2020-02-27 22:26:04 -08:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
2020-08-14 10:58:53 -07:00
|
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
2020-02-27 22:26:04 -08:00
|
|
|
dbm "github.com/tendermint/tm-db"
|
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
|
|
"github.com/cosmos/cosmos-sdk/store/rootmulti"
|
|
|
|
store "github.com/cosmos/cosmos-sdk/store/types"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
func useUpgradeLoader(height int64, upgrades *store.StoreUpgrades) func(*baseapp.BaseApp) {
|
|
|
|
return func(app *baseapp.BaseApp) {
|
|
|
|
app.SetStoreLoader(UpgradeStoreLoader(height, upgrades))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func defaultLogger() log.Logger {
|
|
|
|
return log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
|
|
|
}
|
|
|
|
|
|
|
|
func initStore(t *testing.T, db dbm.DB, storeKey string, k, v []byte) {
|
|
|
|
rs := rootmulti.NewStore(db)
|
|
|
|
rs.SetPruning(store.PruneNothing)
|
|
|
|
key := sdk.NewKVStoreKey(storeKey)
|
|
|
|
rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)
|
|
|
|
err := rs.LoadLatestVersion()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Equal(t, int64(0), rs.LastCommitID().Version)
|
|
|
|
|
|
|
|
// write some data in substore
|
|
|
|
kv, _ := rs.GetStore(key).(store.KVStore)
|
|
|
|
require.NotNil(t, kv)
|
|
|
|
kv.Set(k, v)
|
|
|
|
commitID := rs.Commit()
|
|
|
|
require.Equal(t, int64(1), commitID.Version)
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkStore(t *testing.T, db dbm.DB, ver int64, storeKey string, k, v []byte) {
|
|
|
|
rs := rootmulti.NewStore(db)
|
|
|
|
rs.SetPruning(store.PruneNothing)
|
|
|
|
key := sdk.NewKVStoreKey(storeKey)
|
|
|
|
rs.MountStoreWithDB(key, store.StoreTypeIAVL, nil)
|
|
|
|
err := rs.LoadLatestVersion()
|
|
|
|
require.Nil(t, err)
|
|
|
|
require.Equal(t, ver, rs.LastCommitID().Version)
|
|
|
|
|
|
|
|
// query data in substore
|
|
|
|
kv, _ := rs.GetStore(key).(store.KVStore)
|
|
|
|
|
|
|
|
require.NotNil(t, kv)
|
|
|
|
require.Equal(t, v, kv.Get(k))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that we can make commits and then reload old versions.
|
|
|
|
// Test that LoadLatestVersion actually does.
|
|
|
|
func TestSetLoader(t *testing.T) {
|
|
|
|
// set a temporary home dir
|
2020-09-18 04:08:24 -07:00
|
|
|
homeDir := t.TempDir()
|
2020-02-27 22:26:04 -08:00
|
|
|
upgradeInfoFilePath := filepath.Join(homeDir, "upgrade-info.json")
|
|
|
|
upgradeInfo := &store.UpgradeInfo{
|
|
|
|
Name: "test", Height: 0,
|
|
|
|
}
|
2020-09-18 04:08:24 -07:00
|
|
|
|
2020-02-27 22:26:04 -08:00
|
|
|
data, err := json.Marshal(upgradeInfo)
|
|
|
|
require.NoError(t, err)
|
2020-09-18 04:08:24 -07:00
|
|
|
|
2020-02-27 22:26:04 -08:00
|
|
|
err = ioutil.WriteFile(upgradeInfoFilePath, data, 0644)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// make sure it exists before running everything
|
|
|
|
_, err = os.Stat(upgradeInfoFilePath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
setLoader func(*baseapp.BaseApp)
|
|
|
|
origStoreKey string
|
|
|
|
loadStoreKey string
|
|
|
|
}{
|
|
|
|
"don't set loader": {
|
|
|
|
origStoreKey: "foo",
|
|
|
|
loadStoreKey: "foo",
|
|
|
|
},
|
|
|
|
"rename with inline opts": {
|
|
|
|
setLoader: useUpgradeLoader(0, &store.StoreUpgrades{
|
|
|
|
Renamed: []store.StoreRename{{
|
|
|
|
OldKey: "foo",
|
|
|
|
NewKey: "bar",
|
|
|
|
}},
|
|
|
|
}),
|
|
|
|
origStoreKey: "foo",
|
|
|
|
loadStoreKey: "bar",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
k := []byte("key")
|
|
|
|
v := []byte("value")
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
|
|
|
tc := tc
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// prepare a db with some data
|
|
|
|
db := dbm.NewMemDB()
|
|
|
|
|
|
|
|
initStore(t, db, tc.origStoreKey, k, v)
|
|
|
|
|
|
|
|
// load the app with the existing db
|
|
|
|
opts := []func(*baseapp.BaseApp){baseapp.SetPruning(store.PruneNothing)}
|
|
|
|
if tc.setLoader != nil {
|
|
|
|
opts = append(opts, tc.setLoader)
|
|
|
|
}
|
|
|
|
|
|
|
|
app := baseapp.NewBaseApp(t.Name(), defaultLogger(), db, nil, opts...)
|
2020-04-16 08:10:39 -07:00
|
|
|
capKey := sdk.NewKVStoreKey("main")
|
2020-02-27 22:26:04 -08:00
|
|
|
app.MountStores(capKey)
|
|
|
|
app.MountStores(sdk.NewKVStoreKey(tc.loadStoreKey))
|
2020-04-16 08:10:39 -07:00
|
|
|
err := app.LoadLatestVersion()
|
2020-02-27 22:26:04 -08:00
|
|
|
require.Nil(t, err)
|
|
|
|
|
|
|
|
// "execute" one block
|
2020-08-14 10:58:53 -07:00
|
|
|
app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: 2}})
|
2020-02-27 22:26:04 -08:00
|
|
|
res := app.Commit()
|
|
|
|
require.NotNil(t, res.Data)
|
|
|
|
|
|
|
|
// check db is properly updated
|
|
|
|
checkStore(t, db, 2, tc.loadStoreKey, k, v)
|
|
|
|
checkStore(t, db, 2, tc.loadStoreKey, []byte("foo"), nil)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|