Skip to content

Commit

Permalink
fix(client/v2): improve resolver and tests (backport #16842) (#16861)
Browse files Browse the repository at this point in the history
Co-authored-by: Julien Robert <[email protected]>
  • Loading branch information
mergify[bot] and julienrbrt authored Jul 6, 2023
1 parent 4bda616 commit bc5eb31
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 223 deletions.
10 changes: 6 additions & 4 deletions client/v2/autocli/app.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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,
},
Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions client/v2/autocli/builder.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package autocli

import (
"errors"

"github.com/spf13/cobra"
"google.golang.org/grpc"

Expand All @@ -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
}
17 changes: 9 additions & 8 deletions client/v2/autocli/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
108 changes: 47 additions & 61 deletions client/v2/autocli/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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{})
Expand All @@ -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"),
},
Expand All @@ -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 {
Expand All @@ -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{}
2 changes: 1 addition & 1 deletion client/v2/autocli/flag/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 1 addition & 7 deletions client/v2/autocli/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Expand Down
Loading

0 comments on commit bc5eb31

Please sign in to comment.