Files
supermarket-api/pkg/ramdb/commands_test.go
T
2021-06-20 18:16:33 -04:00

319 lines
6.7 KiB
Go

package ramdb
import (
"fmt"
"sort"
"sync"
"testing"
"github.com/google/btree"
"github.com/stretchr/testify/assert"
)
func TestTable_Get(t *testing.T) {
tests := []struct {
test string
tableConfig func() *table
expectedRecord *Record
expectedError error
}{
{
test: "it should return ErrNoTable if an invalid table is supplied",
tableConfig: func() *table {
return &table{}
},
expectedError: ErrNoTable,
},
{
test: "it should return ErrNoIndex if no index exists for column",
tableConfig: func() *table {
return &table{
exists: true,
}
},
expectedError: ErrNoIndex,
},
{
test: "it should return ErrNoRecord if no Record was found for key",
tableConfig: func() *table {
return &table{
exists: true,
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
},
expectedError: ErrNoRecord,
},
{
test: "it should return a Record when one is found",
tableConfig: func() *table {
tbl := &table{
exists: true,
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
rec, err := NewRecord("test_key", "test_column", struct{}{})
if err != nil {
t.Error(err)
}
tbl.indexes["test_column"].tree.ReplaceOrInsert(rec)
return tbl
},
expectedRecord: &Record{
serialized: []uint8{0x7b, 0x7d},
key: "test_key",
keyColumn: "test_column",
id: 0x92488e1e3eeecdf9,
},
},
}
for _, tc := range tests {
t.Run(tc.test, func(t *testing.T) {
tbl := tc.tableConfig()
Record, err := tbl.Get("test_column", "test_key")
assert.Equal(t, tc.expectedRecord, Record)
assert.Equal(t, tc.expectedError, err)
})
}
}
func TestTable_Select(t *testing.T) {
tests := []struct {
test string
tableConfig func() (*table, []*Record)
expectedRecords []*Record
expectedError error
}{
{
test: "it should return ErrNoTable if an invalid table is supplied",
tableConfig: func() (*table, []*Record) {
return &table{
mutex: &sync.Mutex{},
}, nil
},
expectedError: ErrNoTable,
},
{
test: "it should return ErrNoIndex if no index exists for column",
tableConfig: func() (*table, []*Record) {
return &table{
exists: true,
mutex: &sync.Mutex{},
indexes: make(map[string]*index),
}, nil
},
expectedError: ErrNoIndex,
},
{
test: "it should return all Records in the database",
tableConfig: func() (*table, []*Record) {
tbl := &table{
exists: true,
mutex: &sync.Mutex{},
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
expectedRecords := make([]*Record, 0)
for i := 0; i < 10; i++ {
key := fmt.Sprintf("key-%d", i)
rec, err := NewRecord(key, "test_column", struct{}{})
if err != nil {
t.Error(err)
}
tbl.indexes["test_column"].tree.ReplaceOrInsert(rec)
expectedRecords = append(expectedRecords, rec)
}
sort.Slice(expectedRecords, func(a, b int) bool {
return expectedRecords[a].id < expectedRecords[b].id
})
return tbl, expectedRecords
},
},
}
for _, tc := range tests {
t.Run(tc.test, func(t *testing.T) {
tbl, expectedRecords := tc.tableConfig()
rr, err := tbl.Select("test_column")
assert.Equal(t, expectedRecords, rr)
assert.Equal(t, tc.expectedError, err)
})
}
}
func TestTable_Insert(t *testing.T) {
tests := []struct {
test string
tableConfig func() *table
expectedError error
}{
{
test: "it should return ErrNoTable if an invalid table is supplied",
tableConfig: func() *table {
return &table{
mutex: &sync.Mutex{},
}
},
expectedError: ErrNoTable,
},
{
test: "it should return ErrNoIndex if no index exists for column",
tableConfig: func() *table {
return &table{
exists: true,
mutex: &sync.Mutex{},
indexes: make(map[string]*index),
}
},
expectedError: ErrNoIndex,
},
{
test: "it should return ErrRecordExists if a Record with key exists",
tableConfig: func() *table {
tbl := &table{
exists: true,
mutex: &sync.Mutex{},
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
rec, err := NewRecord("test_key", "test_column", struct{}{})
if err != nil {
t.Error(err)
}
tbl.indexes["test_column"].tree.ReplaceOrInsert(rec)
return tbl
},
expectedError: ErrRecordExists,
},
{
test: "it should return no error if successful",
tableConfig: func() *table {
return &table{
exists: true,
mutex: &sync.Mutex{},
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
},
},
}
for _, tc := range tests {
t.Run(tc.test, func(t *testing.T) {
tbl := tc.tableConfig()
rec, err := NewRecord("test_key", "test_column", struct{}{})
if err != nil {
t.Error(err)
}
err = tbl.Insert(rec)
assert.Equal(t, tc.expectedError, err)
})
}
}
func TestTable_Delete(t *testing.T) {
tests := []struct {
test string
tableConfig func() *table
expectedError error
}{
{
test: "it should return ErrNoTable if an invalid table is supplied",
tableConfig: func() *table {
return &table{
mutex: &sync.Mutex{},
}
},
expectedError: ErrNoTable,
},
{
test: "it should return ErrNoIndex if no index exists for column",
tableConfig: func() *table {
return &table{
exists: true,
mutex: &sync.Mutex{},
indexes: make(map[string]*index),
}
},
expectedError: ErrNoIndex,
},
{
test: "it should return ErrNoRecord if the Record does not exist",
tableConfig: func() *table {
return &table{
exists: true,
mutex: &sync.Mutex{},
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
},
expectedError: ErrNoRecord,
},
{
test: "it should return no error if the item was deleted",
tableConfig: func() *table {
tbl := &table{
exists: true,
mutex: &sync.Mutex{},
indexes: map[string]*index{
"test_column": &index{
tree: btree.New(5),
},
},
}
rec, err := NewRecord("test_key", "test_column", struct{}{})
if err != nil {
t.Error(err)
}
tbl.indexes["test_column"].tree.ReplaceOrInsert(rec)
return tbl
},
},
}
for _, tc := range tests {
t.Run(tc.test, func(t *testing.T) {
tbl := tc.tableConfig()
rec, err := NewRecord("test_key", "test_column", struct{}{})
if err != nil {
t.Error(err)
}
err = tbl.Delete(rec)
assert.Equal(t, tc.expectedError, err)
})
}
}