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  }