github.com/KiraCore/sekai@v0.3.43/app/ante/testutil_test.go (about)

     1  package ante_test
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	simapp "github.com/KiraCore/sekai/app"
     9  	customante "github.com/KiraCore/sekai/app/ante"
    10  	tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
    11  	"github.com/cosmos/cosmos-sdk/client"
    12  	"github.com/cosmos/cosmos-sdk/client/tx"
    13  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    14  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    15  	sdk "github.com/cosmos/cosmos-sdk/types"
    16  	"github.com/cosmos/cosmos-sdk/types/tx/signing"
    17  	"github.com/cosmos/cosmos-sdk/x/auth/ante"
    18  	xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
    19  	"github.com/cosmos/cosmos-sdk/x/auth/types"
    20  	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    21  	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    22  	"github.com/stretchr/testify/suite"
    23  )
    24  
    25  // TestAccount represents an account used in the tests in x/auth/ante.
    26  type TestAccount struct {
    27  	acc  types.AccountI
    28  	priv cryptotypes.PrivKey
    29  }
    30  
    31  // AnteTestSuite is a test suite to be used with ante handler tests.
    32  type AnteTestSuite struct {
    33  	suite.Suite
    34  
    35  	app         *simapp.SekaiApp
    36  	anteHandler sdk.AnteHandler
    37  	ctx         sdk.Context
    38  	clientCtx   client.Context
    39  	txBuilder   client.TxBuilder
    40  }
    41  
    42  // returns context and app with params set on account keeper
    43  func createTestApp(isCheckTx bool) (*simapp.SekaiApp, sdk.Context) {
    44  	app := simapp.Setup(isCheckTx)
    45  	ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
    46  	app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams())
    47  
    48  	return app, ctx
    49  }
    50  
    51  // SetupTest setups a new test, with new app, context, and anteHandler.
    52  func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
    53  	suite.app, suite.ctx = createTestApp(isCheckTx)
    54  	suite.ctx = suite.ctx.WithBlockHeight(1)
    55  
    56  	// Set up TxConfig.
    57  	encodingConfig := simapp.MakeEncodingConfig()
    58  	// We're using TestMsg amino encoding in some tests, so register it here.
    59  	encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
    60  
    61  	suite.clientCtx = client.Context{}.
    62  		WithTxConfig(encodingConfig.TxConfig)
    63  
    64  	suite.anteHandler = customante.NewAnteHandler(
    65  		suite.app.CustomStakingKeeper,
    66  
    67  		suite.app.CustomGovKeeper,
    68  		suite.app.TokensKeeper,
    69  		suite.app.FeeProcessingKeeper,
    70  		suite.app.AccountKeeper,
    71  		suite.app.BankKeeper,
    72  		suite.app.CustodyKeeper,
    73  		nil,
    74  		nil,
    75  		ante.DefaultSigVerificationGasConsumer,
    76  		encodingConfig.TxConfig.SignModeHandler(),
    77  		nil)
    78  }
    79  
    80  // CreateTestAccounts creates `numAccs` accounts, and return all relevant
    81  // information about them including their private keys.
    82  func (suite *AnteTestSuite) CreateTestAccounts(numAccs int) []TestAccount {
    83  	var accounts []TestAccount
    84  
    85  	for i := 0; i < numAccs; i++ {
    86  		priv, _, addr := testdata.KeyTestPubAddr()
    87  		acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
    88  		err := acc.SetAccountNumber(uint64(i))
    89  		suite.Require().NoError(err)
    90  		suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
    91  		coins := sdk.Coins{
    92  			sdk.NewInt64Coin("atom", 10000000),
    93  		}
    94  		suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, coins)
    95  		suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, addr, coins)
    96  
    97  		accounts = append(accounts, TestAccount{acc, priv})
    98  	}
    99  
   100  	return accounts
   101  }
   102  
   103  // CreateTestTx is a helper function to create a tx given multiple inputs.
   104  func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (xauthsigning.Tx, error) {
   105  	// First round: we gather all the signer infos. We use the "set empty
   106  	// signature" hack to do that.
   107  	var sigsV2 []signing.SignatureV2
   108  	for i, priv := range privs {
   109  		sigV2 := signing.SignatureV2{
   110  			PubKey: priv.PubKey(),
   111  			Data: &signing.SingleSignatureData{
   112  				SignMode:  suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(),
   113  				Signature: nil,
   114  			},
   115  			Sequence: accSeqs[i],
   116  		}
   117  
   118  		sigsV2 = append(sigsV2, sigV2)
   119  	}
   120  	err := suite.txBuilder.SetSignatures(sigsV2...)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	// Second round: all signer infos are set, so each signer can sign.
   126  	sigsV2 = []signing.SignatureV2{}
   127  	for i, priv := range privs {
   128  		signerData := xauthsigning.SignerData{
   129  			ChainID:       chainID,
   130  			AccountNumber: accNums[i],
   131  			Sequence:      accSeqs[i],
   132  		}
   133  		sigV2, err := tx.SignWithPrivKey(
   134  			suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
   135  			suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i])
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  
   140  		sigsV2 = append(sigsV2, sigV2)
   141  	}
   142  	err = suite.txBuilder.SetSignatures(sigsV2...)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	return suite.txBuilder.GetTx(), nil
   148  }
   149  
   150  // TestCase represents a test case used in test tables.
   151  type TestCase struct {
   152  	desc      string
   153  	buildTest func() ([]sdk.Msg, []cryptotypes.PrivKey, []uint64, []uint64, sdk.Coins)
   154  	simulate  bool
   155  	expPass   bool
   156  	expErr    error
   157  }
   158  
   159  // CreateTestTx is a helper function to create a tx given multiple inputs.
   160  func (suite *AnteTestSuite) RunTestCase(privs []cryptotypes.PrivKey, msgs []sdk.Msg, feeAmount sdk.Coins, gasLimit uint64, accNums, accSeqs []uint64, chainID string, tc TestCase) {
   161  	suite.Run(fmt.Sprintf("Case %s", tc.desc), func() {
   162  		suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))
   163  		suite.txBuilder.SetFeeAmount(feeAmount)
   164  		suite.txBuilder.SetGasLimit(gasLimit)
   165  
   166  		// Theoretically speaking, ante handler unit tests should only test
   167  		// ante handlers, but here we sometimes also test the tx creation
   168  		// process.
   169  		tx, txErr := suite.CreateTestTx(privs, accNums, accSeqs, chainID)
   170  		newCtx, anteErr := suite.anteHandler(suite.ctx, tx, tc.simulate)
   171  
   172  		if tc.expPass {
   173  			suite.Require().NoError(txErr)
   174  			suite.Require().NoError(anteErr)
   175  			suite.Require().NotNil(newCtx)
   176  
   177  			suite.ctx = newCtx
   178  		} else {
   179  			switch {
   180  			case txErr != nil:
   181  				suite.Require().Error(txErr)
   182  				suite.Require().True(strings.Contains(txErr.Error(), tc.expErr.Error()))
   183  
   184  			case anteErr != nil:
   185  				suite.Require().Error(anteErr)
   186  				suite.Require().True(strings.Contains(anteErr.Error(), tc.expErr.Error()), anteErr.Error())
   187  
   188  			default:
   189  				suite.Fail("expected one of txErr,anteErr to be an error")
   190  			}
   191  		}
   192  	})
   193  }
   194  
   195  func TestAnteTestSuite(t *testing.T) {
   196  	suite.Run(t, new(AnteTestSuite))
   197  }