Skip to content
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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions 06_puppy/patrickmarabeas/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package main

func main() {

Copy link
Member

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.

}
25 changes: 25 additions & 0 deletions 06_puppy/patrickmarabeas/main_test.go
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)
}
}
56 changes: 56 additions & 0 deletions 06_puppy/patrickmarabeas/mapStore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

type MapStore struct {
Copy link
Member

Choose a reason for hiding this comment

The 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
}
81 changes: 81 additions & 0 deletions 06_puppy/patrickmarabeas/store_test.go
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

success seems like a strange name for this variable. Maybe notFound or something which indicates that it didn't exist?


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()})
}
59 changes: 59 additions & 0 deletions 06_puppy/patrickmarabeas/syncStore.go
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
Copy link
Member

Choose a reason for hiding this comment

The 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
}
15 changes: 15 additions & 0 deletions 06_puppy/patrickmarabeas/types.go
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 {
Copy link
Member

Choose a reason for hiding this comment

The 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
}