port tests from tmlibs, fix tests

This commit is contained in:
mossid 2018-10-09 04:43:55 +09:00
parent c770e74571
commit e7c76eb344
2 changed files with 238 additions and 23 deletions

View File

@ -9,6 +9,10 @@ import (
var _ KVStore = prefixStore{}
// prefixStore is similar with tendermint/tendermint/libs/db/prefix_db
// both gives access only to the limited subset of the store
// for convinience or safety
type prefixStore struct {
parent KVStore
prefix []byte
@ -84,13 +88,9 @@ func (s prefixStore) Iterator(start, end []byte) Iterator {
newend = cloneAppend(s.prefix, end)
}
return prefixIterator{
prefix: s.prefix,
start: start,
end: end,
iter: s.parent.Iterator(newstart, newend),
}
iter := s.parent.Iterator(newstart, newend)
return newPrefixIterator(s.prefix, start, end, iter)
}
// Implements KVStore
@ -115,12 +115,7 @@ func (s prefixStore) ReverseIterator(start, end []byte) Iterator {
skipOne(iter, cpIncr(s.prefix))
}
return prefixIterator{
prefix: s.prefix,
start: start,
end: end,
iter: iter,
}
return newPrefixIterator(s.prefix, start, end, iter)
}
type prefixIterator struct {
@ -130,6 +125,16 @@ type prefixIterator struct {
valid bool
}
func newPrefixIterator(prefix, start, end []byte, parent Iterator) prefixIterator {
return prefixIterator{
prefix: prefix,
start: start,
end: end,
iter: parent,
valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix),
}
}
// Implements Iterator
func (iter prefixIterator) Domain() ([]byte, []byte) {
return iter.start, iter.end
@ -155,7 +160,7 @@ func (iter prefixIterator) Next() {
// Implements Iterator
func (iter prefixIterator) Key() (key []byte) {
key = iter.iter.Key()
key = key[len(iter.prefix):]
key = stripPrefix(key, iter.prefix)
return
}

View File

@ -1,7 +1,6 @@
package store
import (
"bytes"
"math/rand"
"testing"
@ -127,9 +126,17 @@ func TestPrefixStoreIteratorEdgeCase(t *testing.T) {
baseStore.Set([]byte{0xAB, 0x00}, []byte{})
baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{})
for iter := prefixStore.Iterator(nil, nil); iter.Valid(); iter.Next() {
require.True(t, bytes.HasPrefix(iter.Key(), prefix))
}
iter := prefixStore.Iterator(nil, nil)
checkDomain(t, iter, nil, nil)
checkItem(t, iter, []byte{}, bz(""))
checkNext(t, iter, true)
checkItem(t, iter, []byte{0x00}, bz(""))
checkNext(t, iter, false)
checkInvalid(t, iter)
iter.Close()
}
func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) {
@ -150,9 +157,14 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) {
baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{})
iter := prefixStore.ReverseIterator(nil, nil)
for ; iter.Valid(); iter.Next() {
require.True(t, bytes.HasPrefix(iter.Key(), prefix))
}
checkDomain(t, iter, nil, nil)
checkItem(t, iter, []byte{0x00}, bz(""))
checkNext(t, iter, true)
checkItem(t, iter, []byte{}, bz(""))
checkNext(t, iter, false)
checkInvalid(t, iter)
iter.Close()
@ -172,9 +184,207 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) {
baseStore.Set([]byte{0xA9, 0xFF, 0xFF}, []byte{})
iter = prefixStore.ReverseIterator(nil, nil)
for ; iter.Valid(); iter.Next() {
require.True(t, bytes.HasPrefix(iter.Key(), prefix))
}
checkDomain(t, iter, nil, nil)
checkItem(t, iter, []byte{0x00}, bz(""))
checkNext(t, iter, true)
checkItem(t, iter, []byte{}, bz(""))
checkNext(t, iter, false)
checkInvalid(t, iter)
iter.Close()
}
// Tests below are ported from https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db_test.go
func mockStoreWithStuff() sdk.KVStore {
db := dbm.NewMemDB()
store := dbStoreAdapter{db}
// Under "key" prefix
store.Set(bz("key"), bz("value"))
store.Set(bz("key1"), bz("value1"))
store.Set(bz("key2"), bz("value2"))
store.Set(bz("key3"), bz("value3"))
store.Set(bz("something"), bz("else"))
store.Set(bz(""), bz(""))
store.Set(bz("k"), bz("val"))
store.Set(bz("ke"), bz("valu"))
store.Set(bz("kee"), bz("valuu"))
return store
}
func checkValue(t *testing.T, store sdk.KVStore, key []byte, expected []byte) {
bz := store.Get(key)
require.Equal(t, expected, bz)
}
func checkValid(t *testing.T, itr sdk.Iterator, expected bool) {
valid := itr.Valid()
require.Equal(t, expected, valid)
}
func checkNext(t *testing.T, itr sdk.Iterator, expected bool) {
itr.Next()
valid := itr.Valid()
require.Equal(t, expected, valid)
}
func checkDomain(t *testing.T, itr sdk.Iterator, start, end []byte) {
ds, de := itr.Domain()
require.Equal(t, start, ds)
require.Equal(t, end, de)
}
func checkItem(t *testing.T, itr sdk.Iterator, key, value []byte) {
require.Exactly(t, key, itr.Key())
require.Exactly(t, value, itr.Value())
}
func checkInvalid(t *testing.T, itr sdk.Iterator) {
checkValid(t, itr, false)
checkKeyPanics(t, itr)
checkValuePanics(t, itr)
checkNextPanics(t, itr)
}
func checkKeyPanics(t *testing.T, itr sdk.Iterator) {
require.Panics(t, func() { itr.Key() })
}
func checkValuePanics(t *testing.T, itr sdk.Iterator) {
require.Panics(t, func() { itr.Value() })
}
func checkNextPanics(t *testing.T, itr sdk.Iterator) {
require.Panics(t, func() { itr.Next() })
}
func TestPrefixDBSimple(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
checkValue(t, pstore, bz("key"), nil)
checkValue(t, pstore, bz(""), bz("value"))
checkValue(t, pstore, bz("key1"), nil)
checkValue(t, pstore, bz("1"), bz("value1"))
checkValue(t, pstore, bz("key2"), nil)
checkValue(t, pstore, bz("2"), bz("value2"))
checkValue(t, pstore, bz("key3"), nil)
checkValue(t, pstore, bz("3"), bz("value3"))
checkValue(t, pstore, bz("something"), nil)
checkValue(t, pstore, bz("k"), nil)
checkValue(t, pstore, bz("ke"), nil)
checkValue(t, pstore, bz("kee"), nil)
}
func TestPrefixDBIterator1(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.Iterator(nil, nil)
checkDomain(t, itr, nil, nil)
checkItem(t, itr, bz(""), bz("value"))
checkNext(t, itr, true)
checkItem(t, itr, bz("1"), bz("value1"))
checkNext(t, itr, true)
checkItem(t, itr, bz("2"), bz("value2"))
checkNext(t, itr, true)
checkItem(t, itr, bz("3"), bz("value3"))
checkNext(t, itr, false)
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBIterator2(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.Iterator(nil, bz(""))
checkDomain(t, itr, nil, bz(""))
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBIterator3(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.Iterator(bz(""), nil)
checkDomain(t, itr, bz(""), nil)
checkItem(t, itr, bz(""), bz("value"))
checkNext(t, itr, true)
checkItem(t, itr, bz("1"), bz("value1"))
checkNext(t, itr, true)
checkItem(t, itr, bz("2"), bz("value2"))
checkNext(t, itr, true)
checkItem(t, itr, bz("3"), bz("value3"))
checkNext(t, itr, false)
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBIterator4(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.Iterator(bz(""), bz(""))
checkDomain(t, itr, bz(""), bz(""))
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator1(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.ReverseIterator(nil, nil)
checkDomain(t, itr, nil, nil)
checkItem(t, itr, bz("3"), bz("value3"))
checkNext(t, itr, true)
checkItem(t, itr, bz("2"), bz("value2"))
checkNext(t, itr, true)
checkItem(t, itr, bz("1"), bz("value1"))
checkNext(t, itr, true)
checkItem(t, itr, bz(""), bz("value"))
checkNext(t, itr, false)
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator2(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.ReverseIterator(nil, bz(""))
checkDomain(t, itr, nil, bz(""))
checkItem(t, itr, bz("3"), bz("value3"))
checkNext(t, itr, true)
checkItem(t, itr, bz("2"), bz("value2"))
checkNext(t, itr, true)
checkItem(t, itr, bz("1"), bz("value1"))
checkNext(t, itr, false)
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator3(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.ReverseIterator(bz(""), nil)
checkDomain(t, itr, bz(""), nil)
checkItem(t, itr, bz(""), bz("value"))
checkNext(t, itr, false)
checkInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator4(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.ReverseIterator(bz(""), bz(""))
checkInvalid(t, itr)
itr.Close()
}