diff --git a/app/test_common.go b/app/test_common.go index 5c46c1ac..9e2b0a11 100644 --- a/app/test_common.go +++ b/app/test_common.go @@ -9,6 +9,7 @@ import ( "time" sdkmath "cosmossdk.io/math" + dasignerskeeper "github.com/0glabs/0g-chain/x/dasigners/v1/keeper" tmdb "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/libs/log" @@ -114,6 +115,7 @@ func (tApp TestApp) GetCommitteeKeeper() committeekeeper.Keeper { return tApp.co func (tApp TestApp) GetEvmutilKeeper() evmutilkeeper.Keeper { return tApp.evmutilKeeper } func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper { return tApp.evmKeeper } func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.feeMarketKeeper } +func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper { return tApp.dasignersKeeper } func (tApp TestApp) GetKVStoreKey(key string) *storetypes.KVStoreKey { return tApp.keys[key] diff --git a/x/dasigners/v1/genesis.go b/x/dasigners/v1/genesis.go index deb04433..bab56a65 100644 --- a/x/dasigners/v1/genesis.go +++ b/x/dasigners/v1/genesis.go @@ -39,7 +39,7 @@ func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { return false }) epochQuorums := make([]*types.Quorums, 0) - for i := 0; i < int(epochNumber); i += 1 { + for i := 0; i <= int(epochNumber); i += 1 { quorumCnt, err := keeper.GetQuorumCount(ctx, uint64(i)) if err != nil { panic("historical quorums not found") diff --git a/x/dasigners/v1/genesis_test.go b/x/dasigners/v1/genesis_test.go new file mode 100644 index 00000000..0a4fc7aa --- /dev/null +++ b/x/dasigners/v1/genesis_test.go @@ -0,0 +1,83 @@ +package dasigners_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/x/dasigners/v1" + "github.com/0glabs/0g-chain/x/dasigners/v1/keeper" + "github.com/0glabs/0g-chain/x/dasigners/v1/types" +) + +type GenesisTestSuite struct { + suite.Suite + + app app.TestApp + ctx sdk.Context + keeper keeper.Keeper + addresses []sdk.AccAddress +} + +func (suite *GenesisTestSuite) SetupTest() { + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetDASignersKeeper() + suite.ctx = suite.app.NewContext(true, tmproto.Header{}) + _, suite.addresses = app.GeneratePrivKeyAddressPairs(10) +} + +func (suite *GenesisTestSuite) TestInitGenesis() { + // Most genesis validation tests are located in the types directory. The 'invalid' test cases are + // randomly selected subset of those tests. + testCases := []struct { + name string + genState *types.GenesisState + expectPass bool + }{ + { + name: "normal", + genState: types.DefaultGenesisState(), + expectPass: true, + }, + } + for _, tc := range testCases { + suite.Run(tc.name, func() { + // Setup (note: suite.SetupTest is not run before every suite.Run) + suite.app = app.NewTestApp() + suite.keeper = suite.app.GetDASignersKeeper() + suite.ctx = suite.app.NewContext(true, tmproto.Header{}) + + // Run + var exportedGenState *types.GenesisState + run := func() { + dasigners.InitGenesis(suite.ctx, suite.keeper, *tc.genState) + exportedGenState = dasigners.ExportGenesis(suite.ctx, suite.keeper) + } + if tc.expectPass { + suite.Require().NotPanics(run) + } else { + suite.Require().Panics(run) + } + + // Check + if tc.expectPass { + fmt.Printf("expected: %v\n", tc.genState) + expectedJson, err := suite.app.AppCodec().MarshalJSON(tc.genState) + suite.Require().NoError(err) + fmt.Printf("actual: %v\n", exportedGenState) + actualJson, err := suite.app.AppCodec().MarshalJSON(exportedGenState) + suite.Require().NoError(err) + suite.Equal(expectedJson, actualJson) + } + }) + } +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/dasigners/v1/testutil/suite.go b/x/dasigners/v1/testutil/suite.go new file mode 100644 index 00000000..54871d78 --- /dev/null +++ b/x/dasigners/v1/testutil/suite.go @@ -0,0 +1,42 @@ +package testutil + +import ( + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/stretchr/testify/suite" + + "github.com/0glabs/0g-chain/app" + "github.com/0glabs/0g-chain/chaincfg" + "github.com/0glabs/0g-chain/x/dasigners/v1/keeper" + "github.com/0glabs/0g-chain/x/dasigners/v1/types" +) + +// Suite implements a test suite for the module integration tests +type Suite struct { + suite.Suite + + Keeper keeper.Keeper + StakingKeeper *stakingkeeper.Keeper + App app.TestApp + Ctx sdk.Context + QueryClient types.QueryClient + Addresses []sdk.AccAddress +} + +// SetupTest instantiates a new app, keepers, and sets suite state +func (suite *Suite) SetupTest() { + chaincfg.SetSDKConfig() + suite.App = app.NewTestApp() + suite.Keeper = suite.App.GetDASignersKeeper() + suite.StakingKeeper = suite.App.GetStakingKeeper() + suite.Ctx = suite.App.NewContext(true, tmproto.Header{}) + _, accAddresses := app.GeneratePrivKeyAddressPairs(10) + suite.Addresses = accAddresses + + // Set query client + queryHelper := suite.App.NewQueryServerTestHelper(suite.Ctx) + queryHandler := suite.Keeper + types.RegisterQueryServer(queryHelper, queryHandler) + suite.QueryClient = types.NewQueryClient(queryHelper) +} diff --git a/x/dasigners/v1/testutil/types.go b/x/dasigners/v1/testutil/types.go new file mode 100644 index 00000000..1ae3828c --- /dev/null +++ b/x/dasigners/v1/testutil/types.go @@ -0,0 +1,25 @@ +package testutil + +import ( + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/assert" +) + +// Avoid cluttering test cases with long function names +func I(in int64) sdkmath.Int { return sdkmath.NewInt(in) } +func D(str string) sdk.Dec { return sdk.MustNewDecFromStr(str) } +func C(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) } +func Cs(coins ...sdk.Coin) sdk.Coins { return sdk.NewCoins(coins...) } + +func AssertProtoMessageJSON(t *testing.T, cdc codec.Codec, expected proto.Message, actual proto.Message) { + expectedJson, err := cdc.MarshalJSON(expected) + assert.NoError(t, err) + actualJson, err := cdc.MarshalJSON(actual) + assert.NoError(t, err) + assert.Equal(t, string(expectedJson), string(actualJson)) +}