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 }