cosmos-sdk/codec/amino_codec_test.go

213 lines
5.5 KiB
Go

package codec_test
import (
"bytes"
"errors"
"testing"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
)
func createTestCodec() *codec.LegacyAmino {
cdc := codec.NewLegacyAmino()
cdc.RegisterInterface((*testdata.Animal)(nil), nil)
cdc.RegisterConcrete(testdata.Dog{}, "testdata/Dog", nil)
cdc.RegisterConcrete(testdata.Cat{}, "testdata/Cat", nil)
return cdc
}
func TestAminoCodec(t *testing.T) {
any, err := types.NewAnyWithValue(&testdata.Dog{Name: "rufus"})
require.NoError(t, err)
testCases := []struct {
name string
codec *codec.AminoCodec
input codec.ProtoMarshaler
recv codec.ProtoMarshaler
marshalErr bool
unmarshalErr bool
}{
{
"valid encoding and decoding",
codec.NewAminoCodec(createTestCodec()),
&testdata.Dog{Name: "rufus"},
&testdata.Dog{},
false,
false,
},
{
"invalid decode type",
codec.NewAminoCodec(createTestCodec()),
&testdata.Dog{Name: "rufus"},
&testdata.Cat{},
false,
true,
},
{
"any marshaling",
codec.NewAminoCodec(createTestCodec()),
&testdata.HasAnimal{Animal: any},
&testdata.HasAnimal{Animal: any},
false,
false,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
bz, err := tc.codec.MarshalBinaryBare(tc.input)
if tc.marshalErr {
require.Error(t, err)
require.Panics(t, func() { tc.codec.MustMarshalBinaryBare(tc.input) })
} else {
var bz2 []byte
require.NoError(t, err)
require.NotPanics(t, func() { bz2 = tc.codec.MustMarshalBinaryBare(tc.input) })
require.Equal(t, bz, bz2)
err := tc.codec.UnmarshalBinaryBare(bz, tc.recv)
if tc.unmarshalErr {
require.Error(t, err)
require.Panics(t, func() { tc.codec.MustUnmarshalBinaryBare(bz, tc.recv) })
} else {
require.NoError(t, err)
require.NotPanics(t, func() { tc.codec.MustUnmarshalBinaryBare(bz, tc.recv) })
require.Equal(t, tc.input, tc.recv)
}
}
bz, err = tc.codec.MarshalBinaryLengthPrefixed(tc.input)
if tc.marshalErr {
require.Error(t, err)
require.Panics(t, func() { tc.codec.MustMarshalBinaryLengthPrefixed(tc.input) })
} else {
var bz2 []byte
require.NoError(t, err)
require.NotPanics(t, func() { bz2 = tc.codec.MustMarshalBinaryLengthPrefixed(tc.input) })
require.Equal(t, bz, bz2)
err := tc.codec.UnmarshalBinaryLengthPrefixed(bz, tc.recv)
if tc.unmarshalErr {
require.Error(t, err)
require.Panics(t, func() { tc.codec.MustUnmarshalBinaryLengthPrefixed(bz, tc.recv) })
} else {
require.NoError(t, err)
require.NotPanics(t, func() { tc.codec.MustUnmarshalBinaryLengthPrefixed(bz, tc.recv) })
require.Equal(t, tc.input, tc.recv)
}
}
bz, err = tc.codec.MarshalJSON(tc.input)
if tc.marshalErr {
require.Error(t, err)
require.Panics(t, func() { tc.codec.MustMarshalJSON(tc.input) })
} else {
var bz2 []byte
require.NoError(t, err)
require.NotPanics(t, func() { bz2 = tc.codec.MustMarshalJSON(tc.input) })
require.Equal(t, bz, bz2)
err := tc.codec.UnmarshalJSON(bz, tc.recv)
if tc.unmarshalErr {
require.Error(t, err)
require.Panics(t, func() { tc.codec.MustUnmarshalJSON(bz, tc.recv) })
} else {
require.NoError(t, err)
require.NotPanics(t, func() { tc.codec.MustUnmarshalJSON(bz, tc.recv) })
require.Equal(t, tc.input, tc.recv)
}
}
})
}
}
func TestAminoCodecMarshalJSONIndent(t *testing.T) {
any, err := types.NewAnyWithValue(&testdata.Dog{Name: "rufus"})
require.NoError(t, err)
testCases := []struct {
name string
input interface{}
marshalErr bool
wantJSON string
}{
{
name: "valid encoding and decoding",
input: &testdata.Dog{Name: "rufus"},
wantJSON: `{
"type": "testdata/Dog",
"value": {
"name": "rufus"
}
}`,
},
{
name: "any marshaling",
input: &testdata.HasAnimal{Animal: any},
wantJSON: `{
"animal": {
"type": "testdata/Dog",
"value": {
"name": "rufus"
}
}
}`,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cdc := codec.NewAminoCodec(createTestCodec())
bz, err := cdc.MarshalJSONIndent(tc.input, "", " ")
if tc.marshalErr {
require.Error(t, err)
require.Panics(t, func() { codec.MustMarshalJSONIndent(cdc.LegacyAmino, tc.input) })
return
}
// Otherwise these are expected to pass.
require.NoError(t, err)
require.Equal(t, bz, []byte(tc.wantJSON))
var bz2 []byte
require.NotPanics(t, func() { bz2 = codec.MustMarshalJSONIndent(cdc.LegacyAmino, tc.input) })
require.Equal(t, bz2, []byte(tc.wantJSON))
})
}
}
func TestAminoCodecPrintTypes(t *testing.T) {
cdc := codec.NewAminoCodec(createTestCodec())
buf := new(bytes.Buffer)
require.NoError(t, cdc.PrintTypes(buf))
lines := bytes.Split(buf.Bytes(), []byte("\n"))
require.True(t, len(lines) > 1)
wantHeader := "| Type | Name | Prefix | Length | Notes |"
require.Equal(t, lines[0], []byte(wantHeader))
// Expecting the types to be listed in the order that they were registered.
require.True(t, bytes.HasPrefix(lines[2], []byte("| Dog | testdata/Dog |")))
require.True(t, bytes.HasPrefix(lines[3], []byte("| Cat | testdata/Cat |")))
}
func TestAminoCodecUnpackAnyFails(t *testing.T) {
cdc := codec.NewAminoCodec(createTestCodec())
err := cdc.UnpackAny(new(types.Any), &testdata.Cat{})
require.Error(t, err)
require.Equal(t, err, errors.New("AminoCodec can't handle unpack protobuf Any's"))
}