Skip to content

Commit

Permalink
chore(store/v2): Increase storev2 tests coverage (#21094)
Browse files Browse the repository at this point in the history
  • Loading branch information
sontrinh16 authored Aug 9, 2024
1 parent a9a687c commit 7a59ce9
Show file tree
Hide file tree
Showing 8 changed files with 493 additions and 6 deletions.
77 changes: 77 additions & 0 deletions store/v2/commitment/store_test_suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,83 @@ func (s *CommitStoreTestSuite) TestStore_Pruning() {
}
}

func (s *CommitStoreTestSuite) TestStore_GetProof() {
storeKeys := []string{storeKey1, storeKey2}
commitStore, err := s.NewStore(dbm.NewMemDB(), storeKeys, nil, coretesting.NewNopLogger())
s.Require().NoError(err)

toVersion := uint64(10)
keyCount := 5

// commit some changes
for version := uint64(1); version <= toVersion; version++ {
cs := corestore.NewChangeset()
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false)
}
}
err := commitStore.WriteChangeset(cs)
s.Require().NoError(err)
_, err = commitStore.Commit(version)
s.Require().NoError(err)
}

// get proof
for version := uint64(1); version <= toVersion; version++ {
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
_, err := commitStore.GetProof([]byte(storeKey), version, []byte(fmt.Sprintf("key-%d-%d", version, i)))
s.Require().NoError(err)
}
}
}

// prune version 1
s.Require().NoError(commitStore.Prune(1))

// check if proof for version 1 is pruned
_, err = commitStore.GetProof([]byte(storeKeys[0]), 1, []byte(fmt.Sprintf("key-%d-%d", 1, 0)))
s.Require().Error(err)
// check the commit info
commit, _ := commitStore.GetCommitInfo(1)
s.Require().Nil(commit)
}

func (s *CommitStoreTestSuite) TestStore_Get() {
storeKeys := []string{storeKey1, storeKey2}
commitStore, err := s.NewStore(dbm.NewMemDB(), storeKeys, nil, coretesting.NewNopLogger())
s.Require().NoError(err)

toVersion := uint64(10)
keyCount := 5

// commit some changes
for version := uint64(1); version <= toVersion; version++ {
cs := corestore.NewChangeset()
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false)
}
}
err := commitStore.WriteChangeset(cs)
s.Require().NoError(err)
_, err = commitStore.Commit(version)
s.Require().NoError(err)
}

// get proof
for version := uint64(1); version <= toVersion; version++ {
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
val, err := commitStore.Get([]byte(storeKey), version, []byte(fmt.Sprintf("key-%d-%d", version, i)))
s.Require().NoError(err)
s.Require().Equal([]byte(fmt.Sprintf("value-%d-%d", version, i)), val)
}
}
}
}

func (s *CommitStoreTestSuite) TestStore_Upgrades() {
storeKeys := []string{storeKey1, storeKey2, storeKey3}
commitDB := dbm.NewMemDB()
Expand Down
101 changes: 101 additions & 0 deletions store/v2/migration/manager_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package migration

import (
"encoding/binary"
"fmt"
"testing"

Expand Down Expand Up @@ -117,3 +118,103 @@ func TestMigrateState(t *testing.T) {
})
}
}

