Skip to content

Commit

Permalink
test: add x/circuit system tests (backport #22331) (#22355)
Browse files Browse the repository at this point in the history
Co-authored-by: Akhil Kumar P <[email protected]>
  • Loading branch information
mergify[bot] and akhilkumarpilli authored Oct 24, 2024
1 parent c296622 commit 5fad401
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 1 deletion.
243 changes: 243 additions & 0 deletions tests/systemtests/circuit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
//go:build system_test

package systemtests

import (
"encoding/json"
"fmt"
"strings"
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
)

var someMsgs = []string{"/cosmos.bank.v1beta1.MsgSend", "/cosmos.bank.v1beta1.MsgMultiSend"}

func TestCircuitCommands(t *testing.T) {
// scenario: test circuit commands
// given a running chain

sut.ResetChain(t)
require.GreaterOrEqual(t, sut.NodesCount(), 2)

cli := NewCLIWrapper(t, sut, verbose)

// get validator addresses
superAdmin := cli.GetKeyAddr("node0")
require.NotEmpty(t, superAdmin)

superAdmin2 := cli.GetKeyAddr("node1")
require.NotEmpty(t, superAdmin2)

// short voting period
// update expedited voting period to avoid validation error
sut.ModifyGenesisJSON(
t,
SetGovVotingPeriod(t, time.Second*8),
SetGovExpeditedVotingPeriod(t, time.Second*7),
)

sut.StartChain(t)

allMsgsAcc := cli.AddKey("allMsgsAcc")
require.NotEmpty(t, allMsgsAcc)

someMsgsAcc := cli.AddKey("someMsgsAcc")
require.NotEmpty(t, someMsgsAcc)

// fund tokens to new created addresses
var amount int64 = 100000
denom := "stake"
rsp := cli.FundAddress(allMsgsAcc, fmt.Sprintf("%d%s", amount, denom))
RequireTxSuccess(t, rsp)
require.Equal(t, amount, cli.QueryBalance(allMsgsAcc, denom))

rsp = cli.FundAddress(someMsgsAcc, fmt.Sprintf("%d%s", amount, denom))
RequireTxSuccess(t, rsp)
require.Equal(t, amount, cli.QueryBalance(someMsgsAcc, denom))

// query gov module account address
rsp = cli.CustomQuery("q", "auth", "module-account", "gov")
govModAddr := gjson.Get(rsp, "account.value.address")

// create a proposal to add super admin
validProposal := fmt.Sprintf(`
{
"messages": [
{
"@type": "/cosmos.circuit.v1.MsgAuthorizeCircuitBreaker",
"granter": "%s",
"grantee": "%s",
"permissions": {"level": 3, "limit_type_urls": []}
}
],
"title": "Params update proposal",
"deposit": "10000000stake",
"summary": "A short summary of my proposal"
}`, govModAddr, superAdmin)
proposalFile := StoreTempFile(t, []byte(validProposal))

rsp = cli.RunAndWait("tx", "gov", "submit-proposal", proposalFile.Name(), "--from="+superAdmin)
RequireTxSuccess(t, rsp)

// vote to proposal from two validators
rsp = cli.RunAndWait("tx", "gov", "vote", "1", "yes", "--from="+superAdmin)
RequireTxSuccess(t, rsp)
rsp = cli.RunAndWait("tx", "gov", "vote", "1", "yes", "--from="+superAdmin2)
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)

authorizeTestCases := []struct {
name string
address string
level int
limtTypeURLs []string
expPermission string
}{
{
"set new super admin",
superAdmin2,
3,
[]string{},
"LEVEL_SUPER_ADMIN",
},
{
"set all msgs level to address",
allMsgsAcc,
2,
[]string{},
"LEVEL_ALL_MSGS",
},
{
"set some msgs level to address",
someMsgsAcc,
1,
someMsgs,
"LEVEL_SOME_MSGS",
},
}

for _, tc := range authorizeTestCases {
t.Run(tc.name, func(t *testing.T) {
permissionJSON := fmt.Sprintf(`{"level":%d,"limit_type_urls":[]}`, tc.level)
if len(tc.limtTypeURLs) != 0 {
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)

// query account permissions
rsp = cli.CustomQuery("q", "circuit", "account", tc.address)
require.Equal(t, tc.expPermission, gjson.Get(rsp, "permission.level").String())
if len(tc.limtTypeURLs) != 0 {
listStr := gjson.Get(rsp, "permission.limit_type_urls").String()

// convert string to array
var msgsList []string
require.NoError(t, json.Unmarshal([]byte(listStr), &msgsList))

require.EqualValues(t, tc.limtTypeURLs, msgsList)
}
})
}

// test disable tx command
testCircuitTxCommand(t, cli, "disable", superAdmin, superAdmin2, allMsgsAcc, someMsgsAcc)

// test reset tx command
testCircuitTxCommand(t, cli, "reset", superAdmin, superAdmin2, allMsgsAcc, someMsgsAcc)
}

