Skip to content

Commit

Permalink
x/bank: convert query CLI commands to use gRPC query client (#6367)
Browse files Browse the repository at this point in the history
* Convert x/bank query cli methods to use gRPC query client

* WIP on x/bank cli query migration

* lint

* Fix integration tests

* Remove Println in favor of updated PrintOutput

* Add PrintOutput tests

Co-authored-by: Federico Kunze <[email protected]>
  • Loading branch information
aaronc and fedekunze authored Jun 18, 2020
1 parent 1c8249e commit 257354d
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 185 deletions.
79 changes: 35 additions & 44 deletions client/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package client

import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -321,67 +322,57 @@ func (ctx Context) WithAccountRetriever(retriever AccountRetriever) Context {
return ctx
}

// Println outputs toPrint to the ctx.Output based on ctx.OutputFormat which is
// PrintOutput outputs toPrint to the ctx.Output based on ctx.OutputFormat which is
// either text or json. If text, toPrint will be YAML encoded. Otherwise, toPrint
// will be JSON encoded using ctx.JSONMarshaler. An error is returned upon failure.
func (ctx Context) Println(toPrint interface{}) error {
var (
out []byte
err error
)

switch ctx.OutputFormat {
case "text":
out, err = yaml.Marshal(&toPrint)
func (ctx Context) PrintOutput(toPrint interface{}) error {
// always serialize JSON initially because proto json can't be directly YAML encoded
out, err := ctx.JSONMarshaler.MarshalJSON(toPrint)
if err != nil {
return err
}

case "json":
out, err = ctx.JSONMarshaler.MarshalJSON(toPrint)
if ctx.OutputFormat == "text" {
// handle text format by decoding and re-encoding JSON as YAML
var j interface{}
err = json.Unmarshal(out, &j)
if err != nil {
return err
}

out, err = yaml.Marshal(j)
if err != nil {
return err
}
} else if ctx.Indent {
// To JSON indent, we re-encode the already encoded JSON given there is no
// error. The re-encoded JSON uses the standard library as the initial encoded
// JSON should have the correct output produced by ctx.JSONMarshaler.
if ctx.Indent && err == nil {
out, err = codec.MarshalIndentFromJSON(out)
out, err = codec.MarshalIndentFromJSON(out)
if err != nil {
return err
}
}

writer := ctx.Output
// default to stdout
if writer == nil {
writer = os.Stdout
}

_, err = writer.Write(out)
if err != nil {
return err
}

_, err = fmt.Fprintf(ctx.Output, "%s\n", out)
return err
}

// PrintOutput prints output while respecting output and indent flags
// NOTE: pass in marshalled structs that have been unmarshaled
// because this function will panic on marshaling errors.
//
// TODO: Remove once client-side Protobuf migration has been completed.
// ref: https://github.com/cosmos/cosmos-sdk/issues/5864
func (ctx Context) PrintOutput(toPrint interface{}) error {
var (
out []byte
err error
)

switch ctx.OutputFormat {
case "text":
out, err = yaml.Marshal(&toPrint)

case "json":
out, err = ctx.JSONMarshaler.MarshalJSON(toPrint)

if ctx.Indent {
out, err = codec.MarshalIndentFromJSON(out)
if ctx.OutputFormat != "text" {
// append new-line for formats besides YAML
_, err = writer.Write([]byte("\n"))
if err != nil {
return err
}
}

if err != nil {
return err
}

fmt.Println(string(out))
return nil
}

Expand Down
128 changes: 128 additions & 0 deletions client/context_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package client_test

import (
"bytes"
"os"
"testing"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/testdata"
"github.com/cosmos/cosmos-sdk/codec/types"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"

Expand Down Expand Up @@ -76,3 +81,126 @@ func TestMain(m *testing.M) {
viper.Set(flags.FlagKeyringBackend, keyring.BackendMemory)
os.Exit(m.Run())
}

func TestContext_PrintOutput(t *testing.T) {
ctx := client.Context{}

animal := &testdata.Dog{
Size_: "big",
Name: "Spot",
}
any, err := types.NewAnyWithValue(animal)
require.NoError(t, err)
hasAnimal := &testdata.HasAnimal{
Animal: any,
X: 10,
}

//
// proto
//
registry := testdata.NewTestInterfaceRegistry()
ctx = ctx.WithJSONMarshaler(codec.NewProtoCodec(registry))

// json
buf := &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{"animal":{"@type":"/cosmos_sdk.codec.v1.Dog","size":"big","name":"Spot"},"x":"10"}
`, string(buf.Bytes()))

// json indent
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = true
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{
"animal": {
"@type": "/cosmos_sdk.codec.v1.Dog",
"name": "Spot",
"size": "big"
},
"x": "10"
}
`, string(buf.Bytes()))

// yaml
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "text"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`animal:
'@type': /cosmos_sdk.codec.v1.Dog
name: Spot
size: big
x: "10"
`, string(buf.Bytes()))

//
// amino
//
amino := testdata.NewTestAmino()
ctx = ctx.WithJSONMarshaler(codec.NewAminoCodec(&codec.Codec{Amino: amino}))

// json
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{"type":"testdata/HasAnimal","value":{"animal":{"type":"testdata/Dog","value":{"size":"big","name":"Spot"}},"x":"10"}}
`, string(buf.Bytes()))

// json indent
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "json"
ctx.Indent = true
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`{
"type": "testdata/HasAnimal",
"value": {
"animal": {
"type": "testdata/Dog",
"value": {
"name": "Spot",
"size": "big"
}
},
"x": "10"
}
}
`, string(buf.Bytes()))

// yaml
buf = &bytes.Buffer{}
ctx = ctx.WithOutput(buf)
ctx.OutputFormat = "text"
ctx.Indent = false
err = ctx.PrintOutput(hasAnimal)
require.NoError(t, err)
require.Equal(t,
`type: testdata/HasAnimal
value:
animal:
type: testdata/Dog
value:
name: Spot
size: big
x: "10"
`, string(buf.Bytes()))
}
4 changes: 2 additions & 2 deletions client/tx/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func GenerateTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
return err
}

return clientCtx.Println(tx.GetTx())
return clientCtx.PrintOutput(tx.GetTx())
}

// BroadcastTx attempts to generate, sign and broadcast a transaction with the
Expand Down Expand Up @@ -125,7 +125,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
return err
}

return clientCtx.Println(res)
return clientCtx.PrintOutput(res)
}

// WriteGeneratedTxResponse writes a generated unsigned transaction to the
Expand Down
40 changes: 40 additions & 0 deletions codec/testdata/test_helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package testdata

import (
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/tendermint/go-amino"
)

func NewTestInterfaceRegistry() types.InterfaceRegistry {
registry := types.NewInterfaceRegistry()
registry.RegisterInterface("Animal", (*Animal)(nil))
registry.RegisterImplementations(
(*Animal)(nil),
&Dog{},
&Cat{},
)
registry.RegisterImplementations(
(*HasAnimalI)(nil),
&HasAnimal{},
)
registry.RegisterImplementations(
(*HasHasAnimalI)(nil),
&HasHasAnimal{},
)
return registry
}

func NewTestAmino() *amino.Codec {
cdc := amino.NewCodec()
cdc.RegisterInterface((*Animal)(nil), nil)
cdc.RegisterConcrete(&Dog{}, "testdata/Dog", nil)
cdc.RegisterConcrete(&Cat{}, "testdata/Cat", nil)

cdc.RegisterInterface((*HasAnimalI)(nil), nil)
cdc.RegisterConcrete(&HasAnimal{}, "testdata/HasAnimal", nil)

cdc.RegisterInterface((*HasHasAnimalI)(nil), nil)
cdc.RegisterConcrete(&HasHasAnimal{}, "testdata/HasHasAnimal", nil)

return cdc
}
2 changes: 1 addition & 1 deletion codec/types/compat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Suite struct {
func (s *Suite) SetupTest() {
s.cdc = amino.NewCodec()
s.cdc.RegisterInterface((*testdata.Animal)(nil), nil)
s.cdc.RegisterConcrete(&testdata.Dog{}, "testdata/Dob", nil)
s.cdc.RegisterConcrete(&testdata.Dog{}, "testdata/Dog", nil)

s.spot = &testdata.Dog{Size_: "small", Name: "Spot"}
s.a = TypeWithInterface{Animal: s.spot}
Expand Down
27 changes: 4 additions & 23 deletions codec/types/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,8 @@ import (
"github.com/cosmos/cosmos-sdk/codec/testdata"
)

func NewTestInterfaceRegistry() types.InterfaceRegistry {
registry := types.NewInterfaceRegistry()
registry.RegisterInterface("Animal", (*testdata.Animal)(nil))
registry.RegisterImplementations(
(*testdata.Animal)(nil),
&testdata.Dog{},
&testdata.Cat{},
)
registry.RegisterImplementations(
(*testdata.HasAnimalI)(nil),
&testdata.HasAnimal{},
)
registry.RegisterImplementations(
(*testdata.HasHasAnimalI)(nil),
&testdata.HasHasAnimal{},
)
return registry
}

func TestPackUnpack(t *testing.T) {
registry := NewTestInterfaceRegistry()
registry := testdata.NewTestInterfaceRegistry()

spot := &testdata.Dog{Name: "Spot"}
any := types.Any{}
Expand Down Expand Up @@ -81,7 +62,7 @@ func TestRegister(t *testing.T) {
}

func TestUnpackInterfaces(t *testing.T) {
registry := NewTestInterfaceRegistry()
registry := testdata.NewTestInterfaceRegistry()

spot := &testdata.Dog{Name: "Spot"}
any, err := types.NewAnyWithValue(spot)
Expand All @@ -105,7 +86,7 @@ func TestUnpackInterfaces(t *testing.T) {
}

func TestNested(t *testing.T) {
registry := NewTestInterfaceRegistry()
registry := testdata.NewTestInterfaceRegistry()

spot := &testdata.Dog{Name: "Spot"}
any, err := types.NewAnyWithValue(spot)
Expand Down Expand Up @@ -145,7 +126,7 @@ func TestAny_ProtoJSON(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "{\"@type\":\"/cosmos_sdk.codec.v1.Dog\",\"name\":\"Spot\"}", json)

registry := NewTestInterfaceRegistry()
registry := testdata.NewTestInterfaceRegistry()
jum := &jsonpb.Unmarshaler{}
var any2 types.Any
err = jum.Unmarshal(strings.NewReader(json), &any2)
Expand Down
Loading

0 comments on commit 257354d

Please sign in to comment.