1// Copyright 2019 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package json_test 6 7import ( 8 "fmt" 9 "math" 10 "strings" 11 "testing" 12 "unicode/utf8" 13 14 "github.com/google/go-cmp/cmp" 15 16 "google.golang.org/protobuf/internal/encoding/json" 17) 18 19type R struct { 20 // E is expected error substring from calling Decoder.Read if set. 21 E string 22 // V is one of the checker implementations that validates the token value. 23 V checker 24 // P is expected Token.Pos() if set > 0. 25 P int 26 // RS is expected result from Token.RawString() if not empty. 27 RS string 28} 29 30// checker defines API for Token validation. 31type checker interface { 32 // check checks and expects for token API call to return and compare 33 // against implementation-stored value. Returns empty string if success, 34 // else returns error message describing the error. 35 check(json.Token) string 36} 37 38// checkers that checks the token kind only. 39var ( 40 EOF = kindOnly{json.EOF} 41 Null = kindOnly{json.Null} 42 ObjectOpen = kindOnly{json.ObjectOpen} 43 ObjectClose = kindOnly{json.ObjectClose} 44 ArrayOpen = kindOnly{json.ArrayOpen} 45 ArrayClose = kindOnly{json.ArrayClose} 46) 47 48type kindOnly struct { 49 want json.Kind 50} 51 52func (x kindOnly) check(tok json.Token) string { 53 if got := tok.Kind(); got != x.want { 54 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, x.want) 55 } 56 return "" 57} 58 59type Name struct { 60 val string 61} 62 63func (x Name) check(tok json.Token) string { 64 if got := tok.Kind(); got != json.Name { 65 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Name) 66 } 67 68 if got := tok.Name(); got != x.val { 69 return fmt.Sprintf("Token.Name(): got %v, want %v", got, x.val) 70 } 71 return "" 72} 73 74type Bool struct { 75 val bool 76} 77 78func (x Bool) check(tok json.Token) string { 79 if got := tok.Kind(); got != json.Bool { 80 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Bool) 81 } 82 83 if got := tok.Bool(); got != x.val { 84 return fmt.Sprintf("Token.Bool(): got %v, want %v", got, x.val) 85 } 86 return "" 87} 88 89type Str struct { 90 val string 91} 92 93func (x Str) check(tok json.Token) string { 94 if got := tok.Kind(); got != json.String { 95 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.String) 96 } 97 98 if got := tok.ParsedString(); got != x.val { 99 return fmt.Sprintf("Token.ParsedString(): got %v, want %v", got, x.val) 100 } 101 return "" 102} 103 104type F64 struct { 105 val float64 106} 107 108func (x F64) check(tok json.Token) string { 109 if got := tok.Kind(); got != json.Number { 110 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 111 } 112 113 got, ok := tok.Float(64) 114 if !ok { 115 return fmt.Sprintf("Token.Float(64): returned not ok") 116 } 117 if got != x.val { 118 return fmt.Sprintf("Token.Float(64): got %v, want %v", got, x.val) 119 } 120 return "" 121} 122 123type F32 struct { 124 val float32 125} 126 127func (x F32) check(tok json.Token) string { 128 if got := tok.Kind(); got != json.Number { 129 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 130 } 131 132 got, ok := tok.Float(32) 133 if !ok { 134 return fmt.Sprintf("Token.Float(32): returned not ok") 135 } 136 if float32(got) != x.val { 137 return fmt.Sprintf("Token.Float(32): got %v, want %v", got, x.val) 138 } 139 return "" 140} 141 142// NotF64 is a checker to validate a Number token where Token.Float(64) returns not ok. 143var NotF64 = xf64{} 144 145type xf64 struct{} 146 147func (x xf64) check(tok json.Token) string { 148 if got := tok.Kind(); got != json.Number { 149 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 150 } 151 152 _, ok := tok.Float(64) 153 if ok { 154 return fmt.Sprintf("Token.Float(64): returned ok") 155 } 156 return "" 157} 158 159// NotF32 is a checker to validate a Number token where Token.Float(32) returns not ok. 160var NotF32 = xf32{} 161 162type xf32 struct{} 163 164func (x xf32) check(tok json.Token) string { 165 if got := tok.Kind(); got != json.Number { 166 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 167 } 168 169 _, ok := tok.Float(32) 170 if ok { 171 return fmt.Sprintf("Token.Float(32): returned ok") 172 } 173 return "" 174} 175 176type I64 struct { 177 val int64 178} 179 180func (x I64) check(tok json.Token) string { 181 if got := tok.Kind(); got != json.Number { 182 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 183 } 184 185 got, ok := tok.Int(64) 186 if !ok { 187 return fmt.Sprintf("Token.Int(64): returned not ok") 188 } 189 if got != x.val { 190 return fmt.Sprintf("Token.Int(64): got %v, want %v", got, x.val) 191 } 192 return "" 193} 194 195type I32 struct { 196 val int32 197} 198 199func (x I32) check(tok json.Token) string { 200 if got := tok.Kind(); got != json.Number { 201 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 202 } 203 204 got, ok := tok.Int(32) 205 if !ok { 206 return fmt.Sprintf("Token.Int(32): returned not ok") 207 } 208 if int32(got) != x.val { 209 return fmt.Sprintf("Token.Int(32): got %v, want %v", got, x.val) 210 } 211 return "" 212} 213 214// NotI64 is a checker to validate a Number token where Token.Int(64) returns not ok. 215var NotI64 = xi64{} 216 217type xi64 struct{} 218 219func (x xi64) check(tok json.Token) string { 220 if got := tok.Kind(); got != json.Number { 221 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 222 } 223 224 _, ok := tok.Int(64) 225 if ok { 226 return fmt.Sprintf("Token.Int(64): returned ok") 227 } 228 return "" 229} 230 231// NotI32 is a checker to validate a Number token where Token.Int(32) returns not ok. 232var NotI32 = xi32{} 233 234type xi32 struct{} 235 236func (x xi32) check(tok json.Token) string { 237 if got := tok.Kind(); got != json.Number { 238 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 239 } 240 241 _, ok := tok.Int(32) 242 if ok { 243 return fmt.Sprintf("Token.Int(32): returned ok") 244 } 245 return "" 246} 247 248type Ui64 struct { 249 val uint64 250} 251 252func (x Ui64) check(tok json.Token) string { 253 if got := tok.Kind(); got != json.Number { 254 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 255 } 256 257 got, ok := tok.Uint(64) 258 if !ok { 259 return fmt.Sprintf("Token.Uint(64): returned not ok") 260 } 261 if got != x.val { 262 return fmt.Sprintf("Token.Uint(64): got %v, want %v", got, x.val) 263 } 264 return "" 265} 266 267type Ui32 struct { 268 val uint32 269} 270 271func (x Ui32) check(tok json.Token) string { 272 if got := tok.Kind(); got != json.Number { 273 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 274 } 275 276 got, ok := tok.Uint(32) 277 if !ok { 278 return fmt.Sprintf("Token.Uint(32): returned not ok") 279 } 280 if uint32(got) != x.val { 281 return fmt.Sprintf("Token.Uint(32): got %v, want %v", got, x.val) 282 } 283 return "" 284} 285 286// NotUi64 is a checker to validate a Number token where Token.Uint(64) returns not ok. 287var NotUi64 = xui64{} 288 289type xui64 struct{} 290 291func (x xui64) check(tok json.Token) string { 292 if got := tok.Kind(); got != json.Number { 293 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 294 } 295 296 _, ok := tok.Uint(64) 297 if ok { 298 return fmt.Sprintf("Token.Uint(64): returned ok") 299 } 300 return "" 301} 302 303// NotI32 is a checker to validate a Number token where Token.Uint(32) returns not ok. 304var NotUi32 = xui32{} 305 306type xui32 struct{} 307 308func (x xui32) check(tok json.Token) string { 309 if got := tok.Kind(); got != json.Number { 310 return fmt.Sprintf("Token.Kind(): got %v, want %v", got, json.Number) 311 } 312 313 _, ok := tok.Uint(32) 314 if ok { 315 return fmt.Sprintf("Token.Uint(32): returned ok") 316 } 317 return "" 318} 319 320var errEOF = json.ErrUnexpectedEOF.Error() 321 322func TestDecoder(t *testing.T) { 323 const space = " \n\r\t" 324 325 tests := []struct { 326 in string 327 // want is a list of expected values returned from calling 328 // Decoder.Read. An item makes the test code invoke 329 // Decoder.Read and compare against R.E for error returned or use R.V to 330 // validate the returned Token object. 331 want []R 332 }{ 333 { 334 in: ``, 335 want: []R{{V: EOF}}, 336 }, 337 { 338 in: space, 339 want: []R{{V: EOF}}, 340 }, 341 { 342 // Calling Read after EOF will keep returning EOF for 343 // succeeding Read calls. 344 in: space, 345 want: []R{ 346 {V: EOF}, 347 {V: EOF}, 348 {V: EOF}, 349 }, 350 }, 351 352 // JSON literals. 353 { 354 in: space + `null` + space, 355 want: []R{ 356 {V: Null, P: len(space), RS: `null`}, 357 {V: EOF}, 358 }, 359 }, 360 { 361 in: space + `true` + space, 362 want: []R{ 363 {V: Bool{true}}, 364 {V: EOF}, 365 }, 366 }, 367 { 368 in: space + `false` + space, 369 want: []R{ 370 {V: Bool{false}}, 371 {V: EOF}, 372 }, 373 }, 374 { 375 // Error returned will produce the same error again. 376 in: space + `foo` + space, 377 want: []R{ 378 {E: `invalid value foo`}, 379 {E: `invalid value foo`}, 380 }, 381 }, 382 383 // JSON strings. 384 { 385 in: space + `""` + space, 386 want: []R{ 387 {V: Str{}}, 388 {V: EOF}, 389 }, 390 }, 391 { 392 in: space + `"hello"` + space, 393 want: []R{ 394 {V: Str{"hello"}, RS: `"hello"`}, 395 {V: EOF}, 396 }, 397 }, 398 { 399 in: `"hello`, 400 want: []R{{E: errEOF}}, 401 }, 402 { 403 in: "\"\x00\"", 404 want: []R{{E: `invalid character '\x00' in string`}}, 405 }, 406 { 407 in: "\"\u0031\u0032\"", 408 want: []R{ 409 {V: Str{"12"}, RS: "\"\u0031\u0032\""}, 410 {V: EOF}, 411 }, 412 }, 413 { 414 // Invalid UTF-8 error is returned in ReadString instead of Read. 415 in: "\"\xff\"", 416 want: []R{{E: `syntax error (line 1:1): invalid UTF-8 in string`}}, 417 }, 418 { 419 in: `"` + string(utf8.RuneError) + `"`, 420 want: []R{ 421 {V: Str{string(utf8.RuneError)}}, 422 {V: EOF}, 423 }, 424 }, 425 { 426 in: `"\uFFFD"`, 427 want: []R{ 428 {V: Str{string(utf8.RuneError)}}, 429 {V: EOF}, 430 }, 431 }, 432 { 433 in: `"\x"`, 434 want: []R{{E: `invalid escape code "\\x" in string`}}, 435 }, 436 { 437 in: `"\uXXXX"`, 438 want: []R{{E: `invalid escape code "\\uXXXX" in string`}}, 439 }, 440 { 441 in: `"\uDEAD"`, // unmatched surrogate pair 442 want: []R{{E: errEOF}}, 443 }, 444 { 445 in: `"\uDEAD\uBEEF"`, // invalid surrogate half 446 want: []R{{E: `invalid escape code "\\uBEEF" in string`}}, 447 }, 448 { 449 in: `"\uD800\udead"`, // valid surrogate pair 450 want: []R{ 451 {V: Str{``}}, 452 {V: EOF}, 453 }, 454 }, 455 { 456 in: `"\u0000\"\\\/\b\f\n\r\t"`, 457 want: []R{ 458 {V: Str{"\u0000\"\\/\b\f\n\r\t"}}, 459 {V: EOF}, 460 }, 461 }, 462 463 // Invalid JSON numbers. 464 { 465 in: `-`, 466 want: []R{{E: `invalid value -`}}, 467 }, 468 { 469 in: `+0`, 470 want: []R{{E: `invalid value +0`}}, 471 }, 472 { 473 in: `-+`, 474 want: []R{{E: `invalid value -+`}}, 475 }, 476 { 477 in: `0.`, 478 want: []R{{E: `invalid value 0.`}}, 479 }, 480 { 481 in: `.1`, 482 want: []R{{E: `invalid value .1`}}, 483 }, 484 { 485 in: `1.0.1`, 486 want: []R{{E: `invalid value 1.0.1`}}, 487 }, 488 { 489 in: `1..1`, 490 want: []R{{E: `invalid value 1..1`}}, 491 }, 492 { 493 in: `-1-2`, 494 want: []R{{E: `invalid value -1-2`}}, 495 }, 496 { 497 in: `01`, 498 want: []R{{E: `invalid value 01`}}, 499 }, 500 { 501 in: `1e`, 502 want: []R{{E: `invalid value 1e`}}, 503 }, 504 { 505 in: `1e1.2`, 506 want: []R{{E: `invalid value 1e1.2`}}, 507 }, 508 { 509 in: `1Ee`, 510 want: []R{{E: `invalid value 1Ee`}}, 511 }, 512 { 513 in: `1.e1`, 514 want: []R{{E: `invalid value 1.e1`}}, 515 }, 516 { 517 in: `1.e+`, 518 want: []R{{E: `invalid value 1.e+`}}, 519 }, 520 { 521 in: `1e+-2`, 522 want: []R{{E: `invalid value 1e+-2`}}, 523 }, 524 { 525 in: `1e--2`, 526 want: []R{{E: `invalid value 1e--2`}}, 527 }, 528 { 529 in: `1.0true`, 530 want: []R{{E: `invalid value 1.0true`}}, 531 }, 532 533 // JSON numbers as floating point. 534 { 535 in: space + `0.0` + space, 536 want: []R{ 537 {V: F32{0}, P: len(space), RS: `0.0`}, 538 {V: EOF}, 539 }, 540 }, 541 { 542 in: space + `0` + space, 543 want: []R{ 544 {V: F32{0}}, 545 {V: EOF}, 546 }, 547 }, 548 { 549 in: space + `-0` + space, 550 want: []R{ 551 {V: F32{float32(math.Copysign(0, -1))}}, 552 {V: EOF}, 553 }, 554 }, 555 { 556 in: `-0`, 557 want: []R{ 558 {V: F64{math.Copysign(0, -1)}}, 559 {V: EOF}, 560 }, 561 }, 562 { 563 in: `-0.0`, 564 want: []R{ 565 {V: F32{float32(math.Copysign(0, -1))}}, 566 {V: EOF}, 567 }, 568 }, 569 { 570 in: `-0.0`, 571 want: []R{ 572 {V: F64{math.Copysign(0, -1)}}, 573 {V: EOF}, 574 }, 575 }, 576 { 577 in: `-1.02`, 578 want: []R{ 579 {V: F32{-1.02}}, 580 {V: EOF}, 581 }, 582 }, 583 { 584 in: `1.020000`, 585 want: []R{ 586 {V: F32{1.02}}, 587 {V: EOF}, 588 }, 589 }, 590 { 591 in: `-1.0e0`, 592 want: []R{ 593 {V: F32{-1}}, 594 {V: EOF}, 595 }, 596 }, 597 { 598 in: `1.0e-000`, 599 want: []R{ 600 {V: F32{1}}, 601 {V: EOF}, 602 }, 603 }, 604 { 605 in: `1e+00`, 606 want: []R{ 607 {V: F32{1}}, 608 {V: EOF}, 609 }, 610 }, 611 { 612 in: `1.02e3`, 613 want: []R{ 614 {V: F32{1.02e3}}, 615 {V: EOF}, 616 }, 617 }, 618 { 619 in: `-1.02E03`, 620 want: []R{ 621 {V: F32{-1.02e3}}, 622 {V: EOF}, 623 }, 624 }, 625 { 626 in: `1.0200e+3`, 627 want: []R{ 628 {V: F32{1.02e3}}, 629 {V: EOF}, 630 }, 631 }, 632 { 633 in: `-1.0200E+03`, 634 want: []R{ 635 {V: F32{-1.02e3}}, 636 {V: EOF}, 637 }, 638 }, 639 { 640 in: `1.0200e-3`, 641 want: []R{ 642 {V: F32{1.02e-3}}, 643 {V: EOF}, 644 }, 645 }, 646 { 647 in: `-1.0200E-03`, 648 want: []R{ 649 {V: F32{-1.02e-3}}, 650 {V: EOF}, 651 }, 652 }, 653 { 654 // Exceeds max float32 limit, but should be ok for float64. 655 in: `3.4e39`, 656 want: []R{ 657 {V: F64{3.4e39}}, 658 {V: EOF}, 659 }, 660 }, 661 662 { 663 // Exceeds max float32 limit. 664 in: `3.4e39`, 665 want: []R{ 666 {V: NotF32}, 667 {V: EOF}, 668 }, 669 }, 670 { 671 // Less than negative max float32 limit. 672 in: `-3.4e39`, 673 want: []R{ 674 {V: NotF32}, 675 {V: EOF}, 676 }, 677 }, 678 { 679 // Exceeds max float64 limit. 680 in: `1.79e+309`, 681 want: []R{ 682 {V: NotF64}, 683 {V: EOF}, 684 }, 685 }, 686 { 687 // Less than negative max float64 limit. 688 in: `-1.79e+309`, 689 want: []R{ 690 {V: NotF64}, 691 {V: EOF}, 692 }, 693 }, 694 695 // JSON numbers as signed integers. 696 { 697 in: space + `0` + space, 698 want: []R{ 699 {V: I32{0}}, 700 {V: EOF}, 701 }, 702 }, 703 { 704 in: space + `-0` + space, 705 want: []R{ 706 {V: I32{0}}, 707 {V: EOF}, 708 }, 709 }, 710 { 711 // Fractional part equals 0 is ok. 712 in: `1.00000`, 713 want: []R{ 714 {V: I32{1}}, 715 {V: EOF}, 716 }, 717 }, 718 { 719 // Fractional part not equals 0 returns error. 720 in: `1.0000000001`, 721 want: []R{ 722 {V: NotI32}, 723 {V: EOF}, 724 }, 725 }, 726 { 727 in: `0e0`, 728 want: []R{ 729 {V: I32{0}}, 730 {V: EOF}, 731 }, 732 }, 733 { 734 in: `0.0E0`, 735 want: []R{ 736 {V: I32{0}}, 737 {V: EOF}, 738 }, 739 }, 740 { 741 in: `0.0E10`, 742 want: []R{ 743 {V: I32{0}}, 744 {V: EOF}, 745 }, 746 }, 747 { 748 in: `-1`, 749 want: []R{ 750 {V: I32{-1}}, 751 {V: EOF}, 752 }, 753 }, 754 { 755 in: `1.0e+0`, 756 want: []R{ 757 {V: I32{1}}, 758 {V: EOF}, 759 }, 760 }, 761 { 762 in: `-1E-0`, 763 want: []R{ 764 {V: I32{-1}}, 765 {V: EOF}, 766 }, 767 }, 768 { 769 in: `1E1`, 770 want: []R{ 771 {V: I32{10}}, 772 {V: EOF}, 773 }, 774 }, 775 { 776 in: `-100.00e-02`, 777 want: []R{ 778 {V: I32{-1}}, 779 {V: EOF}, 780 }, 781 }, 782 { 783 in: `0.1200E+02`, 784 want: []R{ 785 {V: I64{12}}, 786 {V: EOF}, 787 }, 788 }, 789 { 790 in: `0.012e2`, 791 want: []R{ 792 {V: NotI32}, 793 {V: EOF}, 794 }, 795 }, 796 { 797 in: `12e-2`, 798 want: []R{ 799 {V: NotI32}, 800 {V: EOF}, 801 }, 802 }, 803 { 804 // Exceeds math.MaxInt32. 805 in: `2147483648`, 806 want: []R{ 807 {V: NotI32}, 808 {V: EOF}, 809 }, 810 }, 811 { 812 // Exceeds math.MinInt32. 813 in: `-2147483649`, 814 want: []R{ 815 {V: NotI32}, 816 {V: EOF}, 817 }, 818 }, 819 { 820 // Exceeds math.MaxInt32, but ok for int64. 821 in: `2147483648`, 822 want: []R{ 823 {V: I64{2147483648}}, 824 {V: EOF}, 825 }, 826 }, 827 { 828 // Exceeds math.MinInt32, but ok for int64. 829 in: `-2147483649`, 830 want: []R{ 831 {V: I64{-2147483649}}, 832 {V: EOF}, 833 }, 834 }, 835 { 836 // Exceeds math.MaxInt64. 837 in: `9223372036854775808`, 838 want: []R{ 839 {V: NotI64}, 840 {V: EOF}, 841 }, 842 }, 843 { 844 // Exceeds math.MinInt64. 845 in: `-9223372036854775809`, 846 want: []R{ 847 {V: NotI64}, 848 {V: EOF}, 849 }, 850 }, 851 852 // JSON numbers as unsigned integers. 853 { 854 in: space + `0` + space, 855 want: []R{ 856 {V: Ui32{0}}, 857 {V: EOF}, 858 }, 859 }, 860 { 861 in: space + `-0` + space, 862 want: []R{ 863 {V: Ui32{0}}, 864 {V: EOF}, 865 }, 866 }, 867 { 868 in: `-1`, 869 want: []R{ 870 {V: NotUi32}, 871 {V: EOF}, 872 }, 873 }, 874 { 875 // Exceeds math.MaxUint32. 876 in: `4294967296`, 877 want: []R{ 878 {V: NotUi32}, 879 {V: EOF}, 880 }, 881 }, 882 { 883 // Exceeds math.MaxUint64. 884 in: `18446744073709551616`, 885 want: []R{ 886 {V: NotUi64}, 887 {V: EOF}, 888 }, 889 }, 890 891 // JSON sequence of values. 892 { 893 in: `true null`, 894 want: []R{ 895 {V: Bool{true}}, 896 {E: `(line 1:6): unexpected token null`}, 897 }, 898 }, 899 { 900 in: "null false", 901 want: []R{ 902 {V: Null}, 903 {E: `unexpected token false`}, 904 }, 905 }, 906 { 907 in: `true,false`, 908 want: []R{ 909 {V: Bool{true}}, 910 {E: `unexpected token ,`}, 911 }, 912 }, 913 { 914 in: `47"hello"`, 915 want: []R{ 916 {V: I32{47}}, 917 {E: `unexpected token "hello"`}, 918 }, 919 }, 920 { 921 in: `47 "hello"`, 922 want: []R{ 923 {V: I32{47}}, 924 {E: `unexpected token "hello"`}, 925 }, 926 }, 927 { 928 in: `true 42`, 929 want: []R{ 930 {V: Bool{true}}, 931 {E: `unexpected token 42`}, 932 }, 933 }, 934 935 // JSON arrays. 936 { 937 in: space + `[]` + space, 938 want: []R{ 939 {V: ArrayOpen}, 940 {V: ArrayClose}, 941 {V: EOF}, 942 }, 943 }, 944 { 945 in: space + `[` + space + `]` + space, 946 want: []R{ 947 {V: ArrayOpen, P: len(space), RS: `[`}, 948 {V: ArrayClose}, 949 {V: EOF}, 950 }, 951 }, 952 { 953 in: space + `[` + space, 954 want: []R{ 955 {V: ArrayOpen}, 956 {E: errEOF}, 957 }, 958 }, 959 { 960 in: space + `]` + space, 961 want: []R{{E: `unexpected token ]`}}, 962 }, 963 { 964 in: `[null,true,false, 1e1, "hello" ]`, 965 want: []R{ 966 {V: ArrayOpen}, 967 {V: Null}, 968 {V: Bool{true}}, 969 {V: Bool{false}}, 970 {V: I32{10}}, 971 {V: Str{"hello"}}, 972 {V: ArrayClose}, 973 {V: EOF}, 974 }, 975 }, 976 { 977 in: `[` + space + `true` + space + `,` + space + `"hello"` + space + `]`, 978 want: []R{ 979 {V: ArrayOpen}, 980 {V: Bool{true}}, 981 {V: Str{"hello"}}, 982 {V: ArrayClose}, 983 {V: EOF}, 984 }, 985 }, 986 { 987 in: `[` + space + `true` + space + `,` + space + `]`, 988 want: []R{ 989 {V: ArrayOpen}, 990 {V: Bool{true}}, 991 {E: `unexpected token ]`}, 992 }, 993 }, 994 { 995 in: `[` + space + `false` + space + `]`, 996 want: []R{ 997 {V: ArrayOpen}, 998 {V: Bool{false}}, 999 {V: ArrayClose}, 1000 {V: EOF}, 1001 }, 1002 }, 1003 { 1004 in: `[` + space + `1` + space + `0` + space + `]`, 1005 want: []R{ 1006 {V: ArrayOpen}, 1007 {V: I64{1}}, 1008 {E: `unexpected token 0`}, 1009 }, 1010 }, 1011 { 1012 in: `[null`, 1013 want: []R{ 1014 {V: ArrayOpen}, 1015 {V: Null}, 1016 {E: errEOF}, 1017 }, 1018 }, 1019 { 1020 in: `[foo]`, 1021 want: []R{ 1022 {V: ArrayOpen}, 1023 {E: `invalid value foo`}, 1024 }, 1025 }, 1026 { 1027 in: `[{}, "hello", [true, false], null]`, 1028 want: []R{ 1029 {V: ArrayOpen}, 1030 {V: ObjectOpen}, 1031 {V: ObjectClose}, 1032 {V: Str{"hello"}}, 1033 {V: ArrayOpen}, 1034 {V: Bool{true}}, 1035 {V: Bool{false}}, 1036 {V: ArrayClose}, 1037 {V: Null}, 1038 {V: ArrayClose}, 1039 {V: EOF}, 1040 }, 1041 }, 1042 { 1043 in: `[{ ]`, 1044 want: []R{ 1045 {V: ArrayOpen}, 1046 {V: ObjectOpen}, 1047 {E: `unexpected token ]`}, 1048 }, 1049 }, 1050 { 1051 in: `[[ ]`, 1052 want: []R{ 1053 {V: ArrayOpen}, 1054 {V: ArrayOpen}, 1055 {V: ArrayClose}, 1056 {E: errEOF}, 1057 }, 1058 }, 1059 { 1060 in: `[,]`, 1061 want: []R{ 1062 {V: ArrayOpen}, 1063 {E: `unexpected token ,`}, 1064 }, 1065 }, 1066 { 1067 in: `[true "hello"]`, 1068 want: []R{ 1069 {V: ArrayOpen}, 1070 {V: Bool{true}}, 1071 {E: `unexpected token "hello"`}, 1072 }, 1073 }, 1074 { 1075 in: `[] null`, 1076 want: []R{ 1077 {V: ArrayOpen}, 1078 {V: ArrayClose}, 1079 {E: `unexpected token null`}, 1080 }, 1081 }, 1082 { 1083 in: `true []`, 1084 want: []R{ 1085 {V: Bool{true}}, 1086 {E: `unexpected token [`}, 1087 }, 1088 }, 1089 1090 // JSON objects. 1091 { 1092 in: space + `{}` + space, 1093 want: []R{ 1094 {V: ObjectOpen}, 1095 {V: ObjectClose}, 1096 {V: EOF}, 1097 }, 1098 }, 1099 { 1100 in: space + `{` + space + `}` + space, 1101 want: []R{ 1102 {V: ObjectOpen}, 1103 {V: ObjectClose}, 1104 {V: EOF}, 1105 }, 1106 }, 1107 { 1108 in: space + `{` + space, 1109 want: []R{ 1110 {V: ObjectOpen}, 1111 {E: errEOF}, 1112 }, 1113 }, 1114 { 1115 in: space + `}` + space, 1116 want: []R{{E: `unexpected token }`}}, 1117 }, 1118 { 1119 in: `{` + space + `null` + space + `}`, 1120 want: []R{ 1121 {V: ObjectOpen}, 1122 {E: `unexpected token null`}, 1123 }, 1124 }, 1125 { 1126 in: `{[]}`, 1127 want: []R{ 1128 {V: ObjectOpen}, 1129 {E: `(line 1:2): unexpected token [`}, 1130 }, 1131 }, 1132 { 1133 in: `{,}`, 1134 want: []R{ 1135 {V: ObjectOpen}, 1136 {E: `unexpected token ,`}, 1137 }, 1138 }, 1139 { 1140 in: `{"345678"}`, 1141 want: []R{ 1142 {V: ObjectOpen}, 1143 {E: `(line 1:10): unexpected character }, missing ":" after field name`}, 1144 }, 1145 }, 1146 { 1147 in: `{` + space + `"hello"` + space + `:` + space + `"world"` + space + `}`, 1148 want: []R{ 1149 {V: ObjectOpen}, 1150 {V: Name{"hello"}, P: len(space) + 1, RS: `"hello"`}, 1151 {V: Str{"world"}, RS: `"world"`}, 1152 {V: ObjectClose}, 1153 {V: EOF}, 1154 }, 1155 }, 1156 { 1157 in: `{"hello" "world"}`, 1158 want: []R{ 1159 {V: ObjectOpen}, 1160 {E: `(line 1:10): unexpected character ", missing ":" after field name`}, 1161 }, 1162 }, 1163 { 1164 in: `{"hello":`, 1165 want: []R{ 1166 {V: ObjectOpen}, 1167 {V: Name{"hello"}}, 1168 {E: errEOF}, 1169 }, 1170 }, 1171 { 1172 in: `{"hello":"world"`, 1173 want: []R{ 1174 {V: ObjectOpen}, 1175 {V: Name{"hello"}}, 1176 {V: Str{"world"}}, 1177 {E: errEOF}, 1178 }, 1179 }, 1180 { 1181 in: `{"hello":"world",`, 1182 want: []R{ 1183 {V: ObjectOpen}, 1184 {V: Name{"hello"}}, 1185 {V: Str{"world"}}, 1186 {E: errEOF}, 1187 }, 1188 }, 1189 { 1190 in: `{""`, 1191 want: []R{ 1192 {V: ObjectOpen}, 1193 {E: errEOF}, 1194 }, 1195 }, 1196 { 1197 in: `{"34":"89",}`, 1198 want: []R{ 1199 {V: ObjectOpen}, 1200 {V: Name{"34"}, RS: `"34"`}, 1201 {V: Str{"89"}}, 1202 {E: `syntax error (line 1:12): unexpected token }`}, 1203 }, 1204 }, 1205 { 1206 in: `{ 1207 "number": 123e2, 1208 "bool" : false, 1209 "object": {"string": "world"}, 1210 "null" : null, 1211 "array" : [1.01, "hello", true], 1212 "string": "hello" 1213 }`, 1214 want: []R{ 1215 {V: ObjectOpen}, 1216 1217 {V: Name{"number"}}, 1218 {V: I32{12300}}, 1219 1220 {V: Name{"bool"}}, 1221 {V: Bool{false}}, 1222 1223 {V: Name{"object"}}, 1224 {V: ObjectOpen}, 1225 {V: Name{"string"}}, 1226 {V: Str{"world"}}, 1227 {V: ObjectClose}, 1228 1229 {V: Name{"null"}}, 1230 {V: Null}, 1231 1232 {V: Name{"array"}}, 1233 {V: ArrayOpen}, 1234 {V: F32{1.01}}, 1235 {V: Str{"hello"}}, 1236 {V: Bool{true}}, 1237 {V: ArrayClose}, 1238 1239 {V: Name{"string"}}, 1240 {V: Str{"hello"}}, 1241 1242 {V: ObjectClose}, 1243 {V: EOF}, 1244 }, 1245 }, 1246 { 1247 in: `[ 1248 {"object": {"number": 47}}, 1249 ["list"], 1250 null 1251 ]`, 1252 want: []R{ 1253 {V: ArrayOpen}, 1254 1255 {V: ObjectOpen}, 1256 {V: Name{"object"}}, 1257 {V: ObjectOpen}, 1258 {V: Name{"number"}}, 1259 {V: I32{47}}, 1260 {V: ObjectClose}, 1261 {V: ObjectClose}, 1262 1263 {V: ArrayOpen}, 1264 {V: Str{"list"}}, 1265 {V: ArrayClose}, 1266 1267 {V: Null}, 1268 1269 {V: ArrayClose}, 1270 {V: EOF}, 1271 }, 1272 }, 1273 1274 // Tests for line and column info. 1275 { 1276 in: `12345678 x`, 1277 want: []R{ 1278 {V: I64{12345678}}, 1279 {E: `syntax error (line 1:10): invalid value x`}, 1280 }, 1281 }, 1282 { 1283 in: "\ntrue\n x", 1284 want: []R{ 1285 {V: Bool{true}}, 1286 {E: `syntax error (line 3:4): invalid value x`}, 1287 }, 1288 }, 1289 { 1290 in: `""x`, 1291 want: []R{ 1292 {V: Str{""}}, 1293 {E: `syntax error (line 1:4): invalid value x`}, 1294 }, 1295 }, 1296 { 1297 in: "\n\n[\"\"x", 1298 want: []R{ 1299 {V: ArrayOpen}, 1300 {V: Str{""}}, 1301 {E: `syntax error (line 3:7): invalid value x`}, 1302 }, 1303 }, 1304 { 1305 // Multi-rune emojis. 1306 in: `[""x`, 1307 want: []R{ 1308 {V: ArrayOpen}, 1309 {V: Str{""}}, 1310 {E: `syntax error (line 1:8): invalid value x`}, 1311 }, 1312 }, 1313 } 1314 1315 for _, tc := range tests { 1316 tc := tc 1317 t.Run("", func(t *testing.T) { 1318 dec := json.NewDecoder([]byte(tc.in)) 1319 for i, want := range tc.want { 1320 peekTok, peekErr := dec.Peek() 1321 tok, err := dec.Read() 1322 if err != nil { 1323 if want.E == "" { 1324 errorf(t, tc.in, "want#%d: Read() got unexpected error: %v", i, err) 1325 } else if !strings.Contains(err.Error(), want.E) { 1326 errorf(t, tc.in, "want#%d: Read() got %q, want %q", i, err, want.E) 1327 } 1328 return 1329 } 1330 if want.E != "" { 1331 errorf(t, tc.in, "want#%d: Read() got nil error, want %q", i, want.E) 1332 return 1333 } 1334 checkToken(t, tok, i, want, tc.in) 1335 if !cmp.Equal(tok, peekTok, cmp.Comparer(json.TokenEquals)) { 1336 errorf(t, tc.in, "want#%d: Peek() %+v != Read() token %+v", i, peekTok, tok) 1337 } 1338 if err != peekErr { 1339 errorf(t, tc.in, "want#%d: Peek() error %v != Read() error %v", i, err, peekErr) 1340 } 1341 } 1342 }) 1343 } 1344} 1345 1346func checkToken(t *testing.T, tok json.Token, idx int, r R, in string) { 1347 // Validate Token.Pos() if R.P is set. 1348 if r.P > 0 { 1349 got := tok.Pos() 1350 if got != r.P { 1351 errorf(t, in, "want#%d: Token.Pos() got %v want %v", idx, got, r.P) 1352 } 1353 } 1354 // Validate Token.RawString if R.RS is set. 1355 if len(r.RS) > 0 { 1356 got := tok.RawString() 1357 if got != r.RS { 1358 errorf(t, in, "want#%d: Token.RawString() got %v want %v", idx, got, r.P) 1359 } 1360 } 1361 1362 // Skip checking for Token details if r.V is not set. 1363 if r.V == nil { 1364 return 1365 } 1366 1367 if err := r.V.check(tok); err != "" { 1368 errorf(t, in, "want#%d: %s", idx, err) 1369 } 1370 return 1371} 1372 1373func errorf(t *testing.T, in string, fmtStr string, args ...interface{}) { 1374 t.Helper() 1375 vargs := []interface{}{in} 1376 for _, arg := range args { 1377 vargs = append(vargs, arg) 1378 } 1379 t.Errorf("input:\n%s\n~end~\n"+fmtStr, vargs...) 1380} 1381 1382func TestClone(t *testing.T) { 1383 input := `{"outer":{"str":"hello", "number": 123}}` 1384 dec := json.NewDecoder([]byte(input)) 1385 1386 // Clone at the start should produce the same reads as the original. 1387 clone := dec.Clone() 1388 compareDecoders(t, dec, clone) 1389 1390 // Advance to inner object, clone and compare again. 1391 dec.Read() // Read ObjectOpen. 1392 dec.Read() // Read Name. 1393 clone = dec.Clone() 1394 compareDecoders(t, dec, clone) 1395} 1396 1397func compareDecoders(t *testing.T, d1 *json.Decoder, d2 *json.Decoder) { 1398 for { 1399 tok1, err1 := d1.Read() 1400 tok2, err2 := d2.Read() 1401 if tok1.Kind() != tok2.Kind() { 1402 t.Errorf("cloned decoder: got Kind %v, want %v", tok2.Kind(), tok1.Kind()) 1403 } 1404 if tok1.RawString() != tok2.RawString() { 1405 t.Errorf("cloned decoder: got RawString %v, want %v", tok2.RawString(), tok1.RawString()) 1406 } 1407 if err1 != err2 { 1408 t.Errorf("cloned decoder: got error %v, want %v", err2, err1) 1409 } 1410 if tok1.Kind() == json.EOF { 1411 break 1412 } 1413 } 1414} 1415