cosmossdk.io/client/v2@v2.0.0-beta.1/autocli/common_test.go (about)

     1  package autocli
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"net"
     7  	"testing"
     8  
     9  	"github.com/spf13/cobra"
    10  	"google.golang.org/grpc"
    11  	"google.golang.org/grpc/credentials/insecure"
    12  	"google.golang.org/protobuf/reflect/protoregistry"
    13  	"gotest.tools/v3/assert"
    14  
    15  	autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
    16  	reflectionv2alpha1 "cosmossdk.io/api/cosmos/base/reflection/v2alpha1"
    17  	"cosmossdk.io/client/v2/autocli/flag"
    18  	"cosmossdk.io/client/v2/internal/testpb"
    19  
    20  	"github.com/cosmos/cosmos-sdk/client"
    21  	"github.com/cosmos/cosmos-sdk/client/flags"
    22  	addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
    23  	sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
    24  	sdk "github.com/cosmos/cosmos-sdk/types"
    25  	moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
    26  	"github.com/cosmos/cosmos-sdk/x/bank"
    27  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    28  )
    29  
    30  type fixture struct {
    31  	conn *testClientConn
    32  	b    *Builder
    33  }
    34  
    35  func initFixture(t *testing.T) *fixture {
    36  	t.Helper()
    37  	home := t.TempDir()
    38  	server := grpc.NewServer()
    39  	testpb.RegisterQueryServer(server, &testEchoServer{})
    40  	reflectionv2alpha1.RegisterReflectionServiceServer(server, &testReflectionServer{})
    41  	listener, err := net.Listen("tcp", "127.0.0.1:0")
    42  	assert.NilError(t, err)
    43  	go func() {
    44  		err := server.Serve(listener)
    45  		if err != nil {
    46  			panic(err)
    47  		}
    48  	}()
    49  
    50  	clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
    51  	assert.NilError(t, err)
    52  
    53  	encodingConfig := moduletestutil.MakeTestEncodingConfig(bank.AppModuleBasic{})
    54  	kr, err := sdkkeyring.New(sdk.KeyringServiceName(), sdkkeyring.BackendMemory, home, nil, encodingConfig.Codec)
    55  	assert.NilError(t, err)
    56  
    57  	akr, err := sdkkeyring.NewAutoCLIKeyring(kr)
    58  	assert.NilError(t, err)
    59  
    60  	interfaceRegistry := encodingConfig.Codec.InterfaceRegistry()
    61  	banktypes.RegisterInterfaces(interfaceRegistry)
    62  
    63  	var initClientCtx client.Context
    64  	initClientCtx = initClientCtx.
    65  		WithKeyring(kr).
    66  		WithKeyringDir(home).
    67  		WithHomeDir(home).
    68  		WithViper("").
    69  		WithInterfaceRegistry(interfaceRegistry).
    70  		WithTxConfig(encodingConfig.TxConfig).
    71  		WithAccountRetriever(client.MockAccountRetriever{}).
    72  		WithChainID("autocli-test")
    73  
    74  	conn := &testClientConn{ClientConn: clientConn}
    75  	b := &Builder{
    76  		Builder: flag.Builder{
    77  			TypeResolver:          protoregistry.GlobalTypes,
    78  			FileResolver:          protoregistry.GlobalFiles,
    79  			Keyring:               akr,
    80  			AddressCodec:          addresscodec.NewBech32Codec("cosmos"),
    81  			ValidatorAddressCodec: addresscodec.NewBech32Codec("cosmosvaloper"),
    82  			ConsensusAddressCodec: addresscodec.NewBech32Codec("cosmosvalcons"),
    83  		},
    84  		GetClientConn: func(*cobra.Command) (grpc.ClientConnInterface, error) {
    85  			return conn, nil
    86  		},
    87  		AddQueryConnFlags: flags.AddQueryFlagsToCmd,
    88  		AddTxConnFlags:    flags.AddTxFlagsToCmd,
    89  		ClientCtx:         initClientCtx,
    90  	}
    91  	assert.NilError(t, b.ValidateAndComplete())
    92  
    93  	return &fixture{
    94  		conn: conn,
    95  		b:    b,
    96  	}
    97  }
    98  
    99  func runCmd(conn *testClientConn, b *Builder, command func(moduleName string, b *Builder) (*cobra.Command, error), args ...string) (*bytes.Buffer, error) {
   100  	out := &bytes.Buffer{}
   101  	cmd, err := command("test", b)
   102  	if err != nil {
   103  		return out, err
   104  	}
   105  
   106  	cmd.SetArgs(args)
   107  	cmd.SetOut(out)
   108  	return out, cmd.Execute()
   109  }
   110  
   111  type testReflectionServer struct {
   112  	reflectionv2alpha1.UnimplementedReflectionServiceServer
   113  }
   114  
   115  func (t testReflectionServer) GetConfigurationDescriptor(_ context.Context, client *reflectionv2alpha1.GetConfigurationDescriptorRequest) (*reflectionv2alpha1.GetConfigurationDescriptorResponse, error) {
   116  	return &reflectionv2alpha1.GetConfigurationDescriptorResponse{
   117  		Config: &reflectionv2alpha1.ConfigurationDescriptor{
   118  			Bech32AccountAddressPrefix: "cosmos",
   119  		},
   120  	}, nil
   121  }
   122  
   123  var _ reflectionv2alpha1.ReflectionServiceServer = testReflectionServer{}
   124  
   125  type testClientConn struct {
   126  	*grpc.ClientConn
   127  	lastRequest  interface{}
   128  	lastResponse interface{}
   129  }
   130  
   131  func (t *testClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error {
   132  	err := t.ClientConn.Invoke(ctx, method, args, reply, opts...)
   133  	t.lastRequest = args
   134  	t.lastResponse = reply
   135  	return err
   136  }
   137  
   138  type testEchoServer struct {
   139  	testpb.UnimplementedQueryServer
   140  }
   141  
   142  func (t testEchoServer) Echo(_ context.Context, request *testpb.EchoRequest) (*testpb.EchoResponse, error) {
   143  	return &testpb.EchoResponse{Request: request}, nil
   144  }
   145  
   146  var _ testpb.QueryServer = testEchoServer{}
   147  
   148  func TestEnhanceCommand(t *testing.T) {
   149  	b := &Builder{}
   150  	// Test that the command has a subcommand
   151  	cmd := &cobra.Command{Use: "test"}
   152  	cmd.AddCommand(&cobra.Command{Use: "test"})
   153  
   154  	for i := 0; i < 2; i++ {
   155  		cmdTp := cmdType(i)
   156  
   157  		appOptions := AppOptions{
   158  			ModuleOptions: map[string]*autocliv1.ModuleOptions{
   159  				"test": {},
   160  			},
   161  		}
   162  
   163  		err := b.enhanceCommandCommon(cmd, cmdTp, appOptions, map[string]*cobra.Command{})
   164  		assert.NilError(t, err)
   165  
   166  		cmd = &cobra.Command{Use: "test"}
   167  
   168  		appOptions = AppOptions{
   169  			ModuleOptions: map[string]*autocliv1.ModuleOptions{},
   170  		}
   171  		customCommands := map[string]*cobra.Command{
   172  			"test2": {Use: "test"},
   173  		}
   174  		err = b.enhanceCommandCommon(cmd, cmdTp, appOptions, customCommands)
   175  		assert.NilError(t, err)
   176  
   177  		cmd = &cobra.Command{Use: "test"}
   178  		appOptions = AppOptions{
   179  			ModuleOptions: map[string]*autocliv1.ModuleOptions{
   180  				"test": {Tx: nil},
   181  			},
   182  		}
   183  		err = b.enhanceCommandCommon(cmd, cmdTp, appOptions, map[string]*cobra.Command{})
   184  		assert.NilError(t, err)
   185  	}
   186  }
   187  
   188  func TestErrorBuildCommand(t *testing.T) {
   189  	fixture := initFixture(t)
   190  	b := fixture.b
   191  	b.AddQueryConnFlags = nil
   192  	b.AddTxConnFlags = nil
   193  
   194  	commandDescriptor := &autocliv1.ServiceCommandDescriptor{
   195  		Service: testpb.Msg_ServiceDesc.ServiceName,
   196  		RpcCommandOptions: []*autocliv1.RpcCommandOptions{
   197  			{
   198  				RpcMethod: "Send",
   199  				PositionalArgs: []*autocliv1.PositionalArgDescriptor{
   200  					{
   201  						ProtoField: "un-existent-proto-field",
   202  					},
   203  				},
   204  			},
   205  		},
   206  	}
   207  
   208  	appOptions := AppOptions{
   209  		ModuleOptions: map[string]*autocliv1.ModuleOptions{
   210  			"test": {
   211  				Query: commandDescriptor,
   212  				Tx:    commandDescriptor,
   213  			},
   214  		},
   215  		ClientCtx: b.ClientCtx,
   216  	}
   217  
   218  	_, err := b.BuildMsgCommand(appOptions, nil)
   219  	assert.ErrorContains(t, err, "can't find field un-existent-proto-field")
   220  
   221  	appOptions.ModuleOptions["test"].Tx = &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"}
   222  	appOptions.ModuleOptions["test"].Query = &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"}
   223  	_, err = b.BuildMsgCommand(appOptions, nil)
   224  	assert.ErrorContains(t, err, "can't find service un-existent-service")
   225  }