diff --git a/tests/systemtests/.gitignore b/tests/systemtests/.gitignore index 22873da42dfe..1769c53afc59 100644 --- a/tests/systemtests/.gitignore +++ b/tests/systemtests/.gitignore @@ -1,2 +1,3 @@ /testnet /binaries +foo/ diff --git a/tests/systemtests/README.md b/tests/systemtests/README.md index ac9fcb49cdc9..d2aa7112d5be 100644 --- a/tests/systemtests/README.md +++ b/tests/systemtests/README.md @@ -1,61 +1,48 @@ -# Testing +# System tests -Test framework for system tests. -Starts and interacts with a (multi node) blockchain in Go. -Supports +Go black box tests that setup and interact with a local blockchain. The system test [framework](../../systemtests) +works with the compiled binary of the chain artifact only. +To get up to speed, checkout the [getting started guide](../../systemtests/getting_started.md). -* CLI -* Servers -* Events -* RPC +Beside the Go tests and testdata files, this directory can contain the following directories: -Uses: +* `binaries` - cache for binary +* `testnet` - node files -* testify -* gjson -* sjson +Please make sure to not add or push them to git. -Server and client side are executed on the host machine. +## Execution -## Developer +Build a new binary from current branch and copy it to the `tests/systemtests/binaries` folder by running system tests. +In project root: -### Test strategy - -System tests cover the full stack via cli and a running (multi node) network. They are more expensive (in terms of time/ cpu) -to run compared to unit or integration tests. -Therefore, we focus on the **critical path** and do not cover every condition. - -## How to use - -Read the [getting_started.md](getting_started.md) guide to get started. - -### Execute a single test - -```sh -go test -tags system_test -count=1 -v . --run TestStakeUnstake -verbose +```shell +make test-system ``` -Test cli parameters - -* `-verbose` verbose output -* `-wait-time` duration - time to wait for chain events (default 30s) -* `-nodes-count` int - number of nodes in the cluster (default 4) +Or via manual steps -# Port ranges +```shell +make build +mkdir -p ./tests/systemtests/binaries +cp ./build/simd ./tests/systemtests/binaries/ +``` -With *n* nodes: +### Manual test run -* `26657` - `26657+n` - RPC -* `1317` - `1317+n` - API -* `9090` - `9090+n` - GRPC -* `16656` - `16656+n` - P2P +```shell +go test -v -mod=readonly -failfast -tags='system_test' --run TestStakeUnstake ./... --verbose +``` -For example Node *3* listens on `26660` for RPC calls +### Working with macOS -## Resources +Most tests should function seamlessly. However, the file [upgrade_test.go](upgrade_test.go) includes a **build annotation** for Linux only. -* [gjson query syntax](https://github.com/tidwall/gjson#path-syntax) +For the system upgrade test, an older version of the binary is utilized to perform a chain upgrade. This artifact is retrieved from a Docker container built for Linux. -## Disclaimer +To circumvent this limitation locally: +1. Checkout and build the older version of the artifact from a specific tag for your OS. +2. Place the built artifact into the `binaries` folder. +3. Ensure that the filename, including the version, is correct. -This is based on the system test framework in [wasmd](https://github.com/CosmWasm/wasmd) built by Confio. +With the cached artifact in place, the test will use this file instead of attempting to pull it from Docker. \ No newline at end of file diff --git a/tests/systemtests/account_test.go b/tests/systemtests/account_test.go index db4fed5c7126..1b66199ba026 100644 --- a/tests/systemtests/account_test.go +++ b/tests/systemtests/account_test.go @@ -8,6 +8,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) func TestAccountCreation(t *testing.T) { @@ -18,24 +20,24 @@ func TestAccountCreation(t *testing.T) { // when accountB is sending funds to accountA, // AccountB should be created - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // add genesis account with some tokens account1Addr := cli.AddKey("account1") account2Addr := cli.AddKey("account2") require.NotEqual(t, account1Addr, account2Addr) - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", account1Addr, "10000000stake"}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // query account1 rsp := cli.CustomQuery("q", "auth", "account", account1Addr) assert.Equal(t, account1Addr, gjson.Get(rsp, "account.value.address").String(), rsp) rsp1 := cli.RunAndWait("tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from="+account1Addr, "--fees=1stake") - RequireTxSuccess(t, rsp1) + systest.RequireTxSuccess(t, rsp1) // query account2 assertNotFound := func(t assert.TestingT, err error, msgAndArgs ...interface{}) (ok bool) { @@ -44,7 +46,7 @@ func TestAccountCreation(t *testing.T) { _ = cli.WithRunErrorMatcher(assertNotFound).CustomQuery("q", "auth", "account", account2Addr) rsp3 := cli.RunAndWait("tx", "bank", "send", account2Addr, account1Addr, "1000stake", "--from="+account2Addr, "--fees=1stake") - RequireTxSuccess(t, rsp3) + systest.RequireTxSuccess(t, rsp3) // query account2 to make sure its created rsp4 := cli.CustomQuery("q", "auth", "account", account2Addr) @@ -54,19 +56,19 @@ func TestAccountCreation(t *testing.T) { } func TestAccountsMigration(t *testing.T) { - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) - legacyAddress := cli.GetKeyAddr(defaultSrcAddr) + legacyAddress := cli.GetKeyAddr("node0") // Create a receiver account receiverName := "receiver-account" receiverAddress := cli.AddKey(receiverName) require.NotEmpty(t, receiverAddress) - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", receiverAddress, "1000000stake"}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // Get pubkey pubKeyValue := cli.GetPubKeyByCustomField(legacyAddress, "address") @@ -99,7 +101,7 @@ func TestAccountsMigration(t *testing.T) { fmt.Sprintf("--account-init-msg=%s", accountInitMsg), fmt.Sprintf("--from=%s", legacyAddress), "--fees=1stake") - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // 3. Now the account should be existed, query the account Sequence rsp = cli.CustomQuery("q", "accounts", "query", legacyAddress, "cosmos.accounts.defaults.base.v1.QuerySequence", "{}") @@ -121,7 +123,7 @@ func TestAccountsMigration(t *testing.T) { transferAmount+"stake", fmt.Sprintf("--from=%s", legacyAddress), "--fees=1stake") - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // Verify the balances after the transaction newLegacyBalance := cli.QueryBalance(legacyAddress, "stake") @@ -151,5 +153,5 @@ func TestAccountsMigration(t *testing.T) { rsp = cli.RunAndWait("tx", "accounts", "execute", legacyAddress, "cosmos.accounts.defaults.base.v1.MsgSwapPubKey", swapKeyMsg, fmt.Sprintf("--from=%s", legacyAddress), "--fees=1stake") - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) } diff --git a/tests/systemtests/auth_test.go b/tests/systemtests/auth_test.go index feae7f4f1bee..afc366de65d8 100644 --- a/tests/systemtests/auth_test.go +++ b/tests/systemtests/auth_test.go @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" "github.com/tidwall/sjson" + + systest "cosmossdk.io/systemtests" ) const ( @@ -20,10 +22,10 @@ func TestAuthSignAndBroadcastTxCmd(t *testing.T) { // scenario: test auth sign and broadcast commands // given a running chain - sut.ResetChain(t) - require.GreaterOrEqual(t, sut.NodesCount(), 2) + systest.Sut.ResetChain(t) + require.GreaterOrEqual(t, systest.Sut.NodesCount(), 2) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator addresses val1Addr := cli.GetKeyAddr("node0") @@ -32,7 +34,7 @@ func TestAuthSignAndBroadcastTxCmd(t *testing.T) { val2Addr := cli.GetKeyAddr("node1") require.NotEmpty(t, val2Addr) - sut.StartChain(t) + systest.Sut.StartChain(t) var transferAmount, feeAmount int64 = 1000, 1 @@ -40,37 +42,37 @@ func TestAuthSignAndBroadcastTxCmd(t *testing.T) { // run bank tx send with --generate-only flag sendTx := generateBankSendTx(t, cli, val1Addr, val2Addr, transferAmount, feeAmount, "") - txFile := StoreTempFile(t, []byte(fmt.Sprintf("%s\n", sendTx))) + txFile := systest.StoreTempFile(t, []byte(fmt.Sprintf("%s\n", sendTx))) // query node0 account details - signTxCmd := []string{"tx", "sign", txFile.Name(), "--from=" + val1Addr, "--chain-id=" + cli.chainID} + signTxCmd := []string{"tx", "sign", txFile.Name(), "--from=" + val1Addr, "--chain-id=" + cli.ChainID()} testSignTxBroadcast(t, cli, signTxCmd, "sign tx", val1Addr, val2Addr, transferAmount, feeAmount) // test broadcast with empty public key in signed tx - rsp := cli.RunCommandWithArgs(cli.withTXFlags("tx", "sign", txFile.Name(), "--from="+val1Addr)...) + rsp := cli.RunCommandWithArgs(cli.WithTXFlags("tx", "sign", txFile.Name(), "--from="+val1Addr)...) updated, err := sjson.Set(rsp, "auth_info.signer_infos.0.public_key", nil) require.NoError(t, err) - newSignFile := StoreTempFile(t, []byte(updated)) + newSignFile := systest.StoreTempFile(t, []byte(updated)) broadcastCmd := []string{"tx", "broadcast", newSignFile.Name()} - rsp = cli.RunCommandWithArgs(cli.withTXFlags(broadcastCmd...)...) - RequireTxFailure(t, rsp) + rsp = cli.RunCommandWithArgs(cli.WithTXFlags(broadcastCmd...)...) + systest.RequireTxFailure(t, rsp) // test sign-batch tx command // generate another bank send tx with less amount newAmount := int64(100) sendTx2 := generateBankSendTx(t, cli, val1Addr, val2Addr, newAmount, feeAmount, "") - tx2File := StoreTempFile(t, []byte(fmt.Sprintf("%s\n", sendTx2))) + tx2File := systest.StoreTempFile(t, []byte(fmt.Sprintf("%s\n", sendTx2))) - signBatchCmd := []string{"tx", "sign-batch", txFile.Name(), tx2File.Name(), "--from=" + val1Addr, "--chain-id=" + cli.chainID} + signBatchCmd := []string{"tx", "sign-batch", txFile.Name(), tx2File.Name(), "--from=" + val1Addr, "--chain-id=" + cli.ChainID()} sendAmount := transferAmount + newAmount fees := feeAmount * 2 testSignTxBroadcast(t, cli, signBatchCmd, "sign-batch tx", val1Addr, val2Addr, sendAmount, fees) } -func testSignTxBroadcast(t *testing.T, cli *CLIWrapper, txCmd []string, prefix, fromAddr, toAddr string, amount, fees int64) { +func testSignTxBroadcast(t *testing.T, cli *systest.CLIWrapper, txCmd []string, prefix, fromAddr, toAddr string, amount, fees int64) { t.Helper() fromAddrBal := cli.QueryBalance(fromAddr, authTestDenom) @@ -109,21 +111,21 @@ func testSignTxBroadcast(t *testing.T, cli *CLIWrapper, txCmd []string, prefix, cmd := append(txCmd, tc.extraArgs...) // run tx sign command and verify signatures count - rsp = cli.RunCommandWithArgs(cli.withKeyringFlags(cmd...)...) + rsp = cli.RunCommandWithArgs(cli.WithKeyringFlags(cmd...)...) signatures := gjson.Get(rsp, "signatures").Array() require.Len(t, signatures, 1) - signFile := StoreTempFile(t, []byte(rsp)) + signFile := systest.StoreTempFile(t, []byte(rsp)) // validate signature - rsp = cli.RunCommandWithArgs(cli.withKeyringFlags("tx", "validate-signatures", signFile.Name(), "--from="+fromAddr, "--chain-id="+cli.chainID)...) + rsp = cli.RunCommandWithArgs(cli.WithKeyringFlags("tx", "validate-signatures", signFile.Name(), "--from="+fromAddr, "--chain-id="+cli.ChainID())...) require.Contains(t, rsp, "[OK]") // run broadcast tx command broadcastCmd := []string{"tx", "broadcast", signFile.Name()} rsp = cli.RunAndWait(broadcastCmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query balance and confirm transaction expVal1Bal := fromAddrBal - amount - fees @@ -141,10 +143,10 @@ func TestAuthQueryTxCmds(t *testing.T) { // scenario: test query tx and txs commands // given a running chain - sut.ResetChain(t) - require.GreaterOrEqual(t, sut.NodesCount(), 2) + systest.Sut.ResetChain(t) + require.GreaterOrEqual(t, systest.Sut.NodesCount(), 2) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator addresses val1Addr := cli.GetKeyAddr("node0") @@ -153,12 +155,12 @@ func TestAuthQueryTxCmds(t *testing.T) { val2Addr := cli.GetKeyAddr("node1") require.NotEmpty(t, val2Addr) - sut.StartChain(t) + systest.Sut.StartChain(t) // do a bank transfer and use it for query txs feeAmount := "2stake" rsp := cli.RunAndWait("tx", "bank", "send", val1Addr, val2Addr, "10000stake", "--fees="+feeAmount) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // parse values from above tx height := gjson.Get(rsp, "height").String() @@ -231,8 +233,8 @@ func TestAuthMultisigTxCmds(t *testing.T) { // scenario: test auth multisig related tx commands // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") @@ -248,11 +250,11 @@ func TestAuthMultisigTxCmds(t *testing.T) { acc3Addr := cli.AddKey("acc3") require.NotEqual(t, acc1Addr, acc3Addr) - out := cli.RunCommandWithArgs(cli.withKeyringFlags("keys", "add", "multi", "--multisig=acc1,acc2,acc3", "--multisig-threshold=2")...) + out := cli.RunCommandWithArgs(cli.WithKeyringFlags("keys", "add", "multi", "--multisig=acc1,acc2,acc3", "--multisig-threshold=2")...) multiAddr := gjson.Get(out, "address").String() require.NotEmpty(t, multiAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) // fund multisig address some amount var initialAmount, transferAmount, feeAmount int64 = 10000, 100, 1 @@ -265,10 +267,10 @@ func TestAuthMultisigTxCmds(t *testing.T) { // run bank tx send with --generate-only flag sendTx := generateBankSendTx(t, cli, multiAddr, valAddr, transferAmount, feeAmount, "") - txFile := StoreTempFile(t, []byte(sendTx)) + txFile := systest.StoreTempFile(t, []byte(sendTx)) - signTxCmd := cli.withKeyringFlags("tx", "sign", txFile.Name(), "--multisig="+multiAddr, "--chain-id="+cli.chainID) - multiSignTxCmd := cli.withKeyringFlags("tx", "multisign", txFile.Name(), "multi", "--chain-id="+cli.chainID) + signTxCmd := cli.WithKeyringFlags("tx", "sign", txFile.Name(), "--multisig="+multiAddr, "--chain-id="+cli.ChainID()) + multiSignTxCmd := cli.WithKeyringFlags("tx", "multisign", txFile.Name(), "multi", "--chain-id="+cli.ChainID()) testMultisigTxBroadcast(t, cli, multiSigTxInput{ "multisign", @@ -287,10 +289,10 @@ func TestAuthMultisigTxCmds(t *testing.T) { // generate two send transactions in single file multiSendTx := fmt.Sprintf("%s\n%s", sendTx, sendTx) - multiTxFile := StoreTempFile(t, []byte(multiSendTx)) + multiTxFile := systest.StoreTempFile(t, []byte(multiSendTx)) - signBatchTxCmd := cli.withKeyringFlags("tx", "sign-batch", multiTxFile.Name(), "--multisig="+multiAddr, "--signature-only", "--chain-id="+cli.chainID) - multiSignBatchTxCmd := cli.withKeyringFlags("tx", "multisign-batch", multiTxFile.Name(), "multi", "--chain-id="+cli.chainID) + signBatchTxCmd := cli.WithKeyringFlags("tx", "sign-batch", multiTxFile.Name(), "--multisig="+multiAddr, "--signature-only", "--chain-id="+cli.ChainID()) + multiSignBatchTxCmd := cli.WithKeyringFlags("tx", "multisign-batch", multiTxFile.Name(), "multi", "--chain-id="+cli.ChainID()) // as we done couple of bank transactions as batch, // transferred amount will be twice @@ -311,7 +313,7 @@ func TestAuthMultisigTxCmds(t *testing.T) { }) } -func generateBankSendTx(t *testing.T, cli *CLIWrapper, fromAddr, toAddr string, amount, fees int64, memo string) string { +func generateBankSendTx(t *testing.T, cli *systest.CLIWrapper, fromAddr, toAddr string, amount, fees int64, memo string) string { t.Helper() bankSendGenCmd := []string{ @@ -322,7 +324,7 @@ func generateBankSendTx(t *testing.T, cli *CLIWrapper, fromAddr, toAddr string, "--note=" + memo, } - return cli.RunCommandWithArgs(cli.withTXFlags(bankSendGenCmd...)...) + return cli.RunCommandWithArgs(cli.WithTXFlags(bankSendGenCmd...)...) } type multiSigTxInput struct { @@ -338,7 +340,7 @@ type multiSigTxInput struct { feeAmount int64 } -func testMultisigTxBroadcast(t *testing.T, cli *CLIWrapper, i multiSigTxInput) { +func testMultisigTxBroadcast(t *testing.T, cli *systest.CLIWrapper, i multiSigTxInput) { t.Helper() multiAddrBal := cli.QueryBalance(i.multiAddr, authTestDenom) @@ -372,23 +374,23 @@ func testMultisigTxBroadcast(t *testing.T, cli *CLIWrapper, i multiSigTxInput) { cmd := i.multiSignCmd for _, acc := range tc.signingAccs { rsp := cli.RunCommandWithArgs(append(i.signCmd, "--from="+acc)...) - signFile := StoreTempFile(t, []byte(rsp)) + signFile := systest.StoreTempFile(t, []byte(rsp)) cmd = append(cmd, signFile.Name()) } rsp := cli.RunCommandWithArgs(cmd...) - multiSignFile := StoreTempFile(t, []byte(rsp)) + multiSignFile := systest.StoreTempFile(t, []byte(rsp)) // run broadcast tx command broadcastCmd := []string{"tx", "broadcast", multiSignFile.Name()} if tc.expErrMsg != "" { - rsp = cli.RunCommandWithArgs(cli.withTXFlags(broadcastCmd...)...) - RequireTxFailure(t, rsp) + rsp = cli.RunCommandWithArgs(cli.WithTXFlags(broadcastCmd...)...) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, tc.expErrMsg) return } rsp = cli.RunAndWait(broadcastCmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query balance and confirm transaction expMultiBal := multiAddrBal - i.transferAmount - i.feeAmount @@ -406,10 +408,10 @@ func TestAuxSigner(t *testing.T) { // scenario: test tx with direct aux sign mode // given a running chain - sut.ResetChain(t) - require.GreaterOrEqual(t, sut.NodesCount(), 2) + systest.Sut.ResetChain(t) + require.GreaterOrEqual(t, systest.Sut.NodesCount(), 2) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator addresses val1Addr := cli.GetKeyAddr("node0") @@ -418,7 +420,7 @@ func TestAuxSigner(t *testing.T) { val2Addr := cli.GetKeyAddr("node1") require.NotEmpty(t, val2Addr) - sut.StartChain(t) + systest.Sut.StartChain(t) bankSendCmd := []string{"tx", "bank", "send", val1Addr, val2Addr, "10000stake", "--from=" + val1Addr} @@ -467,7 +469,7 @@ func TestAuxSigner(t *testing.T) { return false } - _ = cli.WithRunErrorMatcher(assertTxOutput).Run(cli.withTXFlags(cmd...)...) + _ = cli.WithRunErrorMatcher(assertTxOutput).Run(cli.WithTXFlags(cmd...)...) }) } } @@ -475,7 +477,7 @@ func TestAuxSigner(t *testing.T) { func TestTxEncodeandDecode(t *testing.T) { // scenario: test tx encode and decode commands - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address val1Addr := cli.GetKeyAddr("node0") @@ -483,7 +485,7 @@ func TestTxEncodeandDecode(t *testing.T) { memoText := "testmemo" sendTx := generateBankSendTx(t, cli, val1Addr, val1Addr, 100, 1, memoText) - txFile := StoreTempFile(t, []byte(sendTx)) + txFile := systest.StoreTempFile(t, []byte(sendTx)) // run encode command encodedText := cli.RunCommandWithArgs("tx", "encode", txFile.Name()) @@ -501,45 +503,45 @@ func TestTxWithFeePayer(t *testing.T) { // check tx executed ok // check fees had been deducted from feePayers balance - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose).WithRunErrorsIgnored() + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose).WithRunErrorsIgnored() // add sender and feePayer accounts senderAddr := cli.AddKey("sender") - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", senderAddr, "10000000stake"}, ) feePayerAddr := cli.AddKey("feePayer") - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", feePayerAddr, "10000000stake"}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // send a tx with FeePayer without his signature - rsp := cli.RunCommandWithArgs(cli.withTXFlags( + rsp := cli.RunCommandWithArgs(cli.WithTXFlags( "tx", "bank", "send", senderAddr, "cosmos108jsm625z3ejy63uef2ke7t67h6nukt4ty93nr", "1000stake", "--fees", "1000000stake", "--fee-payer", feePayerAddr, )...) - RequireTxFailure(t, rsp, "invalid number of signatures") + systest.RequireTxFailure(t, rsp, "invalid number of signatures") // send tx with feePayers signature - rsp = cli.RunCommandWithArgs(cli.withTXFlags( + rsp = cli.RunCommandWithArgs(cli.WithTXFlags( "tx", "bank", "send", senderAddr, "cosmos108jsm625z3ejy63uef2ke7t67h6nukt4ty93nr", "1000stake", "--fees", "1000000stake", "--fee-payer", feePayerAddr, "--generate-only", )...) - tempFile := StoreTempFile(t, []byte(rsp)) + tempFile := systest.StoreTempFile(t, []byte(rsp)) - rsp = cli.RunCommandWithArgs(cli.withTXFlags( + rsp = cli.RunCommandWithArgs(cli.WithTXFlags( "tx", "sign", tempFile.Name(), "--from", senderAddr, "--sign-mode", "amino-json", )...) - tempFile = StoreTempFile(t, []byte(rsp)) + tempFile = systest.StoreTempFile(t, []byte(rsp)) - rsp = cli.RunCommandWithArgs(cli.withTXFlags( + rsp = cli.RunCommandWithArgs(cli.WithTXFlags( "tx", "sign", tempFile.Name(), "--from", feePayerAddr, "--sign-mode", "amino-json", )...) - tempFile = StoreTempFile(t, []byte(rsp)) + tempFile = systest.StoreTempFile(t, []byte(rsp)) rsp = cli.RunAndWait([]string{"tx", "broadcast", tempFile.Name()}...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // Query to check fee has been deducted from feePayer balance := cli.QueryBalance(feePayerAddr, authTestDenom) diff --git a/tests/systemtests/authz_test.go b/tests/systemtests/authz_test.go index f3e0ec748c8b..902b6631e8f8 100644 --- a/tests/systemtests/authz_test.go +++ b/tests/systemtests/authz_test.go @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) const ( @@ -29,8 +31,8 @@ func TestAuthzGrantTxCmd(t *testing.T) { // scenario: test authz grant command // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address which will be used as granter granterAddr := cli.GetKeyAddr("node0") @@ -49,7 +51,7 @@ func TestAuthzGrantTxCmd(t *testing.T) { grantee6Addr := cli.AddKey("grantee6") require.NotEqual(t, granterAddr, grantee6Addr) - sut.StartChain(t) + systest.Sut.StartChain(t) // query validator operator address rsp := cli.CustomQuery("q", "staking", "validators") @@ -202,7 +204,7 @@ func TestAuthzGrantTxCmd(t *testing.T) { if tc.expErrMsg != "" { if tc.queryTx { rsp := cli.Run(cmd...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, tc.expErrMsg) } else { assertErr := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { @@ -216,7 +218,7 @@ func TestAuthzGrantTxCmd(t *testing.T) { return } rsp := cli.RunAndWait(cmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query granter-grantee grants resp := cli.CustomQuery("q", "authz", "grants", granterAddr, tc.grantee) @@ -237,8 +239,8 @@ func TestAuthzExecSendAuthorization(t *testing.T) { // scenario: test authz exec send authorization // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address which will be used as granter granterAddr := cli.GetKeyAddr("node0") @@ -256,12 +258,12 @@ func TestAuthzExecSendAuthorization(t *testing.T) { var initialAmount int64 = 10000000 initialBalance := fmt.Sprintf("%d%s", initialAmount, testDenom) - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", granteeAddr, initialBalance}, []string{"genesis", "add-genesis-account", allowedAddr, initialBalance}, []string{"genesis", "add-genesis-account", newAccount, initialBalance}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // query balances granterBal := cli.QueryBalance(granterAddr, testDenom) @@ -271,7 +273,7 @@ func TestAuthzExecSendAuthorization(t *testing.T) { require.Equal(t, initialAmount, allowedAddrBal) var spendLimitAmount int64 = 1000 - expirationTime := time.Now().Add(time.Second * 10).Unix() + expirationTime := time.Now().Add(systest.Sut.BlockTime() * 10) // test exec send authorization @@ -279,10 +281,10 @@ func TestAuthzExecSendAuthorization(t *testing.T) { rsp := cli.RunAndWait("tx", "authz", "grant", granteeAddr, "send", "--spend-limit="+fmt.Sprintf("%d%s", spendLimitAmount, testDenom), "--allow-list="+allowedAddr, - "--expiration="+fmt.Sprintf("%d", expirationTime), + "--expiration="+fmt.Sprintf("%d", expirationTime.Unix()), "--fees=1"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // reduce fees of above tx from granter balance granterBal-- @@ -329,12 +331,12 @@ func TestAuthzExecSendAuthorization(t *testing.T) { cmd := msgSendExec(t, granterAddr, tc.grantee, tc.toAddr, testDenom, tc.amount) if tc.expErrMsg != "" { rsp := cli.Run(cmd...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, tc.expErrMsg) return } rsp := cli.RunAndWait(cmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // check granter balance equals to granterBal - transferredAmount expGranterBal := granterBal - tc.amount @@ -349,11 +351,15 @@ func TestAuthzExecSendAuthorization(t *testing.T) { } // test grant expiry - time.Sleep(time.Second * 10) + require.Eventually(t, func() bool { + resp := cli.CustomQuery("q", "authz", "grants", granterAddr, granteeAddr) + grants := gjson.Get(resp, "grants").Array() + return len(grants) == 0 + }, 10*systest.Sut.BlockTime(), 200*time.Millisecond) execSendCmd := msgSendExec(t, granterAddr, granteeAddr, allowedAddr, testDenom, 10) rsp = cli.Run(execSendCmd...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, "authorization not found") } @@ -369,30 +375,33 @@ func TestAuthzExecGenericAuthorization(t *testing.T) { // query balances granterBal := cli.QueryBalance(granterAddr, testDenom) - expirationTime := time.Now().Add(time.Second * 5).Unix() - execSendCmd := msgSendExec(t, granterAddr, granteeAddr, allowedAddr, testDenom, 10) + expirationTime := time.Now().Add(systest.Sut.BlockTime() * 5) // create generic authorization grant - rsp := cli.RunAndWait("tx", "authz", "grant", granteeAddr, "generic", + _ = cli.RunAndWait("tx", "authz", "grant", granteeAddr, "generic", "--msg-type="+msgSendTypeURL, - "--expiration="+fmt.Sprintf("%d", expirationTime), + "--expiration="+fmt.Sprintf("%d", expirationTime.Unix()), "--fees=1"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) granterBal-- - rsp = cli.RunAndWait(execSendCmd...) - RequireTxSuccess(t, rsp) + execSendCmd := msgSendExec(t, granterAddr, granteeAddr, allowedAddr, testDenom, 10) + _ = cli.RunAndWait(execSendCmd...) // check granter balance equals to granterBal - transferredAmount expGranterBal := granterBal - 10 require.Equal(t, expGranterBal, cli.QueryBalance(granterAddr, testDenom)) - time.Sleep(time.Second * 5) - - // check grants after expiration - resp := cli.CustomQuery("q", "authz", "grants", granterAddr, granteeAddr) - grants := gjson.Get(resp, "grants").Array() - require.Len(t, grants, 0) + // wait until block after expired has passed + maxWait := max(expirationTime.Sub(time.Now()), time.Nanosecond) + 5*systest.Sut.BlockTime() + require.Eventually(t, func() bool { + resp := cli.CustomQuery("q", "authz", "grants", granterAddr, granteeAddr) + grants := gjson.Get(resp, "grants").Array() + if len(grants) != 0 { + t.Log(time.Now().Format(time.RFC3339)) + t.Log(resp) + } + return len(grants) == 0 + }, maxWait, 200*time.Millisecond) } func TestAuthzExecDelegateAuthorization(t *testing.T) { @@ -419,7 +428,7 @@ func TestAuthzExecDelegateAuthorization(t *testing.T) { "--allowed-validators="+val1Addr, "--fees=1"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // reduce fees of above tx from granter balance granterBal-- @@ -478,12 +487,12 @@ func TestAuthzExecDelegateAuthorization(t *testing.T) { cmd := append(append(execCmdArgs, execMsg.Name()), "--from="+tc.grantee) if tc.expErrMsg != "" { rsp := cli.Run(cmd...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, tc.expErrMsg) return } rsp := cli.RunAndWait(cmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // check granter balance equals to granterBal - transferredAmount expGranterBal := granterBal - tc.amount @@ -508,7 +517,7 @@ func TestAuthzExecUndelegateAuthorization(t *testing.T) { // delegate some tokens rsp = cli.RunAndWait("tx", "staking", "delegate", val1Addr, "10000"+testDenom, "--from="+granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query delegated tokens count resp := cli.CustomQuery("q", "staking", "delegation", granterAddr, val1Addr) @@ -518,7 +527,7 @@ func TestAuthzExecUndelegateAuthorization(t *testing.T) { "--allowed-validators="+val1Addr, "--fees=1"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) undelegateTestCases := []struct { name string @@ -552,12 +561,12 @@ func TestAuthzExecUndelegateAuthorization(t *testing.T) { cmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + tc.grantee} if tc.expErrMsg != "" { rsp := cli.Run(cmd...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, tc.expErrMsg) return } rsp := cli.RunAndWait(cmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query delegation and check balance reduced expectedAmount := delegatedAmount - tc.amount @@ -569,7 +578,7 @@ func TestAuthzExecUndelegateAuthorization(t *testing.T) { // revoke existing grant rsp = cli.RunAndWait("tx", "authz", "revoke", granteeAddr, msgUndelegateTypeURL, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // check grants between granter and grantee after revoking resp = cli.CustomQuery("q", "authz", "grants", granterAddr, granteeAddr) @@ -592,14 +601,14 @@ func TestAuthzExecRedelegateAuthorization(t *testing.T) { // delegate some tokens rsp = cli.RunAndWait("tx", "staking", "delegate", val1Addr, "10000"+testDenom, "--from="+granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // test exec redelegate authorization rsp = cli.RunAndWait("tx", "authz", "grant", granteeAddr, "redelegate", fmt.Sprintf("--allowed-validators=%s,%s", val1Addr, val2Addr), "--fees=1"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) var redelegationAmount int64 = 10 @@ -609,7 +618,7 @@ func TestAuthzExecRedelegateAuthorization(t *testing.T) { redelegateCmd := []string{"tx", "authz", "exec", execMsg.Name(), "--from=" + granteeAddr, "--gas=500000", "--fees=10stake"} rsp = cli.RunAndWait(redelegateCmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query new delegation and check balance increased resp := cli.CustomQuery("q", "staking", "delegation", granterAddr, val2Addr) @@ -618,7 +627,7 @@ func TestAuthzExecRedelegateAuthorization(t *testing.T) { // revoke all existing grants rsp = cli.RunAndWait("tx", "authz", "revoke-all", "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // check grants after revoking resp = cli.CustomQuery("q", "authz", "grants-by-granter", granterAddr) @@ -640,28 +649,28 @@ func TestAuthzGRPCQueries(t *testing.T) { rsp := cli.RunAndWait("tx", "authz", "grant", grantee1Addr, "send", "--spend-limit=10000"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) grant1 := fmt.Sprintf(`"authorization":{"@type":"%s","spend_limit":[{"denom":"%s","amount":"10000"}],"allow_list":[]},"expiration":null`, sendAuthzTypeURL, testDenom) rsp = cli.RunAndWait("tx", "authz", "grant", grantee2Addr, "send", "--spend-limit=1000"+testDenom, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) grant2 := fmt.Sprintf(`"authorization":{"@type":"%s","spend_limit":[{"denom":"%s","amount":"1000"}],"allow_list":[]},"expiration":null`, sendAuthzTypeURL, testDenom) rsp = cli.RunAndWait("tx", "authz", "grant", grantee2Addr, "generic", "--msg-type="+msgVoteTypeURL, "--from", granterAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) grant3 := fmt.Sprintf(`"authorization":{"@type":"%s","msg":"%s"},"expiration":null`, genericAuthzTypeURL, msgVoteTypeURL) rsp = cli.RunAndWait("tx", "authz", "grant", grantee2Addr, "generic", "--msg-type="+msgDelegateTypeURL, "--from", grantee1Addr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) grant4 := fmt.Sprintf(`"authorization":{"@type":"%s","msg":"%s"},"expiration":null`, genericAuthzTypeURL, msgDelegateTypeURL) - baseurl := sut.APIAddress() + baseurl := systest.Sut.APIAddress() // test query grant grpc endpoint grantURL := baseurl + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s&msg_type_url=%s" @@ -671,7 +680,7 @@ func TestAuthzGRPCQueries(t *testing.T) { invalidMsgTypeOutput := `{"code":2, "message":"codespace authz code 2: authorization not found: authorization not found for invalidMsg type", "details":[]}` expGrantOutput := fmt.Sprintf(`{"grants":[{%s}],"pagination":null}`, grant1) - grantTestCases := []RestTestCase{ + grantTestCases := []systest.RestTestCase{ { "invalid granter address", fmt.Sprintf(grantURL, "invalid_granter", grantee1Addr, msgSendTypeURL), @@ -710,12 +719,12 @@ func TestAuthzGRPCQueries(t *testing.T) { }, } - RunRestQueries(t, grantTestCases) + systest.RunRestQueries(t, grantTestCases...) // test query grants grpc endpoint grantsURL := baseurl + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s" - grantsTestCases := []RestTestCase{ + grantsTestCases := []systest.RestTestCase{ { "expect single grant", fmt.Sprintf(grantsURL, granterAddr, grantee1Addr), @@ -748,7 +757,7 @@ func TestAuthzGRPCQueries(t *testing.T) { }, } - RunRestQueries(t, grantsTestCases) + systest.RunRestQueries(t, grantsTestCases...) // test query grants by granter grpc endpoint grantsByGranterURL := baseurl + "/cosmos/authz/v1beta1/grants/granter/%s" @@ -757,7 +766,7 @@ func TestAuthzGRPCQueries(t *testing.T) { granterQueryOutput := fmt.Sprintf(`{"grants":[{"granter":"%s","grantee":"%s",%s}],"pagination":{"next_key":null,"total":"1"}}`, grantee1Addr, grantee2Addr, grant4) - granterTestCases := []RestTestCase{ + granterTestCases := []systest.RestTestCase{ { "invalid granter account address", fmt.Sprintf(grantsByGranterURL, "invalid address"), @@ -778,13 +787,13 @@ func TestAuthzGRPCQueries(t *testing.T) { }, } - RunRestQueries(t, granterTestCases) + systest.RunRestQueries(t, granterTestCases...) // test query grants by grantee grpc endpoint grantsByGranteeURL := baseurl + "/cosmos/authz/v1beta1/grants/grantee/%s" grantee1GrantsOutput := fmt.Sprintf(`{"grants":[{"granter":"%s","grantee":"%s",%s}],"pagination":{"next_key":null,"total":"1"}}`, granterAddr, grantee1Addr, grant1) - granteeTestCases := []RestTestCase{ + granteeTestCases := []systest.RestTestCase{ { "invalid grantee account address", fmt.Sprintf(grantsByGranteeURL, "invalid address"), @@ -805,16 +814,16 @@ func TestAuthzGRPCQueries(t *testing.T) { }, } - RunRestQueries(t, granteeTestCases) + systest.RunRestQueries(t, granteeTestCases...) } -func setupChain(t *testing.T) (*CLIWrapper, string, string) { +func setupChain(t *testing.T) (*systest.CLIWrapper, string, string) { t.Helper() - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) - require.GreaterOrEqual(t, cli.nodesCount, 2) + require.GreaterOrEqual(t, systest.Sut.NodesCount(), 2) // get validators' address which will be used as granter and grantee granterAddr := cli.GetKeyAddr("node0") @@ -822,7 +831,7 @@ func setupChain(t *testing.T) (*CLIWrapper, string, string) { granteeAddr := cli.GetKeyAddr("node1") require.NotEmpty(t, granteeAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) return cli, granterAddr, granteeAddr } diff --git a/tests/systemtests/bank_test.go b/tests/systemtests/bank_test.go index d776bc06a874..4591233f5cc8 100644 --- a/tests/systemtests/bank_test.go +++ b/tests/systemtests/bank_test.go @@ -11,23 +11,24 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" "github.com/tidwall/sjson" + + systest "cosmossdk.io/systemtests" ) func TestBankSendTxCmd(t *testing.T) { // scenario: test bank send command // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") - require.NotEmpty(t, valAddr) // add new key receiverAddr := cli.AddKey("account1") denom := "stake" - sut.StartChain(t) + systest.Sut.StartChain(t) // query validator balance and make sure it has enough balance var transferAmount int64 = 1000 @@ -40,7 +41,7 @@ func TestBankSendTxCmd(t *testing.T) { rsp := cli.Run(append(bankSendCmdArgs, "--fees=1stake")...) txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) // check valaddr balance equals to valBalance-(transferedAmount+feeAmount) require.Equal(t, valBalance-(transferAmount+1), cli.QueryBalance(valAddr, denom)) // check receiver balance equals to transferAmount @@ -50,7 +51,7 @@ func TestBankSendTxCmd(t *testing.T) { insufficientCmdArgs := bankSendCmdArgs[0 : len(bankSendCmdArgs)-1] insufficientCmdArgs = append(insufficientCmdArgs, fmt.Sprintf("%d%s", valBalance, denom), "--fees=10stake") rsp = cli.Run(insufficientCmdArgs...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, rsp, "insufficient funds") // test tx bank send with unauthorized signature @@ -58,13 +59,12 @@ func TestBankSendTxCmd(t *testing.T) { require.Len(t, gotOutputs, 1) code := gjson.Get(gotOutputs[0].(string), "code") require.True(t, code.Exists()) - require.Greater(t, code.Int(), int64(0)) + require.Greater(t, code.Int(), int64(0), gotOutputs[0]) return false } - invalidCli := cli - invalidCli.chainID = cli.chainID + "a" // set invalid chain-id + invalidCli := cli.WithChainID(cli.ChainID() + "a") // set invalid chain-id rsp = invalidCli.WithRunErrorMatcher(assertUnauthorizedErr).Run(bankSendCmdArgs...) - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) // test tx bank send generate only assertGenOnlyOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { @@ -100,8 +100,8 @@ func TestBankMultiSendTxCmd(t *testing.T) { // scenario: test bank multi-send command // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // add genesis account with some tokens account1Addr := cli.AddKey("account1") account2Addr := cli.AddKey("account2") @@ -111,11 +111,11 @@ func TestBankMultiSendTxCmd(t *testing.T) { denom := "stake" var initialAmount int64 = 10000000 initialBalance := fmt.Sprintf("%d%s", initialAmount, denom) - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", account1Addr, initialBalance}, []string{"genesis", "add-genesis-account", account2Addr, initialBalance}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // query accounts balances account1Bal := cli.QueryBalance(account1Addr, denom) @@ -172,7 +172,7 @@ func TestBankMultiSendTxCmd(t *testing.T) { rsp := cli.Run(tc.cmdArgs...) txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) // check account1 balance equals to account1Bal - transferredAmount*no_of_accounts - fees expAcc1Balance := account1Bal - (1000 * 2) - 1 require.Equal(t, expAcc1Balance, cli.QueryBalance(account1Addr, denom)) @@ -193,8 +193,8 @@ func TestBankGRPCQueries(t *testing.T) { // scenario: test bank grpc gateway queries // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // update bank denom metadata in genesis atomDenomMetadata := `{"description":"The native staking token of the Cosmos Hub.","denom_units":[{"denom":"uatom","exponent":0,"aliases":["microatom"]},{"denom":"atom","exponent":6,"aliases":["ATOM"]}],"base":"uatom","display":"atom","name":"Cosmos Hub Atom","symbol":"ATOM","uri":"","uri_hash":""}` @@ -202,7 +202,7 @@ func TestBankGRPCQueries(t *testing.T) { bankDenomMetadata := fmt.Sprintf("[%s,%s]", atomDenomMetadata, ethDenomMetadata) - sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { + systest.Sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { state, err := sjson.SetRawBytes(genesis, "app_state.bank.denom_metadata", []byte(bankDenomMetadata)) require.NoError(t, err) return state @@ -212,13 +212,13 @@ func TestBankGRPCQueries(t *testing.T) { account1Addr := cli.AddKey("account1") newDenom := "newdenom" initialAmount := "10000000" - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", account1Addr, "10000000stake," + initialAmount + newDenom}, ) // start chain - sut.StartChain(t) - baseurl := sut.APIAddress() + systest.Sut.StartChain(t) + baseurl := systest.Sut.APIAddress() // test supply grpc endpoint supplyUrl := baseurl + "/cosmos/bank/v1beta1/supply" @@ -229,7 +229,7 @@ func TestBankGRPCQueries(t *testing.T) { bogusDenomOutput := `{"denom":"foobar","amount":"0"}` blockHeightHeader := "x-cosmos-block-height" - blockHeight := sut.CurrentHeight() + blockHeight := systest.Sut.CurrentHeight() supplyTestCases := []struct { name string @@ -275,14 +275,14 @@ func TestBankGRPCQueries(t *testing.T) { for _, tc := range supplyTestCases { t.Run(tc.name, func(t *testing.T) { - resp := GetRequestWithHeaders(t, tc.url, tc.headers, tc.expHttpCode) + resp := systest.GetRequestWithHeaders(t, tc.url, tc.headers, tc.expHttpCode) require.Contains(t, string(resp), tc.expOut) }) } // test denom metadata endpoint denomMetadataUrl := baseurl + "/cosmos/bank/v1beta1/denoms_metadata" - dmTestCases := []RestTestCase{ + dmTestCases := []systest.RestTestCase{ { "test GRPC client metadata", denomMetadataUrl, @@ -303,13 +303,13 @@ func TestBankGRPCQueries(t *testing.T) { }, } - RunRestQueries(t, dmTestCases) + systest.RunRestQueries(t, dmTestCases...) // test bank balances endpoint balanceUrl := baseurl + "/cosmos/bank/v1beta1/balances/" allBalancesOutput := `{"balances":[` + specificDenomOutput + `,{"denom":"stake","amount":"10000000"}],"pagination":{"next_key":null,"total":"2"}}` - balanceTestCases := []RestTestCase{ + balanceTestCases := []systest.RestTestCase{ { "test GRPC total account balance", balanceUrl + account1Addr, @@ -330,5 +330,5 @@ func TestBankGRPCQueries(t *testing.T) { }, } - RunRestQueries(t, balanceTestCases) + systest.RunRestQueries(t, balanceTestCases...) } diff --git a/tests/systemtests/circuit_test.go b/tests/systemtests/circuit_test.go index e6b660e22eca..291c52aba565 100644 --- a/tests/systemtests/circuit_test.go +++ b/tests/systemtests/circuit_test.go @@ -11,6 +11,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) var someMsgs = []string{"/cosmos.bank.v1beta1.MsgSend", "/cosmos.bank.v1beta1.MsgMultiSend"} @@ -19,10 +21,10 @@ func TestCircuitCommands(t *testing.T) { // scenario: test circuit commands // given a running chain - sut.ResetChain(t) - require.GreaterOrEqual(t, sut.NodesCount(), 2) + systest.Sut.ResetChain(t) + require.GreaterOrEqual(t, systest.Sut.NodesCount(), 2) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator addresses superAdmin := cli.GetKeyAddr("node0") @@ -33,13 +35,14 @@ func TestCircuitCommands(t *testing.T) { // short voting period // update expedited voting period to avoid validation error - sut.ModifyGenesisJSON( + votingPeriod := 5 * time.Second + systest.Sut.ModifyGenesisJSON( t, - SetGovVotingPeriod(t, time.Second*8), - SetGovExpeditedVotingPeriod(t, time.Second*7), + systest.SetGovVotingPeriod(t, votingPeriod), + systest.SetGovExpeditedVotingPeriod(t, votingPeriod-time.Second), ) - sut.StartChain(t) + systest.Sut.StartChain(t) allMsgsAcc := cli.AddKey("allMsgsAcc") require.NotEmpty(t, allMsgsAcc) @@ -51,11 +54,11 @@ func TestCircuitCommands(t *testing.T) { var amount int64 = 100000 denom := "stake" rsp := cli.FundAddress(allMsgsAcc, fmt.Sprintf("%d%s", amount, denom)) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) require.Equal(t, amount, cli.QueryBalance(allMsgsAcc, denom)) rsp = cli.FundAddress(someMsgsAcc, fmt.Sprintf("%d%s", amount, denom)) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) require.Equal(t, amount, cli.QueryBalance(someMsgsAcc, denom)) // query gov module account address @@ -77,24 +80,23 @@ func TestCircuitCommands(t *testing.T) { "deposit": "10000000stake", "summary": "A short summary of my proposal" }`, govModAddr, superAdmin) - proposalFile := StoreTempFile(t, []byte(validProposal)) + proposalFile := systest.StoreTempFile(t, []byte(validProposal)) rsp = cli.RunAndWait("tx", "gov", "submit-proposal", proposalFile.Name(), "--from="+superAdmin) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // vote to proposal from two validators rsp = cli.RunAndWait("tx", "gov", "vote", "1", "yes", "--from="+superAdmin) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) rsp = cli.RunAndWait("tx", "gov", "vote", "1", "yes", "--from="+superAdmin2) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // wait for proposal to pass - time.Sleep(time.Second * 8) - - rsp = cli.CustomQuery("q", "circuit", "accounts") - - level := gjson.Get(rsp, fmt.Sprintf("accounts.#(address==%s).permissions.level", superAdmin)).String() - require.Equal(t, "LEVEL_SUPER_ADMIN", level) + require.Eventually(t, func() bool { + rsp = cli.CustomQuery("q", "circuit", "accounts") + level := gjson.Get(rsp, fmt.Sprintf("accounts.#(address==%s).permissions.level", superAdmin)).String() + return "LEVEL_SUPER_ADMIN" == level + }, votingPeriod+systest.Sut.BlockTime(), 200*time.Millisecond) authorizeTestCases := []struct { name string @@ -133,7 +135,7 @@ func TestCircuitCommands(t *testing.T) { permissionJSON = fmt.Sprintf(`{"level":%d,"limit_type_urls":["%s"]}`, tc.level, strings.Join(tc.limtTypeURLs[:], `","`)) } rsp = cli.RunAndWait("tx", "circuit", "authorize", tc.address, permissionJSON, "--from="+superAdmin) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query account permissions rsp = cli.CustomQuery("q", "circuit", "account", tc.address) @@ -157,7 +159,7 @@ func TestCircuitCommands(t *testing.T) { testCircuitTxCommand(t, cli, "reset", superAdmin, superAdmin2, allMsgsAcc, someMsgsAcc) } -func testCircuitTxCommand(t *testing.T, cli *CLIWrapper, txType, superAdmin, superAdmin2, allMsgsAcc, someMsgsAcc string) { +func testCircuitTxCommand(t *testing.T, cli *systest.CLIWrapper, txType, superAdmin, superAdmin2, allMsgsAcc, someMsgsAcc string) { t.Helper() disableTestCases := []struct { @@ -206,7 +208,7 @@ func testCircuitTxCommand(t *testing.T, cli *CLIWrapper, txType, superAdmin, sup cmd := []string{"tx", "circuit", txType, "--from=" + tc.fromAddr} cmd = append(cmd, tc.disableMsgs...) rsp := cli.RunAndWait(cmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // execute given type transaction rsp = cli.CustomQuery("q", "circuit", "disabled-list") @@ -228,15 +230,16 @@ func testCircuitTxCommand(t *testing.T, cli *CLIWrapper, txType, superAdmin, sup // test given msg transaction to confirm for _, tx := range tc.executeTxs { tx = append(tx, "--fees=2stake") - rsp = cli.RunCommandWithArgs(cli.withTXFlags(tx...)...) + rsp = cli.RunCommandWithArgs(cli.WithTXFlags(tx...)...) if txType == "disable" { - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) require.Contains(t, gjson.Get(rsp, "raw_log").String(), "tx type not allowed") - } else { - RequireTxSuccess(t, rsp) + continue } + systest.RequireTxSuccess(t, rsp) // wait for sometime to avoid sequence error - time.Sleep(time.Second * 2) + _, found := cli.AwaitTxCommitted(rsp) + require.True(t, found) } }) } diff --git a/tests/systemtests/cli.go b/tests/systemtests/cli.go deleted file mode 100644 index 423b27dc57f5..000000000000 --- a/tests/systemtests/cli.go +++ /dev/null @@ -1,483 +0,0 @@ -package systemtests - -import ( - "fmt" - "io" - "os" - "os/exec" - "path/filepath" - "slices" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type ( - // blocks until next block is minted - awaitNextBlock func(t *testing.T, timeout ...time.Duration) int64 - // RunErrorAssert is custom type that is satisfies by testify matchers as well - RunErrorAssert func(t assert.TestingT, err error, msgAndArgs ...interface{}) (ok bool) -) - -// CLIWrapper provides a more convenient way to interact with the CLI binary from the Go tests -type CLIWrapper struct { - t *testing.T - nodeAddress string - chainID string - homeDir string - fees string - Debug bool - assertErrorFn RunErrorAssert - awaitNextBlock awaitNextBlock - expTXCommitted bool - execBinary string - nodesCount int -} - -// NewCLIWrapper constructor -func NewCLIWrapper(t *testing.T, sut *SystemUnderTest, verbose bool) *CLIWrapper { - t.Helper() - return NewCLIWrapperX( - t, - sut.execBinary, - sut.rpcAddr, - sut.chainID, - sut.AwaitNextBlock, - sut.nodesCount, - filepath.Join(WorkDir, sut.outputDir), - "1"+sdk.DefaultBondDenom, - verbose, - assert.NoError, - true, - ) -} - -// NewCLIWrapperX extended constructor -func NewCLIWrapperX( - t *testing.T, - execBinary string, - nodeAddress string, - chainID string, - awaiter awaitNextBlock, - nodesCount int, - homeDir string, - fees string, - debug bool, - assertErrorFn RunErrorAssert, - expTXCommitted bool, -) *CLIWrapper { - t.Helper() - if strings.TrimSpace(execBinary) == "" { - t.Fatal("name of executable binary must not be empty") - } - return &CLIWrapper{ - t: t, - execBinary: execBinary, - nodeAddress: nodeAddress, - chainID: chainID, - homeDir: homeDir, - Debug: debug, - awaitNextBlock: awaiter, - nodesCount: nodesCount, - fees: fees, - assertErrorFn: assertErrorFn, - expTXCommitted: expTXCommitted, - } -} - -// WithRunErrorsIgnored does not fail on any error -func (c CLIWrapper) WithRunErrorsIgnored() CLIWrapper { - return c.WithRunErrorMatcher(func(t assert.TestingT, err error, msgAndArgs ...interface{}) bool { - return true - }) -} - -// WithRunErrorMatcher assert function to ensure run command error value -func (c CLIWrapper) WithRunErrorMatcher(f RunErrorAssert) CLIWrapper { - return *NewCLIWrapperX( - c.t, - c.execBinary, - c.nodeAddress, - c.chainID, - c.awaitNextBlock, - c.nodesCount, - c.homeDir, - c.fees, - c.Debug, - f, - c.expTXCommitted, - ) -} - -func (c CLIWrapper) WithNodeAddress(nodeAddr string) CLIWrapper { - return *NewCLIWrapperX( - c.t, - c.execBinary, - nodeAddr, - c.chainID, - c.awaitNextBlock, - c.nodesCount, - c.homeDir, - c.fees, - c.Debug, - c.assertErrorFn, - c.expTXCommitted, - ) -} - -func (c CLIWrapper) WithAssertTXUncommitted() CLIWrapper { - return *NewCLIWrapperX( - c.t, - c.execBinary, - c.nodeAddress, - c.chainID, - c.awaitNextBlock, - c.nodesCount, - c.homeDir, - c.fees, - c.Debug, - c.assertErrorFn, - false, - ) -} - -// Run main entry for executing cli commands. -// When configured, method blocks until tx is committed. -func (c CLIWrapper) Run(args ...string) string { - c.t.Helper() - if c.fees != "" && !slices.ContainsFunc(args, func(s string) bool { - return strings.HasPrefix(s, "--fees") - }) { - args = append(args, "--fees="+c.fees) // add default fee - } - args = c.withTXFlags(args...) - execOutput, ok := c.run(args) - if !ok { - return execOutput - } - rsp, committed := c.AwaitTxCommitted(execOutput, DefaultWaitTime) - c.t.Logf("tx committed: %v", committed) - require.Equal(c.t, c.expTXCommitted, committed, "expected tx committed: %v", c.expTXCommitted) - return rsp -} - -// RunAndWait runs a cli command and waits for the server result when the TX is executed -// It returns the result of the transaction. -func (c CLIWrapper) RunAndWait(args ...string) string { - rsp := c.Run(args...) - RequireTxSuccess(c.t, rsp) - txResult, found := c.AwaitTxCommitted(rsp) - require.True(c.t, found) - return txResult -} - -// RunCommandWithArgs use for run cli command, not tx -func (c CLIWrapper) RunCommandWithArgs(args ...string) string { - c.t.Helper() - execOutput, _ := c.run(args) - return execOutput -} - -// AwaitTxCommitted wait for tx committed on chain -// returns the server execution result and true when found within 3 blocks. -func (c CLIWrapper) AwaitTxCommitted(submitResp string, timeout ...time.Duration) (string, bool) { - c.t.Helper() - RequireTxSuccess(c.t, submitResp) - txHash := gjson.Get(submitResp, "txhash") - require.True(c.t, txHash.Exists()) - var txResult string - for i := 0; i < 3; i++ { // max blocks to wait for a commit - txResult = c.WithRunErrorsIgnored().CustomQuery("q", "tx", txHash.String()) - if code := gjson.Get(txResult, "code"); code.Exists() { - if code.Int() != 0 { // 0 = success code - c.t.Logf("+++ got error response code: %s\n", txResult) - } - return txResult, true - } - c.awaitNextBlock(c.t, timeout...) - } - return "", false -} - -// Keys wasmd keys CLI command -func (c CLIWrapper) Keys(args ...string) string { - args = c.withKeyringFlags(args...) - out, _ := c.run(args) - return out -} - -// CustomQuery main entrypoint for wasmd CLI queries -func (c CLIWrapper) CustomQuery(args ...string) string { - args = c.withQueryFlags(args...) - out, _ := c.run(args) - return out -} - -// execute shell command -func (c CLIWrapper) run(args []string) (output string, ok bool) { - c.t.Helper() - return c.runWithInput(args, nil) -} - -func (c CLIWrapper) runWithInput(args []string, input io.Reader) (output string, ok bool) { - c.t.Helper() - if c.Debug { - c.t.Logf("+++ running `%s %s`", c.execBinary, strings.Join(args, " ")) - } - gotOut, gotErr := func() (out []byte, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("recovered from panic: %v", r) - } - }() - cmd := exec.Command(locateExecutable(c.execBinary), args...) //nolint:gosec // test code only - cmd.Dir = WorkDir - cmd.Stdin = input - return cmd.CombinedOutput() - }() - - if c.Debug { - if gotErr != nil { - c.t.Logf("+++ ERROR output: %s - %s", gotOut, gotErr) - } else { - c.t.Logf("+++ output: %s", gotOut) - } - } - - ok = c.assertErrorFn(c.t, gotErr, string(gotOut)) - return strings.TrimSpace(string(gotOut)), ok -} - -func (c CLIWrapper) withQueryFlags(args ...string) []string { - args = append(args, "--output", "json") - return c.withChainFlags(args...) -} - -func (c CLIWrapper) withTXFlags(args ...string) []string { - args = append(args, - "--broadcast-mode", "sync", - "--output", "json", - "--yes", - "--chain-id", c.chainID, - ) - args = c.withKeyringFlags(args...) - return c.withChainFlags(args...) -} - -func (c CLIWrapper) withKeyringFlags(args ...string) []string { - r := append(args, - "--home", c.homeDir, - "--keyring-backend", "test", - ) - for _, v := range args { - if v == "-a" || v == "--address" { // show address only - return r - } - } - return append(r, "--output", "json") -} - -func (c CLIWrapper) withChainFlags(args ...string) []string { - return append(args, - "--node", c.nodeAddress, - ) -} - -// WasmExecute send MsgExecute to a contract -func (c CLIWrapper) WasmExecute(contractAddr, msg, from string, args ...string) string { - cmd := append([]string{"tx", "wasm", "execute", contractAddr, msg, "--from", from}, args...) - return c.Run(cmd...) -} - -// AddKey add key to default keyring. Returns address -func (c CLIWrapper) AddKey(name string) string { - cmd := c.withKeyringFlags("keys", "add", name, "--no-backup") - out, _ := c.run(cmd) - addr := gjson.Get(out, "address").String() - require.NotEmpty(c.t, addr, "got %q", out) - return addr -} - -// AddKeyFromSeed recovers the key from given seed and add it to default keyring. Returns address -func (c CLIWrapper) AddKeyFromSeed(name, mnemoic string) string { - cmd := c.withKeyringFlags("keys", "add", name, "--recover") - out, _ := c.runWithInput(cmd, strings.NewReader(mnemoic)) - addr := gjson.Get(out, "address").String() - require.NotEmpty(c.t, addr, "got %q", out) - return addr -} - -// GetKeyAddr returns Acc address -func (c CLIWrapper) GetKeyAddr(name string) string { - cmd := c.withKeyringFlags("keys", "show", name, "-a") - out, _ := c.run(cmd) - addr := strings.Trim(out, "\n") - require.NotEmpty(c.t, addr, "got %q", out) - return addr -} - -// GetKeyAddrPrefix returns key address with Beach32 prefix encoding for a key (acc|val|cons) -func (c CLIWrapper) GetKeyAddrPrefix(name, prefix string) string { - cmd := c.withKeyringFlags("keys", "show", name, "-a", "--bech="+prefix) - out, _ := c.run(cmd) - addr := strings.Trim(out, "\n") - require.NotEmpty(c.t, addr, "got %q", out) - return addr -} - -// GetPubKeyByCustomField returns pubkey in base64 by custom field -func (c CLIWrapper) GetPubKeyByCustomField(addr, field string) string { - keysListOutput := c.Keys("keys", "list") - keysList := gjson.Parse(keysListOutput) - - var pubKeyValue string - keysList.ForEach(func(_, value gjson.Result) bool { - if value.Get(field).String() == addr { - pubKeyJSON := gjson.Parse(value.Get("pubkey").String()) - pubKeyValue = pubKeyJSON.Get("key").String() - return false - } - return true - }) - return pubKeyValue -} - -const defaultSrcAddr = "node0" - -// FundAddress sends the token amount to the destination address -func (c CLIWrapper) FundAddress(destAddr, amount string) string { - require.NotEmpty(c.t, destAddr) - require.NotEmpty(c.t, amount) - cmd := []string{"tx", "bank", "send", defaultSrcAddr, destAddr, amount} - rsp := c.Run(cmd...) - RequireTxSuccess(c.t, rsp) - return rsp -} - -// QueryBalances queries all balances for an account. Returns json response -// Example:`{"balances":[{"denom":"node0token","amount":"1000000000"},{"denom":"stake","amount":"400000003"}],"pagination":{}}` -func (c CLIWrapper) QueryBalances(addr string) string { - return c.CustomQuery("q", "bank", "balances", addr) -} - -// QueryBalance returns balance amount for given denom. -// 0 when not found -func (c CLIWrapper) QueryBalance(addr, denom string) int64 { - raw := c.CustomQuery("q", "bank", "balance", addr, denom) - require.Contains(c.t, raw, "amount", raw) - return gjson.Get(raw, "balance.amount").Int() -} - -// QueryTotalSupply returns total amount of tokens for a given denom. -// 0 when not found -func (c CLIWrapper) QueryTotalSupply(denom string) int64 { - raw := c.CustomQuery("q", "bank", "total-supply") - require.Contains(c.t, raw, "amount", raw) - return gjson.Get(raw, fmt.Sprintf("supply.#(denom==%q).amount", denom)).Int() -} - -// SubmitGovProposal submit a gov v1 proposal -func (c CLIWrapper) SubmitGovProposal(proposalJson string, args ...string) string { - if len(args) == 0 { - args = []string{"--from=" + defaultSrcAddr} - } - - pathToProposal := filepath.Join(c.t.TempDir(), "proposal.json") - err := os.WriteFile(pathToProposal, []byte(proposalJson), os.FileMode(0o744)) - require.NoError(c.t, err) - c.t.Log("Submit upgrade proposal") - return c.Run(append([]string{"tx", "gov", "submit-proposal", pathToProposal}, args...)...) -} - -// SubmitAndVoteGovProposal submit proposal, let all validators vote yes and return proposal id -func (c CLIWrapper) SubmitAndVoteGovProposal(proposalJson string, args ...string) string { - rsp := c.SubmitGovProposal(proposalJson, args...) - RequireTxSuccess(c.t, rsp) - raw := c.CustomQuery("q", "gov", "proposals", "--depositor", c.GetKeyAddr(defaultSrcAddr)) - proposals := gjson.Get(raw, "proposals.#.id").Array() - require.NotEmpty(c.t, proposals, raw) - ourProposalID := proposals[len(proposals)-1].String() // last is ours - for i := 0; i < c.nodesCount; i++ { - go func(i int) { // do parallel - c.t.Logf("Voting: validator %d\n", i) - rsp = c.Run("tx", "gov", "vote", ourProposalID, "yes", "--from", c.GetKeyAddr(fmt.Sprintf("node%d", i))) - RequireTxSuccess(c.t, rsp) - }(i) - } - return ourProposalID -} - -// Version returns the current version of the client binary -func (c CLIWrapper) Version() string { - v, ok := c.run([]string{"version"}) - require.True(c.t, ok) - return v -} - -// RequireTxSuccess require the received response to contain the success code -func RequireTxSuccess(t *testing.T, got string) { - t.Helper() - code, details := parseResultCode(t, got) - require.Equal(t, int64(0), code, "non success tx code : %s", details) -} - -// RequireTxFailure require the received response to contain any failure code and the passed msgsgs -func RequireTxFailure(t *testing.T, got string, containsMsgs ...string) { - t.Helper() - code, details := parseResultCode(t, got) - require.NotEqual(t, int64(0), code, details) - for _, msg := range containsMsgs { - require.Contains(t, details, msg) - } -} - -func parseResultCode(t *testing.T, got string) (int64, string) { - t.Helper() - code := gjson.Get(got, "code") - require.True(t, code.Exists(), "got response: %q", got) - - details := got - if log := gjson.Get(got, "raw_log"); log.Exists() && len(log.String()) != 0 { - details = log.String() - } - return code.Int(), details -} - -var ( - // ErrOutOfGasMatcher requires error with "out of gas" message - ErrOutOfGasMatcher RunErrorAssert = func(t assert.TestingT, err error, args ...interface{}) bool { - const oogMsg = "out of gas" - return expErrWithMsg(t, err, args, oogMsg) - } - // ErrTimeoutMatcher requires time out message - ErrTimeoutMatcher RunErrorAssert = func(t assert.TestingT, err error, args ...interface{}) bool { - const expMsg = "timed out waiting for tx to be included in a block" - return expErrWithMsg(t, err, args, expMsg) - } - // ErrPostFailedMatcher requires post failed - ErrPostFailedMatcher RunErrorAssert = func(t assert.TestingT, err error, args ...interface{}) bool { - const expMsg = "post failed" - return expErrWithMsg(t, err, args, expMsg) - } -) - -func expErrWithMsg(t assert.TestingT, err error, args []interface{}, expMsg string) bool { - if ok := assert.Error(t, err, args); !ok { - return false - } - var found bool - for _, v := range args { - if strings.Contains(fmt.Sprintf("%s", v), expMsg) { - found = true - break - } - } - assert.True(t, found, "expected %q but got: %s", expMsg, args) - return false // always abort -} diff --git a/tests/systemtests/cometbft_client_test.go b/tests/systemtests/cometbft_client_test.go index 6e0668ff71c7..732b39a480ae 100644 --- a/tests/systemtests/cometbft_client_test.go +++ b/tests/systemtests/cometbft_client_test.go @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" + systest "cosmossdk.io/systemtests" + "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -21,75 +23,78 @@ import ( ) func TestQueryNodeInfo(t *testing.T) { - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) res, err := qc.GetNodeInfo(context.Background(), &cmtservice.GetNodeInfoRequest{}) assert.NoError(t, err) - v := NewCLIWrapper(t, sut, true).Version() + v := systest.NewCLIWrapper(t, systest.Sut, true).Version() assert.Equal(t, res.ApplicationVersion.Version, v) + baseurl := systest.Sut.APIAddress() // TODO: we should be adding a way to distinguish a v2. Eventually we should skip some v2 system depending on the consensus engine we want to test - restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/node_info"))) + restRes := systest.GetRequest(t, must(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/node_info"))) assert.NoError(t, err) assert.Equal(t, gjson.GetBytes(restRes, "application_version.version").String(), res.ApplicationVersion.Version) } func TestQuerySyncing(t *testing.T) { - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) res, err := qc.GetSyncing(context.Background(), &cmtservice.GetSyncingRequest{}) assert.NoError(t, err) - restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/syncing"))) + baseurl := systest.Sut.APIAddress() + restRes := systest.GetRequest(t, must(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/syncing"))) assert.Equal(t, gjson.GetBytes(restRes, "syncing").Bool(), res.Syncing) } func TestQueryLatestBlock(t *testing.T) { - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) res, err := qc.GetLatestBlock(context.Background(), &cmtservice.GetLatestBlockRequest{}) assert.NoError(t, err) assert.Contains(t, res.SdkBlock.Header.ProposerAddress, "cosmosvalcons") - _ = GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/blocks/latest"))) + baseurl := systest.Sut.APIAddress() + _ = systest.GetRequest(t, must(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/blocks/latest"))) } func TestQueryBlockByHeight(t *testing.T) { - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - sut.AwaitNBlocks(t, 2, time.Second*25) + systest.Sut.AwaitNBlocks(t, 2, time.Second*25) - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) res, err := qc.GetBlockByHeight(context.Background(), &cmtservice.GetBlockByHeightRequest{Height: 2}) assert.NoError(t, err) assert.Equal(t, res.SdkBlock.Header.Height, int64(2)) assert.Contains(t, res.SdkBlock.Header.ProposerAddress, "cosmosvalcons") - restRes := GetRequest(t, mustV(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/blocks/2"))) + baseurl := systest.Sut.APIAddress() + restRes := systest.GetRequest(t, must(url.JoinPath(baseurl, "/cosmos/base/tendermint/v1beta1/blocks/2"))) assert.Equal(t, gjson.GetBytes(restRes, "sdk_block.header.height").Int(), int64(2)) assert.Contains(t, gjson.GetBytes(restRes, "sdk_block.header.proposer_address").String(), "cosmosvalcons") } func TestQueryLatestValidatorSet(t *testing.T) { - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) - sut.ResetChain(t) - sut.StartChain(t) + if systest.Sut.NodesCount() < 2 { + t.Skip("not enough nodes") + return + } + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - vals := sut.RPCClient(t).Validators() + vals := systest.Sut.RPCClient(t).Validators() - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) res, err := qc.GetLatestValidatorSet(context.Background(), &cmtservice.GetLatestValidatorSetRequest{ Pagination: nil, }) @@ -104,17 +109,18 @@ func TestQueryLatestValidatorSet(t *testing.T) { assert.NoError(t, err) assert.Equal(t, len(res.Validators), 2) - restRes := GetRequest(t, fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=%d&pagination.limit=%d", baseurl, 0, 2)) + baseurl := systest.Sut.APIAddress() + restRes := systest.GetRequest(t, fmt.Sprintf("%s/cosmos/base/tendermint/v1beta1/validatorsets/latest?pagination.offset=%d&pagination.limit=%d", baseurl, 0, 2)) assert.Equal(t, len(gjson.GetBytes(restRes, "validators").Array()), 2) } func TestLatestValidatorSet(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - vals := sut.RPCClient(t).Validators() + vals := systest.Sut.RPCClient(t).Validators() - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) testCases := []struct { name string req *cmtservice.GetLatestValidatorSetRequest @@ -143,12 +149,12 @@ func TestLatestValidatorSet(t *testing.T) { } func TestLatestValidatorSet_GRPCGateway(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + baseurl := systest.Sut.APIAddress() - vals := sut.RPCClient(t).Validators() + vals := systest.Sut.RPCClient(t).Validators() testCases := []struct { name string @@ -163,12 +169,12 @@ func TestLatestValidatorSet_GRPCGateway(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if tc.expErr { - rsp := GetRequestWithHeaders(t, baseurl+tc.url, nil, http.StatusBadRequest) + rsp := systest.GetRequestWithHeaders(t, baseurl+tc.url, nil, http.StatusBadRequest) errMsg := gjson.GetBytes(rsp, "message").String() assert.Contains(t, errMsg, tc.expErrMsg) return } - rsp := GetRequest(t, baseurl+tc.url) + rsp := systest.GetRequest(t, baseurl+tc.url) assert.Equal(t, len(vals), int(gjson.GetBytes(rsp, "pagination.total").Int())) }) @@ -176,11 +182,11 @@ func TestLatestValidatorSet_GRPCGateway(t *testing.T) { } func TestValidatorSetByHeight(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) - vals := sut.RPCClient(t).Validators() + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) + vals := systest.Sut.RPCClient(t).Validators() testCases := []struct { name string @@ -207,15 +213,14 @@ func TestValidatorSetByHeight(t *testing.T) { } } -func TestValidatorSetByHeight_GRPCGateway(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) - - vals := sut.RPCClient(t).Validators() +func TestValidatorSetByHeight_GRPCRestGateway(t *testing.T) { + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) - baseurl := fmt.Sprintf("http://localhost:%d", apiPortStart) + vals := systest.Sut.RPCClient(t).Validators() - block := sut.AwaitNextBlock(t, time.Second*3) + baseurl := systest.Sut.APIAddress() + block := systest.Sut.AwaitNextBlock(t, time.Second*3) testCases := []struct { name string url string @@ -230,7 +235,7 @@ func TestValidatorSetByHeight_GRPCGateway(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - rsp := GetRequestWithHeaders(t, tc.url, nil, tc.expHttpCode) + rsp := systest.GetRequestWithHeaders(t, tc.url, nil, tc.expHttpCode) if tc.expErr { errMsg := gjson.GetBytes(rsp, "message").String() assert.Contains(t, errMsg, tc.expErrMsg) @@ -242,11 +247,9 @@ func TestValidatorSetByHeight_GRPCGateway(t *testing.T) { } func TestABCIQuery(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) - sut.AwaitNBlocks(t, 3) + systest.Sut.StartChain(t) - qc := cmtservice.NewServiceClient(sut.RPCClient(t)) + qc := cmtservice.NewServiceClient(systest.Sut.RPCClient(t)) cdc := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) testCases := []struct { name string @@ -328,3 +331,10 @@ func TestABCIQuery(t *testing.T) { }) } } + +func must[T any](r T, err error) T { + if err != nil { + panic(err) + } + return r +} diff --git a/tests/systemtests/distribution_test.go b/tests/systemtests/distribution_test.go index e074b89e7cf3..7e40589bf5da 100644 --- a/tests/systemtests/distribution_test.go +++ b/tests/systemtests/distribution_test.go @@ -7,7 +7,6 @@ import ( "net/http" "os" "path/filepath" - "regexp" "strings" "testing" @@ -15,6 +14,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" "github.com/tidwall/sjson" + + systest "cosmossdk.io/systemtests" ) const ( @@ -25,18 +26,18 @@ func TestWithdrawAllRewardsCmd(t *testing.T) { // scenario: test distribution withdraw all rewards command // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) newAddr := cli.AddKey("newAddr") require.NotEmpty(t, newAddr) var initialAmount int64 = 10000000 initialBalance := fmt.Sprintf("%d%s", initialAmount, distrTestDenom) - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", newAddr, initialBalance}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // query balance newAddrBal := cli.QueryBalance(newAddr, distrTestDenom) @@ -54,11 +55,11 @@ func TestWithdrawAllRewardsCmd(t *testing.T) { // delegate tokens to validator1 rsp = cli.RunAndWait("tx", "staking", "delegate", val1Addr, delegation, "--from="+newAddr, "--fees=1"+distrTestDenom) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // delegate tokens to validator2 rsp = cli.RunAndWait("tx", "staking", "delegate", val2Addr, delegation, "--from="+newAddr, "--fees=1"+distrTestDenom) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // check updated balance: newAddrBal - delegatedBal - fees expBal := newAddrBal - (delegationAmount * 2) - 2 @@ -101,32 +102,32 @@ func TestWithdrawAllRewardsCmd(t *testing.T) { // test withdraw-all-rewards transaction rsp = cli.RunAndWait(withdrawCmdArgs...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) } func TestDistrValidatorGRPCQueries(t *testing.T) { // scenario: test distribution validator grpc gateway queries // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) valOperAddr := cli.GetKeyAddrPrefix("node0", "val") require.NotEmpty(t, valOperAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) - sut.AwaitNBlocks(t, 3) + systest.Sut.AwaitNBlocks(t, 3) - baseurl := sut.APIAddress() + baseurl := systest.Sut.APIAddress() expectedAmountOutput := fmt.Sprintf(`{"denom":"%s","amount":"203.105000000000000000"}`, distrTestDenom) // test params grpc endpoint paramsURL := baseurl + "/cosmos/distribution/v1beta1/params" - paramsTestCases := []RestTestCase{ + paramsTestCases := []systest.RestTestCase{ { "gRPC request params", paramsURL, @@ -134,13 +135,13 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { `{"params":{"community_tax":"0.020000000000000000","base_proposer_reward":"0.000000000000000000","bonus_proposer_reward":"0.000000000000000000","withdraw_addr_enabled":true}}`, }, } - RunRestQueries(t, paramsTestCases) + systest.RunRestQueries(t, paramsTestCases...) // test validator distribution info grpc endpoint validatorsURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s` validatorsOutput := fmt.Sprintf(`{"operator_address":"%s","self_bond_rewards":[],"commission":[%s]}`, valAddr, expectedAmountOutput) - validatorsTestCases := []RestTestCase{ + validatorsTestCases := []systest.RestTestCase{ { "gRPC request validator with valid validator address", fmt.Sprintf(validatorsURL, valOperAddr), @@ -148,12 +149,12 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { validatorsOutput, }, } - TestRestQueryIgnoreNumbers(t, validatorsTestCases) + systest.TestRestQueryIgnoreNumbers(t, validatorsTestCases...) // test outstanding rewards grpc endpoint outstandingRewardsURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards` - rewardsTestCases := []RestTestCase{ + rewardsTestCases := []systest.RestTestCase{ { "gRPC request outstanding rewards with valid validator address", fmt.Sprintf(outstandingRewardsURL, valOperAddr), @@ -161,12 +162,12 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { fmt.Sprintf(`{"rewards":{"rewards":[%s]}}`, expectedAmountOutput), }, } - TestRestQueryIgnoreNumbers(t, rewardsTestCases) + systest.TestRestQueryIgnoreNumbers(t, rewardsTestCases...) // test validator commission grpc endpoint commissionURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/commission` - commissionTestCases := []RestTestCase{ + commissionTestCases := []systest.RestTestCase{ { "gRPC request commission with valid validator address", fmt.Sprintf(commissionURL, valOperAddr), @@ -174,13 +175,13 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { fmt.Sprintf(`{"commission":{"commission":[%s]}}`, expectedAmountOutput), }, } - TestRestQueryIgnoreNumbers(t, commissionTestCases) + systest.TestRestQueryIgnoreNumbers(t, commissionTestCases...) // test validator slashes grpc endpoint slashURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/slashes` invalidHeightOutput := `{"code":3, "message":"strconv.ParseUint: parsing \"-3\": invalid syntax", "details":[]}` - slashTestCases := []RestTestCase{ + slashTestCases := []systest.RestTestCase{ { "invalid start height", fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "-3", "3"), @@ -200,15 +201,15 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { `{"slashes":[],"pagination":{"next_key":null,"total":"0"}}`, }, } - RunRestQueries(t, slashTestCases) + systest.RunRestQueries(t, slashTestCases...) } func TestDistrDelegatorGRPCQueries(t *testing.T) { // scenario: test distribution validator gsrpc gateway queries // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") @@ -218,17 +219,12 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { // update commission rate of node0 validator // generate new gentx and copy it to genesis.json before starting network - rsp := cli.RunCommandWithArgs("genesis", "gentx", "node0", "100000000"+distrTestDenom, "--chain-id="+cli.chainID, "--commission-rate=0.01", "--home", sut.nodePath(0), "--keyring-backend=test") - // extract gentx path from above command output - re := regexp.MustCompile(`"(.*?\.json)"`) - match := re.FindStringSubmatch(rsp) - require.GreaterOrEqual(t, len(match), 1) - - updatedGentx := filepath.Join(WorkDir, match[1]) - updatedGentxBz, err := os.ReadFile(updatedGentx) // #nosec G304 + outFile := filepath.Join(t.TempDir(), "gentx.json") + rsp := cli.RunCommandWithArgs("genesis", "gentx", "node0", "100000000"+distrTestDenom, "--chain-id="+cli.ChainID(), "--commission-rate=0.01", "--home", systest.Sut.NodeDir(0), "--keyring-backend=test", "--output-document="+outFile) + updatedGentxBz, err := os.ReadFile(outFile) // #nosec G304 require.NoError(t, err) - sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { + systest.Sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { state, err := sjson.SetRawBytes(genesis, "app_state.genutil.gen_txs.0", updatedGentxBz) require.NoError(t, err) return state @@ -240,26 +236,26 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { var initialAmount int64 = 1000000000 initialBalance := fmt.Sprintf("%d%s", initialAmount, distrTestDenom) - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", delAddr, initialBalance}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // delegate some tokens to valOperAddr rsp = cli.RunAndWait("tx", "staking", "delegate", valOperAddr, "100000000"+distrTestDenom, "--from="+delAddr) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) - sut.AwaitNBlocks(t, 5) + systest.Sut.AwaitNBlocks(t, 5) - baseurl := sut.APIAddress() + baseurl := systest.Sut.APIAddress() // test delegator rewards grpc endpoint delegatorRewardsURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/rewards` expectedAmountOutput := `{"denom":"stake","amount":"0.121275000000000000"}` rewardsOutput := fmt.Sprintf(`{"rewards":[{"validator_address":"%s","reward":[%s]}],"total":[%s]}`, valOperAddr, expectedAmountOutput, expectedAmountOutput) - delegatorRewardsTestCases := []RestTestCase{ + delegatorRewardsTestCases := []systest.RestTestCase{ { "valid rewards request with valid delegator address", fmt.Sprintf(delegatorRewardsURL, delAddr), @@ -273,11 +269,11 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { fmt.Sprintf(`{"rewards":[%s]}`, expectedAmountOutput), }, } - TestRestQueryIgnoreNumbers(t, delegatorRewardsTestCases) + systest.TestRestQueryIgnoreNumbers(t, delegatorRewardsTestCases...) // test delegator validators grpc endpoint delegatorValsURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/validators` - valsTestCases := []RestTestCase{ + valsTestCases := []systest.RestTestCase{ { "gRPC request delegator validators with valid delegator address", fmt.Sprintf(delegatorValsURL, delAddr), @@ -285,11 +281,11 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { fmt.Sprintf(`{"validators":["%s"]}`, valOperAddr), }, } - RunRestQueries(t, valsTestCases) + systest.RunRestQueries(t, valsTestCases...) // test withdraw address grpc endpoint withdrawAddrURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/withdraw_address` - withdrawAddrTestCases := []RestTestCase{ + withdrawAddrTestCases := []systest.RestTestCase{ { "gRPC request withdraw address with valid delegator address", fmt.Sprintf(withdrawAddrURL, delAddr), @@ -297,5 +293,5 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { fmt.Sprintf(`{"withdraw_address":"%s"}`, delAddr), }, } - RunRestQueries(t, withdrawAddrTestCases) + systest.RunRestQueries(t, withdrawAddrTestCases...) } diff --git a/tests/systemtests/export_test.go b/tests/systemtests/export_test.go index 5d392d8ce10f..0f5f91176e78 100644 --- a/tests/systemtests/export_test.go +++ b/tests/systemtests/export_test.go @@ -6,32 +6,33 @@ import ( "fmt" "os" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) func TestExportCmd_WithHeight(t *testing.T) { - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) - sut.StartChain(t) + systest.Sut.StartChain(t) // Wait 10s for producing blocks - time.Sleep(10 * time.Second) + systest.Sut.AwaitNBlocks(t, 10) - sut.StopChain() + systest.Sut.StopChain() testCases := []struct { name string args []string expZeroHeight bool }{ - {"should export correct height", []string{"genesis", "export", "--home", sut.nodePath(0)}, false}, - {"should export correct height with --height", []string{"genesis", "export", "--height=5", "--home", sut.nodePath(0), "--log_level=disabled"}, false}, - {"should export height 0 with --for-zero-height", []string{"genesis", "export", "--for-zero-height=true", "--home", sut.nodePath(0)}, true}, + {"should export correct height", []string{"genesis", "export", "--home", systest.Sut.NodeDir(0)}, false}, + {"should export correct height with --height", []string{"genesis", "export", "--height=5", "--home", systest.Sut.NodeDir(0), "--log_level=disabled"}, false}, + {"should export height 0 with --for-zero-height", []string{"genesis", "export", "--for-zero-height=true", "--home", systest.Sut.NodeDir(0)}, true}, } for _, tc := range testCases { @@ -45,21 +46,21 @@ func TestExportCmd_WithHeight(t *testing.T) { // Check consensus params of exported state maxGas := gjson.Get(res, "consensus.params.block.max_gas").Int() - require.Equal(t, maxGas, int64(MaxGas)) + require.Equal(t, maxGas, int64(systest.MaxGas)) } } func TestExportCmd_WithFileFlag(t *testing.T) { - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) exportFile := "foobar.json" - sut.StartChain(t) + systest.Sut.StartChain(t) // Wait 10s for producing blocks - time.Sleep(10 * time.Second) + systest.Sut.AwaitNBlocks(t, 10) - sut.StopChain() + systest.Sut.StopChain() testCases := []struct { name string @@ -68,7 +69,7 @@ func TestExportCmd_WithFileFlag(t *testing.T) { errMsg string }{ {"invalid home dir", []string{"genesis", "export", "--home=foo"}, true, "no such file or directory"}, - {"should export state to the specified file", []string{"genesis", "export", fmt.Sprintf("--output-document=%s", exportFile), "--home", sut.nodePath(0)}, false, ""}, + {"should export state to the specified file", []string{"genesis", "export", fmt.Sprintf("--output-document=%s", exportFile), "--home", systest.Sut.NodeDir(0)}, false, ""}, } for _, tc := range testCases { diff --git a/tests/systemtests/fraud_test.go b/tests/systemtests/fraud_test.go index 0479f526cc2d..a4c0b7875d8e 100644 --- a/tests/systemtests/fraud_test.go +++ b/tests/systemtests/fraud_test.go @@ -11,6 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) func TestValidatorDoubleSign(t *testing.T) { @@ -18,35 +20,35 @@ func TestValidatorDoubleSign(t *testing.T) { // given: a running chain // when: a second instance with the same val key signs a block // then: the validator is removed from the active set and jailed forever - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) - sut.StartChain(t) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) + systest.Sut.StartChain(t) // Check the validator is in the active set rsp := cli.CustomQuery("q", "staking", "validators") t.Log(rsp) - validatorPubKey := LoadValidatorPubKeyForNode(t, sut, 0) - rpc, pkBz := sut.RPCClient(t), validatorPubKey.Bytes() + validatorPubKey := systest.LoadValidatorPubKeyForNode(t, systest.Sut, 0) + rpc, pkBz := systest.Sut.RPCClient(t), validatorPubKey.Bytes() - nodePowerBefore := QueryCometValidatorPower(rpc, pkBz) + nodePowerBefore := systest.QueryCometValidatorPower(rpc, pkBz) require.NotEmpty(t, nodePowerBefore) t.Logf("nodePowerBefore: %v", nodePowerBefore) - newNode := sut.AddFullnode(t, func(nodeNumber int, nodePath string) { - valKeyFile := filepath.Join(WorkDir, nodePath, "config", "priv_validator_key.json") + newNode := systest.Sut.AddFullnode(t, func(nodeNumber int, nodePath string) { + valKeyFile := filepath.Join(systest.WorkDir, nodePath, "config", "priv_validator_key.json") _ = os.Remove(valKeyFile) - _ = MustCopyFile(filepath.Join(WorkDir, sut.nodePath(0), "config", "priv_validator_key.json"), valKeyFile) + _ = systest.MustCopyFile(filepath.Join(systest.Sut.NodeDir(0), "config", "priv_validator_key.json"), valKeyFile) }) - sut.AwaitNodeUp(t, fmt.Sprintf("http://%s:%d", newNode.IP, newNode.RPCPort)) + systest.Sut.AwaitNodeUp(t, fmt.Sprintf("http://%s:%d", newNode.IP, newNode.RPCPort)) // let's wait some blocks to have evidence and update persisted var nodePowerAfter int64 = -1 for i := 0; i < 30; i++ { - sut.AwaitNextBlock(t) - if nodePowerAfter = QueryCometValidatorPower(rpc, pkBz); nodePowerAfter == 0 { + systest.Sut.AwaitNextBlock(t) + if nodePowerAfter = systest.QueryCometValidatorPower(rpc, pkBz); nodePowerAfter == 0 { break } - t.Logf("wait %d", sut.CurrentHeight()) + t.Logf("wait %d", systest.Sut.CurrentHeight()) } // then comet status updated require.Empty(t, nodePowerAfter) @@ -57,5 +59,5 @@ func TestValidatorDoubleSign(t *testing.T) { assert.True(t, gjson.Get(rsp, "validator.jailed").Bool(), rsp) // let's run for some blocks to confirm all good - sut.AwaitNBlocks(t, 5) + systest.Sut.AwaitNBlocks(t, 5) } diff --git a/tests/systemtests/genesis_io.go b/tests/systemtests/genesis_io.go deleted file mode 100644 index f3a61e54a2dd..000000000000 --- a/tests/systemtests/genesis_io.go +++ /dev/null @@ -1,55 +0,0 @@ -package systemtests - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// SetConsensusMaxGas max gas that can be consumed in a block -func SetConsensusMaxGas(t *testing.T, max int) GenesisMutator { - t.Helper() - return func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "consensus.params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, max))) - require.NoError(t, err) - return state - } -} - -func SetGovVotingPeriod(t *testing.T, period time.Duration) GenesisMutator { - t.Helper() - return func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.gov.params.voting_period", []byte(fmt.Sprintf("%q", period.String()))) - require.NoError(t, err) - return state - } -} - -func SetGovExpeditedVotingPeriod(t *testing.T, period time.Duration) GenesisMutator { - t.Helper() - return func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.gov.params.expedited_voting_period", []byte(fmt.Sprintf("%q", period.String()))) - require.NoError(t, err) - return state - } -} - -// GetGenesisBalance return the balance amount for an address from the given genesis json -func GetGenesisBalance(rawGenesis []byte, addr string) sdk.Coins { - var r []sdk.Coin - balances := gjson.GetBytes(rawGenesis, fmt.Sprintf(`app_state.bank.balances.#[address==%q]#.coins`, addr)).Array() - for _, coins := range balances { - for _, coin := range coins.Array() { - r = append(r, sdk.NewCoin(coin.Get("denom").String(), sdkmath.NewInt(coin.Get("amount").Int()))) - } - } - return r -} diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 3d7957474b7c..d1ee4c8fb08d 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -3,6 +3,8 @@ module cosmossdk.io/tests/systemtests go 1.23.1 require ( + cosmossdk.io/math v1.4.0 + cosmossdk.io/systemtests v0.0.0-20241126144654-14d98d277124 github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/cosmos-sdk v0.50.6 github.com/cosmos/gogogateway v1.2.0 // indirect @@ -13,23 +15,16 @@ require ( github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.20.4 // indirect - github.com/spf13/cast v1.6.0 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect + github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/grpc v1.67.1 -) - -require ( - cosmossdk.io/math v1.4.0 - github.com/cometbft/cometbft v0.38.8 - github.com/cometbft/cometbft/api v1.0.0-rc.1 - github.com/creachadair/tomledit v0.0.26 github.com/tidwall/gjson v1.14.2 github.com/tidwall/sjson v1.2.5 + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/grpc v1.68.0 // indirect ) require ( @@ -48,7 +43,6 @@ require ( github.com/DataDog/zstd v1.5.6 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/bytedance/sonic v1.12.4 // indirect github.com/bytedance/sonic/loader v0.2.1 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect @@ -61,25 +55,28 @@ require ( github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft-db v1.0.1 // indirect + github.com/cometbft/cometbft v0.38.15 // indirect + github.com/cometbft/cometbft-db v0.14.1 // indirect + github.com/cometbft/cometbft/api v1.0.0-rc.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.0.2 // indirect + github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/creachadair/tomledit v0.0.26 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v4 v4.3.0 // indirect github.com/dgraph-io/ristretto v1.0.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/dot v1.6.2 // indirect - github.com/fatih/color v1.17.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/getsentry/sentry-go v0.29.0 // indirect - github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect @@ -92,19 +89,19 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-metrics v0.5.3 // indirect - github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/go-plugin v1.6.2 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect - github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/skiplist v1.2.1 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -113,32 +110,30 @@ require ( github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/lib/pq v1.10.7 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/linxGnu/grocksdb v1.9.3 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/minio/highwayhash v1.0.2 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/minio/highwayhash v1.0.3 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/oklog/run v1.1.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect - github.com/rs/cors v1.11.0 // indirect + github.com/rs/cors v1.11.1 // indirect github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/viper v1.19.0 // indirect @@ -150,20 +145,20 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect - go.etcd.io/bbolt v1.3.11 // indirect + go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.12.0 // indirect - golang.org/x/crypto v0.27.0 // indirect - golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect - golang.org/x/net v0.29.0 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect - google.golang.org/protobuf v1.35.1 // indirect + golang.org/x/term v0.26.0 // indirect + golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/protobuf v1.35.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index f7749f8578d3..8e80976253cd 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -16,6 +16,8 @@ cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ= cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk= cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= +cosmossdk.io/systemtests v0.0.0-20241126144654-14d98d277124 h1:pzhysmpO6+HA/vnJKVTfmtZAtCJJzLqsBZAwzOCFa7Q= +cosmossdk.io/systemtests v0.0.0-20241126144654-14d98d277124/go.mod h1:IQrj3oVhIBn1X8183/IL1z3l7HgjePVSHLeZtUUjGjI= cosmossdk.io/x/tx v1.0.0-alpha.2 h1:UW80FMm7B0fiAMsrfe5+HabSJ3XBg+tQa6/GK9prqWk= cosmossdk.io/x/tx v1.0.0-alpha.2/go.mod h1:r4yTKSJ7ZCCR95YbBfY3nfvbgNw6m9F6f25efWYYQWo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -42,8 +44,8 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= -github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= +github.com/adlio/schema v1.3.6 h1:k1/zc2jNfeiZBA5aFTRy37jlBIuCkXCm0XmvpzCKI9I= +github.com/adlio/schema v1.3.6/go.mod h1:qkxwLgPBd1FgLRHYVCmQT/rrBr3JH38J9LjmVzWNudg= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -72,10 +74,8 @@ github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5M github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/bytedance/sonic v1.12.4 h1:9Csb3c9ZJhfUWeMtpCDCq6BUoH5ogfDFLUgQ/jG+R0k= @@ -131,10 +131,10 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.8 h1:XyJ9Cu3xqap6xtNxiemrO8roXZ+KS2Zlu7qQ0w1trvU= -github.com/cometbft/cometbft v0.38.8/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= -github.com/cometbft/cometbft-db v1.0.1 h1:SylKuLseMLQKw3+i8y8KozZyJcQSL98qEe2CGMCGTYE= -github.com/cometbft/cometbft-db v1.0.1/go.mod h1:EBrFs1GDRiTqrWXYi4v90Awf/gcdD5ExzdPbg4X8+mk= +github.com/cometbft/cometbft v0.38.15 h1:5veFd8k1uXM27PBg9sMO3hAfRJ3vbh4OmmLf6cVrqXg= +github.com/cometbft/cometbft v0.38.15/go.mod h1:+wh6ap6xctVG+JOHwbl8pPKZ0GeqdPYqISu7F4b43cQ= +github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= +github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= github.com/cometbft/cometbft/api v1.0.0-rc.1 h1:GtdXwDGlqwHYs16A4egjwylfYOMYyEacLBrs3Zvpt7g= github.com/cometbft/cometbft/api v1.0.0-rc.1/go.mod h1:NDFKiBBD8HJC6QQLAoUI99YhsiRZtg2+FJWfk6A6m6o= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -145,8 +145,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs= -github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= +github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33 h1:NnqmEOIzUPazzBrhGenzI1AQCBtJ0Hbnb/DDoykpko0= +github.com/cosmos/cosmos-db v1.0.3-0.20240829004618-717cba019b33/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/cosmos-sdk v0.50.6 h1:efR3MsvMHX5sxS3be+hOobGk87IzlZbSpsI2x/Vw3hk= @@ -178,8 +178,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v4 v4.3.0 h1:lcsCE1/1qrRhqP+zYx6xDZb8n7U+QlwNicpc676Ub40= @@ -214,8 +214,8 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= @@ -228,8 +228,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/getsentry/sentry-go v0.29.0 h1:YtWluuCFg9OfcqnaujpY918N/AhCCwarIDWOYSBAjCA= github.com/getsentry/sentry-go v0.29.0/go.mod h1:jhPesDAL0Q0W2+2YEuVOvdWmVtdsr1+jtBrlDEVWwLY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -244,8 +244,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= -github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= @@ -355,8 +355,8 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= @@ -381,8 +381,8 @@ github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYS github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= -github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -404,15 +404,15 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= -github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= -github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/skiplist v1.2.1 h1:dTi93MgjwErA/8idWTzIw4Y1kZsMWx35fmI2c8Rij7w= +github.com/huandu/skiplist v1.2.1/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -467,10 +467,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.9.3 h1:s1cbPcOd0cU2SKXRG1nEqCOWYAELQjdqg3RVI2MH9ik= @@ -496,13 +494,11 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= -github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q= +github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -562,8 +558,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= -github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -579,12 +575,11 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU= -github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -605,8 +600,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= -github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -621,8 +616,8 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= -github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -641,8 +636,8 @@ github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/f github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= -github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -654,16 +649,16 @@ github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgY github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= -github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -672,8 +667,8 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -701,7 +696,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -739,8 +733,8 @@ github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWp github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= -go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5 h1:qxen9oVGzDdIRP6ejyAJc760RwW4SnVDiTYTzwnXuxo= +go.etcd.io/bbolt v1.4.0-alpha.0.0.20240404170359-43604f3112c5/go.mod h1:eW0HG9/oHQhvRCvb1/pIXW4cOvtDqeQK+XSi3TnwaXY= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -772,13 +766,13 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= -golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= +golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= +golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -792,8 +786,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -822,8 +816,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -844,7 +838,6 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -888,20 +881,21 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -924,8 +918,8 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= -golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -948,10 +942,10 @@ google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -970,8 +964,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -986,8 +980,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/tests/systemtests/gov_test.go b/tests/systemtests/gov_test.go index b3270275b454..3f9d41cf6fb5 100644 --- a/tests/systemtests/gov_test.go +++ b/tests/systemtests/gov_test.go @@ -13,6 +13,7 @@ import ( "github.com/tidwall/gjson" "cosmossdk.io/math" + systest "cosmossdk.io/systemtests" "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" @@ -21,14 +22,14 @@ import ( func TestSubmitProposal(t *testing.T) { // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() require.NotEmpty(t, valAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) // get gov module address resp := cli.CustomQuery("q", "auth", "module-account", "gov") @@ -41,7 +42,7 @@ func TestSubmitProposal(t *testing.T) { "deposit": "-324foocoin" }` - invalidPropFile := StoreTempFile(t, []byte(invalidProp)) + invalidPropFile := systest.StoreTempFile(t, []byte(invalidProp)) defer invalidPropFile.Close() // Create a valid new proposal JSON. @@ -64,7 +65,7 @@ func TestSubmitProposal(t *testing.T) { "metadata": "%s", "deposit": "%s" }`, govAddress, base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin("stake", math.NewInt(100000))) - validPropFile := StoreTempFile(t, []byte(validProp)) + validPropFile := systest.StoreTempFile(t, []byte(validProp)) defer validPropFile.Close() testCases := []struct { @@ -114,7 +115,7 @@ func TestSubmitProposal(t *testing.T) { rsp := cli.Run(tc.args...) txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) } }) } @@ -123,14 +124,14 @@ func TestSubmitProposal(t *testing.T) { func TestSubmitLegacyProposal(t *testing.T) { // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() require.NotEmpty(t, valAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) invalidProp := `{ "title": "", @@ -138,7 +139,7 @@ func TestSubmitLegacyProposal(t *testing.T) { "type": "Text", "deposit": "-324foocoin" }` - invalidPropFile := StoreTempFile(t, []byte(invalidProp)) + invalidPropFile := systest.StoreTempFile(t, []byte(invalidProp)) defer invalidPropFile.Close() validProp := fmt.Sprintf(`{ @@ -147,7 +148,7 @@ func TestSubmitLegacyProposal(t *testing.T) { "type": "Text", "deposit": "%s" }`, sdk.NewCoin("stake", math.NewInt(154310))) - validPropFile := StoreTempFile(t, []byte(validProp)) + validPropFile := systest.StoreTempFile(t, []byte(validProp)) defer validPropFile.Close() testCases := []struct { @@ -227,7 +228,7 @@ func TestSubmitLegacyProposal(t *testing.T) { rsp := cli.Run(tc.args...) txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) } }) } @@ -236,14 +237,14 @@ func TestSubmitLegacyProposal(t *testing.T) { func TestNewCmdWeightedVote(t *testing.T) { // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() require.NotEmpty(t, valAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) // Submit a new proposal for voting proposalArgs := []string{ @@ -260,7 +261,7 @@ func TestNewCmdWeightedVote(t *testing.T) { rsp := cli.Run(proposalArgs...) txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) proposalsResp := cli.CustomQuery("q", "gov", "proposals") proposals := gjson.Get(proposalsResp, "proposals.#.id").Array() @@ -361,7 +362,7 @@ func TestNewCmdWeightedVote(t *testing.T) { } else { rsp := cli.Run(tc.args...) if tc.expectErr { - RequireTxFailure(t, rsp) + systest.RequireTxFailure(t, rsp) } else { cli.AwaitTxCommitted(rsp) } @@ -372,22 +373,20 @@ func TestNewCmdWeightedVote(t *testing.T) { func TestQueryDeposit(t *testing.T) { // given a running chain - - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) // short voting period // update expedited voting period to avoid validation error - sut.ModifyGenesisJSON( + votingPeriod := 3 * time.Second + systest.Sut.ModifyGenesisJSON( t, - SetGovVotingPeriod(t, time.Second*8), - SetGovExpeditedVotingPeriod(t, time.Second*7), + systest.SetGovVotingPeriod(t, votingPeriod), + systest.SetGovExpeditedVotingPeriod(t, votingPeriod-time.Second), ) + systest.Sut.StartChain(t) // get validator address - valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String() - require.NotEmpty(t, valAddr) - - sut.StartChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) + valAddr := cli.GetKeyAddr("node0") // Submit a new proposal for voting proposalArgs := []string{ @@ -404,7 +403,7 @@ func TestQueryDeposit(t *testing.T) { rsp := cli.Run(proposalArgs...) txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) // Query initial deposit resp := cli.CustomQuery("q", "gov", "deposit", "1", valAddr) @@ -415,8 +414,9 @@ func TestQueryDeposit(t *testing.T) { deposits := gjson.Get(resp, "deposits").Array() require.Equal(t, len(deposits), 1) - time.Sleep(time.Second * 8) - resp = cli.CustomQuery("q", "gov", "deposits", "1") - deposits = gjson.Get(resp, "deposits").Array() - require.Equal(t, len(deposits), 0) + assert.Eventually(t, func() bool { + resp = cli.CustomQuery("q", "gov", "deposits", "1") + deposits = gjson.Get(resp, "deposits").Array() + return len(deposits) == 0 + }, votingPeriod, 100*time.Millisecond) } diff --git a/tests/systemtests/group_test.go b/tests/systemtests/group_test.go index 6966d30751e5..fd7e6ef448bf 100644 --- a/tests/systemtests/group_test.go +++ b/tests/systemtests/group_test.go @@ -8,6 +8,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) const ( @@ -18,18 +20,18 @@ func TestGroupCommands(t *testing.T) { // scenario: test group commands // given a running chain - sut.ResetChain(t) - require.GreaterOrEqual(t, sut.NodesCount(), 2) + systest.Sut.ResetChain(t) + require.GreaterOrEqual(t, systest.Sut.NodesCount(), 2) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) - baseurl := sut.APIAddress() + baseurl := systest.Sut.APIAddress() // test create group memberWeight := "5" @@ -43,10 +45,10 @@ func TestGroupCommands(t *testing.T) { } ] }`, valAddr, memberWeight, validMetadata) - validMembersFile := StoreTempFile(t, []byte(validMembers)) + validMembersFile := systest.StoreTempFile(t, []byte(validMembers)) createGroupCmd := []string{"tx", "group", "create-group", valAddr, validMetadata, validMembersFile.Name(), "--from=" + valAddr} rsp := cli.RunAndWait(createGroupCmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query groups by admin to confirm group creation rsp = cli.CustomQuery("q", "group", "groups-by-admin", valAddr) @@ -56,34 +58,34 @@ func TestGroupCommands(t *testing.T) { // test create group policies for i := 0; i < 5; i++ { threshold := i + 1 - policyFile := StoreTempFile(t, []byte(fmt.Sprintf(`{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"%d", "windows":{"voting_period":"30000s"}}`, threshold))) + policyFile := systest.StoreTempFile(t, []byte(fmt.Sprintf(`{"@type":"/cosmos.group.v1.ThresholdDecisionPolicy", "threshold":"%d", "windows":{"voting_period":"30000s"}}`, threshold))) policyCmd := []string{"tx", "group", "create-group-policy", valAddr, groupId, validMetadata, policyFile.Name(), "--from=" + valAddr} rsp = cli.RunAndWait(policyCmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // TODO: remove isV2() check once v2 is integrated with grpc gateway var groupPoliciesResp, policyAddrQuery string - if isV2() { + if systest.IsV2() { groupPoliciesResp = cli.CustomQuery("q", "group", "group-policies-by-group", groupId) policyAddrQuery = fmt.Sprintf("group_policies.#(decision_policy.value.threshold==%d).address", threshold) } else { - groupPoliciesResp = string(GetRequest(t, fmt.Sprintf("%s/cosmos/group/v1/group_policies_by_group/%s", baseurl, groupId))) + groupPoliciesResp = string(systest.GetRequest(t, fmt.Sprintf("%s/cosmos/group/v1/group_policies_by_group/%s", baseurl, groupId))) policyAddrQuery = fmt.Sprintf("group_policies.#(decision_policy.threshold==%d).address", threshold) } require.Equal(t, gjson.Get(groupPoliciesResp, "pagination.total").Int(), int64(threshold)) policyAddr := gjson.Get(groupPoliciesResp, policyAddrQuery).String() require.NotEmpty(t, policyAddr) - rsp = cli.RunCommandWithArgs(cli.withTXFlags("tx", "bank", "send", valAddr, policyAddr, "1000stake", "--generate-only")...) + rsp = cli.RunCommandWithArgs(cli.WithTXFlags("tx", "bank", "send", valAddr, policyAddr, "1000stake", "--generate-only")...) require.Equal(t, policyAddr, gjson.Get(rsp, "body.messages.0.to_address").String()) } // test create group policy with percentage decision policy percentagePolicyType := "/cosmos.group.v1.PercentageDecisionPolicy" - policyFile := StoreTempFile(t, []byte(fmt.Sprintf(`{"@type":"%s", "percentage":"%f", "windows":{"voting_period":"30000s"}}`, percentagePolicyType, 0.5))) + policyFile := systest.StoreTempFile(t, []byte(fmt.Sprintf(`{"@type":"%s", "percentage":"%f", "windows":{"voting_period":"30000s"}}`, percentagePolicyType, 0.5))) policyCmd := []string{"tx", "group", "create-group-policy", valAddr, groupId, validMetadata, policyFile.Name(), "--from=" + valAddr} rsp = cli.RunAndWait(policyCmd...) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) groupPoliciesResp := cli.CustomQuery("q", "group", "group-policies-by-admin", valAddr) require.Equal(t, gjson.Get(groupPoliciesResp, "pagination.total").Int(), int64(6)) @@ -106,9 +108,9 @@ func TestGroupCommands(t *testing.T) { "summary": "Summary", "proposers": ["%s"] }`, policyAddr, policyAddr, valAddr, validMetadata, valAddr) - proposalFile := StoreTempFile(t, []byte(proposalJSON)) + proposalFile := systest.StoreTempFile(t, []byte(proposalJSON)) rsp = cli.RunAndWait("tx", "group", "submit-proposal", proposalFile.Name()) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query proposals rsp = cli.CustomQuery("q", "group", "proposals-by-group-policy", policyAddr) @@ -117,15 +119,15 @@ func TestGroupCommands(t *testing.T) { // test vote proposal rsp = cli.RunAndWait("tx", "group", "vote", proposalId, valAddr, "yes", validMetadata) - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) // query votes // TODO: remove isV2() check once v2 is integrated with grpc gateway var voteResp string - if isV2() { + if systest.IsV2() { voteResp = cli.CustomQuery("q", "group", "vote", proposalId, valAddr) } else { - voteResp = string(GetRequest(t, fmt.Sprintf("%s/cosmos/group/v1/vote_by_proposal_voter/%s/%s", baseurl, proposalId, valAddr))) + voteResp = string(systest.GetRequest(t, fmt.Sprintf("%s/cosmos/group/v1/vote_by_proposal_voter/%s/%s", baseurl, proposalId, valAddr))) } require.Equal(t, "VOTE_OPTION_YES", gjson.Get(voteResp, "vote.option").String()) } diff --git a/tests/systemtests/io_utils.go b/tests/systemtests/io_utils.go deleted file mode 100644 index a9cd1094fba6..000000000000 --- a/tests/systemtests/io_utils.go +++ /dev/null @@ -1,65 +0,0 @@ -package systemtests - -import ( - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" -) - -// MustCopyFile copies the file from the source path `src` to the destination path `dest` and returns an open file handle to `dest`. -func MustCopyFile(src, dest string) *os.File { - in, err := os.Open(src) - if err != nil { - panic(fmt.Sprintf("failed to open %q: %v", src, err)) - } - defer in.Close() - - out, err := os.Create(dest) - if err != nil { - panic(fmt.Sprintf("failed to create %q: %v", dest, err)) - } - defer out.Close() - - _, err = io.Copy(out, in) - if err != nil { - panic(fmt.Sprintf("failed to copy from %q to %q: %v", src, dest, err)) - } - return out -} - -// MustCopyFilesInDir copies all files (excluding directories) from the source directory `src` to the destination directory `dest`. -func MustCopyFilesInDir(src, dest string) { - err := os.MkdirAll(dest, 0o750) - if err != nil { - panic(fmt.Sprintf("failed to create %q: %v", dest, err)) - } - - fs, err := os.ReadDir(src) - if err != nil { - panic(fmt.Sprintf("failed to read dir %q: %v", src, err)) - } - - for _, f := range fs { - if f.IsDir() { - continue - } - _ = MustCopyFile(filepath.Join(src, f.Name()), filepath.Join(dest, f.Name())) - } -} - -// StoreTempFile creates a temporary file in the test's temporary directory with the provided content. -// It returns a pointer to the created file. Errors during the process are handled with test assertions. -func StoreTempFile(t *testing.T, content []byte) *os.File { - t.Helper() - out, err := os.CreateTemp(t.TempDir(), "") - require.NoError(t, err) - _, err = io.Copy(out, bytes.NewReader(content)) - require.NoError(t, err) - require.NoError(t, out.Close()) - return out -} diff --git a/tests/systemtests/main_test.go b/tests/systemtests/main_test.go index f561a892d990..3bcc3ba8b2ca 100644 --- a/tests/systemtests/main_test.go +++ b/tests/systemtests/main_test.go @@ -2,8 +2,12 @@ package systemtests -import "testing" +import ( + "testing" + + systest "cosmossdk.io/systemtests" +) func TestMain(m *testing.M) { - RunTests(m) + systest.RunTests(m) } diff --git a/tests/systemtests/mint_test.go b/tests/systemtests/mint_test.go index c95aaaee1233..1be1a713743b 100644 --- a/tests/systemtests/mint_test.go +++ b/tests/systemtests/mint_test.go @@ -7,16 +7,18 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/sjson" + + systest "cosmossdk.io/systemtests" ) func TestMintQueries(t *testing.T) { // scenario: test mint grpc queries // given a running chain - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) - sut.ModifyGenesisJSON(t, + systest.Sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { state, err := sjson.Set(string(genesis), "app_state.mint.minter.inflation", "1.00") require.NoError(t, err) @@ -29,17 +31,17 @@ func TestMintQueries(t *testing.T) { }, ) - sut.StartChain(t) + systest.Sut.StartChain(t) - sut.AwaitNextBlock(t) + systest.Sut.AwaitNextBlock(t) - baseurl := sut.APIAddress() + baseurl := systest.Sut.APIAddress() blockHeightHeader := "x-cosmos-block-height" queryAtHeight := "1" // TODO: check why difference in values when querying with height between v1 and v2 // ref: https://github.com/cosmos/cosmos-sdk/issues/22302 - if isV2() { + if systest.IsV2() { queryAtHeight = "2" } @@ -78,10 +80,10 @@ func TestMintQueries(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // TODO: remove below check once grpc gateway is implemented in v2 - if isV2() { + if systest.IsV2() { return } - resp := GetRequestWithHeaders(t, tc.url, tc.headers, http.StatusOK) + resp := systest.GetRequestWithHeaders(t, tc.url, tc.headers, http.StatusOK) require.JSONEq(t, tc.expOut, string(resp)) }) } diff --git a/tests/systemtests/node_utils.go b/tests/systemtests/node_utils.go deleted file mode 100644 index f503a0f390ad..000000000000 --- a/tests/systemtests/node_utils.go +++ /dev/null @@ -1,46 +0,0 @@ -package systemtests - -import ( - "bytes" - "path/filepath" - "testing" - - "github.com/cometbft/cometbft/privval" - "github.com/stretchr/testify/require" - - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" -) - -// LoadValidatorPubKeyForNode load validator nodes consensus pub key for given node number -func LoadValidatorPubKeyForNode(t *testing.T, sut *SystemUnderTest, nodeNumber int) cryptotypes.PubKey { - t.Helper() - return LoadValidatorPubKey(t, filepath.Join(WorkDir, sut.nodePath(nodeNumber), "config", "priv_validator_key.json")) -} - -// LoadValidatorPubKey load validator nodes consensus pub key from disk -func LoadValidatorPubKey(t *testing.T, keyFile string) cryptotypes.PubKey { - t.Helper() - filePV := privval.LoadFilePVEmptyState(keyFile, "") - pubKey, err := filePV.GetPubKey() - require.NoError(t, err) - valPubKey, err := cryptocodec.FromCmtPubKeyInterface(pubKey) - require.NoError(t, err) - return valPubKey -} - -// QueryCometValidatorPowerForNode returns the validator's power from tendermint RPC endpoint. 0 when not found -func QueryCometValidatorPowerForNode(t *testing.T, sut *SystemUnderTest, nodeNumber int) int64 { - t.Helper() - pubKebBz := LoadValidatorPubKeyForNode(t, sut, nodeNumber).Bytes() - return QueryCometValidatorPower(sut.RPCClient(t), pubKebBz) -} - -func QueryCometValidatorPower(c RPCClient, pubKebBz []byte) int64 { - for _, v := range c.Validators() { - if bytes.Equal(v.PubKey.Bytes(), pubKebBz) { - return v.VotingPower - } - } - return 0 -} diff --git a/tests/systemtests/rest_cli.go b/tests/systemtests/rest_cli.go deleted file mode 100644 index 3ad1e30dda68..000000000000 --- a/tests/systemtests/rest_cli.go +++ /dev/null @@ -1,87 +0,0 @@ -package systemtests - -import ( - "io" - "net/http" - "regexp" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/testutil" -) - -type RestTestCase struct { - name string - url string - expCode int - expOut string -} - -// RunRestQueries runs given Rest testcases by making requests and -// checking response with expected output -func RunRestQueries(t *testing.T, testCases []RestTestCase) { - t.Helper() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - resp := GetRequestWithHeaders(t, tc.url, nil, tc.expCode) - require.JSONEq(t, tc.expOut, string(resp)) - }) - } -} - -// TestRestQueryIgnoreNumbers runs given rest testcases by making requests and -// checking response with expected output ignoring number values -// This method is used when number values in response are non-deterministic -func TestRestQueryIgnoreNumbers(t *testing.T, testCases []RestTestCase) { - t.Helper() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - resp, err := testutil.GetRequest(tc.url) - require.NoError(t, err) - - // regular expression pattern to match any numeric value in the JSON - numberRegexPattern := `"\d+(\.\d+)?"` - - // compile the regex - r, err := regexp.Compile(numberRegexPattern) - require.NoError(t, err) - - // replace all numeric values in the above JSONs with `NUMBER` text - expectedJSON := r.ReplaceAllString(tc.expOut, `"NUMBER"`) - actualJSON := r.ReplaceAllString(string(resp), `"NUMBER"`) - - // compare two jsons - require.JSONEq(t, expectedJSON, actualJSON) - }) - } -} - -func GetRequest(t *testing.T, url string) []byte { - t.Helper() - return GetRequestWithHeaders(t, url, nil, http.StatusOK) -} - -func GetRequestWithHeaders(t *testing.T, url string, headers map[string]string, expCode int) []byte { - t.Helper() - req, err := http.NewRequest("GET", url, nil) - require.NoError(t, err) - - for key, value := range headers { - req.Header.Set(key, value) - } - - httpClient := &http.Client{} - res, err := httpClient.Do(req) - require.NoError(t, err) - defer func() { - _ = res.Body.Close() - }() - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.Equal(t, expCode, res.StatusCode, "status code should be %d, got: %d, %s", expCode, res.StatusCode, body) - - return body -} diff --git a/tests/systemtests/rpc_client.go b/tests/systemtests/rpc_client.go deleted file mode 100644 index 4714715be600..000000000000 --- a/tests/systemtests/rpc_client.go +++ /dev/null @@ -1,113 +0,0 @@ -package systemtests - -import ( - "context" - "errors" - "reflect" - "strconv" - "testing" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - rpcclient "github.com/cometbft/cometbft/rpc/client" - client "github.com/cometbft/cometbft/rpc/client/http" - cmtypes "github.com/cometbft/cometbft/types" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" -) - -// RPCClient is a test helper to interact with a node via the RPC endpoint. -type RPCClient struct { - client *client.HTTP - t *testing.T -} - -// NewRPCClient constructor -func NewRPCClient(t *testing.T, addr string) RPCClient { - t.Helper() - httpClient, err := client.New(addr, "/websocket") - require.NoError(t, err) - require.NoError(t, httpClient.Start()) - t.Cleanup(func() { _ = httpClient.Stop() }) - return RPCClient{client: httpClient, t: t} -} - -// Validators returns list of validators -func (r RPCClient) Validators() []*cmtypes.Validator { - v, err := r.client.Validators(context.Background(), nil, nil, nil) - require.NoError(r.t, err) - return v.Validators -} - -func (r RPCClient) Invoke(ctx context.Context, method string, req, reply interface{}, opts ...grpc.CallOption) error { - if reflect.ValueOf(req).IsNil() { - return errors.New("request cannot be nil") - } - - ir := types.NewInterfaceRegistry() - cryptocodec.RegisterInterfaces(ir) - cdc := codec.NewProtoCodec(ir).GRPCCodec() - - reqBz, err := cdc.Marshal(req) - if err != nil { - return err - } - - var height int64 - md, _ := metadata.FromOutgoingContext(ctx) - if heights := md.Get(grpctypes.GRPCBlockHeightHeader); len(heights) > 0 { - height, err := strconv.ParseInt(heights[0], 10, 64) - if err != nil { - return err - } - if height < 0 { - return errors.New("height must be greater than or equal to 0") - } - } - - abciReq := abci.QueryRequest{ - Path: method, - Data: reqBz, - Height: height, - } - - abciOpts := rpcclient.ABCIQueryOptions{ - Height: height, - Prove: abciReq.Prove, - } - - result, err := r.client.ABCIQueryWithOptions(ctx, abciReq.Path, abciReq.Data, abciOpts) - if err != nil { - return err - } - - if !result.Response.IsOK() { - return errors.New(result.Response.String()) - } - - err = cdc.Unmarshal(result.Response.Value, reply) - if err != nil { - return err - } - - md = metadata.Pairs(grpctypes.GRPCBlockHeightHeader, strconv.FormatInt(result.Response.Height, 10)) - for _, callOpt := range opts { - header, ok := callOpt.(grpc.HeaderCallOption) - if !ok { - continue - } - - *header.HeaderAddr = md - } - - return types.UnpackInterfaces(reply, ir) -} - -func (r RPCClient) NewStream(ctx context.Context, desc *grpc.StreamDesc, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) { - return nil, errors.New("not implemented") -} diff --git a/tests/systemtests/snapshots_test.go b/tests/systemtests/snapshots_test.go index c4d6b257fc93..b47708e7b449 100644 --- a/tests/systemtests/snapshots_test.go +++ b/tests/systemtests/snapshots_test.go @@ -8,24 +8,26 @@ import ( "testing" "github.com/stretchr/testify/require" + + systest "cosmossdk.io/systemtests" ) func TestSnapshots(t *testing.T) { - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) - sut.StartChain(t) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) + systest.Sut.StartChain(t) // Wait for chain produce some blocks - sut.AwaitNBlocks(t, 6) + systest.Sut.AwaitNBlocks(t, 6) // Stop all nodes - sut.StopChain() + systest.Sut.StopChain() var ( command string restoreableDirs []string ) - node0Dir := sut.NodeDir(0) - if isV2() { + node0Dir := systest.Sut.NodeDir(0) + if systest.IsV2() { command = "store" restoreableDirs = []string{fmt.Sprintf("%s/data/application.db", node0Dir), fmt.Sprintf("%s/data/ss", node0Dir)} } else { @@ -62,7 +64,7 @@ func TestSnapshots(t *testing.T) { // Remove database err := os.RemoveAll(fmt.Sprintf("%s/data/application.db", node0Dir)) require.NoError(t, err) - if isV2() { + if systest.IsV2() { require.NoError(t, os.RemoveAll(fmt.Sprintf("%s/data/ss", node0Dir))) } @@ -73,22 +75,22 @@ func TestSnapshots(t *testing.T) { } func TestPrune(t *testing.T) { - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) - sut.StartChain(t) + systest.Sut.StartChain(t) // Wait for chain produce some blocks - sut.AwaitNBlocks(t, 6) + systest.Sut.AwaitNBlocks(t, 6) // Stop all nodes - sut.StopChain() + systest.Sut.StopChain() - node0Dir := sut.NodeDir(0) + node0Dir := systest.Sut.NodeDir(0) // prune var command []string - if isV2() { + if systest.IsV2() { command = []string{"store", "prune", "--store.keep-recent=1"} } else { command = []string{"prune", "everything"} diff --git a/tests/systemtests/staking_test.go b/tests/systemtests/staking_test.go index 58b6c863a744..ba734d6e8d90 100644 --- a/tests/systemtests/staking_test.go +++ b/tests/systemtests/staking_test.go @@ -7,6 +7,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" + + systest "cosmossdk.io/systemtests" ) func TestStakeUnstake(t *testing.T) { @@ -15,17 +17,17 @@ func TestStakeUnstake(t *testing.T) { // check validator has been updated // undelegate some tokens - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // add genesis account with some tokens account1Addr := cli.AddKey("account1") - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", account1Addr, "10000000stake"}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) // query validator address to delegate tokens rsp := cli.CustomQuery("q", "staking", "validators") @@ -34,7 +36,7 @@ func TestStakeUnstake(t *testing.T) { // stake tokens rsp = cli.RunAndWait("tx", "staking", "delegate", valAddr, "1000000stake", "--from="+account1Addr, "--fees=1stake") - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) t.Log(cli.QueryBalance(account1Addr, "stake")) assert.Equal(t, int64(8999999), cli.QueryBalance(account1Addr, "stake")) @@ -52,7 +54,7 @@ func TestStakeUnstake(t *testing.T) { // unstake tokens rsp = cli.RunAndWait("tx", "staking", "unbond", valAddr, "5000stake", "--from="+account1Addr, "--fees=1stake") - RequireTxSuccess(t, rsp) + systest.RequireTxSuccess(t, rsp) rsp = cli.CustomQuery("q", "staking", "delegation", account1Addr, valAddr) assert.Equal(t, "995000", gjson.Get(rsp, "delegation_response.balance.amount").String(), rsp) diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go deleted file mode 100644 index 7105ff400ed1..000000000000 --- a/tests/systemtests/system.go +++ /dev/null @@ -1,951 +0,0 @@ -package systemtests - -import ( - "bufio" - "bytes" - "container/ring" - "context" - "fmt" - "io" - "maps" - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "sync/atomic" - "syscall" - "testing" - "time" - - "github.com/cometbft/cometbft/libs/sync" - client "github.com/cometbft/cometbft/rpc/client/http" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - tmtypes "github.com/cometbft/cometbft/types" - "github.com/stretchr/testify/require" - "github.com/tidwall/sjson" - - "github.com/cosmos/cosmos-sdk/server" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -var ( - // WorkDir is the directory where tests are executed. Path should be relative to this dir - WorkDir string - - // ExecBinaryUnversionedRegExp regular expression to extract the unversioned binary name - ExecBinaryUnversionedRegExp = regexp.MustCompile(`^(\w+)-?.*$`) - - MaxGas = 10_000_000 -) - -type TestnetInitializer interface { - Initialize() -} - -// SystemUnderTest blockchain provisioning -type SystemUnderTest struct { - execBinary string - blockListener *EventListener - currentHeight atomic.Int64 - outputDir string - testnetInitializer TestnetInitializer - - // blockTime is the expected/desired block time. This is not going to be very precise - // since Tendermint consensus does not allow specifying it directly. - blockTime time.Duration - rpcAddr string - apiAddr string - initialNodesCount int - nodesCount int - minGasPrice string - cleanupFn []CleanupFn - outBuff *ring.Ring - errBuff *ring.Ring - out io.Writer - verbose bool - ChainStarted bool - projectName string - dirty bool // requires full reset when marked dirty - - pidsLock sync.RWMutex - pids map[int]struct{} - chainID string -} - -func NewSystemUnderTest(execBinary string, verbose bool, nodesCount int, blockTime time.Duration, initer ...TestnetInitializer) *SystemUnderTest { - if execBinary == "" { - panic("executable binary name must not be empty") - } - nameTokens := ExecBinaryUnversionedRegExp.FindAllString(execBinary, 1) - if len(nameTokens) == 0 || nameTokens[0] == "" { - panic("failed to parse project name from binary") - } - - execBinary = filepath.Join(WorkDir, "binaries", execBinary) - s := &SystemUnderTest{ - chainID: "testing", - execBinary: execBinary, - outputDir: "./testnet", - blockTime: blockTime, - rpcAddr: "tcp://localhost:26657", - apiAddr: fmt.Sprintf("http://localhost:%d", apiPortStart), - initialNodesCount: nodesCount, - outBuff: ring.New(100), - errBuff: ring.New(100), - out: os.Stdout, - verbose: verbose, - minGasPrice: fmt.Sprintf("0.000001%s", sdk.DefaultBondDenom), - projectName: nameTokens[0], - pids: make(map[int]struct{}, nodesCount), - } - s.testnetInitializer = NewSingleHostTestnetCmdInitializer(execBinary, WorkDir, s.chainID, s.outputDir, s.initialNodesCount, s.minGasPrice, s.CommitTimeout(), s.Log) - return s -} - -func (s *SystemUnderTest) SetExecBinary(binary string) { - s.execBinary = binary -} - -func (s *SystemUnderTest) SetTestnetInitializer(testnetInitializer TestnetInitializer) { - s.testnetInitializer = testnetInitializer -} - -// CommitTimeout returns the max time to wait for a commit. Default to 90% of block time -func (s *SystemUnderTest) CommitTimeout() time.Duration { - // The commit timeout is a lower bound for the block time. We try to set it to a level that allows us to reach the expected block time. - return time.Duration((int64(s.blockTime) * 90) / 100) // leave 10% for all other operations -} - -func (s *SystemUnderTest) SetupChain() { - s.Logf("Setup chain: %s\n", s.outputDir) - if err := os.RemoveAll(filepath.Join(WorkDir, s.outputDir)); err != nil { - panic(err.Error()) - } - s.testnetInitializer.Initialize() - s.nodesCount = s.initialNodesCount - - // modify genesis with system test defaults - src := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json") - genesisBz, err := os.ReadFile(src) // #nosec G304 - if err != nil { - panic(fmt.Sprintf("failed to load genesis: %s", err)) - } - - genesisBz, err = sjson.SetRawBytes(genesisBz, "consensus.params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, MaxGas))) - if err != nil { - panic(fmt.Sprintf("failed to set block max gas: %s", err)) - } - s.withEachNodeHome(func(i int, home string) { - if err := saveGenesis(home, genesisBz); err != nil { - panic(err) - } - }) - - // backup genesis - dest := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json.orig") - MustCopyFile(src, dest) - // backup keyring - src = filepath.Join(WorkDir, s.nodePath(0), "keyring-test") - dest = filepath.Join(WorkDir, s.outputDir, "keyring-test") - MustCopyFilesInDir(src, dest) -} - -func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string) { - t.Helper() - s.Log("Start chain\n") - s.ChainStarted = true - s.startNodesAsync(t, append([]string{"start", "--log_level=info", "--log_no_color"}, xargs...)...) - - s.AwaitNodeUp(t, s.rpcAddr) - - t.Log("Start new block listener") - s.blockListener = NewEventListener(t, s.rpcAddr) - s.cleanupFn = append(s.cleanupFn, - s.blockListener.Subscribe("tm.event='NewBlock'", func(e ctypes.ResultEvent) (more bool) { - newBlock, ok := e.Data.(tmtypes.EventDataNewBlock) - require.True(t, ok, "unexpected type %T", e.Data) - s.currentHeight.Store(newBlock.Block.Height) - return true - }), - ) - s.AwaitNextBlock(t, 4e9) -} - -// MarkDirty whole chain will be reset when marked dirty -func (s *SystemUnderTest) MarkDirty() { - s.dirty = true -} - -// IsDirty true when non default genesis or other state modification were applied that might create incompatibility for tests -func (s *SystemUnderTest) IsDirty() bool { - return s.dirty -} - -// watchLogs stores stdout/stderr in a file and in a ring buffer to output the last n lines on test error -func (s *SystemUnderTest) watchLogs(node int, cmd *exec.Cmd) { - logfile, err := os.Create(filepath.Join(WorkDir, s.outputDir, fmt.Sprintf("node%d.out", node))) - if err != nil { - panic(fmt.Sprintf("open logfile error %#+v", err)) - } - - errReader, err := cmd.StderrPipe() - if err != nil { - panic(fmt.Sprintf("stderr reader error %#+v", err)) - } - stopRingBuffer := make(chan struct{}) - go appendToBuf(io.TeeReader(errReader, logfile), s.errBuff, stopRingBuffer) - - outReader, err := cmd.StdoutPipe() - if err != nil { - panic(fmt.Sprintf("stdout reader error %#+v", err)) - } - go appendToBuf(io.TeeReader(outReader, logfile), s.outBuff, stopRingBuffer) - s.cleanupFn = append(s.cleanupFn, func() { - close(stopRingBuffer) - _ = logfile.Close() - }) -} - -func appendToBuf(r io.Reader, b *ring.Ring, stop <-chan struct{}) { - scanner := bufio.NewScanner(r) - for scanner.Scan() { - select { - case <-stop: - return - default: - } - text := scanner.Text() - // filter out noise - if isLogNoise(text) { - continue - } - b.Value = text - b = b.Next() - } -} - -func isLogNoise(text string) bool { - for _, v := range []string{ - "\x1b[36mmodule=\x1b[0mrpc-server", // "module=rpc-server", - } { - if strings.Contains(text, v) { - return true - } - } - return false -} - -// AwaitUpgradeInfo blocks util an upgrade info file is persisted to disk -func (s *SystemUnderTest) AwaitUpgradeInfo(t *testing.T) { - t.Helper() - var found bool - for !found { - s.withEachNodeHome(func(i int, home string) { - _, err := os.Stat(filepath.Join(s.nodePath(0), "data", "upgrade-info.json")) - switch { - case err == nil: - found = true - case !os.IsNotExist(err): - t.Fatal(err.Error()) - } - }) - time.Sleep(s.blockTime / 2) - } -} - -func (s *SystemUnderTest) AwaitChainStopped() { - for s.anyNodeRunning() { - time.Sleep(s.blockTime) - } -} - -// AwaitNodeUp ensures the node is running -func (s *SystemUnderTest) AwaitNodeUp(t *testing.T, rpcAddr string) { - t.Helper() - t.Logf("Await node is up: %s", rpcAddr) - timeout := DefaultWaitTime - ctx, done := context.WithTimeout(context.Background(), timeout) - defer done() - - started := make(chan struct{}) - go func() { // query for a non empty block on status page - t.Logf("Checking node status: %s\n", rpcAddr) - for { - con, err := client.New(rpcAddr, "/websocket") - if err != nil || con.Start() != nil { - time.Sleep(time.Second) - continue - } - result, err := con.Status(ctx) - if err != nil || result.SyncInfo.LatestBlockHeight < 1 { - _ = con.Stop() - continue - } - t.Logf("Node started. Current block: %d\n", result.SyncInfo.LatestBlockHeight) - _ = con.Stop() - started <- struct{}{} - } - }() - select { - case <-started: - case <-ctx.Done(): - require.NoError(t, ctx.Err()) - case <-time.NewTimer(timeout).C: - t.Fatalf("timeout waiting for node start: %s", timeout) - } -} - -// StopChain stops the system under test and executes all registered cleanup callbacks -func (s *SystemUnderTest) StopChain() { - s.Log("Stop chain\n") - if !s.ChainStarted { - return - } - - for _, c := range s.cleanupFn { - c() - } - s.cleanupFn = nil - // send SIGTERM - s.withEachPid(func(p *os.Process) { - go func() { - if err := p.Signal(syscall.SIGTERM); err != nil { - s.Logf("failed to stop node with pid %d: %s\n", p.Pid, err) - } - }() - }) - // give some final time to shut down - s.withEachPid(func(p *os.Process) { - time.Sleep(200 * time.Millisecond) - }) - // goodbye - for ; s.anyNodeRunning(); time.Sleep(100 * time.Millisecond) { - s.withEachPid(func(p *os.Process) { - s.Logf("killing node %d\n", p.Pid) - if err := p.Kill(); err != nil { - s.Logf("failed to kill node with pid %d: %s\n", p.Pid, err) - } - }) - } - s.ChainStarted = false -} - -func (s *SystemUnderTest) withEachPid(cb func(p *os.Process)) { - s.pidsLock.RLock() - pids := maps.Keys(s.pids) - s.pidsLock.RUnlock() - - for pid := range pids { - p, err := os.FindProcess(pid) - if err != nil { - continue - } - cb(p) - } -} - -// PrintBuffer prints the chain logs to the console -func (s *SystemUnderTest) PrintBuffer() { - s.outBuff.Do(func(v interface{}) { - if v != nil { - _, _ = fmt.Fprintf(s.out, "out> %s\n", v) - } - }) - fmt.Fprint(s.out, "8< chain err -----------------------------------------\n") - s.errBuff.Do(func(v interface{}) { - if v != nil { - _, _ = fmt.Fprintf(s.out, "err> %s\n", v) - } - }) -} - -// AwaitNBlocks blocks until the current height + n block is reached. An optional timeout parameter can be passed to abort early -func (s *SystemUnderTest) AwaitNBlocks(t *testing.T, n int64, timeout ...time.Duration) { - t.Helper() - s.AwaitBlockHeight(t, s.CurrentHeight()+n, timeout...) -} - -// AwaitBlockHeight blocks until the target height is reached. An optional timeout parameter can be passed to abort early -func (s *SystemUnderTest) AwaitBlockHeight(t *testing.T, targetHeight int64, timeout ...time.Duration) { - t.Helper() - require.Greater(t, targetHeight, s.currentHeight.Load()) - var maxWaitTime time.Duration - if len(timeout) != 0 { - maxWaitTime = timeout[0] - } else { - maxWaitTime = time.Duration(targetHeight-s.currentHeight.Load()+3) * s.blockTime - } - abort := time.NewTimer(maxWaitTime).C - for { - select { - case <-abort: - t.Fatalf("Timeout - block %d not reached within %s", targetHeight, maxWaitTime) - return - default: - if current := s.AwaitNextBlock(t); current >= targetHeight { - return - } - } - } -} - -// AwaitNextBlock is a first class function that any caller can use to ensure a new block was minted. -// Returns the new height -func (s *SystemUnderTest) AwaitNextBlock(t *testing.T, timeout ...time.Duration) int64 { - t.Helper() - maxWaitTime := s.blockTime * 3 - if len(timeout) != 0 { // optional argument to overwrite default timeout - maxWaitTime = timeout[0] - } - done := make(chan int64) - go func() { - for start, current := s.currentHeight.Load(), s.currentHeight.Load(); current == start; current = s.currentHeight.Load() { - time.Sleep(s.blockTime) - } - done <- s.currentHeight.Load() - close(done) - }() - select { - case v := <-done: - return v - case <-time.NewTimer(maxWaitTime).C: - t.Fatalf("Timeout - no block within %s", maxWaitTime) - return -1 - } -} - -// ResetDirtyChain reset chain when non default setup or state (dirty) -func (s *SystemUnderTest) ResetDirtyChain(t *testing.T) { - t.Helper() - if s.IsDirty() { - s.ResetChain(t) - } -} - -// ResetChain stops and clears all nodes state via 'unsafe-reset-all' -func (s *SystemUnderTest) ResetChain(t *testing.T) { - t.Helper() - t.Log("Reset chain") - s.StopChain() - restoreOriginalGenesis(t, s) - restoreOriginalKeyring(t, s) - s.resetBuffers() - - // remove all additional nodes - for i := s.initialNodesCount; i < s.nodesCount; i++ { - _ = os.RemoveAll(filepath.Join(WorkDir, s.nodePath(i))) - _ = os.Remove(filepath.Join(WorkDir, s.outputDir, fmt.Sprintf("node%d.out", i))) - } - s.nodesCount = s.initialNodesCount - - // reset all validator nodes - s.ForEachNodeExecAndWait(t, []string{"comet", "unsafe-reset-all"}) - s.currentHeight.Store(0) - s.dirty = false -} - -// ModifyGenesisCLI executes the CLI commands to modify the genesis -func (s *SystemUnderTest) ModifyGenesisCLI(t *testing.T, cmds ...[]string) { - t.Helper() - s.ForEachNodeExecAndWait(t, cmds...) - s.MarkDirty() -} - -type GenesisMutator func([]byte) []byte - -// ModifyGenesisJSON resets the chain and executes the callbacks to update the json representation -// The mutator callbacks after each other receive the genesis as raw bytes and return the updated genesis for the next. -// example: -// -// return func(genesis []byte) []byte { -// val, _ := json.Marshal(sdk.NewDecCoins(fees...)) -// state, _ := sjson.SetRawBytes(genesis, "app_state.globalfee.params.minimum_gas_prices", val) -// return state -// } -func (s *SystemUnderTest) ModifyGenesisJSON(t *testing.T, mutators ...GenesisMutator) { - t.Helper() - s.ResetChain(t) - s.modifyGenesisJSON(t, mutators...) -} - -// modify json without enforcing a reset -func (s *SystemUnderTest) modifyGenesisJSON(t *testing.T, mutators ...GenesisMutator) { - t.Helper() - require.Empty(t, s.currentHeight.Load(), "forced chain reset required") - current, err := os.ReadFile(filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json")) - require.NoError(t, err) - for _, m := range mutators { - current = m(current) - } - out := StoreTempFile(t, current) - defer os.Remove(out.Name()) - s.setGenesis(t, out.Name()) - s.MarkDirty() -} - -// ReadGenesisJSON returns current genesis.json content as raw string -func (s *SystemUnderTest) ReadGenesisJSON(t *testing.T) string { - t.Helper() - content, err := os.ReadFile(filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json")) - require.NoError(t, err) - return string(content) -} - -// setGenesis copy genesis file to all nodes -func (s *SystemUnderTest) setGenesis(t *testing.T, srcPath string) { - t.Helper() - in, err := os.Open(srcPath) - require.NoError(t, err) - defer in.Close() - var buf bytes.Buffer - - _, err = io.Copy(&buf, in) - require.NoError(t, err) - - s.withEachNodeHome(func(i int, home string) { - require.NoError(t, saveGenesis(home, buf.Bytes())) - }) -} - -func saveGenesis(home string, content []byte) error { - out, err := os.Create(filepath.Join(WorkDir, home, "config", "genesis.json")) - if err != nil { - return fmt.Errorf("out file: %w", err) - } - defer out.Close() - - if _, err = io.Copy(out, bytes.NewReader(content)); err != nil { - return fmt.Errorf("write out file: %w", err) - } - - if err = out.Close(); err != nil { - return fmt.Errorf("close out file: %w", err) - } - return nil -} - -// ForEachNodeExecAndWait runs the given app executable commands for all cluster nodes synchronously -// The commands output is returned for each node. -func (s *SystemUnderTest) ForEachNodeExecAndWait(t *testing.T, cmds ...[]string) [][]string { - t.Helper() - result := make([][]string, s.nodesCount) - s.withEachNodeHome(func(i int, home string) { - result[i] = make([]string, len(cmds)) - for j, xargs := range cmds { - xargs = append(xargs, "--home", home) - s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(xargs, " ")) - out := MustRunShellCmd(t, s.execBinary, xargs...) - s.Logf("Result: %s\n", out) - result[i][j] = out - } - }) - return result -} - -func MustRunShellCmd(t *testing.T, cmd string, args ...string) string { - t.Helper() - out, err := RunShellCmd(cmd, args...) - require.NoError(t, err) - return out -} - -func RunShellCmd(cmd string, args ...string) (string, error) { - c := exec.Command( //nolint:gosec // used by tests only - locateExecutable(cmd), - args..., - ) - c.Dir = WorkDir - out, err := c.Output() - if err != nil { - return string(out), fmt.Errorf("run `%s %s`: out: %s: %w", cmd, strings.Join(args, " "), string(out), err) - } - return string(out), nil -} - -// startNodesAsync runs the given app cli command for all cluster nodes and returns without waiting -func (s *SystemUnderTest) startNodesAsync(t *testing.T, xargs ...string) { - t.Helper() - s.withEachNodeHome(func(i int, home string) { - args := append(xargs, "--home="+home) - s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " ")) - cmd := exec.Command( //nolint:gosec // used by tests only - locateExecutable(s.execBinary), - args..., - ) - cmd.Dir = WorkDir - s.watchLogs(i, cmd) - require.NoError(t, cmd.Start(), "node %d", i) - s.Logf("Node started: %d\n", cmd.Process.Pid) - - // cleanup when stopped - s.awaitProcessCleanup(cmd) - }) -} - -// tracks the PID in state with a go routine waiting for the shutdown completion to unregister -func (s *SystemUnderTest) awaitProcessCleanup(cmd *exec.Cmd) { - pid := cmd.Process.Pid - s.pidsLock.Lock() - s.pids[pid] = struct{}{} - s.pidsLock.Unlock() - go func() { - _ = cmd.Wait() // blocks until shutdown - s.Logf("Node stopped: %d\n", pid) - s.pidsLock.Lock() - delete(s.pids, pid) - s.pidsLock.Unlock() - }() -} - -func (s *SystemUnderTest) withEachNodeHome(cb func(i int, home string)) { - for i := 0; i < s.nodesCount; i++ { - cb(i, s.nodePath(i)) - } -} - -// NodeDir returns the workdir and path to the node home folder. -func (s *SystemUnderTest) NodeDir(i int) string { - return filepath.Join(WorkDir, s.nodePath(i)) -} - -// nodePath returns the path of the node within the work dir. not absolute -func (s *SystemUnderTest) nodePath(i int) string { - return NodePath(i, s.outputDir, s.projectName) -} - -func NodePath(n int, outputDir, name string) string { - return fmt.Sprintf("%s/node%d/%s", outputDir, n, name) -} - -func (s *SystemUnderTest) Log(msg string) { - if s.verbose { - _, _ = fmt.Fprint(s.out, msg) - } -} - -func (s *SystemUnderTest) Logf(msg string, args ...interface{}) { - s.Log(fmt.Sprintf(msg, args...)) -} - -func (s *SystemUnderTest) RPCClient(t *testing.T) RPCClient { - t.Helper() - return NewRPCClient(t, s.rpcAddr) -} - -func (s *SystemUnderTest) APIAddress() string { - return s.apiAddr -} - -func (s *SystemUnderTest) AllPeers(t *testing.T) []string { - t.Helper() - result := make([]string, s.nodesCount) - for i, n := range s.AllNodes(t) { - result[i] = n.PeerAddr() - } - return result -} - -func (s *SystemUnderTest) AllNodes(t *testing.T) []Node { - t.Helper() - return AllNodes(t, s) -} - -func AllNodes(t *testing.T, s *SystemUnderTest) []Node { - t.Helper() - result := make([]Node, s.nodesCount) - outs := s.ForEachNodeExecAndWait(t, []string{"comet", "show-node-id"}) - ip := "127.0.0.1" - if false { // is there still a use case for external ip? - var err error - ip, err = server.ExternalIP() - require.NoError(t, err) - } - for i, out := range outs { - result[i] = Node{ - ID: strings.TrimSpace(out[0]), - IP: ip, - RPCPort: 26657 + i, // as defined in testnet command - P2PPort: 16656 + i, // as defined in testnet command - } - } - return result -} - -func (s *SystemUnderTest) resetBuffers() { - s.outBuff = ring.New(100) - s.errBuff = ring.New(100) -} - -// AddFullnode starts a new fullnode that connects to the existing chain but is not a validator. -func (s *SystemUnderTest) AddFullnode(t *testing.T, beforeStart ...func(nodeNumber int, nodePath string)) Node { - t.Helper() - s.MarkDirty() - s.nodesCount++ - nodeNumber := s.nodesCount - 1 - nodePath := s.nodePath(nodeNumber) - _ = os.RemoveAll(nodePath) // drop any legacy path, just in case - - // prepare new node - moniker := fmt.Sprintf("node%d", nodeNumber) - args := []string{"init", moniker, "--home=" + nodePath, "--overwrite"} - s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " ")) - cmd := exec.Command( //nolint:gosec // used by tests only - locateExecutable(s.execBinary), - args..., - ) - cmd.Dir = WorkDir - s.watchLogs(nodeNumber, cmd) - require.NoError(t, cmd.Run(), "failed to start node with id %d", nodeNumber) - require.NoError(t, saveGenesis(nodePath, []byte(s.ReadGenesisJSON(t)))) - - configPath := filepath.Join(WorkDir, nodePath, "config") - - // quick hack: copy config and overwrite by start params - for _, tomlFile := range []string{"config.toml", "app.toml"} { - configFile := filepath.Join(configPath, tomlFile) - _ = os.Remove(configFile) - _ = MustCopyFile(filepath.Join(WorkDir, s.nodePath(0), "config", tomlFile), configFile) - } - // start node - allNodes := s.AllNodes(t) - node := allNodes[len(allNodes)-1] - peers := make([]string, len(allNodes)-1) - for i, n := range allNodes[0 : len(allNodes)-1] { - peers[i] = n.PeerAddr() - } - for _, c := range beforeStart { - c(nodeNumber, nodePath) - } - args = []string{ - "start", - "--p2p.persistent_peers=" + strings.Join(peers, ","), - fmt.Sprintf("--p2p.laddr=tcp://localhost:%d", node.P2PPort), - fmt.Sprintf("--rpc.laddr=tcp://localhost:%d", node.RPCPort), - fmt.Sprintf("--grpc.address=localhost:%d", 9090+nodeNumber), - "--p2p.pex=false", - "--moniker=" + moniker, - "--log_level=info", - "--log_no_color", - "--home", nodePath, - } - s.Logf("Execute `%s %s`\n", s.execBinary, strings.Join(args, " ")) - cmd = exec.Command( //nolint:gosec // used by tests only - locateExecutable(s.execBinary), - args..., - ) - cmd.Dir = WorkDir - s.watchLogs(nodeNumber, cmd) - require.NoError(t, cmd.Start(), "node %d", nodeNumber) - s.awaitProcessCleanup(cmd) - return node -} - -// NewEventListener constructor for Eventlistener with system rpc address -func (s *SystemUnderTest) NewEventListener(t *testing.T) *EventListener { - t.Helper() - return NewEventListener(t, s.rpcAddr) -} - -// is any process let running? -func (s *SystemUnderTest) anyNodeRunning() bool { - s.pidsLock.RLock() - defer s.pidsLock.RUnlock() - return len(s.pids) != 0 -} - -func (s *SystemUnderTest) CurrentHeight() int64 { - return s.currentHeight.Load() -} - -// NodesCount returns the number of node instances used -func (s *SystemUnderTest) NodesCount() int { - return s.nodesCount -} - -type Node struct { - ID string - IP string - RPCPort int - P2PPort int -} - -func (n Node) PeerAddr() string { - return fmt.Sprintf("%s@%s:%d", n.ID, n.IP, n.P2PPort) -} - -func (n Node) RPCAddr() string { - return fmt.Sprintf("tcp://%s:%d", n.IP, n.RPCPort) -} - -// locateExecutable looks up the binary on the OS path. -func locateExecutable(file string) string { - if strings.TrimSpace(file) == "" { - panic("executable binary name must not be empty") - } - path, err := exec.LookPath(file) - if err != nil { - panic(fmt.Sprintf("unexpected error with file %q: %s", file, err.Error())) - } - if path == "" { - panic(fmt.Sprintf("%q not found", file)) - } - return path -} - -// EventListener watches for events on the chain -type EventListener struct { - t *testing.T - client *client.HTTP -} - -// NewEventListener event listener -func NewEventListener(t *testing.T, rpcAddr string) *EventListener { - t.Helper() - httpClient, err := client.New(rpcAddr, "/websocket") - require.NoError(t, err) - require.NoError(t, httpClient.Start()) - return &EventListener{client: httpClient, t: t} -} - -var DefaultWaitTime = 30 * time.Second - -type ( - CleanupFn func() - EventConsumer func(e ctypes.ResultEvent) (more bool) -) - -// Subscribe to receive events for a topic. Does not block. -// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events -func (l *EventListener) Subscribe(query string, cb EventConsumer) func() { - ctx, done := context.WithCancel(context.Background()) - l.t.Cleanup(done) - eventsChan, err := l.client.WSEvents.Subscribe(ctx, "testing", query) - require.NoError(l.t, err) - cleanup := func() { - ctx, _ := context.WithTimeout(ctx, DefaultWaitTime) //nolint:govet // used in cleanup only - go l.client.WSEvents.Unsubscribe(ctx, "testing", query) //nolint:errcheck // used by tests only - done() - } - go func() { - for e := range eventsChan { - if !cb(e) { - return - } - } - }() - return cleanup -} - -// AwaitQuery blocks and waits for a single result or timeout. This can be used with `broadcast-mode=async`. -// For query syntax See https://docs.cosmos.network/master/core/events.html#subscribing-to-events -func (l *EventListener) AwaitQuery(query string, optMaxWaitTime ...time.Duration) *ctypes.ResultEvent { - c, result := CaptureSingleEventConsumer() - maxWaitTime := DefaultWaitTime - if len(optMaxWaitTime) != 0 { - maxWaitTime = optMaxWaitTime[0] - } - cleanupFn := l.Subscribe(query, TimeoutConsumer(l.t, maxWaitTime, c)) - l.t.Cleanup(cleanupFn) - return result -} - -// TimeoutConsumer is an event consumer decorator with a max wait time. Panics when wait time exceeded without -// a result returned -func TimeoutConsumer(t *testing.T, maxWaitTime time.Duration, next EventConsumer) EventConsumer { - t.Helper() - ctx, done := context.WithCancel(context.Background()) - t.Cleanup(done) - timeout := time.NewTimer(maxWaitTime) - timedOut := make(chan struct{}, 1) - go func() { - select { - case <-ctx.Done(): - case <-timeout.C: - timedOut <- struct{}{} - close(timedOut) - } - }() - return func(e ctypes.ResultEvent) (more bool) { - select { - case <-timedOut: - t.Fatalf("Timeout waiting for new events %s", maxWaitTime) - return false - default: - timeout.Reset(maxWaitTime) - result := next(e) - if !result { - done() - } - return result - } - } -} - -// CaptureSingleEventConsumer consumes one event. No timeout -func CaptureSingleEventConsumer() (EventConsumer, *ctypes.ResultEvent) { - var result ctypes.ResultEvent - return func(e ctypes.ResultEvent) (more bool) { - return false - }, &result -} - -// CaptureAllEventsConsumer is an `EventConsumer` that captures all events until `done()` is called to stop or timeout happens. -// The consumer works async in the background and returns all the captured events when `done()` is called. -// This can be used to verify that certain events have happened. -// Example usage: -// -// c, done := CaptureAllEventsConsumer(t) -// query := `tm.event='Tx'` -// cleanupFn := l.Subscribe(query, c) -// t.Cleanup(cleanupFn) -// -// // do something in your test that create events -// -// assert.Len(t, done(), 1) // then verify your assumption -func CaptureAllEventsConsumer(t *testing.T, optMaxWaitTime ...time.Duration) (c EventConsumer, done func() []ctypes.ResultEvent) { - t.Helper() - maxWaitTime := DefaultWaitTime - if len(optMaxWaitTime) != 0 { - maxWaitTime = optMaxWaitTime[0] - } - var ( - mu sync.Mutex - capturedEvents []ctypes.ResultEvent - exit bool - ) - collectEventsConsumer := func(e ctypes.ResultEvent) (more bool) { - mu.Lock() - defer mu.Unlock() - if exit { - return false - } - capturedEvents = append(capturedEvents, e) - return true - } - - return TimeoutConsumer(t, maxWaitTime, collectEventsConsumer), func() []ctypes.ResultEvent { - mu.Lock() - defer mu.Unlock() - exit = true - return capturedEvents - } -} - -// restoreOriginalGenesis replace nodes genesis by the one created on setup -func restoreOriginalGenesis(t *testing.T, s *SystemUnderTest) { - t.Helper() - src := filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json.orig") - s.setGenesis(t, src) -} - -// restoreOriginalKeyring replaces test keyring with original -func restoreOriginalKeyring(t *testing.T, s *SystemUnderTest) { - t.Helper() - dest := filepath.Join(WorkDir, s.outputDir, "keyring-test") - require.NoError(t, os.RemoveAll(dest)) - for i := 0; i < s.initialNodesCount; i++ { - src := filepath.Join(WorkDir, s.nodePath(i), "keyring-test") - MustCopyFilesInDir(src, dest) - } -} diff --git a/tests/systemtests/test_runner.go b/tests/systemtests/test_runner.go deleted file mode 100644 index e1227e9b386f..000000000000 --- a/tests/systemtests/test_runner.go +++ /dev/null @@ -1,129 +0,0 @@ -package systemtests - -import ( - "flag" - "fmt" - "os" - "os/exec" - "strconv" - "strings" - "testing" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -var ( - sut *SystemUnderTest - verbose bool - execBinaryName string -) - -func RunTests(m *testing.M) { - waitTime := flag.Duration("wait-time", DefaultWaitTime, "time to wait for chain events") - nodesCount := flag.Int("nodes-count", 4, "number of nodes in the cluster") - blockTime := flag.Duration("block-time", 1000*time.Millisecond, "block creation time") - execBinary := flag.String("binary", "simd", "executable binary for server/ client side") - bech32Prefix := flag.String("bech32", "cosmos", "bech32 prefix to be used with addresses") - flag.BoolVar(&verbose, "verbose", false, "verbose output") - flag.Parse() - - // fail fast on most common setup issue - requireEnoughFileHandlers(*nodesCount + 1) // +1 as tests may start another node - - dir, err := os.Getwd() - if err != nil { - panic(err) - } - WorkDir = dir - if verbose { - println("Work dir: ", WorkDir) - } - initSDKConfig(*bech32Prefix) - - DefaultWaitTime = *waitTime - if *execBinary == "" { - panic("executable binary name must not be empty") - } - execBinaryName = *execBinary - - sut = NewSystemUnderTest(*execBinary, verbose, *nodesCount, *blockTime) - sut.SetupChain() // setup chain and keyring - - // run tests - exitCode := m.Run() - - // postprocess - sut.StopChain() - if verbose || exitCode != 0 { - sut.PrintBuffer() - printResultFlag(exitCode == 0) - } - - os.Exit(exitCode) -} - -func GetSystemUnderTest() *SystemUnderTest { - return sut -} - -func IsVerbose() bool { - return verbose -} - -func GetExecutableName() string { - return execBinaryName -} - -// requireEnoughFileHandlers uses `ulimit` -func requireEnoughFileHandlers(nodesCount int) { - ulimit, err := exec.LookPath("ulimit") - if err != nil || ulimit == "" { // skip when not available - return - } - - cmd := exec.Command(ulimit, "-n") - cmd.Dir = WorkDir - out, err := cmd.CombinedOutput() - if err != nil { - panic(fmt.Sprintf("unexpected error :%#+v, output: %s", err, string(out))) - } - fileDescrCount, err := strconv.Atoi(strings.Trim(string(out), " \t\n")) - if err != nil { - panic(fmt.Sprintf("unexpected error :%#+v, output: %s", err, string(out))) - } - expFH := nodesCount * 260 // random number that worked on my box - if fileDescrCount < expFH { - panic(fmt.Sprintf("Fail fast. Insufficient setup. Run 'ulimit -n %d'", expFH)) - } -} - -func initSDKConfig(bech32Prefix string) { - config := sdk.GetConfig() - config.SetBech32PrefixForAccount(bech32Prefix, bech32Prefix+sdk.PrefixPublic) - config.SetBech32PrefixForValidator(bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator, bech32Prefix+sdk.PrefixValidator+sdk.PrefixOperator+sdk.PrefixPublic) - config.SetBech32PrefixForConsensusNode(bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus, bech32Prefix+sdk.PrefixValidator+sdk.PrefixConsensus+sdk.PrefixPublic) -} - -const ( - successFlag = ` - ___ _ _ ___ ___ ___ ___ ___ -/ __| | | |/ __/ __/ _ \/ __/ __| -\__ \ |_| | (_| (_| __/\__ \__ \ -|___/\__,_|\___\___\___||___/___/` - failureFlag = ` - __ _ _ _ - / _| (_) | | | -| |_ __ _ _| | ___ __| | -| _/ _| | | |/ _ \/ _| | -| || (_| | | | __/ (_| | -|_| \__,_|_|_|\___|\__,_|` -) - -func printResultFlag(ok bool) { - if ok { - fmt.Println(successFlag) - } else { - fmt.Println(failureFlag) - } -} diff --git a/tests/systemtests/testnet_init.go b/tests/systemtests/testnet_init.go deleted file mode 100644 index 9033c283e43a..000000000000 --- a/tests/systemtests/testnet_init.go +++ /dev/null @@ -1,234 +0,0 @@ -package systemtests - -import ( - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/cometbft/cometbft/p2p" - "github.com/creachadair/tomledit" - "github.com/creachadair/tomledit/parser" -) - -// isV2 checks if the tests run with simapp v2 -func isV2() bool { - buildOptions := os.Getenv("COSMOS_BUILD_OPTIONS") - return strings.Contains(buildOptions, "v2") -} - -// SingleHostTestnetCmdInitializer default testnet cmd that supports the --single-host param -type SingleHostTestnetCmdInitializer struct { - execBinary string - workDir string - chainID string - outputDir string - initialNodesCount int - minGasPrice string - commitTimeout time.Duration - log func(string) -} - -// NewSingleHostTestnetCmdInitializer constructor -func NewSingleHostTestnetCmdInitializer( - execBinary, workDir, chainID, outputDir string, - initialNodesCount int, - minGasPrice string, - commitTimeout time.Duration, - log func(string), -) *SingleHostTestnetCmdInitializer { - return &SingleHostTestnetCmdInitializer{ - execBinary: execBinary, - workDir: workDir, - chainID: chainID, - outputDir: outputDir, - initialNodesCount: initialNodesCount, - minGasPrice: minGasPrice, - commitTimeout: commitTimeout, - log: log, - } -} - -// InitializerWithBinary creates new SingleHostTestnetCmdInitializer from sut with given binary -func InitializerWithBinary(binary string, sut *SystemUnderTest) TestnetInitializer { - return NewSingleHostTestnetCmdInitializer( - binary, - WorkDir, - sut.chainID, - sut.outputDir, - sut.initialNodesCount, - sut.minGasPrice, - sut.CommitTimeout(), - sut.Log, - ) -} - -func (s SingleHostTestnetCmdInitializer) Initialize() { - args := []string{ - "testnet", - "init-files", - "--chain-id=" + s.chainID, - "--output-dir=" + s.outputDir, - "--validator-count=" + strconv.Itoa(s.initialNodesCount), - "--keyring-backend=test", - "--commit-timeout=" + s.commitTimeout.String(), - "--single-host", - } - - if isV2() { - args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) - } else { - args = append(args, "--minimum-gas-prices="+s.minGasPrice) - } - - s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) - out, err := RunShellCmd(s.execBinary, args...) - if err != nil { - panic(err) - } - s.log(out) -} - -// ModifyConfigYamlInitializer testnet cmd prior to --single-host param. Modifies the toml files. -type ModifyConfigYamlInitializer struct { - execBinary string - workDir string - chainID string - outputDir string - initialNodesCount int - minGasPrice string - commitTimeout time.Duration - log func(string) - projectName string -} - -func NewModifyConfigYamlInitializer(exec string, s *SystemUnderTest) *ModifyConfigYamlInitializer { - return &ModifyConfigYamlInitializer{ - execBinary: exec, - workDir: WorkDir, - chainID: s.chainID, - outputDir: s.outputDir, - initialNodesCount: s.initialNodesCount, - minGasPrice: s.minGasPrice, - commitTimeout: s.CommitTimeout(), - log: s.Log, - projectName: s.projectName, - } -} - -const ( - rpcPortStart = 26657 - apiPortStart = 1317 - grpcPortStart = 9090 - p2pPortStart = 16656 -) - -func (s ModifyConfigYamlInitializer) Initialize() { - // init with legacy testnet command - args := []string{ - "testnet", - "init-files", - "--chain-id=" + s.chainID, - "--output-dir=" + s.outputDir, - "--v=" + strconv.Itoa(s.initialNodesCount), - "--keyring-backend=test", - } - - if isV2() { - args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) - } else { - args = append(args, "--minimum-gas-prices="+s.minGasPrice) - } - - s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) - - out, err := RunShellCmd(s.execBinary, args...) - if err != nil { - panic(err) - } - s.log(out) - - nodeAddresses := make([]string, s.initialNodesCount) - for i := 0; i < s.initialNodesCount; i++ { - nodeDir := filepath.Join(WorkDir, NodePath(i, s.outputDir, s.projectName), "config") - id := string(mustV(p2p.LoadNodeKey(filepath.Join(nodeDir, "node_key.json"))).ID()) - nodeAddresses[i] = fmt.Sprintf("%s@127.0.0.1:%d", id, p2pPortStart+i) - } - - // then update configs - for i := 0; i < s.initialNodesCount; i++ { - nodeDir := filepath.Join(WorkDir, NodePath(i, s.outputDir, s.projectName), "config") - nodeNumber := i - EditToml(filepath.Join(nodeDir, "config.toml"), func(doc *tomledit.Document) { - UpdatePort(doc, rpcPortStart+i, "rpc", "laddr") - UpdatePort(doc, p2pPortStart+i, "p2p", "laddr") - SetBool(doc, false, "p2p", "addr_book_strict") - SetBool(doc, false, "p2p", "pex") - SetBool(doc, true, "p2p", "allow_duplicate_ip") - peers := make([]string, s.initialNodesCount) - copy(peers, nodeAddresses[0:nodeNumber]) - copy(peers[nodeNumber:], nodeAddresses[nodeNumber+1:]) - SetValue(doc, strings.Join(peers, ","), "p2p", "persistent_peers") - SetValue(doc, s.commitTimeout.String(), "consensus", "timeout_commit") - }) - EditToml(filepath.Join(nodeDir, "app.toml"), func(doc *tomledit.Document) { - UpdatePort(doc, apiPortStart+i, "api", "address") - UpdatePort(doc, grpcPortStart+i, "grpc", "address") - }) - } -} - -func EditToml(filename string, f func(doc *tomledit.Document)) { - tomlFile := mustV(os.OpenFile(filename, os.O_RDWR, 0o600)) - defer tomlFile.Close() - doc := mustV(tomledit.Parse(tomlFile)) - f(doc) - mustV(tomlFile.Seek(0, 0)) // reset the cursor to the beginning of the file - must(tomlFile.Truncate(0)) - must(tomledit.Format(tomlFile, doc)) -} - -func SetBool(doc *tomledit.Document, newVal bool, xpath ...string) { - e := doc.First(xpath...) - if e == nil { - panic(fmt.Sprintf("not found: %v", xpath)) - } - e.Value = parser.MustValue(strconv.FormatBool(newVal)) -} - -func SetValue(doc *tomledit.Document, newVal string, xpath ...string) { - e := doc.First(xpath...) - if e == nil { - panic(fmt.Sprintf("not found: %v", xpath)) - } - e.Value = parser.MustValue(fmt.Sprintf("%q", newVal)) -} - -func UpdatePort(doc *tomledit.Document, newPort int, xpath ...string) { - e := doc.First(xpath...) - if e == nil { - panic(fmt.Sprintf("not found: %v", xpath)) - } - data := e.Value.X.String() - pos := strings.LastIndexAny(data, ":") - if pos == -1 { - panic("column not found") - } - data = data[0:pos+1] + strconv.Itoa(newPort) - e.Value = parser.MustValue(data + "\"") -} - -// mustV same as must but with value returned -func mustV[T any](r T, err error) T { - must(err) - return r -} - -// must simple panic on error for fluent calls -func must(err error) { - if err != nil { - panic(err) - } -} diff --git a/tests/systemtests/tx_test.go b/tests/systemtests/tx_test.go index 344aff775ebc..84a0c9fc20c2 100644 --- a/tests/systemtests/tx_test.go +++ b/tests/systemtests/tx_test.go @@ -6,23 +6,23 @@ import ( "context" "encoding/base64" "encoding/json" - "os" - "fmt" - + "os" "testing" - "github.com/cosmos/cosmos-sdk/testutil" - "github.com/cosmos/cosmos-sdk/types/tx" "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + systest "cosmossdk.io/systemtests" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/legacy" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/std" + "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -34,9 +34,9 @@ var ( ) func TestQueryBySig(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -44,21 +44,21 @@ func TestQueryBySig(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) // create unsign tx - bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=10stake", fmt.Sprintf("--chain-id=%s", sut.chainID), "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=10stake", "--chain-id=" + cli.ChainID(), "--sign-mode=direct", "--generate-only"} unsignedTx := cli.RunCommandWithArgs(bankSendCmdArgs...) - txFile := StoreTempFile(t, []byte(unsignedTx)) + txFile := systest.StoreTempFile(t, []byte(unsignedTx)) - signedTx := cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", valAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet/node0/simd") + signedTx := cli.RunCommandWithArgs("tx", "sign", txFile.Name(), "--from="+valAddr, "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home="+systest.Sut.NodeDir(0)) sig := gjson.Get(signedTx, "signatures.0").String() - signedTxFile := StoreTempFile(t, []byte(signedTx)) + signedTxFile := systest.StoreTempFile(t, []byte(signedTx)) res := cli.Run("tx", "broadcast", signedTxFile.Name()) - RequireTxSuccess(t, res) + systest.RequireTxSuccess(t, res) sigFormatted := fmt.Sprintf("%s.%s='%s'", sdk.EventTypeTx, sdk.AttributeKeySignature, sig) resp, err := qc.GetTxsEvent(context.Background(), &tx.GetTxsEventRequest{ @@ -73,9 +73,9 @@ func TestQueryBySig(t *testing.T) { } func TestSimulateTx_GRPC(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -83,17 +83,17 @@ func TestSimulateTx_GRPC(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) // create unsign tx - bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), fmt.Sprintf("--chain-id=%s", sut.chainID), "--fees=10stake", "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + cli.ChainID(), "--fees=10stake", "--sign-mode=direct", "--generate-only"} res := cli.RunCommandWithArgs(bankSendCmdArgs...) - txFile := StoreTempFile(t, []byte(res)) + txFile := systest.StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", valAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet/node0/simd") - signedTxFile := StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), "--from="+valAddr, "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home="+systest.Sut.NodeDir(0)) + signedTxFile := systest.StoreTempFile(t, []byte(res)) res = cli.RunCommandWithArgs("tx", "encode", signedTxFile.Name()) txBz, err := base64.StdEncoding.DecodeString(res) @@ -135,9 +135,9 @@ func TestSimulateTx_GRPC(t *testing.T) { } func TestSimulateTx_GRPCGateway(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -145,18 +145,18 @@ func TestSimulateTx_GRPCGateway(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) // qc := tx.NewServiceClient(sut.RPCClient(t)) - baseURL := sut.APIAddress() + baseURL := systest.Sut.APIAddress() // create unsign tx - bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), fmt.Sprintf("--chain-id=%s", sut.chainID), "--fees=10stake", "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + cli.ChainID(), "--fees=10stake", "--sign-mode=direct", "--generate-only"} res := cli.RunCommandWithArgs(bankSendCmdArgs...) - txFile := StoreTempFile(t, []byte(res)) + txFile := systest.StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", valAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet/node0/simd") - signedTxFile := StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), "--from="+valAddr, "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home="+systest.Sut.NodeDir(0)) + signedTxFile := systest.StoreTempFile(t, []byte(res)) res = cli.RunCommandWithArgs("tx", "encode", signedTxFile.Name()) txBz, err := base64.StdEncoding.DecodeString(res) @@ -197,9 +197,9 @@ func TestSimulateTx_GRPCGateway(t *testing.T) { } func TestGetTxEvents_GRPC(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -207,18 +207,18 @@ func TestGetTxEvents_GRPC(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) rsp := cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--note=foobar", "--fees=1stake") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) rsp = cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake") txResult, found = cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) testCases := []struct { name string @@ -311,9 +311,9 @@ func TestGetTxEvents_GRPC(t *testing.T) { } func TestGetTxEvents_GRPCGateway(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -321,19 +321,19 @@ func TestGetTxEvents_GRPCGateway(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) // qc := tx.NewServiceClient(sut.RPCClient(t)) - baseURL := sut.APIAddress() + baseURL := systest.Sut.APIAddress() rsp := cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--note=foobar", "--fees=1stake") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) rsp = cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake") txResult, found = cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) testCases := []struct { name string @@ -407,9 +407,9 @@ func TestGetTxEvents_GRPCGateway(t *testing.T) { } func TestGetTx_GRPC(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -417,14 +417,14 @@ func TestGetTx_GRPC(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) rsp := cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake", "--note=foobar") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) txHash := gjson.Get(txResult, "txhash").String() testCases := []struct { @@ -454,9 +454,9 @@ func TestGetTx_GRPC(t *testing.T) { } func TestGetTx_GRPCGateway(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -464,14 +464,14 @@ func TestGetTx_GRPCGateway(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - baseURL := sut.APIAddress() + baseURL := systest.Sut.APIAddress() rsp := cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake", "--note=foobar") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) txHash := gjson.Get(txResult, "txhash").String() testCases := []struct { @@ -517,9 +517,9 @@ func TestGetTx_GRPCGateway(t *testing.T) { } func TestGetBlockWithTxs_GRPC(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -527,14 +527,14 @@ func TestGetBlockWithTxs_GRPC(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) rsp := cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake", "--note=foobar") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) height := gjson.Get(txResult, "height").Int() testCases := []struct { @@ -575,9 +575,9 @@ func TestGetBlockWithTxs_GRPC(t *testing.T) { } func TestGetBlockWithTxs_GRPCGateway(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -585,14 +585,14 @@ func TestGetBlockWithTxs_GRPCGateway(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - baseUrl := sut.APIAddress() + baseUrl := systest.Sut.APIAddress() rsp := cli.Run("tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake", "--note=foobar") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) height := gjson.Get(txResult, "height").Int() testCases := []struct { @@ -635,16 +635,16 @@ func TestGetBlockWithTxs_GRPCGateway(t *testing.T) { } func TestTxEncode_GRPC(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) protoTx := &tx.Tx{ Body: &tx.TxBody{ @@ -680,16 +680,16 @@ func TestTxEncode_GRPC(t *testing.T) { } func TestTxEncode_GRPCGateway(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) - sut.StartChain(t) + systest.Sut.StartChain(t) - baseUrl := sut.APIAddress() + baseUrl := systest.Sut.APIAddress() protoTx := &tx.Tx{ Body: &tx.TxBody{ @@ -724,9 +724,9 @@ func TestTxEncode_GRPCGateway(t *testing.T) { } func TestTxDecode_GRPC(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -734,17 +734,17 @@ func TestTxDecode_GRPC(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) // create unsign tx - bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), fmt.Sprintf("--chain-id=%s", sut.chainID), "--fees=10stake", "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + cli.ChainID(), "--fees=10stake", "--sign-mode=direct", "--generate-only"} res := cli.RunCommandWithArgs(bankSendCmdArgs...) - txFile := StoreTempFile(t, []byte(res)) + txFile := systest.StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", valAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet/node0/simd") - signedTxFile := StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), "--from="+valAddr, "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home="+systest.Sut.NodeDir(0)) + signedTxFile := systest.StoreTempFile(t, []byte(res)) res = cli.RunCommandWithArgs("tx", "encode", signedTxFile.Name()) txBz, err := base64.StdEncoding.DecodeString(res) @@ -779,9 +779,9 @@ func TestTxDecode_GRPC(t *testing.T) { } func TestTxDecode_GRPCGateway(t *testing.T) { - sut.ResetChain(t) + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -789,17 +789,17 @@ func TestTxDecode_GRPCGateway(t *testing.T) { // add new key receiverAddr := cli.AddKey("account1") - sut.StartChain(t) + systest.Sut.StartChain(t) - basrUrl := sut.APIAddress() + basrUrl := systest.Sut.APIAddress() // create unsign tx - bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), fmt.Sprintf("--chain-id=%s", sut.chainID), "--fees=10stake", "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", valAddr, receiverAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + cli.ChainID(), "--fees=10stake", "--sign-mode=direct", "--generate-only"} res := cli.RunCommandWithArgs(bankSendCmdArgs...) - txFile := StoreTempFile(t, []byte(res)) + txFile := systest.StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", valAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet/node0/simd") - signedTxFile := StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), "--from="+valAddr, "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home="+systest.Sut.NodeDir(0)) + signedTxFile := systest.StoreTempFile(t, []byte(res)) res = cli.RunCommandWithArgs("tx", "encode", signedTxFile.Name()) txBz, err := base64.StdEncoding.DecodeString(res) @@ -835,15 +835,15 @@ func TestTxDecode_GRPCGateway(t *testing.T) { } func TestTxEncodeAmino_GRPC(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) legacyAmino := codec.NewLegacyAmino() std.RegisterLegacyAminoCodec(legacyAmino) legacytx.RegisterLegacyAminoCodec(legacyAmino) legacy.RegisterAminoMsg(legacyAmino, &banktypes.MsgSend{}, "cosmos-sdk/MsgSend") - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) txJSONBytes, stdTx := readTestAminoTxJSON(t, legacyAmino) testCases := []struct { @@ -879,15 +879,15 @@ func TestTxEncodeAmino_GRPC(t *testing.T) { } func TestTxEncodeAmino_GRPCGateway(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) legacyAmino := codec.NewLegacyAmino() std.RegisterLegacyAminoCodec(legacyAmino) legacytx.RegisterLegacyAminoCodec(legacyAmino) legacy.RegisterAminoMsg(legacyAmino, &banktypes.MsgSend{}, "cosmos-sdk/MsgSend") - baseUrl := sut.APIAddress() + baseUrl := systest.Sut.APIAddress() txJSONBytes, stdTx := readTestAminoTxJSON(t, legacyAmino) testCases := []struct { @@ -925,15 +925,15 @@ func TestTxEncodeAmino_GRPCGateway(t *testing.T) { } func TestTxDecodeAmino_GRPC(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) legacyAmino := codec.NewLegacyAmino() std.RegisterLegacyAminoCodec(legacyAmino) legacytx.RegisterLegacyAminoCodec(legacyAmino) legacy.RegisterAminoMsg(legacyAmino, &banktypes.MsgSend{}, "cosmos-sdk/MsgSend") - qc := tx.NewServiceClient(sut.RPCClient(t)) + qc := tx.NewServiceClient(systest.Sut.RPCClient(t)) encodedTx, stdTx := readTestAminoTxBinary(t, legacyAmino) invalidTxBytes := append(encodedTx, byte(0o00)) @@ -971,15 +971,15 @@ func TestTxDecodeAmino_GRPC(t *testing.T) { } func TestTxDecodeAmino_GRPCGateway(t *testing.T) { - sut.ResetChain(t) - sut.StartChain(t) + systest.Sut.ResetChain(t) + systest.Sut.StartChain(t) legacyAmino := codec.NewLegacyAmino() std.RegisterLegacyAminoCodec(legacyAmino) legacytx.RegisterLegacyAminoCodec(legacyAmino) legacy.RegisterAminoMsg(legacyAmino, &banktypes.MsgSend{}, "cosmos-sdk/MsgSend") - baseUrl := sut.APIAddress() + baseUrl := systest.Sut.APIAddress() encodedTx, stdTx := readTestAminoTxBinary(t, legacyAmino) invalidTxBytes := append(encodedTx, byte(0o00)) @@ -1019,9 +1019,11 @@ func TestTxDecodeAmino_GRPCGateway(t *testing.T) { } func TestSimMultiSigTx(t *testing.T) { - sut.ResetChain(t) + t.Skip() // waiting for @hieuvubk fix + + systest.Sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // get validator address valAddr := cli.GetKeyAddr("node0") require.NotEmpty(t, valAddr) @@ -1030,7 +1032,7 @@ func TestSimMultiSigTx(t *testing.T) { _ = cli.AddKey("account1") _ = cli.AddKey("account2") - sut.StartChain(t) + systest.Sut.StartChain(t) multiSigName := "multisig" cli.RunCommandWithArgs("keys", "add", multiSigName, "--multisig=account1,account2", "--multisig-threshold=2", "--keyring-backend=test", "--home=./testnet") @@ -1040,7 +1042,7 @@ func TestSimMultiSigTx(t *testing.T) { rsp := cli.Run("tx", "bank", "send", valAddr, multiSigAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--fees=1stake") txResult, found := cli.AwaitTxCommitted(rsp) require.True(t, found) - RequireTxSuccess(t, txResult) + systest.RequireTxSuccess(t, txResult) multiSigBalance := cli.QueryBalance(multiSigAddr, denom) require.Equal(t, multiSigBalance, transferAmount) @@ -1048,20 +1050,20 @@ func TestSimMultiSigTx(t *testing.T) { // Send from multisig to validator // create unsign tx var newTransferAmount int64 = 100 - bankSendCmdArgs := []string{"tx", "bank", "send", multiSigAddr, valAddr, fmt.Sprintf("%d%s", newTransferAmount, denom), fmt.Sprintf("--chain-id=%s", sut.chainID), "--fees=10stake", "--sign-mode=direct", "--generate-only"} + bankSendCmdArgs := []string{"tx", "bank", "send", multiSigAddr, valAddr, fmt.Sprintf("%d%s", newTransferAmount, denom), "--chain-id=" + cli.ChainID(), "--fees=10stake", "--sign-mode=direct", "--generate-only"} res := cli.RunCommandWithArgs(bankSendCmdArgs...) - txFile := StoreTempFile(t, []byte(res)) + txFile := systest.StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", "account1"), fmt.Sprintf("--multisig=%s", multiSigAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet") - account1Signed := StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", "account2"), fmt.Sprintf("--multisig=%s", multiSigAddr), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet") - account2Signed := StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", "account1"), fmt.Sprintf("--multisig=%s", multiSigAddr), "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home=./testnet") + account1Signed := systest.StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "sign", txFile.Name(), fmt.Sprintf("--from=%s", "account2"), fmt.Sprintf("--multisig=%s", multiSigAddr), "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home=./testnet") + account2Signed := systest.StoreTempFile(t, []byte(res)) - res = cli.RunCommandWithArgs("tx", "multisign-batch", txFile.Name(), multiSigName, account1Signed.Name(), account2Signed.Name(), fmt.Sprintf("--chain-id=%s", sut.chainID), "--keyring-backend=test", "--home=./testnet") - txSignedFile := StoreTempFile(t, []byte(res)) + res = cli.RunCommandWithArgs("tx", "multisign-batch", txFile.Name(), multiSigName, account1Signed.Name(), account2Signed.Name(), "--chain-id="+cli.ChainID(), "--keyring-backend=test", "--home=./testnet") + txSignedFile := systest.StoreTempFile(t, []byte(res)) res = cli.Run("tx", "broadcast", txSignedFile.Name()) - RequireTxSuccess(t, res) + systest.RequireTxSuccess(t, res) multiSigBalance = cli.QueryBalance(multiSigAddr, denom) require.Equal(t, multiSigBalance, transferAmount-newTransferAmount-10) diff --git a/tests/systemtests/unordered_tx_test.go b/tests/systemtests/unordered_tx_test.go index 579552efe0e7..aec8f914130c 100644 --- a/tests/systemtests/unordered_tx_test.go +++ b/tests/systemtests/unordered_tx_test.go @@ -9,31 +9,35 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + systest "cosmossdk.io/systemtests" ) func TestUnorderedTXDuplicate(t *testing.T) { - t.Skip("The unordered tx handling is not wired in v2") - + if systest.IsV2() { + t.Skip("The unordered tx handling is not wired in v2") + return + } // scenario: test unordered tx duplicate // given a running chain with a tx in the unordered tx pool // when a new tx with the same hash is broadcasted // then the new tx should be rejected - sut.ResetChain(t) - cli := NewCLIWrapper(t, sut, verbose) + systest.Sut.ResetChain(t) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // add genesis account with some tokens account1Addr := cli.AddKey("account1") account2Addr := cli.AddKey("account2") - sut.ModifyGenesisCLI(t, + systest.Sut.ModifyGenesisCLI(t, []string{"genesis", "add-genesis-account", account1Addr, "10000000stake"}, ) - sut.StartChain(t) + systest.Sut.StartChain(t) timeoutTimestamp := time.Now().Add(time.Minute) // send tokens rsp1 := cli.Run("tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from="+account1Addr, "--fees=1stake", fmt.Sprintf("--timeout-timestamp=%v", timeoutTimestamp.Unix()), "--unordered", "--sequence=1", "--note=1") - RequireTxSuccess(t, rsp1) + systest.RequireTxSuccess(t, rsp1) assertDuplicateErr := func(xt assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { require.Len(t, gotOutputs, 1) @@ -41,9 +45,9 @@ func TestUnorderedTXDuplicate(t *testing.T) { return false // always abort } rsp2 := cli.WithRunErrorMatcher(assertDuplicateErr).Run("tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from="+account1Addr, "--fees=1stake", fmt.Sprintf("--timeout-timestamp=%v", timeoutTimestamp.Unix()), "--unordered", "--sequence=1") - RequireTxFailure(t, rsp2) + systest.RequireTxFailure(t, rsp2) require.Eventually(t, func() bool { return cli.QueryBalance(account2Addr, "stake") == 5000 - }, time.Minute, time.Microsecond*500, "TX was not executed before timeout") + }, 10*systest.Sut.BlockTime(), 200*time.Millisecond, "TX was not executed before timeout") } diff --git a/tests/systemtests/upgrade_test.go b/tests/systemtests/upgrade_test.go index 85dde92d2023..febefcee0e08 100644 --- a/tests/systemtests/upgrade_test.go +++ b/tests/systemtests/upgrade_test.go @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + systest "cosmossdk.io/systemtests" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" ) @@ -21,26 +23,26 @@ func TestChainUpgrade(t *testing.T) { // start a legacy chain with some state // when a chain upgrade proposal is executed // then the chain upgrades successfully - sut.StopChain() + systest.Sut.StopChain() legacyBinary := FetchExecutable(t, "v0.50") t.Logf("+++ legacy binary: %s\n", legacyBinary) - currentBranchBinary := sut.execBinary - currentInitializer := sut.testnetInitializer - sut.SetExecBinary(legacyBinary) - sut.SetTestnetInitializer(NewModifyConfigYamlInitializer(legacyBinary, sut)) - sut.SetupChain() + currentBranchBinary := systest.Sut.ExecBinary() + currentInitializer := systest.Sut.TestnetInitializer() + systest.Sut.SetExecBinary(legacyBinary) + systest.Sut.SetTestnetInitializer(systest.InitializerWithBinary(legacyBinary, systest.Sut)) + systest.Sut.SetupChain() votingPeriod := 5 * time.Second // enough time to vote - sut.ModifyGenesisJSON(t, SetGovVotingPeriod(t, votingPeriod)) + systest.Sut.ModifyGenesisJSON(t, systest.SetGovVotingPeriod(t, votingPeriod)) const ( upgradeHeight int64 = 22 upgradeName = "v050-to-v052" // must match UpgradeName in simapp/upgrades.go ) - sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight+1)) + systest.Sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight+1)) - cli := NewCLIWrapper(t, sut, verbose) + cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) govAddr := sdk.AccAddress(address.Module("gov")).String() // submit upgrade proposal proposal := fmt.Sprintf(` @@ -61,32 +63,32 @@ func TestChainUpgrade(t *testing.T) { "summary": "testing" }`, govAddr, upgradeName, upgradeHeight) proposalID := cli.SubmitAndVoteGovProposal(proposal) - t.Logf("current_height: %d\n", sut.currentHeight) + t.Logf("current_height: %d\n", systest.Sut.CurrentHeight()) raw := cli.CustomQuery("q", "gov", "proposal", proposalID) t.Log(raw) - sut.AwaitBlockHeight(t, upgradeHeight-1, 60*time.Second) - t.Logf("current_height: %d\n", sut.currentHeight) + systest.Sut.AwaitBlockHeight(t, upgradeHeight-1, 60*time.Second) + t.Logf("current_height: %d\n", systest.Sut.CurrentHeight()) raw = cli.CustomQuery("q", "gov", "proposal", proposalID) proposalStatus := gjson.Get(raw, "proposal.status").String() require.Equal(t, "PROPOSAL_STATUS_PASSED", proposalStatus, raw) // PROPOSAL_STATUS_PASSED t.Log("waiting for upgrade info") - sut.AwaitUpgradeInfo(t) - sut.StopChain() + systest.Sut.AwaitUpgradeInfo(t) + systest.Sut.StopChain() t.Log("Upgrade height was reached. Upgrading chain") - sut.SetExecBinary(currentBranchBinary) - sut.SetTestnetInitializer(currentInitializer) - sut.StartChain(t) - cli = NewCLIWrapper(t, sut, verbose) + systest.Sut.SetExecBinary(currentBranchBinary) + systest.Sut.SetTestnetInitializer(currentInitializer) + systest.Sut.StartChain(t) + cli = systest.NewCLIWrapper(t, systest.Sut, systest.Verbose) // smoke test that new version runs - ownerAddr := cli.GetKeyAddr(defaultSrcAddr) - got := cli.Run("tx", "accounts", "init", "continuous-locking-account", `{"end_time":"2034-01-22T11:38:15.116127Z", "owner":"`+ownerAddr+`"}`, "--from="+defaultSrcAddr) - RequireTxSuccess(t, got) - got = cli.Run("tx", "protocolpool", "fund-community-pool", "100stake", "--from="+defaultSrcAddr) - RequireTxSuccess(t, got) + ownerAddr := cli.GetKeyAddr("node0") + got := cli.Run("tx", "accounts", "init", "continuous-locking-account", `{"end_time":"2034-01-22T11:38:15.116127Z", "owner":"`+ownerAddr+`"}`, "--from=node0") + systest.RequireTxSuccess(t, got) + got = cli.Run("tx", "protocolpool", "fund-community-pool", "100stake", "--from=node0") + systest.RequireTxSuccess(t, got) } const cacheDir = "binaries" @@ -94,20 +96,20 @@ const cacheDir = "binaries" // FetchExecutable to download and extract tar.gz for linux func FetchExecutable(t *testing.T, version string) string { // use local cache - cacheFolder := filepath.Join(WorkDir, cacheDir) + cacheFolder := filepath.Join(systest.WorkDir, cacheDir) err := os.MkdirAll(cacheFolder, 0o777) if err != nil && !os.IsExist(err) { panic(err) } - cacheFile := filepath.Join(cacheFolder, fmt.Sprintf("%s_%s", execBinaryName, version)) + cacheFile := filepath.Join(cacheFolder, fmt.Sprintf("%s_%s", systest.GetExecutableName(), version)) if _, err := os.Stat(cacheFile); err == nil { return cacheFile } destFile := cacheFile t.Log("+++ version not in cache, downloading from docker image") - MustRunShellCmd(t, "docker", "pull", "ghcr.io/cosmos/simapp:"+version) - MustRunShellCmd(t, "docker", "create", "--name=ci_temp", "ghcr.io/cosmos/simapp:"+version) - MustRunShellCmd(t, "docker", "cp", "ci_temp:/usr/bin/simd", destFile) + systest.MustRunShellCmd(t, "docker", "pull", "ghcr.io/cosmos/simapp:"+version) + systest.MustRunShellCmd(t, "docker", "create", "--name=ci_temp", "ghcr.io/cosmos/simapp:"+version) + systest.MustRunShellCmd(t, "docker", "cp", "ci_temp:/usr/bin/simd", destFile) return destFile }