github.com/hashicorp/hcl/v2@v2.20.0/json/scanner_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package json 5 6 import ( 7 "bytes" 8 "fmt" 9 "reflect" 10 "testing" 11 12 "github.com/hashicorp/hcl/v2" 13 ) 14 15 func TestScan(t *testing.T) { 16 tests := []struct { 17 Input string 18 Want []token 19 }{ 20 { 21 ``, 22 []token{ 23 { 24 Type: tokenEOF, 25 Range: hcl.Range{ 26 Start: hcl.Pos{ 27 Byte: 0, 28 Line: 1, 29 Column: 1, 30 }, 31 End: hcl.Pos{ 32 Byte: 0, 33 Line: 1, 34 Column: 1, 35 }, 36 }, 37 }, 38 }, 39 }, 40 { 41 ` `, 42 []token{ 43 { 44 Type: tokenEOF, 45 Range: hcl.Range{ 46 Start: hcl.Pos{ 47 Byte: 3, 48 Line: 1, 49 Column: 4, 50 }, 51 End: hcl.Pos{ 52 Byte: 3, 53 Line: 1, 54 Column: 4, 55 }, 56 }, 57 }, 58 }, 59 }, 60 { 61 `{}`, 62 []token{ 63 { 64 Type: tokenBraceO, 65 Bytes: []byte(`{`), 66 Range: hcl.Range{ 67 Start: hcl.Pos{ 68 Byte: 0, 69 Line: 1, 70 Column: 1, 71 }, 72 End: hcl.Pos{ 73 Byte: 1, 74 Line: 1, 75 Column: 2, 76 }, 77 }, 78 }, 79 { 80 Type: tokenBraceC, 81 Bytes: []byte(`}`), 82 Range: hcl.Range{ 83 Start: hcl.Pos{ 84 Byte: 1, 85 Line: 1, 86 Column: 2, 87 }, 88 End: hcl.Pos{ 89 Byte: 2, 90 Line: 1, 91 Column: 3, 92 }, 93 }, 94 }, 95 { 96 Type: tokenEOF, 97 Range: hcl.Range{ 98 Start: hcl.Pos{ 99 Byte: 2, 100 Line: 1, 101 Column: 3, 102 }, 103 End: hcl.Pos{ 104 Byte: 2, 105 Line: 1, 106 Column: 3, 107 }, 108 }, 109 }, 110 }, 111 }, 112 { 113 `][`, 114 []token{ 115 { 116 Type: tokenBrackC, 117 Bytes: []byte(`]`), 118 Range: hcl.Range{ 119 Start: hcl.Pos{ 120 Byte: 0, 121 Line: 1, 122 Column: 1, 123 }, 124 End: hcl.Pos{ 125 Byte: 1, 126 Line: 1, 127 Column: 2, 128 }, 129 }, 130 }, 131 { 132 Type: tokenBrackO, 133 Bytes: []byte(`[`), 134 Range: hcl.Range{ 135 Start: hcl.Pos{ 136 Byte: 1, 137 Line: 1, 138 Column: 2, 139 }, 140 End: hcl.Pos{ 141 Byte: 2, 142 Line: 1, 143 Column: 3, 144 }, 145 }, 146 }, 147 { 148 Type: tokenEOF, 149 Range: hcl.Range{ 150 Start: hcl.Pos{ 151 Byte: 2, 152 Line: 1, 153 Column: 3, 154 }, 155 End: hcl.Pos{ 156 Byte: 2, 157 Line: 1, 158 Column: 3, 159 }, 160 }, 161 }, 162 }, 163 }, 164 { 165 `:,`, 166 []token{ 167 { 168 Type: tokenColon, 169 Bytes: []byte(`:`), 170 Range: hcl.Range{ 171 Start: hcl.Pos{ 172 Byte: 0, 173 Line: 1, 174 Column: 1, 175 }, 176 End: hcl.Pos{ 177 Byte: 1, 178 Line: 1, 179 Column: 2, 180 }, 181 }, 182 }, 183 { 184 Type: tokenComma, 185 Bytes: []byte(`,`), 186 Range: hcl.Range{ 187 Start: hcl.Pos{ 188 Byte: 1, 189 Line: 1, 190 Column: 2, 191 }, 192 End: hcl.Pos{ 193 Byte: 2, 194 Line: 1, 195 Column: 3, 196 }, 197 }, 198 }, 199 { 200 Type: tokenEOF, 201 Range: hcl.Range{ 202 Start: hcl.Pos{ 203 Byte: 2, 204 Line: 1, 205 Column: 3, 206 }, 207 End: hcl.Pos{ 208 Byte: 2, 209 Line: 1, 210 Column: 3, 211 }, 212 }, 213 }, 214 }, 215 }, 216 { 217 `1`, 218 []token{ 219 { 220 Type: tokenNumber, 221 Bytes: []byte(`1`), 222 Range: hcl.Range{ 223 Start: hcl.Pos{ 224 Byte: 0, 225 Line: 1, 226 Column: 1, 227 }, 228 End: hcl.Pos{ 229 Byte: 1, 230 Line: 1, 231 Column: 2, 232 }, 233 }, 234 }, 235 { 236 Type: tokenEOF, 237 Range: hcl.Range{ 238 Start: hcl.Pos{ 239 Byte: 1, 240 Line: 1, 241 Column: 2, 242 }, 243 End: hcl.Pos{ 244 Byte: 1, 245 Line: 1, 246 Column: 2, 247 }, 248 }, 249 }, 250 }, 251 }, 252 { 253 ` 1`, 254 []token{ 255 { 256 Type: tokenNumber, 257 Bytes: []byte(`1`), 258 Range: hcl.Range{ 259 Start: hcl.Pos{ 260 Byte: 2, 261 Line: 1, 262 Column: 3, 263 }, 264 End: hcl.Pos{ 265 Byte: 3, 266 Line: 1, 267 Column: 4, 268 }, 269 }, 270 }, 271 { 272 Type: tokenEOF, 273 Range: hcl.Range{ 274 Start: hcl.Pos{ 275 Byte: 3, 276 Line: 1, 277 Column: 4, 278 }, 279 End: hcl.Pos{ 280 Byte: 3, 281 Line: 1, 282 Column: 4, 283 }, 284 }, 285 }, 286 }, 287 }, 288 { 289 ` 12`, 290 []token{ 291 { 292 Type: tokenNumber, 293 Bytes: []byte(`12`), 294 Range: hcl.Range{ 295 Start: hcl.Pos{ 296 Byte: 2, 297 Line: 1, 298 Column: 3, 299 }, 300 End: hcl.Pos{ 301 Byte: 4, 302 Line: 1, 303 Column: 5, 304 }, 305 }, 306 }, 307 { 308 Type: tokenEOF, 309 Range: hcl.Range{ 310 Start: hcl.Pos{ 311 Byte: 4, 312 Line: 1, 313 Column: 5, 314 }, 315 End: hcl.Pos{ 316 Byte: 4, 317 Line: 1, 318 Column: 5, 319 }, 320 }, 321 }, 322 }, 323 }, 324 { 325 `1 2`, 326 []token{ 327 { 328 Type: tokenNumber, 329 Bytes: []byte(`1`), 330 Range: hcl.Range{ 331 Start: hcl.Pos{ 332 Byte: 0, 333 Line: 1, 334 Column: 1, 335 }, 336 End: hcl.Pos{ 337 Byte: 1, 338 Line: 1, 339 Column: 2, 340 }, 341 }, 342 }, 343 { 344 Type: tokenNumber, 345 Bytes: []byte(`2`), 346 Range: hcl.Range{ 347 Start: hcl.Pos{ 348 Byte: 2, 349 Line: 1, 350 Column: 3, 351 }, 352 End: hcl.Pos{ 353 Byte: 3, 354 Line: 1, 355 Column: 4, 356 }, 357 }, 358 }, 359 { 360 Type: tokenEOF, 361 Range: hcl.Range{ 362 Start: hcl.Pos{ 363 Byte: 3, 364 Line: 1, 365 Column: 4, 366 }, 367 End: hcl.Pos{ 368 Byte: 3, 369 Line: 1, 370 Column: 4, 371 }, 372 }, 373 }, 374 }, 375 }, 376 { 377 "\n1\n 2", 378 []token{ 379 { 380 Type: tokenNumber, 381 Bytes: []byte(`1`), 382 Range: hcl.Range{ 383 Start: hcl.Pos{ 384 Byte: 1, 385 Line: 2, 386 Column: 1, 387 }, 388 End: hcl.Pos{ 389 Byte: 2, 390 Line: 2, 391 Column: 2, 392 }, 393 }, 394 }, 395 { 396 Type: tokenNumber, 397 Bytes: []byte(`2`), 398 Range: hcl.Range{ 399 Start: hcl.Pos{ 400 Byte: 4, 401 Line: 3, 402 Column: 2, 403 }, 404 End: hcl.Pos{ 405 Byte: 5, 406 Line: 3, 407 Column: 3, 408 }, 409 }, 410 }, 411 { 412 Type: tokenEOF, 413 Range: hcl.Range{ 414 Start: hcl.Pos{ 415 Byte: 5, 416 Line: 3, 417 Column: 3, 418 }, 419 End: hcl.Pos{ 420 Byte: 5, 421 Line: 3, 422 Column: 3, 423 }, 424 }, 425 }, 426 }, 427 }, 428 { 429 `-1 2.5`, 430 []token{ 431 { 432 Type: tokenNumber, 433 Bytes: []byte(`-1`), 434 Range: hcl.Range{ 435 Start: hcl.Pos{ 436 Byte: 0, 437 Line: 1, 438 Column: 1, 439 }, 440 End: hcl.Pos{ 441 Byte: 2, 442 Line: 1, 443 Column: 3, 444 }, 445 }, 446 }, 447 { 448 Type: tokenNumber, 449 Bytes: []byte(`2.5`), 450 Range: hcl.Range{ 451 Start: hcl.Pos{ 452 Byte: 3, 453 Line: 1, 454 Column: 4, 455 }, 456 End: hcl.Pos{ 457 Byte: 6, 458 Line: 1, 459 Column: 7, 460 }, 461 }, 462 }, 463 { 464 Type: tokenEOF, 465 Range: hcl.Range{ 466 Start: hcl.Pos{ 467 Byte: 6, 468 Line: 1, 469 Column: 7, 470 }, 471 End: hcl.Pos{ 472 Byte: 6, 473 Line: 1, 474 Column: 7, 475 }, 476 }, 477 }, 478 }, 479 }, 480 { 481 `true`, 482 []token{ 483 { 484 Type: tokenKeyword, 485 Bytes: []byte(`true`), 486 Range: hcl.Range{ 487 Start: hcl.Pos{ 488 Byte: 0, 489 Line: 1, 490 Column: 1, 491 }, 492 End: hcl.Pos{ 493 Byte: 4, 494 Line: 1, 495 Column: 5, 496 }, 497 }, 498 }, 499 { 500 Type: tokenEOF, 501 Range: hcl.Range{ 502 Start: hcl.Pos{ 503 Byte: 4, 504 Line: 1, 505 Column: 5, 506 }, 507 End: hcl.Pos{ 508 Byte: 4, 509 Line: 1, 510 Column: 5, 511 }, 512 }, 513 }, 514 }, 515 }, 516 { 517 `[true]`, 518 []token{ 519 { 520 Type: tokenBrackO, 521 Bytes: []byte(`[`), 522 Range: hcl.Range{ 523 Start: hcl.Pos{ 524 Byte: 0, 525 Line: 1, 526 Column: 1, 527 }, 528 End: hcl.Pos{ 529 Byte: 1, 530 Line: 1, 531 Column: 2, 532 }, 533 }, 534 }, 535 { 536 Type: tokenKeyword, 537 Bytes: []byte(`true`), 538 Range: hcl.Range{ 539 Start: hcl.Pos{ 540 Byte: 1, 541 Line: 1, 542 Column: 2, 543 }, 544 End: hcl.Pos{ 545 Byte: 5, 546 Line: 1, 547 Column: 6, 548 }, 549 }, 550 }, 551 { 552 Type: tokenBrackC, 553 Bytes: []byte(`]`), 554 Range: hcl.Range{ 555 Start: hcl.Pos{ 556 Byte: 5, 557 Line: 1, 558 Column: 6, 559 }, 560 End: hcl.Pos{ 561 Byte: 6, 562 Line: 1, 563 Column: 7, 564 }, 565 }, 566 }, 567 { 568 Type: tokenEOF, 569 Range: hcl.Range{ 570 Start: hcl.Pos{ 571 Byte: 6, 572 Line: 1, 573 Column: 7, 574 }, 575 End: hcl.Pos{ 576 Byte: 6, 577 Line: 1, 578 Column: 7, 579 }, 580 }, 581 }, 582 }, 583 }, 584 { 585 `""`, 586 []token{ 587 { 588 Type: tokenString, 589 Bytes: []byte(`""`), 590 Range: hcl.Range{ 591 Start: hcl.Pos{ 592 Byte: 0, 593 Line: 1, 594 Column: 1, 595 }, 596 End: hcl.Pos{ 597 Byte: 2, 598 Line: 1, 599 Column: 3, 600 }, 601 }, 602 }, 603 { 604 Type: tokenEOF, 605 Range: hcl.Range{ 606 Start: hcl.Pos{ 607 Byte: 2, 608 Line: 1, 609 Column: 3, 610 }, 611 End: hcl.Pos{ 612 Byte: 2, 613 Line: 1, 614 Column: 3, 615 }, 616 }, 617 }, 618 }, 619 }, 620 { 621 `"hello"`, 622 []token{ 623 { 624 Type: tokenString, 625 Bytes: []byte(`"hello"`), 626 Range: hcl.Range{ 627 Start: hcl.Pos{ 628 Byte: 0, 629 Line: 1, 630 Column: 1, 631 }, 632 End: hcl.Pos{ 633 Byte: 7, 634 Line: 1, 635 Column: 8, 636 }, 637 }, 638 }, 639 { 640 Type: tokenEOF, 641 Range: hcl.Range{ 642 Start: hcl.Pos{ 643 Byte: 7, 644 Line: 1, 645 Column: 8, 646 }, 647 End: hcl.Pos{ 648 Byte: 7, 649 Line: 1, 650 Column: 8, 651 }, 652 }, 653 }, 654 }, 655 }, 656 { 657 `"he\"llo"`, 658 []token{ 659 { 660 Type: tokenString, 661 Bytes: []byte(`"he\"llo"`), 662 Range: hcl.Range{ 663 Start: hcl.Pos{ 664 Byte: 0, 665 Line: 1, 666 Column: 1, 667 }, 668 End: hcl.Pos{ 669 Byte: 9, 670 Line: 1, 671 Column: 10, 672 }, 673 }, 674 }, 675 { 676 Type: tokenEOF, 677 Range: hcl.Range{ 678 Start: hcl.Pos{ 679 Byte: 9, 680 Line: 1, 681 Column: 10, 682 }, 683 End: hcl.Pos{ 684 Byte: 9, 685 Line: 1, 686 Column: 10, 687 }, 688 }, 689 }, 690 }, 691 }, 692 { 693 `"hello\\" 1`, 694 []token{ 695 { 696 Type: tokenString, 697 Bytes: []byte(`"hello\\"`), 698 Range: hcl.Range{ 699 Start: hcl.Pos{ 700 Byte: 0, 701 Line: 1, 702 Column: 1, 703 }, 704 End: hcl.Pos{ 705 Byte: 9, 706 Line: 1, 707 Column: 10, 708 }, 709 }, 710 }, 711 { 712 Type: tokenNumber, 713 Bytes: []byte(`1`), 714 Range: hcl.Range{ 715 Start: hcl.Pos{ 716 Byte: 10, 717 Line: 1, 718 Column: 11, 719 }, 720 End: hcl.Pos{ 721 Byte: 11, 722 Line: 1, 723 Column: 12, 724 }, 725 }, 726 }, 727 { 728 Type: tokenEOF, 729 Range: hcl.Range{ 730 Start: hcl.Pos{ 731 Byte: 11, 732 Line: 1, 733 Column: 12, 734 }, 735 End: hcl.Pos{ 736 Byte: 11, 737 Line: 1, 738 Column: 12, 739 }, 740 }, 741 }, 742 }, 743 }, 744 { 745 `"🇬🇧"`, 746 []token{ 747 { 748 Type: tokenString, 749 Bytes: []byte(`"🇬🇧"`), 750 Range: hcl.Range{ 751 Start: hcl.Pos{ 752 Byte: 0, 753 Line: 1, 754 Column: 1, 755 }, 756 End: hcl.Pos{ 757 Byte: 10, 758 Line: 1, 759 Column: 4, 760 }, 761 }, 762 }, 763 { 764 Type: tokenEOF, 765 Range: hcl.Range{ 766 Start: hcl.Pos{ 767 Byte: 10, 768 Line: 1, 769 Column: 4, 770 }, 771 End: hcl.Pos{ 772 Byte: 10, 773 Line: 1, 774 Column: 4, 775 }, 776 }, 777 }, 778 }, 779 }, 780 { 781 `"á́́́́́́́"`, 782 []token{ 783 { 784 Type: tokenString, 785 Bytes: []byte(`"á́́́́́́́"`), 786 Range: hcl.Range{ 787 Start: hcl.Pos{ 788 Byte: 0, 789 Line: 1, 790 Column: 1, 791 }, 792 End: hcl.Pos{ 793 Byte: 19, 794 Line: 1, 795 Column: 4, 796 }, 797 }, 798 }, 799 { 800 Type: tokenEOF, 801 Range: hcl.Range{ 802 Start: hcl.Pos{ 803 Byte: 19, 804 Line: 1, 805 Column: 4, 806 }, 807 End: hcl.Pos{ 808 Byte: 19, 809 Line: 1, 810 Column: 4, 811 }, 812 }, 813 }, 814 }, 815 }, 816 { 817 `&`, 818 []token{ 819 { 820 Type: tokenInvalid, 821 Bytes: []byte(`&`), 822 Range: hcl.Range{ 823 Start: hcl.Pos{ 824 Byte: 0, 825 Line: 1, 826 Column: 1, 827 }, 828 End: hcl.Pos{ 829 Byte: 1, 830 Line: 1, 831 Column: 2, 832 }, 833 }, 834 }, 835 { 836 Type: tokenEOF, 837 Range: hcl.Range{ 838 Start: hcl.Pos{ 839 Byte: 1, 840 Line: 1, 841 Column: 2, 842 }, 843 End: hcl.Pos{ 844 Byte: 1, 845 Line: 1, 846 Column: 2, 847 }, 848 }, 849 }, 850 }, 851 }, 852 } 853 854 for _, test := range tests { 855 t.Run(test.Input, func(t *testing.T) { 856 buf := []byte(test.Input) 857 start := pos{ 858 Filename: "", 859 Pos: hcl.Pos{ 860 Byte: 0, 861 Line: 1, 862 Column: 1, 863 }, 864 } 865 got := scan(buf, start) 866 867 if !reflect.DeepEqual(got, test.Want) { 868 errMsg := &bytes.Buffer{} 869 errMsg.WriteString("wrong result\ngot:\n") 870 if len(got) == 0 { 871 errMsg.WriteString(" (empty slice)\n") 872 } 873 for _, tok := range got { 874 fmt.Fprintf(errMsg, " - %#v\n", tok) 875 } 876 errMsg.WriteString("want:\n") 877 if len(test.Want) == 0 { 878 errMsg.WriteString(" (empty slice)\n") 879 } 880 for _, tok := range test.Want { 881 fmt.Fprintf(errMsg, " - %#v\n", tok) 882 } 883 t.Error(errMsg.String()) 884 } 885 }) 886 } 887 }