func testCircuitTxCommand(t *testing.T, cli *CLIWrapper, txType, superAdmin, superAdmin2, allMsgsAcc, someMsgsAcc string) {
t.Helper()

disableTestCases := []struct {
name string
fromAddr string
disableMsgs []string
executeTxs [][]string
}{
{
txType + " msgs with super admin",
superAdmin,
[]string{"/cosmos.gov.v1.MsgVote"},
[][]string{
{
"tx", "gov", "vote", "3", "yes", "--from=" + superAdmin,
},
},
},
{
txType + " msgs with all msgs level address",
allMsgsAcc,
[]string{"/cosmos.gov.v1.MsgDeposit"},
[][]string{
{
"tx", "gov", "deposit", "3", "1000stake", "--from=" + allMsgsAcc,
},
},
},
{
txType + " msgs with some msgs level address",
someMsgsAcc,
someMsgs,
[][]string{
{
"tx", "bank", "send", superAdmin, someMsgsAcc, "10000stake",
},
{
"tx", "bank", "multi-send", superAdmin, someMsgsAcc, superAdmin2, "10000stake", "--from=" + superAdmin,
},
},
},
}

for _, tc := range disableTestCases {
t.Run(tc.name, func(t *testing.T) {
cmd := []string{"tx", "circuit", txType, "--from=" + tc.fromAddr}
cmd = append(cmd, tc.disableMsgs...)
rsp := cli.RunAndWait(cmd...)
RequireTxSuccess(t, rsp)

// execute given type transaction
rsp = cli.CustomQuery("q", "circuit", "disabled-list")
var list []string
if gjson.Get(rsp, "disabled_list").Exists() {
listJSON := gjson.Get(rsp, "disabled_list").Raw

// convert string to array
require.NoError(t, json.Unmarshal([]byte(listJSON), &list))
}
for _, msg := range tc.disableMsgs {
if txType == "disable" {
require.Contains(t, list, msg)
} else {
require.NotContains(t, list, msg)
}
}

// test given msg transaction to confirm
for _, tx := range tc.executeTxs {
tx = append(tx, "--fees=2stake")
rsp = cli.RunCommandWithArgs(cli.withTXFlags(tx...)...)
if txType == "disable" {
RequireTxFailure(t, rsp)
require.Contains(t, gjson.Get(rsp, "raw_log").String(), "tx type not allowed")
} else {
RequireTxSuccess(t, rsp)
}
// wait for sometime to avoid sequence error
time.Sleep(time.Second * 2)
}
})
}
}
2 changes: 1 addition & 1 deletion x/circuit/autocli.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
"SOME_MSGS" = 1,
"ALL_MSGS" = 2,
"SUPER_ADMIN" = 3,`,
Example: fmt.Sprintf(`%s tx circuit authorize [address] '{"level":1,"limit_type_urls":["/cosmos.bank.v1beta1.MsgSend, /cosmos.bank.v1beta1.MsgMultiSend"]}'"`, version.AppName),
Example: fmt.Sprintf(`%s tx circuit authorize [address] '{"level":1,"limit_type_urls":["/cosmos.bank.v1beta1.MsgSend", "/cosmos.bank.v1beta1.MsgMultiSend"]}'"`, version.AppName),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
{ProtoField: "grantee"},
{ProtoField: "permissions"}, // TODO(@julienrbrt) Support flattening msg for setting each field as a positional arg
Expand Down

0 comments on commit 5fad401

Please sign in to comment.