Compare commits
No commits in common. "05226985c748c5acf565179fb2dc65fba12f0932" and "fc67cf14ff598ed544d2139121c0effa9740e571" have entirely different histories.
05226985c7
...
fc67cf14ff
@ -1,45 +0,0 @@
|
|||||||
package countdown
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
finalWord = "Go!"
|
|
||||||
countdownStart = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
type Sleeper interface {
|
|
||||||
Sleep()
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConfigurableSleeper struct {
|
|
||||||
duration time.Duration
|
|
||||||
sleep func(time.Duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfigurableSleeper(
|
|
||||||
duration time.Duration,
|
|
||||||
sleep func(time.Duration),
|
|
||||||
) *ConfigurableSleeper {
|
|
||||||
return &ConfigurableSleeper{
|
|
||||||
duration: duration,
|
|
||||||
sleep: sleep,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ConfigurableSleeper) Sleep() {
|
|
||||||
s.sleep(s.duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Countdown(out io.Writer, sleeper Sleeper) {
|
|
||||||
// XXX: The sequence is not tested
|
|
||||||
for i := countdownStart; i > 0; i-- {
|
|
||||||
fmt.Fprintf(out, "%d\n", i)
|
|
||||||
// This is difficult to test!
|
|
||||||
sleeper.Sleep()
|
|
||||||
}
|
|
||||||
fmt.Fprint(out, finalWord)
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package countdown
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
write = "write"
|
|
||||||
sleep = "sleep"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SpyCountdownOperations struct {
|
|
||||||
Calls []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SpyCountdownOperations) Sleep() {
|
|
||||||
s.Calls = append(s.Calls, sleep)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SpyCountdownOperations) Write(p []byte) (n int, err error) {
|
|
||||||
s.Calls = append(s.Calls, write)
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SpyTime struct {
|
|
||||||
durationSlept time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SpyTime) Sleep(duration time.Duration) {
|
|
||||||
s.durationSlept = duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCountdown(t *testing.T) {
|
|
||||||
t.Run("print 3 to Go!", func(t *testing.T) {
|
|
||||||
buffer := &bytes.Buffer{}
|
|
||||||
Countdown(buffer, &SpyCountdownOperations{})
|
|
||||||
|
|
||||||
got := buffer.String()
|
|
||||||
want := `3
|
|
||||||
2
|
|
||||||
1
|
|
||||||
Go!`
|
|
||||||
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("got %q want %q", got, want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("sleep before every print", func(t *testing.T) {
|
|
||||||
spySleepPrinter := &SpyCountdownOperations{}
|
|
||||||
|
|
||||||
Countdown(spySleepPrinter, spySleepPrinter)
|
|
||||||
|
|
||||||
want := []string{
|
|
||||||
write, sleep, write, sleep, write, sleep, write,
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(want, spySleepPrinter.Calls) {
|
|
||||||
t.Errorf("wanted %v got %v", want, spySleepPrinter.Calls)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfigurableSleeper(t *testing.T) {
|
|
||||||
sleepTime := 5 * time.Second
|
|
||||||
|
|
||||||
spyTime := &SpyTime{}
|
|
||||||
sleeper := NewConfigurableSleeper(sleepTime, spyTime.Sleep)
|
|
||||||
sleeper.Sleep()
|
|
||||||
|
|
||||||
if spyTime.durationSlept != sleepTime {
|
|
||||||
t.Errorf("should have slept for %v but slept for %v", sleepTime, spyTime.durationSlept)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +1,10 @@
|
|||||||
package dictionary
|
package dictionary
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
type Dictionary map[string]string
|
type Dictionary map[string]string
|
||||||
|
|
||||||
const (
|
var ErrNotFound = errors.New("could not find the word you were looking for")
|
||||||
ErrNotFound = DictionaryErr("could not find the word you were looking for")
|
|
||||||
ErrWordExists = DictionaryErr("word exists")
|
|
||||||
ErrWordDoesNotExist = DictionaryErr("word does not exist")
|
|
||||||
)
|
|
||||||
|
|
||||||
type DictionaryErr string
|
|
||||||
|
|
||||||
// implements the Error interface, makes it an "error"
|
|
||||||
func (e DictionaryErr) Error() string {
|
|
||||||
return string(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Dictionary) Search(word string) (string, error) {
|
func (d Dictionary) Search(word string) (string, error) {
|
||||||
result, ok := d[word]
|
result, ok := d[word]
|
||||||
@ -22,33 +13,3 @@ func (d Dictionary) Search(word string) (string, error) {
|
|||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d Dictionary) Add(word, definition string) error {
|
|
||||||
_, err := d.Search(word)
|
|
||||||
switch err {
|
|
||||||
case ErrNotFound:
|
|
||||||
d[word] = definition
|
|
||||||
case nil:
|
|
||||||
return ErrWordExists
|
|
||||||
default:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Dictionary) Update(word, definition string) error {
|
|
||||||
_, err := d.Search(word)
|
|
||||||
switch err {
|
|
||||||
case ErrNotFound:
|
|
||||||
return ErrWordDoesNotExist
|
|
||||||
case nil:
|
|
||||||
d[word] = definition
|
|
||||||
default:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d Dictionary) Delete(word string) {
|
|
||||||
delete(d, word)
|
|
||||||
}
|
|
||||||
|
@ -1,22 +1,12 @@
|
|||||||
package dictionary
|
package dictionary
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func assertStrings(t testing.TB, got, want, given string) {
|
func assertStrings(t testing.TB, got, want string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("got %q want %q given %q", got, want, given)
|
t.Errorf("got %q want %q given %q", got, want, "test")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertError(t testing.TB, got, want error) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("got %q want %q", got, want)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,82 +17,16 @@ func TestSearch(t *testing.T) {
|
|||||||
got, _ := dictionary.Search("test")
|
got, _ := dictionary.Search("test")
|
||||||
want := "this is just a test"
|
want := "this is just a test"
|
||||||
|
|
||||||
assertStrings(t, got, want, "test")
|
assertStrings(t, got, want)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unknown word", func(t *testing.T) {
|
t.Run("unknown word", func(t *testing.T) {
|
||||||
_, err := dictionary.Search("undefined")
|
_, err := dictionary.Search("undefined")
|
||||||
|
want := "could not find the word you were looking for"
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected to get an error")
|
t.Fatal("expected to get an error")
|
||||||
}
|
}
|
||||||
assertError(t, err, ErrNotFound)
|
|
||||||
})
|
assertStrings(t, err.Error(), want)
|
||||||
}
|
|
||||||
|
|
||||||
func assertDefinition(t testing.TB, dict Dictionary, word, def string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
got, err := dict.Search(word)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Should find added word:", err)
|
|
||||||
}
|
|
||||||
assertStrings(t, got, def, word)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
|
||||||
t.Run("new word", func(t *testing.T) {
|
|
||||||
dict := Dictionary{}
|
|
||||||
|
|
||||||
word := "test"
|
|
||||||
def := "this is just a test"
|
|
||||||
|
|
||||||
dict.Add(word, def)
|
|
||||||
assertDefinition(t, dict, word, def)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("existing word", func(t *testing.T) {
|
|
||||||
word := "test"
|
|
||||||
def := "this is just a test"
|
|
||||||
dict := Dictionary{word: def}
|
|
||||||
|
|
||||||
err := dict.Add(word, def)
|
|
||||||
assertError(t, err, ErrWordExists)
|
|
||||||
assertDefinition(t, dict, word, def)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
|
||||||
t.Run("update an existing word", func(t *testing.T) {
|
|
||||||
word := "test"
|
|
||||||
def := "this is just a test"
|
|
||||||
updated := "updated definition"
|
|
||||||
dict := Dictionary{word: def}
|
|
||||||
|
|
||||||
dict.Update(word, updated)
|
|
||||||
assertDefinition(t, dict, word, updated)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("update an non-existing word", func(t *testing.T) {
|
|
||||||
word := "test"
|
|
||||||
updated := "updated definition"
|
|
||||||
dict := Dictionary{}
|
|
||||||
|
|
||||||
err := dict.Update(word, updated)
|
|
||||||
assertError(t, err, ErrWordDoesNotExist)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDelete(t *testing.T) {
|
|
||||||
t.Run("delete a word", func(t *testing.T) {
|
|
||||||
word := "test"
|
|
||||||
def := "this is just a test"
|
|
||||||
dict := Dictionary{word: def}
|
|
||||||
|
|
||||||
dict.Delete(word)
|
|
||||||
_, err := dict.Search(word)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected to get an error")
|
|
||||||
}
|
|
||||||
assertError(t, err, ErrNotFound)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package greet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGreet(t *testing.T) {
|
|
||||||
buffer := bytes.Buffer{}
|
|
||||||
Greet(&buffer, "Chris")
|
|
||||||
got := buffer.String()
|
|
||||||
want := "Hello, Chris"
|
|
||||||
|
|
||||||
if got != want {
|
|
||||||
t.Errorf("got %q want %q", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package greet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Greet(writer io.Writer, name string) {
|
|
||||||
fmt.Fprintf(writer, "Hello, %s", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MyGreeterHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
Greet(w, "world")
|
|
||||||
}
|
|
||||||
|
|
||||||
// func main() {
|
|
||||||
// log.Fatal(http.ListenAndServe(":5001", http.HandlerFunc(MyGreeterHandler)))
|
|
||||||
// }
|
|
Loading…
x
Reference in New Issue
Block a user