Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(gov): Migrate e2e to system test #21927

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/local-testnet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SIMD="$ROOT/build/simdv2"

COSMOS_BUILD_OPTIONS=v2 make build

$SIMD testnet init-files --chain-id=testing --output-dir="$HOME/.testnet" --validator-count=3 --keyring-backend=test --minimum-gas-prices=0.000001stake --commit-timeout=900ms --single-host
$SIMD testnet init-files --chain-id=testing --output-dir="$HOME/.testnet" --validator-count=3 --keyring-backend=test --server.minimum-gas-prices=0.000001stake --commit-timeout=900ms --single-host

$SIMD start --log_level=info --home "$HOME/.testnet/node0/simdv2" &
$SIMD start --log_level=info --home "$HOME/.testnet/node1/simdv2" &
Expand Down
2 changes: 2 additions & 0 deletions tests/systemtests/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ func (c CLIWrapper) runWithInput(args []string, input io.Reader) (output string,
return cmd.CombinedOutput()
}()
gotOut = filterProtoNoise(gotOut)
fmt.Println("assertError", gotErr)
fmt.Println("assertError", string(gotOut))
ok = c.assertErrorFn(c.t, gotErr, string(gotOut))
return strings.TrimSpace(string(gotOut)), ok
}
Expand Down
237 changes: 237 additions & 0 deletions tests/systemtests/gov_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
//go:build system_test

package systemtests

import (
"encoding/base64"
"fmt"
"os"
"testing"

"cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
)

func TestSubmitProposal(t *testing.T) {
// given a running chain

sut.ResetChain(t)
cli := NewCLIWrapper(t, sut, verbose)

// get validator address
valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String()
require.NotEmpty(t, valAddr)

sut.StartChain(t)

// get gov module address
resp := cli.CustomQuery("q", "auth", "module-account", "gov")
govAddress := gjson.Get(resp, "account.value.address").String()

invalidProp := `{
"title": "",
"description": "Where is the title!?",
"type": "Text",
"deposit": "-324foocoin"
}`
invalidPropFile := testutil.WriteToNewTempFile(t, invalidProp)
os.WriteFile("test", []byte(invalidProp), 0o600)
defer invalidPropFile.Close()

// Create a valid new proposal JSON.
propMetadata := []byte{42}
validProp := fmt.Sprintf(`
{
"messages": [
{
"@type": "/cosmos.gov.v1.MsgExecLegacyContent",
"authority": "%s",
"content": {
"@type": "/cosmos.gov.v1beta1.TextProposal",
"title": "My awesome title",
"description": "My awesome description"
}
}
],
"title": "My awesome title",
"summary": "My awesome description",
"metadata": "%s",
"deposit": "%s"
}`, govAddress, base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin("stake", math.NewInt(100000)))
validPropFile := testutil.WriteToNewTempFile(t, validProp)
defer validPropFile.Close()

testCases := []struct {
name string
args []string
expectErr bool
errMsg string
}{
{
"invalid proposal",
[]string{
"tx", "gov", "submit-proposal",
invalidPropFile.Name(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
},
true,
"invalid character in coin string",
},
{
"valid proposal",
[]string{
"tx", "gov", "submit-proposal",
validPropFile.Name(),
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
},
false,
"",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.expectErr {
assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool {
require.Contains(t, gotOutputs[0], tc.errMsg)
return false
}

cli.WithRunErrorMatcher(assertOutput).Run(tc.args...)
} else {
rsp := cli.Run(tc.args...)
txResult, found := cli.AwaitTxCommitted(rsp)
require.True(t, found)
RequireTxSuccess(t, txResult)
}
})
}
}

