742 lines
20 KiB
Go
742 lines
20 KiB
Go
package autocli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
"google.golang.org/protobuf/testing/protocmp"
|
|
"google.golang.org/protobuf/types/known/durationpb"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
"gotest.tools/v3/assert"
|
|
"gotest.tools/v3/golden"
|
|
|
|
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
|
queryv1beta1 "cosmossdk.io/api/cosmos/base/query/v1beta1"
|
|
basev1beta1 "cosmossdk.io/api/cosmos/base/v1beta1"
|
|
"cosmossdk.io/client/v2/internal/testpb"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
)
|
|
|
|
var buildModuleQueryCommand = func(moduleName string, f *fixture) (*cobra.Command, error) {
|
|
ctx := context.WithValue(context.Background(), client.ClientContextKey, &f.clientCtx)
|
|
cmd := topLevelCmd(ctx, moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName))
|
|
|
|
err := f.b.AddQueryServiceCommands(cmd, testCmdDesc)
|
|
return cmd, err
|
|
}
|
|
|
|
var buildModuleQueryCommandOptional = func(moduleName string, f *fixture) (*cobra.Command, error) {
|
|
ctx := context.WithValue(context.Background(), client.ClientContextKey, &f.clientCtx)
|
|
cmd := topLevelCmd(ctx, moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName))
|
|
|
|
err := f.b.AddQueryServiceCommands(cmd, testCmdDescOptional)
|
|
return cmd, err
|
|
}
|
|
|
|
var buildModuleVargasOptional = func(moduleName string, f *fixture) (*cobra.Command, error) {
|
|
ctx := context.WithValue(context.Background(), client.ClientContextKey, &f.clientCtx)
|
|
cmd := topLevelCmd(ctx, moduleName, fmt.Sprintf("Querying commands for the %s module", moduleName))
|
|
|
|
err := f.b.AddQueryServiceCommands(cmd, testCmdDescInvalidOptAndVargas)
|
|
return cmd, err
|
|
}
|
|
|
|
var testCmdDesc = &autocliv1.ServiceCommandDescriptor{
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
Use: "echo [pos1] [pos2] [pos3...]",
|
|
Version: "1.0",
|
|
Alias: []string{"e"},
|
|
SuggestFor: []string{"eco"},
|
|
Example: "echo 1 abc {}",
|
|
Short: "echo echos the value provided by the user",
|
|
Long: "echo echos the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments",
|
|
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
|
{
|
|
ProtoField: "positional1",
|
|
},
|
|
{
|
|
ProtoField: "positional2",
|
|
},
|
|
{
|
|
ProtoField: "positional3_varargs",
|
|
Varargs: true,
|
|
},
|
|
},
|
|
FlagOptions: map[string]*autocliv1.FlagOptions{
|
|
"u32": {
|
|
Name: "uint32",
|
|
Shorthand: "u",
|
|
Usage: "some random uint32",
|
|
},
|
|
"i32": {
|
|
Usage: "some random int32",
|
|
DefaultValue: "3",
|
|
},
|
|
"u64": {
|
|
Usage: "some random uint64",
|
|
DefaultValue: "5",
|
|
},
|
|
"deprecated_field": {
|
|
Deprecated: "don't use this",
|
|
},
|
|
"shorthand_deprecated_field": {
|
|
Shorthand: "s",
|
|
Deprecated: "bad idea",
|
|
},
|
|
"hidden_bool": {
|
|
Hidden: true,
|
|
},
|
|
"a_coin": {
|
|
Usage: "some random coin",
|
|
},
|
|
"duration": {
|
|
Usage: "some random duration",
|
|
},
|
|
"bz": {
|
|
Usage: "some bytes",
|
|
},
|
|
"map_string_string": {
|
|
Usage: "some map of string to string",
|
|
},
|
|
"map_string_uint32": {
|
|
Usage: "some map of string to int32",
|
|
},
|
|
"map_string_coin": {
|
|
Usage: "some map of string to coin",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{
|
|
// we test the sub-command functionality using the same service with different options
|
|
"deprecatedecho": {
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
Deprecated: "don't use this",
|
|
},
|
|
},
|
|
},
|
|
"skipecho": {
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
Skip: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var testCmdDescOptional = &autocliv1.ServiceCommandDescriptor{
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
Use: "echo [pos1] [pos2] [pos3...]",
|
|
Version: "1.0",
|
|
Alias: []string{"e"},
|
|
SuggestFor: []string{"eco"},
|
|
Example: "echo 1 abc {}",
|
|
Short: "echo echos the value provided by the user",
|
|
Long: "echo echos the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments",
|
|
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
|
{
|
|
ProtoField: "positional1",
|
|
},
|
|
{
|
|
ProtoField: "positional2",
|
|
Optional: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var testCmdDescInvalidOptAndVargas = &autocliv1.ServiceCommandDescriptor{
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
Use: "echo [pos1] [pos2] [pos3...]",
|
|
Version: "1.0",
|
|
Alias: []string{"e"},
|
|
SuggestFor: []string{"eco"},
|
|
Example: "echo 1 abc {}",
|
|
Short: "echo echos the value provided by the user",
|
|
Long: "echo echos the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments",
|
|
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
|
{
|
|
ProtoField: "positional1",
|
|
},
|
|
{
|
|
ProtoField: "positional2",
|
|
Optional: true,
|
|
},
|
|
{
|
|
ProtoField: "positional3_varargs",
|
|
Varargs: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
func TestCoin(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"1234foo,4321bar",
|
|
"100uatom",
|
|
"--a-coin", "100000foo",
|
|
)
|
|
assert.ErrorContains(t, err, "coin flag must be a single coin, specific multiple coins with multiple flags or spaces")
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"1234foo",
|
|
"4321bar",
|
|
"100uatom",
|
|
"--a-coin", "100000foo",
|
|
"--coins", "100000bar",
|
|
"--coins", "100uatom",
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
expectedResp := &testpb.EchoResponse{
|
|
Request: &testpb.EchoRequest{
|
|
Positional1: 1,
|
|
Positional2: "abc",
|
|
Positional3Varargs: []*basev1beta1.Coin{
|
|
{Amount: "1234", Denom: "foo"},
|
|
{Amount: "4321", Denom: "bar"},
|
|
{Amount: "100", Denom: "uatom"},
|
|
},
|
|
ACoin: &basev1beta1.Coin{
|
|
Amount: "100000",
|
|
Denom: "foo",
|
|
},
|
|
Coins: []*basev1beta1.Coin{
|
|
{Amount: "100000", Denom: "bar"},
|
|
{Amount: "100", Denom: "uatom"},
|
|
},
|
|
Page: &queryv1beta1.PageRequest{},
|
|
I32: 3,
|
|
U64: 5,
|
|
},
|
|
}
|
|
assert.DeepEqual(t, fixture.conn.lastResponse.(*testpb.EchoResponse), expectedResp, protocmp.Transform())
|
|
}
|
|
|
|
func TestOptional(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommandOptional,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
)
|
|
assert.NilError(t, err)
|
|
request := fixture.conn.lastRequest.(*testpb.EchoRequest)
|
|
assert.Equal(t, request.Positional2, "abc")
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommandOptional,
|
|
"echo",
|
|
"1",
|
|
)
|
|
assert.NilError(t, err)
|
|
|
|
request = fixture.conn.lastRequest.(*testpb.EchoRequest)
|
|
assert.Equal(t, request.Positional2, "")
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommandOptional,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"extra-arg",
|
|
)
|
|
assert.ErrorContains(t, err, "accepts between 1 and 2 arg(s), received 3")
|
|
|
|
_, err = runCmd(fixture, buildModuleVargasOptional,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"extra-arg",
|
|
)
|
|
assert.ErrorContains(t, err, "optional positional argument positional2 must be the last argument")
|
|
}
|
|
|
|
func TestMap(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"1234foo",
|
|
"4321bar",
|
|
"--map-string-uint32", "bar=123",
|
|
"--map-string-string", "val=foo",
|
|
"--map-string-coin", "baz=100000foo",
|
|
"--map-string-coin", "sec=100000bar",
|
|
"--map-string-coin", "multi=100000bar,flag=100000foo",
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"1234foo",
|
|
"4321bar",
|
|
"--map-string-uint32", "bar=123",
|
|
"--map-string-coin", "baz,100000foo",
|
|
"--map-string-coin", "sec=100000bar",
|
|
)
|
|
assert.ErrorContains(t, err, "invalid argument \"baz,100000foo\" for \"--map-string-coin\" flag: invalid format, expected key=value")
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"1234foo",
|
|
"4321bar",
|
|
"--map-string-uint32", "bar=not-unint32",
|
|
"--map-string-coin", "baz=100000foo",
|
|
"--map-string-coin", "sec=100000bar",
|
|
)
|
|
assert.ErrorContains(t, err, "invalid argument \"bar=not-unint32\" for \"--map-string-uint32\" flag: strconv.ParseUint: parsing \"not-unint32\": invalid syntax")
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"1234foo",
|
|
"4321bar",
|
|
"--map-string-uint32", "bar=123.9",
|
|
"--map-string-coin", "baz=100000foo",
|
|
"--map-string-coin", "sec=100000bar",
|
|
)
|
|
assert.ErrorContains(t, err, "invalid argument \"bar=123.9\" for \"--map-string-uint32\" flag: strconv.ParseUint: parsing \"123.9\": invalid syntax")
|
|
}
|
|
|
|
// TestEverything tests all the different types of flags are correctly read and as well as correctly returned
|
|
// This tests the flag binding and the message building
|
|
func TestEverything(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1",
|
|
"abc",
|
|
"123.123123124foo",
|
|
"4321bar",
|
|
"--a-bool",
|
|
"--an-enum", "one",
|
|
"--a-message", `{"bar":"abc", "baz":-3}`,
|
|
"--duration", "4h3s",
|
|
"--uint32", "27",
|
|
"--u64", "3267246890",
|
|
"--i32", "-253",
|
|
"--i64", "-234602347",
|
|
"--str", "def",
|
|
"--timestamp", "2019-01-02T00:01:02Z",
|
|
"--a-coin", "100000foo",
|
|
"--an-address", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk",
|
|
"--a-validator-address", "cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z",
|
|
"--a-consensus-address", "cosmosvalcons16vm0nx49eam4q0xasdnwdzsdl6ymgyjt757sgr",
|
|
"--bz", "c2RncXdlZndkZ3NkZw==",
|
|
"--page-count-total",
|
|
"--page-key", "MTIzNTQ4N3NnaGRhcw==",
|
|
"--page-limit", "1000",
|
|
"--page-offset", "10",
|
|
"--page-reverse",
|
|
"--bools", "true",
|
|
"--bools", "false,false,true",
|
|
"--enums", "one",
|
|
"--enums", "five",
|
|
"--enums", "two",
|
|
"--strings", "abc",
|
|
"--strings", "xyz",
|
|
"--strings", "xyz,qrs",
|
|
"--durations", "3s",
|
|
"--durations", "5s",
|
|
"--durations", "10h",
|
|
"--some-messages", "{}",
|
|
"--some-messages", `{"bar":"baz"}`,
|
|
"--some-messages", `{"baz":-1}`,
|
|
"--uints", "1,2,3",
|
|
"--uints", "4",
|
|
)
|
|
assert.NilError(t, err)
|
|
|
|
expectedResp := &testpb.EchoResponse{
|
|
Request: &testpb.EchoRequest{
|
|
Positional1: 1,
|
|
Positional2: "abc",
|
|
Positional3Varargs: []*basev1beta1.Coin{
|
|
{Amount: "123.123123124", Denom: "foo"},
|
|
{Amount: "4321", Denom: "bar"},
|
|
},
|
|
ABool: true,
|
|
AnEnum: testpb.Enum_ENUM_ONE,
|
|
AMessage: &testpb.AMessage{
|
|
Bar: "abc",
|
|
Baz: -3,
|
|
},
|
|
Duration: durationpb.New(4*time.Hour + 3*time.Second),
|
|
U32: 27,
|
|
U64: 3267246890,
|
|
I32: -253,
|
|
I64: -234602347,
|
|
Str: "def",
|
|
Timestamp: ×tamppb.Timestamp{
|
|
Seconds: 1546387262,
|
|
},
|
|
ACoin: &basev1beta1.Coin{
|
|
Amount: "100000",
|
|
Denom: "foo",
|
|
},
|
|
AnAddress: "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk",
|
|
AValidatorAddress: "cosmosvaloper1tnh2q55v8wyygtt9srz5safamzdengsn9dsd7z",
|
|
AConsensusAddress: "cosmosvalcons16vm0nx49eam4q0xasdnwdzsdl6ymgyjt757sgr",
|
|
Bz: []byte("sdgqwefwdgsdg"),
|
|
Page: &queryv1beta1.PageRequest{
|
|
CountTotal: true,
|
|
Key: []byte("1235487sghdas"),
|
|
Limit: 1000,
|
|
Offset: 10,
|
|
Reverse: true,
|
|
},
|
|
Bools: []bool{true, false, false, true},
|
|
Enums: []testpb.Enum{testpb.Enum_ENUM_ONE, testpb.Enum_ENUM_FIVE, testpb.Enum_ENUM_TWO},
|
|
Strings: []string{
|
|
"abc",
|
|
"xyz",
|
|
"xyz",
|
|
"qrs",
|
|
},
|
|
Durations: []*durationpb.Duration{
|
|
durationpb.New(3 * time.Second),
|
|
durationpb.New(5 * time.Second),
|
|
durationpb.New(10 * time.Hour),
|
|
},
|
|
SomeMessages: []*testpb.AMessage{
|
|
{},
|
|
{Bar: "baz"},
|
|
{Baz: -1},
|
|
},
|
|
Uints: []uint32{1, 2, 3, 4},
|
|
},
|
|
}
|
|
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
assert.DeepEqual(t, fixture.conn.lastResponse.(*testpb.EchoResponse), expectedResp, protocmp.Transform())
|
|
}
|
|
|
|
func TestPubKeyParsingConsensusAddress(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--a-consensus-address", "{\"@type\":\"/cosmos.crypto.ed25519.PubKey\",\"key\":\"j8qdbR+AlH/V6aBTCSWXRvX3JUESF2bV+SEzndBhF0o=\"}",
|
|
"-u", "27", // shorthand
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
}
|
|
|
|
func TestJSONParsing(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--some-messages", `{"bar":"baz"}`,
|
|
"-u", "27", // shorthand
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--some-messages", "testdata/some_message.json",
|
|
"-u", "27", // shorthand
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.DeepEqual(t, fixture.conn.lastRequest, fixture.conn.lastResponse.(*testpb.EchoResponse).Request, protocmp.Transform())
|
|
}
|
|
|
|
func TestOptions(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "123foo",
|
|
"-u", "27", // shorthand
|
|
"--u64", "5", // no opt default value
|
|
)
|
|
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
|
|
}
|
|
|
|
func TestBinaryFlag(t *testing.T) {
|
|
// Create a temporary file with some content
|
|
tempFile, err := os.Open("testdata/file.test")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
content := []byte("this is just a test file")
|
|
if err := tempFile.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Test cases
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected []byte
|
|
hasError bool
|
|
err string
|
|
}{
|
|
{
|
|
name: "Valid file path with extension",
|
|
input: tempFile.Name(),
|
|
expected: content,
|
|
hasError: false,
|
|
err: "",
|
|
},
|
|
{
|
|
name: "Valid hex-encoded string",
|
|
input: "68656c6c6f20776f726c64",
|
|
expected: []byte("hello world"),
|
|
hasError: false,
|
|
err: "",
|
|
},
|
|
{
|
|
name: "Valid base64-encoded string",
|
|
input: "SGVsbG8gV29ybGQ=",
|
|
expected: []byte("Hello World"),
|
|
hasError: false,
|
|
err: "",
|
|
},
|
|
{
|
|
name: "Invalid input (not a file path or encoded string)",
|
|
input: "not a file or encoded string",
|
|
expected: nil,
|
|
hasError: true,
|
|
err: "input string is neither a valid file path, hex, or base64 encoded",
|
|
},
|
|
}
|
|
|
|
// Run test cases
|
|
fixture := initFixture(t)
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", `100foo`,
|
|
"--bz", tc.input,
|
|
)
|
|
if tc.hasError {
|
|
assert.ErrorContains(t, err, tc.err)
|
|
} else {
|
|
assert.NilError(t, err)
|
|
lastReq := fixture.conn.lastRequest.(*testpb.EchoRequest)
|
|
assert.DeepEqual(t, tc.expected, lastReq.Bz)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAddressValidation(t *testing.T) {
|
|
t.Skip() // TODO(@julienrbrt) re-able with better keyring instiantiation
|
|
|
|
fixture := initFixture(t)
|
|
|
|
_, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--an-address", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk",
|
|
)
|
|
assert.NilError(t, err)
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--an-address", "regen1y74p8wyy4enfhfn342njve6cjmj5c8dtlqj7ule2",
|
|
)
|
|
assert.ErrorContains(t, err, "invalid account address")
|
|
|
|
_, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--an-address", "cosmps1BAD_ENCODING",
|
|
)
|
|
assert.ErrorContains(t, err, "invalid account address")
|
|
}
|
|
|
|
func TestOutputFormat(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
out, err := runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--output", "json",
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, strings.Contains(out.String(), "{"))
|
|
|
|
out, err = runCmd(fixture, buildModuleQueryCommand,
|
|
"echo",
|
|
"1", "abc", "1foo",
|
|
"--output", "text",
|
|
)
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, strings.Contains(out.String(), " positional1: 1"))
|
|
}
|
|
|
|
func TestHelpQuery(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
out, err := runCmd(fixture, buildModuleQueryCommand, "-h")
|
|
assert.NilError(t, err)
|
|
golden.Assert(t, out.String(), "help-toplevel.golden")
|
|
|
|
out, err = runCmd(fixture, buildModuleQueryCommand, "echo", "-h")
|
|
assert.NilError(t, err)
|
|
golden.Assert(t, out.String(), "help-echo.golden")
|
|
|
|
out, err = runCmd(fixture, buildModuleQueryCommand, "deprecatedecho", "echo", "-h")
|
|
assert.NilError(t, err)
|
|
golden.Assert(t, out.String(), "help-deprecated.golden")
|
|
|
|
out, err = runCmd(fixture, buildModuleQueryCommand, "skipecho", "-h")
|
|
assert.NilError(t, err)
|
|
golden.Assert(t, out.String(), "help-skip.golden")
|
|
}
|
|
|
|
func TestDeprecatedQuery(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
out, err := runCmd(fixture, 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, 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) {
|
|
b := &Builder{}
|
|
customCommandCalled := false
|
|
|
|
appOptions := AppOptions{
|
|
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
|
"test": {
|
|
Query: testCmdDesc,
|
|
},
|
|
},
|
|
}
|
|
|
|
cmd, err := b.BuildQueryCommand(context.Background(), appOptions, map[string]*cobra.Command{
|
|
"test": {Use: "test", Run: func(cmd *cobra.Command, args []string) {
|
|
customCommandCalled = true
|
|
}},
|
|
})
|
|
assert.NilError(t, err)
|
|
cmd.SetArgs([]string{"test", "query"})
|
|
assert.NilError(t, cmd.Execute())
|
|
assert.Assert(t, customCommandCalled)
|
|
}
|
|
|
|
func TestNotFoundErrorsQuery(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
b := fixture.b
|
|
b.AddQueryConnFlags = nil
|
|
b.AddTxConnFlags = nil
|
|
|
|
buildModuleQueryCommand := func(_ string, cmdDescriptor *autocliv1.ServiceCommandDescriptor) (*cobra.Command, error) {
|
|
cmd := topLevelCmd(context.Background(), "query", "Querying subcommands")
|
|
err := b.AddMsgServiceCommands(cmd, cmdDescriptor)
|
|
return cmd, err
|
|
}
|
|
|
|
// bad service
|
|
_, err := buildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{Service: "foo"})
|
|
assert.ErrorContains(t, err, "can't find service foo")
|
|
|
|
// bad method
|
|
_, err = buildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{{RpcMethod: "bar"}},
|
|
})
|
|
assert.ErrorContains(t, err, "rpc method \"bar\" not found")
|
|
|
|
// bad positional field
|
|
_, err = buildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
|
{
|
|
ProtoField: "foo",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
assert.ErrorContains(t, err, "can't find field foo")
|
|
|
|
// bad flag field
|
|
_, err = buildModuleQueryCommand("test", &autocliv1.ServiceCommandDescriptor{
|
|
Service: testpb.Query_ServiceDesc.ServiceName,
|
|
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
|
{
|
|
RpcMethod: "Echo",
|
|
FlagOptions: map[string]*autocliv1.FlagOptions{
|
|
"baz": {},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
assert.ErrorContains(t, err, "can't find field baz")
|
|
}
|
|
|
|
func TestDurationMarshal(t *testing.T) {
|
|
fixture := initFixture(t)
|
|
|
|
out, err := runCmd(fixture, buildModuleQueryCommand, "echo", "1", "abc", "--duration", "1s")
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, strings.Contains(out.String(), "duration: 1s"))
|
|
}
|