From f8c677d2a062242daacc5de565af29e17584f721 Mon Sep 17 00:00:00 2001 From: Patrick Marabeas Date: Mon, 19 Aug 2019 14:34:04 +1000 Subject: [PATCH 1/3] Add MapStore which implements the Storer interface Adds the Puppy, Storer and MapStore type definitions. MapStore implements the Storer interface and supplies a NewMapStore factory function. - Uuid increment is handled internally by MapStore Create - Read will return an empty Puppy struct if provided uuid doesn't exist - Update returns a bool whether a matching identifier was modified - Destroy returns a bool whether a matching identifier was modified Lab 06 (#537) --- 06_puppy/patrickmarabeas/mapStore.go | 56 ++++++++++++++++++ 06_puppy/patrickmarabeas/store_test.go | 80 ++++++++++++++++++++++++++ 06_puppy/patrickmarabeas/types.go | 15 +++++ 3 files changed, 151 insertions(+) create mode 100644 06_puppy/patrickmarabeas/mapStore.go create mode 100644 06_puppy/patrickmarabeas/store_test.go create mode 100644 06_puppy/patrickmarabeas/types.go diff --git a/06_puppy/patrickmarabeas/mapStore.go b/06_puppy/patrickmarabeas/mapStore.go new file mode 100644 index 000000000..f23af91ef --- /dev/null +++ b/06_puppy/patrickmarabeas/mapStore.go @@ -0,0 +1,56 @@ +package main + +type MapStore struct { + uuid uint + store map[uint]Puppy +} + +// NewMapStore returns a pointer to a new instance of the MapStore struct which implements the Storer interface. +func NewMapStore() Storer { + return &MapStore{ + uuid: 0, + store: map[uint]Puppy{}, + } +} + +// Create increments the uuid and adds the provided Puppy struct to the store with this identifier. +func (store *MapStore) Create(puppy Puppy) uint { + puppy.ID = store.uuid + store.store[puppy.ID] = puppy + store.uuid++ + + return puppy.ID +} + +// Read returns the puppy matching the provided uuid. +// An empty Puppy struct is returned if the identifier does not exist. +func (store *MapStore) Read(id uint) Puppy { + if _, ok := store.store[id]; ok { + return store.store[id] + } + + return Puppy{} +} + +// Update modifies the puppy matching the provided uuid in the store with the provided Puppy struct. +// It returns a bool whether a matching identifier was modified or not. +func (store *MapStore) Update(id uint, puppy Puppy) bool { + if _, ok := store.store[id]; !ok { + return false + } + + puppy.ID = id + store.store[id] = puppy + return true +} + +// Destroy removes the puppy matching the provided uuid from the store. +// It returns a bool whether a matching identifier was deleted or not. +func (store *MapStore) Destroy(id uint) bool { + if _, ok := store.store[id]; !ok { + return false + } + + delete(store.store, id) + return true +} diff --git a/06_puppy/patrickmarabeas/store_test.go b/06_puppy/patrickmarabeas/store_test.go new file mode 100644 index 000000000..481f0c17e --- /dev/null +++ b/06_puppy/patrickmarabeas/store_test.go @@ -0,0 +1,80 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type StoreSuite struct { + suite.Suite + store Storer +} + +func (suite *StoreSuite) TestCreate() { + a := assert.New(suite.T()) + id := suite.store.Create(Puppy{Breed: "Wolf", Color: "Grey", Value: "450"}) + id2 := suite.store.Create(Puppy{Breed: "Boxer", Color: "Brown", Value: "300"}) + + a.EqualValues(id+1, id2) +} + +func (suite *StoreSuite) TestRead() { + a := assert.New(suite.T()) + data := suite.store.Read(0) + + a.Equal(data, Puppy{ID: 0, Breed: "Wolf", Color: "Grey", Value: "450"}) +} + +func (suite *StoreSuite) TestReadNonExistent() { + a := assert.New(suite.T()) + success := suite.store.Read(100) + + a.Equal(success, Puppy{}) +} + +func (suite *StoreSuite) TestUpdate() { + a := assert.New(suite.T()) + success := suite.store.Update(0, Puppy{Breed: "Doberman", Color: "Black", Value: "500"}) + data := suite.store.Read(0) + + a.Equal(success, true) + a.Equal(data, Puppy{ID: 0, Breed: "Doberman", Color: "Black", Value: "500"}) +} + +func (suite *StoreSuite) TestUpdateNonExistent() { + a := assert.New(suite.T()) + success := suite.store.Update(100, Puppy{Breed: "Doberman", Color: "Black", Value: "500"}) + + a.Equal(success, false) +} + +func (suite *StoreSuite) TestDestroy() { + a := assert.New(suite.T()) + success := suite.store.Destroy(1) + data := suite.store.Read(1) + + a.Equal(success, true) + a.Equal(data, Puppy{}) +} + +func (suite *StoreSuite) TestDestroyNonExistent() { + a := assert.New(suite.T()) + success := suite.store.Destroy(100) + + a.Equal(success, false) +} + +func (suite *StoreSuite) TestIdIncrementOnDelete() { + a := assert.New(suite.T()) + id := suite.store.Create(Puppy{Breed: "Greyhound", Color: "Light Brown", Value: "700"}) + suite.store.Destroy(id) + newID := suite.store.Create(Puppy{Breed: "Greyhound", Color: "Light Brown", Value: "700"}) + + a.EqualValues(newID, 3) +} + +func TestStore(t *testing.T) { + suite.Run(t, &StoreSuite{store: NewMapStore()}) +} diff --git a/06_puppy/patrickmarabeas/types.go b/06_puppy/patrickmarabeas/types.go new file mode 100644 index 000000000..3f47c86ca --- /dev/null +++ b/06_puppy/patrickmarabeas/types.go @@ -0,0 +1,15 @@ +package main + +type Puppy struct { + ID uint + Breed string + Color string + Value string +} + +type Storer interface { + Create(puppy Puppy) uint + Read(ID uint) Puppy + Update(ID uint, puppy Puppy) bool + Destroy(ID uint) bool +} From 33d55de88e6d7d291375a46d37a33fe829c3176b Mon Sep 17 00:00:00 2001 From: Patrick Marabeas Date: Mon, 19 Aug 2019 14:35:22 +1000 Subject: [PATCH 2/3] Add SyncStore which implements the Storer interface SyncStore implements the Storer interface and supplies a NewSyncStore factory function. - Uuid increment is handled internally by SyncStore Create - Read will return an empty Puppy struct if provided uuid doesn't exist - Update returns a bool whether a matching identifier was modified - Destroy returns a bool whether a matching identifier was modified Lab 06 (#537) --- 06_puppy/patrickmarabeas/store_test.go | 1 + 06_puppy/patrickmarabeas/syncStore.go | 59 ++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 06_puppy/patrickmarabeas/syncStore.go diff --git a/06_puppy/patrickmarabeas/store_test.go b/06_puppy/patrickmarabeas/store_test.go index 481f0c17e..4c93c3639 100644 --- a/06_puppy/patrickmarabeas/store_test.go +++ b/06_puppy/patrickmarabeas/store_test.go @@ -77,4 +77,5 @@ func (suite *StoreSuite) TestIdIncrementOnDelete() { func TestStore(t *testing.T) { suite.Run(t, &StoreSuite{store: NewMapStore()}) + suite.Run(t, &StoreSuite{store: NewSyncStore()}) } diff --git a/06_puppy/patrickmarabeas/syncStore.go b/06_puppy/patrickmarabeas/syncStore.go new file mode 100644 index 000000000..74911a005 --- /dev/null +++ b/06_puppy/patrickmarabeas/syncStore.go @@ -0,0 +1,59 @@ +package main + +import ( + "sync" +) + +type SyncStore struct { + uuid uint + sync.Map +} + +// NewSyncStore returns a pointer to a new instance of the SyncStore struct which implements the Storer interface. +func NewSyncStore() Storer { + return &SyncStore{ + uuid: 0, + } +} + +// Create increments the uuid and adds the provided Puppy struct to the store with this identifier. +func (store *SyncStore) Create(puppy Puppy) uint { + puppy.ID = store.uuid + store.Store(puppy.ID, puppy) + store.uuid++ + + return puppy.ID +} + +// Read returns the puppy matching the provided uuid. +// An empty Puppy struct is returned if the identifier does not exist. +func (store *SyncStore) Read(id uint) Puppy { + if value, ok := store.Load(id); ok { + return value.(Puppy) + } + + return Puppy{} +} + +// Update modifies the puppy matching the provided uuid in the store with the provided Puppy struct. +// It returns a bool whether a matching identifier was modified or not. +func (store *SyncStore) Update(id uint, puppy Puppy) bool { + if _, ok := store.Load(id); !ok { + return false + } + + puppy.ID = id + store.Store(id, puppy) + return true +} + +// Destroy removes the puppy matching the provided uuid from the store. +// It returns a bool whether a matching identifier was deleted or not. +func (store *SyncStore) Destroy(id uint) bool { + if _, ok := store.Load(id); !ok { + return false + } + + store.Delete(id) + return true +} From 5d53a527a101444f52be01b792b7455c29769a6a Mon Sep 17 00:00:00 2001 From: Patrick Marabeas Date: Mon, 19 Aug 2019 15:21:09 +1000 Subject: [PATCH 3/3] Add empty main function Add empty main function and tests to pass build requirements --- 06_puppy/patrickmarabeas/main.go | 5 +++++ 06_puppy/patrickmarabeas/main_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 06_puppy/patrickmarabeas/main.go create mode 100644 06_puppy/patrickmarabeas/main_test.go diff --git a/06_puppy/patrickmarabeas/main.go b/06_puppy/patrickmarabeas/main.go new file mode 100644 index 000000000..790580777 --- /dev/null +++ b/06_puppy/patrickmarabeas/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + +} diff --git a/06_puppy/patrickmarabeas/main_test.go b/06_puppy/patrickmarabeas/main_test.go new file mode 100644 index 000000000..c98b5b046 --- /dev/null +++ b/06_puppy/patrickmarabeas/main_test.go @@ -0,0 +1,25 @@ +package main + +import ( + "bytes" + "io" + "os" + "testing" +) + +var out io.Writer = os.Stdout + +func TestMainOutput(t *testing.T) { + var buf bytes.Buffer + out = &buf + + main() + + expected := "" + + got := buf.String() + + if expected != got { + t.Errorf("\nExpected: %s\nGot: %s", expected, got) + } +}