github.com/MetalBlockchain/metalgo@v1.11.9/codec/test_codec.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package codec
     5  
     6  import (
     7  	"math"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  var (
    14  	Tests = []func(c GeneralCodec, t testing.TB){
    15  		TestStruct,
    16  		TestRegisterStructTwice,
    17  		TestUInt32,
    18  		TestUIntPtr,
    19  		TestSlice,
    20  		TestMaxSizeSlice,
    21  		TestBool,
    22  		TestArray,
    23  		TestBigArray,
    24  		TestPointerToStruct,
    25  		TestSliceOfStruct,
    26  		TestInterface,
    27  		TestSliceOfInterface,
    28  		TestArrayOfInterface,
    29  		TestPointerToInterface,
    30  		TestString,
    31  		TestNilSlice,
    32  		TestSerializeUnexportedField,
    33  		TestSerializeOfNoSerializeField,
    34  		TestNilSliceSerialization,
    35  		TestEmptySliceSerialization,
    36  		TestSliceWithEmptySerialization,
    37  		TestSliceWithEmptySerializationError,
    38  		TestMapWithEmptySerialization,
    39  		TestMapWithEmptySerializationError,
    40  		TestSliceTooLarge,
    41  		TestNegativeNumbers,
    42  		TestTooLargeUnmarshal,
    43  		TestUnmarshalInvalidInterface,
    44  		TestExtraSpace,
    45  		TestSliceLengthOverflow,
    46  		TestMap,
    47  		TestCanMarshalLargeSlices,
    48  	}
    49  
    50  	MultipleTagsTests = []func(c GeneralCodec, t testing.TB){
    51  		TestMultipleTags,
    52  	}
    53  )
    54  
    55  // The below structs and interfaces exist
    56  // for the sake of testing
    57  
    58  var (
    59  	_ Foo = (*MyInnerStruct)(nil)
    60  	_ Foo = (*MyInnerStruct2)(nil)
    61  )
    62  
    63  type Foo interface {
    64  	Foo() int
    65  }
    66  
    67  type MyInnerStruct struct {
    68  	Str string `serialize:"true"`
    69  }
    70  
    71  func (*MyInnerStruct) Foo() int {
    72  	return 1
    73  }
    74  
    75  type MyInnerStruct2 struct {
    76  	Bool bool `serialize:"true"`
    77  }
    78  
    79  func (*MyInnerStruct2) Foo() int {
    80  	return 2
    81  }
    82  
    83  // MyInnerStruct3 embeds Foo, an interface,
    84  // so it has to implement TypeID and ConcreteInstance
    85  type MyInnerStruct3 struct {
    86  	Str string        `serialize:"true"`
    87  	M1  MyInnerStruct `serialize:"true"`
    88  	F   Foo           `serialize:"true"`
    89  }
    90  
    91  type myStruct struct {
    92  	InnerStruct  MyInnerStruct               `serialize:"true"`
    93  	InnerStruct2 *MyInnerStruct              `serialize:"true"`
    94  	Member1      int64                       `serialize:"true"`
    95  	Member2      uint16                      `serialize:"true"`
    96  	MyArray2     [5]string                   `serialize:"true"`
    97  	MyArray3     [3]MyInnerStruct            `serialize:"true"`
    98  	MyArray4     [2]*MyInnerStruct2          `serialize:"true"`
    99  	MySlice      []byte                      `serialize:"true"`
   100  	MySlice2     []string                    `serialize:"true"`
   101  	MySlice3     []MyInnerStruct             `serialize:"true"`
   102  	MySlice4     []*MyInnerStruct2           `serialize:"true"`
   103  	MyArray      [4]byte                     `serialize:"true"`
   104  	MyInterface  Foo                         `serialize:"true"`
   105  	MySlice5     []Foo                       `serialize:"true"`
   106  	InnerStruct3 MyInnerStruct3              `serialize:"true"`
   107  	MyPointer    *Foo                        `serialize:"true"`
   108  	MyMap1       map[string]string           `serialize:"true"`
   109  	MyMap2       map[int32][]MyInnerStruct3  `serialize:"true"`
   110  	MyMap3       map[MyInnerStruct2][]int32  `serialize:"true"`
   111  	MyMap4       map[int32]*int32            `serialize:"true"`
   112  	MyMap5       map[int32]int32             `serialize:"true"`
   113  	MyMap6       map[[5]int32]int32          `serialize:"true"`
   114  	MyMap7       map[interface{}]interface{} `serialize:"true"`
   115  	Uint8        uint8                       `serialize:"true"`
   116  	Int8         int8                        `serialize:"true"`
   117  	Uint16       uint16                      `serialize:"true"`
   118  	Int16        int16                       `serialize:"true"`
   119  	Uint32       uint32                      `serialize:"true"`
   120  	Int32        int32                       `serialize:"true"`
   121  	Uint64       uint64                      `serialize:"true"`
   122  	Int64        int64                       `serialize:"true"`
   123  	Bool         bool                        `serialize:"true"`
   124  	String       string                      `serialize:"true"`
   125  }
   126  
   127  // Test marshaling/unmarshaling a complicated struct
   128  func TestStruct(codec GeneralCodec, t testing.TB) {
   129  	require := require.New(t)
   130  
   131  	temp := Foo(&MyInnerStruct{})
   132  	myMap3 := make(map[MyInnerStruct2][]int32)
   133  	myMap3[MyInnerStruct2{false}] = []int32{991, 12}
   134  	myMap3[MyInnerStruct2{true}] = []int32{1911, 1921}
   135  
   136  	myMap4 := make(map[int32]*int32)
   137  	zero := int32(0)
   138  	one := int32(1)
   139  	myMap4[0] = &zero
   140  	myMap4[1] = &one
   141  
   142  	myMap6 := make(map[[5]int32]int32)
   143  	myMap6[[5]int32{0, 1, 2, 3, 4}] = 1
   144  	myMap6[[5]int32{1, 2, 3, 4, 5}] = 2
   145  
   146  	myMap7 := make(map[interface{}]interface{})
   147  	myMap7["key"] = "value"
   148  	myMap7[int32(1)] = int32(2)
   149  
   150  	myStructInstance := myStruct{
   151  		InnerStruct:  MyInnerStruct{"hello"},
   152  		InnerStruct2: &MyInnerStruct{"yello"},
   153  		Member1:      1,
   154  		Member2:      2,
   155  		MySlice:      []byte{1, 2, 3, 4},
   156  		MySlice2:     []string{"one", "two", "three"},
   157  		MySlice3:     []MyInnerStruct{{"abc"}, {"ab"}, {"c"}},
   158  		MySlice4:     []*MyInnerStruct2{{true}, {}},
   159  		MySlice5:     []Foo{&MyInnerStruct2{true}, &MyInnerStruct2{}},
   160  		MyArray:      [4]byte{5, 6, 7, 8},
   161  		MyArray2:     [5]string{"four", "five", "six", "seven"},
   162  		MyArray3:     [3]MyInnerStruct{{"d"}, {"e"}, {"f"}},
   163  		MyArray4:     [2]*MyInnerStruct2{{}, {true}},
   164  		MyInterface:  &MyInnerStruct{"yeet"},
   165  		InnerStruct3: MyInnerStruct3{
   166  			Str: "str",
   167  			M1: MyInnerStruct{
   168  				Str: "other str",
   169  			},
   170  			F: &MyInnerStruct2{},
   171  		},
   172  		MyPointer: &temp,
   173  		MyMap1: map[string]string{
   174  			"test": "test",
   175  		},
   176  		MyMap2: map[int32][]MyInnerStruct3{
   177  			199921: {
   178  				{
   179  					Str: "str-1",
   180  					M1: MyInnerStruct{
   181  						Str: "other str",
   182  					},
   183  					F: &MyInnerStruct2{},
   184  				},
   185  				{
   186  					Str: "str-2",
   187  					M1: MyInnerStruct{
   188  						Str: "other str",
   189  					},
   190  					F: &MyInnerStruct2{},
   191  				},
   192  			},
   193  			1921: {
   194  				{
   195  					Str: "str0",
   196  					M1: MyInnerStruct{
   197  						Str: "other str",
   198  					},
   199  					F: &MyInnerStruct2{},
   200  				},
   201  				{
   202  					Str: "str1",
   203  					M1: MyInnerStruct{
   204  						Str: "other str",
   205  					},
   206  					F: &MyInnerStruct2{},
   207  				},
   208  			},
   209  		},
   210  		MyMap3: myMap3,
   211  		MyMap4: myMap4,
   212  		MyMap6: myMap6,
   213  		MyMap7: myMap7,
   214  	}
   215  
   216  	manager := NewDefaultManager()
   217  	// Register the types that may be unmarshaled into interfaces
   218  	require.NoError(codec.RegisterType(&MyInnerStruct{}))
   219  	require.NoError(codec.RegisterType(&MyInnerStruct2{}))
   220  	require.NoError(codec.RegisterType(""))
   221  	require.NoError(codec.RegisterType(int32(0)))
   222  	require.NoError(manager.RegisterCodec(0, codec))
   223  
   224  	myStructBytes, err := manager.Marshal(0, myStructInstance)
   225  	require.NoError(err)
   226  
   227  	bytesLen, err := manager.Size(0, myStructInstance)
   228  	require.NoError(err)
   229  	require.Len(myStructBytes, bytesLen)
   230  
   231  	myStructUnmarshaled := &myStruct{}
   232  	version, err := manager.Unmarshal(myStructBytes, myStructUnmarshaled)
   233  	require.NoError(err)
   234  
   235  	// In myStructInstance MyMap4 is nil and in myStructUnmarshaled MyMap4 is an
   236  	// empty map
   237  	require.Empty(myStructUnmarshaled.MyMap5)
   238  	myStructUnmarshaled.MyMap5 = nil
   239  
   240  	require.Zero(version)
   241  	require.Equal(myStructInstance, *myStructUnmarshaled)
   242  }
   243  
   244  func TestRegisterStructTwice(codec GeneralCodec, t testing.TB) {
   245  	require := require.New(t)
   246  
   247  	require.NoError(codec.RegisterType(&MyInnerStruct{}))
   248  	err := codec.RegisterType(&MyInnerStruct{})
   249  	require.ErrorIs(err, ErrDuplicateType)
   250  }
   251  
   252  func TestUInt32(codec GeneralCodec, t testing.TB) {
   253  	require := require.New(t)
   254  
   255  	number := uint32(500)
   256  
   257  	manager := NewDefaultManager()
   258  	require.NoError(manager.RegisterCodec(0, codec))
   259  
   260  	bytes, err := manager.Marshal(0, number)
   261  	require.NoError(err)
   262  
   263  	bytesLen, err := manager.Size(0, number)
   264  	require.NoError(err)
   265  	require.Len(bytes, bytesLen)
   266  
   267  	var numberUnmarshaled uint32
   268  	version, err := manager.Unmarshal(bytes, &numberUnmarshaled)
   269  	require.NoError(err)
   270  	require.Zero(version)
   271  	require.Equal(number, numberUnmarshaled)
   272  }
   273  
   274  func TestUIntPtr(codec GeneralCodec, t testing.TB) {
   275  	require := require.New(t)
   276  
   277  	manager := NewDefaultManager()
   278  
   279  	require.NoError(manager.RegisterCodec(0, codec))
   280  
   281  	number := uintptr(500)
   282  	_, err := manager.Marshal(0, number)
   283  	require.ErrorIs(err, ErrUnsupportedType)
   284  }
   285  
   286  func TestSlice(codec GeneralCodec, t testing.TB) {
   287  	require := require.New(t)
   288  
   289  	mySlice := []bool{true, false, true, true}
   290  	manager := NewDefaultManager()
   291  	require.NoError(manager.RegisterCodec(0, codec))
   292  
   293  	bytes, err := manager.Marshal(0, mySlice)
   294  	require.NoError(err)
   295  
   296  	bytesLen, err := manager.Size(0, mySlice)
   297  	require.NoError(err)
   298  	require.Len(bytes, bytesLen)
   299  
   300  	var sliceUnmarshaled []bool
   301  	version, err := manager.Unmarshal(bytes, &sliceUnmarshaled)
   302  	require.NoError(err)
   303  	require.Zero(version)
   304  	require.Equal(mySlice, sliceUnmarshaled)
   305  }
   306  
   307  // Test marshalling/unmarshalling largest possible slice
   308  func TestMaxSizeSlice(codec GeneralCodec, t testing.TB) {
   309  	require := require.New(t)
   310  
   311  	mySlice := make([]string, math.MaxUint16)
   312  	mySlice[0] = "first!"
   313  	mySlice[math.MaxUint16-1] = "last!"
   314  	manager := NewDefaultManager()
   315  	require.NoError(manager.RegisterCodec(0, codec))
   316  
   317  	bytes, err := manager.Marshal(0, mySlice)
   318  	require.NoError(err)
   319  
   320  	bytesLen, err := manager.Size(0, mySlice)
   321  	require.NoError(err)
   322  	require.Len(bytes, bytesLen)
   323  
   324  	var sliceUnmarshaled []string
   325  	version, err := manager.Unmarshal(bytes, &sliceUnmarshaled)
   326  	require.NoError(err)
   327  	require.Zero(version)
   328  	require.Equal(mySlice, sliceUnmarshaled)
   329  }
   330  
   331  // Test marshalling a bool
   332  func TestBool(codec GeneralCodec, t testing.TB) {
   333  	require := require.New(t)
   334  
   335  	myBool := true
   336  	manager := NewDefaultManager()
   337  	require.NoError(manager.RegisterCodec(0, codec))
   338  
   339  	bytes, err := manager.Marshal(0, myBool)
   340  	require.NoError(err)
   341  
   342  	bytesLen, err := manager.Size(0, myBool)
   343  	require.NoError(err)
   344  	require.Len(bytes, bytesLen)
   345  
   346  	var boolUnmarshaled bool
   347  	version, err := manager.Unmarshal(bytes, &boolUnmarshaled)
   348  	require.NoError(err)
   349  	require.Zero(version)
   350  	require.Equal(myBool, boolUnmarshaled)
   351  }
   352  
   353  // Test marshalling an array
   354  func TestArray(codec GeneralCodec, t testing.TB) {
   355  	require := require.New(t)
   356  
   357  	myArr := [5]uint64{5, 6, 7, 8, 9}
   358  	manager := NewDefaultManager()
   359  	require.NoError(manager.RegisterCodec(0, codec))
   360  
   361  	bytes, err := manager.Marshal(0, myArr)
   362  	require.NoError(err)
   363  
   364  	bytesLen, err := manager.Size(0, myArr)
   365  	require.NoError(err)
   366  	require.Len(bytes, bytesLen)
   367  
   368  	var myArrUnmarshaled [5]uint64
   369  	version, err := manager.Unmarshal(bytes, &myArrUnmarshaled)
   370  	require.NoError(err)
   371  	require.Zero(version)
   372  	require.Equal(myArr, myArrUnmarshaled)
   373  }
   374  
   375  // Test marshalling a really big array
   376  func TestBigArray(codec GeneralCodec, t testing.TB) {
   377  	require := require.New(t)
   378  
   379  	myArr := [30000]uint64{5, 6, 7, 8, 9}
   380  	manager := NewDefaultManager()
   381  	require.NoError(manager.RegisterCodec(0, codec))
   382  
   383  	bytes, err := manager.Marshal(0, myArr)
   384  	require.NoError(err)
   385  
   386  	bytesLen, err := manager.Size(0, myArr)
   387  	require.NoError(err)
   388  	require.Len(bytes, bytesLen)
   389  
   390  	var myArrUnmarshaled [30000]uint64
   391  	version, err := manager.Unmarshal(bytes, &myArrUnmarshaled)
   392  	require.NoError(err)
   393  	require.Zero(version)
   394  	require.Equal(myArr, myArrUnmarshaled)
   395  }
   396  
   397  // Test marshalling a pointer to a struct
   398  func TestPointerToStruct(codec GeneralCodec, t testing.TB) {
   399  	require := require.New(t)
   400  
   401  	myPtr := &MyInnerStruct{Str: "Hello!"}
   402  	manager := NewDefaultManager()
   403  	require.NoError(manager.RegisterCodec(0, codec))
   404  
   405  	bytes, err := manager.Marshal(0, myPtr)
   406  	require.NoError(err)
   407  
   408  	bytesLen, err := manager.Size(0, myPtr)
   409  	require.NoError(err)
   410  	require.Len(bytes, bytesLen)
   411  
   412  	var myPtrUnmarshaled *MyInnerStruct
   413  	version, err := manager.Unmarshal(bytes, &myPtrUnmarshaled)
   414  	require.NoError(err)
   415  	require.Zero(version)
   416  	require.Equal(myPtr, myPtrUnmarshaled)
   417  }
   418  
   419  // Test marshalling a slice of structs
   420  func TestSliceOfStruct(codec GeneralCodec, t testing.TB) {
   421  	require := require.New(t)
   422  	mySlice := []MyInnerStruct3{
   423  		{
   424  			Str: "One",
   425  			M1:  MyInnerStruct{"Two"},
   426  			F:   &MyInnerStruct{"Three"},
   427  		},
   428  		{
   429  			Str: "Four",
   430  			M1:  MyInnerStruct{"Five"},
   431  			F:   &MyInnerStruct{"Six"},
   432  		},
   433  	}
   434  	require.NoError(codec.RegisterType(&MyInnerStruct{}))
   435  
   436  	manager := NewDefaultManager()
   437  	require.NoError(manager.RegisterCodec(0, codec))
   438  
   439  	bytes, err := manager.Marshal(0, mySlice)
   440  	require.NoError(err)
   441  
   442  	bytesLen, err := manager.Size(0, mySlice)
   443  	require.NoError(err)
   444  	require.Len(bytes, bytesLen)
   445  
   446  	var mySliceUnmarshaled []MyInnerStruct3
   447  	version, err := manager.Unmarshal(bytes, &mySliceUnmarshaled)
   448  	require.NoError(err)
   449  	require.Zero(version)
   450  	require.Equal(mySlice, mySliceUnmarshaled)
   451  }
   452  
   453  // Test marshalling an interface
   454  func TestInterface(codec GeneralCodec, t testing.TB) {
   455  	require := require.New(t)
   456  
   457  	require.NoError(codec.RegisterType(&MyInnerStruct2{}))
   458  
   459  	manager := NewDefaultManager()
   460  	require.NoError(manager.RegisterCodec(0, codec))
   461  
   462  	var f Foo = &MyInnerStruct2{true}
   463  	bytes, err := manager.Marshal(0, &f)
   464  	require.NoError(err)
   465  
   466  	bytesLen, err := manager.Size(0, &f)
   467  	require.NoError(err)
   468  	require.Len(bytes, bytesLen)
   469  
   470  	var unmarshaledFoo Foo
   471  	version, err := manager.Unmarshal(bytes, &unmarshaledFoo)
   472  	require.NoError(err)
   473  	require.Zero(version)
   474  	require.Equal(f, unmarshaledFoo)
   475  }
   476  
   477  // Test marshalling a slice of interfaces
   478  func TestSliceOfInterface(codec GeneralCodec, t testing.TB) {
   479  	require := require.New(t)
   480  
   481  	mySlice := []Foo{
   482  		&MyInnerStruct{
   483  			Str: "Hello",
   484  		},
   485  		&MyInnerStruct{
   486  			Str: ", World!",
   487  		},
   488  	}
   489  	require.NoError(codec.RegisterType(&MyInnerStruct{}))
   490  
   491  	manager := NewDefaultManager()
   492  	require.NoError(manager.RegisterCodec(0, codec))
   493  
   494  	bytes, err := manager.Marshal(0, mySlice)
   495  	require.NoError(err)
   496  
   497  	bytesLen, err := manager.Size(0, mySlice)
   498  	require.NoError(err)
   499  	require.Len(bytes, bytesLen)
   500  
   501  	var mySliceUnmarshaled []Foo
   502  	version, err := manager.Unmarshal(bytes, &mySliceUnmarshaled)
   503  	require.NoError(err)
   504  	require.Zero(version)
   505  	require.Equal(mySlice, mySliceUnmarshaled)
   506  }
   507  
   508  // Test marshalling an array of interfaces
   509  func TestArrayOfInterface(codec GeneralCodec, t testing.TB) {
   510  	require := require.New(t)
   511  
   512  	myArray := [2]Foo{
   513  		&MyInnerStruct{
   514  			Str: "Hello",
   515  		},
   516  		&MyInnerStruct{
   517  			Str: ", World!",
   518  		},
   519  	}
   520  	require.NoError(codec.RegisterType(&MyInnerStruct{}))
   521  
   522  	manager := NewDefaultManager()
   523  	require.NoError(manager.RegisterCodec(0, codec))
   524  
   525  	bytes, err := manager.Marshal(0, myArray)
   526  	require.NoError(err)
   527  
   528  	bytesLen, err := manager.Size(0, myArray)
   529  	require.NoError(err)
   530  	require.Len(bytes, bytesLen)
   531  
   532  	var myArrayUnmarshaled [2]Foo
   533  	version, err := manager.Unmarshal(bytes, &myArrayUnmarshaled)
   534  	require.NoError(err)
   535  	require.Zero(version)
   536  	require.Equal(myArray, myArrayUnmarshaled)
   537  }
   538  
   539  // Test marshalling a pointer to an interface
   540  func TestPointerToInterface(codec GeneralCodec, t testing.TB) {
   541  	require := require.New(t)
   542  
   543  	var myinnerStruct Foo = &MyInnerStruct{Str: "Hello!"}
   544  	myPtr := &myinnerStruct
   545  
   546  	require.NoError(codec.RegisterType(&MyInnerStruct{}))
   547  
   548  	manager := NewDefaultManager()
   549  	require.NoError(manager.RegisterCodec(0, codec))
   550  
   551  	bytes, err := manager.Marshal(0, &myPtr)
   552  	require.NoError(err)
   553  
   554  	bytesLen, err := manager.Size(0, &myPtr)
   555  	require.NoError(err)
   556  	require.Len(bytes, bytesLen)
   557  
   558  	var myPtrUnmarshaled *Foo
   559  	version, err := manager.Unmarshal(bytes, &myPtrUnmarshaled)
   560  	require.NoError(err)
   561  	require.Zero(version)
   562  	require.Equal(myPtr, myPtrUnmarshaled)
   563  }
   564  
   565  // Test marshalling a string
   566  func TestString(codec GeneralCodec, t testing.TB) {
   567  	require := require.New(t)
   568  
   569  	myString := "Ayy"
   570  	manager := NewDefaultManager()
   571  	require.NoError(manager.RegisterCodec(0, codec))
   572  
   573  	bytes, err := manager.Marshal(0, myString)
   574  	require.NoError(err)
   575  
   576  	bytesLen, err := manager.Size(0, myString)
   577  	require.NoError(err)
   578  	require.Len(bytes, bytesLen)
   579  
   580  	var stringUnmarshaled string
   581  	version, err := manager.Unmarshal(bytes, &stringUnmarshaled)
   582  	require.NoError(err)
   583  	require.Zero(version)
   584  	require.Equal(myString, stringUnmarshaled)
   585  }
   586  
   587  // Ensure a nil slice is unmarshaled to slice with length 0
   588  func TestNilSlice(codec GeneralCodec, t testing.TB) {
   589  	require := require.New(t)
   590  
   591  	type structWithSlice struct {
   592  		Slice []byte `serialize:"true"`
   593  	}
   594  
   595  	myStruct := structWithSlice{Slice: nil}
   596  	manager := NewDefaultManager()
   597  	require.NoError(manager.RegisterCodec(0, codec))
   598  
   599  	bytes, err := manager.Marshal(0, myStruct)
   600  	require.NoError(err)
   601  
   602  	bytesLen, err := manager.Size(0, myStruct)
   603  	require.NoError(err)
   604  	require.Len(bytes, bytesLen)
   605  
   606  	var structUnmarshaled structWithSlice
   607  	version, err := manager.Unmarshal(bytes, &structUnmarshaled)
   608  	require.NoError(err)
   609  	require.Zero(version)
   610  	require.Empty(structUnmarshaled.Slice)
   611  }
   612  
   613  // Ensure that trying to serialize a struct with an unexported member
   614  // that has `serialize:"true"` returns error
   615  func TestSerializeUnexportedField(codec GeneralCodec, t testing.TB) {
   616  	require := require.New(t)
   617  
   618  	type s struct {
   619  		ExportedField   string `serialize:"true"`
   620  		unexportedField string `serialize:"true"` //nolint:revive
   621  	}
   622  
   623  	myS := s{
   624  		ExportedField:   "Hello, ",
   625  		unexportedField: "world!",
   626  	}
   627  
   628  	manager := NewDefaultManager()
   629  	require.NoError(manager.RegisterCodec(0, codec))
   630  
   631  	_, err := manager.Marshal(0, myS)
   632  	require.ErrorIs(err, ErrUnexportedField)
   633  
   634  	_, err = manager.Size(0, myS)
   635  	require.ErrorIs(err, ErrUnexportedField)
   636  }
   637  
   638  func TestSerializeOfNoSerializeField(codec GeneralCodec, t testing.TB) {
   639  	require := require.New(t)
   640  
   641  	type s struct {
   642  		SerializedField   string `serialize:"true"`
   643  		UnserializedField string `serialize:"false"`
   644  		UnmarkedField     string
   645  	}
   646  	myS := s{
   647  		SerializedField:   "Serialize me",
   648  		UnserializedField: "Do not serialize me",
   649  		UnmarkedField:     "No declared serialize",
   650  	}
   651  	manager := NewDefaultManager()
   652  	require.NoError(manager.RegisterCodec(0, codec))
   653  
   654  	marshalled, err := manager.Marshal(0, myS)
   655  	require.NoError(err)
   656  
   657  	bytesLen, err := manager.Size(0, myS)
   658  	require.NoError(err)
   659  	require.Len(marshalled, bytesLen)
   660  
   661  	unmarshalled := s{}
   662  	version, err := manager.Unmarshal(marshalled, &unmarshalled)
   663  	require.NoError(err)
   664  	require.Zero(version)
   665  
   666  	expectedUnmarshalled := s{SerializedField: "Serialize me"}
   667  	require.Equal(expectedUnmarshalled, unmarshalled)
   668  }
   669  
   670  // Test marshalling of nil slice
   671  func TestNilSliceSerialization(codec GeneralCodec, t testing.TB) {
   672  	require := require.New(t)
   673  
   674  	type simpleSliceStruct struct {
   675  		Arr []uint32 `serialize:"true"`
   676  	}
   677  
   678  	manager := NewDefaultManager()
   679  	require.NoError(manager.RegisterCodec(0, codec))
   680  
   681  	val := &simpleSliceStruct{}
   682  	expected := []byte{0, 0, 0, 0, 0, 0} // 0 for codec version, then nil slice marshaled as 0 length slice
   683  	result, err := manager.Marshal(0, val)
   684  	require.NoError(err)
   685  	require.Equal(expected, result)
   686  
   687  	bytesLen, err := manager.Size(0, val)
   688  	require.NoError(err)
   689  	require.Len(result, bytesLen)
   690  
   691  	valUnmarshaled := &simpleSliceStruct{}
   692  	version, err := manager.Unmarshal(result, &valUnmarshaled)
   693  	require.NoError(err)
   694  	require.Zero(version)
   695  	require.Empty(valUnmarshaled.Arr)
   696  }
   697  
   698  // Test marshaling a slice that has 0 elements (but isn't nil)
   699  func TestEmptySliceSerialization(codec GeneralCodec, t testing.TB) {
   700  	require := require.New(t)
   701  
   702  	type simpleSliceStruct struct {
   703  		Arr []uint32 `serialize:"true"`
   704  	}
   705  
   706  	manager := NewDefaultManager()
   707  	require.NoError(manager.RegisterCodec(0, codec))
   708  
   709  	val := &simpleSliceStruct{Arr: make([]uint32, 0, 1)}
   710  	expected := []byte{0, 0, 0, 0, 0, 0} // 0 for codec version (uint16) and 0 for size (uint32)
   711  	result, err := manager.Marshal(0, val)
   712  	require.NoError(err)
   713  	require.Equal(expected, result)
   714  
   715  	bytesLen, err := manager.Size(0, val)
   716  	require.NoError(err)
   717  	require.Len(result, bytesLen)
   718  
   719  	valUnmarshaled := &simpleSliceStruct{}
   720  	version, err := manager.Unmarshal(result, &valUnmarshaled)
   721  	require.NoError(err)
   722  	require.Zero(version)
   723  	require.Equal(val, valUnmarshaled)
   724  }
   725  
   726  // Test marshaling empty slice of zero length structs
   727  func TestSliceWithEmptySerialization(codec GeneralCodec, t testing.TB) {
   728  	require := require.New(t)
   729  
   730  	type emptyStruct struct{}
   731  
   732  	type nestedSliceStruct struct {
   733  		Arr []emptyStruct `serialize:"true"`
   734  	}
   735  
   736  	manager := NewDefaultManager()
   737  	require.NoError(manager.RegisterCodec(0, codec))
   738  
   739  	val := &nestedSliceStruct{
   740  		Arr: make([]emptyStruct, 0),
   741  	}
   742  	expected := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // codec version (0x00, 0x00) then (0x00, 0x00, 0x00, 0x00) for numElts
   743  	result, err := manager.Marshal(0, val)
   744  	require.NoError(err)
   745  	require.Equal(expected, result)
   746  
   747  	bytesLen, err := manager.Size(0, val)
   748  	require.NoError(err)
   749  	require.Len(result, bytesLen)
   750  
   751  	unmarshaled := nestedSliceStruct{}
   752  	version, err := manager.Unmarshal(expected, &unmarshaled)
   753  	require.NoError(err)
   754  	require.Zero(version)
   755  	require.Empty(unmarshaled.Arr)
   756  }
   757  
   758  func TestSliceWithEmptySerializationError(codec GeneralCodec, t testing.TB) {
   759  	require := require.New(t)
   760  
   761  	type emptyStruct struct{}
   762  
   763  	type nestedSliceStruct struct {
   764  		Arr []emptyStruct `serialize:"true"`
   765  	}
   766  
   767  	manager := NewDefaultManager()
   768  	require.NoError(manager.RegisterCodec(0, codec))
   769  
   770  	val := &nestedSliceStruct{
   771  		Arr: make([]emptyStruct, 1),
   772  	}
   773  	_, err := manager.Marshal(0, val)
   774  	require.ErrorIs(err, ErrMarshalZeroLength)
   775  
   776  	_, err = manager.Size(0, val)
   777  	require.ErrorIs(err, ErrMarshalZeroLength)
   778  
   779  	b := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01} // codec version (0x00, 0x00) then (0x00, 0x00, 0x00, 0x01) for numElts
   780  
   781  	unmarshaled := nestedSliceStruct{}
   782  	_, err = manager.Unmarshal(b, &unmarshaled)
   783  	require.ErrorIs(err, ErrUnmarshalZeroLength)
   784  }
   785  
   786  // Test marshaling empty map of zero length structs
   787  func TestMapWithEmptySerialization(codec GeneralCodec, t testing.TB) {
   788  	require := require.New(t)
   789  
   790  	type emptyStruct struct{}
   791  
   792  	manager := NewDefaultManager()
   793  	require.NoError(manager.RegisterCodec(0, codec))
   794  
   795  	val := make(map[emptyStruct]emptyStruct)
   796  	expected := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // codec version (0x00, 0x00) then (0x00, 0x00, 0x00, 0x00) for numElts
   797  	result, err := manager.Marshal(0, val)
   798  	require.NoError(err)
   799  	require.Equal(expected, result)
   800  
   801  	bytesLen, err := manager.Size(0, val)
   802  	require.NoError(err)
   803  	require.Len(result, bytesLen)
   804  
   805  	var unmarshaled map[emptyStruct]emptyStruct
   806  	version, err := manager.Unmarshal(expected, &unmarshaled)
   807  	require.NoError(err)
   808  	require.Zero(version)
   809  	require.Empty(unmarshaled)
   810  }
   811  
   812  func TestMapWithEmptySerializationError(codec GeneralCodec, t testing.TB) {
   813  	require := require.New(t)
   814  
   815  	type emptyStruct struct{}
   816  
   817  	manager := NewDefaultManager()
   818  	require.NoError(manager.RegisterCodec(0, codec))
   819  
   820  	val := map[emptyStruct]emptyStruct{
   821  		{}: {},
   822  	}
   823  	_, err := manager.Marshal(0, val)
   824  	require.ErrorIs(err, ErrMarshalZeroLength)
   825  
   826  	_, err = manager.Size(0, val)
   827  	require.ErrorIs(err, ErrMarshalZeroLength)
   828  
   829  	b := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01} // codec version (0x00, 0x00) then (0x00, 0x00, 0x00, 0x01) for numElts
   830  
   831  	var unmarshaled map[emptyStruct]emptyStruct
   832  	_, err = manager.Unmarshal(b, &unmarshaled)
   833  	require.ErrorIs(err, ErrUnmarshalZeroLength)
   834  }
   835  
   836  func TestSliceTooLarge(codec GeneralCodec, t testing.TB) {
   837  	require := require.New(t)
   838  
   839  	manager := NewDefaultManager()
   840  	require.NoError(manager.RegisterCodec(0, codec))
   841  
   842  	val := []struct{}{}
   843  	b := []byte{0x00, 0x00, 0xff, 0xff, 0xff, 0xff}
   844  	_, err := manager.Unmarshal(b, &val)
   845  	require.ErrorIs(err, ErrMaxSliceLenExceeded)
   846  }
   847  
   848  // Ensure serializing structs with negative number members works
   849  func TestNegativeNumbers(codec GeneralCodec, t testing.TB) {
   850  	require := require.New(t)
   851  
   852  	type s struct {
   853  		MyInt8  int8  `serialize:"true"`
   854  		MyInt16 int16 `serialize:"true"`
   855  		MyInt32 int32 `serialize:"true"`
   856  		MyInt64 int64 `serialize:"true"`
   857  	}
   858  
   859  	manager := NewDefaultManager()
   860  	require.NoError(manager.RegisterCodec(0, codec))
   861  
   862  	myS := s{-1, -2, -3, -4}
   863  	bytes, err := manager.Marshal(0, myS)
   864  	require.NoError(err)
   865  
   866  	bytesLen, err := manager.Size(0, myS)
   867  	require.NoError(err)
   868  	require.Len(bytes, bytesLen)
   869  
   870  	mySUnmarshaled := s{}
   871  	version, err := manager.Unmarshal(bytes, &mySUnmarshaled)
   872  	require.NoError(err)
   873  	require.Zero(version)
   874  	require.Equal(myS, mySUnmarshaled)
   875  }
   876  
   877  // Ensure deserializing structs with too many bytes errors correctly
   878  func TestTooLargeUnmarshal(codec GeneralCodec, t testing.TB) {
   879  	require := require.New(t)
   880  
   881  	type inner struct {
   882  		B uint16 `serialize:"true"`
   883  	}
   884  	bytes := []byte{0, 0, 0, 0}
   885  
   886  	manager := NewManager(3)
   887  	require.NoError(manager.RegisterCodec(0, codec))
   888  
   889  	s := inner{}
   890  	_, err := manager.Unmarshal(bytes, &s)
   891  	require.ErrorIs(err, ErrUnmarshalTooBig)
   892  }
   893  
   894  type outerInterface interface {
   895  	ToInt() int
   896  }
   897  
   898  type outer struct {
   899  	Interface outerInterface `serialize:"true"`
   900  }
   901  
   902  type innerInterface struct{}
   903  
   904  func (*innerInterface) ToInt() int {
   905  	return 0
   906  }
   907  
   908  type innerNoInterface struct{}
   909  
   910  // Ensure deserializing structs into the wrong interface errors gracefully
   911  func TestUnmarshalInvalidInterface(codec GeneralCodec, t testing.TB) {
   912  	require := require.New(t)
   913  
   914  	manager := NewDefaultManager()
   915  	require.NoError(codec.RegisterType(&innerInterface{}))
   916  	require.NoError(codec.RegisterType(&innerNoInterface{}))
   917  	require.NoError(manager.RegisterCodec(0, codec))
   918  
   919  	{
   920  		bytes := []byte{0, 0, 0, 0, 0, 0}
   921  		s := outer{}
   922  		version, err := manager.Unmarshal(bytes, &s)
   923  		require.NoError(err)
   924  		require.Zero(version)
   925  	}
   926  	{
   927  		bytes := []byte{0, 0, 0, 0, 0, 1}
   928  		s := outer{}
   929  		_, err := manager.Unmarshal(bytes, &s)
   930  		require.ErrorIs(err, ErrDoesNotImplementInterface)
   931  	}
   932  }
   933  
   934  // Test unmarshaling something with extra data
   935  func TestExtraSpace(codec GeneralCodec, t testing.TB) {
   936  	require := require.New(t)
   937  
   938  	manager := NewDefaultManager()
   939  	require.NoError(manager.RegisterCodec(0, codec))
   940  
   941  	// codec version 0x0000 then 0x01 for b then 0x02 as extra data.
   942  	byteSlice := []byte{0x00, 0x00, 0x01, 0x02}
   943  	var b byte
   944  	_, err := manager.Unmarshal(byteSlice, &b)
   945  	require.ErrorIs(err, ErrExtraSpace)
   946  }
   947  
   948  // Ensure deserializing slices whose lengths exceed MaxInt32 error correctly
   949  func TestSliceLengthOverflow(codec GeneralCodec, t testing.TB) {
   950  	require := require.New(t)
   951  
   952  	type inner struct {
   953  		Vals []uint32 `serialize:"true"`
   954  	}
   955  	bytes := []byte{
   956  		// Codec Version:
   957  		0x00, 0x00,
   958  		// Slice Length:
   959  		0xff, 0xff, 0xff, 0xff,
   960  	}
   961  
   962  	manager := NewDefaultManager()
   963  	require.NoError(manager.RegisterCodec(0, codec))
   964  
   965  	s := inner{}
   966  	_, err := manager.Unmarshal(bytes, &s)
   967  	require.ErrorIs(err, ErrMaxSliceLenExceeded)
   968  }
   969  
   970  type MultipleVersionsStruct struct {
   971  	BothTags    string `tag1:"true"  tag2:"true"`
   972  	SingleTag1  string `tag1:"true"`
   973  	SingleTag2  string `             tag2:"true"`
   974  	EitherTags1 string `tag1:"false" tag2:"true"`
   975  	EitherTags2 string `tag1:"true"  tag2:"false"`
   976  	NoTags      string `tag1:"false" tag2:"false"`
   977  }
   978  
   979  func TestMultipleTags(codec GeneralCodec, t testing.TB) {
   980  	// received codec is expected to have both v1 and v2 registered as tags
   981  	inputs := MultipleVersionsStruct{
   982  		BothTags:    "both Tags",
   983  		SingleTag1:  "Only Tag1",
   984  		SingleTag2:  "Only Tag2",
   985  		EitherTags1: "Tag2 is false",
   986  		EitherTags2: "Tag1 is false",
   987  		NoTags:      "Neither Tag",
   988  	}
   989  
   990  	manager := NewDefaultManager()
   991  	for _, codecVersion := range []uint16{0, 1, 2022} {
   992  		require := require.New(t)
   993  
   994  		require.NoError(manager.RegisterCodec(codecVersion, codec))
   995  
   996  		bytes, err := manager.Marshal(codecVersion, inputs)
   997  		require.NoError(err)
   998  
   999  		output := MultipleVersionsStruct{}
  1000  		_, err = manager.Unmarshal(bytes, &output)
  1001  		require.NoError(err)
  1002  
  1003  		require.Equal(inputs.BothTags, output.BothTags)
  1004  		require.Equal(inputs.SingleTag1, output.SingleTag1)
  1005  		require.Equal(inputs.SingleTag2, output.SingleTag2)
  1006  		require.Equal(inputs.EitherTags1, output.EitherTags1)
  1007  		require.Equal(inputs.EitherTags2, output.EitherTags2)
  1008  		require.Empty(output.NoTags)
  1009  	}
  1010  }
  1011  
  1012  func TestMap(codec GeneralCodec, t testing.TB) {
  1013  	require := require.New(t)
  1014  
  1015  	data1 := map[string]MyInnerStruct2{
  1016  		"test": {true},
  1017  		"bar":  {false},
  1018  	}
  1019  
  1020  	data2 := map[string]MyInnerStruct2{
  1021  		"bar":  {false},
  1022  		"test": {true},
  1023  	}
  1024  
  1025  	data3 := map[string]MyInnerStruct2{
  1026  		"bar": {false},
  1027  	}
  1028  
  1029  	outerMap := make(map[int32]map[string]MyInnerStruct2)
  1030  	outerMap[3] = data1
  1031  	outerMap[19] = data2
  1032  
  1033  	outerArray := [3]map[string]MyInnerStruct2{
  1034  		data1,
  1035  		data2,
  1036  		data3,
  1037  	}
  1038  
  1039  	manager := NewDefaultManager()
  1040  	require.NoError(manager.RegisterCodec(0, codec))
  1041  
  1042  	data1Bytes, err := manager.Marshal(0, data1)
  1043  	require.NoError(err)
  1044  
  1045  	// data1 and data2 should have the same byte representation even though
  1046  	// their key-value pairs were defined in a different order.
  1047  	data2Bytes, err := manager.Marshal(0, data2)
  1048  	require.NoError(err)
  1049  	require.Equal(data1Bytes, data2Bytes)
  1050  
  1051  	// Make sure Size returns the correct size for the marshalled data
  1052  	data1Size, err := manager.Size(0, data1)
  1053  	require.NoError(err)
  1054  	require.Len(data1Bytes, data1Size)
  1055  
  1056  	var unmarshalledData1 map[string]MyInnerStruct2
  1057  	_, err = manager.Unmarshal(data1Bytes, &unmarshalledData1)
  1058  	require.NoError(err)
  1059  	require.Equal(data1, unmarshalledData1)
  1060  
  1061  	outerMapBytes, err := manager.Marshal(0, outerMap)
  1062  	require.NoError(err)
  1063  
  1064  	outerMapSize, err := manager.Size(0, outerMap)
  1065  	require.NoError(err)
  1066  	require.Len(outerMapBytes, outerMapSize)
  1067  
  1068  	var unmarshalledOuterMap map[int32]map[string]MyInnerStruct2
  1069  	_, err = manager.Unmarshal(outerMapBytes, &unmarshalledOuterMap)
  1070  	require.NoError(err)
  1071  	require.Equal(outerMap, unmarshalledOuterMap)
  1072  
  1073  	outerArrayBytes, err := manager.Marshal(0, outerArray)
  1074  	require.NoError(err)
  1075  
  1076  	outerArraySize, err := manager.Size(0, outerArray)
  1077  	require.NoError(err)
  1078  	require.Len(outerArrayBytes, outerArraySize)
  1079  }
  1080  
  1081  func TestCanMarshalLargeSlices(codec GeneralCodec, t testing.TB) {
  1082  	require := require.New(t)
  1083  
  1084  	data := make([]uint16, 1_000_000)
  1085  
  1086  	manager := NewManager(math.MaxInt)
  1087  	require.NoError(manager.RegisterCodec(0, codec))
  1088  
  1089  	bytes, err := manager.Marshal(0, data)
  1090  	require.NoError(err)
  1091  
  1092  	var unmarshalledData []uint16
  1093  	_, err = manager.Unmarshal(bytes, &unmarshalledData)
  1094  	require.NoError(err)
  1095  	require.Equal(data, unmarshalledData)
  1096  }
  1097  
  1098  func FuzzStructUnmarshal(codec GeneralCodec, f *testing.F) {
  1099  	manager := NewDefaultManager()
  1100  	// Register the types that may be unmarshaled into interfaces
  1101  	require.NoError(f, codec.RegisterType(&MyInnerStruct{}))
  1102  	require.NoError(f, codec.RegisterType(&MyInnerStruct2{}))
  1103  	require.NoError(f, codec.RegisterType(""))
  1104  	require.NoError(f, codec.RegisterType(int32(0)))
  1105  	require.NoError(f, manager.RegisterCodec(0, codec))
  1106  
  1107  	f.Fuzz(func(t *testing.T, bytes []byte) {
  1108  		require := require.New(t)
  1109  
  1110  		myParsedStruct := &myStruct{}
  1111  		version, err := manager.Unmarshal(bytes, myParsedStruct)
  1112  		if err != nil {
  1113  			return
  1114  		}
  1115  		require.Zero(version)
  1116  
  1117  		marshalled, err := manager.Marshal(version, myParsedStruct)
  1118  		require.NoError(err)
  1119  		require.Equal(bytes, marshalled)
  1120  
  1121  		size, err := manager.Size(version, myParsedStruct)
  1122  		require.NoError(err)
  1123  		require.Len(bytes, size)
  1124  	})
  1125  }