added more test
This commit is contained in:
parent
d98ea3764f
commit
c441ccdf01
|
@ -5,6 +5,7 @@ import (
|
|||
"sort"
|
||||
"sync"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
)
|
||||
|
||||
|
@ -134,6 +135,16 @@ func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator {
|
|||
return ci.iterator(start, end, false)
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (ci *cacheKVStore) Subspace(prefix []byte) Iterator {
|
||||
return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), true)
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (ci *cacheKVStore) ReverseSubspace(prefix []byte) Iterator {
|
||||
return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), false)
|
||||
}
|
||||
|
||||
func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator {
|
||||
var parent, cache Iterator
|
||||
if ascending {
|
||||
|
|
|
@ -19,5 +19,13 @@ func (dsa dbStoreAdapter) CacheWrap() CacheWrap {
|
|||
return NewCacheKVStore(dsa)
|
||||
}
|
||||
|
||||
func (dsa dbStoreAdapter) Subspace(prefix []byte) Iterator {
|
||||
return dsa.Iterator(prefix, sdk.PrefixEndBytes(prefix))
|
||||
}
|
||||
|
||||
func (dsa dbStoreAdapter) ReverseSubspace(prefix []byte) Iterator {
|
||||
return dsa.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix))
|
||||
}
|
||||
|
||||
// dbm.DB implements KVStore so we can CacheKVStore it.
|
||||
var _ KVStore = dbStoreAdapter{dbm.DB(nil)}
|
||||
|
|
|
@ -119,33 +119,21 @@ func (st *iavlStore) Iterator(start, end []byte) Iterator {
|
|||
return newIAVLIterator(st.tree.Tree(), start, end, true)
|
||||
}
|
||||
|
||||
func (st *iavlStore) Subspace(prefix []byte) Iterator {
|
||||
end := make([]byte, len(prefix))
|
||||
copy(end, prefix)
|
||||
finished := false
|
||||
i := 1
|
||||
|
||||
for !finished {
|
||||
if end[len(end)-i] != byte(255) {
|
||||
end[len(end)-i]++
|
||||
finished = true
|
||||
} else {
|
||||
end[len(end)-i]++
|
||||
i++
|
||||
if i > len(end) {
|
||||
end = nil
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return st.Iterator(prefix, end)
|
||||
}
|
||||
|
||||
// Implements IterKVStore.
|
||||
// Implements KVStore.
|
||||
func (st *iavlStore) ReverseIterator(start, end []byte) Iterator {
|
||||
return newIAVLIterator(st.tree.Tree(), start, end, false)
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (st *iavlStore) Subspace(prefix []byte) Iterator {
|
||||
return st.Iterator(prefix, sdk.PrefixEndBytes(prefix))
|
||||
}
|
||||
|
||||
// Implements KVStore.
|
||||
func (st *iavlStore) ReverseSubspace(prefix []byte) Iterator {
|
||||
return st.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix))
|
||||
}
|
||||
|
||||
// Query implements ABCI interface, allows queries
|
||||
//
|
||||
// by default we will return from (latest height -1),
|
||||
|
|
|
@ -198,6 +198,65 @@ func TestIAVLSubspace(t *testing.T) {
|
|||
assert.Equal(t, len(expected), i)
|
||||
}
|
||||
|
||||
func TestIAVLReverseSubspace(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
tree, _ := newTree(t, db)
|
||||
iavlStore := newIAVLStore(tree, numHistory)
|
||||
|
||||
iavlStore.Set([]byte("test1"), []byte("test1"))
|
||||
iavlStore.Set([]byte("test2"), []byte("test2"))
|
||||
iavlStore.Set([]byte("test3"), []byte("test3"))
|
||||
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4"))
|
||||
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4"))
|
||||
iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4"))
|
||||
iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4"))
|
||||
iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4"))
|
||||
iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4"))
|
||||
|
||||
i := 0
|
||||
|
||||
iter := iavlStore.ReverseSubspace([]byte("test"))
|
||||
expected := []string{"test3", "test2", "test1"}
|
||||
for i = 0; iter.Valid(); iter.Next() {
|
||||
expectedKey := expected[i]
|
||||
key, value := iter.Key(), iter.Value()
|
||||
assert.EqualValues(t, key, expectedKey)
|
||||
assert.EqualValues(t, value, expectedKey)
|
||||
i += 1
|
||||
}
|
||||
assert.Equal(t, len(expected), i)
|
||||
|
||||
iter = iavlStore.ReverseSubspace([]byte{byte(55), byte(255), byte(255)})
|
||||
expected2 := [][]byte{
|
||||
[]byte{byte(55), byte(255), byte(255), byte(255)},
|
||||
[]byte{byte(55), byte(255), byte(255), byte(1)},
|
||||
[]byte{byte(55), byte(255), byte(255), byte(0)},
|
||||
}
|
||||
for i = 0; iter.Valid(); iter.Next() {
|
||||
expectedKey := expected2[i]
|
||||
key, value := iter.Key(), iter.Value()
|
||||
assert.EqualValues(t, key, expectedKey)
|
||||
assert.EqualValues(t, value, []byte("test4"))
|
||||
i += 1
|
||||
}
|
||||
assert.Equal(t, len(expected), i)
|
||||
|
||||
iter = iavlStore.ReverseSubspace([]byte{byte(255), byte(255)})
|
||||
expected2 = [][]byte{
|
||||
[]byte{byte(255), byte(255), byte(255)},
|
||||
[]byte{byte(255), byte(255), byte(1)},
|
||||
[]byte{byte(255), byte(255), byte(0)},
|
||||
}
|
||||
for i = 0; iter.Valid(); iter.Next() {
|
||||
expectedKey := expected2[i]
|
||||
key, value := iter.Key(), iter.Value()
|
||||
assert.EqualValues(t, key, expectedKey)
|
||||
assert.EqualValues(t, value, []byte("test4"))
|
||||
i += 1
|
||||
}
|
||||
assert.Equal(t, len(expected), i)
|
||||
}
|
||||
|
||||
func TestIAVLStoreQuery(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
tree := iavl.NewVersionedTree(db, cacheSize)
|
||||
|
|
|
@ -111,6 +111,14 @@ type KVStore interface {
|
|||
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
|
||||
ReverseIterator(start, end []byte) Iterator
|
||||
|
||||
// Iterator over all the keys with a certain prefix in ascending order.
|
||||
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
|
||||
Subspace(prefix []byte) Iterator
|
||||
|
||||
// Iterator over all the keys with a certain prefix in descending order.
|
||||
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
|
||||
ReverseSubspace(prefix []byte) Iterator
|
||||
|
||||
// TODO Not yet implemented.
|
||||
// CreateSubKVStore(key *storeKey) (KVStore, error)
|
||||
|
||||
|
@ -222,3 +230,28 @@ func (key *KVStoreKey) Name() string {
|
|||
func (key *KVStoreKey) String() string {
|
||||
return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name)
|
||||
}
|
||||
|
||||
// TODO: Move to TmLibs
|
||||
func PrefixEndBytes(prefix []byte) []byte {
|
||||
if prefix == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
end := make([]byte, len(prefix))
|
||||
copy(end, prefix)
|
||||
finished := false
|
||||
|
||||
for !finished {
|
||||
if end[len(end)-1] != byte(255) {
|
||||
end[len(end)-1]++
|
||||
finished = true
|
||||
} else {
|
||||
end = end[:len(end)-1]
|
||||
if len(end) == 0 {
|
||||
end = nil
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return end
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue