cosmos-sdk/db/prefix/prefix_test.go

158 lines
5.1 KiB
Go
Raw Normal View History

feat: ADR-040: Implement KV Store with decoupled storage and SMT (#9892) ## Description Resolves: https://github.com/cosmos/cosmos-sdk/issues/10117 Implements a `CommitKVStore` which separates the concerns of state storage and state commitment according to [ADR-040](https://github.com/cosmos/cosmos-sdk/blob/eb7d939f86c6cd7b4218492364cdda3f649f06b5/docs/architecture/adr-040-storage-and-smt-state-commitments.md). --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - n/a - [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [x] added a changelog entry to `CHANGELOG.md` - [x] included comments for [documenting Go code](https://blog.golang.org/godoc) - [x] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
2021-10-19 04:58:06 -07:00
package prefix_test
import (
"testing"
"github.com/stretchr/testify/require"
dbm "github.com/cosmos/cosmos-sdk/db"
"github.com/cosmos/cosmos-sdk/db/dbtest"
"github.com/cosmos/cosmos-sdk/db/memdb"
pfx "github.com/cosmos/cosmos-sdk/db/prefix"
)
func fillDBWithStuff(t *testing.T, dbw dbm.DBWriter) {
// Under "key" prefix
require.NoError(t, dbw.Set([]byte("key"), []byte("value")))
require.NoError(t, dbw.Set([]byte("key1"), []byte("value1")))
require.NoError(t, dbw.Set([]byte("key2"), []byte("value2")))
require.NoError(t, dbw.Set([]byte("key3"), []byte("value3")))
require.NoError(t, dbw.Set([]byte("something"), []byte("else")))
require.NoError(t, dbw.Set([]byte("k"), []byte("val")))
require.NoError(t, dbw.Set([]byte("ke"), []byte("valu")))
require.NoError(t, dbw.Set([]byte("kee"), []byte("valuu")))
require.NoError(t, dbw.Commit())
}
func mockDBWithStuff(t *testing.T) dbm.DBConnection {
db := memdb.NewDB()
fillDBWithStuff(t, db.Writer())
return db
}
func makePrefixReader(t *testing.T, db dbm.DBConnection, pre []byte) dbm.DBReader {
view := db.Reader()
require.NotNil(t, view)
return pfx.NewPrefixReader(view, pre)
}
func TestPrefixDBSimple(t *testing.T) {
pdb := makePrefixReader(t, mockDBWithStuff(t), []byte("key"))
dbtest.AssertValue(t, pdb, []byte("key"), nil)
dbtest.AssertValue(t, pdb, []byte("key1"), nil)
dbtest.AssertValue(t, pdb, []byte("1"), []byte("value1"))
dbtest.AssertValue(t, pdb, []byte("key2"), nil)
dbtest.AssertValue(t, pdb, []byte("2"), []byte("value2"))
dbtest.AssertValue(t, pdb, []byte("key3"), nil)
dbtest.AssertValue(t, pdb, []byte("3"), []byte("value3"))
dbtest.AssertValue(t, pdb, []byte("something"), nil)
dbtest.AssertValue(t, pdb, []byte("k"), nil)
dbtest.AssertValue(t, pdb, []byte("ke"), nil)
dbtest.AssertValue(t, pdb, []byte("kee"), nil)
}
func TestPrefixDBIterator1(t *testing.T) {
pdb := makePrefixReader(t, mockDBWithStuff(t), []byte("key"))
itr, err := pdb.Iterator(nil, nil)
require.NoError(t, err)
dbtest.AssertDomain(t, itr, nil, nil)
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("1"), []byte("value1"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("2"), []byte("value2"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("3"), []byte("value3"))
dbtest.AssertNext(t, itr, false)
dbtest.AssertInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator1(t *testing.T) {
pdb := makePrefixReader(t, mockDBWithStuff(t), []byte("key"))
itr, err := pdb.ReverseIterator(nil, nil)
require.NoError(t, err)
dbtest.AssertDomain(t, itr, nil, nil)
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("3"), []byte("value3"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("2"), []byte("value2"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("1"), []byte("value1"))
dbtest.AssertNext(t, itr, false)
dbtest.AssertInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator5(t *testing.T) {
pdb := makePrefixReader(t, mockDBWithStuff(t), []byte("key"))
itr, err := pdb.ReverseIterator([]byte("1"), nil)
require.NoError(t, err)
dbtest.AssertDomain(t, itr, []byte("1"), nil)
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("3"), []byte("value3"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("2"), []byte("value2"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("1"), []byte("value1"))
dbtest.AssertNext(t, itr, false)
dbtest.AssertInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator6(t *testing.T) {
pdb := makePrefixReader(t, mockDBWithStuff(t), []byte("key"))
itr, err := pdb.ReverseIterator([]byte("2"), nil)
require.NoError(t, err)
dbtest.AssertDomain(t, itr, []byte("2"), nil)
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("3"), []byte("value3"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("2"), []byte("value2"))
dbtest.AssertNext(t, itr, false)
dbtest.AssertInvalid(t, itr)
itr.Close()
}
func TestPrefixDBReverseIterator7(t *testing.T) {
pdb := makePrefixReader(t, mockDBWithStuff(t), []byte("key"))
itr, err := pdb.ReverseIterator(nil, []byte("2"))
require.NoError(t, err)
dbtest.AssertDomain(t, itr, nil, []byte("2"))
dbtest.AssertNext(t, itr, true)
dbtest.AssertItem(t, itr, []byte("1"), []byte("value1"))
dbtest.AssertNext(t, itr, false)
dbtest.AssertInvalid(t, itr)
itr.Close()
}
func TestPrefixDBViewVersion(t *testing.T) {
prefix := []byte("key")
db := memdb.NewDB()
fillDBWithStuff(t, db.Writer())
id, err := db.SaveNextVersion()
require.NoError(t, err)
pdb := pfx.NewPrefixReadWriter(db.ReadWriter(), prefix)
pdb.Set([]byte("1"), []byte("newvalue1"))
pdb.Delete([]byte("2"))
pdb.Set([]byte("4"), []byte("newvalue4"))
pdb.Discard()
dbview, err := db.ReaderAt(id)
require.NotNil(t, dbview)
require.NoError(t, err)
view := pfx.NewPrefixReader(dbview, prefix)
require.NotNil(t, view)
defer view.Discard()
dbtest.AssertValue(t, view, []byte("1"), []byte("value1"))
dbtest.AssertValue(t, view, []byte("2"), []byte("value2"))
dbtest.AssertValue(t, view, []byte("4"), nil)
}