From c211488b0b4b0e85eec68d24350a594ebdac5c46 Mon Sep 17 00:00:00 2001 From: SaReN Date: Wed, 6 May 2020 06:46:37 +0530 Subject: [PATCH] x/auth: cli tests (#6152) * Add cli tests for auth * Format imports * Fix auth tests * Remove keys in validate sign call * Eliminate defer in tests * Format imports * Test commit --- tests/cli/helpers.go | 12 -- tests/cli/simd_test.go | 2 +- x/auth/client/cli/cli_test.go | 334 +++++++++++++++++++++++++++++- x/auth/client/testutil/helpers.go | 23 +- x/bank/client/cli/cli_test.go | 2 +- x/slashing/client/cli/cli_test.go | 2 +- x/staking/client/cli/cli_test.go | 2 +- 7 files changed, 356 insertions(+), 21 deletions(-) diff --git a/tests/cli/helpers.go b/tests/cli/helpers.go index ba332eda01..6c7fa77815 100644 --- a/tests/cli/helpers.go +++ b/tests/cli/helpers.go @@ -167,18 +167,6 @@ func (f *Fixtures) CLIConfig(key, value string, flags ...string) { ExecuteWriteCheckErr(f.T, AddFlags(cmd, flags)) } -// TxBroadcast is simcli tx broadcast -func (f *Fixtures) TxBroadcast(fileName string, flags ...string) (bool, string, string) { - cmd := fmt.Sprintf("%s tx broadcast %v %v", f.SimcliBinary, f.Flags(), fileName) - return ExecuteWriteRetStdStreams(f.T, AddFlags(cmd, flags), clientkeys.DefaultKeyPass) -} - -// TxEncode is simcli tx encode -func (f *Fixtures) TxEncode(fileName string, flags ...string) (bool, string, string) { - cmd := fmt.Sprintf("%s tx encode %v %v", f.SimcliBinary, f.Flags(), fileName) - return ExecuteWriteRetStdStreams(f.T, AddFlags(cmd, flags), clientkeys.DefaultKeyPass) -} - //utils func AddFlags(cmd string, flags []string) string { diff --git a/tests/cli/simd_test.go b/tests/cli/simd_test.go index 91640226e9..2be36dc8e9 100644 --- a/tests/cli/simd_test.go +++ b/tests/cli/simd_test.go @@ -125,7 +125,7 @@ func TestCLIValidateGenesis(t *testing.T) { // start simd server proc := f.SDStart() - defer proc.Stop(false) + t.Cleanup(func() { proc.Stop(false) }) f.ValidateGenesis() diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index e1d33a0a37..66a7cc9f28 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -3,14 +3,20 @@ package cli_test import ( + "encoding/base64" + "fmt" + "strings" "testing" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/tests/cli" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/client/testutil" + bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" ) func TestCLIValidateSignatures(t *testing.T) { @@ -27,7 +33,7 @@ func TestCLIValidateSignatures(t *testing.T) { barAddr := f.KeyAddress(cli.KeyBar) // generate sendTx with default gas - success, stdout, stderr := testutil.TxSend(f, fooAddr.String(), barAddr, sdk.NewInt64Coin("stake", 10), "--generate-only") + success, stdout, stderr := bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewInt64Coin("stake", 10), "--generate-only") require.True(t, success) require.Empty(t, stderr) @@ -66,3 +72,329 @@ func TestCLIValidateSignatures(t *testing.T) { // Cleanup testing directories f.Cleanup() } + +func TestCLISendGenerateSignAndBroadcast(t *testing.T) { + t.Parallel() + f := cli.InitFixtures(t) + + // start simd server + proc := f.SDStart() + t.Cleanup(func() { proc.Stop(false) }) + + fooAddr := f.KeyAddress(cli.KeyFoo) + barAddr := f.KeyAddress(cli.KeyBar) + + // Test generate sendTx with default gas + sendTokens := sdk.TokensFromConsensusPower(10) + success, stdout, stderr := bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only") + require.True(t, success) + require.Empty(t, stderr) + msg := cli.UnmarshalStdTx(t, f.Cdc, stdout) + require.Equal(t, msg.Fee.Gas, uint64(flags.DefaultGasLimit)) + require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) + + // Test generate sendTx with --gas=$amount + success, stdout, stderr = bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--gas=100", "--generate-only") + require.True(t, success) + require.Empty(t, stderr) + + msg = cli.UnmarshalStdTx(t, f.Cdc, stdout) + require.Equal(t, msg.Fee.Gas, uint64(100)) + require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 0, len(msg.GetSignatures())) + + // Test generate sendTx, estimate gas + success, stdout, stderr = bankcli.TxSend(f, fooAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only") + require.True(t, success) + require.Empty(t, stderr) + msg = cli.UnmarshalStdTx(t, f.Cdc, stdout) + require.True(t, msg.Fee.Gas > 0) + require.Equal(t, len(msg.Msgs), 1) + + // Write the output to disk + unsignedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Test validate-signatures + success, stdout, _ = testutil.TxValidateSignatures(f, unsignedTxFile.Name()) + require.False(t, success) + require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n\n", fooAddr.String()), stdout) + + // Test sign + + // Does not work in offline mode + success, stdout, stderr = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--offline") + require.Contains(t, stderr, "required flag(s) \"account-number\", \"sequence\" not set") + require.False(t, success) + + // But works offline if we set account number and sequence + success, _, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--offline", "--account-number", "1", "--sequence", "1") + require.True(t, success) + + // Sign transaction + success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name()) + require.True(t, success) + msg = cli.UnmarshalStdTx(t, f.Cdc, stdout) + require.Equal(t, len(msg.Msgs), 1) + require.Equal(t, 1, len(msg.GetSignatures())) + require.Equal(t, fooAddr.String(), msg.GetSigners()[0].String()) + + // Write the output to disk + signedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Test validate-signatures + success, stdout, _ = testutil.TxValidateSignatures(f, signedTxFile.Name()) + require.True(t, success) + require.Equal(t, fmt.Sprintf("Signers:\n 0: %v\n\nSignatures:\n 0: %v\t\t\t[OK]\n\n", fooAddr.String(), + fooAddr.String()), stdout) + + // Ensure foo has right amount of funds + startTokens := sdk.TokensFromConsensusPower(50) + require.Equal(t, startTokens, bankcli.QueryBalances(f, fooAddr).AmountOf(cli.Denom)) + + // Test broadcast + + // Does not work in offline mode + success, _, stderr = testutil.TxBroadcast(f, signedTxFile.Name(), "--offline") + require.Contains(t, stderr, "cannot broadcast tx during offline mode") + require.False(t, success) + tests.WaitForNextNBlocksTM(1, f.Port) + + success, stdout, _ = testutil.TxBroadcast(f, signedTxFile.Name()) + require.True(t, success) + tests.WaitForNextNBlocksTM(1, f.Port) + + // Ensure account state + require.Equal(t, sendTokens, bankcli.QueryBalances(f, barAddr).AmountOf(cli.Denom)) + require.Equal(t, startTokens.Sub(sendTokens), bankcli.QueryBalances(f, fooAddr).AmountOf(cli.Denom)) + + f.Cleanup() +} + +func TestCLIMultisignInsufficientCosigners(t *testing.T) { + t.Parallel() + f := cli.InitFixtures(t) + + // start simd server with minimum fees + proc := f.SDStart() + t.Cleanup(func() { proc.Stop(false) }) + + fooBarBazAddr := f.KeyAddress(cli.KeyFooBarBaz) + barAddr := f.KeyAddress(cli.KeyBar) + + // Send some tokens from one account to the other + success, _, _ := bankcli.TxSend(f, cli.KeyFoo, fooBarBazAddr, sdk.NewInt64Coin(cli.Denom, 10), "-y") + require.True(t, success) + tests.WaitForNextNBlocksTM(1, f.Port) + + // Test generate sendTx with multisig + success, stdout, _ := bankcli.TxSend(f, fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(cli.Denom, 5), "--generate-only") + require.True(t, success) + + // Write the output to disk + unsignedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Sign with foo's key + success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y") + require.True(t, success) + + // Write the output to disk + fooSignatureFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Multisign, not enough signatures + success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{fooSignatureFile.Name()}) + require.True(t, success) + + // Write the output to disk + signedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Validate the multisignature + success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name()) + require.False(t, success) + + // Broadcast the transaction + success, stdOut, _ := testutil.TxBroadcast(f, signedTxFile.Name()) + require.Contains(t, stdOut, "signature verification failed") + require.True(t, success) + + // Cleanup testing directories + f.Cleanup() +} + +func TestCLIEncode(t *testing.T) { + t.Parallel() + f := cli.InitFixtures(t) + + // start simd server + proc := f.SDStart() + t.Cleanup(func() { proc.Stop(false) }) + + // Build a testing transaction and write it to disk + barAddr := f.KeyAddress(cli.KeyBar) + keyAddr := f.KeyAddress(cli.KeyFoo) + + sendTokens := sdk.TokensFromConsensusPower(10) + success, stdout, stderr := bankcli.TxSend(f, keyAddr.String(), barAddr, sdk.NewCoin(cli.Denom, sendTokens), "--generate-only", "--memo", "deadbeef") + require.True(t, success) + require.Empty(t, stderr) + + // Write it to disk + jsonTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Run the encode command, and trim the extras from the stdout capture + success, base64Encoded, _ := testutil.TxEncode(f, jsonTxFile.Name()) + require.True(t, success) + trimmedBase64 := strings.Trim(base64Encoded, "\"\n") + + // Decode the base64 + decodedBytes, err := base64.StdEncoding.DecodeString(trimmedBase64) + require.Nil(t, err) + + // Check that the transaction decodes as epxceted + var decodedTx auth.StdTx + require.Nil(t, f.Cdc.UnmarshalBinaryBare(decodedBytes, &decodedTx)) + require.Equal(t, "deadbeef", decodedTx.Memo) +} + +func TestCLIMultisignSortSignatures(t *testing.T) { + t.Parallel() + f := cli.InitFixtures(t) + + // start simd server with minimum fees + proc := f.SDStart() + t.Cleanup(func() { proc.Stop(false) }) + + fooBarBazAddr := f.KeyAddress(cli.KeyFooBarBaz) + barAddr := f.KeyAddress(cli.KeyBar) + + // Send some tokens from one account to the other + success, _, _ := bankcli.TxSend(f, cli.KeyFoo, fooBarBazAddr, sdk.NewInt64Coin(cli.Denom, 10), "-y") + require.True(t, success) + tests.WaitForNextNBlocksTM(1, f.Port) + + // Ensure account balances match expected + require.Equal(t, int64(10), bankcli.QueryBalances(f, fooBarBazAddr).AmountOf(cli.Denom).Int64()) + + // Test generate sendTx with multisig + success, stdout, _ := bankcli.TxSend(f, fooBarBazAddr.String(), barAddr, sdk.NewInt64Coin(cli.Denom, 5), "--generate-only") + require.True(t, success) + + // Write the output to disk + unsignedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Sign with foo's key + success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String()) + require.True(t, success) + + // Write the output to disk + fooSignatureFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Sign with baz's key + success, stdout, _ = testutil.TxSign(f, cli.KeyBaz, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String()) + require.True(t, success) + + // Write the output to disk + bazSignatureFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Multisign, keys in different order + success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{ + bazSignatureFile.Name(), fooSignatureFile.Name()}) + require.True(t, success) + + // Write the output to disk + signedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Validate the multisignature + success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name()) + require.True(t, success) + + // Broadcast the transaction + success, _, _ = testutil.TxBroadcast(f, signedTxFile.Name()) + require.True(t, success) + + // Cleanup testing directories + f.Cleanup() +} + +func TestCLIMultisign(t *testing.T) { + t.Parallel() + f := cli.InitFixtures(t) + + // start simd server with minimum fees + proc := f.SDStart() + t.Cleanup(func() { proc.Stop(false) }) + + fooBarBazAddr := f.KeyAddress(cli.KeyFooBarBaz) + bazAddr := f.KeyAddress(cli.KeyBaz) + + // Send some tokens from one account to the other + success, _, _ := bankcli.TxSend(f, cli.KeyFoo, fooBarBazAddr, sdk.NewInt64Coin(cli.Denom, 10), "-y") + require.True(t, success) + tests.WaitForNextNBlocksTM(1, f.Port) + + // Ensure account balances match expected + require.Equal(t, int64(10), bankcli.QueryBalances(f, fooBarBazAddr).AmountOf(cli.Denom).Int64()) + + // Test generate sendTx with multisig + success, stdout, stderr := bankcli.TxSend(f, fooBarBazAddr.String(), bazAddr, sdk.NewInt64Coin(cli.Denom, 10), "--generate-only") + require.True(t, success) + require.Empty(t, stderr) + + // Write the output to disk + unsignedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Sign with foo's key + success, stdout, _ = testutil.TxSign(f, cli.KeyFoo, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y") + require.True(t, success) + + // Write the output to disk + fooSignatureFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Sign with bar's key + success, stdout, _ = testutil.TxSign(f, cli.KeyBar, unsignedTxFile.Name(), "--multisig", fooBarBazAddr.String(), "-y") + require.True(t, success) + + // Write the output to disk + barSignatureFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Multisign + + // Does not work in offline mode + success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{ + fooSignatureFile.Name(), barSignatureFile.Name()}, "--offline") + require.Contains(t, "couldn't verify signature", stdout) + require.False(t, success) + + // Success multisign + success, stdout, _ = testutil.TxMultisign(f, unsignedTxFile.Name(), cli.KeyFooBarBaz, []string{ + fooSignatureFile.Name(), barSignatureFile.Name()}) + require.True(t, success) + + // Write the output to disk + signedTxFile, cleanup := tests.WriteToNewTempFile(t, stdout) + t.Cleanup(cleanup) + + // Validate the multisignature + success, _, _ = testutil.TxValidateSignatures(f, signedTxFile.Name()) + require.True(t, success) + + // Broadcast the transaction + success, _, _ = testutil.TxBroadcast(f, signedTxFile.Name()) + require.True(t, success) + + // Cleanup testing directories + f.Cleanup() +} diff --git a/x/auth/client/testutil/helpers.go b/x/auth/client/testutil/helpers.go index c1e3edf55a..20faccf95a 100644 --- a/x/auth/client/testutil/helpers.go +++ b/x/auth/client/testutil/helpers.go @@ -2,10 +2,10 @@ package testutil import ( "fmt" + "strings" clientkeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/tests/cli" - sdk "github.com/cosmos/cosmos-sdk/types" ) // TxSign is simcli sign @@ -15,10 +15,15 @@ func TxSign(f *cli.Fixtures, signer, fileName string, flags ...string) (bool, st return cli.ExecuteWriteRetStdStreams(f.T, cli.AddFlags(cmd, flags), clientkeys.DefaultKeyPass) } -// TxSend is simcli tx send -func TxSend(f *cli.Fixtures, from string, to sdk.AccAddress, amount sdk.Coin, flags ...string) (bool, string, string) { - cmd := fmt.Sprintf("%s tx send --keyring-backend=test %s %s %s %v", f.SimcliBinary, from, to, amount, f.Flags()) +// TxBroadcast is simcli tx broadcast +func TxBroadcast(f *cli.Fixtures, fileName string, flags ...string) (bool, string, string) { + cmd := fmt.Sprintf("%s tx broadcast %v %v", f.SimcliBinary, f.Flags(), fileName) + return cli.ExecuteWriteRetStdStreams(f.T, cli.AddFlags(cmd, flags), clientkeys.DefaultKeyPass) +} +// TxEncode is simcli tx encode +func TxEncode(f *cli.Fixtures, fileName string, flags ...string) (bool, string, string) { + cmd := fmt.Sprintf("%s tx encode %v %v", f.SimcliBinary, f.Flags(), fileName) return cli.ExecuteWriteRetStdStreams(f.T, cli.AddFlags(cmd, flags), clientkeys.DefaultKeyPass) } @@ -29,3 +34,13 @@ func TxValidateSignatures(f *cli.Fixtures, fileName string, flags ...string) (bo return cli.ExecuteWriteRetStdStreams(f.T, cli.AddFlags(cmd, flags), clientkeys.DefaultKeyPass) } + +// TxMultisign is simcli tx multisign +func TxMultisign(f *cli.Fixtures, fileName, name string, signaturesFiles []string, + flags ...string) (bool, string, string) { + + cmd := fmt.Sprintf("%s tx multisign --keyring-backend=test %v %s %s %s", f.SimcliBinary, f.Flags(), + fileName, name, strings.Join(signaturesFiles, " "), + ) + return cli.ExecuteWriteRetStdStreams(f.T, cli.AddFlags(cmd, flags)) +} diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index 9bd74c6cdb..fa35b5b6f0 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -211,7 +211,7 @@ func TestCLIQuerySupply(t *testing.T) { // start simd server proc := f.SDStart() - defer proc.Stop(false) + t.Cleanup(func() { proc.Stop(false) }) totalSupply := testutil.QueryTotalSupply(f) totalSupplyOf := testutil.QueryTotalSupplyOf(f, cli.FooDenom) diff --git a/x/slashing/client/cli/cli_test.go b/x/slashing/client/cli/cli_test.go index a39d2e77bf..1d5d8ffec1 100644 --- a/x/slashing/client/cli/cli_test.go +++ b/x/slashing/client/cli/cli_test.go @@ -18,7 +18,7 @@ func TestCLISlashingGetParams(t *testing.T) { // start simd server proc := f.SDStart() - defer proc.Stop(false) + t.Cleanup(func() { proc.Stop(false) }) params := testutil.QuerySlashingParams(f) require.Equal(t, int64(100), params.SignedBlocksWindow) diff --git a/x/staking/client/cli/cli_test.go b/x/staking/client/cli/cli_test.go index 599974c5a7..24ee0026ce 100644 --- a/x/staking/client/cli/cli_test.go +++ b/x/staking/client/cli/cli_test.go @@ -21,7 +21,7 @@ func TestCLICreateValidator(t *testing.T) { // start simd server proc := f.SDStart() - defer proc.Stop(false) + t.Cleanup(func() { proc.Stop(false) }) barAddr := f.KeyAddress(cli.KeyBar) barVal := sdk.ValAddress(barAddr)