func TestStartMigrateState(t *testing.T) {
for _, noCommitStore := range []bool{false, true} {
t.Run(fmt.Sprintf("Migrate noCommitStore=%v", noCommitStore), func(t *testing.T) {
m, orgCommitStore := setupMigrationManager(t, noCommitStore)

chDone := make(chan struct{})
chChangeset := make(chan *VersionedChangeset, 1)

// apply changeset
toVersion := uint64(10)
keyCount := 5
changesets := []corestore.Changeset{}

for version := uint64(1); version <= toVersion; version++ {
cs := corestore.NewChangeset()
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false)
}
}
changesets = append(changesets, *cs)
require.NoError(t, orgCommitStore.WriteChangeset(cs))
_, err := orgCommitStore.Commit(version)
require.NoError(t, err)
}

// feed changesets to channel
go func() {
for version := uint64(1); version <= toVersion; version++ {
chChangeset <- &VersionedChangeset{
Version: version,
Changeset: &changesets[version-1],
}
}
}()

// check if migrate process complete
go func() {
for {
migrateVersion := m.GetMigratedVersion()
if migrateVersion == toVersion-1 {
break
}
}

chDone <- struct{}{}
}()

err := m.Start(toVersion-1, chChangeset, chDone)
require.NoError(t, err)

// expecting error for conflicting process, since Migrate trigger snapshotter create migration,
// which start a snapshot process already.
_, err = m.snapshotsManager.Create(toVersion - 1)
require.Error(t, err)

if m.stateCommitment != nil {
// check the migrated state
for version := uint64(1); version < toVersion; version++ {
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
val, err := m.stateCommitment.Get([]byte(storeKey), toVersion-1, []byte(fmt.Sprintf("key-%d-%d", version, i)))
require.NoError(t, err)
require.Equal(t, []byte(fmt.Sprintf("value-%d-%d", version, i)), val)
}
}
}
// check the latest state
val, err := m.stateCommitment.Get([]byte("store1"), toVersion-1, []byte("key-100-1"))
require.NoError(t, err)
require.Nil(t, val)
val, err = m.stateCommitment.Get([]byte("store2"), toVersion-1, []byte("key-100-0"))
require.NoError(t, err)
require.Nil(t, val)
}

// check the storage
for version := uint64(1); version < toVersion; version++ {
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
val, err := m.stateStorage.Get([]byte(storeKey), toVersion-1, []byte(fmt.Sprintf("key-%d-%d", version, i)))
require.NoError(t, err)
require.Equal(t, []byte(fmt.Sprintf("value-%d-%d", version, i)), val)
}
}
}

// check if migration db write change set to storage
for version := uint64(1); version < toVersion; version++ {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, version)
csKey := []byte(fmt.Sprintf(migrateChangesetKeyFmt, buf))
csVal, err := m.db.Get(csKey)
require.NoError(t, err)
require.NotEmpty(t, csVal)
}
})
}
}
104 changes: 104 additions & 0 deletions store/v2/pruning/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,107 @@ func TestPruningOption(t *testing.T) {
})
}
}

