github.com/Finschia/finschia-sdk@v0.48.1/baseapp/baseapp_test.go (about) 1 package baseapp 2 3 import ( 4 "encoding/json" 5 "os" 6 "testing" 7 8 "github.com/golang/mock/gomock" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 abci "github.com/tendermint/tendermint/abci/types" 12 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 13 dbm "github.com/tendermint/tm-db" 14 15 ocabci "github.com/Finschia/ostracon/abci/types" 16 "github.com/Finschia/ostracon/libs/log" 17 18 "github.com/Finschia/finschia-sdk/codec" 19 "github.com/Finschia/finschia-sdk/codec/legacy" 20 "github.com/Finschia/finschia-sdk/server/config" 21 "github.com/Finschia/finschia-sdk/snapshots" 22 store "github.com/Finschia/finschia-sdk/store/types" 23 sdk "github.com/Finschia/finschia-sdk/types" 24 "github.com/Finschia/finschia-sdk/x/auth/legacy/legacytx" 25 ) 26 27 var ( 28 capKey1 = sdk.NewKVStoreKey("key1") 29 capKey2 = sdk.NewKVStoreKey("key2") 30 ) 31 32 func defaultLogger() log.Logger { 33 return log.NewOCLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app") 34 } 35 36 func newBaseApp(name string, options ...func(*BaseApp)) *BaseApp { 37 logger := defaultLogger() 38 db := dbm.NewMemDB() 39 codec := codec.NewLegacyAmino() 40 registerTestCodec(codec) 41 return NewBaseApp(name, logger, db, testTxDecoder(codec), options...) 42 } 43 44 func registerTestCodec(cdc *codec.LegacyAmino) { 45 // register Tx, Msg 46 sdk.RegisterLegacyAminoCodec(cdc) 47 48 // register test types 49 cdc.RegisterConcrete(&txTest{}, "cosmos-sdk/baseapp/txTest", nil) 50 legacy.RegisterAminoMsg(cdc, &msgCounter{}, "cosmos-sdk/baseapp/msgCounter") 51 legacy.RegisterAminoMsg(cdc, &msgCounter2{}, "cosmos-sdk/baseapp/msgCounter2") 52 legacy.RegisterAminoMsg(cdc, &msgKeyValue{}, "cosmos-sdk/baseapp/msgKeyValue") 53 legacy.RegisterAminoMsg(cdc, &msgNoRoute{}, "cosmos-sdk/baseapp/msgNoRoute") 54 } 55 56 // aminoTxEncoder creates a amino TxEncoder for testing purposes. 57 func aminoTxEncoder() sdk.TxEncoder { 58 cdc := codec.NewLegacyAmino() 59 registerTestCodec(cdc) 60 61 return legacytx.StdTxConfig{Cdc: cdc}.TxEncoder() 62 } 63 64 // simple one store baseapp 65 func setupBaseApp(t *testing.T, options ...func(*BaseApp)) *BaseApp { 66 app := newBaseApp(t.Name(), options...) 67 require.Equal(t, t.Name(), app.Name()) 68 69 app.MountStores(capKey1, capKey2) 70 app.SetParamStore(¶mStore{db: dbm.NewMemDB()}) 71 72 // stores are mounted 73 err := app.LoadLatestVersion() 74 require.Nil(t, err) 75 return app 76 } 77 78 func TestLoadVersionPruning(t *testing.T) { 79 logger := log.NewNopLogger() 80 pruningOptions := store.PruningOptions{ 81 KeepRecent: 2, 82 KeepEvery: 3, 83 Interval: 1, 84 } 85 pruningOpt := SetPruning(pruningOptions) 86 db := dbm.NewMemDB() 87 name := t.Name() 88 app := NewBaseApp(name, logger, db, nil, pruningOpt) 89 90 // make a cap key and mount the store 91 capKey := sdk.NewKVStoreKey("key1") 92 app.MountStores(capKey) 93 94 err := app.LoadLatestVersion() // needed to make stores non-nil 95 require.Nil(t, err) 96 97 emptyCommitID := sdk.CommitID{} 98 99 // fresh store has zero/empty last commit 100 lastHeight := app.LastBlockHeight() 101 lastID := app.LastCommitID() 102 require.Equal(t, int64(0), lastHeight) 103 require.Equal(t, emptyCommitID, lastID) 104 105 var lastCommitID sdk.CommitID 106 107 // Commit seven blocks, of which 7 (latest) is kept in addition to 6, 5 108 // (keep recent) and 3 (keep every). 109 for i := int64(1); i <= 7; i++ { 110 app.BeginBlock(ocabci.RequestBeginBlock{Header: tmproto.Header{Height: i}}) 111 res := app.Commit() 112 lastCommitID = sdk.CommitID{Version: i, Hash: res.Data} 113 } 114 115 for _, v := range []int64{1, 2, 4} { 116 _, err = app.cms.CacheMultiStoreWithVersion(v) 117 require.NoError(t, err) 118 } 119 120 for _, v := range []int64{3, 5, 6, 7} { 121 _, err = app.cms.CacheMultiStoreWithVersion(v) 122 require.NoError(t, err) 123 } 124 125 // reload with LoadLatestVersion, check it loads last version 126 app = NewBaseApp(name, logger, db, nil, pruningOpt) 127 app.MountStores(capKey) 128 129 err = app.LoadLatestVersion() 130 require.Nil(t, err) 131 testLoadVersionHelper(t, app, int64(7), lastCommitID) 132 } 133 134 func testLoadVersionHelper(t *testing.T, app *BaseApp, expectedHeight int64, expectedID sdk.CommitID) { 135 lastHeight := app.LastBlockHeight() 136 lastID := app.LastCommitID() 137 require.Equal(t, expectedHeight, lastHeight) 138 require.Equal(t, expectedID, lastID) 139 } 140 141 func TestSetMinGasPrices(t *testing.T) { 142 minGasPrices := sdk.DecCoins{sdk.NewInt64DecCoin("stake", 5000)} 143 app := newBaseApp(t.Name(), SetMinGasPrices(minGasPrices.String())) 144 require.Equal(t, minGasPrices, app.minGasPrices) 145 } 146 147 func TestGetMaximumBlockGas(t *testing.T) { 148 app := setupBaseApp(t) 149 app.InitChain(abci.RequestInitChain{}) 150 ctx := app.NewContext(true, tmproto.Header{}) 151 152 app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 0}}) 153 require.Equal(t, uint64(0), app.getMaximumBlockGas(ctx)) 154 155 app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -1}}) 156 require.Equal(t, uint64(0), app.getMaximumBlockGas(ctx)) 157 158 app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: 5000000}}) 159 require.Equal(t, uint64(5000000), app.getMaximumBlockGas(ctx)) 160 161 app.StoreConsensusParams(ctx, &abci.ConsensusParams{Block: &abci.BlockParams{MaxGas: -5000000}}) 162 require.Panics(t, func() { app.getMaximumBlockGas(ctx) }) 163 } 164 165 func TestListSnapshots(t *testing.T) { 166 type setupConfig struct { 167 blocks uint64 168 blockTxs int 169 snapshotInterval uint64 170 snapshotKeepEvery uint32 171 } 172 173 app, _ := setupBaseAppWithSnapshots(t, 2, 5) 174 175 expected := abci.ResponseListSnapshots{Snapshots: []*abci.Snapshot{ 176 {Height: 2, Format: 1, Chunks: 2}, 177 }} 178 179 resp := app.ListSnapshots(abci.RequestListSnapshots{}) 180 queryResponse := app.Query(abci.RequestQuery{ 181 Path: "/app/snapshots", 182 }) 183 184 queryListSnapshotsResp := abci.ResponseListSnapshots{} 185 err := json.Unmarshal(queryResponse.Value, &queryListSnapshotsResp) 186 require.NoError(t, err) 187 188 for i, s := range resp.Snapshots { 189 querySnapshot := queryListSnapshotsResp.Snapshots[i] 190 // we check that the query snapshot and function snapshot are equal 191 // Then we check that the hash and metadata are not empty. We atm 192 // do not have a good way to generate the expected value for these. 193 assert.Equal(t, *s, *querySnapshot) 194 assert.NotEmpty(t, s.Hash) 195 assert.NotEmpty(t, s.Metadata) 196 // Set hash and metadata to nil, so we can check the other snapshot 197 // fields against expected 198 s.Hash = nil 199 s.Metadata = nil 200 } 201 assert.Equal(t, expected, resp) 202 } 203 204 func TestSnapshotManager(t *testing.T) { 205 app := newBaseApp(t.Name()) 206 require.Nil(t, app.SnapshotManager()) 207 208 tempDir := t.TempDir() 209 snapshotDB, err := sdk.NewLevelDB("metadata", tempDir) 210 if err != nil { 211 require.NoError(t, err) 212 } 213 snapshotStore, err := snapshots.NewStore(snapshotDB, tempDir) 214 if err != nil { 215 require.NoError(t, err) 216 } 217 app.SetSnapshotStore(snapshotStore) 218 require.NotNil(t, app.SnapshotManager()) 219 } 220 221 func TestSetChanCheckTxSize(t *testing.T) { 222 logger := defaultLogger() 223 db := dbm.NewMemDB() 224 225 var size = uint(100) 226 227 app := NewBaseApp(t.Name(), logger, db, nil, SetChanCheckTxSize(size)) 228 require.Equal(t, int(size), cap(app.chCheckTx)) 229 230 app = NewBaseApp(t.Name(), logger, db, nil) 231 require.Equal(t, config.DefaultChanCheckTxSize, cap(app.chCheckTx)) 232 } 233 234 func TestCreateEvents(t *testing.T) { 235 testCases := map[string]struct { 236 eventsIn sdk.Events 237 messageName string 238 eventsOut sdk.Events 239 }{ 240 "cosmos": { 241 messageName: "cosmos.foo.v1beta1.MsgFoo", 242 eventsOut: sdk.Events{{Type: "message", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e}, Value: []uint8{0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x66, 0x6f, 0x6f, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x46, 0x6f, 0x6f}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x33, 0x6a, 0x6b, 0x7a, 0x65, 0x72, 0x7a, 0x76, 0x34, 0x6a, 0x6b, 0x76, 0x6b, 0x75, 0x64, 0x32, 0x63, 0x6d}, Index: false}, {Key: []uint8{0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65}, Value: []uint8{0x66, 0x6f, 0x6f}, Index: false}}}}, 243 }, 244 "ibc without module attribute": { 245 messageName: "ibc.foo.bar.v1.MsgBar", 246 eventsOut: sdk.Events{{Type: "message", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e}, Value: []uint8{0x2f, 0x69, 0x62, 0x63, 0x2e, 0x66, 0x6f, 0x6f, 0x2e, 0x62, 0x61, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x61, 0x72}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x33, 0x6a, 0x6b, 0x7a, 0x65, 0x72, 0x7a, 0x76, 0x34, 0x6a, 0x6b, 0x76, 0x6b, 0x75, 0x64, 0x32, 0x63, 0x6d}, Index: false}}}}, 247 }, 248 "ibc with module attribute": { 249 eventsIn: sdk.Events{{Type: "message", Attributes: []abci.EventAttribute{{Key: []uint8{0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65}, Value: []uint8{0x66, 0x6f, 0x6f, 0x53, 0x62, 0x61, 0x72}, Index: false}}}}, 250 messageName: "ibc.foo.bar.v1.MsgBar", 251 eventsOut: sdk.Events{{Type: "message", Attributes: []abci.EventAttribute{{Key: []uint8{0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e}, Value: []uint8{0x2f, 0x69, 0x62, 0x63, 0x2e, 0x66, 0x6f, 0x6f, 0x2e, 0x62, 0x61, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x61, 0x72}, Index: false}, {Key: []uint8{0x73, 0x65, 0x6e, 0x64, 0x65, 0x72}, Value: []uint8{0x6c, 0x69, 0x6e, 0x6b, 0x31, 0x76, 0x33, 0x6a, 0x6b, 0x7a, 0x65, 0x72, 0x7a, 0x76, 0x34, 0x6a, 0x6b, 0x76, 0x6b, 0x75, 0x64, 0x32, 0x63, 0x6d}, Index: false}}}, {Type: "message", Attributes: []abci.EventAttribute{{Key: []uint8{0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65}, Value: []uint8{0x66, 0x6f, 0x6f, 0x53, 0x62, 0x61, 0x72}, Index: false}}}}, 252 }, 253 } 254 255 for name, tc := range testCases { 256 t.Run(name, func(t *testing.T) { 257 ctrl := gomock.NewController(t) 258 msg := NewMockXXXMessage(ctrl) 259 260 signer := sdk.AccAddress([]byte("deadbeef")) 261 msg. 262 EXPECT(). 263 GetSigners(). 264 Return([]sdk.AccAddress{signer}). 265 AnyTimes() 266 msg. 267 EXPECT(). 268 XXX_MessageName(). 269 Return(tc.messageName). 270 AnyTimes() 271 272 eventsOut := createEvents(tc.eventsIn, msg) 273 require.Equal(t, tc.eventsOut, eventsOut) 274 }) 275 } 276 }