Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
parent
4bda616956
commit
bc5eb31751
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user