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 }