diff --git a/go.mod b/go.mod index e19ef51..db3f22d 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/spf13/viper v1.6.3 github.com/stretchr/testify v1.6.1 github.com/tendermint/go-amino v0.15.1 + github.com/tendermint/iavl v0.14.0 github.com/tendermint/tendermint v0.33.6 github.com/tendermint/tm-db v0.5.1 go.etcd.io/bbolt v1.3.4 // indirect diff --git a/x/wasm/internal/types/iavl_range_test.go b/x/wasm/internal/types/iavl_range_test.go new file mode 100644 index 0000000..3f7a054 --- /dev/null +++ b/x/wasm/internal/types/iavl_range_test.go @@ -0,0 +1,59 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/iavl" + "github.com/magiconair/properties/assert" + "github.com/stretchr/testify/require" + iavl2 "github.com/tendermint/iavl" + dbm "github.com/tendermint/tm-db" + "testing" +) + +// This is modeled close to +// https://github.com/CosmWasm/cosmwasm-plus/blob/f97a7de44b6a930fd1d5179ee6f95b786a532f32/packages/storage-plus/src/prefix.rs#L183 +// and designed to ensure the IAVL store handles bounds the same way as the mock storage we use in Rust contract tests +func TestIavlRangeBounds(t *testing.T) { + db := dbm.NewMemDB() + tree, err := iavl2.NewMutableTree(db, 50) + require.NoError(t, err) + store := iavl.UnsafeNewStore(tree) + + expected := []KV{ + {[]byte("bar"), []byte("1")}, + {[]byte("ra"), []byte("2")}, + {[]byte("zi"), []byte("3")}, + } + reversed := []KV{ + {[]byte("zi"), []byte("3")}, + {[]byte("ra"), []byte("2")}, + {[]byte("bar"), []byte("1")}, + } + + // set up test cases, like `ensure_proper_range_bounds` in `cw-storage-plus` + for _, kv := range expected { + store.Set(kv.Key, kv.Value) + } + + ascAll := store.Iterator(nil, nil) + assert.Equal(t, expected, consume(ascAll)) + + descAll := store.ReverseIterator(nil, nil) + assert.Equal(t, reversed, consume(descAll)) +} + +type KV struct { + Key []byte + Value []byte +} + +func consume(itr store.Iterator) []KV { + defer itr.Close() + + var res []KV + for ; itr.Valid(); itr.Next() { + k, v := itr.Key(), itr.Value() + res = append(res, KV{k, v}) + } + return res +} \ No newline at end of file