func (s *PruningManagerTestSuite) TestSignalCommit() {
// commit version 1
cs := corestore.NewChangeset()
for _, storeKey := range storeKeys {
cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", 1, 0)), []byte(fmt.Sprintf("value-%d-%d", 1, 0)), false)
}

s.Require().NoError(s.sc.WriteChangeset(cs))
_, err := s.sc.Commit(1)
s.Require().NoError(err)

s.Require().NoError(s.ss.ApplyChangeset(1, cs))

// commit version 2
for _, storeKey := range storeKeys {
cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", 2, 0)), []byte(fmt.Sprintf("value-%d-%d", 2, 0)), false)
}

// signaling commit has started
s.Require().NoError(s.manager.SignalCommit(true, 2))

s.Require().NoError(s.sc.WriteChangeset(cs))
_, err = s.sc.Commit(2)
s.Require().NoError(err)

s.Require().NoError(s.ss.ApplyChangeset(2, cs))

// try prune before signaling commit has finished
s.Require().NoError(s.manager.Prune(2))

// proof is removed no matter SignalCommit has not yet inform that commit process has finish
// since commitInfo is remove async with tree data
checkSCPrune := func() bool {
count := 0
for _, storeKey := range storeKeys {
_, err := s.sc.GetProof([]byte(storeKey), 1, []byte(fmt.Sprintf("key-%d-%d", 1, 0)))
if err != nil {
count++
}
}

return count == len(storeKeys)
}
s.Require().Eventually(checkSCPrune, 10*time.Second, 1*time.Second)

// data from state commitment should not be pruned since we haven't signal the commit process has finished
val, err := s.sc.Get([]byte(storeKeys[0]), 1, []byte(fmt.Sprintf("key-%d-%d", 1, 0)))
s.Require().NoError(err)
s.Require().Equal(val, []byte(fmt.Sprintf("value-%d-%d", 1, 0)))

// signaling commit has finished, version 1 should be pruned
s.Require().NoError(s.manager.SignalCommit(false, 2))

checkSCPrune = func() bool {
count := 0
for _, storeKey := range storeKeys {
_, err := s.sc.GetProof([]byte(storeKey), 1, []byte(fmt.Sprintf("key-%d-%d", 1, 0)))
if err != nil {
count++
}
}

return count == len(storeKeys)
}
s.Require().Eventually(checkSCPrune, 10*time.Second, 1*time.Second)

// try with signal commit start and finish accordingly
// commit changesets with pruning
toVersion := uint64(100)
keyCount := 10
for version := uint64(3); version <= toVersion; version++ {
cs := corestore.NewChangeset()
for _, storeKey := range storeKeys {
for i := 0; i < keyCount; i++ {
cs.Add([]byte(storeKey), []byte(fmt.Sprintf("key-%d-%d", version, i)), []byte(fmt.Sprintf("value-%d-%d", version, i)), false)
}
}
s.Require().NoError(s.manager.SignalCommit(true, version))

s.Require().NoError(s.sc.WriteChangeset(cs))
_, err := s.sc.Commit(version)
s.Require().NoError(err)

s.Require().NoError(s.ss.ApplyChangeset(version, cs))

s.Require().NoError(s.manager.SignalCommit(false, version))

}

// wait for the pruning to finish in the commitment store
checkSCPrune = func() bool {
count := 0
for _, storeKey := range storeKeys {
_, err := s.sc.GetProof([]byte(storeKey), toVersion-1, []byte(fmt.Sprintf("key-%d-%d", toVersion-1, 0)))
if err != nil {
count++
}
}

return count == len(storeKeys)
}
s.Require().Eventually(checkSCPrune, 10*time.Second, 1*time.Second)
}
2 changes: 1 addition & 1 deletion store/v2/root/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ func (s *RootStoreTestSuite) TestMultiStore_PruningRestart() {
return false
}
// wait for async pruning process to finish
s.Require().Eventually(checkErr, 5*time.Second, 100*time.Millisecond, "expected error when loading height: %d", v)
s.Require().Eventually(checkErr, 10*time.Second, 1*time.Second, "expected error when loading height: %d", v)
}
}

Expand Down
26 changes: 25 additions & 1 deletion store/v2/snapshots/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (m *mockCommitSnapshotter) Restore(

var item snapshotstypes.SnapshotItem
m.items = [][]byte{}
keyCount := 0
for {
item.Reset()
err := protoReader.ReadMsg(&item)
Expand All @@ -133,6 +134,19 @@ func (m *mockCommitSnapshotter) Restore(
break
}
m.items = append(m.items, payload.Payload)
// mock feeding chStorage to check if the loop closed properly
//
// ref: https://github.com/cosmos/cosmos-sdk/pull/21106
chStorage <- &corestore.StateChanges{
Actor: []byte("actor"),
StateChanges: []corestore.KVPair{
{
Key: []byte(fmt.Sprintf("key-%d", keyCount)),
Value: payload.Payload,
},
},
}
keyCount++
}

return item, nil
Expand All @@ -155,9 +169,19 @@ func (m *mockCommitSnapshotter) SupportedFormats() []uint32 {
return []uint32{snapshotstypes.CurrentFormat}
}

type mockStorageSnapshotter struct{}
type mockStorageSnapshotter struct {
items map[string][]byte
}

func (m *mockStorageSnapshotter) Restore(version uint64, chStorage <-chan *corestore.StateChanges) error {
// mock consuming chStorage to check if the loop closed properly
//
// ref: https://github.com/cosmos/cosmos-sdk/pull/21106
for change := range chStorage {
for _, kv := range change.StateChanges {
m.items[string(kv.Key)] = kv.Value
}
}
return nil
}

Expand Down
Loading

0 comments on commit 7a59ce9

Please sign in to comment.