diff --git a/maps/dictionary.go b/maps/dictionary.go new file mode 100644 index 0000000..dd19ad4 --- /dev/null +++ b/maps/dictionary.go @@ -0,0 +1,58 @@ +package maps + +type Dictionary map[string]string + +const ( + ErrNotFound = DictionaryErr("could not find the word you were looking for") + ErrWordExists = DictionaryErr("cannot add word because it already exists") + ErrWordDoesNotExist = DictionaryErr("cannot update word because it does not exist") +) + +type DictionaryErr string + +func (e DictionaryErr) Error() string { + return string(e) +} + +func (d Dictionary) Search(word string) (string, error) { + definition, ok := d[word] + if !ok { + return "", ErrNotFound + } + + return definition, 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) +} diff --git a/maps/dictionary_test.go b/maps/dictionary_test.go new file mode 100644 index 0000000..f1ce538 --- /dev/null +++ b/maps/dictionary_test.go @@ -0,0 +1,105 @@ +package maps + +import "testing" + +func TestSearch(t *testing.T) { + dictionary := Dictionary{"test": "this is just a test"} + + t.Run("known word", func(t *testing.T) { + got, _ := dictionary.Search("test") + want := "this is just a test" + + assertStrings(t, got, want) + }) + + t.Run("unknown word", func(t *testing.T) { + _, got := dictionary.Search("unknown") + + assertError(t, got, ErrNotFound) + }) +} + +func TestAdd(t *testing.T) { + t.Run("new word", func(t *testing.T) { + dictionary := Dictionary{} + word := "test" + definition := "this is just a test" + + err := dictionary.Add(word, definition) + + assertError(t, err, nil) + assertDefinition(t, dictionary, word, definition) + }) + t.Run("existing word", func(t *testing.T) { + word := "test" + definition := "this is just a test" + dictionary := Dictionary{word: definition} + err := dictionary.Add(word, "new test") + + assertError(t, err, ErrWordExists) + assertDefinition(t, dictionary, word, definition) + }) +} + +func TestUpdate(t *testing.T) { + t.Run("existing word", func(t *testing.T) { + word := "test" + definition := "this is just a test" + dictionary := Dictionary{word: definition} + newDefinition := "new definition" + + err := dictionary.Update(word, newDefinition) + + assertError(t, err, nil) + assertDefinition(t, dictionary, word, newDefinition) + }) + + t.Run("new word", func(t *testing.T) { + word := "test" + definition := "this is just a test" + dictionary := Dictionary{} + + err := dictionary.Update(word, definition) + + assertError(t, err, ErrWordDoesNotExist) + }) +} + +func TestDelete(t *testing.T) { + word := "test" + dictionary := Dictionary{word: "test definition"} + + dictionary.Delete(word) + + _, err := dictionary.Search(word) + if err != ErrNotFound { + t.Errorf("Expected %q to be deleted", word) + } +} + +func assertDefinition(t testing.TB, dictionary Dictionary, word, definition string) { + t.Helper() + + got, err := dictionary.Search(word) + if err != nil { + t.Fatal("should find added word:", err) + } + + assertStrings(t, got, definition) +} + +func assertStrings(t testing.TB, got, want string) { + t.Helper() + + if got != want { + t.Errorf("got %q want %q", got, want) + } +} + +func assertError(t testing.TB, got, want error) { + t.Helper() + + if got != want { + t.Errorf("got error %q want %q", got, want) + } +}