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  }