diff --git a/client/v2/autocli/app.go b/client/v2/autocli/app.go index 0125a67d9931..83f78443e335 100644 --- a/client/v2/autocli/app.go +++ b/client/v2/autocli/app.go @@ -1,10 +1,10 @@ package autocli import ( - "errors" - + "github.com/cosmos/gogoproto/proto" "github.com/spf13/cobra" "google.golang.org/grpc" + "google.golang.org/protobuf/reflect/protoregistry" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" "cosmossdk.io/client/v2/autocli/flag" @@ -60,6 +60,8 @@ type AppOptions struct { func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error { builder := &Builder{ Builder: flag.Builder{ + TypeResolver: protoregistry.GlobalTypes, + FileResolver: proto.HybridResolver, AddressCodec: appOptions.AddressCodec, ValidatorAddressCodec: appOptions.ValidatorAddressCodec, }, @@ -74,8 +76,8 @@ func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error { } func (appOptions AppOptions) EnhanceRootCommandWithBuilder(rootCmd *cobra.Command, builder *Builder) error { - if builder.AddressCodec == nil || builder.ValidatorAddressCodec == nil { - return errors.New("address codec is required in builder") + if err := builder.Validate(); err != nil { + return err } // extract any custom commands from modules diff --git a/client/v2/autocli/builder.go b/client/v2/autocli/builder.go index 5766c5aa8770..65aa13bbbcbf 100644 --- a/client/v2/autocli/builder.go +++ b/client/v2/autocli/builder.go @@ -1,6 +1,8 @@ package autocli import ( + "errors" + "github.com/spf13/cobra" "google.golang.org/grpc" @@ -20,3 +22,23 @@ type Builder struct { AddTxConnFlags func(*cobra.Command) } + +func (b *Builder) Validate() error { + if b.AddressCodec == nil { + return errors.New("address codec is required in builder") + } + + if b.ValidatorAddressCodec == nil { + return errors.New("validator address codec is required in builder") + } + + if b.TypeResolver == nil { + return errors.New("type resolver is required in builder") + } + + if b.FileResolver == nil { + return errors.New("file resolver is required in builder") + } + + return nil +} diff --git a/client/v2/autocli/common.go b/client/v2/autocli/common.go index af9c97ff38df..e4d371b81a1f 100644 --- a/client/v2/autocli/common.go +++ b/client/v2/autocli/common.go @@ -35,14 +35,15 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip } cmd := &cobra.Command{ - Use: use, - Long: long, - Short: options.Short, - Example: options.Example, - Aliases: options.Alias, - SuggestFor: options.SuggestFor, - Deprecated: options.Deprecated, - Version: options.Version, + SilenceUsage: true, + Use: use, + Long: long, + Short: options.Short, + Example: options.Example, + Aliases: options.Alias, + SuggestFor: options.SuggestFor, + Deprecated: options.Deprecated, + Version: options.Version, } cmd.SetContext(context.Background()) diff --git a/client/v2/autocli/common_test.go b/client/v2/autocli/common_test.go index 0e9eb59b0ee9..39150813d67c 100644 --- a/client/v2/autocli/common_test.go +++ b/client/v2/autocli/common_test.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/reflect/protoregistry" "gotest.tools/v3/assert" reflectionv2alpha1 "cosmossdk.io/api/cosmos/base/reflection/v2alpha1" @@ -19,7 +20,13 @@ import ( addresscodec "github.com/cosmos/cosmos-sdk/codec/address" ) -func testExecCommon(t *testing.T, buildModuleCommand func(string, *Builder) (*cobra.Command, error), args ...string) *testClientConn { +type fixture struct { + conn *testClientConn + b *Builder +} + +func initFixture(t *testing.T) *fixture { + t.Helper() server := grpc.NewServer() testpb.RegisterQueryServer(server, &testEchoServer{}) reflectionv2alpha1.RegisterReflectionServiceServer(server, &testReflectionServer{}) @@ -34,21 +41,12 @@ func testExecCommon(t *testing.T, buildModuleCommand func(string, *Builder) (*co clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) assert.NilError(t, err) - defer func() { - err := clientConn.Close() - if err != nil { - panic(err) - } - }() - conn := &testClientConn{ - ClientConn: clientConn, - t: t, - out: &bytes.Buffer{}, - errorOut: &bytes.Buffer{}, - } + conn := &testClientConn{ClientConn: clientConn} b := &Builder{ Builder: flag.Builder{ + TypeResolver: protoregistry.GlobalTypes, + FileResolver: protoregistry.GlobalFiles, AddressCodec: addresscodec.NewBech32Codec("cosmos"), ValidatorAddressCodec: addresscodec.NewBech32Codec("cosmosvaloper"), }, @@ -58,59 +56,24 @@ func testExecCommon(t *testing.T, buildModuleCommand func(string, *Builder) (*co AddQueryConnFlags: flags.AddQueryFlagsToCmd, AddTxConnFlags: flags.AddTxFlagsToCmd, } + assert.NilError(t, b.Validate()) - cmd, err := buildModuleCommand("test", b) - assert.NilError(t, err) - assert.NilError(t, err) - cmd.SetArgs(args) - cmd.SetOut(conn.out) - cmd.SetErr(conn.errorOut) - cmd.Execute() - return conn + return &fixture{ + conn: conn, + b: b, + } } -func testExecCommonWithErr(t *testing.T, expectedErr string, buildModuleCommand func(string, *Builder) (*cobra.Command, error), args ...string) { - server := grpc.NewServer() - testpb.RegisterQueryServer(server, &testEchoServer{}) - reflectionv2alpha1.RegisterReflectionServiceServer(server, &testReflectionServer{}) - listener, err := net.Listen("tcp", "127.0.0.1:0") - assert.NilError(t, err) - go func() { - err := server.Serve(listener) - if err != nil { - panic(err) - } - }() - - clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) - assert.NilError(t, err) - defer func() { - err := clientConn.Close() - if err != nil { - panic(err) - } - }() - - conn := &testClientConn{ - ClientConn: clientConn, - t: t, - out: &bytes.Buffer{}, - errorOut: &bytes.Buffer{}, - } - b := &Builder{ - Builder: flag.Builder{ - AddressCodec: addresscodec.NewBech32Codec("cosmos"), - ValidatorAddressCodec: addresscodec.NewBech32Codec("cosmosvaloper"), - }, - GetClientConn: func(*cobra.Command) (grpc.ClientConnInterface, error) { - return conn, nil - }, - AddQueryConnFlags: flags.AddQueryFlagsToCmd, - AddTxConnFlags: flags.AddTxFlagsToCmd, +func runCmd(conn *testClientConn, b *Builder, command func(moduleName string, b *Builder) (*cobra.Command, error), args ...string) (*bytes.Buffer, error) { + out := &bytes.Buffer{} + cmd, err := command("test", b) + if err != nil { + return out, err } - _, err = buildModuleCommand("test", b) - assert.Equal(t, expectedErr, err.Error()) + cmd.SetArgs(args) + cmd.SetOut(out) + return out, cmd.Execute() } type testReflectionServer struct { @@ -126,3 +89,26 @@ func (t testReflectionServer) GetConfigurationDescriptor(_ context.Context, clie } var _ reflectionv2alpha1.ReflectionServiceServer = testReflectionServer{} + +type testClientConn struct { + *grpc.ClientConn + lastRequest interface{} + lastResponse interface{} +} + +func (t *testClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error { + err := t.ClientConn.Invoke(ctx, method, args, reply, opts...) + t.lastRequest = args + t.lastResponse = reply + return err +} + +type testEchoServer struct { + testpb.UnimplementedQueryServer +} + +func (t testEchoServer) Echo(_ context.Context, request *testpb.EchoRequest) (*testpb.EchoResponse, error) { + return &testpb.EchoResponse{Request: request}, nil +} + +var _ testpb.QueryServer = testEchoServer{} diff --git a/client/v2/autocli/flag/register.go b/client/v2/autocli/flag/register.go index 5edbb0f6e4de..df0c6932f400 100644 --- a/client/v2/autocli/flag/register.go +++ b/client/v2/autocli/flag/register.go @@ -75,7 +75,7 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m } if hasVarargs { - handler.CobraArgs = cobra.MinimumNArgs(n) + handler.CobraArgs = cobra.MinimumNArgs(n - 1) handler.hasVarargs = true } else if hasOptional { handler.CobraArgs = cobra.RangeArgs(n-1, n) diff --git a/client/v2/autocli/msg.go b/client/v2/autocli/msg.go index 704d4e3c08b6..2548e508deda 100644 --- a/client/v2/autocli/msg.go +++ b/client/v2/autocli/msg.go @@ -8,7 +8,6 @@ import ( "github.com/spf13/cobra" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" ) // BuildMsgCommand builds the msg commands for all the provided modules. If a custom command is provided for a @@ -42,12 +41,7 @@ func (b *Builder) AddMsgServiceCommands(cmd *cobra.Command, cmdDescriptor *autoc return nil } - resolver := b.FileResolver - if b.FileResolver == nil { - resolver = protoregistry.GlobalFiles - } - - descriptor, err := resolver.FindDescriptorByName(protoreflect.FullName(cmdDescriptor.Service)) + descriptor, err := b.FileResolver.FindDescriptorByName(protoreflect.FullName(cmdDescriptor.Service)) if err != nil { return errors.Errorf("can't find service %s: %v", cmdDescriptor.Service, err) } diff --git a/client/v2/autocli/msg_test.go b/client/v2/autocli/msg_test.go index b58393da8b19..ed70e203f937 100644 --- a/client/v2/autocli/msg_test.go +++ b/client/v2/autocli/msg_test.go @@ -98,16 +98,18 @@ var testCmdMsgDesc = &autocliv1.ServiceCommandDescriptor{ } func TestMsgOptions(t *testing.T) { - conn := testExecCommon(t, - buildModuleMsgCommand, - "send", "5", "6", "1foo", + fixture := initFixture(t) + out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", + "5", "6", "1foo", "--uint32", "7", "--u64", "8", "--output", "json", ) - response := conn.out.String() + assert.NilError(t, err) + + response := out.String() var output testpb.MsgRequest - err := protojson.Unmarshal([]byte(response), &output) + err = protojson.Unmarshal([]byte(response), &output) assert.NilError(t, err) assert.Equal(t, output.GetU32(), uint32(7)) assert.Equal(t, output.GetPositional1(), int32(5)) @@ -115,50 +117,61 @@ func TestMsgOptions(t *testing.T) { } func TestMsgOutputFormat(t *testing.T) { - conn := testExecCommon(t, buildModuleMsgCommand, + fixture := initFixture(t) + + out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "5", "6", "1foo", "--output", "json", ) - assert.Assert(t, strings.Contains(conn.out.String(), "{")) - conn = testExecCommon(t, buildModuleMsgCommand, + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "{")) + + out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "5", "6", "1foo", "--output", "text", ) - - assert.Assert(t, strings.Contains(conn.out.String(), "positional1: 5")) + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "positional1: 5")) } func TestMsgOptionsError(t *testing.T) { - conn := testExecCommon(t, buildModuleMsgCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "5", "--uint32", "7", "--u64", "8", ) + assert.ErrorContains(t, err, "requires at least 2 arg(s)") - assert.Assert(t, strings.Contains(conn.errorOut.String(), "requires at least 3 arg")) - - conn = testExecCommon(t, buildModuleMsgCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "5", "6", `{"denom":"foo","amount":"1"}`, "--uint32", "7", "--u64", "abc", ) - assert.Assert(t, strings.Contains(conn.errorOut.String(), "invalid argument ")) + assert.ErrorContains(t, err, "invalid argument ") } func TestDeprecatedMsg(t *testing.T) { - conn := testExecCommon(t, buildModuleMsgCommand, "send", - "1", "abc", `{"denom":"foo","amount":"1"}`, - "--deprecated-field", "foo") - assert.Assert(t, strings.Contains(conn.out.String(), "--deprecated-field has been deprecated")) - - conn = testExecCommon(t, buildModuleMsgCommand, "send", - "1", "abc", `{"denom":"foo","amount":"1"}`, - "-d", "foo") - assert.Assert(t, strings.Contains(conn.out.String(), "--shorthand-deprecated-field has been deprecated")) + fixture := initFixture(t) + + out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, + "send", "1", "abc", "--deprecated-field", "foo", + ) + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "--deprecated-field has been deprecated")) + + out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, + "send", "1", "abc", "5stake", "-d", "foo", + ) + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "--shorthand-deprecated-field has been deprecated")) } func TestEverythingMsg(t *testing.T) { - conn := testExecCommon(t, buildModuleMsgCommand, + fixture := initFixture(t) + + out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "1", "abc", @@ -200,9 +213,11 @@ func TestEverythingMsg(t *testing.T) { "--uints", "1,2,3", "--uints", "4", ) - response := conn.out.String() + assert.NilError(t, err) + + response := out.String() var output testpb.MsgRequest - err := protojson.Unmarshal([]byte(response), &output) + err = protojson.Unmarshal([]byte(response), &output) assert.NilError(t, err) assert.Equal(t, output.GetU32(), uint32(27)) assert.Equal(t, output.GetU64(), uint64(3267246890)) @@ -213,14 +228,19 @@ func TestEverythingMsg(t *testing.T) { } func TestHelpMsg(t *testing.T) { - conn := testExecCommon(t, buildModuleMsgCommand, "-h") - golden.Assert(t, conn.out.String(), "help-toplevel-msg.golden") + fixture := initFixture(t) - conn = testExecCommon(t, buildModuleMsgCommand, "send", "-h") - golden.Assert(t, conn.out.String(), "help-echo-msg.golden") + out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-toplevel-msg.golden") - conn = testExecCommon(t, buildModuleMsgCommand, "deprecatedmsg", "send", "-h") - golden.Assert(t, conn.out.String(), "help-deprecated-msg.golden") + out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-echo-msg.golden") + + out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "deprecatedmsg", "send", "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-deprecated-msg.golden") } func TestBuildMsgCommand(t *testing.T) { @@ -246,7 +266,10 @@ func TestBuildMsgCommand(t *testing.T) { } func TestErrorBuildMsgCommand(t *testing.T) { - b := &Builder{} + fixture := initFixture(t) + b := fixture.b + b.AddQueryConnFlags = nil + b.AddTxConnFlags = nil commandDescriptor := &autocliv1.ServiceCommandDescriptor{ Service: testpb.Msg_ServiceDesc.ServiceName, @@ -268,6 +291,8 @@ func TestErrorBuildMsgCommand(t *testing.T) { Tx: commandDescriptor, }, }, + AddressCodec: b.AddressCodec, + ValidatorAddressCodec: b.ValidatorAddressCodec, } _, err := b.BuildMsgCommand(appOptions, nil, enhanceMsg) @@ -280,7 +305,11 @@ func TestErrorBuildMsgCommand(t *testing.T) { } func TestNotFoundErrorsMsg(t *testing.T) { - b := &Builder{} + fixture := initFixture(t) + b := fixture.b + b.AddQueryConnFlags = nil + b.AddTxConnFlags = nil + buildModuleMsgCommand := func(moduleName string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) { cmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName)) diff --git a/client/v2/autocli/query.go b/client/v2/autocli/query.go index 3fd10ea525dd..a97e92b91210 100644 --- a/client/v2/autocli/query.go +++ b/client/v2/autocli/query.go @@ -8,7 +8,6 @@ import ( "github.com/spf13/cobra" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" "cosmossdk.io/client/v2/internal/util" ) @@ -46,11 +45,7 @@ func (b *Builder) AddQueryServiceCommands(cmd *cobra.Command, cmdDescriptor *aut return nil } - resolver := b.FileResolver - if resolver == nil { - resolver = protoregistry.GlobalFiles - } - descriptor, err := resolver.FindDescriptorByName(protoreflect.FullName(cmdDescriptor.Service)) + descriptor, err := b.FileResolver.FindDescriptorByName(protoreflect.FullName(cmdDescriptor.Service)) if err != nil { return errors.Errorf("can't find service %s: %v", cmdDescriptor.Service, err) } @@ -121,7 +116,7 @@ func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescript bz, err := jsonMarshalOptions.Marshal(output.Interface()) if err != nil { - return err + return fmt.Errorf("cannot marshal response %v: %w", output.Interface(), err) } err = b.outOrStdoutFormat(cmd, bz) diff --git a/client/v2/autocli/query_test.go b/client/v2/autocli/query_test.go index 8bcef2d988e0..cf467f313248 100644 --- a/client/v2/autocli/query_test.go +++ b/client/v2/autocli/query_test.go @@ -1,15 +1,12 @@ package autocli import ( - "bytes" - "context" "fmt" "os" "strings" "testing" "github.com/spf13/cobra" - "google.golang.org/grpc" "google.golang.org/protobuf/testing/protocmp" "gotest.tools/v3/assert" "gotest.tools/v3/golden" @@ -186,7 +183,9 @@ var testCmdDescInvalidOptAndVargas = &autocliv1.ServiceCommandDescriptor{ } func TestCoin(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -195,45 +194,54 @@ func TestCoin(t *testing.T) { "--a-coin", "100000foo", "--duration", "4h3s", ) - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.NilError(t, err) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) } func TestOptional(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommandOptional, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommandOptional, "echo", "1", "abc", ) - request := conn.lastRequest.(*testpb.EchoRequest) + assert.NilError(t, err) + request := fixture.conn.lastRequest.(*testpb.EchoRequest) assert.Equal(t, request.Positional2, "abc") - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) - conn = testExecCommon(t, buildModuleQueryCommandOptional, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommandOptional, "echo", "1", ) - request = conn.lastRequest.(*testpb.EchoRequest) + assert.NilError(t, err) + + request = fixture.conn.lastRequest.(*testpb.EchoRequest) assert.Equal(t, request.Positional2, "") - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) - conn = testExecCommon(t, buildModuleQueryCommandOptional, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommandOptional, "echo", "1", "abc", "extra-arg", ) - assert.Equal(t, conn.errorOut.String(), "Error: accepts between 1 and 2 arg(s), received 3\n") + assert.ErrorContains(t, err, "accepts between 1 and 2 arg(s), received 3") - testExecCommonWithErr(t, "optional positional argument positional2 must be the last argument", buildModuleVargasOptional, + _, err = runCmd(fixture.conn, fixture.b, buildModuleVargasOptional, "echo", "1", "abc", "extra-arg", ) + assert.ErrorContains(t, err, "optional positional argument positional2 must be the last argument") } func TestMap(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -245,9 +253,10 @@ func TestMap(t *testing.T) { "--map-string-coin", "sec=100000bar", "--map-string-coin", "multi=100000bar,flag=100000foo", ) - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.NilError(t, err) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) - conn = testExecCommon(t, buildModuleQueryCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -257,9 +266,9 @@ func TestMap(t *testing.T) { "--map-string-coin", "baz,100000foo", "--map-string-coin", "sec=100000bar", ) - assert.Equal(t, "Error: invalid argument \"baz,100000foo\" for \"--map-string-coin\" flag: invalid format, expected key=value\n", conn.errorOut.String()) + assert.ErrorContains(t, err, "invalid argument \"baz,100000foo\" for \"--map-string-coin\" flag: invalid format, expected key=value") - conn = testExecCommon(t, buildModuleQueryCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -269,9 +278,9 @@ func TestMap(t *testing.T) { "--map-string-coin", "baz=100000foo", "--map-string-coin", "sec=100000bar", ) - assert.Equal(t, "Error: invalid argument \"bar=not-unint32\" for \"--map-string-uint32\" flag: strconv.ParseUint: parsing \"not-unint32\": invalid syntax\n", conn.errorOut.String()) + assert.ErrorContains(t, err, "invalid argument \"bar=not-unint32\" for \"--map-string-uint32\" flag: strconv.ParseUint: parsing \"not-unint32\": invalid syntax") - conn = testExecCommon(t, buildModuleQueryCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -281,11 +290,13 @@ func TestMap(t *testing.T) { "--map-string-coin", "baz=100000foo", "--map-string-coin", "sec=100000bar", ) - assert.Equal(t, "Error: invalid argument \"bar=123.9\" for \"--map-string-uint32\" flag: strconv.ParseUint: parsing \"123.9\": invalid syntax\n", conn.errorOut.String()) + assert.ErrorContains(t, err, "invalid argument \"bar=123.9\" for \"--map-string-uint32\" flag: strconv.ParseUint: parsing \"123.9\": invalid syntax") } func TestMapError(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -295,11 +306,14 @@ func TestMapError(t *testing.T) { "--map-string-coin", "baz=100000foo", "--map-string-coin", "sec=100000bar", ) - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.NilError(t, err) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) } func TestEverything(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", @@ -340,35 +354,44 @@ func TestEverything(t *testing.T) { "--uints", "1,2,3", "--uints", "4", ) - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.NilError(t, err) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) } func TestJSONParsing(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", "--some-messages", `{"bar":"baz"}`, "-u", "27", // shorthand ) - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.NilError(t, err) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) - conn = testExecCommon(t, buildModuleQueryCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", "--some-messages", "testdata/some_message.json", "-u", "27", // shorthand ) - assert.DeepEqual(t, conn.lastRequest, conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) + assert.NilError(t, err) + assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform()) } func TestOptions(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "123foo", "-u", "27", // shorthand "--u64", "5", // no opt default value ) - lastReq := conn.lastRequest.(*testpb.EchoRequest) + assert.NilError(t, err) + + lastReq := fixture.conn.lastRequest.(*testpb.EchoRequest) assert.Equal(t, uint32(27), lastReq.U32) // shorthand got set assert.Equal(t, int32(3), lastReq.I32) // default value got set assert.Equal(t, uint64(5), lastReq.U64) // no opt default value got set @@ -424,87 +447,102 @@ func TestBinaryFlag(t *testing.T) { } // Run test cases + fixture := initFixture(t) for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", - "1", "abc", `{"denom":"foo","amount":"1"}`, + "1", "abc", `100foo`, "--bz", tc.input, ) - errorOut := conn.errorOut.String() - if errorOut == "" { - lastReq := conn.lastRequest.(*testpb.EchoRequest) - assert.DeepEqual(t, tc.expected, lastReq.Bz) + if tc.hasError { + assert.ErrorContains(t, err, tc.err) } else { - assert.Assert(t, strings.Contains(conn.errorOut.String(), tc.err)) + assert.NilError(t, err) + lastReq := fixture.conn.lastRequest.(*testpb.EchoRequest) + assert.DeepEqual(t, tc.expected, lastReq.Bz) } }) } } func TestAddressValidation(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + _, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", "--an-address", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", ) - assert.Equal(t, "", conn.errorOut.String()) + assert.NilError(t, err) - conn = testExecCommon(t, buildModuleQueryCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", - "--an-address", "regen1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", + "--an-address", "regen1y74p8wyy4enfhfn342njve6cjmj5c8dtlqj7ule2", ) - assert.Assert(t, strings.Contains(conn.errorOut.String(), "Error: invalid argument")) + assert.ErrorContains(t, err, "invalid bech32 account address") - conn = testExecCommon(t, buildModuleQueryCommand, + _, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", "--an-address", "cosmps1BAD_ENCODING", ) - assert.Assert(t, strings.Contains(conn.errorOut.String(), "Error: invalid argument")) + assert.ErrorContains(t, err, "invalid bech32 account address") } func TestOutputFormat(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, + fixture := initFixture(t) + + out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", "--output", "json", ) - assert.Assert(t, strings.Contains(conn.out.String(), "{")) - conn = testExecCommon(t, buildModuleQueryCommand, + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "{")) + + out, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "1", "abc", "1foo", "--output", "text", ) - fmt.Println(conn.out.String()) - assert.Assert(t, strings.Contains(conn.out.String(), " positional1: 1")) + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), " positional1: 1")) } func TestHelp(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, "-h") - golden.Assert(t, conn.out.String(), "help-toplevel.golden") + fixture := initFixture(t) - conn = testExecCommon(t, buildModuleQueryCommand, "echo", "-h") - golden.Assert(t, conn.out.String(), "help-echo.golden") + out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-toplevel.golden") - conn = testExecCommon(t, buildModuleQueryCommand, "deprecatedecho", "echo", "-h") - golden.Assert(t, conn.out.String(), "help-deprecated.golden") + out, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-echo.golden") - conn = testExecCommon(t, buildModuleQueryCommand, "skipecho", "-h") - golden.Assert(t, conn.out.String(), "help-skip.golden") + out, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "deprecatedecho", "echo", "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-deprecated.golden") + + out, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "skipecho", "-h") + assert.NilError(t, err) + golden.Assert(t, out.String(), "help-skip.golden") } func TestDeprecated(t *testing.T) { - conn := testExecCommon(t, buildModuleQueryCommand, "echo", - "1", "abc", `{}`, - "--deprecated-field", "foo") - assert.Assert(t, strings.Contains(conn.out.String(), "--deprecated-field has been deprecated")) - - conn = testExecCommon(t, buildModuleQueryCommand, "echo", - "1", "abc", `{}`, - "-s", "foo") - assert.Assert(t, strings.Contains(conn.out.String(), "--shorthand-deprecated-field has been deprecated")) + fixture := initFixture(t) + + out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", + "1", "abc", "--deprecated-field", "foo") + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "--deprecated-field has been deprecated")) + + out, err = runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo", + "1", "abc", "-s", "foo") + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "--shorthand-deprecated-field has been deprecated")) } func TestBuildCustomQueryCommand(t *testing.T) { @@ -531,7 +569,10 @@ func TestBuildCustomQueryCommand(t *testing.T) { } func TestNotFoundErrors(t *testing.T) { - b := &Builder{} + fixture := initFixture(t) + b := fixture.b + b.AddQueryConnFlags = nil + b.AddTxConnFlags = nil buildModuleQueryCommand := func(moduleName string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) { cmd := topLevelCmd("query", "Querying subcommands") @@ -581,29 +622,3 @@ func TestNotFoundErrors(t *testing.T) { }) assert.ErrorContains(t, err, "can't find field baz") } - -type testClientConn struct { - *grpc.ClientConn - t *testing.T - lastRequest interface{} - lastResponse interface{} - out *bytes.Buffer - errorOut *bytes.Buffer -} - -func (t *testClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error { - err := t.ClientConn.Invoke(ctx, method, args, reply, opts...) - t.lastRequest = args - t.lastResponse = reply - return err -} - -type testEchoServer struct { - testpb.UnimplementedQueryServer -} - -func (t testEchoServer) Echo(_ context.Context, request *testpb.EchoRequest) (*testpb.EchoResponse, error) { - return &testpb.EchoResponse{Request: request}, nil -} - -var _ testpb.QueryServer = testEchoServer{} diff --git a/client/v2/go.mod b/client/v2/go.mod index 1e132baf84e0..911a281cd3b1 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -9,6 +9,7 @@ require ( github.com/cockroachdb/errors v1.10.0 github.com/cosmos/cosmos-proto v1.0.0-beta.3 github.com/cosmos/cosmos-sdk v0.50.0-alpha.1 + github.com/cosmos/gogoproto v1.4.10 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df @@ -46,7 +47,6 @@ require ( github.com/cosmos/cosmos-db v1.0.0 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/gogoproto v1.4.10 // indirect github.com/cosmos/iavl v1.0.0-beta.2 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect diff --git a/client/v2/internal/util/util.go b/client/v2/internal/util/util.go index d37c023a8706..31d748a8f7b3 100644 --- a/client/v2/internal/util/util.go +++ b/client/v2/internal/util/util.go @@ -17,10 +17,6 @@ func DescriptorDocs(descriptor protoreflect.Descriptor) string { } func ResolveMessageType(resolver protoregistry.MessageTypeResolver, descriptor protoreflect.MessageDescriptor) protoreflect.MessageType { - if resolver == nil { - resolver = protoregistry.GlobalTypes - } - typ, err := resolver.FindMessageByName(descriptor.FullName()) if err == nil { return typ