From f79489e297f2513bba36ca0412537bc0c34300e0 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli <akhilkumar7947@gmail.com> Date: Tue, 22 Oct 2024 12:33:42 +0530 Subject: [PATCH 1/3] WIP: add x/circuit system tests --- tests/systemtests/circuit_test.go | 147 ++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 tests/systemtests/circuit_test.go diff --git a/tests/systemtests/circuit_test.go b/tests/systemtests/circuit_test.go new file mode 100644 index 000000000000..4e4cc6468fba --- /dev/null +++ b/tests/systemtests/circuit_test.go @@ -0,0 +1,147 @@ +package systemtests + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +func TestCircuitCmds(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) + + accountAddr := cli.AddKey("account") + require.NotEmpty(t, accountAddr) + + // 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)) + + rsp = cli.FundAddress(accountAddr, fmt.Sprintf("%d%s", amount, denom)) + RequireTxSuccess(t, rsp) + require.Equal(t, amount, cli.QueryBalance(accountAddr, 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, + "", + "LEVEL_SUPER_ADMIN", + }, + { + "set all msgs level to address", + allMsgsAcc, + 2, + "", + "LEVEL_ALL_MSGS", + }, + { + "set some msgs level to address", + someMsgsAcc, + 1, + "/cosmos.bank.v1beta1.MsgSend, /cosmos.bank.v1beta1.MsgMultiSend", + "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 tc.limtTypeURLS != "" { + permissionJSON = fmt.Sprintf(`{"level":%d,"limit_type_urls":["%s"]}`, tc.level, 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 tc.limtTypeURLS != "" { + require.Equal(t, tc.limtTypeURLS, gjson.Get(rsp, "permission.limit_type_urls.0").String()) + } + }) + } +} From 228fb8c450bd448d0e08a1e356e9b29c4f0e3677 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli <akhilkumar7947@gmail.com> Date: Tue, 22 Oct 2024 16:10:31 +0530 Subject: [PATCH 2/3] done system tests --- tests/systemtests/circuit_test.go | 128 ++++++++++++++++++++++++++---- x/circuit/autocli.go | 2 +- 2 files changed, 113 insertions(+), 17 deletions(-) diff --git a/tests/systemtests/circuit_test.go b/tests/systemtests/circuit_test.go index 4e4cc6468fba..1fd3e8d0b746 100644 --- a/tests/systemtests/circuit_test.go +++ b/tests/systemtests/circuit_test.go @@ -1,7 +1,11 @@ +//go:build system_test + package systemtests import ( + "encoding/json" "fmt" + "strings" "testing" "time" @@ -9,7 +13,9 @@ import ( "github.com/tidwall/gjson" ) -func TestCircuitCmds(t *testing.T) { +var someMsgs = []string{"/cosmos.bank.v1beta1.MsgSend", "/cosmos.bank.v1beta1.MsgMultiSend"} + +func TestCircuitCommands(t *testing.T) { // scenario: test circuit commands // given a running chain @@ -41,9 +47,6 @@ func TestCircuitCmds(t *testing.T) { someMsgsAcc := cli.AddKey("someMsgsAcc") require.NotEmpty(t, someMsgsAcc) - accountAddr := cli.AddKey("account") - require.NotEmpty(t, accountAddr) - // fund tokens to new created addresses var amount int64 = 100000 denom := "stake" @@ -55,10 +58,6 @@ func TestCircuitCmds(t *testing.T) { RequireTxSuccess(t, rsp) require.Equal(t, amount, cli.QueryBalance(someMsgsAcc, denom)) - rsp = cli.FundAddress(accountAddr, fmt.Sprintf("%d%s", amount, denom)) - RequireTxSuccess(t, rsp) - require.Equal(t, amount, cli.QueryBalance(accountAddr, denom)) - // query gov module account address rsp = cli.CustomQuery("q", "auth", "module-account", "gov") govModAddr := gjson.Get(rsp, "account.value.address") @@ -101,28 +100,28 @@ func TestCircuitCmds(t *testing.T) { name string address string level int - limtTypeURLS string + 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, - "/cosmos.bank.v1beta1.MsgSend, /cosmos.bank.v1beta1.MsgMultiSend", + someMsgs, "LEVEL_SOME_MSGS", }, } @@ -130,8 +129,8 @@ func TestCircuitCmds(t *testing.T) { for _, tc := range authorizeTestCases { t.Run(tc.name, func(t *testing.T) { permissionJSON := fmt.Sprintf(`{"level":%d,"limit_type_urls":[]}`, tc.level) - if tc.limtTypeURLS != "" { - permissionJSON = fmt.Sprintf(`{"level":%d,"limit_type_urls":["%s"]}`, tc.level, tc.limtTypeURLS) + 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) @@ -139,8 +138,105 @@ func TestCircuitCmds(t *testing.T) { // query account permissions rsp = cli.CustomQuery("q", "circuit", "account", tc.address) require.Equal(t, tc.expPermission, gjson.Get(rsp, "permission.level").String()) - if tc.limtTypeURLS != "" { - require.Equal(t, tc.limtTypeURLS, gjson.Get(rsp, "permission.limit_type_urls.0").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 rsp != "{}" { + listStr := gjson.Get(rsp, "disabled_list").String() + + // convert string to array + require.NoError(t, json.Unmarshal([]byte(listStr), &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) } }) } diff --git a/x/circuit/autocli.go b/x/circuit/autocli.go index e9cc67701cf7..a1cb8ada74e6 100644 --- a/x/circuit/autocli.go +++ b/x/circuit/autocli.go @@ -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 From 0a52dab6931b0459b0b954e15b95d21c8a666b8b Mon Sep 17 00:00:00 2001 From: akhilkumarpilli <akhilkumar7947@gmail.com> Date: Thu, 24 Oct 2024 11:02:26 +0530 Subject: [PATCH 3/3] address coderabbitai comments --- tests/systemtests/circuit_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/systemtests/circuit_test.go b/tests/systemtests/circuit_test.go index 1fd3e8d0b746..e6b660e22eca 100644 --- a/tests/systemtests/circuit_test.go +++ b/tests/systemtests/circuit_test.go @@ -100,7 +100,7 @@ func TestCircuitCommands(t *testing.T) { name string address string level int - limtTypeURLS []string + limtTypeURLs []string expPermission string }{ { @@ -129,8 +129,8 @@ func TestCircuitCommands(t *testing.T) { 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[:], `","`)) + 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) @@ -138,14 +138,14 @@ func TestCircuitCommands(t *testing.T) { // 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 { + 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) + require.EqualValues(t, tc.limtTypeURLs, msgsList) } }) } @@ -211,11 +211,11 @@ func testCircuitTxCommand(t *testing.T, cli *CLIWrapper, txType, superAdmin, sup // execute given type transaction rsp = cli.CustomQuery("q", "circuit", "disabled-list") var list []string - if rsp != "{}" { - listStr := gjson.Get(rsp, "disabled_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(listStr), &list)) + require.NoError(t, json.Unmarshal([]byte(listJSON), &list)) } for _, msg := range tc.disableMsgs { if txType == "disable" {