github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/internal/third_party/yaml/decode_test.go (about) 1 package yaml_test 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "strconv" 9 "strings" 10 "testing" 11 12 "github.com/joomcode/cue/cue/ast" 13 "github.com/joomcode/cue/cue/format" 14 "github.com/joomcode/cue/internal/cuetest" 15 "github.com/joomcode/cue/internal/third_party/yaml" 16 ) 17 18 var unmarshalIntTest = 123 19 20 var unmarshalTests = []struct { 21 data string 22 want string 23 }{ 24 { 25 "", 26 "", 27 }, 28 { 29 "{}", 30 "", 31 }, { 32 "v: hi", 33 `v: "hi"`, 34 }, { 35 "v: hi", 36 `v: "hi"`, 37 }, { 38 "v: true", 39 "v: true", 40 }, { 41 "v: 10", 42 "v: 10", 43 }, { 44 "v: 0b10", 45 "v: 0b10", 46 }, { 47 "v: 0xA", 48 "v: 0xA", 49 }, { 50 "v: 4294967296", 51 "v: 4294967296", 52 }, { 53 "v: 0.1", 54 "v: 0.1", 55 }, { 56 "v: .1", 57 "v: 0.1", 58 }, { 59 "v: .Inf", 60 "v: +Inf", 61 }, { 62 "v: -.Inf", 63 "v: -Inf", 64 }, { 65 "v: -10", 66 "v: -10", 67 }, { 68 "v: -.1", 69 "v: -0.1", 70 }, 71 72 // Simple values. 73 { 74 "123", 75 "123", 76 }, 77 78 // Floats from spec 79 { 80 "canonical: 6.8523e+5", 81 "canonical: 6.8523e+5", 82 }, { 83 "expo: 685.230_15e+03", 84 "expo: 685.230_15e+03", 85 }, { 86 "fixed: 685_230.15", 87 "fixed: 685_230.15", 88 }, { 89 "neginf: -.inf", 90 "neginf: -Inf", 91 }, { 92 "fixed: 685_230.15", 93 "fixed: 685_230.15", 94 }, 95 //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 96 //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 97 98 // Bools from spec 99 { 100 "canonical: y", 101 `canonical: "y"`, 102 }, { 103 "answer: n", 104 `answer: "n"`, 105 }, { 106 "answer: NO", 107 `answer: "NO"`, 108 }, { 109 "logical: True", 110 "logical: true", 111 }, { 112 "option: on", 113 `option: "on"`, 114 }, { 115 "answer: off", 116 `answer: "off"`, 117 }, 118 // Ints from spec 119 { 120 "canonical: 685230", 121 "canonical: 685230", 122 }, { 123 "decimal: +685_230", 124 "decimal: +685_230", 125 }, { 126 "octal: 02472256", 127 "octal: 0o2472256", 128 }, { 129 "hexa: 0x_0A_74_AE", 130 "hexa: 0x_0A_74_AE", 131 }, { 132 "bin: 0b1010_0111_0100_1010_1110", 133 "bin: 0b1010_0111_0100_1010_1110", 134 }, { 135 "bin: -0b101010", 136 "bin: -0b101010", 137 }, { 138 "bin: -0b1000000000000000000000000000000000000000000000000000000000000000", 139 "bin: -0b1000000000000000000000000000000000000000000000000000000000000000", 140 }, { 141 "decimal: +685_230", 142 "decimal: +685_230", 143 }, 144 145 //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 146 147 // Nulls from spec 148 { 149 "empty:", 150 "empty: null", 151 }, { 152 "canonical: ~", 153 "canonical: null", 154 }, { 155 "english: null", 156 "english: null", 157 }, { 158 "_foo: 1", 159 `"_foo": 1`, 160 }, { 161 `"#foo": 1`, 162 `"#foo": 1`, 163 }, { 164 "_#foo: 1", 165 `"_#foo": 1`, 166 }, { 167 "~: null key", 168 `"null": "null key"`, 169 }, { 170 `empty: 171 apple: "newline"`, 172 `empty: null 173 apple: "newline"`, 174 }, 175 176 // Flow sequence 177 { 178 "seq: [A,B]", 179 `seq: ["A", "B"]`, 180 }, { 181 "seq: [A,B,C,]", 182 `seq: ["A", "B", "C"]`, 183 }, { 184 "seq: [A,1,C]", 185 `seq: ["A", 1, "C"]`, 186 }, 187 // Block sequence 188 { 189 "seq:\n - A\n - B", 190 `seq: [ 191 "A", 192 "B", 193 ]`, 194 }, { 195 "seq:\n - A\n - B\n - C", 196 `seq: [ 197 "A", 198 "B", 199 "C", 200 ]`, 201 }, { 202 "seq:\n - A\n - 1\n - C", 203 `seq: [ 204 "A", 205 1, 206 "C", 207 ]`, 208 }, 209 210 // Literal block scalar 211 { 212 "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 213 `scalar: """ 214 215 literal 216 217 \ttext 218 219 """`, 220 }, 221 222 // Folded block scalar 223 { 224 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 225 `scalar: """ 226 227 folded line 228 next line 229 * one 230 * two 231 232 last line 233 234 """`, 235 }, 236 237 // Structs 238 { 239 "a: {b: c}", 240 `a: {b: "c"}`, 241 }, 242 { 243 "hello: world", 244 `hello: "world"`, 245 }, { 246 "a:", 247 "a: null", 248 }, { 249 "a: 1", 250 "a: 1", 251 }, { 252 "a: 1.0", 253 "a: 1.0", 254 }, { 255 "a: [1, 2]", 256 "a: [1, 2]", 257 }, { 258 "a: y", 259 `a: "y"`, 260 }, { 261 "{ a: 1, b: {c: 1} }", 262 `a: 1, b: {c: 1}`, 263 }, { 264 ` 265 True: 1 266 Null: 1 267 .Inf: 2 268 `, 269 `"true": 1 270 "null": 1 271 "+Inf": 2`, 272 }, 273 274 // Some cross type conversions 275 { 276 "v: 42", 277 "v: 42", 278 }, { 279 "v: -42", 280 "v: -42", 281 }, { 282 "v: 4294967296", 283 "v: 4294967296", 284 }, { 285 "v: -4294967296", 286 "v: -4294967296", 287 }, 288 289 // int 290 { 291 "int_max: 2147483647", 292 "int_max: 2147483647", 293 }, 294 { 295 "int_min: -2147483648", 296 "int_min: -2147483648", 297 }, 298 { 299 "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 300 "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 301 }, 302 303 // int64 304 { 305 "int64_max: 9223372036854775807", 306 "int64_max: 9223372036854775807", 307 }, 308 { 309 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", 310 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", 311 }, 312 { 313 "int64_min: -9223372036854775808", 314 "int64_min: -9223372036854775808", 315 }, 316 { 317 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", 318 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", 319 }, 320 { 321 "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 322 "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 323 }, 324 325 // uint 326 { 327 "uint_max: 4294967295", 328 "uint_max: 4294967295", 329 }, 330 331 // uint64 332 { 333 "uint64_max: 18446744073709551615", 334 "uint64_max: 18446744073709551615", 335 }, 336 { 337 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", 338 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", 339 }, 340 { 341 "uint64_maxint64: 9223372036854775807", 342 "uint64_maxint64: 9223372036854775807", 343 }, 344 345 // float32 346 { 347 "float32_max: 3.40282346638528859811704183484516925440e+38", 348 "float32_max: 3.40282346638528859811704183484516925440e+38", 349 }, 350 { 351 "float32_nonzero: 1.401298464324817070923729583289916131280e-45", 352 "float32_nonzero: 1.401298464324817070923729583289916131280e-45", 353 }, 354 { 355 "float32_maxuint64: 18446744073709551615", 356 "float32_maxuint64: 18446744073709551615", 357 }, 358 { 359 "float32_maxuint64+1: 18446744073709551616", 360 `"float32_maxuint64+1": 18446744073709551616`, 361 }, 362 363 // float64 364 { 365 "float64_max: 1.797693134862315708145274237317043567981e+308", 366 "float64_max: 1.797693134862315708145274237317043567981e+308", 367 }, 368 { 369 "float64_nonzero: 4.940656458412465441765687928682213723651e-324", 370 "float64_nonzero: 4.940656458412465441765687928682213723651e-324", 371 }, 372 { 373 "float64_maxuint64: 18446744073709551615", 374 "float64_maxuint64: 18446744073709551615", 375 }, 376 { 377 "float64_maxuint64+1: 18446744073709551616", 378 `"float64_maxuint64+1": 18446744073709551616`, 379 }, 380 381 // Overflow cases. 382 { 383 "v: 4294967297", 384 "v: 4294967297", 385 }, { 386 "v: 128", 387 "v: 128", 388 }, 389 390 // Quoted values. 391 { 392 "'1': '\"2\"'", 393 `"1": "\"2\""`, 394 }, { 395 "v:\n- A\n- 'B\n\n C'\n", 396 `v: [ 397 "A", 398 """ 399 B 400 C 401 """, 402 ]`, 403 }, { 404 `"\0"`, 405 `"\u0000"`, 406 }, 407 408 // Explicit tags. 409 { 410 "v: !!float '1.1'", 411 "v: 1.1", 412 }, { 413 "v: !!float 0", 414 "v: float & 0", // Should this be 0.0? 415 }, { 416 "v: !!float -1", 417 "v: float & -1", // Should this be -1.0? 418 }, { 419 "v: !!null ''", 420 "v: null", 421 }, { 422 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 423 "v: 1", 424 }, 425 426 // Non-specific tag (Issue #75) 427 { 428 "v: ! test", 429 // TODO: map[string]interface{}{"v": "test"}, 430 "", 431 }, 432 433 // Anchors and aliases. 434 { 435 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 436 `a: 1 437 b: 2 438 c: 1 439 d: 2`, 440 }, { 441 "a: &a {c: 1}\nb: *a", 442 `a: {c: 1} 443 b: { 444 c: 1 445 }`, 446 }, { 447 "a: &a [1, 2]\nb: *a", 448 "a: [1, 2]\nb: [1, 2]", // TODO: a: [1, 2], b: a 449 }, 450 451 { 452 "foo: ''", 453 `foo: ""`, 454 }, { 455 "foo: null", 456 "foo: null", 457 }, 458 459 // Support for ~ 460 { 461 "foo: ~", 462 "foo: null", 463 }, 464 465 // Bug #1191981 466 { 467 "" + 468 "%YAML 1.1\n" + 469 "--- !!str\n" + 470 `"Generic line break (no glyph)\n\` + "\n" + 471 ` Generic line break (glyphed)\n\` + "\n" + 472 ` Line separator\u2028\` + "\n" + 473 ` Paragraph separator\u2029"` + "\n", 474 `""" 475 Generic line break (no glyph) 476 Generic line break (glyphed) 477 Line separator\u2028Paragraph separator\u2029 478 """`, 479 }, 480 481 // bug 1243827 482 { 483 "a: -b_c", 484 `a: "-b_c"`, 485 }, 486 { 487 "a: +b_c", 488 `a: "+b_c"`, 489 }, 490 { 491 "a: 50cent_of_dollar", 492 `a: "50cent_of_dollar"`, 493 }, 494 495 // issue #295 (allow scalars with colons in flow mappings and sequences) 496 { 497 "a: {b: https://github.com/go-yaml/yaml}", 498 `a: {b: "https://github.com/go-yaml/yaml"}`, 499 }, 500 { 501 "a: [https://github.com/go-yaml/yaml]", 502 `a: ["https://github.com/go-yaml/yaml"]`, 503 }, 504 505 // Duration 506 { 507 "a: 3s", 508 `a: "3s"`, // for now 509 }, 510 511 // Issue #24. 512 { 513 "a: <foo>", 514 `a: "<foo>"`, 515 }, 516 517 // Base 60 floats are obsolete and unsupported. 518 { 519 "a: 1:1\n", 520 `a: "1:1"`, 521 }, 522 523 // Binary data. 524 { 525 "a: !!binary gIGC\n", 526 `a: '\x80\x81\x82'`, 527 }, { 528 "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 529 "a: '" + strings.Repeat(`\x90`, 54) + "'", 530 }, { 531 "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", 532 "a: '" + strings.Repeat(`\x00`, 52) + "'", 533 }, 534 535 // Ordered maps. 536 { 537 "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", 538 `b: 2, a: 1, d: 4, c: 3, sub: {e: 5}`, 539 }, 540 541 // Spacing 542 { 543 ` 544 a: {} 545 c: 1 546 d: [ 547 ] 548 e: [] 549 `, 550 `a: {} 551 c: 1 552 d: [ 553 ] 554 e: []`, 555 }, 556 557 { 558 ` 559 a: 560 - { "a": 1, "b": 2 } 561 - { "c": 1, "d": 2 } 562 `, 563 `a: [{ 564 a: 1, b: 2 565 }, { 566 c: 1, d: 2 567 }]`, 568 }, 569 570 { 571 "a:\n b:\n c: d\n e: f\n", 572 `a: { 573 b: { 574 c: "d" 575 e: "f" 576 } 577 }`, 578 }, 579 580 // Issue #39. 581 { 582 "a:\n b:\n c: d\n", 583 `a: { 584 b: { 585 c: "d" 586 } 587 }`, 588 }, 589 590 // Timestamps 591 { 592 // Date only. 593 "a: 2015-01-01\n", 594 `a: "2015-01-01"`, 595 }, 596 { 597 // RFC3339 598 "a: 2015-02-24T18:19:39.12Z\n", 599 `a: "2015-02-24T18:19:39.12Z"`, 600 }, 601 { 602 // RFC3339 with short dates. 603 "a: 2015-2-3T3:4:5Z", 604 `a: "2015-2-3T3:4:5Z"`, 605 }, 606 { 607 // ISO8601 lower case t 608 "a: 2015-02-24t18:19:39Z\n", 609 `a: "2015-02-24t18:19:39Z"`, 610 }, 611 { 612 // space separate, no time zone 613 "a: 2015-02-24 18:19:39\n", 614 `a: "2015-02-24 18:19:39"`, 615 }, 616 // Some cases not currently handled. Uncomment these when 617 // the code is fixed. 618 // { 619 // // space separated with time zone 620 // "a: 2001-12-14 21:59:43.10 -5", 621 // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, 622 // }, 623 // { 624 // // arbitrary whitespace between fields 625 // "a: 2001-12-14 \t\t \t21:59:43.10 \t Z", 626 // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, 627 // }, 628 { 629 // explicit string tag 630 "a: !!str 2015-01-01", 631 `a: "2015-01-01"`, 632 }, 633 { 634 // explicit timestamp tag on quoted string 635 "a: !!timestamp \"2015-01-01\"", 636 `a: "2015-01-01"`, 637 }, 638 { 639 // explicit timestamp tag on unquoted string 640 "a: !!timestamp 2015-01-01", 641 `a: "2015-01-01"`, 642 }, 643 { 644 // quoted string that's a valid timestamp 645 "a: \"2015-01-01\"", 646 "a: \"2015-01-01\"", 647 }, 648 649 // Empty list 650 { 651 "a: []", 652 "a: []", 653 }, 654 655 // UTF-16-LE 656 { 657 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", 658 `ñoño: "very yes"`, 659 }, 660 // UTF-16-LE with surrogate. 661 { 662 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", 663 `ñoño: "very yes 🟔"`, 664 }, 665 666 // UTF-16-BE 667 { 668 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", 669 `ñoño: "very yes"`, 670 }, 671 // UTF-16-BE with surrogate. 672 { 673 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", 674 `ñoño: "very yes 🟔"`, 675 }, 676 677 // YAML Float regex shouldn't match this 678 { 679 "a: 123456e1\n", 680 `a: "123456e1"`, 681 }, { 682 "a: 123456E1\n", 683 `a: "123456E1"`, 684 }, 685 // yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes 686 { 687 "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n", 688 `"First occurrence": "Foo" 689 "Second occurrence": "Foo" 690 "Override anchor": "Bar" 691 "Reuse anchor": "Bar"`, 692 }, 693 // Single document with garbage following it. 694 { 695 "---\nhello\n...\n}not yaml", 696 `"hello"`, 697 }, 698 } 699 700 type M map[interface{}]interface{} 701 702 type inlineB struct { 703 B int 704 inlineC `yaml:",inline"` 705 } 706 707 type inlineC struct { 708 C int 709 } 710 711 func cueStr(node ast.Node) string { 712 if s, ok := node.(*ast.StructLit); ok { 713 node = &ast.File{ 714 Decls: s.Elts, 715 } 716 } 717 b, _ := format.Node(node) 718 return strings.TrimSpace(string(b)) 719 } 720 721 func newDecoder(t *testing.T, data string) *yaml.Decoder { 722 dec, err := yaml.NewDecoder("test.yaml", strings.NewReader(data)) 723 if err != nil { 724 t.Fatal(err) 725 } 726 return dec 727 } 728 729 func callUnmarshal(t *testing.T, data string) (ast.Expr, error) { 730 return yaml.Unmarshal("test.yaml", []byte(data)) 731 } 732 733 func TestUnmarshal(t *testing.T) { 734 for i, item := range unmarshalTests { 735 t.Run(strconv.Itoa(i), func(t *testing.T) { 736 t.Logf("test %d: %q", i, item.data) 737 expr, err := callUnmarshal(t, item.data) 738 if _, ok := err.(*yaml.TypeError); !ok && err != nil { 739 t.Fatal("expected error to be nil") 740 } 741 if got := cueStr(expr); got != item.want { 742 t.Errorf("\n got: %v;\nwant: %v", got, item.want) 743 } 744 }) 745 } 746 } 747 748 // For debug purposes: do not delete. 749 func TestX(t *testing.T) { 750 y := ` 751 ` 752 y = strings.TrimSpace(y) 753 if len(y) == 0 { 754 t.Skip() 755 } 756 757 expr, err := callUnmarshal(t, y) 758 if _, ok := err.(*yaml.TypeError); !ok && err != nil { 759 t.Fatal(err) 760 } 761 t.Error(cueStr(expr)) 762 } 763 764 // // TODO(v3): This test should also work when unmarshaling onto an interface{}. 765 // func (s *S) TestUnmarshalFullTimestamp(c *C) { 766 // // Full timestamp in same format as encoded. This is confirmed to be 767 // // properly decoded by Python as a timestamp as well. 768 // var str = "2015-02-24T18:19:39.123456789-03:00" 769 // expr, err := yaml.Unmarshal([]byte(str)) 770 // c.Assert(err, IsNil) 771 // c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location())) 772 // c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC)) 773 // } 774 775 func TestDecoderSingleDocument(t *testing.T) { 776 // Test that Decoder.Decode works as expected on 777 // all the unmarshal tests. 778 for i, item := range unmarshalTests { 779 t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) { 780 if item.data == "" { 781 // Behaviour differs when there's no YAML. 782 return 783 } 784 expr, err := newDecoder(t, item.data).Decode() 785 if _, ok := err.(*yaml.TypeError); !ok && err != nil { 786 t.Errorf("err should be nil, was %v", err) 787 } 788 if got := cueStr(expr); got != item.want { 789 t.Errorf("\n got: %v;\nwant: %v", got, item.want) 790 } 791 }) 792 } 793 } 794 795 var decoderTests = []struct { 796 data string 797 want string 798 }{{ 799 "", 800 "", 801 }, { 802 "a: b", 803 `a: "b"`, 804 }, { 805 "---\na: b\n...\n", 806 `a: "b"`, 807 }, { 808 "---\n'hello'\n...\n---\ngoodbye\n...\n", 809 `"hello"` + "\n" + `"goodbye"`, 810 }} 811 812 func TestDecoder(t *testing.T) { 813 for i, item := range decoderTests { 814 t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) { 815 var values []string 816 dec := newDecoder(t, item.data) 817 for { 818 expr, err := dec.Decode() 819 if err == io.EOF { 820 break 821 } 822 if err != nil { 823 t.Errorf("err should be nil, was %v", err) 824 } 825 values = append(values, cueStr(expr)) 826 } 827 got := strings.Join(values, "\n") 828 if got != item.want { 829 t.Errorf("\n got: %v;\nwant: %v", got, item.want) 830 } 831 }) 832 } 833 } 834 835 type errReader struct{} 836 837 func (errReader) Read([]byte) (int, error) { 838 return 0, errors.New("some read error") 839 } 840 841 func TestUnmarshalNaN(t *testing.T) { 842 expr, err := callUnmarshal(t, "notanum: .NaN") 843 if err != nil { 844 t.Fatal("unexpected error", err) 845 } 846 got := cueStr(expr) 847 want := "notanum: NaN" 848 if got != want { 849 t.Errorf("got %v; want %v", got, want) 850 } 851 } 852 853 var unmarshalErrorTests = []struct { 854 data, error string 855 }{ 856 {"\nv: !!float 'error'", "test.yaml:2: cannot decode !!str `error` as a !!float"}, 857 {"v: [A,", "test.yaml:1: did not find expected node content"}, 858 {"v:\n- [A,", "test.yaml:2: did not find expected node content"}, 859 {"a:\n- b: *,", "test.yaml:2: did not find expected alphabetic or numeric character"}, 860 {"a: *b\n", "test.yaml:1: unknown anchor 'b' referenced"}, 861 {"a: &a\n b: *a\n", "test.yaml:2: anchor 'a' value contains itself"}, 862 {"value: -", "test.yaml:1: block sequence entries are not allowed in this context"}, 863 {"a: !!binary ==", "test.yaml:1: !!binary value contains invalid base64 data"}, 864 {"{[.]}", `test.yaml:1: invalid map key: sequence`}, 865 {"{{.}}", `test.yaml:1: invalid map key: map`}, 866 {"b: *a\na: &a {c: 1}", `test.yaml:1: unknown anchor 'a' referenced`}, 867 {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "test.yaml:1: did not find expected whitespace"}, 868 } 869 870 func TestUnmarshalErrors(t *testing.T) { 871 for i, item := range unmarshalErrorTests { 872 t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) { 873 expr, err := callUnmarshal(t, item.data) 874 val := "" 875 if expr != nil { 876 val = cueStr(expr) 877 } 878 if err == nil || err.Error() != item.error { 879 t.Errorf("got %v; want %v; (value %v)", err, item.error, val) 880 } 881 }) 882 } 883 } 884 885 func TestDecoderErrors(t *testing.T) { 886 for i, item := range unmarshalErrorTests { 887 t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) { 888 _, err := newDecoder(t, item.data).Decode() 889 if err == nil || err.Error() != item.error { 890 t.Errorf("got %v; want %v", err, item.error) 891 } 892 }) 893 } 894 } 895 896 func TestFiles(t *testing.T) { 897 files := []string{"merge"} 898 for _, test := range files { 899 t.Run(test, func(t *testing.T) { 900 testname := fmt.Sprintf("testdata/%s.test", test) 901 filename := fmt.Sprintf("testdata/%s.out", test) 902 mergeTests, err := ioutil.ReadFile(testname) 903 if err != nil { 904 t.Fatal(err) 905 } 906 expr, err := yaml.Unmarshal("test.yaml", mergeTests) 907 if err != nil { 908 t.Fatal(err) 909 } 910 got := cueStr(expr) 911 if cuetest.UpdateGoldenFiles { 912 ioutil.WriteFile(filename, []byte(got), 0644) 913 return 914 } 915 b, err := ioutil.ReadFile(filename) 916 if err != nil { 917 t.Fatal(err) 918 } 919 if want := string(b); got != want { 920 t.Errorf("\n got: %v;\nwant: %v", got, want) 921 } 922 }) 923 } 924 } 925 926 func TestFuzzCrashers(t *testing.T) { 927 cases := []string{ 928 // runtime error: index out of range 929 "\"\\0\\\r\n", 930 931 // should not happen 932 " 0: [\n] 0", 933 "? ? \"\n\" 0", 934 " - {\n000}0", 935 "0:\n 0: [0\n] 0", 936 " - \"\n000\"0", 937 " - \"\n000\"\"", 938 "0:\n - {\n000}0", 939 "0:\n - \"\n000\"0", 940 "0:\n - \"\n000\"\"", 941 942 // runtime error: index out of range 943 " \ufeff\n", 944 "? \ufeff\n", 945 "? \ufeff:\n", 946 "0: \ufeff\n", 947 "? \ufeff: \ufeff\n", 948 } 949 for _, data := range cases { 950 _, _ = callUnmarshal(t, data) 951 } 952 } 953 954 //var data []byte 955 //func init() { 956 // var err error 957 // data, err = ioutil.ReadFile("/tmp/file.yaml") 958 // if err != nil { 959 // panic(err) 960 // } 961 //} 962 // 963 //func (s *S) BenchmarkUnmarshal(c *C) { 964 // var err error 965 // for i := 0; i < c.N; i++ { 966 // var v map[string]interface{} 967 // err = yaml.Unmarshal(data, &v) 968 // } 969 // if err != nil { 970 // panic(err) 971 // } 972 //} 973 // 974 //func (s *S) BenchmarkMarshal(c *C) { 975 // var v map[string]interface{} 976 // yaml.Unmarshal(data, &v) 977 // c.ResetTimer() 978 // for i := 0; i < c.N; i++ { 979 // yaml.Marshal(&v) 980 // } 981 //}