github.com/Finschia/finschia-sdk@v0.48.1/codec/proto_codec_test.go (about) 1 package codec_test 2 3 import ( 4 "errors" 5 "fmt" 6 "testing" 7 8 "github.com/gogo/protobuf/proto" 9 "github.com/stretchr/testify/require" 10 11 "github.com/Finschia/finschia-sdk/codec" 12 "github.com/Finschia/finschia-sdk/codec/types" 13 "github.com/Finschia/finschia-sdk/testutil/testdata" 14 ) 15 16 func createTestInterfaceRegistry() types.InterfaceRegistry { 17 interfaceRegistry := types.NewInterfaceRegistry() 18 interfaceRegistry.RegisterInterface("testdata.Animal", 19 (*testdata.Animal)(nil), 20 &testdata.Dog{}, 21 &testdata.Cat{}, 22 ) 23 24 return interfaceRegistry 25 } 26 27 func TestProtoMarsharlInterface(t *testing.T) { 28 cdc := codec.NewProtoCodec(createTestInterfaceRegistry()) 29 m := interfaceMarshaler{cdc.MarshalInterface, cdc.UnmarshalInterface} 30 testInterfaceMarshaling(require.New(t), m, false) 31 m = interfaceMarshaler{cdc.MarshalInterfaceJSON, cdc.UnmarshalInterfaceJSON} 32 testInterfaceMarshaling(require.New(t), m, false) 33 } 34 35 func TestProtoCodec(t *testing.T) { 36 cdc := codec.NewProtoCodec(createTestInterfaceRegistry()) 37 testMarshaling(t, cdc) 38 } 39 40 type lyingProtoMarshaler struct { 41 codec.ProtoMarshaler 42 falseSize int 43 } 44 45 func (lpm *lyingProtoMarshaler) Size() int { 46 return lpm.falseSize 47 } 48 49 func TestProtoCodecUnmarshalLengthPrefixedChecks(t *testing.T) { 50 cdc := codec.NewProtoCodec(createTestInterfaceRegistry()) 51 52 truth := &testdata.Cat{Lives: 9, Moniker: "glowing"} 53 realSize := len(cdc.MustMarshal(truth)) 54 55 falseSizes := []int{ 56 100, 57 5, 58 } 59 60 for _, falseSize := range falseSizes { 61 falseSize := falseSize 62 63 t.Run(fmt.Sprintf("ByMarshaling falseSize=%d", falseSize), func(t *testing.T) { 64 lpm := &lyingProtoMarshaler{ 65 ProtoMarshaler: &testdata.Cat{Lives: 9, Moniker: "glowing"}, 66 falseSize: falseSize, 67 } 68 var serialized []byte 69 require.NotPanics(t, func() { serialized = cdc.MustMarshalLengthPrefixed(lpm) }) 70 71 recv := new(testdata.Cat) 72 gotErr := cdc.UnmarshalLengthPrefixed(serialized, recv) 73 var wantErr error 74 if falseSize > realSize { 75 wantErr = fmt.Errorf("not enough bytes to read; want: %d, got: %d", falseSize, realSize) 76 } else { 77 wantErr = fmt.Errorf("too many bytes to read; want: %d, got: %d", falseSize, realSize) 78 } 79 require.Equal(t, gotErr, wantErr) 80 }) 81 } 82 83 t.Run("Crafted bad uvarint size", func(t *testing.T) { 84 crafted := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f} 85 recv := new(testdata.Cat) 86 gotErr := cdc.UnmarshalLengthPrefixed(crafted, recv) 87 require.Equal(t, gotErr, errors.New("invalid number of bytes read from length-prefixed encoding: -10")) 88 89 require.Panics(t, func() { cdc.MustUnmarshalLengthPrefixed(crafted, recv) }) 90 }) 91 } 92 93 func mustAny(msg proto.Message) *types.Any { 94 any, err := types.NewAnyWithValue(msg) 95 if err != nil { 96 panic(err) 97 } 98 return any 99 } 100 101 func BenchmarkProtoCodecMarshalLengthPrefixed(b *testing.B) { 102 pCdc := codec.NewProtoCodec(types.NewInterfaceRegistry()) 103 msg := &testdata.HasAnimal{ 104 X: 1000, 105 Animal: mustAny(&testdata.HasAnimal{ 106 X: 2000, 107 Animal: mustAny(&testdata.HasAnimal{ 108 X: 3000, 109 Animal: mustAny(&testdata.HasAnimal{ 110 X: 4000, 111 Animal: mustAny(&testdata.HasAnimal{ 112 X: 5000, 113 Animal: mustAny(&testdata.Cat{ 114 Moniker: "Garfield", 115 Lives: 6, 116 }), 117 }), 118 }), 119 }), 120 }), 121 } 122 123 b.ResetTimer() 124 b.ReportAllocs() 125 126 for i := 0; i < b.N; i++ { 127 blob, err := pCdc.MarshalLengthPrefixed(msg) 128 if err != nil { 129 b.Fatal(err) 130 } 131 b.SetBytes(int64(len(blob))) 132 } 133 }