diff --git a/go.mod b/go.mod index 968bc5c..fe89412 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/davidlick/supermarket-api go 1.16 require ( + github.com/Rhymond/go-money v1.0.2 // indirect github.com/go-chi/chi v1.5.4 // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/btree v1.0.1 // indirect diff --git a/go.sum b/go.sum index f48f12d..b408994 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Rhymond/go-money v1.0.2 h1:KklB66H3VlpNMkm8T5BH/MROK88o7q9CCn1hl853TzI= +github.com/Rhymond/go-money v1.0.2/go.mod h1:iHvCuIvitxu2JIlAlhF0g9jHqjRSr+rpdOs7Omqlupg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/interfaces/ramdb.go b/internal/interfaces/ramdb.go new file mode 100644 index 0000000..df6002a --- /dev/null +++ b/internal/interfaces/ramdb.go @@ -0,0 +1,10 @@ +package interfaces + +import "github.com/davidlick/supermarket-api/pkg/ramdb" + +type RamDB interface { + Get(column, key string) (r *ramdb.Record, err error) + Select(column string) (rr []*ramdb.Record, err error) + Insert(r *ramdb.Record) error + Delete(r *ramdb.Record) error +} diff --git a/internal/mocks/ramdb.go b/internal/mocks/ramdb.go new file mode 100644 index 0000000..cc28efb --- /dev/null +++ b/internal/mocks/ramdb.go @@ -0,0 +1,92 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./internal/interfaces/ramdb.go + +// Package mocks is a generated GoMock package. +package mocks + +import ( + ramdb "github.com/davidlick/supermarket-api/pkg/ramdb" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockRamDB is a mock of RamDB interface +type MockRamDB struct { + ctrl *gomock.Controller + recorder *MockRamDBMockRecorder +} + +// MockRamDBMockRecorder is the mock recorder for MockRamDB +type MockRamDBMockRecorder struct { + mock *MockRamDB +} + +// NewMockRamDB creates a new mock instance +func NewMockRamDB(ctrl *gomock.Controller) *MockRamDB { + mock := &MockRamDB{ctrl: ctrl} + mock.recorder = &MockRamDBMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockRamDB) EXPECT() *MockRamDBMockRecorder { + return m.recorder +} + +// Get mocks base method +func (m *MockRamDB) Get(column, key string) (*ramdb.Record, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", column, key) + ret0, _ := ret[0].(*ramdb.Record) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get +func (mr *MockRamDBMockRecorder) Get(column, key interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockRamDB)(nil).Get), column, key) +} + +// Select mocks base method +func (m *MockRamDB) Select(column string) ([]*ramdb.Record, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Select", column) + ret0, _ := ret[0].([]*ramdb.Record) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Select indicates an expected call of Select +func (mr *MockRamDBMockRecorder) Select(column interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Select", reflect.TypeOf((*MockRamDB)(nil).Select), column) +} + +// Insert mocks base method +func (m *MockRamDB) Insert(r *ramdb.Record) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Insert", r) + ret0, _ := ret[0].(error) + return ret0 +} + +// Insert indicates an expected call of Insert +func (mr *MockRamDBMockRecorder) Insert(r interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockRamDB)(nil).Insert), r) +} + +// Delete mocks base method +func (m *MockRamDB) Delete(r *ramdb.Record) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", r) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete +func (mr *MockRamDBMockRecorder) Delete(r interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockRamDB)(nil).Delete), r) +} diff --git a/internal/produce/README.md b/internal/produce/README.md new file mode 100644 index 0000000..53bf6f1 --- /dev/null +++ b/internal/produce/README.md @@ -0,0 +1,24 @@ +# Produce Service + +This produce service allows persisting produce in a database. It supports adding multiple produce items, removing a produce item, getting a produce item by produce code, and selecting all produce items from the database. + +## Example + +```go +// Create database and table. +db := ramdb.NewDatabase() +_ = db.CreateTable("produce", KeyProduceCode) + +produceSvc := produce.NewService(db) + +produceItem := produce.Item{ + Code: "A12T-4GH7-QPL9-3N4M", + Name: "Lettuce", + Price: money.New(346, "USD"), +} + +_ = produceSvc.Add([]Item{produceItem}) +_, _ = produceSvc.Get(produceItem.Code) +_, _ = produceSvc.All() +_ = produceSvc.Remove(produceItem) +``` diff --git a/internal/produce/constants.go b/internal/produce/constants.go new file mode 100644 index 0000000..02076f5 --- /dev/null +++ b/internal/produce/constants.go @@ -0,0 +1,5 @@ +package produce + +const ( + KeyProduceCode = "produce_code" +) diff --git a/internal/produce/models.go b/internal/produce/models.go new file mode 100644 index 0000000..1948287 --- /dev/null +++ b/internal/produce/models.go @@ -0,0 +1,10 @@ +package produce + +import "github.com/Rhymond/go-money" + +// Item models a produce item. +type Item struct { + Code string + Name string + Price *money.Money +} diff --git a/internal/produce/produce.go b/internal/produce/produce.go new file mode 100644 index 0000000..c1a0f00 --- /dev/null +++ b/internal/produce/produce.go @@ -0,0 +1,77 @@ +package produce + +import ( + "strings" + + "github.com/davidlick/supermarket-api/internal/interfaces" + "github.com/davidlick/supermarket-api/pkg/ramdb" +) + +type service struct { + db interfaces.RamDB +} + +// NewService creates a new produce service for storing produce items. +func NewService(db interfaces.RamDB) *service { + return &service{ + db: db, + } +} + +// Add adds the Items to the database. +func (s *service) Add(items []Item) error { + for _, item := range items { + rec, err := ramdb.NewRecord(strings.ToLower(item.Code), KeyProduceCode, item) + if err != nil { + return err + } + + err = s.db.Insert(rec) + if err != nil { + return err + } + } + + return nil +} + +// Remove removes the item from the database. +func (s *service) Remove(item Item) error { + rec, err := ramdb.NewRecord(strings.ToLower(item.Code), KeyProduceCode, item) + if err != nil { + return err + } + + return s.db.Delete(rec) +} + +// Get fetches the produceCode from the database. +func (s *service) Get(produceCode string) (item Item, err error) { + rec, err := s.db.Get(KeyProduceCode, strings.ToLower(produceCode)) + if err != nil { + return + } + + err = rec.Deserialize(&item) + return +} + +// All returns all produce items stored in the database. +func (s *service) All() (items []Item, err error) { + recs, err := s.db.Select(KeyProduceCode) + if err != nil { + return + } + + for _, rec := range recs { + var item Item + err = rec.Deserialize(&item) + if err != nil { + return + } + + items = append(items, item) + } + + return +} diff --git a/internal/produce/produce_test.go b/internal/produce/produce_test.go new file mode 100644 index 0000000..ff55254 --- /dev/null +++ b/internal/produce/produce_test.go @@ -0,0 +1,279 @@ +package produce + +import ( + "errors" + "testing" + + "github.com/Rhymond/go-money" + "github.com/davidlick/supermarket-api/internal/mocks" + "github.com/davidlick/supermarket-api/pkg/ramdb" + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +func TestService_Add(t *testing.T) { + tests := []struct { + test string + expectFunc func(t *testing.T, mockRamDB *mocks.MockRamDB) []Item + expectedError error + }{ + { + test: "it should add all Items", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) []Item { + items := []Item{ + {Code: "code-1", Name: "name-1", Price: money.New(101, "USD")}, + {Code: "code-2", Name: "name-2", Price: money.New(202, "USD")}, + {Code: "code-3", Name: "name-3", Price: money.New(303, "USD")}, + {Code: "code-4", Name: "name-4", Price: money.New(404, "USD")}, + {Code: "code-5", Name: "name-5", Price: money.New(505, "USD")}, + } + + for _, item := range items { + rec, err := ramdb.NewRecord(item.Code, KeyProduceCode, item) + if err != nil { + t.Error(err) + } + + mockRamDB.EXPECT().Insert(rec).Return(nil) + } + + return items + }, + }, + { + test: "it should return an error from ramdb", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) []Item { + mockRamDB.EXPECT().Insert(gomock.Any()).Return(errors.New("test error")) + return []Item{ + {Code: "code-1", Name: "name-1", Price: money.New(101, "USD")}, + } + }, + expectedError: errors.New("test error"), + }, + } + + for _, tc := range tests { + t.Run(tc.test, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockRamDB := mocks.NewMockRamDB(ctrl) + + items := tc.expectFunc(t, mockRamDB) + + svc := NewService(mockRamDB) + err := svc.Add(items) + + assert.Equal(t, tc.expectedError, err) + }) + } +} + +func TestService_Add_Lowercased(t *testing.T) { + t.Run("it should store produce codes lowercased", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + item := Item{ + Code: "TEST_CODE", + Name: "Name", + Price: money.New(101, "USD"), + } + + mockRamDB := mocks.NewMockRamDB(ctrl) + rec, err := ramdb.NewRecord("test_code", KeyProduceCode, item) + if err != nil { + t.Error(err) + } + + mockRamDB.EXPECT().Insert(rec).Return(nil) + + svc := NewService(mockRamDB) + err = svc.Add([]Item{item}) + + assert.Nil(t, err) + }) +} + +func TestService_Remove(t *testing.T) { + tests := []struct { + test string + expectFunc func(t *testing.T, mockRamDB *mocks.MockRamDB) Item + expectedError error + }{ + { + test: "it should successfully remove an item", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) Item { + item := Item{Code: "code-1", Name: "name-1", Price: money.New(101, "USD")} + rec, err := ramdb.NewRecord(item.Code, KeyProduceCode, item) + if err != nil { + t.Error(err) + } + + mockRamDB.EXPECT().Delete(rec).Return(nil) + return item + }, + }, + { + test: "it should return an error from ramdb", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) Item { + mockRamDB.EXPECT().Delete(gomock.Any()).Return(errors.New("test error")) + return Item{} + }, + expectedError: errors.New("test error"), + }, + } + + for _, tc := range tests { + t.Run(tc.test, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockRamDB := mocks.NewMockRamDB(ctrl) + + item := tc.expectFunc(t, mockRamDB) + + svc := NewService(mockRamDB) + err := svc.Remove(item) + + assert.Equal(t, tc.expectedError, err) + }) + } +} + +func TestService_Get(t *testing.T) { + tests := []struct { + test string + expectFunc func(t *testing.T, mockRamDB *mocks.MockRamDB) Item + expectedError error + }{ + { + test: "it should return the item successfully", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) Item { + item := Item{Code: "produce_code", Name: "name-1", Price: money.New(101, "USD")} + rec, err := ramdb.NewRecord(item.Code, KeyProduceCode, item) + if err != nil { + t.Error(err) + } + + mockRamDB.EXPECT().Get(KeyProduceCode, "test_code").Return(rec, nil) + return item + }, + }, + { + test: "it should return an error from ramdb", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) Item { + mockRamDB.EXPECT().Get(KeyProduceCode, "test_code").Return(nil, errors.New("test error")) + return Item{} + }, + expectedError: errors.New("test error"), + }, + } + + for _, tc := range tests { + t.Run(tc.test, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockRamDB := mocks.NewMockRamDB(ctrl) + + expectedItem := tc.expectFunc(t, mockRamDB) + + svc := NewService(mockRamDB) + item, err := svc.Get("test_code") + + assert.Equal(t, expectedItem, item) + assert.Equal(t, tc.expectedError, err) + }) + } +} + +func TestService_Get_CaseInsensitive(t *testing.T) { + t.Run("it should lowercase produce codes before getting", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + searchItem := Item{ + Code: "TEST_CODE", + } + + expectedItem := Item{ + Code: "test_code", + } + + rec, err := ramdb.NewRecord("test_code", KeyProduceCode, expectedItem) + if err != nil { + t.Error(err) + } + + mockRamDB := mocks.NewMockRamDB(ctrl) + mockRamDB.EXPECT().Get(KeyProduceCode, "test_code").Return(rec, nil) + + svc := NewService(mockRamDB) + + item, err := svc.Get(searchItem.Code) + + assert.Equal(t, item, expectedItem) + assert.Nil(t, err) + }) +} + +func TestService_All(t *testing.T) { + tests := []struct { + test string + expectFunc func(t *testing.T, mockRamDB *mocks.MockRamDB) []Item + expectedError error + }{ + { + test: "it should return all items", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) []Item { + items := []Item{ + {Code: "code-1", Name: "name-1", Price: money.New(101, "USD")}, + {Code: "code-2", Name: "name-2", Price: money.New(202, "USD")}, + {Code: "code-3", Name: "name-3", Price: money.New(303, "USD")}, + {Code: "code-4", Name: "name-4", Price: money.New(404, "USD")}, + {Code: "code-5", Name: "name-5", Price: money.New(505, "USD")}, + } + + var recs []*ramdb.Record + for _, item := range items { + rec, err := ramdb.NewRecord(item.Code, KeyProduceCode, item) + if err != nil { + t.Error(err) + } + + recs = append(recs, rec) + } + + mockRamDB.EXPECT().Select(KeyProduceCode).Return(recs, nil) + + return items + }, + }, + { + test: "it should return a ramdb error", + expectFunc: func(t *testing.T, mockRamDB *mocks.MockRamDB) []Item { + mockRamDB.EXPECT().Select(gomock.Any()).Return(nil, errors.New("test error")) + return nil + }, + expectedError: errors.New("test error"), + }, + } + + for _, tc := range tests { + t.Run(tc.test, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockRamDB := mocks.NewMockRamDB(ctrl) + + expectedItems := tc.expectFunc(t, mockRamDB) + + svc := NewService(mockRamDB) + items, err := svc.All() + + assert.Equal(t, expectedItems, items) + assert.Equal(t, tc.expectedError, err) + }) + } +} diff --git a/pkg/ramdb/README.md b/pkg/ramdb/README.md index b35075b..2e40a5c 100644 --- a/pkg/ramdb/README.md +++ b/pkg/ramdb/README.md @@ -27,7 +27,7 @@ indog := HotDog{ Brat: true, } -// Create a new record and insert. +// Create a new Record and insert. rec, _ := ramdb.NewRecord("1", "frank_id", indog) _ = db.From("hotdogs").Insert(rec) diff --git a/pkg/ramdb/commands.go b/pkg/ramdb/commands.go index 7c1db15..11528a5 100644 --- a/pkg/ramdb/commands.go +++ b/pkg/ramdb/commands.go @@ -3,7 +3,7 @@ package ramdb import "github.com/google/btree" // Get validates that the table and index for the given column exists and searches for the given key in the tree. -func (t *table) Get(column, key string) (r *record, err error) { +func (t *table) Get(column, key string) (r *Record, err error) { if !t.exists { return nil, ErrNoTable } @@ -16,18 +16,18 @@ func (t *table) Get(column, key string) (r *record, err error) { } // keyLookup tries to find the given key in the tree. It returns ErrNoRecord if not found. -func (t *table) keyLookup(key string, index *index) (r *record, err error) { - item := &record{id: keyHash(key)} +func (t *table) keyLookup(key string, index *index) (r *Record, err error) { + item := &Record{id: keyHash(key)} result := index.tree.Get(item) if result == nil { return nil, ErrNoRecord } - return result.(*record), nil + return result.(*Record), nil } -// Select returns all of the records in the database sorted in ascending order by id. -func (t *table) Select(column string) (rr []*record, err error) { +// Select returns all of the Records in the database sorted in ascending order by id. +func (t *table) Select(column string) (rr []*Record, err error) { if !t.exists { return nil, ErrNoTable } @@ -37,7 +37,7 @@ func (t *table) Select(column string) (rr []*record, err error) { } t.indexes[column].tree.Ascend(func(item btree.Item) bool { - r := item.(*record) + r := item.(*Record) rr = append(rr, r) return true }) @@ -45,8 +45,8 @@ func (t *table) Select(column string) (rr []*record, err error) { return } -// Insert adds the record to the database. It returns ErrRecordExists if the record already exists. Insert is thread safe. -func (t *table) Insert(r *record) error { +// Insert adds the Record to the database. It returns ErrRecordExists if the Record already exists. Insert is thread safe. +func (t *table) Insert(r *Record) error { if !t.exists { return ErrNoTable } @@ -69,8 +69,8 @@ func (t *table) Insert(r *record) error { } -// Delete removes the item from the database. It returns ErrNoRecord if the record does not exist and ErrNotDeleted if the removal fails. Delete is thread safe. -func (t *table) Delete(r *record) error { +// Delete removes the item from the database. It returns ErrNoRecord if the Record does not exist and ErrNotDeleted if the removal fails. Delete is thread safe. +func (t *table) Delete(r *Record) error { if !t.exists { return ErrNoTable } diff --git a/pkg/ramdb/commands_test.go b/pkg/ramdb/commands_test.go index a589358..466e3b4 100644 --- a/pkg/ramdb/commands_test.go +++ b/pkg/ramdb/commands_test.go @@ -14,7 +14,7 @@ func TestTable_Get(t *testing.T) { tests := []struct { test string tableConfig func() *table - expectedRecord *record + expectedRecord *Record expectedError error }{ { @@ -34,7 +34,7 @@ func TestTable_Get(t *testing.T) { expectedError: ErrNoIndex, }, { - test: "it should return ErrNoRecord if no record was found for key", + test: "it should return ErrNoRecord if no Record was found for key", tableConfig: func() *table { return &table{ exists: true, @@ -48,7 +48,7 @@ func TestTable_Get(t *testing.T) { expectedError: ErrNoRecord, }, { - test: "it should return a record when one is found", + test: "it should return a Record when one is found", tableConfig: func() *table { tbl := &table{ exists: true, @@ -65,7 +65,7 @@ func TestTable_Get(t *testing.T) { tbl.indexes["test_column"].tree.ReplaceOrInsert(rec) return tbl }, - expectedRecord: &record{ + expectedRecord: &Record{ serialized: []uint8{0x7b, 0x7d}, key: "test_key", keyColumn: "test_column", @@ -78,9 +78,9 @@ func TestTable_Get(t *testing.T) { t.Run(tc.test, func(t *testing.T) { tbl := tc.tableConfig() - record, err := tbl.Get("test_column", "test_key") + Record, err := tbl.Get("test_column", "test_key") - assert.Equal(t, tc.expectedRecord, record) + assert.Equal(t, tc.expectedRecord, Record) assert.Equal(t, tc.expectedError, err) }) } @@ -89,13 +89,13 @@ func TestTable_Get(t *testing.T) { func TestTable_Select(t *testing.T) { tests := []struct { test string - tableConfig func() (*table, []*record) - expectedRecords []*record + tableConfig func() (*table, []*Record) + expectedRecords []*Record expectedError error }{ { test: "it should return ErrNoTable if an invalid table is supplied", - tableConfig: func() (*table, []*record) { + tableConfig: func() (*table, []*Record) { return &table{ mutex: &sync.Mutex{}, }, nil @@ -104,7 +104,7 @@ func TestTable_Select(t *testing.T) { }, { test: "it should return ErrNoIndex if no index exists for column", - tableConfig: func() (*table, []*record) { + tableConfig: func() (*table, []*Record) { return &table{ exists: true, mutex: &sync.Mutex{}, @@ -114,8 +114,8 @@ func TestTable_Select(t *testing.T) { expectedError: ErrNoIndex, }, { - test: "it should return all records in the database", - tableConfig: func() (*table, []*record) { + test: "it should return all Records in the database", + tableConfig: func() (*table, []*Record) { tbl := &table{ exists: true, mutex: &sync.Mutex{}, @@ -126,7 +126,7 @@ func TestTable_Select(t *testing.T) { }, } - expectedRecords := make([]*record, 0) + expectedRecords := make([]*Record, 0) for i := 0; i < 10; i++ { key := fmt.Sprintf("key-%d", i) rec, err := NewRecord(key, "test_column", struct{}{}) @@ -185,7 +185,7 @@ func TestTable_Insert(t *testing.T) { expectedError: ErrNoIndex, }, { - test: "it should return ErrRecordExists if a record with key exists", + test: "it should return ErrRecordExists if a Record with key exists", tableConfig: func() *table { tbl := &table{ exists: true, @@ -265,7 +265,7 @@ func TestTable_Delete(t *testing.T) { expectedError: ErrNoIndex, }, { - test: "it should return ErrNoRecord if the record does not exist", + test: "it should return ErrNoRecord if the Record does not exist", tableConfig: func() *table { return &table{ exists: true, diff --git a/pkg/ramdb/record.go b/pkg/ramdb/record.go index aeb6c47..d16072f 100644 --- a/pkg/ramdb/record.go +++ b/pkg/ramdb/record.go @@ -8,21 +8,21 @@ import ( "github.com/google/btree" ) -type record struct { +type Record struct { serialized []byte keyColumn string key string id uint64 } -// NewRecord returns a pointer to a record populated with data, key, and a hash of the key used for ordering in the tree. -func NewRecord(key, keyColumn string, data interface{}) (*record, error) { +// NewRecord returns a pointer to a Record populated with data, key, and a hash of the key used for ordering in the tree. +func NewRecord(key, keyColumn string, data interface{}) (*Record, error) { serialized, err := json.Marshal(data) if err != nil { return nil, err } - var r record + var r Record r.serialized = serialized r.keyColumn = keyColumn r.key = key @@ -39,13 +39,13 @@ func keyHash(s string) uint64 { } // Deserialize unmarshals the serialized data into `into`. -func (r *record) Deserialize(into interface{}) error { +func (r *Record) Deserialize(into interface{}) error { err := json.Unmarshal(r.serialized, &into) return err } -// Less is used to order items and for looking up records in the tree. -func (r *record) Less(than btree.Item) bool { - re := than.(*record) +// Less is used to order items and for looking up Records in the tree. +func (r *Record) Less(than btree.Item) bool { + re := than.(*Record) return r.id < re.id } diff --git a/pkg/ramdb/record_test.go b/pkg/ramdb/record_test.go index 9bab553..d542842 100644 --- a/pkg/ramdb/record_test.go +++ b/pkg/ramdb/record_test.go @@ -12,7 +12,7 @@ func TestRecord_NewRecord(t *testing.T) { key string keyColumn string data interface{} - expectedRecord *record + expectedRecord *Record expectedError string }{ { @@ -29,7 +29,7 @@ func TestRecord_NewRecord(t *testing.T) { key: "test-record", keyColumn: "test-column", data: struct{}{}, - expectedRecord: &record{ + expectedRecord: &Record{ serialized: []byte("{}"), key: "test-record", keyColumn: "test-column",