416 lines
12 KiB
Go
416 lines
12 KiB
Go
//go:build system_test
|
|
|
|
package systemtests
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tidwall/gjson"
|
|
|
|
"cosmossdk.io/math"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
)
|
|
|
|
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 := StoreTempFile(t, []byte(invalidProp))
|
|
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 := StoreTempFile(t, []byte(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)
|
|
|
|
invalidProp := `{
|
|
"title": "",
|
|
"description": "Where is the title!?",
|
|
"type": "Text",
|
|
"deposit": "-324foocoin"
|
|
}`
|
|
invalidPropFile := StoreTempFile(t, []byte(invalidProp))
|
|
defer invalidPropFile.Close()
|
|
|
|
validProp := fmt.Sprintf(`{
|
|
"title": "Text Proposal",
|
|
"description": "Hello, World!",
|
|
"type": "Text",
|
|
"deposit": "%s"
|
|
}`, sdk.NewCoin("stake", math.NewInt(154310)))
|
|
validPropFile := StoreTempFile(t, []byte(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()),
|
|
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"),
|
|
fmt.Sprintf("--%s=%s", "type", "Text"),
|
|
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"),
|
|
fmt.Sprintf("--%s=%s", "type", "Text"),
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewCmdWeightedVote(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)
|
|
|
|
// Submit a new proposal for voting
|
|
proposalArgs := []string{
|
|
"tx", "gov", "submit-legacy-proposal",
|
|
fmt.Sprintf("--%s='Text Proposal'", "title"),
|
|
fmt.Sprintf("--%s='Where is the title!?'", "description"),
|
|
fmt.Sprintf("--%s=%s", "type", "Text"),
|
|
fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10_000_000)).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()),
|
|
}
|
|
rsp := cli.Run(proposalArgs...)
|
|
txResult, found := cli.AwaitTxCommitted(rsp)
|
|
require.True(t, found)
|
|
RequireTxSuccess(t, txResult)
|
|
|
|
proposalsResp := cli.CustomQuery("q", "gov", "proposals")
|
|
proposals := gjson.Get(proposalsResp, "proposals.#.id").Array()
|
|
require.NotEmpty(t, proposals)
|
|
|
|
proposal1 := cli.CustomQuery("q", "gov", "proposal", "1")
|
|
fmt.Println("first proposal", proposal1)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
args []string
|
|
expectErr bool
|
|
expectedCode uint32
|
|
broadcasted bool
|
|
errMsg string
|
|
}{
|
|
{
|
|
"vote for invalid proposal",
|
|
[]string{
|
|
"tx", "gov", "weighted-vote",
|
|
"10",
|
|
"yes",
|
|
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, 3, true,
|
|
"inactive proposal",
|
|
},
|
|
{
|
|
"valid vote",
|
|
[]string{
|
|
"tx", "gov", "weighted-vote",
|
|
"1",
|
|
"yes",
|
|
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, 0, true,
|
|
"",
|
|
},
|
|
{
|
|
"valid vote with metadata",
|
|
[]string{
|
|
"tx", "gov", "weighted-vote",
|
|
"1",
|
|
"yes",
|
|
fmt.Sprintf("--%s=%s", flags.FlagFrom, valAddr),
|
|
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
|
|
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
|
|
fmt.Sprintf("--metadata=%s", "AQ=="),
|
|
fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()),
|
|
},
|
|
false, 0, true,
|
|
"",
|
|
},
|
|
{
|
|
"invalid valid split vote string",
|
|
[]string{
|
|
"tx", "gov", "weighted-vote",
|
|
"1",
|
|
"yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05",
|
|
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, 0, false,
|
|
"is not a valid vote option",
|
|
},
|
|
{
|
|
"valid split vote",
|
|
[]string{
|
|
"tx", "gov", "weighted-vote",
|
|
"1",
|
|
"yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05",
|
|
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, 0, true,
|
|
"",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if !tc.broadcasted {
|
|
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...)
|
|
if tc.expectErr {
|
|
RequireTxFailure(t, rsp)
|
|
} else {
|
|
cli.AwaitTxCommitted(rsp)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestQueryDeposit(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)
|
|
|
|
// Submit a new proposal for voting
|
|
proposalArgs := []string{
|
|
"tx", "gov", "submit-legacy-proposal",
|
|
fmt.Sprintf("--%s='Text Proposal'", "title"),
|
|
fmt.Sprintf("--%s='Where is the title!?'", "description"),
|
|
fmt.Sprintf("--%s=%s", "type", "Text"),
|
|
fmt.Sprintf("--%s=%s", "deposit", sdk.NewCoin("stake", math.NewInt(10_000_000)).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()),
|
|
}
|
|
rsp := cli.Run(proposalArgs...)
|
|
txResult, found := cli.AwaitTxCommitted(rsp)
|
|
require.True(t, found)
|
|
RequireTxSuccess(t, txResult)
|
|
|
|
// Query initial deposit
|
|
resp := cli.CustomQuery("q", "gov", "deposit", "1", valAddr)
|
|
depositAmount := gjson.Get(resp, "deposit.amount.0.amount").Int()
|
|
require.Equal(t, depositAmount, int64(10_000_000))
|
|
|
|
resp = cli.CustomQuery("q", "gov", "deposits", "1")
|
|
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)
|
|
}
|