2017-12-11 23:36:50 -08:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
2018-01-30 10:59:05 -08:00
|
|
|
abci "github.com/tendermint/abci/types"
|
|
|
|
"github.com/tendermint/iavl"
|
2017-12-11 23:36:50 -08:00
|
|
|
cmn "github.com/tendermint/tmlibs/common"
|
|
|
|
dbm "github.com/tendermint/tmlibs/db"
|
|
|
|
|
2018-01-30 10:59:05 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2017-12-11 23:36:50 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
cacheSize = 100
|
|
|
|
numHistory int64 = 5
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
treeData = map[string]string{
|
|
|
|
"hello": "goodbye",
|
|
|
|
"aloha": "shalom",
|
|
|
|
}
|
|
|
|
nMoreData = 0
|
|
|
|
)
|
|
|
|
|
|
|
|
// make a tree and save it
|
|
|
|
func newTree(t *testing.T, db dbm.DB) (*iavl.VersionedTree, CommitID) {
|
|
|
|
tree := iavl.NewVersionedTree(db, cacheSize)
|
|
|
|
for k, v := range treeData {
|
|
|
|
tree.Set([]byte(k), []byte(v))
|
|
|
|
}
|
|
|
|
for i := 0; i < nMoreData; i++ {
|
|
|
|
key := cmn.RandBytes(12)
|
|
|
|
value := cmn.RandBytes(50)
|
|
|
|
tree.Set(key, value)
|
|
|
|
}
|
|
|
|
hash, ver, err := tree.SaveVersion()
|
|
|
|
assert.Nil(t, err)
|
|
|
|
return tree, CommitID{ver, hash}
|
|
|
|
}
|
|
|
|
|
2017-12-12 20:13:51 -08:00
|
|
|
func TestIAVLStoreGetSetHasDelete(t *testing.T) {
|
2017-12-11 23:36:50 -08:00
|
|
|
db := dbm.NewMemDB()
|
|
|
|
tree, _ := newTree(t, db)
|
|
|
|
iavlStore := newIAVLStore(tree, numHistory)
|
|
|
|
|
|
|
|
key := "hello"
|
|
|
|
|
|
|
|
exists := iavlStore.Has([]byte(key))
|
|
|
|
assert.True(t, exists)
|
|
|
|
|
2017-12-12 20:13:51 -08:00
|
|
|
value := iavlStore.Get([]byte(key))
|
2017-12-11 23:36:50 -08:00
|
|
|
assert.EqualValues(t, value, treeData[key])
|
|
|
|
|
|
|
|
value2 := "notgoodbye"
|
2017-12-12 20:13:51 -08:00
|
|
|
iavlStore.Set([]byte(key), []byte(value2))
|
2017-12-11 23:36:50 -08:00
|
|
|
|
2017-12-12 20:13:51 -08:00
|
|
|
value = iavlStore.Get([]byte(key))
|
2017-12-11 23:36:50 -08:00
|
|
|
assert.EqualValues(t, value, value2)
|
|
|
|
|
2017-12-12 20:13:51 -08:00
|
|
|
iavlStore.Delete([]byte(key))
|
2017-12-11 23:36:50 -08:00
|
|
|
|
|
|
|
exists = iavlStore.Has([]byte(key))
|
|
|
|
assert.False(t, exists)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIAVLIterator(t *testing.T) {
|
|
|
|
db := dbm.NewMemDB()
|
|
|
|
tree, _ := newTree(t, db)
|
|
|
|
iavlStore := newIAVLStore(tree, numHistory)
|
|
|
|
iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz"))
|
|
|
|
expected := []string{"aloha", "hello"}
|
2018-04-05 12:54:30 -07:00
|
|
|
var i int
|
|
|
|
|
2018-03-30 13:36:04 -07:00
|
|
|
for i = 0; iter.Valid(); iter.Next() {
|
2017-12-11 23:36:50 -08:00
|
|
|
expectedKey := expected[i]
|
|
|
|
key, value := iter.Key(), iter.Value()
|
|
|
|
assert.EqualValues(t, key, expectedKey)
|
|
|
|
assert.EqualValues(t, value, treeData[expectedKey])
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2017-12-11 23:36:50 -08:00
|
|
|
}
|
2018-03-31 10:30:25 -07:00
|
|
|
assert.Equal(t, len(expected), i)
|
2018-03-30 13:36:04 -07:00
|
|
|
|
|
|
|
iter = iavlStore.Iterator([]byte("golang"), []byte("rocks"))
|
|
|
|
expected = []string{"hello"}
|
|
|
|
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, treeData[expectedKey])
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-31 15:02:29 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
|
|
|
|
iter = iavlStore.Iterator(nil, []byte("golang"))
|
|
|
|
expected = []string{"aloha"}
|
|
|
|
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, treeData[expectedKey])
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-31 15:02:29 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
|
|
|
|
iter = iavlStore.Iterator(nil, []byte("shalom"))
|
|
|
|
expected = []string{"aloha", "hello"}
|
|
|
|
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, treeData[expectedKey])
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-31 15:02:29 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
|
|
|
|
iter = iavlStore.Iterator(nil, nil)
|
|
|
|
expected = []string{"aloha", "hello"}
|
|
|
|
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, treeData[expectedKey])
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-30 13:36:04 -07:00
|
|
|
}
|
2018-03-31 10:30:25 -07:00
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
|
|
|
|
iter = iavlStore.Iterator([]byte("golang"), nil)
|
|
|
|
expected = []string{"hello"}
|
|
|
|
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, treeData[expectedKey])
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-31 10:30:25 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
2017-12-11 23:36:50 -08:00
|
|
|
}
|
2018-01-30 10:59:05 -08:00
|
|
|
|
2018-04-05 12:54:30 -07:00
|
|
|
func TestIAVLSubspaceIterator(t *testing.T) {
|
2018-03-19 13:04:52 -07:00
|
|
|
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"))
|
2018-03-30 13:36:04 -07:00
|
|
|
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"))
|
2018-03-31 15:26:00 -07:00
|
|
|
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"))
|
|
|
|
|
2018-03-30 13:36:04 -07:00
|
|
|
i := 0
|
2018-03-19 13:04:52 -07:00
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
iter := sdk.KVStorePrefixIterator(iavlStore, []byte("test"))
|
2018-03-19 13:04:52 -07:00
|
|
|
expected := []string{"test1", "test2", "test3"}
|
2018-03-30 13:36:04 -07:00
|
|
|
for i = 0; iter.Valid(); iter.Next() {
|
2018-03-19 13:04:52 -07:00
|
|
|
expectedKey := expected[i]
|
|
|
|
key, value := iter.Key(), iter.Value()
|
|
|
|
assert.EqualValues(t, key, expectedKey)
|
|
|
|
assert.EqualValues(t, value, expectedKey)
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-19 13:04:52 -07:00
|
|
|
}
|
2018-03-31 10:30:25 -07:00
|
|
|
assert.Equal(t, len(expected), i)
|
2018-03-30 13:36:04 -07:00
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
iter = sdk.KVStorePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)})
|
2018-03-30 13:36:04 -07:00
|
|
|
expected2 := [][]byte{
|
|
|
|
[]byte{byte(55), byte(255), byte(255), byte(0)},
|
|
|
|
[]byte{byte(55), byte(255), byte(255), byte(1)},
|
|
|
|
[]byte{byte(55), byte(255), byte(255), byte(255)},
|
|
|
|
}
|
|
|
|
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"))
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-30 13:36:04 -07:00
|
|
|
}
|
2018-03-31 10:30:25 -07:00
|
|
|
assert.Equal(t, len(expected), i)
|
2018-03-30 13:36:04 -07:00
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
iter = sdk.KVStorePrefixIterator(iavlStore, []byte{byte(255), byte(255)})
|
2018-03-30 13:36:04 -07:00
|
|
|
expected2 = [][]byte{
|
|
|
|
[]byte{byte(255), byte(255), byte(0)},
|
|
|
|
[]byte{byte(255), byte(255), byte(1)},
|
|
|
|
[]byte{byte(255), byte(255), byte(255)},
|
|
|
|
}
|
|
|
|
for i = 0; iter.Valid(); iter.Next() {
|
2018-04-01 09:00:28 -07:00
|
|
|
expectedKey := expected2[i]
|
|
|
|
key, value := iter.Key(), iter.Value()
|
|
|
|
assert.EqualValues(t, key, expectedKey)
|
|
|
|
assert.EqualValues(t, value, []byte("test4"))
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-04-01 09:00:28 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
}
|
|
|
|
|
2018-04-05 12:54:30 -07:00
|
|
|
func TestIAVLReverseSubspaceIterator(t *testing.T) {
|
2018-04-01 09:00:28 -07:00
|
|
|
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
|
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
iter := sdk.KVStoreReversePrefixIterator(iavlStore, []byte("test"))
|
2018-04-01 09:00:28 -07:00
|
|
|
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)
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-04-01 09:00:28 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
iter = sdk.KVStoreReversePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)})
|
2018-04-01 09:00:28 -07:00
|
|
|
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"))
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-04-01 09:00:28 -07:00
|
|
|
}
|
|
|
|
assert.Equal(t, len(expected), i)
|
|
|
|
|
2018-05-26 18:00:39 -07:00
|
|
|
iter = sdk.KVStoreReversePrefixIterator(iavlStore, []byte{byte(255), byte(255)})
|
2018-04-01 09:00:28 -07:00
|
|
|
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() {
|
2018-03-30 13:36:04 -07:00
|
|
|
expectedKey := expected2[i]
|
|
|
|
key, value := iter.Key(), iter.Value()
|
|
|
|
assert.EqualValues(t, key, expectedKey)
|
|
|
|
assert.EqualValues(t, value, []byte("test4"))
|
2018-04-18 21:49:24 -07:00
|
|
|
i++
|
2018-03-30 13:36:04 -07:00
|
|
|
}
|
2018-03-31 10:30:25 -07:00
|
|
|
assert.Equal(t, len(expected), i)
|
2018-03-19 13:04:52 -07:00
|
|
|
}
|
|
|
|
|
2018-01-30 10:59:05 -08:00
|
|
|
func TestIAVLStoreQuery(t *testing.T) {
|
|
|
|
db := dbm.NewMemDB()
|
|
|
|
tree := iavl.NewVersionedTree(db, cacheSize)
|
|
|
|
iavlStore := newIAVLStore(tree, numHistory)
|
|
|
|
|
2018-05-08 13:32:41 -07:00
|
|
|
k1, v1 := []byte("key1"), []byte("val1")
|
|
|
|
k2, v2 := []byte("key2"), []byte("val2")
|
2018-05-08 13:15:35 -07:00
|
|
|
v3 := []byte("val3")
|
|
|
|
|
2018-05-08 13:32:41 -07:00
|
|
|
ksub := []byte("key")
|
2018-05-09 15:24:51 -07:00
|
|
|
KVs0 := []KVPair{}
|
|
|
|
KVs1 := []KVPair{
|
2018-05-08 13:32:41 -07:00
|
|
|
{k1, v1},
|
|
|
|
{k2, v2},
|
|
|
|
}
|
2018-05-09 15:24:51 -07:00
|
|
|
KVs2 := []KVPair{
|
2018-05-08 13:32:41 -07:00
|
|
|
{k1, v3},
|
|
|
|
{k2, v2},
|
|
|
|
}
|
|
|
|
valExpSubEmpty := cdc.MustMarshalBinary(KVs0)
|
2018-05-08 13:15:35 -07:00
|
|
|
valExpSub1 := cdc.MustMarshalBinary(KVs1)
|
|
|
|
valExpSub2 := cdc.MustMarshalBinary(KVs2)
|
2018-01-30 10:59:05 -08:00
|
|
|
|
|
|
|
cid := iavlStore.Commit()
|
|
|
|
ver := cid.Version
|
2018-05-08 13:15:35 -07:00
|
|
|
query := abci.RequestQuery{Path: "/key", Data: k1, Height: ver}
|
|
|
|
querySub := abci.RequestQuery{Path: "/subspace", Data: ksub, Height: ver}
|
2018-01-30 10:59:05 -08:00
|
|
|
|
2018-05-08 13:32:41 -07:00
|
|
|
// query subspace before anything set
|
|
|
|
qres := iavlStore.Query(querySub)
|
2018-01-30 10:59:05 -08:00
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
2018-05-08 13:32:41 -07:00
|
|
|
assert.Equal(t, valExpSubEmpty, qres.Value)
|
|
|
|
|
|
|
|
// set data
|
|
|
|
iavlStore.Set(k1, v1)
|
|
|
|
iavlStore.Set(k2, v2)
|
|
|
|
|
|
|
|
// set data without commit, doesn't show up
|
|
|
|
qres = iavlStore.Query(query)
|
2018-05-08 13:15:35 -07:00
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
|
|
|
assert.Nil(t, qres.Value)
|
2018-01-30 10:59:05 -08:00
|
|
|
|
|
|
|
// commit it, but still don't see on old version
|
|
|
|
cid = iavlStore.Commit()
|
|
|
|
qres = iavlStore.Query(query)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
|
|
|
assert.Nil(t, qres.Value)
|
|
|
|
|
|
|
|
// but yes on the new version
|
|
|
|
query.Height = cid.Version
|
|
|
|
qres = iavlStore.Query(query)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
2018-05-08 13:15:35 -07:00
|
|
|
assert.Equal(t, v1, qres.Value)
|
|
|
|
|
|
|
|
// and for the subspace
|
|
|
|
qres = iavlStore.Query(querySub)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
|
|
|
assert.Equal(t, valExpSub1, qres.Value)
|
2018-01-30 10:59:05 -08:00
|
|
|
|
|
|
|
// modify
|
2018-05-08 13:15:35 -07:00
|
|
|
iavlStore.Set(k1, v3)
|
2018-01-30 10:59:05 -08:00
|
|
|
cid = iavlStore.Commit()
|
|
|
|
|
|
|
|
// query will return old values, as height is fixed
|
|
|
|
qres = iavlStore.Query(query)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
2018-05-08 13:15:35 -07:00
|
|
|
assert.Equal(t, v1, qres.Value)
|
|
|
|
|
2018-01-30 10:59:05 -08:00
|
|
|
// update to latest in the query and we are happy
|
|
|
|
query.Height = cid.Version
|
|
|
|
qres = iavlStore.Query(query)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
|
|
|
assert.Equal(t, v3, qres.Value)
|
|
|
|
query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version}
|
|
|
|
qres = iavlStore.Query(query2)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
|
|
|
assert.Equal(t, v2, qres.Value)
|
2018-05-08 13:15:35 -07:00
|
|
|
// and for the subspace
|
|
|
|
qres = iavlStore.Query(querySub)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
|
|
|
assert.Equal(t, valExpSub2, qres.Value)
|
2018-01-30 10:59:05 -08:00
|
|
|
|
|
|
|
// default (height 0) will show latest -1
|
2018-05-08 13:15:35 -07:00
|
|
|
query0 := abci.RequestQuery{Path: "/store", Data: k1}
|
2018-01-30 10:59:05 -08:00
|
|
|
qres = iavlStore.Query(query0)
|
|
|
|
assert.Equal(t, uint32(sdk.CodeOK), qres.Code)
|
2018-05-08 13:15:35 -07:00
|
|
|
assert.Equal(t, v1, qres.Value)
|
2018-01-30 10:59:05 -08:00
|
|
|
}
|