0g-chain/x/precisebank/genesis_test.go

272 lines
7.8 KiB
Go

package precisebank_test
import (
"testing"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/precisebank"
"github.com/kava-labs/kava/x/precisebank/keeper"
"github.com/kava-labs/kava/x/precisebank/testutil"
"github.com/kava-labs/kava/x/precisebank/types"
"github.com/stretchr/testify/suite"
)
type GenesisTestSuite struct {
testutil.Suite
}
func TestGenesisTestSuite(t *testing.T) {
suite.Run(t, new(GenesisTestSuite))
}
func (suite *GenesisTestSuite) TestInitGenesis() {
tests := []struct {
name string
setupFn func()
genesisState *types.GenesisState
panicMsg string
}{
{
"valid - default genesisState",
func() {},
types.DefaultGenesisState(),
"",
},
{
"valid - empty genesisState",
func() {},
&types.GenesisState{},
"failed to validate precisebank genesis state: nil remainder amount",
},
{
"valid - module balance matches non-zero amount",
func() {
// Set module account balance to expected amount
err := suite.BankKeeper.MintCoins(
suite.Ctx,
types.ModuleName,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(2))),
)
suite.Require().NoError(err)
},
types.NewGenesisState(
types.FractionalBalances{
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)),
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)),
},
// 2 leftover from 0.999... + 0.999...
sdkmath.NewInt(2),
),
"",
},
{
// Other GenesisState.Validate() tests are in types/genesis_test.go
"invalid genesisState - GenesisState.Validate() is called",
func() {},
types.NewGenesisState(
types.FractionalBalances{
types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)),
types.NewFractionalBalance(sdk.AccAddress{1}.String(), sdkmath.NewInt(1)),
},
sdkmath.ZeroInt(),
),
"failed to validate precisebank genesis state: invalid balances: duplicate address kava1qy0xn7za",
},
{
"invalid - module balance insufficient",
func() {},
types.NewGenesisState(
types.FractionalBalances{
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)),
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)),
},
// 2 leftover from 0.999... + 0.999...
sdkmath.NewInt(2),
),
"module account balance does not match sum of fractional balances and remainder, balance is 0ukava but expected 2000000000000akava (2ukava)",
},
{
"invalid - module balance excessive",
func() {
// Set module account balance to greater than expected amount
err := suite.BankKeeper.MintCoins(
suite.Ctx,
types.ModuleName,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(100))),
)
suite.Require().NoError(err)
},
types.NewGenesisState(
types.FractionalBalances{
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().SubRaw(1)),
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().SubRaw(1)),
},
sdkmath.NewInt(2),
),
"module account balance does not match sum of fractional balances and remainder, balance is 100ukava but expected 2000000000000akava (2ukava)",
},
{
"sets module account",
func() {
// Delete the module account first to ensure it's created here
moduleAcc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
suite.AccountKeeper.RemoveAccount(suite.Ctx, moduleAcc)
// Ensure module account is deleted in state.
// GetModuleAccount() will always return non-nil and does not
// necessarily equate to the account being stored in the account store.
suite.Require().Nil(suite.AccountKeeper.GetAccount(suite.Ctx, moduleAcc.GetAddress()))
},
types.DefaultGenesisState(),
"",
},
}
for _, tc := range tests {
suite.Run(tc.name, func() {
suite.SetupTest()
tc.setupFn()
if tc.panicMsg != "" {
suite.Require().PanicsWithValue(
tc.panicMsg,
func() {
precisebank.InitGenesis(
suite.Ctx,
suite.Keeper,
suite.AccountKeeper,
suite.BankKeeper,
tc.genesisState,
)
},
)
return
}
suite.Require().NotPanics(func() {
precisebank.InitGenesis(
suite.Ctx,
suite.Keeper,
suite.AccountKeeper,
suite.BankKeeper,
tc.genesisState,
)
})
// Ensure module account is created
moduleAcc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
suite.NotNil(moduleAcc)
suite.NotNil(
suite.AccountKeeper.GetAccount(suite.Ctx, moduleAcc.GetAddress()),
"module account should be created & stored in account store",
)
// Verify balances are set in state, get full list of balances in
// state to ensure they are set AND no extra balances are set
var bals []types.FractionalBalance
suite.Keeper.IterateFractionalBalances(suite.Ctx, func(addr sdk.AccAddress, bal sdkmath.Int) bool {
bals = append(bals, types.NewFractionalBalance(addr.String(), bal))
return false
})
suite.Require().ElementsMatch(tc.genesisState.Balances, bals, "balances should be set in state")
remainder := suite.Keeper.GetRemainderAmount(suite.Ctx)
suite.Require().Equal(tc.genesisState.Remainder, remainder, "remainder should be set in state")
// Additional verification of state via invariants
invariantFn := keeper.AllInvariants(suite.Keeper)
msg, broken := invariantFn(suite.Ctx)
suite.Require().False(broken, "invariants should not be broken after InitGenesis")
suite.Require().Empty(msg, "invariants should not return a message after InitGenesis")
})
}
}
func (suite *GenesisTestSuite) TestExportGenesis() {
// ExportGenesis(InitGenesis(genesisState)) == genesisState
// Must also be valid.
tests := []struct {
name string
initGenesisState func() *types.GenesisState
}{
{
"InitGenesis(DefaultGenesisState)",
func() *types.GenesisState {
return types.DefaultGenesisState()
},
},
{
"balances, no remainder",
func() *types.GenesisState {
err := suite.BankKeeper.MintCoins(
suite.Ctx,
types.ModuleName,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))),
)
suite.Require().NoError(err)
return types.NewGenesisState(
types.FractionalBalances{
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)),
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2)),
},
sdkmath.ZeroInt(),
)
},
},
{
"balances, remainder",
func() *types.GenesisState {
err := suite.BankKeeper.MintCoins(
suite.Ctx,
types.ModuleName,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdkmath.NewInt(1))),
)
suite.Require().NoError(err)
return types.NewGenesisState(
types.FractionalBalances{
types.NewFractionalBalance(sdk.AccAddress{1}.String(), types.ConversionFactor().QuoRaw(2)),
types.NewFractionalBalance(sdk.AccAddress{2}.String(), types.ConversionFactor().QuoRaw(2).SubRaw(1)),
},
sdkmath.OneInt(),
)
},
},
}
for _, tc := range tests {
suite.Run(tc.name, func() {
// Reset state
suite.SetupTest()
initGs := tc.initGenesisState()
suite.Require().NotPanics(func() {
precisebank.InitGenesis(
suite.Ctx,
suite.Keeper,
suite.AccountKeeper,
suite.BankKeeper,
initGs,
)
})
genesisState := precisebank.ExportGenesis(suite.Ctx, suite.Keeper)
suite.Require().NoError(genesisState.Validate(), "exported genesis state should be valid")
suite.Require().Equal(
initGs,
genesisState,
"exported genesis state should equal initial genesis state",
)
})
}
}