github.com/Finschia/finschia-sdk@v0.48.1/x/auth/ante/testutil_test.go (about) 1 package ante_test 2 3 import ( 4 "errors" 5 "fmt" 6 "testing" 7 8 "github.com/stretchr/testify/suite" 9 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 10 11 "github.com/Finschia/finschia-sdk/client" 12 "github.com/Finschia/finschia-sdk/client/tx" 13 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 14 "github.com/Finschia/finschia-sdk/simapp" 15 "github.com/Finschia/finschia-sdk/testutil/testdata" 16 sdk "github.com/Finschia/finschia-sdk/types" 17 "github.com/Finschia/finschia-sdk/types/tx/signing" 18 "github.com/Finschia/finschia-sdk/x/auth/ante" 19 xauthsigning "github.com/Finschia/finschia-sdk/x/auth/signing" 20 "github.com/Finschia/finschia-sdk/x/auth/types" 21 authtypes "github.com/Finschia/finschia-sdk/x/auth/types" 22 minttypes "github.com/Finschia/finschia-sdk/x/mint/types" 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.SimApp 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.SimApp, 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.MakeTestEncodingConfig() 58 // We're using TestMsg encoding in some tests, so register it here. 59 encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil) 60 testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry) 61 62 suite.clientCtx = client.Context{}. 63 WithTxConfig(encodingConfig.TxConfig) 64 65 anteHandler, err := ante.NewAnteHandler( 66 ante.HandlerOptions{ 67 AccountKeeper: suite.app.AccountKeeper, 68 BankKeeper: suite.app.BankKeeper, 69 FeegrantKeeper: suite.app.FeeGrantKeeper, 70 SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), 71 SigGasConsumer: ante.DefaultSigVerificationGasConsumer, 72 }, 73 ) 74 75 suite.Require().NoError(err) 76 suite.anteHandler = anteHandler 77 } 78 79 // CreateTestAccounts creates `numAccs` accounts, and return all relevant 80 // information about them including their private keys. 81 func (suite *AnteTestSuite) CreateTestAccounts(numAccs int) []TestAccount { 82 var accounts []TestAccount 83 84 for i := 0; i < numAccs; i++ { 85 priv, _, addr := testdata.KeyTestPubAddr() 86 acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr) 87 err := acc.SetAccountNumber(uint64(i)) 88 suite.Require().NoError(err) 89 suite.app.AccountKeeper.SetAccount(suite.ctx, acc) 90 someCoins := sdk.Coins{ 91 sdk.NewInt64Coin("atom", 10000000), 92 } 93 err = suite.app.BankKeeper.MintCoins(suite.ctx, minttypes.ModuleName, someCoins) 94 suite.Require().NoError(err) 95 96 err = suite.app.BankKeeper.SendCoinsFromModuleToAccount(suite.ctx, minttypes.ModuleName, addr, someCoins) 97 suite.Require().NoError(err) 98 99 accounts = append(accounts, TestAccount{acc, priv}) 100 } 101 102 return accounts 103 } 104 105 // CreateTestTx is a helper function to create a tx given multiple inputs. 106 func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (xauthsigning.Tx, error) { 107 // First round: we gather all the signer infos. We use the "set empty 108 // signature" hack to do that. 109 var sigsV2 []signing.SignatureV2 110 for i, priv := range privs { 111 sigV2 := signing.SignatureV2{ 112 PubKey: priv.PubKey(), 113 Data: &signing.SingleSignatureData{ 114 SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), 115 Signature: nil, 116 }, 117 Sequence: accSeqs[i], 118 } 119 120 sigsV2 = append(sigsV2, sigV2) 121 } 122 err := suite.txBuilder.SetSignatures(sigsV2...) 123 if err != nil { 124 return nil, err 125 } 126 127 // Second round: all signer infos are set, so each signer can sign. 128 sigsV2 = []signing.SignatureV2{} 129 for i, priv := range privs { 130 signerData := xauthsigning.SignerData{ 131 ChainID: chainID, 132 AccountNumber: accNums[i], 133 Sequence: accSeqs[i], 134 } 135 sigV2, err := tx.SignWithPrivKey( 136 suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData, 137 suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i]) 138 if err != nil { 139 return nil, err 140 } 141 142 sigsV2 = append(sigsV2, sigV2) 143 } 144 err = suite.txBuilder.SetSignatures(sigsV2...) 145 if err != nil { 146 return nil, err 147 } 148 149 return suite.txBuilder.GetTx(), nil 150 } 151 152 // TestCase represents a test case used in test tables. 153 type TestCase struct { 154 desc string 155 malleate func() 156 simulate bool 157 expPass bool 158 expErr error 159 } 160 161 // CreateTestTx is a helper function to create a tx given multiple inputs. 162 func (suite *AnteTestSuite) RunTestCase(privs []cryptotypes.PrivKey, msgs []sdk.Msg, feeAmount sdk.Coins, gasLimit uint64, accNums, accSeqs []uint64, chainID string, tc TestCase) { 163 suite.Run(fmt.Sprintf("Case %s", tc.desc), func() { 164 suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...)) 165 suite.txBuilder.SetFeeAmount(feeAmount) 166 suite.txBuilder.SetGasLimit(gasLimit) 167 168 // Theoretically speaking, ante handler unit tests should only test 169 // ante handlers, but here we sometimes also test the tx creation 170 // process. 171 tx, txErr := suite.CreateTestTx(privs, accNums, accSeqs, chainID) 172 newCtx, anteErr := suite.anteHandler(suite.ctx, tx, tc.simulate) 173 174 if tc.expPass { 175 suite.Require().NoError(txErr) 176 suite.Require().NoError(anteErr) 177 suite.Require().NotNil(newCtx) 178 179 suite.ctx = newCtx 180 } else { 181 switch { 182 case txErr != nil: 183 suite.Require().Error(txErr) 184 suite.Require().True(errors.Is(txErr, tc.expErr)) 185 186 case anteErr != nil: 187 suite.Require().Error(anteErr) 188 suite.Require().True(errors.Is(anteErr, tc.expErr)) 189 190 default: 191 suite.Fail("expected one of txErr,anteErr to be an error") 192 } 193 } 194 }) 195 } 196 197 func TestAnteTestSuite(t *testing.T) { 198 suite.Run(t, new(AnteTestSuite)) 199 }