-
Notifications
You must be signed in to change notification settings - Fork 164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement CRUD puppy with interface #538
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package main | ||
|
||
func main() { | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package main | ||
|
||
type MapStore struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to see some documentation on the MapStore struct as well, since it is a part of the exported package. |
||
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. success seems like a strange name for this variable. Maybe |
||
|
||
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()}) | ||
suite.Run(t, &StoreSuite{store: NewSyncStore()}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package main | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
type SyncStore struct { | ||
patrickmarabeas marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again here with the documentation as well |
||
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package main | ||
|
||
type Puppy struct { | ||
ID uint | ||
Breed string | ||
Color string | ||
Value string | ||
} | ||
|
||
type Storer interface { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again here with the documentation. |
||
Create(puppy Puppy) uint | ||
Read(ID uint) Puppy | ||
Update(ID uint, puppy Puppy) bool | ||
Destroy(ID uint) bool | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it a little strange seeing a blank main program. I know the description of the lab doesn't state what you need to include in the main, so you have technically ticked all the boxes, but I feel it makes sense to maybe create a puppy or something to give context to the work being done. Happy to hear your thoughts otherwise.