func TestSubmitLegacyProposal(t *testing.T) {
// given a running chain

sut.ResetChain(t)
cli := NewCLIWrapper(t, sut, verbose)

// get validator address
valAddr := gjson.Get(cli.Keys("keys", "list"), "0.address").String()
require.NotEmpty(t, valAddr)

sut.StartChain(t)

// get gov module address
// resp := cli.CustomQuery("q", "auth", "module-account", "gov")
// govAddress := gjson.Get(resp, "account.value.address").String()

invalidProp := `{
"title": "",
"description": "Where is the title!?",
"type": "Text",
"deposit": "-324foocoin"
}`
invalidPropFile := testutil.WriteToNewTempFile(t, invalidProp)
defer invalidPropFile.Close()

validProp := fmt.Sprintf(`{
"title": "Text Proposal",
"description": "Hello, World!",
"type": "Text",
"deposit": "%s"
}`, sdk.NewCoin("stake", math.NewInt(154310)))
validPropFile := testutil.WriteToNewTempFile(t, validProp)
defer validPropFile.Close()

testCases := []struct {
name string
args []string
expectErr bool
errMsg string
}{
{
"invalid proposal (file)",
[]string{
"tx", "gov", "submit-legacy-proposal",
fmt.Sprintf("--%s=%s", "proposal", invalidPropFile.Name()), //nolint:staticcheck // we are intentionally using a deprecated flag here.
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
},
true,
"proposal title is required",
},
{
"invalid proposal",
[]string{
"tx", "gov", "submit-legacy-proposal",
fmt.Sprintf("--%s='Where is the title!?'", "description"), //nolint:staticcheck // we are intentionally using a deprecated flag here.
fmt.Sprintf("--%s=%s", "type", "Text"), //nolint:staticcheck // we are intentionally using a deprecated flag here.
fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10000)).String()),
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
},
true,
"proposal title is required",
},
{
"valid transaction (file)",
[]string{
"tx", "gov", "submit-legacy-proposal",
fmt.Sprintf("--%s=%s", "proposal", validPropFile.Name()),
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
},
false,
"",
},
{
"valid transaction",
[]string{
"tx", "gov", "submit-legacy-proposal",
fmt.Sprintf("--%s='Text Proposal'", "title"),
fmt.Sprintf("--%s='Where is the title!?'", "description"), //nolint:staticcheck // we are intentionally using a deprecated flag here.
fmt.Sprintf("--%s=%s", "type", "Text"), //nolint:staticcheck // we are intentionally using a deprecated flag here.
fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(100000)).String()),
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
},
false,
"",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.expectErr {
assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool {
fmt.Println("gotOut", gotOutputs)
require.Contains(t, gotOutputs[0], tc.errMsg)
return false
}

cli.WithRunErrorMatcher(assertOutput).Run(tc.args...)
} else {
rsp := cli.Run(tc.args...)
txResult, found := cli.AwaitTxCommitted(rsp)
require.True(t, found)
RequireTxSuccess(t, txResult)
}
})
}
}
9 changes: 9 additions & 0 deletions tests/systemtests/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ func (s *SystemUnderTest) SetupChain() {
if err != nil {
panic(fmt.Sprintf("failed set block max gas: %s", err))
}
// Short period for gov
genesisBz, err = sjson.SetRawBytes(genesisBz, "app_state.gov.params.max_deposit_period", []byte(fmt.Sprintf(`"%s"`, "20s")))
if err != nil {
panic(fmt.Sprintf("failed set block max gas: %s", err))
}
genesisBz, err = sjson.SetRawBytes(genesisBz, "app_state.gov.params.voting_period", []byte(fmt.Sprintf(`"%s"`, "8s")))
if err != nil {
panic(fmt.Sprintf("failed set block max gas: %s", err))
}
s.withEachNodeHome(func(i int, home string) {
if err := saveGenesis(home, genesisBz); err != nil {
panic(err)
Expand Down
6 changes: 6 additions & 0 deletions tests/systemtests/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"title": "",
"description": "Where is the title!?",
"type": "Text",
"deposit": "-324foocoin"
}
Empty file added tests/systemtests/test.json
Empty file.
1 change: 1 addition & 0 deletions x/gov/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func (k msgServer) ExecLegacyContent(ctx context.Context, msg *v1.MsgExecLegacyC
}

// Ensure that the content has a respective handler
fmt.Println("legacyRouter", k.Keeper.legacyRouter)
if !k.Keeper.legacyRouter.HasRoute(content.ProposalRoute()) {
return nil, errors.Wrap(govtypes.ErrNoProposalHandlerExists, content.ProposalRoute())
}
Expand Down
1 change: 1 addition & 0 deletions x/gov/keeper/proposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func (k Keeper) SubmitProposal(ctx context.Context, messages []sdk.Msg, metadata
}

// Ensure that the content has a respective handler
fmt.Println(k.legacyRouter)
if !k.legacyRouter.HasRoute(content.ProposalRoute()) {
return v1.Proposal{}, errorsmod.Wrap(types.ErrNoProposalHandlerExists, content.ProposalRoute())
}
Expand Down
Loading