fix(client/v2): improve resolver and tests (backport #16842) (#16861)

Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot] 2023-07-06 17:34:32 +00:00 committed by GitHub
parent 4bda616956
commit bc5eb31751
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 263 additions and 223 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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())

View File

@ -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,57 +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 {
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,
}
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
type fixture struct {
conn *testClientConn
b *Builder
}
func testExecCommonWithErr(t *testing.T, expectedErr string, buildModuleCommand func(string, *Builder) (*cobra.Command, error), args ...string) {
func initFixture(t *testing.T) *fixture {
t.Helper()
server := grpc.NewServer()
testpb.RegisterQueryServer(server, &testEchoServer{})
reflectionv2alpha1.RegisterReflectionServiceServer(server, &testReflectionServer{})
@ -84,21 +41,12 @@ func testExecCommonWithErr(t *testing.T, expectedErr string, buildModuleCommand
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"),
},
@ -108,9 +56,24 @@ func testExecCommonWithErr(t *testing.T, expectedErr string, buildModuleCommand
AddQueryConnFlags: flags.AddQueryFlagsToCmd,
AddTxConnFlags: flags.AddTxFlagsToCmd,
}
assert.NilError(t, b.Validate())
_, err = buildModuleCommand("test", b)
assert.Equal(t, expectedErr, err.Error())
return &fixture{
conn: conn,
b: b,
}
}
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
}
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{}

View File

@ -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)

View File

@ -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)
}

View File

@ -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"))
fixture := initFixture(t)
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"))
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))

View File

@ -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)

View File

@ -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"))
fixture := initFixture(t)
conn = testExecCommon(t, buildModuleQueryCommand, "echo",
"1", "abc", `{}`,
"-s", "foo")
assert.Assert(t, strings.Contains(conn.out.String(), "--shorthand-deprecated-field has been deprecated"))
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{}

View File

@ -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

View File

@ -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