github.com/Finschia/finschia-sdk@v0.48.1/simapp/app_test.go (about) 1 package simapp 2 3 import ( 4 "encoding/json" 5 "os" 6 "testing" 7 8 "github.com/golang/mock/gomock" 9 "github.com/stretchr/testify/require" 10 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 "github.com/Finschia/ostracon/libs/log" 16 17 "github.com/Finschia/finschia-sdk/baseapp" 18 "github.com/Finschia/finschia-sdk/tests/mocks" 19 sdk "github.com/Finschia/finschia-sdk/types" 20 "github.com/Finschia/finschia-sdk/types/module" 21 "github.com/Finschia/finschia-sdk/x/auth" 22 "github.com/Finschia/finschia-sdk/x/auth/vesting" 23 authz_m "github.com/Finschia/finschia-sdk/x/authz/module" 24 "github.com/Finschia/finschia-sdk/x/bank" 25 banktypes "github.com/Finschia/finschia-sdk/x/bank/types" 26 "github.com/Finschia/finschia-sdk/x/capability" 27 "github.com/Finschia/finschia-sdk/x/crisis" 28 "github.com/Finschia/finschia-sdk/x/distribution" 29 "github.com/Finschia/finschia-sdk/x/evidence" 30 feegrantmodule "github.com/Finschia/finschia-sdk/x/feegrant/module" 31 foundationmodule "github.com/Finschia/finschia-sdk/x/foundation/module" 32 "github.com/Finschia/finschia-sdk/x/genutil" 33 "github.com/Finschia/finschia-sdk/x/gov" 34 "github.com/Finschia/finschia-sdk/x/mint" 35 "github.com/Finschia/finschia-sdk/x/params" 36 "github.com/Finschia/finschia-sdk/x/slashing" 37 "github.com/Finschia/finschia-sdk/x/staking" 38 tokenmodule "github.com/Finschia/finschia-sdk/x/token/module" 39 "github.com/Finschia/finschia-sdk/x/upgrade" 40 ) 41 42 func TestSimAppExportAndBlockedAddrs(t *testing.T) { 43 encCfg := MakeTestEncodingConfig() 44 db := dbm.NewMemDB() 45 app := NewSimApp(log.NewOCLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) 46 47 for acc := range maccPerms { 48 require.Equal(t, !allowedReceivingModAcc[acc], app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)), 49 "ensure that blocked addresses are properly set in bank keeper") 50 } 51 52 genesisState := NewDefaultGenesisState(encCfg.Marshaler) 53 stateBytes, err := json.MarshalIndent(genesisState, "", " ") 54 require.NoError(t, err) 55 56 // Initialize the chain 57 app.InitChain( 58 abci.RequestInitChain{ 59 Validators: []abci.ValidatorUpdate{}, 60 AppStateBytes: stateBytes, 61 }, 62 ) 63 app.Commit() 64 65 // Making a new app object with the db, so that initchain hasn't been called 66 app2 := NewSimApp(log.NewOCLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) 67 _, err = app2.ExportAppStateAndValidators(false, []string{}) 68 require.NoError(t, err, "ExportAppStateAndValidators should not have an error") 69 } 70 71 func TestGetMaccPerms(t *testing.T) { 72 dup := GetMaccPerms() 73 require.Equal(t, maccPerms, dup, "duplicated module account permissions differed from actual module account permissions") 74 } 75 76 func TestRunMigrations(t *testing.T) { 77 db := dbm.NewMemDB() 78 encCfg := MakeTestEncodingConfig() 79 logger := log.NewOCLogger(log.NewSyncWriter(os.Stdout)) 80 app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) 81 82 // Create a new baseapp and configurator for the purpose of this test. 83 bApp := baseapp.NewBaseApp(appName, logger, db, encCfg.TxConfig.TxDecoder()) 84 bApp.SetCommitMultiStoreTracer(nil) 85 bApp.SetInterfaceRegistry(encCfg.InterfaceRegistry) 86 app.BaseApp = bApp 87 app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) 88 89 // We register all modules on the Configurator, except x/bank. x/bank will 90 // serve as the test subject on which we run the migration tests. 91 // 92 // The loop below is the same as calling `RegisterServices` on 93 // ModuleManager, except that we skip x/bank. 94 for _, module := range app.mm.Modules { 95 if module.Name() == banktypes.ModuleName { 96 continue 97 } 98 99 module.RegisterServices(app.configurator) 100 } 101 102 // Initialize the chain 103 app.InitChain(abci.RequestInitChain{}) 104 app.Commit() 105 106 testCases := []struct { 107 name string 108 moduleName string 109 forVersion uint64 110 expRegErr bool // errors while registering migration 111 expRegErrMsg string 112 expRunErr bool // errors while running migration 113 expRunErrMsg string 114 expCalled int 115 }{ 116 { 117 "cannot register migration for version 0", 118 "bank", 0, 119 true, "module migration versions should start at 1: invalid version", false, "", 0, 120 }, 121 // TODO(dudong2): bank module has no migration func, so comment out tests 122 // { 123 // "throws error on RunMigrations if no migration registered for bank", 124 // "", 1, 125 // false, "", true, "no migrations found for module bank: not found", 0, 126 // }, 127 // { 128 // "can register and run migration handler for x/bank", 129 // "bank", 1, 130 // false, "", false, "", 1, 131 // }, 132 // { 133 // "cannot register migration handler for same module & forVersion", 134 // "bank", 1, 135 // true, "another migration for module bank and version 1 already exists: internal logic error", false, "", 0, 136 // }, 137 } 138 139 for _, tc := range testCases { 140 t.Run(tc.name, func(t *testing.T) { 141 var err error 142 143 // Since it's very hard to test actual in-place store migrations in 144 // tests (due to the difficulty of maintaining multiple versions of a 145 // module), we're just testing here that the migration logic is 146 // called. 147 called := 0 148 149 if tc.moduleName != "" { 150 // Register migration for module from version `forVersion` to `forVersion+1`. 151 err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context) error { 152 called++ 153 154 return nil 155 }) 156 157 if tc.expRegErr { 158 require.EqualError(t, err, tc.expRegErrMsg) 159 160 return 161 } 162 } 163 require.NoError(t, err) 164 165 // Run migrations only for bank. That's why we put the initial 166 // version for bank as 1, and for all other modules, we put as 167 // their latest ConsensusVersion. 168 _, err = app.mm.RunMigrations( 169 app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), app.configurator, 170 module.VersionMap{ 171 "bank": 1, 172 "auth": auth.AppModule{}.ConsensusVersion(), 173 "authz": authz_m.AppModule{}.ConsensusVersion(), 174 "staking": staking.AppModule{}.ConsensusVersion(), 175 "mint": mint.AppModule{}.ConsensusVersion(), 176 "distribution": distribution.AppModule{}.ConsensusVersion(), 177 "slashing": slashing.AppModule{}.ConsensusVersion(), 178 "gov": gov.AppModule{}.ConsensusVersion(), 179 "params": params.AppModule{}.ConsensusVersion(), 180 "upgrade": upgrade.AppModule{}.ConsensusVersion(), 181 "vesting": vesting.AppModule{}.ConsensusVersion(), 182 "feegrant": feegrantmodule.AppModule{}.ConsensusVersion(), 183 "evidence": evidence.AppModule{}.ConsensusVersion(), 184 "crisis": crisis.AppModule{}.ConsensusVersion(), 185 "genutil": genutil.AppModule{}.ConsensusVersion(), 186 "capability": capability.AppModule{}.ConsensusVersion(), 187 "foundation": foundationmodule.AppModule{}.ConsensusVersion(), 188 "token": tokenmodule.AppModule{}.ConsensusVersion(), 189 }, 190 ) 191 if tc.expRunErr { 192 require.EqualError(t, err, tc.expRunErrMsg) 193 } else { 194 require.NoError(t, err) 195 // Make sure bank's migration is called. 196 require.Equal(t, tc.expCalled, called) 197 } 198 }) 199 } 200 } 201 202 func TestInitGenesisOnMigration(t *testing.T) { 203 db := dbm.NewMemDB() 204 encCfg := MakeTestEncodingConfig() 205 logger := log.NewOCLogger(log.NewSyncWriter(os.Stdout)) 206 app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) 207 ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) 208 209 // Create a mock module. This module will serve as the new module we're 210 // adding during a migration. 211 mockCtrl := gomock.NewController(t) 212 t.Cleanup(mockCtrl.Finish) 213 mockModule := mocks.NewMockAppModule(mockCtrl) 214 mockDefaultGenesis := json.RawMessage(`{"key": "value"}`) 215 mockModule.EXPECT().DefaultGenesis(gomock.Eq(app.appCodec)).Times(1).Return(mockDefaultGenesis) 216 mockModule.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(app.appCodec), gomock.Eq(mockDefaultGenesis)).Times(1).Return(nil) 217 mockModule.EXPECT().ConsensusVersion().Times(1).Return(uint64(0)) 218 219 app.mm.Modules["mock"] = mockModule 220 221 // Run migrations only for "mock" module. We exclude it from 222 // the VersionMap to simulate upgrading with a new module. 223 _, err := app.mm.RunMigrations(ctx, app.configurator, 224 module.VersionMap{ 225 "bank": bank.AppModule{}.ConsensusVersion(), 226 "auth": auth.AppModule{}.ConsensusVersion(), 227 "authz": authz_m.AppModule{}.ConsensusVersion(), 228 "staking": staking.AppModule{}.ConsensusVersion(), 229 "mint": mint.AppModule{}.ConsensusVersion(), 230 "distribution": distribution.AppModule{}.ConsensusVersion(), 231 "slashing": slashing.AppModule{}.ConsensusVersion(), 232 "gov": gov.AppModule{}.ConsensusVersion(), 233 "params": params.AppModule{}.ConsensusVersion(), 234 "upgrade": upgrade.AppModule{}.ConsensusVersion(), 235 "vesting": vesting.AppModule{}.ConsensusVersion(), 236 "evidence": evidence.AppModule{}.ConsensusVersion(), 237 "crisis": crisis.AppModule{}.ConsensusVersion(), 238 "genutil": genutil.AppModule{}.ConsensusVersion(), 239 "capability": capability.AppModule{}.ConsensusVersion(), 240 "foundation": foundationmodule.AppModule{}.ConsensusVersion(), 241 "token": tokenmodule.AppModule{}.ConsensusVersion(), 242 }, 243 ) 244 245 require.NoError(t, err) 246 } 247 248 func TestUpgradeStateOnGenesis(t *testing.T) { 249 encCfg := MakeTestEncodingConfig() 250 db := dbm.NewMemDB() 251 app := NewSimApp(log.NewOCLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) 252 genesisState := NewDefaultGenesisState(encCfg.Marshaler) 253 stateBytes, err := json.MarshalIndent(genesisState, "", " ") 254 require.NoError(t, err) 255 256 // Initialize the chain 257 app.InitChain( 258 abci.RequestInitChain{ 259 Validators: []abci.ValidatorUpdate{}, 260 AppStateBytes: stateBytes, 261 }, 262 ) 263 264 // make sure the upgrade keeper has version map in state 265 ctx := app.NewContext(false, tmproto.Header{}) 266 vm := app.UpgradeKeeper.GetModuleVersionMap(ctx) 267 for v, i := range app.mm.Modules { 268 require.Equal(t, vm[v], i.ConsensusVersion()) 269 } 270 }