github.com/cosmos/cosmos-sdk@v0.50.10/types/module/module_test.go (about)

     1  package module_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"io"
     8  	"testing"
     9  
    10  	abci "github.com/cometbft/cometbft/abci/types"
    11  	cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
    12  	"github.com/golang/mock/gomock"
    13  	"github.com/spf13/cobra"
    14  	"github.com/stretchr/testify/require"
    15  	"google.golang.org/grpc"
    16  
    17  	"cosmossdk.io/core/appmodule"
    18  	"cosmossdk.io/log"
    19  
    20  	"github.com/cosmos/cosmos-sdk/codec"
    21  	"github.com/cosmos/cosmos-sdk/codec/types"
    22  	"github.com/cosmos/cosmos-sdk/testutil/mock"
    23  	sdk "github.com/cosmos/cosmos-sdk/types"
    24  	"github.com/cosmos/cosmos-sdk/types/module"
    25  	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    26  )
    27  
    28  var errFoo = errors.New("dummy")
    29  
    30  func (MockCoreAppModule) GetQueryCmd() *cobra.Command {
    31  	return &cobra.Command{
    32  		Use: "foo",
    33  	}
    34  }
    35  
    36  func TestBasicManager(t *testing.T) {
    37  	mockCtrl := gomock.NewController(t)
    38  	t.Cleanup(mockCtrl.Finish)
    39  	legacyAmino := codec.NewLegacyAmino()
    40  	interfaceRegistry := types.NewInterfaceRegistry()
    41  	cdc := codec.NewProtoCodec(interfaceRegistry)
    42  
    43  	// Test with a legacy module, a mock core module that doesn't return anything,
    44  	// and a core module defined in this file
    45  	expDefaultGenesis := map[string]json.RawMessage{
    46  		"mockAppModuleBasic1": json.RawMessage(``),
    47  		"mockCoreAppModule2":  json.RawMessage(`null`),
    48  		"mockCoreAppModule3": json.RawMessage(`{
    49    "someField": "someKey"
    50  }`),
    51  	}
    52  
    53  	// legacy module
    54  	mockAppModuleBasic1 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
    55  	mockAppModuleBasic1.EXPECT().Name().AnyTimes().Return("mockAppModuleBasic1")
    56  	mockAppModuleBasic1.EXPECT().DefaultGenesis(gomock.Eq(cdc)).Times(1).Return(json.RawMessage(``))
    57  	// Allow ValidateGenesis to be called any times because other module can fail before this one is called.
    58  	mockAppModuleBasic1.EXPECT().ValidateGenesis(gomock.Eq(cdc), gomock.Eq(nil), gomock.Eq(expDefaultGenesis["mockAppModuleBasic1"])).AnyTimes().Return(nil)
    59  	mockAppModuleBasic1.EXPECT().RegisterLegacyAminoCodec(gomock.Eq(legacyAmino)).Times(1)
    60  	mockAppModuleBasic1.EXPECT().RegisterInterfaces(gomock.Eq(interfaceRegistry)).Times(1)
    61  
    62  	// mock core API module
    63  	mockCoreAppModule2 := mock.NewMockCoreAppModule(mockCtrl)
    64  	mockCoreAppModule2.EXPECT().DefaultGenesis(gomock.Any()).AnyTimes().Return(nil)
    65  	mockCoreAppModule2.EXPECT().ValidateGenesis(gomock.Any()).AnyTimes().Return(nil)
    66  	mockAppModule2 := module.CoreAppModuleBasicAdaptor("mockCoreAppModule2", mockCoreAppModule2)
    67  
    68  	// mock core API module (but all methods are implemented)
    69  	mockCoreAppModule3 := module.CoreAppModuleBasicAdaptor("mockCoreAppModule3", MockCoreAppModule{})
    70  
    71  	mm := module.NewBasicManager(mockAppModuleBasic1, mockAppModule2, mockCoreAppModule3)
    72  
    73  	require.Equal(t, mockAppModuleBasic1, mm["mockAppModuleBasic1"])
    74  	require.Equal(t, mockAppModule2, mm["mockCoreAppModule2"])
    75  	require.Equal(t, mockCoreAppModule3, mm["mockCoreAppModule3"])
    76  
    77  	mm.RegisterLegacyAminoCodec(legacyAmino)
    78  	mm.RegisterInterfaces(interfaceRegistry)
    79  
    80  	require.Equal(t, expDefaultGenesis, mm.DefaultGenesis(cdc))
    81  
    82  	var data map[string]string
    83  	require.Equal(t, map[string]string(nil), data)
    84  
    85  	require.ErrorIs(t, mm.ValidateGenesis(cdc, nil, expDefaultGenesis), errFoo)
    86  
    87  	mockCmd := &cobra.Command{Use: "root"}
    88  	mm.AddTxCommands(mockCmd)
    89  	mm.AddQueryCommands(mockCmd)
    90  	require.Equal(t, 1, len(mockCmd.Commands()))
    91  
    92  	// validate genesis returns nil
    93  	require.Nil(t, module.NewBasicManager().ValidateGenesis(cdc, nil, expDefaultGenesis))
    94  }
    95  
    96  func TestAssertNoForgottenModules(t *testing.T) {
    97  	mockCtrl := gomock.NewController(t)
    98  	t.Cleanup(mockCtrl.Finish)
    99  	mockAppModule1 := mock.NewMockHasABCIEndBlock(mockCtrl)
   100  	mockAppModule3 := mock.NewMockCoreAppModule(mockCtrl)
   101  
   102  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   103  	mm := module.NewManager(
   104  		mockAppModule1,
   105  		module.CoreAppModuleBasicAdaptor("module3", mockAppModule3),
   106  	)
   107  	require.NotNil(t, mm)
   108  	require.Equal(t, 2, len(mm.Modules))
   109  
   110  	require.Equal(t, []string{"module1", "module3"}, mm.OrderInitGenesis)
   111  	require.PanicsWithValue(t, "all modules must be defined when setting SetOrderInitGenesis, missing: [module3]", func() {
   112  		mm.SetOrderInitGenesis("module1")
   113  	})
   114  
   115  	require.Equal(t, []string{"module1", "module3"}, mm.OrderExportGenesis)
   116  	require.PanicsWithValue(t, "all modules must be defined when setting SetOrderExportGenesis, missing: [module3]", func() {
   117  		mm.SetOrderExportGenesis("module1")
   118  	})
   119  
   120  	require.Equal(t, []string{"module1", "module3"}, mm.OrderEndBlockers)
   121  	require.PanicsWithValue(t, "all modules must be defined when setting SetOrderEndBlockers, missing: [module1]", func() {
   122  		mm.SetOrderEndBlockers("module3")
   123  	})
   124  }
   125  
   126  func TestManagerOrderSetters(t *testing.T) {
   127  	mockCtrl := gomock.NewController(t)
   128  	t.Cleanup(mockCtrl.Finish)
   129  	mockAppModule1 := mock.NewMockAppModule(mockCtrl)
   130  	mockAppModule2 := mock.NewMockAppModule(mockCtrl)
   131  	mockAppModule3 := mock.NewMockCoreAppModule(mockCtrl)
   132  
   133  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   134  	mockAppModule2.EXPECT().Name().Times(2).Return("module2")
   135  	mm := module.NewManager(mockAppModule1, mockAppModule2, module.CoreAppModuleBasicAdaptor("module3", mockAppModule3))
   136  	require.NotNil(t, mm)
   137  	require.Equal(t, 3, len(mm.Modules))
   138  
   139  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderInitGenesis)
   140  	mm.SetOrderInitGenesis("module2", "module1", "module3")
   141  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderInitGenesis)
   142  
   143  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderExportGenesis)
   144  	mm.SetOrderExportGenesis("module2", "module1", "module3")
   145  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderExportGenesis)
   146  
   147  	require.Equal(t, []string{}, mm.OrderPreBlockers)
   148  	mm.SetOrderPreBlockers("module2", "module1", "module3")
   149  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderPreBlockers)
   150  
   151  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderBeginBlockers)
   152  	mm.SetOrderBeginBlockers("module2", "module1", "module3")
   153  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderBeginBlockers)
   154  
   155  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderEndBlockers)
   156  	mm.SetOrderEndBlockers("module2", "module1", "module3")
   157  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderEndBlockers)
   158  
   159  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrepareCheckStaters)
   160  	mm.SetOrderPrepareCheckStaters("module3", "module2", "module1")
   161  	require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrepareCheckStaters)
   162  
   163  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrecommiters)
   164  	mm.SetOrderPrecommiters("module3", "module2", "module1")
   165  	require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrecommiters)
   166  }
   167  
   168  func TestManager_RegisterInvariants(t *testing.T) {
   169  	mockCtrl := gomock.NewController(t)
   170  	t.Cleanup(mockCtrl.Finish)
   171  
   172  	mockAppModule1 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   173  	mockAppModule2 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   174  	mockAppModule3 := mock.NewMockCoreAppModule(mockCtrl)
   175  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   176  	mockAppModule2.EXPECT().Name().Times(2).Return("module2")
   177  	// TODO: This is not working for Core API modules yet
   178  	mm := module.NewManager(mockAppModule1, mockAppModule2, module.CoreAppModuleBasicAdaptor("mockAppModule3", mockAppModule3))
   179  	require.NotNil(t, mm)
   180  	require.Equal(t, 3, len(mm.Modules))
   181  
   182  	// test RegisterInvariants
   183  	mockInvariantRegistry := mock.NewMockInvariantRegistry(mockCtrl)
   184  	mockAppModule1.EXPECT().RegisterInvariants(gomock.Eq(mockInvariantRegistry)).Times(1)
   185  	mockAppModule2.EXPECT().RegisterInvariants(gomock.Eq(mockInvariantRegistry)).Times(1)
   186  	mm.RegisterInvariants(mockInvariantRegistry)
   187  }
   188  
   189  func TestManager_RegisterQueryServices(t *testing.T) {
   190  	mockCtrl := gomock.NewController(t)
   191  	t.Cleanup(mockCtrl.Finish)
   192  
   193  	mockAppModule1 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   194  	mockAppModule2 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   195  	mockAppModule3 := MockCoreAppModule{}
   196  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   197  	mockAppModule2.EXPECT().Name().Times(2).Return("module2")
   198  	// TODO: This is not working for Core API modules yet
   199  	mm := module.NewManager(mockAppModule1, mockAppModule2, module.CoreAppModuleBasicAdaptor("mockAppModule3", mockAppModule3))
   200  	require.NotNil(t, mm)
   201  	require.Equal(t, 3, len(mm.Modules))
   202  
   203  	msgRouter := mock.NewMockServer(mockCtrl)
   204  	msgRouter.EXPECT().RegisterService(gomock.Any(), gomock.Any()).Times(1)
   205  	queryRouter := mock.NewMockServer(mockCtrl)
   206  	queryRouter.EXPECT().RegisterService(gomock.Any(), gomock.Any()).Times(1)
   207  
   208  	interfaceRegistry := types.NewInterfaceRegistry()
   209  	cdc := codec.NewProtoCodec(interfaceRegistry)
   210  	cfg := module.NewConfigurator(cdc, msgRouter, queryRouter)
   211  	mockAppModule1.EXPECT().RegisterServices(cfg).Times(1)
   212  	mockAppModule2.EXPECT().RegisterServices(cfg).Times(1)
   213  
   214  	require.NotPanics(t, func() { mm.RegisterServices(cfg) })
   215  }
   216  
   217  func TestManager_InitGenesis(t *testing.T) {
   218  	mockCtrl := gomock.NewController(t)
   219  	t.Cleanup(mockCtrl.Finish)
   220  
   221  	mockAppModule1 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   222  	mockAppModule2 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   223  	mockAppModule3 := mock.NewMockCoreAppModule(mockCtrl)
   224  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   225  	mockAppModule2.EXPECT().Name().Times(4).Return("module2")
   226  	mm := module.NewManager(mockAppModule1, mockAppModule2, module.CoreAppModuleBasicAdaptor("module3", mockAppModule3))
   227  	require.NotNil(t, mm)
   228  	require.Equal(t, 3, len(mm.Modules))
   229  
   230  	ctx := sdk.NewContext(nil, cmtproto.Header{}, false, log.NewNopLogger())
   231  	interfaceRegistry := types.NewInterfaceRegistry()
   232  	cdc := codec.NewProtoCodec(interfaceRegistry)
   233  	genesisData := map[string]json.RawMessage{"module1": json.RawMessage(`{"key": "value"}`)}
   234  
   235  	// this should panic since the validator set is empty even after init genesis
   236  	mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1)
   237  	_, err := mm.InitGenesis(ctx, cdc, genesisData)
   238  	require.ErrorContains(t, err, "validator set is empty after InitGenesis")
   239  
   240  	// test panic
   241  	genesisData = map[string]json.RawMessage{
   242  		"module1": json.RawMessage(`{"key": "value"}`),
   243  		"module2": json.RawMessage(`{"key": "value"}`),
   244  		"module3": json.RawMessage(`{"key": "value"}`),
   245  	}
   246  
   247  	mockAppModuleABCI1 := mock.NewMockAppModuleWithAllExtensionsABCI(mockCtrl)
   248  	mockAppModuleABCI2 := mock.NewMockAppModuleWithAllExtensionsABCI(mockCtrl)
   249  	mockAppModuleABCI1.EXPECT().Name().Times(4).Return("module1")
   250  	mockAppModuleABCI2.EXPECT().Name().Times(2).Return("module2")
   251  	mmABCI := module.NewManager(mockAppModuleABCI1, mockAppModuleABCI2)
   252  	// panic because more than one module returns validator set updates
   253  	mockAppModuleABCI1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return([]abci.ValidatorUpdate{{}})
   254  	mockAppModuleABCI2.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module2"])).Times(1).Return([]abci.ValidatorUpdate{{}})
   255  	_, err = mmABCI.InitGenesis(ctx, cdc, genesisData)
   256  	require.ErrorContains(t, err, "validator InitGenesis updates already set by a previous module")
   257  
   258  	// happy path
   259  
   260  	mm2 := module.NewManager(mockAppModuleABCI1, mockAppModule2, module.CoreAppModuleBasicAdaptor("module3", mockAppModule3))
   261  	mockAppModuleABCI1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return([]abci.ValidatorUpdate{{}})
   262  	mockAppModule2.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module2"])).Times(1)
   263  	mockAppModule3.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Any()).Times(1).Return(nil)
   264  	_, err = mm2.InitGenesis(ctx, cdc, genesisData)
   265  	require.NoError(t, err)
   266  }
   267  
   268  func TestManager_ExportGenesis(t *testing.T) {
   269  	mockCtrl := gomock.NewController(t)
   270  	t.Cleanup(mockCtrl.Finish)
   271  
   272  	mockAppModule1 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   273  	mockAppModule2 := mock.NewMockAppModuleWithAllExtensions(mockCtrl)
   274  	mockCoreAppModule := MockCoreAppModule{}
   275  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   276  	mockAppModule2.EXPECT().Name().Times(2).Return("module2")
   277  	mm := module.NewManager(mockAppModule1, mockAppModule2, module.CoreAppModuleBasicAdaptor("mockCoreAppModule", mockCoreAppModule))
   278  	require.NotNil(t, mm)
   279  	require.Equal(t, 3, len(mm.Modules))
   280  
   281  	ctx := sdk.NewContext(nil, cmtproto.Header{}, false, log.NewNopLogger())
   282  	interfaceRegistry := types.NewInterfaceRegistry()
   283  	cdc := codec.NewProtoCodec(interfaceRegistry)
   284  	mockAppModule1.EXPECT().ExportGenesis(gomock.Eq(ctx), gomock.Eq(cdc)).AnyTimes().Return(json.RawMessage(`{"key1": "value1"}`))
   285  	mockAppModule2.EXPECT().ExportGenesis(gomock.Eq(ctx), gomock.Eq(cdc)).AnyTimes().Return(json.RawMessage(`{"key2": "value2"}`))
   286  
   287  	want := map[string]json.RawMessage{
   288  		"module1": json.RawMessage(`{"key1": "value1"}`),
   289  		"module2": json.RawMessage(`{"key2": "value2"}`),
   290  		"mockCoreAppModule": json.RawMessage(`{
   291    "someField": "someKey"
   292  }`),
   293  	}
   294  
   295  	res, err := mm.ExportGenesis(ctx, cdc)
   296  	require.NoError(t, err)
   297  	require.Equal(t, want, res)
   298  
   299  	res, err = mm.ExportGenesisForModules(ctx, cdc, []string{})
   300  	require.NoError(t, err)
   301  	require.Equal(t, want, res)
   302  
   303  	res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1"})
   304  	require.NoError(t, err)
   305  	require.Equal(t, map[string]json.RawMessage{"module1": json.RawMessage(`{"key1": "value1"}`)}, res)
   306  
   307  	res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module2"})
   308  	require.NoError(t, err)
   309  	require.NotEqual(t, map[string]json.RawMessage{"module1": json.RawMessage(`{"key1": "value1"}`)}, res)
   310  
   311  	_, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1", "modulefoo"})
   312  	require.Error(t, err)
   313  }
   314  
   315  func TestManager_EndBlock(t *testing.T) {
   316  	mockCtrl := gomock.NewController(t)
   317  	t.Cleanup(mockCtrl.Finish)
   318  
   319  	mockAppModule1 := mock.NewMockHasABCIEndBlock(mockCtrl)
   320  	mockAppModule2 := mock.NewMockHasABCIEndBlock(mockCtrl)
   321  	mockAppModule3 := mock.NewMockAppModule(mockCtrl)
   322  	mockAppModule1.EXPECT().Name().Times(2).Return("module1")
   323  	mockAppModule2.EXPECT().Name().Times(2).Return("module2")
   324  	mockAppModule3.EXPECT().Name().Times(2).Return("module3")
   325  	mm := module.NewManager(mockAppModule1, mockAppModule2, mockAppModule3)
   326  	require.NotNil(t, mm)
   327  	require.Equal(t, 3, len(mm.Modules))
   328  
   329  	mockAppModule1.EXPECT().EndBlock(gomock.Any()).Times(1).Return([]abci.ValidatorUpdate{{}}, nil)
   330  	mockAppModule2.EXPECT().EndBlock(gomock.Any()).Times(1)
   331  	ret, err := mm.EndBlock(sdk.Context{})
   332  	require.NoError(t, err)
   333  	require.Equal(t, []abci.ValidatorUpdate{{}}, ret.ValidatorUpdates)
   334  
   335  	// test panic
   336  	mockAppModule1.EXPECT().EndBlock(gomock.Any()).Times(1).Return([]abci.ValidatorUpdate{{}}, nil)
   337  	mockAppModule2.EXPECT().EndBlock(gomock.Any()).Times(1).Return([]abci.ValidatorUpdate{{}}, nil)
   338  	_, err = mm.EndBlock(sdk.Context{})
   339  	require.Error(t, err)
   340  }
   341  
   342  // Core API exclusive tests
   343  func TestCoreAPIManager(t *testing.T) {
   344  	mockCtrl := gomock.NewController(t)
   345  	module1 := mock.NewMockCoreAppModule(mockCtrl)
   346  	module2 := MockCoreAppModule{}
   347  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   348  		"module1": module1,
   349  		"module2": module2,
   350  	})
   351  
   352  	require.NotNil(t, mm)
   353  	require.Equal(t, 2, len(mm.Modules))
   354  	require.Equal(t, module1, mm.Modules["module1"])
   355  	require.Equal(t, module2, mm.Modules["module2"])
   356  }
   357  
   358  func TestCoreAPIManager_InitGenesis(t *testing.T) {
   359  	mockCtrl := gomock.NewController(t)
   360  	t.Cleanup(mockCtrl.Finish)
   361  
   362  	mockAppModule1 := mock.NewMockCoreAppModule(mockCtrl)
   363  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{"module1": mockAppModule1})
   364  	require.NotNil(t, mm)
   365  	require.Equal(t, 1, len(mm.Modules))
   366  
   367  	ctx := sdk.NewContext(nil, cmtproto.Header{}, false, log.NewNopLogger())
   368  	interfaceRegistry := types.NewInterfaceRegistry()
   369  	cdc := codec.NewProtoCodec(interfaceRegistry)
   370  	genesisData := map[string]json.RawMessage{"module1": json.RawMessage(`{"key": "value"}`)}
   371  
   372  	// this should panic since the validator set is empty even after init genesis
   373  	mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Any()).Times(1).Return(nil)
   374  	_, err := mm.InitGenesis(ctx, cdc, genesisData)
   375  	require.ErrorContains(t, err, "validator set is empty after InitGenesis, please ensure at least one validator is initialized with a delegation greater than or equal to the DefaultPowerReduction")
   376  
   377  	// TODO: add happy path test. We are not returning any validator updates, this will come with the services.
   378  	// REF: https://github.com/cosmos/cosmos-sdk/issues/14688
   379  }
   380  
   381  func TestCoreAPIManager_ExportGenesis(t *testing.T) {
   382  	mockAppModule1 := MockCoreAppModule{}
   383  	mockAppModule2 := MockCoreAppModule{}
   384  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   385  		"module1": mockAppModule1,
   386  		"module2": mockAppModule2,
   387  	})
   388  	require.NotNil(t, mm)
   389  	require.Equal(t, 2, len(mm.Modules))
   390  
   391  	ctx := sdk.NewContext(nil, cmtproto.Header{}, false, log.NewNopLogger())
   392  	interfaceRegistry := types.NewInterfaceRegistry()
   393  	cdc := codec.NewProtoCodec(interfaceRegistry)
   394  	want := map[string]json.RawMessage{
   395  		"module1": json.RawMessage(`{
   396    "someField": "someKey"
   397  }`),
   398  		"module2": json.RawMessage(`{
   399    "someField": "someKey"
   400  }`),
   401  	}
   402  
   403  	res, err := mm.ExportGenesis(ctx, cdc)
   404  	require.NoError(t, err)
   405  	require.Equal(t, want, res)
   406  
   407  	res, err = mm.ExportGenesisForModules(ctx, cdc, []string{})
   408  	require.NoError(t, err)
   409  	require.Equal(t, want, res)
   410  
   411  	res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1"})
   412  	require.NoError(t, err)
   413  	require.Equal(t, map[string]json.RawMessage{"module1": want["module1"]}, res)
   414  
   415  	res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module2"})
   416  	require.NoError(t, err)
   417  	require.NotEqual(t, map[string]json.RawMessage{"module1": want["module1"]}, res)
   418  
   419  	_, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1", "modulefoo"})
   420  	require.Error(t, err)
   421  }
   422  
   423  func TestCoreAPIManagerOrderSetters(t *testing.T) {
   424  	mockCtrl := gomock.NewController(t)
   425  	t.Cleanup(mockCtrl.Finish)
   426  	mockAppModule1 := mock.NewMockCoreAppModule(mockCtrl)
   427  	mockAppModule2 := mock.NewMockCoreAppModule(mockCtrl)
   428  	mockAppModule3 := mock.NewMockCoreAppModule(mockCtrl)
   429  
   430  	mm := module.NewManagerFromMap(
   431  		map[string]appmodule.AppModule{
   432  			"module1": mockAppModule1,
   433  			"module2": mockAppModule2,
   434  			"module3": mockAppModule3,
   435  		})
   436  	require.NotNil(t, mm)
   437  	require.Equal(t, 3, len(mm.Modules))
   438  
   439  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderInitGenesis)
   440  	mm.SetOrderInitGenesis("module2", "module1", "module3")
   441  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderInitGenesis)
   442  
   443  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderExportGenesis)
   444  	mm.SetOrderExportGenesis("module2", "module1", "module3")
   445  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderExportGenesis)
   446  
   447  	require.Equal(t, []string{}, mm.OrderPreBlockers)
   448  	mm.SetOrderPreBlockers("module2", "module1", "module3")
   449  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderPreBlockers)
   450  
   451  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderBeginBlockers)
   452  	mm.SetOrderBeginBlockers("module2", "module1", "module3")
   453  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderBeginBlockers)
   454  
   455  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderEndBlockers)
   456  	mm.SetOrderEndBlockers("module2", "module1", "module3")
   457  	require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderEndBlockers)
   458  
   459  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrepareCheckStaters)
   460  	mm.SetOrderPrepareCheckStaters("module3", "module2", "module1")
   461  	require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrepareCheckStaters)
   462  
   463  	require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrecommiters)
   464  	mm.SetOrderPrecommiters("module3", "module2", "module1")
   465  	require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrecommiters)
   466  }
   467  
   468  func TestCoreAPIManager_PreBlock(t *testing.T) {
   469  	mockCtrl := gomock.NewController(t)
   470  	t.Cleanup(mockCtrl.Finish)
   471  
   472  	mockAppModule1 := mock.NewMockCoreAppModuleWithPreBlock(mockCtrl)
   473  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   474  		"module1": mockAppModule1,
   475  		"module2": mock.NewMockCoreAppModule(mockCtrl),
   476  	})
   477  	require.NotNil(t, mm)
   478  	require.Equal(t, 2, len(mm.Modules))
   479  	require.Equal(t, 1, len(mm.OrderPreBlockers))
   480  
   481  	mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(&sdk.ResponsePreBlock{
   482  		ConsensusParamsChanged: true,
   483  	}, nil)
   484  	res, err := mm.PreBlock(sdk.Context{})
   485  	require.NoError(t, err)
   486  	require.True(t, res.ConsensusParamsChanged)
   487  
   488  	// test false
   489  	mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(&sdk.ResponsePreBlock{
   490  		ConsensusParamsChanged: false,
   491  	}, nil)
   492  	res, err = mm.PreBlock(sdk.Context{})
   493  	require.NoError(t, err)
   494  	require.False(t, res.ConsensusParamsChanged)
   495  
   496  	// test error
   497  	mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(nil, errors.New("some error"))
   498  	_, err = mm.PreBlock(sdk.Context{})
   499  	require.EqualError(t, err, "some error")
   500  }
   501  
   502  func TestCoreAPIManager_BeginBlock(t *testing.T) {
   503  	mockCtrl := gomock.NewController(t)
   504  	t.Cleanup(mockCtrl.Finish)
   505  
   506  	mockAppModule1 := mock.NewMockCoreAppModule(mockCtrl)
   507  	mockAppModule2 := mock.NewMockCoreAppModule(mockCtrl)
   508  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   509  		"module1": mockAppModule1,
   510  		"module2": mockAppModule2,
   511  	})
   512  	require.NotNil(t, mm)
   513  	require.Equal(t, 2, len(mm.Modules))
   514  
   515  	mockAppModule1.EXPECT().BeginBlock(gomock.Any()).Times(1).Return(nil)
   516  	mockAppModule2.EXPECT().BeginBlock(gomock.Any()).Times(1).Return(nil)
   517  	_, err := mm.BeginBlock(sdk.Context{})
   518  	require.NoError(t, err)
   519  
   520  	// test panic
   521  	mockAppModule1.EXPECT().BeginBlock(gomock.Any()).Times(1).Return(errors.New("some error"))
   522  	_, err = mm.BeginBlock(sdk.Context{})
   523  	require.EqualError(t, err, "some error")
   524  }
   525  
   526  func TestCoreAPIManager_EndBlock(t *testing.T) {
   527  	mockCtrl := gomock.NewController(t)
   528  	t.Cleanup(mockCtrl.Finish)
   529  
   530  	mockAppModule1 := mock.NewMockCoreAppModule(mockCtrl)
   531  	mockAppModule2 := mock.NewMockCoreAppModule(mockCtrl)
   532  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   533  		"module1": mockAppModule1,
   534  		"module2": mockAppModule2,
   535  	})
   536  	require.NotNil(t, mm)
   537  	require.Equal(t, 2, len(mm.Modules))
   538  
   539  	mockAppModule1.EXPECT().EndBlock(gomock.Any()).Times(1).Return(nil)
   540  	mockAppModule2.EXPECT().EndBlock(gomock.Any()).Times(1).Return(nil)
   541  	res, err := mm.EndBlock(sdk.Context{})
   542  	require.NoError(t, err)
   543  	require.Len(t, res.ValidatorUpdates, 0)
   544  
   545  	// test panic
   546  	mockAppModule1.EXPECT().EndBlock(gomock.Any()).Times(1).Return(errors.New("some error"))
   547  	_, err = mm.EndBlock(sdk.Context{})
   548  	require.EqualError(t, err, "some error")
   549  }
   550  
   551  func TestManager_PrepareCheckState(t *testing.T) {
   552  	mockCtrl := gomock.NewController(t)
   553  	t.Cleanup(mockCtrl.Finish)
   554  
   555  	mockAppModule1 := mock.NewMockCoreAppModule(mockCtrl)
   556  	mockAppModule2 := mock.NewMockCoreAppModule(mockCtrl)
   557  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   558  		"module1": mockAppModule1,
   559  		"module2": mockAppModule2,
   560  	})
   561  	require.NotNil(t, mm)
   562  	require.Equal(t, 2, len(mm.Modules))
   563  
   564  	mockAppModule1.EXPECT().PrepareCheckState(gomock.Any()).Times(1).Return(nil)
   565  	mockAppModule2.EXPECT().PrepareCheckState(gomock.Any()).Times(1).Return(nil)
   566  	err := mm.PrepareCheckState(sdk.Context{})
   567  	require.NoError(t, err)
   568  
   569  	mockAppModule1.EXPECT().PrepareCheckState(gomock.Any()).Times(1).Return(errors.New("some error"))
   570  	err = mm.PrepareCheckState(sdk.Context{})
   571  	require.EqualError(t, err, "some error")
   572  }
   573  
   574  func TestManager_Precommit(t *testing.T) {
   575  	mockCtrl := gomock.NewController(t)
   576  	t.Cleanup(mockCtrl.Finish)
   577  
   578  	mockAppModule1 := mock.NewMockCoreAppModule(mockCtrl)
   579  	mockAppModule2 := mock.NewMockCoreAppModule(mockCtrl)
   580  	mm := module.NewManagerFromMap(map[string]appmodule.AppModule{
   581  		"module1": mockAppModule1,
   582  		"module2": mockAppModule2,
   583  	})
   584  	require.NotNil(t, mm)
   585  	require.Equal(t, 2, len(mm.Modules))
   586  
   587  	mockAppModule1.EXPECT().Precommit(gomock.Any()).Times(1).Return(nil)
   588  	mockAppModule2.EXPECT().Precommit(gomock.Any()).Times(1).Return(nil)
   589  	err := mm.Precommit(sdk.Context{})
   590  	require.NoError(t, err)
   591  
   592  	mockAppModule1.EXPECT().Precommit(gomock.Any()).Times(1).Return(errors.New("some error"))
   593  	err = mm.Precommit(sdk.Context{})
   594  	require.EqualError(t, err, "some error")
   595  }
   596  
   597  // MockCoreAppModule allows us to test functions like DefaultGenesis
   598  type MockCoreAppModule struct{}
   599  
   600  // RegisterServices implements appmodule.HasServices
   601  func (MockCoreAppModule) RegisterServices(reg grpc.ServiceRegistrar) error {
   602  	// Use Auth's service definitions as a placeholder
   603  	authtypes.RegisterQueryServer(reg, &authtypes.UnimplementedQueryServer{})
   604  	authtypes.RegisterMsgServer(reg, &authtypes.UnimplementedMsgServer{})
   605  	return nil
   606  }
   607  
   608  func (MockCoreAppModule) IsOnePerModuleType() {}
   609  func (MockCoreAppModule) IsAppModule()        {}
   610  func (MockCoreAppModule) DefaultGenesis(target appmodule.GenesisTarget) error {
   611  	someFieldWriter, err := target("someField")
   612  	if err != nil {
   613  		return err
   614  	}
   615  	someFieldWriter.Write([]byte(`"someKey"`))
   616  	return someFieldWriter.Close()
   617  }
   618  
   619  func (MockCoreAppModule) ValidateGenesis(src appmodule.GenesisSource) error {
   620  	rdr, err := src("someField")
   621  	if err != nil {
   622  		return err
   623  	}
   624  	data, err := io.ReadAll(rdr)
   625  	if err != nil {
   626  		return err
   627  	}
   628  
   629  	// this check will always fail, but it's just an example
   630  	if string(data) != `"dummy validation"` {
   631  		return errFoo
   632  	}
   633  
   634  	return nil
   635  }
   636  func (MockCoreAppModule) InitGenesis(context.Context, appmodule.GenesisSource) error { return nil }
   637  func (MockCoreAppModule) ExportGenesis(ctx context.Context, target appmodule.GenesisTarget) error {
   638  	wrt, err := target("someField")
   639  	if err != nil {
   640  		return err
   641  	}
   642  	wrt.Write([]byte(`"someKey"`))
   643  	return wrt.Close()
   644  }
   645  
   646  var (
   647  	_ appmodule.AppModule   = MockCoreAppModule{}
   648  	_ appmodule.HasGenesis  = MockCoreAppModule{}
   649  	_ appmodule.HasServices = MockCoreAppModule{}
   650  )