package db import ( "fmt" "os" "testing" "github.com/stretchr/testify/assert" ) func TestDBIteratorSingleKey(t *testing.T) { for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { db, dir := newTempDB(t, backend) defer os.RemoveAll(dir) db.SetSync(bz("1"), bz("value_1")) itr := db.Iterator(nil, nil) checkValid(t, itr, true) checkNext(t, itr, false) checkValid(t, itr, false) checkNextPanics(t, itr) // Once invalid... checkInvalid(t, itr) }) } } func TestDBIteratorTwoKeys(t *testing.T) { for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { db, dir := newTempDB(t, backend) defer os.RemoveAll(dir) db.SetSync(bz("1"), bz("value_1")) db.SetSync(bz("2"), bz("value_1")) { // Fail by calling Next too much itr := db.Iterator(nil, nil) checkValid(t, itr, true) checkNext(t, itr, true) checkValid(t, itr, true) checkNext(t, itr, false) checkValid(t, itr, false) checkNextPanics(t, itr) // Once invalid... checkInvalid(t, itr) } }) } } func TestDBIteratorMany(t *testing.T) { for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { db, dir := newTempDB(t, backend) defer os.RemoveAll(dir) keys := make([][]byte, 100) for i := 0; i < 100; i++ { keys[i] = []byte{byte(i)} } value := []byte{5} for _, k := range keys { db.Set(k, value) } itr := db.Iterator(nil, nil) defer itr.Close() for ; itr.Valid(); itr.Next() { assert.Equal(t, db.Get(itr.Key()), itr.Value()) } }) } } func TestDBIteratorEmpty(t *testing.T) { for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { db, dir := newTempDB(t, backend) defer os.RemoveAll(dir) itr := db.Iterator(nil, nil) checkInvalid(t, itr) }) } } func TestDBIteratorEmptyBeginAfter(t *testing.T) { for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { db, dir := newTempDB(t, backend) defer os.RemoveAll(dir) itr := db.Iterator(bz("1"), nil) checkInvalid(t, itr) }) } } func TestDBIteratorNonemptyBeginAfter(t *testing.T) { for backend := range backends { t.Run(fmt.Sprintf("Backend %s", backend), func(t *testing.T) { db, dir := newTempDB(t, backend) defer os.RemoveAll(dir) db.SetSync(bz("1"), bz("value_1")) itr := db.Iterator(bz("2"), nil) checkInvalid(t, itr) }) } } func TestDBBatchWrite(t *testing.T) { testCases := []struct { modify func(batch Batch) calls map[string]int }{ 0: { func(batch Batch) { batch.Set(bz("1"), bz("1")) batch.Set(bz("2"), bz("2")) batch.Delete(bz("3")) batch.Set(bz("4"), bz("4")) batch.Write() }, map[string]int{ "Set": 0, "SetSync": 0, "SetNoLock": 3, "SetNoLockSync": 0, "Delete": 0, "DeleteSync": 0, "DeleteNoLock": 1, "DeleteNoLockSync": 0, }, }, 1: { func(batch Batch) { batch.Set(bz("1"), bz("1")) batch.Set(bz("2"), bz("2")) batch.Set(bz("4"), bz("4")) batch.Delete(bz("3")) batch.Write() }, map[string]int{ "Set": 0, "SetSync": 0, "SetNoLock": 3, "SetNoLockSync": 0, "Delete": 0, "DeleteSync": 0, "DeleteNoLock": 1, "DeleteNoLockSync": 0, }, }, 2: { func(batch Batch) { batch.Set(bz("1"), bz("1")) batch.Set(bz("2"), bz("2")) batch.Delete(bz("3")) batch.Set(bz("4"), bz("4")) batch.WriteSync() }, map[string]int{ "Set": 0, "SetSync": 0, "SetNoLock": 2, "SetNoLockSync": 1, "Delete": 0, "DeleteSync": 0, "DeleteNoLock": 1, "DeleteNoLockSync": 0, }, }, 3: { func(batch Batch) { batch.Set(bz("1"), bz("1")) batch.Set(bz("2"), bz("2")) batch.Set(bz("4"), bz("4")) batch.Delete(bz("3")) batch.WriteSync() }, map[string]int{ "Set": 0, "SetSync": 0, "SetNoLock": 3, "SetNoLockSync": 0, "Delete": 0, "DeleteSync": 0, "DeleteNoLock": 0, "DeleteNoLockSync": 1, }, }, } for i, tc := range testCases { mdb := newMockDB() ddb := NewDebugDB(t.Name(), mdb) batch := ddb.NewBatch() tc.modify(batch) for call, exp := range tc.calls { got := mdb.calls[call] assert.Equal(t, exp, got, "#%v - key: %s", i, call) } } }