1package yaml_test 2 3import ( 4 "errors" 5 "io" 6 "math" 7 "reflect" 8 "strings" 9 "time" 10 11 . "gopkg.in/check.v1" 12 "gopkg.in/yaml.v2" 13) 14 15var unmarshalIntTest = 123 16 17var unmarshalTests = []struct { 18 data string 19 value interface{} 20}{ 21 { 22 "", 23 (*struct{})(nil), 24 }, 25 { 26 "{}", &struct{}{}, 27 }, { 28 "v: hi", 29 map[string]string{"v": "hi"}, 30 }, { 31 "v: hi", map[string]interface{}{"v": "hi"}, 32 }, { 33 "v: true", 34 map[string]string{"v": "true"}, 35 }, { 36 "v: true", 37 map[string]interface{}{"v": true}, 38 }, { 39 "v: 10", 40 map[string]interface{}{"v": 10}, 41 }, { 42 "v: 0b10", 43 map[string]interface{}{"v": 2}, 44 }, { 45 "v: 0xA", 46 map[string]interface{}{"v": 10}, 47 }, { 48 "v: 4294967296", 49 map[string]int64{"v": 4294967296}, 50 }, { 51 "v: 0.1", 52 map[string]interface{}{"v": 0.1}, 53 }, { 54 "v: .1", 55 map[string]interface{}{"v": 0.1}, 56 }, { 57 "v: .Inf", 58 map[string]interface{}{"v": math.Inf(+1)}, 59 }, { 60 "v: -.Inf", 61 map[string]interface{}{"v": math.Inf(-1)}, 62 }, { 63 "v: -10", 64 map[string]interface{}{"v": -10}, 65 }, { 66 "v: -.1", 67 map[string]interface{}{"v": -0.1}, 68 }, 69 70 // Simple values. 71 { 72 "123", 73 &unmarshalIntTest, 74 }, 75 76 // Floats from spec 77 { 78 "canonical: 6.8523e+5", 79 map[string]interface{}{"canonical": 6.8523e+5}, 80 }, { 81 "expo: 685.230_15e+03", 82 map[string]interface{}{"expo": 685.23015e+03}, 83 }, { 84 "fixed: 685_230.15", 85 map[string]interface{}{"fixed": 685230.15}, 86 }, { 87 "neginf: -.inf", 88 map[string]interface{}{"neginf": math.Inf(-1)}, 89 }, { 90 "fixed: 685_230.15", 91 map[string]float64{"fixed": 685230.15}, 92 }, 93 //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 94 //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 95 96 // Bools from spec 97 { 98 "canonical: y", 99 map[string]interface{}{"canonical": true}, 100 }, { 101 "answer: NO", 102 map[string]interface{}{"answer": false}, 103 }, { 104 "logical: True", 105 map[string]interface{}{"logical": true}, 106 }, { 107 "option: on", 108 map[string]interface{}{"option": true}, 109 }, { 110 "option: on", 111 map[string]bool{"option": true}, 112 }, 113 // Ints from spec 114 { 115 "canonical: 685230", 116 map[string]interface{}{"canonical": 685230}, 117 }, { 118 "decimal: +685_230", 119 map[string]interface{}{"decimal": 685230}, 120 }, { 121 "octal: 02472256", 122 map[string]interface{}{"octal": 685230}, 123 }, { 124 "hexa: 0x_0A_74_AE", 125 map[string]interface{}{"hexa": 685230}, 126 }, { 127 "bin: 0b1010_0111_0100_1010_1110", 128 map[string]interface{}{"bin": 685230}, 129 }, { 130 "bin: -0b101010", 131 map[string]interface{}{"bin": -42}, 132 }, { 133 "bin: -0b1000000000000000000000000000000000000000000000000000000000000000", 134 map[string]interface{}{"bin": -9223372036854775808}, 135 }, { 136 "decimal: +685_230", 137 map[string]int{"decimal": 685230}, 138 }, 139 140 //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 141 142 // Nulls from spec 143 { 144 "empty:", 145 map[string]interface{}{"empty": nil}, 146 }, { 147 "canonical: ~", 148 map[string]interface{}{"canonical": nil}, 149 }, { 150 "english: null", 151 map[string]interface{}{"english": nil}, 152 }, { 153 "~: null key", 154 map[interface{}]string{nil: "null key"}, 155 }, { 156 "empty:", 157 map[string]*bool{"empty": nil}, 158 }, 159 160 // Flow sequence 161 { 162 "seq: [A,B]", 163 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 164 }, { 165 "seq: [A,B,C,]", 166 map[string][]string{"seq": []string{"A", "B", "C"}}, 167 }, { 168 "seq: [A,1,C]", 169 map[string][]string{"seq": []string{"A", "1", "C"}}, 170 }, { 171 "seq: [A,1,C]", 172 map[string][]int{"seq": []int{1}}, 173 }, { 174 "seq: [A,1,C]", 175 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 176 }, 177 // Block sequence 178 { 179 "seq:\n - A\n - B", 180 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 181 }, { 182 "seq:\n - A\n - B\n - C", 183 map[string][]string{"seq": []string{"A", "B", "C"}}, 184 }, { 185 "seq:\n - A\n - 1\n - C", 186 map[string][]string{"seq": []string{"A", "1", "C"}}, 187 }, { 188 "seq:\n - A\n - 1\n - C", 189 map[string][]int{"seq": []int{1}}, 190 }, { 191 "seq:\n - A\n - 1\n - C", 192 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 193 }, 194 195 // Literal block scalar 196 { 197 "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 198 map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, 199 }, 200 201 // Folded block scalar 202 { 203 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 204 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, 205 }, 206 207 // Map inside interface with no type hints. 208 { 209 "a: {b: c}", 210 map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 211 }, 212 213 // Structs and type conversions. 214 { 215 "hello: world", 216 &struct{ Hello string }{"world"}, 217 }, { 218 "a: {b: c}", 219 &struct{ A struct{ B string } }{struct{ B string }{"c"}}, 220 }, { 221 "a: {b: c}", 222 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, 223 }, { 224 "a: {b: c}", 225 &struct{ A map[string]string }{map[string]string{"b": "c"}}, 226 }, { 227 "a: {b: c}", 228 &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, 229 }, { 230 "a:", 231 &struct{ A map[string]string }{}, 232 }, { 233 "a: 1", 234 &struct{ A int }{1}, 235 }, { 236 "a: 1", 237 &struct{ A float64 }{1}, 238 }, { 239 "a: 1.0", 240 &struct{ A int }{1}, 241 }, { 242 "a: 1.0", 243 &struct{ A uint }{1}, 244 }, { 245 "a: [1, 2]", 246 &struct{ A []int }{[]int{1, 2}}, 247 }, { 248 "a: [1, 2]", 249 &struct{ A [2]int }{[2]int{1, 2}}, 250 }, { 251 "a: 1", 252 &struct{ B int }{0}, 253 }, { 254 "a: 1", 255 &struct { 256 B int "a" 257 }{1}, 258 }, { 259 "a: y", 260 &struct{ A bool }{true}, 261 }, 262 263 // Some cross type conversions 264 { 265 "v: 42", 266 map[string]uint{"v": 42}, 267 }, { 268 "v: -42", 269 map[string]uint{}, 270 }, { 271 "v: 4294967296", 272 map[string]uint64{"v": 4294967296}, 273 }, { 274 "v: -4294967296", 275 map[string]uint64{}, 276 }, 277 278 // int 279 { 280 "int_max: 2147483647", 281 map[string]int{"int_max": math.MaxInt32}, 282 }, 283 { 284 "int_min: -2147483648", 285 map[string]int{"int_min": math.MinInt32}, 286 }, 287 { 288 "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 289 map[string]int{}, 290 }, 291 292 // int64 293 { 294 "int64_max: 9223372036854775807", 295 map[string]int64{"int64_max": math.MaxInt64}, 296 }, 297 { 298 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", 299 map[string]int64{"int64_max_base2": math.MaxInt64}, 300 }, 301 { 302 "int64_min: -9223372036854775808", 303 map[string]int64{"int64_min": math.MinInt64}, 304 }, 305 { 306 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", 307 map[string]int64{"int64_neg_base2": -math.MaxInt64}, 308 }, 309 { 310 "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 311 map[string]int64{}, 312 }, 313 314 // uint 315 { 316 "uint_min: 0", 317 map[string]uint{"uint_min": 0}, 318 }, 319 { 320 "uint_max: 4294967295", 321 map[string]uint{"uint_max": math.MaxUint32}, 322 }, 323 { 324 "uint_underflow: -1", 325 map[string]uint{}, 326 }, 327 328 // uint64 329 { 330 "uint64_min: 0", 331 map[string]uint{"uint64_min": 0}, 332 }, 333 { 334 "uint64_max: 18446744073709551615", 335 map[string]uint64{"uint64_max": math.MaxUint64}, 336 }, 337 { 338 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", 339 map[string]uint64{"uint64_max_base2": math.MaxUint64}, 340 }, 341 { 342 "uint64_maxint64: 9223372036854775807", 343 map[string]uint64{"uint64_maxint64": math.MaxInt64}, 344 }, 345 { 346 "uint64_underflow: -1", 347 map[string]uint64{}, 348 }, 349 350 // float32 351 { 352 "float32_max: 3.40282346638528859811704183484516925440e+38", 353 map[string]float32{"float32_max": math.MaxFloat32}, 354 }, 355 { 356 "float32_nonzero: 1.401298464324817070923729583289916131280e-45", 357 map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, 358 }, 359 { 360 "float32_maxuint64: 18446744073709551615", 361 map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, 362 }, 363 { 364 "float32_maxuint64+1: 18446744073709551616", 365 map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, 366 }, 367 368 // float64 369 { 370 "float64_max: 1.797693134862315708145274237317043567981e+308", 371 map[string]float64{"float64_max": math.MaxFloat64}, 372 }, 373 { 374 "float64_nonzero: 4.940656458412465441765687928682213723651e-324", 375 map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, 376 }, 377 { 378 "float64_maxuint64: 18446744073709551615", 379 map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, 380 }, 381 { 382 "float64_maxuint64+1: 18446744073709551616", 383 map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, 384 }, 385 386 // Overflow cases. 387 { 388 "v: 4294967297", 389 map[string]int32{}, 390 }, { 391 "v: 128", 392 map[string]int8{}, 393 }, 394 395 // Quoted values. 396 { 397 "'1': '\"2\"'", 398 map[interface{}]interface{}{"1": "\"2\""}, 399 }, { 400 "v:\n- A\n- 'B\n\n C'\n", 401 map[string][]string{"v": []string{"A", "B\nC"}}, 402 }, 403 404 // Explicit tags. 405 { 406 "v: !!float '1.1'", 407 map[string]interface{}{"v": 1.1}, 408 }, { 409 "v: !!float 0", 410 map[string]interface{}{"v": float64(0)}, 411 }, { 412 "v: !!float -1", 413 map[string]interface{}{"v": float64(-1)}, 414 }, { 415 "v: !!null ''", 416 map[string]interface{}{"v": nil}, 417 }, { 418 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 419 map[string]interface{}{"v": 1}, 420 }, 421 422 // Non-specific tag (Issue #75) 423 { 424 "v: ! test", 425 map[string]interface{}{"v": "test"}, 426 }, 427 428 // Anchors and aliases. 429 { 430 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 431 &struct{ A, B, C, D int }{1, 2, 1, 2}, 432 }, { 433 "a: &a {c: 1}\nb: *a", 434 &struct { 435 A, B struct { 436 C int 437 } 438 }{struct{ C int }{1}, struct{ C int }{1}}, 439 }, { 440 "a: &a [1, 2]\nb: *a", 441 &struct{ B []int }{[]int{1, 2}}, 442 }, 443 444 // Bug #1133337 445 { 446 "foo: ''", 447 map[string]*string{"foo": new(string)}, 448 }, { 449 "foo: null", 450 map[string]*string{"foo": nil}, 451 }, { 452 "foo: null", 453 map[string]string{"foo": ""}, 454 }, { 455 "foo: null", 456 map[string]interface{}{"foo": nil}, 457 }, 458 459 // Support for ~ 460 { 461 "foo: ~", 462 map[string]*string{"foo": nil}, 463 }, { 464 "foo: ~", 465 map[string]string{"foo": ""}, 466 }, { 467 "foo: ~", 468 map[string]interface{}{"foo": nil}, 469 }, 470 471 // Ignored field 472 { 473 "a: 1\nb: 2\n", 474 &struct { 475 A int 476 B int "-" 477 }{1, 0}, 478 }, 479 480 // Bug #1191981 481 { 482 "" + 483 "%YAML 1.1\n" + 484 "--- !!str\n" + 485 `"Generic line break (no glyph)\n\` + "\n" + 486 ` Generic line break (glyphed)\n\` + "\n" + 487 ` Line separator\u2028\` + "\n" + 488 ` Paragraph separator\u2029"` + "\n", 489 "" + 490 "Generic line break (no glyph)\n" + 491 "Generic line break (glyphed)\n" + 492 "Line separator\u2028Paragraph separator\u2029", 493 }, 494 495 // Struct inlining 496 { 497 "a: 1\nb: 2\nc: 3\n", 498 &struct { 499 A int 500 C inlineB `yaml:",inline"` 501 }{1, inlineB{2, inlineC{3}}}, 502 }, 503 504 // Map inlining 505 { 506 "a: 1\nb: 2\nc: 3\n", 507 &struct { 508 A int 509 C map[string]int `yaml:",inline"` 510 }{1, map[string]int{"b": 2, "c": 3}}, 511 }, 512 513 // bug 1243827 514 { 515 "a: -b_c", 516 map[string]interface{}{"a": "-b_c"}, 517 }, 518 { 519 "a: +b_c", 520 map[string]interface{}{"a": "+b_c"}, 521 }, 522 { 523 "a: 50cent_of_dollar", 524 map[string]interface{}{"a": "50cent_of_dollar"}, 525 }, 526 527 // issue #295 (allow scalars with colons in flow mappings and sequences) 528 { 529 "a: {b: https://github.com/go-yaml/yaml}", 530 map[string]interface{}{"a": map[interface{}]interface{}{ 531 "b": "https://github.com/go-yaml/yaml", 532 }}, 533 }, 534 { 535 "a: [https://github.com/go-yaml/yaml]", 536 map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}}, 537 }, 538 539 // Duration 540 { 541 "a: 3s", 542 map[string]time.Duration{"a": 3 * time.Second}, 543 }, 544 545 // Issue #24. 546 { 547 "a: <foo>", 548 map[string]string{"a": "<foo>"}, 549 }, 550 551 // Base 60 floats are obsolete and unsupported. 552 { 553 "a: 1:1\n", 554 map[string]string{"a": "1:1"}, 555 }, 556 557 // Binary data. 558 { 559 "a: !!binary gIGC\n", 560 map[string]string{"a": "\x80\x81\x82"}, 561 }, { 562 "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 563 map[string]string{"a": strings.Repeat("\x90", 54)}, 564 }, { 565 "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", 566 map[string]string{"a": strings.Repeat("\x00", 52)}, 567 }, 568 569 // Ordered maps. 570 { 571 "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", 572 &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, 573 }, 574 575 // Issue #39. 576 { 577 "a:\n b:\n c: d\n", 578 map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}}, 579 }, 580 581 // Custom map type. 582 { 583 "a: {b: c}", 584 M{"a": M{"b": "c"}}, 585 }, 586 587 // Support encoding.TextUnmarshaler. 588 { 589 "a: 1.2.3.4\n", 590 map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}}, 591 }, 592 { 593 "a: 2015-02-24T18:19:39Z\n", 594 map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}}, 595 }, 596 597 // Timestamps 598 { 599 // Date only. 600 "a: 2015-01-01\n", 601 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 602 }, 603 { 604 // RFC3339 605 "a: 2015-02-24T18:19:39.12Z\n", 606 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)}, 607 }, 608 { 609 // RFC3339 with short dates. 610 "a: 2015-2-3T3:4:5Z", 611 map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)}, 612 }, 613 { 614 // ISO8601 lower case t 615 "a: 2015-02-24t18:19:39Z\n", 616 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, 617 }, 618 { 619 // space separate, no time zone 620 "a: 2015-02-24 18:19:39\n", 621 map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)}, 622 }, 623 // Some cases not currently handled. Uncomment these when 624 // the code is fixed. 625 // { 626 // // space separated with time zone 627 // "a: 2001-12-14 21:59:43.10 -5", 628 // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, 629 // }, 630 // { 631 // // arbitrary whitespace between fields 632 // "a: 2001-12-14 \t\t \t21:59:43.10 \t Z", 633 // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)}, 634 // }, 635 { 636 // explicit string tag 637 "a: !!str 2015-01-01", 638 map[string]interface{}{"a": "2015-01-01"}, 639 }, 640 { 641 // explicit timestamp tag on quoted string 642 "a: !!timestamp \"2015-01-01\"", 643 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 644 }, 645 { 646 // explicit timestamp tag on unquoted string 647 "a: !!timestamp 2015-01-01", 648 map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 649 }, 650 { 651 // quoted string that's a valid timestamp 652 "a: \"2015-01-01\"", 653 map[string]interface{}{"a": "2015-01-01"}, 654 }, 655 { 656 // explicit timestamp tag into interface. 657 "a: !!timestamp \"2015-01-01\"", 658 map[string]interface{}{"a": "2015-01-01"}, 659 }, 660 { 661 // implicit timestamp tag into interface. 662 "a: 2015-01-01", 663 map[string]interface{}{"a": "2015-01-01"}, 664 }, 665 666 // Encode empty lists as zero-length slices. 667 { 668 "a: []", 669 &struct{ A []int }{[]int{}}, 670 }, 671 672 // UTF-16-LE 673 { 674 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", 675 M{"ñoño": "very yes"}, 676 }, 677 // UTF-16-LE with surrogate. 678 { 679 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", 680 M{"ñoño": "very yes "}, 681 }, 682 683 // UTF-16-BE 684 { 685 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", 686 M{"ñoño": "very yes"}, 687 }, 688 // UTF-16-BE with surrogate. 689 { 690 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", 691 M{"ñoño": "very yes "}, 692 }, 693 694 // This *is* in fact a float number, per the spec. #171 was a mistake. 695 { 696 "a: 123456e1\n", 697 M{"a": 123456e1}, 698 }, { 699 "a: 123456E1\n", 700 M{"a": 123456E1}, 701 }, 702 // yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes 703 { 704 "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n", 705 map[interface{}]interface{}{ 706 "Reuse anchor": "Bar", 707 "First occurrence": "Foo", 708 "Second occurrence": "Foo", 709 "Override anchor": "Bar", 710 }, 711 }, 712 // Single document with garbage following it. 713 { 714 "---\nhello\n...\n}not yaml", 715 "hello", 716 }, 717 { 718 "a: 5\n", 719 &struct{ A jsonNumberT }{"5"}, 720 }, 721 { 722 "a: 5.5\n", 723 &struct{ A jsonNumberT }{"5.5"}, 724 }, 725} 726 727type M map[interface{}]interface{} 728 729type inlineB struct { 730 B int 731 inlineC `yaml:",inline"` 732} 733 734type inlineC struct { 735 C int 736} 737 738func (s *S) TestUnmarshal(c *C) { 739 for i, item := range unmarshalTests { 740 c.Logf("test %d: %q", i, item.data) 741 t := reflect.ValueOf(item.value).Type() 742 value := reflect.New(t) 743 err := yaml.Unmarshal([]byte(item.data), value.Interface()) 744 if _, ok := err.(*yaml.TypeError); !ok { 745 c.Assert(err, IsNil) 746 } 747 c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err)) 748 } 749} 750 751// TODO(v3): This test should also work when unmarshaling onto an interface{}. 752func (s *S) TestUnmarshalFullTimestamp(c *C) { 753 // Full timestamp in same format as encoded. This is confirmed to be 754 // properly decoded by Python as a timestamp as well. 755 var str = "2015-02-24T18:19:39.123456789-03:00" 756 var t time.Time 757 err := yaml.Unmarshal([]byte(str), &t) 758 c.Assert(err, IsNil) 759 c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location())) 760 c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC)) 761} 762 763func (s *S) TestDecoderSingleDocument(c *C) { 764 // Test that Decoder.Decode works as expected on 765 // all the unmarshal tests. 766 for i, item := range unmarshalTests { 767 c.Logf("test %d: %q", i, item.data) 768 if item.data == "" { 769 // Behaviour differs when there's no YAML. 770 continue 771 } 772 t := reflect.ValueOf(item.value).Type() 773 value := reflect.New(t) 774 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface()) 775 if _, ok := err.(*yaml.TypeError); !ok { 776 c.Assert(err, IsNil) 777 } 778 c.Assert(value.Elem().Interface(), DeepEquals, item.value) 779 } 780} 781 782var decoderTests = []struct { 783 data string 784 values []interface{} 785}{{ 786 "", 787 nil, 788}, { 789 "a: b", 790 []interface{}{ 791 map[interface{}]interface{}{"a": "b"}, 792 }, 793}, { 794 "---\na: b\n...\n", 795 []interface{}{ 796 map[interface{}]interface{}{"a": "b"}, 797 }, 798}, { 799 "---\n'hello'\n...\n---\ngoodbye\n...\n", 800 []interface{}{ 801 "hello", 802 "goodbye", 803 }, 804}} 805 806func (s *S) TestDecoder(c *C) { 807 for i, item := range decoderTests { 808 c.Logf("test %d: %q", i, item.data) 809 var values []interface{} 810 dec := yaml.NewDecoder(strings.NewReader(item.data)) 811 for { 812 var value interface{} 813 err := dec.Decode(&value) 814 if err == io.EOF { 815 break 816 } 817 c.Assert(err, IsNil) 818 values = append(values, value) 819 } 820 c.Assert(values, DeepEquals, item.values) 821 } 822} 823 824type errReader struct{} 825 826func (errReader) Read([]byte) (int, error) { 827 return 0, errors.New("some read error") 828} 829 830func (s *S) TestDecoderReadError(c *C) { 831 err := yaml.NewDecoder(errReader{}).Decode(&struct{}{}) 832 c.Assert(err, ErrorMatches, `yaml: input error: some read error`) 833} 834 835func (s *S) TestUnmarshalNaN(c *C) { 836 value := map[string]interface{}{} 837 err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) 838 c.Assert(err, IsNil) 839 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 840} 841 842var unmarshalErrorTests = []struct { 843 data, error string 844}{ 845 {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, 846 {"v: [A,", "yaml: line 1: did not find expected node content"}, 847 {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, 848 {"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"}, 849 {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, 850 {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, 851 {"value: -", "yaml: block sequence entries are not allowed in this context"}, 852 {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, 853 {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, 854 {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, 855 {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`}, 856 {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"}, 857 { 858 "a: &a [00,00,00,00,00,00,00,00,00]\n" + 859 "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" + 860 "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" + 861 "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" + 862 "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" + 863 "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" + 864 "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" + 865 "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" + 866 "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n", 867 "yaml: document contains excessive aliasing", 868 }, 869} 870 871func (s *S) TestUnmarshalErrors(c *C) { 872 for i, item := range unmarshalErrorTests { 873 c.Logf("test %d: %q", i, item.data) 874 var value interface{} 875 err := yaml.Unmarshal([]byte(item.data), &value) 876 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 877 } 878} 879 880func (s *S) TestDecoderErrors(c *C) { 881 for _, item := range unmarshalErrorTests { 882 var value interface{} 883 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value) 884 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 885 } 886} 887 888var unmarshalerTests = []struct { 889 data, tag string 890 value interface{} 891}{ 892 {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 893 {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 894 {"_: 10", "!!int", 10}, 895 {"_: null", "!!null", nil}, 896 {`_: BAR!`, "!!str", "BAR!"}, 897 {`_: "BAR!"`, "!!str", "BAR!"}, 898 {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 899 {`_: ""`, "!!str", ""}, 900} 901 902var unmarshalerResult = map[int]error{} 903 904type unmarshalerType struct { 905 value interface{} 906} 907 908func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { 909 if err := unmarshal(&o.value); err != nil { 910 return err 911 } 912 if i, ok := o.value.(int); ok { 913 if result, ok := unmarshalerResult[i]; ok { 914 return result 915 } 916 } 917 return nil 918} 919 920type unmarshalerPointer struct { 921 Field *unmarshalerType "_" 922} 923 924type unmarshalerValue struct { 925 Field unmarshalerType "_" 926} 927 928func (s *S) TestUnmarshalerPointerField(c *C) { 929 for _, item := range unmarshalerTests { 930 obj := &unmarshalerPointer{} 931 err := yaml.Unmarshal([]byte(item.data), obj) 932 c.Assert(err, IsNil) 933 if item.value == nil { 934 c.Assert(obj.Field, IsNil) 935 } else { 936 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 937 c.Assert(obj.Field.value, DeepEquals, item.value) 938 } 939 } 940} 941 942func (s *S) TestUnmarshalerValueField(c *C) { 943 for _, item := range unmarshalerTests { 944 obj := &unmarshalerValue{} 945 err := yaml.Unmarshal([]byte(item.data), obj) 946 c.Assert(err, IsNil) 947 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 948 c.Assert(obj.Field.value, DeepEquals, item.value) 949 } 950} 951 952func (s *S) TestUnmarshalerWholeDocument(c *C) { 953 obj := &unmarshalerType{} 954 err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) 955 c.Assert(err, IsNil) 956 value, ok := obj.value.(map[interface{}]interface{}) 957 c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) 958 c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) 959} 960 961func (s *S) TestUnmarshalerTypeError(c *C) { 962 unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} 963 unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} 964 defer func() { 965 delete(unmarshalerResult, 2) 966 delete(unmarshalerResult, 4) 967 }() 968 969 type T struct { 970 Before int 971 After int 972 M map[string]*unmarshalerType 973 } 974 var v T 975 data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` 976 err := yaml.Unmarshal([]byte(data), &v) 977 c.Assert(err, ErrorMatches, ""+ 978 "yaml: unmarshal errors:\n"+ 979 " line 1: cannot unmarshal !!str `A` into int\n"+ 980 " foo\n"+ 981 " bar\n"+ 982 " line 1: cannot unmarshal !!str `B` into int") 983 c.Assert(v.M["abc"], NotNil) 984 c.Assert(v.M["def"], IsNil) 985 c.Assert(v.M["ghi"], NotNil) 986 c.Assert(v.M["jkl"], IsNil) 987 988 c.Assert(v.M["abc"].value, Equals, 1) 989 c.Assert(v.M["ghi"].value, Equals, 3) 990} 991 992type proxyTypeError struct{} 993 994func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { 995 var s string 996 var a int32 997 var b int64 998 if err := unmarshal(&s); err != nil { 999 panic(err) 1000 } 1001 if s == "a" { 1002 if err := unmarshal(&b); err == nil { 1003 panic("should have failed") 1004 } 1005 return unmarshal(&a) 1006 } 1007 if err := unmarshal(&a); err == nil { 1008 panic("should have failed") 1009 } 1010 return unmarshal(&b) 1011} 1012 1013func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { 1014 type T struct { 1015 Before int 1016 After int 1017 M map[string]*proxyTypeError 1018 } 1019 var v T 1020 data := `{before: A, m: {abc: a, def: b}, after: B}` 1021 err := yaml.Unmarshal([]byte(data), &v) 1022 c.Assert(err, ErrorMatches, ""+ 1023 "yaml: unmarshal errors:\n"+ 1024 " line 1: cannot unmarshal !!str `A` into int\n"+ 1025 " line 1: cannot unmarshal !!str `a` into int32\n"+ 1026 " line 1: cannot unmarshal !!str `b` into int64\n"+ 1027 " line 1: cannot unmarshal !!str `B` into int") 1028} 1029 1030type failingUnmarshaler struct{} 1031 1032var failingErr = errors.New("failingErr") 1033 1034func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 1035 return failingErr 1036} 1037 1038func (s *S) TestUnmarshalerError(c *C) { 1039 err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) 1040 c.Assert(err, Equals, failingErr) 1041} 1042 1043type sliceUnmarshaler []int 1044 1045func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 1046 var slice []int 1047 err := unmarshal(&slice) 1048 if err == nil { 1049 *su = slice 1050 return nil 1051 } 1052 1053 var intVal int 1054 err = unmarshal(&intVal) 1055 if err == nil { 1056 *su = []int{intVal} 1057 return nil 1058 } 1059 1060 return err 1061} 1062 1063func (s *S) TestUnmarshalerRetry(c *C) { 1064 var su sliceUnmarshaler 1065 err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) 1066 c.Assert(err, IsNil) 1067 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) 1068 1069 err = yaml.Unmarshal([]byte("1"), &su) 1070 c.Assert(err, IsNil) 1071 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) 1072} 1073 1074// From http://yaml.org/type/merge.html 1075var mergeTests = ` 1076anchors: 1077 list: 1078 - &CENTER { "x": 1, "y": 2 } 1079 - &LEFT { "x": 0, "y": 2 } 1080 - &BIG { "r": 10 } 1081 - &SMALL { "r": 1 } 1082 1083# All the following maps are equal: 1084 1085plain: 1086 # Explicit keys 1087 "x": 1 1088 "y": 2 1089 "r": 10 1090 label: center/big 1091 1092mergeOne: 1093 # Merge one map 1094 << : *CENTER 1095 "r": 10 1096 label: center/big 1097 1098mergeMultiple: 1099 # Merge multiple maps 1100 << : [ *CENTER, *BIG ] 1101 label: center/big 1102 1103override: 1104 # Override 1105 << : [ *BIG, *LEFT, *SMALL ] 1106 "x": 1 1107 label: center/big 1108 1109shortTag: 1110 # Explicit short merge tag 1111 !!merge "<<" : [ *CENTER, *BIG ] 1112 label: center/big 1113 1114longTag: 1115 # Explicit merge long tag 1116 !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ] 1117 label: center/big 1118 1119inlineMap: 1120 # Inlined map 1121 << : {"x": 1, "y": 2, "r": 10} 1122 label: center/big 1123 1124inlineSequenceMap: 1125 # Inlined map in sequence 1126 << : [ *CENTER, {"r": 10} ] 1127 label: center/big 1128` 1129 1130func (s *S) TestMerge(c *C) { 1131 var want = map[interface{}]interface{}{ 1132 "x": 1, 1133 "y": 2, 1134 "r": 10, 1135 "label": "center/big", 1136 } 1137 1138 var m map[interface{}]interface{} 1139 err := yaml.Unmarshal([]byte(mergeTests), &m) 1140 c.Assert(err, IsNil) 1141 for name, test := range m { 1142 if name == "anchors" { 1143 continue 1144 } 1145 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) 1146 } 1147} 1148 1149func (s *S) TestMergeStruct(c *C) { 1150 type Data struct { 1151 X, Y, R int 1152 Label string 1153 } 1154 want := Data{1, 2, 10, "center/big"} 1155 1156 var m map[string]Data 1157 err := yaml.Unmarshal([]byte(mergeTests), &m) 1158 c.Assert(err, IsNil) 1159 for name, test := range m { 1160 if name == "anchors" { 1161 continue 1162 } 1163 c.Assert(test, Equals, want, Commentf("test %q failed", name)) 1164 } 1165} 1166 1167var unmarshalNullTests = []func() interface{}{ 1168 func() interface{} { var v interface{}; v = "v"; return &v }, 1169 func() interface{} { var s = "s"; return &s }, 1170 func() interface{} { var s = "s"; sptr := &s; return &sptr }, 1171 func() interface{} { var i = 1; return &i }, 1172 func() interface{} { var i = 1; iptr := &i; return &iptr }, 1173 func() interface{} { m := map[string]int{"s": 1}; return &m }, 1174 func() interface{} { m := map[string]int{"s": 1}; return m }, 1175} 1176 1177func (s *S) TestUnmarshalNull(c *C) { 1178 for _, test := range unmarshalNullTests { 1179 item := test() 1180 zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() 1181 err := yaml.Unmarshal([]byte("null"), item) 1182 c.Assert(err, IsNil) 1183 if reflect.TypeOf(item).Kind() == reflect.Map { 1184 c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) 1185 } else { 1186 c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) 1187 } 1188 } 1189} 1190 1191func (s *S) TestUnmarshalSliceOnPreset(c *C) { 1192 // Issue #48. 1193 v := struct{ A []int }{[]int{1}} 1194 yaml.Unmarshal([]byte("a: [2]"), &v) 1195 c.Assert(v.A, DeepEquals, []int{2}) 1196} 1197 1198var unmarshalStrictTests = []struct { 1199 data string 1200 value interface{} 1201 error string 1202}{{ 1203 data: "a: 1\nc: 2\n", 1204 value: struct{ A, B int }{A: 1}, 1205 error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`, 1206}, { 1207 data: "a: 1\nb: 2\na: 3\n", 1208 value: struct{ A, B int }{A: 3, B: 2}, 1209 error: `yaml: unmarshal errors:\n line 3: field a already set in type struct { A int; B int }`, 1210}, { 1211 data: "c: 3\na: 1\nb: 2\nc: 4\n", 1212 value: struct { 1213 A int 1214 inlineB `yaml:",inline"` 1215 }{ 1216 A: 1, 1217 inlineB: inlineB{ 1218 B: 2, 1219 inlineC: inlineC{ 1220 C: 4, 1221 }, 1222 }, 1223 }, 1224 error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`, 1225}, { 1226 data: "c: 0\na: 1\nb: 2\nc: 1\n", 1227 value: struct { 1228 A int 1229 inlineB `yaml:",inline"` 1230 }{ 1231 A: 1, 1232 inlineB: inlineB{ 1233 B: 2, 1234 inlineC: inlineC{ 1235 C: 1, 1236 }, 1237 }, 1238 }, 1239 error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`, 1240}, { 1241 data: "c: 1\na: 1\nb: 2\nc: 3\n", 1242 value: struct { 1243 A int 1244 M map[string]interface{} `yaml:",inline"` 1245 }{ 1246 A: 1, 1247 M: map[string]interface{}{ 1248 "b": 2, 1249 "c": 3, 1250 }, 1251 }, 1252 error: `yaml: unmarshal errors:\n line 4: key "c" already set in map`, 1253}, { 1254 data: "a: 1\n9: 2\nnull: 3\n9: 4", 1255 value: map[interface{}]interface{}{ 1256 "a": 1, 1257 nil: 3, 1258 9: 4, 1259 }, 1260 error: `yaml: unmarshal errors:\n line 4: key 9 already set in map`, 1261}} 1262 1263func (s *S) TestUnmarshalStrict(c *C) { 1264 for i, item := range unmarshalStrictTests { 1265 c.Logf("test %d: %q", i, item.data) 1266 // First test that normal Unmarshal unmarshals to the expected value. 1267 t := reflect.ValueOf(item.value).Type() 1268 value := reflect.New(t) 1269 err := yaml.Unmarshal([]byte(item.data), value.Interface()) 1270 c.Assert(err, Equals, nil) 1271 c.Assert(value.Elem().Interface(), DeepEquals, item.value) 1272 1273 // Then test that UnmarshalStrict fails on the same thing. 1274 t = reflect.ValueOf(item.value).Type() 1275 value = reflect.New(t) 1276 err = yaml.UnmarshalStrict([]byte(item.data), value.Interface()) 1277 c.Assert(err, ErrorMatches, item.error) 1278 } 1279} 1280 1281type textUnmarshaler struct { 1282 S string 1283} 1284 1285func (t *textUnmarshaler) UnmarshalText(s []byte) error { 1286 t.S = string(s) 1287 return nil 1288} 1289 1290func (s *S) TestFuzzCrashers(c *C) { 1291 cases := []string{ 1292 // runtime error: index out of range 1293 "\"\\0\\\r\n", 1294 1295 // should not happen 1296 " 0: [\n] 0", 1297 "? ? \"\n\" 0", 1298 " - {\n000}0", 1299 "0:\n 0: [0\n] 0", 1300 " - \"\n000\"0", 1301 " - \"\n000\"\"", 1302 "0:\n - {\n000}0", 1303 "0:\n - \"\n000\"0", 1304 "0:\n - \"\n000\"\"", 1305 1306 // runtime error: index out of range 1307 " \ufeff\n", 1308 "? \ufeff\n", 1309 "? \ufeff:\n", 1310 "0: \ufeff\n", 1311 "? \ufeff: \ufeff\n", 1312 } 1313 for _, data := range cases { 1314 var v interface{} 1315 _ = yaml.Unmarshal([]byte(data), &v) 1316 } 1317} 1318 1319//var data []byte 1320//func init() { 1321// var err error 1322// data, err = ioutil.ReadFile("/tmp/file.yaml") 1323// if err != nil { 1324// panic(err) 1325// } 1326//} 1327// 1328//func (s *S) BenchmarkUnmarshal(c *C) { 1329// var err error 1330// for i := 0; i < c.N; i++ { 1331// var v map[string]interface{} 1332// err = yaml.Unmarshal(data, &v) 1333// } 1334// if err != nil { 1335// panic(err) 1336// } 1337//} 1338// 1339//func (s *S) BenchmarkMarshal(c *C) { 1340// var v map[string]interface{} 1341// yaml.Unmarshal(data, &v) 1342// c.ResetTimer() 1343// for i := 0; i < c.N; i++ { 1344// yaml.Marshal(&v) 1345// } 1346//} 1347