github.com/hamba/avro/v2@v2.22.1-0.20240518180522-aff3955acf7d/reader_test.go (about) 1 package avro_test 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 "strconv" 8 "testing" 9 10 "github.com/hamba/avro/v2" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestNewReader(t *testing.T) { 16 r := avro.NewReader(bytes.NewBuffer([]byte{}), 10) 17 18 assert.IsType(t, &avro.Reader{}, r) 19 } 20 21 func TestReader_Reset(t *testing.T) { 22 r := &avro.Reader{} 23 24 r.Reset([]byte{0x01}) 25 26 assert.True(t, r.ReadBool()) 27 } 28 29 func TestReader_ReportError(t *testing.T) { 30 r := &avro.Reader{} 31 32 r.ReportError("test", "bar") 33 34 assert.EqualError(t, r.Error, "avro: test: bar") 35 } 36 37 func TestReader_ReportErrorExistingError(t *testing.T) { 38 err := errors.New("test") 39 40 r := &avro.Reader{} 41 r.Error = err 42 43 r.ReportError("test", "bar") 44 45 assert.Equal(t, err, r.Error) 46 } 47 48 func TestReader_Peek(t *testing.T) { 49 r := (&avro.Reader{}).Reset([]byte{0x36}) 50 51 b := r.Peek() 52 53 i := r.ReadInt() 54 55 require.NoError(t, r.Error) 56 assert.Equal(t, byte(0x36), b) 57 assert.Equal(t, int32(27), i) 58 } 59 60 func TestReader_PeekNoData(t *testing.T) { 61 r := (&avro.Reader{}).Reset([]byte{0x36}) 62 63 _ = r.ReadInt() 64 65 _ = r.Peek() 66 67 assert.ErrorIs(t, r.Error, io.EOF) 68 } 69 70 func TestReader_ReadPastBuffer(t *testing.T) { 71 r := (&avro.Reader{}).Reset([]byte{0xE2}) 72 73 r.ReadInt() 74 75 assert.Error(t, r.Error) 76 } 77 78 func TestReader_ReadDelayedReader(t *testing.T) { 79 rdr := &delayedReader{b: []byte{0x36}} 80 r := avro.NewReader(rdr, 10) 81 82 i := r.ReadInt() 83 84 require.NoError(t, r.Error) 85 assert.Equal(t, int32(27), i) 86 } 87 88 func TestReader_Read(t *testing.T) { 89 tests := []struct { 90 name string 91 data []byte 92 want []byte 93 wantErr require.ErrorAssertionFunc 94 }{ 95 { 96 name: "valid", 97 data: []byte{0xAC, 0xDC, 0x01, 0x00, 0x10, 0x0F}, 98 want: []byte{0xAC, 0xDC, 0x01, 0x00, 0x10, 0x0F}, 99 wantErr: require.NoError, 100 }, 101 { 102 name: "eof", 103 data: []byte{0xAC}, // io.ErrUnexpectedEOF 104 want: []byte{0xAC, 0x00, 0x00, 0x00, 0x00, 0x00}, 105 wantErr: require.Error, 106 }, 107 } 108 109 for _, test := range tests { 110 test := test 111 t.Run(test.name, func(t *testing.T) { 112 r := avro.NewReader(bytes.NewReader(test.data), 2) 113 114 got := make([]byte, 6) 115 r.Read(got) 116 117 test.wantErr(t, r.Error) 118 assert.Equal(t, test.want, got) 119 }) 120 } 121 } 122 123 func TestReader_ReadBool(t *testing.T) { 124 tests := []struct { 125 name string 126 data []byte 127 want bool 128 wantErr require.ErrorAssertionFunc 129 }{ 130 { 131 name: "false", 132 data: []byte{0x00}, 133 want: false, 134 wantErr: require.NoError, 135 }, 136 { 137 name: "true", 138 data: []byte{0x01}, 139 want: true, 140 wantErr: require.NoError, 141 }, 142 { 143 name: "invalid bool", 144 data: []byte{0x02}, 145 want: false, 146 wantErr: require.Error, 147 }, 148 { 149 name: "eof", 150 data: []byte(nil), // io.ErrUnexpectedEOF 151 want: false, 152 wantErr: require.Error, 153 }, 154 } 155 156 for _, test := range tests { 157 test := test 158 t.Run(test.name, func(t *testing.T) { 159 160 r := avro.NewReader(bytes.NewReader(test.data), 10) 161 162 got := r.ReadBool() 163 164 test.wantErr(t, r.Error) 165 assert.Equal(t, test.want, got) 166 }) 167 } 168 } 169 170 func TestReader_ReadInt(t *testing.T) { 171 tests := []struct { 172 name string 173 data []byte 174 want int32 175 wantErr require.ErrorAssertionFunc 176 }{ 177 { 178 name: "positive int", 179 data: []byte{0x36}, 180 want: 27, 181 wantErr: require.NoError, 182 }, 183 { 184 name: "negative int", 185 data: []byte{0x0f}, 186 want: -8, 187 wantErr: require.NoError, 188 }, 189 { 190 name: "negative int", 191 data: []byte{0x01}, 192 want: -1, 193 wantErr: require.NoError, 194 }, 195 { 196 name: "zero", 197 data: []byte{0x00}, 198 want: 0, 199 wantErr: require.NoError, 200 }, 201 { 202 name: "one", 203 data: []byte{0x02}, 204 want: 1, 205 wantErr: require.NoError, 206 }, 207 { 208 name: "negative 64", 209 data: []byte{0x7f}, 210 want: -64, 211 wantErr: require.NoError, 212 }, 213 { 214 name: "multi byte int", 215 data: []byte{0x80, 0x01}, 216 want: 64, 217 wantErr: require.NoError, 218 }, 219 { 220 name: "large int", 221 data: []byte{0xaa, 0xb4, 0xde, 0x75}, 222 want: 123456789, 223 wantErr: require.NoError, 224 }, 225 { 226 name: "larger int", 227 data: []byte{0xe2, 0xa2, 0xf3, 0xad, 0x07}, 228 want: 987654321, 229 wantErr: require.NoError, 230 }, 231 { 232 name: "overflow", 233 data: []byte{0xe2, 0xa2, 0xf3, 0xad, 0xad, 0xad}, 234 want: 0, 235 wantErr: require.Error, 236 }, 237 { 238 name: "eof", 239 data: []byte{0xe2}, 240 want: 0, 241 wantErr: require.Error, 242 }, 243 } 244 245 for _, test := range tests { 246 t.Run(test.name, func(t *testing.T) { 247 r := avro.NewReader(bytes.NewReader(test.data), 10) 248 249 got := r.ReadInt() 250 251 test.wantErr(t, r.Error) 252 assert.Equal(t, test.want, got) 253 }) 254 } 255 } 256 257 func TestReader_ReadIntShortReadAcrossBuffer(t *testing.T) { 258 data := []byte{0xe2, 0xa2, 0xf3, 0xad} 259 r := avro.NewReader(bytes.NewReader(data), 3) 260 261 _ = r.ReadInt() 262 263 assert.NotPanics(t, func() { 264 b := make([]byte, 3) 265 r.Read(b) 266 }) 267 } 268 269 func TestReader_ReadLong(t *testing.T) { 270 tests := []struct { 271 name string 272 data []byte 273 want int64 274 wantErr require.ErrorAssertionFunc 275 }{ 276 { 277 name: "long", 278 data: []byte{0x36}, 279 want: 27, 280 wantErr: require.NoError, 281 }, 282 { 283 name: "negative long", 284 data: []byte{0x0f}, 285 want: -8, 286 wantErr: require.NoError, 287 }, 288 { 289 name: "negative long", 290 data: []byte{0x01}, 291 want: -1, 292 wantErr: require.NoError, 293 }, 294 { 295 name: "zero", 296 data: []byte{0x00}, 297 want: 0, 298 wantErr: require.NoError, 299 }, 300 { 301 name: "one", 302 data: []byte{0x02}, 303 want: 1, 304 wantErr: require.NoError, 305 }, 306 { 307 name: "negative 64", 308 data: []byte{0x7f}, 309 want: -64, 310 wantErr: require.NoError, 311 }, 312 { 313 name: "multi-byte", 314 data: []byte{0x80, 0x01}, 315 want: 64, 316 wantErr: require.NoError, 317 }, 318 { 319 name: "large long", 320 data: []byte{0xaa, 0xb4, 0xde, 0x75}, 321 want: 123456789, 322 wantErr: require.NoError, 323 }, 324 { 325 name: "larger long", 326 data: []byte{0xe2, 0xa2, 0xf3, 0xad, 0x07}, 327 want: 987654321, 328 wantErr: require.NoError, 329 }, 330 { 331 name: "very very big long", 332 data: []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, 333 want: 9223372036854775807, 334 wantErr: require.NoError, 335 }, 336 { 337 name: "very very big negative long", 338 data: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, 339 want: -9223372036854775808, 340 wantErr: require.NoError, 341 }, 342 { 343 name: "very very big negative long", 344 data: []byte{0xbd, 0xb1, 0xae, 0xd4, 0xd2, 0xcd, 0xbd, 0xe4, 0x97, 0x01}, 345 want: -5468631321897454687, 346 wantErr: require.NoError, 347 }, 348 { 349 name: "overflow", 350 data: []byte{0xe2, 0xa2, 0xf3, 0xad, 0xad, 0xad, 0xe2, 0xa2, 0xf3, 0xad, 0xad}, 351 want: 0, 352 wantErr: require.Error, 353 }, 354 { 355 name: "eof", 356 data: []byte{0xe2}, 357 want: 0, 358 wantErr: require.Error, 359 }, 360 } 361 362 for _, test := range tests { 363 t.Run(test.name, func(t *testing.T) { 364 r := avro.NewReader(bytes.NewReader(test.data), 10) 365 366 got := r.ReadLong() 367 368 test.wantErr(t, r.Error) 369 assert.Equal(t, test.want, got) 370 }) 371 } 372 } 373 374 func TestReader_ReadLongShortReadAcrossBuffer(t *testing.T) { 375 data := []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 376 r := avro.NewReader(bytes.NewReader(data), 8) 377 378 _ = r.ReadLong() 379 380 assert.NotPanics(t, func() { 381 b := make([]byte, 3) 382 r.Read(b) 383 }) 384 } 385 386 func TestReader_ReadFloat(t *testing.T) { 387 tests := []struct { 388 data []byte 389 want float32 390 wantErr require.ErrorAssertionFunc 391 }{ 392 { 393 data: []byte{0x00, 0x00, 0x00, 0x00}, 394 want: 0.0, 395 wantErr: require.NoError, 396 }, 397 { 398 data: []byte{0x00, 0x00, 0x80, 0x3F}, 399 want: 1.0, 400 wantErr: require.NoError, 401 }, 402 { 403 data: []byte{0x33, 0x33, 0x93, 0x3F}, 404 want: 1.15, 405 wantErr: require.NoError, 406 }, 407 { 408 data: []byte{0x23, 0xDB, 0x57, 0xC2}, 409 want: -53.964, 410 wantErr: require.NoError, 411 }, 412 { 413 data: []byte{0xA3, 0x79, 0xEB, 0xCC}, 414 want: -123456789.123, 415 wantErr: require.NoError, 416 }, 417 { 418 data: []byte{0x62, 0x20, 0x71, 0x49}, 419 want: 987654.111115, 420 wantErr: require.NoError, 421 }, 422 { 423 data: []byte(nil), // io.EOF 424 want: 0, 425 wantErr: require.Error, 426 }, 427 } 428 429 for _, test := range tests { 430 test := test 431 r := avro.NewReader(bytes.NewReader(test.data), 2) 432 433 got := r.ReadFloat() 434 435 test.wantErr(t, r.Error) 436 assert.Equal(t, test.want, got) 437 } 438 } 439 440 func TestReader_ReadDouble(t *testing.T) { 441 tests := []struct { 442 data []byte 443 want float64 444 wantErr require.ErrorAssertionFunc 445 }{ 446 { 447 data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 448 want: 0.0, 449 wantErr: require.NoError, 450 }, 451 { 452 data: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F}, 453 want: 1.0, 454 wantErr: require.NoError, 455 }, 456 { 457 data: []byte{0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xF2, 0x3F}, 458 want: 1.15, 459 wantErr: require.NoError, 460 }, 461 { 462 data: []byte{0x08, 0xAC, 0x1C, 0x5A, 0x64, 0xFB, 0x4A, 0xC0}, 463 want: -53.964, 464 wantErr: require.NoError, 465 }, 466 { 467 data: []byte{0xB6, 0xF3, 0x7D, 0x54, 0x34, 0x6F, 0x9D, 0xC1}, 468 want: -123456789.123, 469 wantErr: require.NoError, 470 }, 471 { 472 data: []byte{0xB6, 0x10, 0xE4, 0x38, 0x0C, 0x24, 0x2E, 0x41}, 473 want: 987654.111115, 474 wantErr: require.NoError, 475 }, 476 { 477 data: []byte{0x75, 0x6B, 0x7E, 0x54, 0x34, 0x6F, 0x9D, 0x41}, 478 want: 123456789.123456789, 479 wantErr: require.NoError, 480 }, 481 { 482 data: []byte{0x00, 0x00, 0x00, 0x00, 0xD0, 0x12, 0x63, 0x41}, 483 want: 9999999.99999999999999999999999, 484 wantErr: require.NoError, 485 }, 486 { 487 data: []byte{0x18, 0xFC, 0x1A, 0xDD, 0x1F, 0x0E, 0x0A, 0x43}, 488 want: 916734926348163.01973408746523, 489 wantErr: require.NoError, 490 }, 491 { 492 data: []byte{0x0A, 0x8F, 0xA6, 0x40, 0xAC, 0xAD, 0x8D, 0xC3}, 493 want: -267319348967891263.1928357138913857, 494 wantErr: require.NoError, 495 }, 496 { 497 data: []byte(nil), // io.EOF 498 want: 0, 499 wantErr: require.Error, 500 }, 501 } 502 503 for _, test := range tests { 504 r := avro.NewReader(bytes.NewReader(test.data), 4) 505 506 got := r.ReadDouble() 507 508 test.wantErr(t, r.Error) 509 assert.Equal(t, test.want, got) 510 } 511 } 512 513 func TestReader_ReadBytes(t *testing.T) { 514 tests := []struct { 515 data []byte 516 want []byte 517 wantErr require.ErrorAssertionFunc 518 }{ 519 { 520 data: []byte{0x02, 0x02}, 521 want: []byte{0x02}, 522 wantErr: require.NoError, 523 }, 524 { 525 data: []byte{0x04, 0x03, 0xFF}, 526 want: []byte{0x03, 0xFF}, 527 wantErr: require.NoError, 528 }, 529 { 530 data: []byte{0x08, 0xEC, 0xAB, 0x44, 0x00}, 531 want: []byte{0xEC, 0xAB, 0x44, 0x00}, 532 wantErr: require.NoError, 533 }, 534 { 535 data: []byte{0x0C, 0xAC, 0xDC, 0x01, 0x00, 0x10, 0x0F}, 536 want: []byte{0xAC, 0xDC, 0x01, 0x00, 0x10, 0x0F}, 537 wantErr: require.NoError, 538 }, 539 { 540 data: []byte(nil), // io.EOF no length 541 want: []byte{}, 542 wantErr: require.Error, 543 }, 544 { 545 data: []byte{0x05, 0x03, 0xFF, 0x0A}, // Invalid bytes length 546 want: nil, 547 wantErr: require.Error, 548 }, 549 { 550 data: []byte{0x08, 0xFF}, // io.EOF length greater then data 551 want: []byte{0xFF, 0x0, 0x0, 0x0}, 552 wantErr: require.Error, 553 }, 554 } 555 556 for i, test := range tests { 557 test := test 558 t.Run(strconv.Itoa(i), func(t *testing.T) { 559 r := avro.NewReader(bytes.NewReader(test.data), 10) 560 561 got := r.ReadBytes() 562 563 test.wantErr(t, r.Error) 564 assert.Equal(t, test.want, got) 565 }) 566 } 567 } 568 569 func TestReader_ReadBytesLargerThanMaxByteSliceSize(t *testing.T) { 570 data := []byte{ 571 246, 255, 255, 255, 255, 10, 255, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 572 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 573 32, 32, 32, 32, 32, 32, 32, 574 } 575 r := avro.NewReader(bytes.NewReader(data), 4) 576 577 _ = r.ReadBytes() 578 579 assert.Error(t, r.Error) 580 } 581 582 func TestReader_ReadString(t *testing.T) { 583 tests := []struct { 584 data []byte 585 want string 586 wantErr require.ErrorAssertionFunc 587 }{ 588 { 589 data: []byte{0x00}, 590 want: "", 591 wantErr: require.NoError, 592 }, 593 { 594 data: []byte{0x06, 0x66, 0x6F, 0x6F}, 595 want: "foo", 596 wantErr: require.NoError, 597 }, 598 { 599 data: []byte{0x08, 0x61, 0x76, 0x72, 0x6F}, 600 want: "avro", 601 wantErr: require.NoError, 602 }, 603 { 604 data: []byte{0x0C, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65}, 605 want: "apache", 606 wantErr: require.NoError, 607 }, 608 { 609 data: []byte{0x28, 0x6F, 0x70, 0x70, 0x61, 0x6E, 0x20, 0x67, 0x61, 0x6E, 0x67, 0x6E, 0x61, 0x6D, 0x20, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x21}, 610 want: "oppan gangnam style!", 611 wantErr: require.NoError, 612 }, 613 { 614 data: []byte{0x36, 0xD1, 0x87, 0xD0, 0xB5, 0x2D, 0xD1, 0x82, 0xD0, 0xBE, 0x20, 0xD0, 0xBF, 0xD0, 0xBE, 0x20, 0xD1, 0x80, 0xD1, 0x83, 0xD1, 0x81, 0xD1, 0x81, 0xD0, 0xBA, 0xD0, 0xB8}, 615 want: "че-то по русски", 616 wantErr: require.NoError, 617 }, 618 { 619 data: []byte{0x0C, 0xE4, 0xB8, 0x96, 0xE7, 0x95, 0x8C}, 620 want: "世界", 621 wantErr: require.NoError, 622 }, 623 { 624 data: []byte{0x22, 0x21, 0xE2, 0x84, 0x96, 0x3B, 0x25, 0x3A, 0x3F, 0x2A, 0x22, 0x28, 0x29, 0x40, 0x23, 0x24, 0x5E, 0x26}, 625 want: "!№;%:?*\"()@#$^&", 626 wantErr: require.NoError, 627 }, 628 { 629 data: []byte(nil), // io.EOF no length 630 want: "", 631 wantErr: require.Error, 632 }, 633 { 634 data: []byte{0x05, 0x66, 0x6F, 0x6F, 0x6F}, // Invalid string length 635 want: "", 636 wantErr: require.Error, 637 }, 638 { 639 data: []byte{0x08, 0x66}, // io.EOF length greater then data 640 want: "\x66\x00\x00\x00", 641 wantErr: require.Error, 642 }, 643 } 644 645 for i, test := range tests { 646 test := test 647 t.Run(strconv.Itoa(i), func(t *testing.T) { 648 r := avro.NewReader(bytes.NewReader(test.data), 10) 649 650 got := r.ReadString() 651 652 test.wantErr(t, r.Error) 653 assert.Equal(t, test.want, got) 654 }) 655 } 656 } 657 658 func TestReader_ReadStringLargerThanMaxByteSliceSize(t *testing.T) { 659 data := []byte{ 660 246, 255, 255, 255, 255, 10, 255, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 661 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 662 32, 32, 32, 32, 32, 32, 32, 663 } 664 r := avro.NewReader(bytes.NewReader(data), 4) 665 666 _ = r.ReadString() 667 668 assert.Error(t, r.Error) 669 } 670 671 func TestReader_ReadStringFastPathIsntBoundToBuffer(t *testing.T) { 672 data := []byte{0x06, 0x66, 0x6F, 0x6F, 0x08, 0x61, 0x76, 0x72, 0x6F} 673 r := avro.NewReader(bytes.NewReader(data), 4) 674 675 got1 := r.ReadString() 676 got2 := r.ReadString() 677 678 require.NoError(t, r.Error) 679 assert.Equal(t, "foo", got1) 680 assert.Equal(t, "avro", got2) 681 } 682 683 func TestReader_ReadBlockHeader(t *testing.T) { 684 tests := []struct { 685 data []byte 686 len int64 687 size int64 688 }{ 689 { 690 data: []byte{0x80, 0x01}, 691 len: 64, 692 size: 0, 693 }, 694 { 695 data: []byte{0x7F, 0x80, 0x01}, 696 len: 64, 697 size: 64, 698 }, 699 } 700 701 for _, test := range tests { 702 r := avro.NewReader(bytes.NewReader(test.data), 10) 703 704 gotLen, gotSize := r.ReadBlockHeader() 705 706 require.NoError(t, r.Error) 707 assert.Equal(t, test.len, gotLen) 708 assert.Equal(t, test.size, gotSize) 709 } 710 } 711 712 type delayedReader struct { 713 count int 714 b []byte 715 } 716 717 func (r *delayedReader) Read(p []byte) (n int, err error) { 718 if r.count == 0 { 719 r.count++ 720 return 0, nil 721 } 722 723 return copy(p, r.b), nil 724 }