github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/primitive/values_test.go (about) 1 // Copyright 2020 DataStax 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package primitive 16 17 import ( 18 "bytes" 19 "errors" 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 ) 25 26 func TestReadValue(t *testing.T) { 27 // versions < 4 28 for _, version := range SupportedProtocolVersionsLesserThan(ProtocolVersion4) { 29 t.Run(version.String(), func(t *testing.T) { 30 tests := []struct { 31 name string 32 source []byte 33 expected *Value 34 err error 35 }{ 36 { 37 "value length null", 38 []byte{ 39 0xff, 0xff, 0xff, 0xff, // length -1 40 }, 41 NewNullValue(), 42 nil, 43 }, 44 { 45 "value length unset", 46 []byte{ 47 0xff, 0xff, 0xff, 0xfe, // length -2 48 }, 49 nil, 50 fmt.Errorf("cannot use unset value with %v", version), 51 }, 52 { 53 "value empty", 54 []byte{ 55 0, 0, 0, 0, // length 56 }, 57 NewValue([]byte{}), 58 nil, 59 }, 60 { 61 "value non empty", 62 []byte{ 63 0, 0, 0, 5, // length 64 1, 2, 3, 4, 5, // contents 65 }, 66 NewValue([]byte{1, 2, 3, 4, 5}), 67 nil, 68 }, 69 { 70 "cannot read value length", 71 []byte{ 72 0, 0, 0, 73 }, 74 nil, 75 fmt.Errorf("cannot read [value] length: %w", 76 fmt.Errorf("cannot read [int]: %w", 77 errors.New("unexpected EOF")), 78 ), 79 }, 80 { 81 "invalid value length", 82 []byte{ 83 0xff, 0xff, 0xff, 0xfd, // -3 84 }, 85 nil, 86 errors.New("invalid [value] length: -3"), 87 }, 88 { 89 "cannot read value contents", 90 []byte{ 91 0, 0, 0, 2, // length 92 1, // contents 93 }, 94 nil, 95 fmt.Errorf("cannot read [value] content: %w", 96 errors.New("unexpected EOF")), 97 }, 98 } 99 for _, tt := range tests { 100 t.Run(tt.name, func(t *testing.T) { 101 buf := bytes.NewReader(tt.source) 102 actual, err := ReadValue(buf, version) 103 assert.Equal(t, tt.expected, actual) 104 assert.Equal(t, tt.err, err) 105 }) 106 } 107 }) 108 } 109 // versions >= 4 110 for _, version := range SupportedProtocolVersionsGreaterThanOrEqualTo(ProtocolVersion4) { 111 t.Run(version.String(), func(t *testing.T) { 112 var tests = []struct { 113 name string 114 source []byte 115 expected *Value 116 err error 117 }{ 118 { 119 "value length null", 120 []byte{ 121 0xff, 0xff, 0xff, 0xff, // length -1 122 }, 123 NewNullValue(), 124 nil, 125 }, 126 { 127 "value length unset", 128 []byte{ 129 0xff, 0xff, 0xff, 0xfe, // length -2 130 }, 131 NewUnsetValue(), 132 nil, 133 }, 134 { 135 "value empty", 136 []byte{ 137 0, 0, 0, 0, // length 138 }, 139 NewValue([]byte{}), 140 nil, 141 }, 142 { 143 "value non empty", 144 []byte{ 145 0, 0, 0, 5, // length 146 1, 2, 3, 4, 5, // contents 147 }, 148 NewValue([]byte{1, 2, 3, 4, 5}), 149 nil, 150 }, 151 { 152 "cannot read value length", 153 []byte{ 154 0, 0, 0, 155 }, 156 nil, 157 fmt.Errorf("cannot read [value] length: %w", 158 fmt.Errorf("cannot read [int]: %w", 159 errors.New("unexpected EOF")), 160 ), 161 }, 162 { 163 "invalid value length", 164 []byte{ 165 0xff, 0xff, 0xff, 0xfd, // -3 166 }, 167 nil, 168 errors.New("invalid [value] length: -3"), 169 }, 170 { 171 "cannot read value contents", 172 []byte{ 173 0, 0, 0, 2, // length 174 1, // contents 175 }, 176 nil, 177 fmt.Errorf("cannot read [value] content: %w", 178 errors.New("unexpected EOF")), 179 }, 180 } 181 for _, tt := range tests { 182 t.Run(tt.name, func(t *testing.T) { 183 buf := bytes.NewReader(tt.source) 184 actual, err := ReadValue(buf, version) 185 assert.Equal(t, tt.expected, actual) 186 assert.Equal(t, tt.err, err) 187 }) 188 } 189 }) 190 } 191 } 192 193 func TestWriteValue(t *testing.T) { 194 // versions < 4 195 for _, version := range SupportedProtocolVersionsLesserThan(ProtocolVersion4) { 196 t.Run(version.String(), func(t *testing.T) { 197 tests := []struct { 198 name string 199 input *Value 200 expected []byte 201 err error 202 }{ 203 { 204 "nil value", 205 nil, 206 nil, 207 errors.New("cannot write a nil [value]"), 208 }, 209 { 210 "empty value (type regular, nil contents)", 211 &Value{}, 212 []byte{0xff, 0xff, 0xff, 0xff}, // length -1 213 nil, 214 }, 215 { 216 "non empty value (type regular, non nil contents)", 217 &Value{ 218 Type: ValueTypeRegular, 219 Contents: []byte{1, 2, 3, 4}, 220 }, 221 []byte{0, 0, 0, 4, 1, 2, 3, 4}, 222 nil, 223 }, 224 { 225 "empty value with type null", 226 &Value{Type: ValueTypeNull}, 227 []byte{0xff, 0xff, 0xff, 0xff}, // length -1 228 nil, 229 }, 230 { 231 "empty value with type null but non nil contents", 232 &Value{ 233 Type: ValueTypeNull, 234 Contents: []byte{1, 2, 3, 4}, 235 }, 236 []byte{0xff, 0xff, 0xff, 0xff}, // length -1 237 nil, 238 }, 239 { 240 "empty value with type unset", 241 &Value{Type: ValueTypeUnset}, 242 nil, 243 fmt.Errorf("cannot use unset value with %v", version), 244 }, 245 { 246 "empty value with type unset but non nil contents", 247 &Value{ 248 Type: ValueTypeUnset, 249 Contents: []byte{1, 2, 3, 4}, 250 }, 251 nil, 252 fmt.Errorf("cannot use unset value with %v", version), 253 }, 254 { 255 "unknown type", 256 &Value{Type: 1}, 257 nil, 258 errors.New("unknown [value] type: 1"), 259 }, 260 } 261 for _, tt := range tests { 262 t.Run(tt.name, func(t *testing.T) { 263 buf := &bytes.Buffer{} 264 err := WriteValue(tt.input, buf, version) 265 assert.Equal(t, tt.expected, buf.Bytes()) 266 assert.Equal(t, tt.err, err) 267 }) 268 } 269 }) 270 } 271 // versions >= 4 272 for _, version := range SupportedProtocolVersionsGreaterThanOrEqualTo(ProtocolVersion4) { 273 t.Run(version.String(), func(t *testing.T) { 274 var tests = []struct { 275 name string 276 input *Value 277 expected []byte 278 err error 279 }{ 280 { 281 "nil value", 282 nil, 283 nil, 284 errors.New("cannot write a nil [value]"), 285 }, 286 { 287 "empty value (type regular, nil contents)", 288 &Value{}, 289 []byte{0xff, 0xff, 0xff, 0xff}, // length -1 290 nil, 291 }, 292 { 293 "non empty value (type regular, non nil contents)", 294 &Value{ 295 Type: ValueTypeRegular, 296 Contents: []byte{1, 2, 3, 4}, 297 }, 298 []byte{0, 0, 0, 4, 1, 2, 3, 4}, 299 nil, 300 }, 301 { 302 "empty value with type null", 303 &Value{Type: ValueTypeNull}, 304 []byte{0xff, 0xff, 0xff, 0xff}, // length -1 305 nil, 306 }, 307 { 308 "empty value with type null but non nil contents", 309 &Value{ 310 Type: ValueTypeNull, 311 Contents: []byte{1, 2, 3, 4}, 312 }, 313 []byte{0xff, 0xff, 0xff, 0xff}, // length -1 314 nil, 315 }, 316 { 317 "empty value with type unset", 318 &Value{Type: ValueTypeUnset}, 319 []byte{0xff, 0xff, 0xff, 0xfe}, // length -2 320 nil, 321 }, 322 { 323 "empty value with type unset but non nil contents", 324 &Value{ 325 Type: ValueTypeUnset, 326 Contents: []byte{1, 2, 3, 4}, 327 }, 328 []byte{0xff, 0xff, 0xff, 0xfe}, // length -2 329 nil, 330 }, 331 { 332 "unknown type", 333 &Value{Type: 1}, 334 nil, 335 errors.New("unknown [value] type: 1"), 336 }, 337 } 338 for _, tt := range tests { 339 t.Run(tt.name, func(t *testing.T) { 340 buf := &bytes.Buffer{} 341 err := WriteValue(tt.input, buf, version) 342 assert.Equal(t, tt.expected, buf.Bytes()) 343 assert.Equal(t, tt.err, err) 344 }) 345 } 346 }) 347 } 348 } 349 350 func TestLengthOfValue(t *testing.T) { 351 tests := []struct { 352 name string 353 input *Value 354 expected int 355 err error 356 }{ 357 { 358 "nil value", 359 nil, 360 -1, 361 errors.New("cannot compute length of a nil [value]"), 362 }, 363 { 364 "empty value (type regular, nil contents)", 365 &Value{}, 366 LengthOfInt, // length -1 367 nil, 368 }, 369 { 370 "non empty value (type regular, non nil contents)", 371 NewValue([]byte{1, 2, 3, 4}), 372 LengthOfInt + len([]byte{1, 2, 3, 4}), 373 nil, 374 }, 375 { 376 "empty value with type null", 377 NewNullValue(), 378 LengthOfInt, 379 nil, 380 }, 381 { 382 "empty value with type null but non nil contents", 383 &Value{ 384 Type: ValueTypeNull, 385 Contents: []byte{1, 2, 3, 4}, 386 }, 387 LengthOfInt, 388 nil, 389 }, 390 { 391 "empty value with type unset", 392 NewUnsetValue(), 393 LengthOfInt, 394 nil, 395 }, 396 { 397 "empty value with type unset but non nil contents", 398 &Value{ 399 Type: ValueTypeUnset, 400 Contents: []byte{1, 2, 3, 4}, 401 }, 402 LengthOfInt, 403 nil, 404 }, 405 { 406 "unknown type", 407 &Value{Type: 1}, 408 -1, 409 errors.New("unknown [value] type: 1"), 410 }, 411 } 412 for _, tt := range tests { 413 t.Run(tt.name, func(t *testing.T) { 414 actual, err := LengthOfValue(tt.input) 415 assert.Equal(t, tt.expected, actual) 416 assert.Equal(t, tt.err, err) 417 }) 418 } 419 } 420 421 func TestReadPositionalValues(t *testing.T) { 422 for _, version := range SupportedProtocolVersions() { 423 t.Run(version.String(), func(t *testing.T) { 424 tests := []struct { 425 name string 426 source []byte 427 expected []*Value 428 err error 429 }{ 430 { 431 "empty positional values", 432 []byte{0, 0}, 433 []*Value{}, 434 nil, 435 }, 436 { 437 "1 element, value empty", 438 []byte{ 439 0, 1, // length of list 440 0, 0, 0, 0, // length of element 441 }, 442 []*Value{{ 443 Type: ValueTypeRegular, 444 Contents: []byte{}, 445 }}, 446 nil, 447 }, 448 { 449 "1 element, value non empty", 450 []byte{ 451 0, 1, // length of list 452 0, 0, 0, 5, // length of element 453 1, 2, 3, 4, 5, // contents of element 454 }, 455 []*Value{{ 456 Type: ValueTypeRegular, 457 Contents: []byte{1, 2, 3, 4, 5}, 458 }}, 459 nil, 460 }, 461 { 462 "3 elements", 463 []byte{ 464 0, 3, // length of list 465 0xff, 0xff, 0xff, 0xff, // length of element 1 466 0, 0, 0, 0, // length of element 2 467 0, 0, 0, 5, // length of element 3 468 1, 2, 3, 4, 5, // contents of element 3 469 }, 470 []*Value{ 471 { 472 Type: ValueTypeNull, 473 Contents: nil, 474 }, 475 { 476 Type: ValueTypeRegular, 477 Contents: []byte{}, 478 }, 479 { 480 Type: ValueTypeRegular, 481 Contents: []byte{1, 2, 3, 4, 5}, 482 }, 483 }, 484 nil, 485 }, 486 { 487 "cannot read positional values length", 488 []byte{0}, 489 nil, 490 fmt.Errorf("cannot read positional [value]s length: %w", 491 fmt.Errorf("cannot read [short]: %w", 492 errors.New("unexpected EOF"))), 493 }, 494 { 495 "cannot read positional values element", 496 []byte{0, 1, 0, 0, 0, 1}, 497 nil, 498 fmt.Errorf("cannot read positional [value]s element 0 content: %w", 499 fmt.Errorf("cannot read [value] content: %w", 500 errors.New("EOF"))), 501 }, 502 } 503 for _, tt := range tests { 504 t.Run(tt.name, func(t *testing.T) { 505 buf := bytes.NewBuffer(tt.source) 506 actual, err := ReadPositionalValues(buf, version) 507 assert.Equal(t, tt.expected, actual) 508 assert.Equal(t, tt.err, err) 509 }) 510 } 511 }) 512 } 513 } 514 515 func TestWritePositionalValues(t *testing.T) { 516 // versions < 4 517 for _, version := range SupportedProtocolVersionsLesserThan(ProtocolVersion4) { 518 t.Run(version.String(), func(t *testing.T) { 519 tests := []struct { 520 name string 521 input []*Value 522 expected []byte 523 err error 524 }{ 525 { 526 "nil positional values", 527 nil, 528 []byte{0, 0}, 529 nil, 530 }, 531 { 532 "nil positional values", 533 []*Value{}, 534 []byte{0, 0}, 535 nil, 536 }, 537 { 538 "1 element, value empty", 539 []*Value{{ 540 Type: ValueTypeRegular, 541 Contents: []byte{}, 542 }}, 543 []byte{ 544 0, 1, // length of list 545 0, 0, 0, 0, // length of element 546 }, 547 nil, 548 }, 549 { 550 "1 element, value null", 551 []*Value{{ 552 Type: ValueTypeRegular, 553 Contents: nil, 554 }}, 555 []byte{ 556 0, 1, // length of list 557 0xff, 0xff, 0xff, 0xff, // length of element 558 }, 559 nil, 560 }, 561 { 562 "1 element, value null", 563 []*Value{{ 564 Type: ValueTypeNull, 565 Contents: nil, 566 }}, 567 []byte{ 568 0, 1, // length of list 569 0xff, 0xff, 0xff, 0xff, // length of element 570 }, 571 nil, 572 }, 573 { 574 "1 element, value non empty", 575 []*Value{{ 576 Type: ValueTypeRegular, 577 Contents: []byte{1, 2, 3, 4, 5}, 578 }}, 579 []byte{ 580 0, 1, // length of list 581 0, 0, 0, 5, // length of element 582 1, 2, 3, 4, 5, // contents of element 583 }, 584 nil, 585 }, 586 { 587 "3 elements", 588 []*Value{ 589 { 590 Type: ValueTypeNull, 591 Contents: nil, 592 }, 593 { 594 Type: ValueTypeRegular, 595 Contents: []byte{}, 596 }, 597 { 598 Type: ValueTypeRegular, 599 Contents: []byte{1, 2, 3, 4, 5}, 600 }, 601 }, 602 []byte{ 603 0, 3, // length of list 604 0xff, 0xff, 0xff, 0xff, // length of element 1 605 0, 0, 0, 0, // length of element 2 606 0, 0, 0, 5, // length of element 3 607 1, 2, 3, 4, 5, // contents of element 3 608 }, 609 nil, 610 }, 611 } 612 for _, tt := range tests { 613 t.Run(tt.name, func(t *testing.T) { 614 buf := &bytes.Buffer{} 615 err := WritePositionalValues(tt.input, buf, version) 616 assert.Equal(t, tt.expected, buf.Bytes()) 617 assert.Equal(t, tt.err, err) 618 }) 619 } 620 }) 621 } 622 // versions >= 4 623 for _, version := range SupportedProtocolVersionsGreaterThanOrEqualTo(ProtocolVersion4) { 624 t.Run(version.String(), func(t *testing.T) { 625 var tests = []struct { 626 name string 627 input []*Value 628 expected []byte 629 err error 630 }{ 631 { 632 "nil positional values", 633 nil, 634 []byte{0, 0}, 635 nil, 636 }, 637 { 638 "nil positional values", 639 []*Value{}, 640 []byte{0, 0}, 641 nil, 642 }, 643 { 644 "1 element, value empty", 645 []*Value{{ 646 Type: ValueTypeRegular, 647 Contents: []byte{}, 648 }}, 649 []byte{ 650 0, 1, // length of list 651 0, 0, 0, 0, // length of element 652 }, 653 nil, 654 }, 655 { 656 "1 element, value null", 657 []*Value{{ 658 Type: ValueTypeRegular, 659 Contents: nil, 660 }}, 661 []byte{ 662 0, 1, // length of list 663 0xff, 0xff, 0xff, 0xff, // length of element 664 }, 665 nil, 666 }, 667 { 668 "1 element, value null", 669 []*Value{{ 670 Type: ValueTypeNull, 671 Contents: nil, 672 }}, 673 []byte{ 674 0, 1, // length of list 675 0xff, 0xff, 0xff, 0xff, // length of element 676 }, 677 nil, 678 }, 679 { 680 "1 element, value non empty", 681 []*Value{{ 682 Type: ValueTypeRegular, 683 Contents: []byte{1, 2, 3, 4, 5}, 684 }}, 685 []byte{ 686 0, 1, // length of list 687 0, 0, 0, 5, // length of element 688 1, 2, 3, 4, 5, // contents of element 689 }, 690 nil, 691 }, 692 { 693 "4 elements", 694 []*Value{ 695 { 696 Type: ValueTypeNull, 697 Contents: nil, 698 }, 699 { 700 Type: ValueTypeUnset, 701 Contents: nil, 702 }, 703 { 704 Type: ValueTypeRegular, 705 Contents: []byte{}, 706 }, 707 { 708 Type: ValueTypeRegular, 709 Contents: []byte{1, 2, 3, 4, 5}, 710 }, 711 }, 712 []byte{ 713 0, 4, // length of list 714 0xff, 0xff, 0xff, 0xff, // length of element 1 715 0xff, 0xff, 0xff, 0xfe, // length of element 2 716 0, 0, 0, 0, // length of element 3 717 0, 0, 0, 5, // length of element 4 718 1, 2, 3, 4, 5, // contents of element 4 719 }, 720 nil, 721 }, 722 } 723 for _, tt := range tests { 724 t.Run(tt.name, func(t *testing.T) { 725 buf := &bytes.Buffer{} 726 err := WritePositionalValues(tt.input, buf, version) 727 assert.Equal(t, tt.expected, buf.Bytes()) 728 assert.Equal(t, tt.err, err) 729 }) 730 } 731 }) 732 } 733 } 734 735 func TestLengthOfPositionalValues(t *testing.T) { 736 tests := []struct { 737 name string 738 input []*Value 739 expected int 740 err error 741 }{ 742 { 743 "nil positional values", 744 nil, 745 LengthOfShort, 746 nil, 747 }, 748 { 749 "nil positional values", 750 []*Value{}, 751 LengthOfShort, 752 nil, 753 }, 754 { 755 "1 element, value empty", 756 []*Value{{ 757 Type: ValueTypeRegular, 758 Contents: []byte{}, 759 }}, 760 LengthOfShort + LengthOfInt, 761 nil, 762 }, 763 { 764 "1 element, value null", 765 []*Value{{ 766 Type: ValueTypeRegular, 767 Contents: nil, 768 }}, 769 LengthOfShort + LengthOfInt, 770 nil, 771 }, 772 { 773 "1 element, value null", 774 []*Value{{ 775 Type: ValueTypeNull, 776 Contents: nil, 777 }}, 778 LengthOfShort + LengthOfInt, 779 nil, 780 }, 781 { 782 "1 element, value non empty", 783 []*Value{{ 784 Type: ValueTypeRegular, 785 Contents: []byte{1, 2, 3, 4, 5}, 786 }}, 787 LengthOfShort + LengthOfInt + len([]byte{1, 2, 3, 4, 5}), 788 nil, 789 }, 790 { 791 "4 elements", 792 []*Value{ 793 { 794 Type: ValueTypeNull, 795 Contents: nil, 796 }, 797 { 798 Type: ValueTypeUnset, 799 Contents: nil, 800 }, 801 { 802 Type: ValueTypeRegular, 803 Contents: []byte{}, 804 }, 805 { 806 Type: ValueTypeRegular, 807 Contents: []byte{1, 2, 3, 4, 5}, 808 }, 809 }, 810 LengthOfShort + // length of list 811 LengthOfInt + // length of element 1 812 LengthOfInt + // length of element 2 813 LengthOfInt + // length of element 3 814 LengthOfInt + // length of element 4 815 len([]byte{1, 2, 3, 4, 5}), // contents of element 4 816 nil, 817 }, 818 } 819 for _, tt := range tests { 820 t.Run(tt.name, func(t *testing.T) { 821 actual, err := LengthOfPositionalValues(tt.input) 822 assert.Equal(t, tt.expected, actual) 823 assert.Equal(t, tt.err, err) 824 }) 825 } 826 } 827 828 func TestReadNamedValues(t *testing.T) { 829 for _, version := range SupportedProtocolVersions() { 830 t.Run(version.String(), func(t *testing.T) { 831 tests := []struct { 832 name string 833 source []byte 834 expected map[string]*Value 835 err error 836 }{ 837 { 838 "empty named values", 839 []byte{0, 0}, 840 map[string]*Value{}, 841 nil, 842 }, 843 { 844 "1 element, value empty", 845 []byte{ 846 0, 1, // length of list 847 0, 0, // length of element key 848 0, 0, 0, 0, // length of element 849 }, 850 map[string]*Value{ 851 "": { 852 Type: ValueTypeRegular, 853 Contents: []byte{}, 854 }}, 855 nil, 856 }, 857 { 858 "1 element, value non empty", 859 []byte{ 860 0, 1, // length of list 861 0, 5, // length of element key 862 h, e, l, l, o, // contents of element key 863 0, 0, 0, 5, // length of element value 864 1, 2, 3, 4, 5, // contents of element value 865 }, 866 map[string]*Value{ 867 "hello": { 868 Type: ValueTypeRegular, 869 Contents: []byte{1, 2, 3, 4, 5}, 870 }}, 871 nil, 872 }, 873 { 874 "3 elements", 875 []byte{ 876 0, 3, // length of list 877 0, 5, // length of element 1 key 878 h, e, l, l, o, // contents of element 1 key 879 0xff, 0xff, 0xff, 0xff, // length of element 1 value 880 0, 5, // length of element 2 key 881 w, o, r, l, d, // contents of element 2 key 882 0, 0, 0, 0, // length of element 2 value 883 0, 6, // length of element 3 key 884 h, o, l, 0xc3, 0xa0, 0x21, // contents of element 3 key: holà! 885 0, 0, 0, 5, // length of element 3 value 886 1, 2, 3, 4, 5, // contents of element 3 value 887 }, 888 map[string]*Value{ 889 "hello": { 890 Type: ValueTypeNull, 891 Contents: nil, 892 }, 893 "world": { 894 Type: ValueTypeRegular, 895 Contents: []byte{}, 896 }, 897 "holà!": { 898 Type: ValueTypeRegular, 899 Contents: []byte{1, 2, 3, 4, 5}, 900 }, 901 }, 902 nil, 903 }, 904 { 905 "cannot read named values length", 906 []byte{0}, 907 nil, 908 fmt.Errorf("cannot read named [value]s length: %w", 909 fmt.Errorf("cannot read [short]: %w", 910 errors.New("unexpected EOF"))), 911 }, 912 { 913 "cannot read named values element key", 914 []byte{0, 1, 0, 1}, 915 nil, 916 fmt.Errorf("cannot read named [value]s entry 0 name: %w", 917 fmt.Errorf("cannot read [string] content: %w", 918 errors.New("EOF"))), 919 }, 920 { 921 "cannot read named values element value", 922 []byte{0, 1, 0, 1, h, 0, 1}, 923 nil, 924 fmt.Errorf("cannot read named [value]s entry 0 content: %w", 925 fmt.Errorf("cannot read [value] length: %w", 926 fmt.Errorf("cannot read [int]: %w", 927 errors.New("unexpected EOF")))), 928 }, 929 } 930 for _, tt := range tests { 931 t.Run(tt.name, func(t *testing.T) { 932 buf := bytes.NewBuffer(tt.source) 933 actual, err := ReadNamedValues(buf, version) 934 assert.EqualValues(t, tt.expected, actual) 935 assert.Equal(t, tt.err, err) 936 }) 937 } 938 }) 939 } 940 } 941 942 func TestWriteNamedValues(t *testing.T) { 943 for _, version := range SupportedProtocolVersions() { 944 t.Run(version.String(), func(t *testing.T) { 945 tests := []struct { 946 name string 947 input map[string]*Value 948 expected []byte 949 err error 950 }{ 951 { 952 "nil named values", 953 nil, 954 []byte{0, 0}, 955 nil, 956 }, 957 { 958 "nil named values", 959 map[string]*Value{}, 960 []byte{0, 0}, 961 nil, 962 }, 963 { 964 "1 element, value empty", 965 map[string]*Value{ 966 "": { 967 Type: ValueTypeRegular, 968 Contents: []byte{}, 969 }}, 970 []byte{ 971 0, 1, // length of list 972 0, 0, // length of element key 973 0, 0, 0, 0, // length of element 974 }, 975 nil, 976 }, 977 { 978 "1 element, value non empty", 979 map[string]*Value{ 980 "hello": { 981 Type: ValueTypeRegular, 982 Contents: []byte{1, 2, 3, 4, 5}, 983 }}, 984 []byte{ 985 0, 1, // length of list 986 0, 5, // length of element key 987 h, e, l, l, o, // contents of element key 988 0, 0, 0, 5, // length of element value 989 1, 2, 3, 4, 5, // contents of element value 990 }, 991 nil, 992 }, 993 // cannot reliably test maps with more than one key because iteration order is not deterministic 994 } 995 for _, tt := range tests { 996 t.Run(tt.name, func(t *testing.T) { 997 buf := &bytes.Buffer{} 998 err := WriteNamedValues(tt.input, buf, version) 999 assert.Equal(t, tt.expected, buf.Bytes()) 1000 assert.Equal(t, tt.err, err) 1001 }) 1002 } 1003 }) 1004 } 1005 } 1006 1007 func TestLengthOfNamedValues(t *testing.T) { 1008 tests := []struct { 1009 name string 1010 input map[string]*Value 1011 expected int 1012 err error 1013 }{ 1014 { 1015 "nil named values", 1016 nil, 1017 LengthOfShort, 1018 nil, 1019 }, 1020 { 1021 "nil named values", 1022 map[string]*Value{}, 1023 LengthOfShort, 1024 nil, 1025 }, 1026 { 1027 "1 element, value empty", 1028 map[string]*Value{ 1029 "": { 1030 Type: ValueTypeRegular, 1031 Contents: []byte{}, 1032 }}, 1033 LengthOfShort + // length of list 1034 LengthOfShort + // length of element key 1035 LengthOfInt, // length of element 1036 nil, 1037 }, 1038 { 1039 "1 element, value non empty", 1040 map[string]*Value{ 1041 "hello": { 1042 Type: ValueTypeRegular, 1043 Contents: []byte{1, 2, 3, 4, 5}, 1044 }}, 1045 LengthOfShort + // length of list 1046 LengthOfShort + // length of element key 1047 len("hello") + // contents of element key 1048 LengthOfInt + // length of element value 1049 5, // contents of element value 1050 nil, 1051 }, 1052 { 1053 "3 elements", 1054 map[string]*Value{ 1055 "hello": { 1056 Type: ValueTypeNull, 1057 Contents: nil, 1058 }, 1059 "world": { 1060 Type: ValueTypeRegular, 1061 Contents: []byte{}, 1062 }, 1063 "holà!": { 1064 Type: ValueTypeRegular, 1065 Contents: []byte{1, 2, 3, 4, 5}, 1066 }, 1067 }, 1068 LengthOfShort + // length of list 1069 LengthOfShort + // length of element 1 key 1070 len("hello") + // contents of element 1 key 1071 LengthOfInt + // length of element 1 value 1072 LengthOfShort + // length of element 2 key 1073 len("world") + // contents of element 2 key 1074 LengthOfInt + // length of element 2 value 1075 LengthOfShort + // length of element 3 key 1076 len("holà!") + // contents of element 3 key: holà! 1077 LengthOfInt + // length of element 3 value 1078 5, // contents of element 3 value 1079 nil, 1080 }, 1081 } 1082 for _, tt := range tests { 1083 t.Run(tt.name, func(t *testing.T) { 1084 actual, err := LengthOfNamedValues(tt.input) 1085 assert.Equal(t, tt.expected, actual) 1086 assert.Equal(t, tt.err, err) 1087 }) 1088 } 1089 }