diff --git a/types/module/interface_module.go b/types/module/interface_module.go index 1aaec42ea8..69524d2d6b 100644 --- a/types/module/interface_module.go +++ b/types/module/interface_module.go @@ -1,6 +1,8 @@ package module -import "github.com/cosmos/cosmos-sdk/codec/types" +import ( + "github.com/cosmos/cosmos-sdk/codec/types" +) // InterfaceModule is an interface that modules can implement in order to // register their interfaces and implementations in an InterfaceRegistry @@ -16,6 +18,7 @@ func (bm BasicManager) RegisterInterfaceModules(registry types.InterfaceRegistry if !ok { continue } + im.RegisterInterfaceTypes(registry) } } diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index 77082da339..d234c5a7ca 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -189,9 +189,6 @@ func (s *IntegrationTestSuite) TestNewSendTxCmd() { val := s.network.Validators[0] clientCtx := val.ClientCtx.WithOutput(buf) - ctx := context.Background() - ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) - testCases := []struct { name string from, to sdk.AccAddress diff --git a/x/crisis/client/cli/cli_test.go b/x/crisis/client/cli/cli_test.go new file mode 100644 index 0000000000..d3a7a2b9f9 --- /dev/null +++ b/x/crisis/client/cli/cli_test.go @@ -0,0 +1,120 @@ +package cli_test + +import ( + "bytes" + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/crisis/client/cli" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg testutil.Config + network *testutil.Network +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := testutil.DefaultConfig() + cfg.NumValidators = 1 + + s.cfg = cfg + s.network = testutil.NewTestNetwork(s.T(), cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestNewMsgVerifyInvariantTxCmd() { + buf := new(bytes.Buffer) + val := s.network.Validators[0] + clientCtx := val.ClientCtx.WithOutput(buf) + + ctx := context.Background() + ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) + + testCases := []struct { + name string + args []string + expectErr bool + respType fmt.Stringer + expectedCode uint32 + }{ + { + "missing module", + []string{ + "", "total-supply", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, nil, 0, + }, + { + "missing invariant route", + []string{ + "bank", "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + true, nil, 0, + }, + { + "valid transaction", + []string{ + "bank", "total-supply", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + false, &sdk.TxResponse{}, 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + buf.Reset() + + cmd := cli.NewMsgVerifyInvariantTxCmd() + cmd.SetErr(buf) + cmd.SetOut(buf) + cmd.SetArgs(tc.args) + + err := cmd.ExecuteContext(ctx) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(buf.Bytes(), tc.respType), buf.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code) + } + }) + } +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/crisis/client/cli/tx.go b/x/crisis/client/cli/tx.go index faab5390b4..29739d1f52 100644 --- a/x/crisis/client/cli/tx.go +++ b/x/crisis/client/cli/tx.go @@ -1,6 +1,8 @@ package cli import ( + "errors" + "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" @@ -10,7 +12,7 @@ import ( ) // NewTxCmd returns a root CLI command handler for all x/crisis transaction commands. -func NewTxCmd(clientCtx client.Context) *cobra.Command { +func NewTxCmd() *cobra.Command { txCmd := &cobra.Command{ Use: types.ModuleName, Short: "Crisis transactions subcommands", @@ -19,30 +21,42 @@ func NewTxCmd(clientCtx client.Context) *cobra.Command { RunE: client.ValidateCmd, } - txCmd.AddCommand(NewMsgVerifyInvariantTxCmd(clientCtx)) + txCmd.AddCommand(NewMsgVerifyInvariantTxCmd()) return txCmd } // NewMsgVerifyInvariantTxCmd returns a CLI command handler for creating a // MsgVerifyInvariant transaction. -func NewMsgVerifyInvariantTxCmd(clientCtx client.Context) *cobra.Command { +func NewMsgVerifyInvariantTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: "invariant-broken [module-name] [invariant-route]", Short: "Submit proof that an invariant broken to halt the chain", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - clientCtx := clientCtx.InitWithInput(cmd.InOrStdin()) + clientCtx := client.GetClientContextFromCmd(cmd) + + clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + + moduleName, route := args[0], args[1] + if moduleName == "" { + return errors.New("invalid module name") + } + if route == "" { + return errors.New("invalid invariant route") + } senderAddr := clientCtx.GetFromAddress() - moduleName, route := args[0], args[1] msg := types.NewMsgVerifyInvariant(senderAddr, moduleName, route) if err := msg.ValidateBasic(); err != nil { return err } - return tx.GenerateOrBroadcastTx(clientCtx, msg) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } diff --git a/x/crisis/module.go b/x/crisis/module.go index 62e50b91ed..d281ac0648 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -5,14 +5,13 @@ import ( "fmt" "github.com/gogo/protobuf/grpc" - "github.com/gorilla/mux" "github.com/spf13/cobra" - abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/crisis/client/cli" @@ -58,13 +57,19 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, bz json.RawMessag func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} // GetTxCmd returns the root tx command for the crisis module. -func (b AppModuleBasic) GetTxCmd(clientCtx client.Context) *cobra.Command { - return cli.NewTxCmd(clientCtx) +func (b AppModuleBasic) GetTxCmd(_ client.Context) *cobra.Command { + return cli.NewTxCmd() } // GetQueryCmd returns no root query command for the crisis module. func (AppModuleBasic) GetQueryCmd(clientCtx client.Context) *cobra.Command { return nil } +// RegisterInterfaceTypes registers interfaces and implementations of the crisis +// module. +func (AppModuleBasic) RegisterInterfaceTypes(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + //____________________________________________________________________________ // AppModule implements an application module for the crisis module. diff --git a/x/crisis/types/codec.go b/x/crisis/types/codec.go index 33cf719824..b35dd6d9a3 100644 --- a/x/crisis/types/codec.go +++ b/x/crisis/types/codec.go @@ -2,14 +2,21 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" ) // RegisterCodec registers the necessary x/crisis interfaces and concrete types // on the provided Amino codec. These types are used for Amino JSON serialization. func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterConcrete(MsgVerifyInvariant{}, "cosmos-sdk/MsgVerifyInvariant", nil) + cdc.RegisterConcrete(&MsgVerifyInvariant{}, "cosmos-sdk/MsgVerifyInvariant", nil) +} + +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgVerifyInvariant{}, + ) } var ( @@ -21,7 +28,7 @@ var ( // // The actual codec used for serialization should be provided to x/crisis and // defined at the application level. - ModuleCdc = codec.NewHybridCodec(amino, types.NewInterfaceRegistry()) + ModuleCdc = codec.NewHybridCodec(amino, codectypes.NewInterfaceRegistry()) ) func init() { diff --git a/x/crisis/types/msgs.go b/x/crisis/types/msgs.go index 4d3a2fa3c2..97446f07d1 100644 --- a/x/crisis/types/msgs.go +++ b/x/crisis/types/msgs.go @@ -8,13 +8,11 @@ import ( var _ sdk.Msg = &MsgVerifyInvariant{} // NewMsgVerifyInvariant creates a new MsgVerifyInvariant object -func NewMsgVerifyInvariant(sender sdk.AccAddress, invariantModuleName, - invariantRoute string) *MsgVerifyInvariant { - +func NewMsgVerifyInvariant(sender sdk.AccAddress, invModeName, invRoute string) *MsgVerifyInvariant { return &MsgVerifyInvariant{ Sender: sender, - InvariantModuleName: invariantModuleName, - InvariantRoute: invariantRoute, + InvariantModuleName: invModeName, + InvariantRoute: invRoute, } }