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 ` 727a: 728 b 729b: 730 ? a 731 : a`, 732 &M{"a": "b", 733 "b": M{ 734 "a": "a", 735 }}, 736 }, 737} 738 739type M map[interface{}]interface{} 740 741type inlineB struct { 742 B int 743 inlineC `yaml:",inline"` 744} 745 746type inlineC struct { 747 C int 748} 749 750func (s *S) TestUnmarshal(c *C) { 751 for i, item := range unmarshalTests { 752 c.Logf("test %d: %q", i, item.data) 753 t := reflect.ValueOf(item.value).Type() 754 value := reflect.New(t) 755 err := yaml.Unmarshal([]byte(item.data), value.Interface()) 756 if _, ok := err.(*yaml.TypeError); !ok { 757 c.Assert(err, IsNil) 758 } 759 c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err)) 760 } 761} 762 763// TODO(v3): This test should also work when unmarshaling onto an interface{}. 764func (s *S) TestUnmarshalFullTimestamp(c *C) { 765 // Full timestamp in same format as encoded. This is confirmed to be 766 // properly decoded by Python as a timestamp as well. 767 var str = "2015-02-24T18:19:39.123456789-03:00" 768 var t time.Time 769 err := yaml.Unmarshal([]byte(str), &t) 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 775func (s *S) TestDecoderSingleDocument(c *C) { 776 // Test that Decoder.Decode works as expected on 777 // all the unmarshal tests. 778 for i, item := range unmarshalTests { 779 c.Logf("test %d: %q", i, item.data) 780 if item.data == "" { 781 // Behaviour differs when there's no YAML. 782 continue 783 } 784 t := reflect.ValueOf(item.value).Type() 785 value := reflect.New(t) 786 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface()) 787 if _, ok := err.(*yaml.TypeError); !ok { 788 c.Assert(err, IsNil) 789 } 790 c.Assert(value.Elem().Interface(), DeepEquals, item.value) 791 } 792} 793 794var decoderTests = []struct { 795 data string 796 values []interface{} 797}{{ 798 "", 799 nil, 800}, { 801 "a: b", 802 []interface{}{ 803 map[interface{}]interface{}{"a": "b"}, 804 }, 805}, { 806 "---\na: b\n...\n", 807 []interface{}{ 808 map[interface{}]interface{}{"a": "b"}, 809 }, 810}, { 811 "---\n'hello'\n...\n---\ngoodbye\n...\n", 812 []interface{}{ 813 "hello", 814 "goodbye", 815 }, 816}} 817 818func (s *S) TestDecoder(c *C) { 819 for i, item := range decoderTests { 820 c.Logf("test %d: %q", i, item.data) 821 var values []interface{} 822 dec := yaml.NewDecoder(strings.NewReader(item.data)) 823 for { 824 var value interface{} 825 err := dec.Decode(&value) 826 if err == io.EOF { 827 break 828 } 829 c.Assert(err, IsNil) 830 values = append(values, value) 831 } 832 c.Assert(values, DeepEquals, item.values) 833 } 834} 835 836type errReader struct{} 837 838func (errReader) Read([]byte) (int, error) { 839 return 0, errors.New("some read error") 840} 841 842func (s *S) TestDecoderReadError(c *C) { 843 err := yaml.NewDecoder(errReader{}).Decode(&struct{}{}) 844 c.Assert(err, ErrorMatches, `yaml: input error: some read error`) 845} 846 847func (s *S) TestUnmarshalNaN(c *C) { 848 value := map[string]interface{}{} 849 err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) 850 c.Assert(err, IsNil) 851 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 852} 853 854var unmarshalErrorTests = []struct { 855 data, error string 856}{ 857 {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, 858 {"v: [A,", "yaml: line 1: did not find expected node content"}, 859 {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, 860 {"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"}, 861 {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, 862 {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, 863 {"a: &x null\n<<:\n- *x\nb: &x {}\n", `yaml: map merge requires map or sequence of maps as the value`}, // Issue #529. 864 {"value: -", "yaml: block sequence entries are not allowed in this context"}, 865 {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, 866 {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, 867 {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, 868 {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`}, 869 {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"}, 870 {"a:\n 1:\nb\n 2:", ".*could not find expected ':'"}, 871 { 872 "a: &a [00,00,00,00,00,00,00,00,00]\n" + 873 "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" + 874 "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" + 875 "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" + 876 "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" + 877 "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" + 878 "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" + 879 "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" + 880 "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n", 881 "yaml: document contains excessive aliasing", 882 }, 883} 884 885func (s *S) TestUnmarshalErrors(c *C) { 886 for i, item := range unmarshalErrorTests { 887 c.Logf("test %d: %q", i, item.data) 888 var value interface{} 889 err := yaml.Unmarshal([]byte(item.data), &value) 890 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 891 892 if strings.Contains(item.data, ":") { 893 // Repeat test with typed value. 894 var value map[string]interface{} 895 err := yaml.Unmarshal([]byte(item.data), &value) 896 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 897 } 898 } 899} 900 901func (s *S) TestDecoderErrors(c *C) { 902 for _, item := range unmarshalErrorTests { 903 var value interface{} 904 err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value) 905 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 906 } 907} 908 909var unmarshalerTests = []struct { 910 data, tag string 911 value interface{} 912}{ 913 {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 914 {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 915 {"_: 10", "!!int", 10}, 916 {"_: null", "!!null", nil}, 917 {`_: BAR!`, "!!str", "BAR!"}, 918 {`_: "BAR!"`, "!!str", "BAR!"}, 919 {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 920 {`_: ""`, "!!str", ""}, 921} 922 923var unmarshalerResult = map[int]error{} 924 925type unmarshalerType struct { 926 value interface{} 927} 928 929func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { 930 if err := unmarshal(&o.value); err != nil { 931 return err 932 } 933 if i, ok := o.value.(int); ok { 934 if result, ok := unmarshalerResult[i]; ok { 935 return result 936 } 937 } 938 return nil 939} 940 941type unmarshalerPointer struct { 942 Field *unmarshalerType "_" 943} 944 945type unmarshalerValue struct { 946 Field unmarshalerType "_" 947} 948 949func (s *S) TestUnmarshalerPointerField(c *C) { 950 for _, item := range unmarshalerTests { 951 obj := &unmarshalerPointer{} 952 err := yaml.Unmarshal([]byte(item.data), obj) 953 c.Assert(err, IsNil) 954 if item.value == nil { 955 c.Assert(obj.Field, IsNil) 956 } else { 957 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 958 c.Assert(obj.Field.value, DeepEquals, item.value) 959 } 960 } 961} 962 963func (s *S) TestUnmarshalerValueField(c *C) { 964 for _, item := range unmarshalerTests { 965 obj := &unmarshalerValue{} 966 err := yaml.Unmarshal([]byte(item.data), obj) 967 c.Assert(err, IsNil) 968 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 969 c.Assert(obj.Field.value, DeepEquals, item.value) 970 } 971} 972 973func (s *S) TestUnmarshalerWholeDocument(c *C) { 974 obj := &unmarshalerType{} 975 err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) 976 c.Assert(err, IsNil) 977 value, ok := obj.value.(map[interface{}]interface{}) 978 c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) 979 c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) 980} 981 982func (s *S) TestUnmarshalerTypeError(c *C) { 983 unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} 984 unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} 985 defer func() { 986 delete(unmarshalerResult, 2) 987 delete(unmarshalerResult, 4) 988 }() 989 990 type T struct { 991 Before int 992 After int 993 M map[string]*unmarshalerType 994 } 995 var v T 996 data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` 997 err := yaml.Unmarshal([]byte(data), &v) 998 c.Assert(err, ErrorMatches, ""+ 999 "yaml: unmarshal errors:\n"+ 1000 " line 1: cannot unmarshal !!str `A` into int\n"+ 1001 " foo\n"+ 1002 " bar\n"+ 1003 " line 1: cannot unmarshal !!str `B` into int") 1004 c.Assert(v.M["abc"], NotNil) 1005 c.Assert(v.M["def"], IsNil) 1006 c.Assert(v.M["ghi"], NotNil) 1007 c.Assert(v.M["jkl"], IsNil) 1008 1009 c.Assert(v.M["abc"].value, Equals, 1) 1010 c.Assert(v.M["ghi"].value, Equals, 3) 1011} 1012 1013type proxyTypeError struct{} 1014 1015func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { 1016 var s string 1017 var a int32 1018 var b int64 1019 if err := unmarshal(&s); err != nil { 1020 panic(err) 1021 } 1022 if s == "a" { 1023 if err := unmarshal(&b); err == nil { 1024 panic("should have failed") 1025 } 1026 return unmarshal(&a) 1027 } 1028 if err := unmarshal(&a); err == nil { 1029 panic("should have failed") 1030 } 1031 return unmarshal(&b) 1032} 1033 1034func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { 1035 type T struct { 1036 Before int 1037 After int 1038 M map[string]*proxyTypeError 1039 } 1040 var v T 1041 data := `{before: A, m: {abc: a, def: b}, after: B}` 1042 err := yaml.Unmarshal([]byte(data), &v) 1043 c.Assert(err, ErrorMatches, ""+ 1044 "yaml: unmarshal errors:\n"+ 1045 " line 1: cannot unmarshal !!str `A` into int\n"+ 1046 " line 1: cannot unmarshal !!str `a` into int32\n"+ 1047 " line 1: cannot unmarshal !!str `b` into int64\n"+ 1048 " line 1: cannot unmarshal !!str `B` into int") 1049} 1050 1051type failingUnmarshaler struct{} 1052 1053var failingErr = errors.New("failingErr") 1054 1055func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 1056 return failingErr 1057} 1058 1059func (s *S) TestUnmarshalerError(c *C) { 1060 err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) 1061 c.Assert(err, Equals, failingErr) 1062} 1063 1064type sliceUnmarshaler []int 1065 1066func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 1067 var slice []int 1068 err := unmarshal(&slice) 1069 if err == nil { 1070 *su = slice 1071 return nil 1072 } 1073 1074 var intVal int 1075 err = unmarshal(&intVal) 1076 if err == nil { 1077 *su = []int{intVal} 1078 return nil 1079 } 1080 1081 return err 1082} 1083 1084func (s *S) TestUnmarshalerRetry(c *C) { 1085 var su sliceUnmarshaler 1086 err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) 1087 c.Assert(err, IsNil) 1088 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) 1089 1090 err = yaml.Unmarshal([]byte("1"), &su) 1091 c.Assert(err, IsNil) 1092 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) 1093} 1094 1095// From http://yaml.org/type/merge.html 1096var mergeTests = ` 1097anchors: 1098 list: 1099 - &CENTER { "x": 1, "y": 2 } 1100 - &LEFT { "x": 0, "y": 2 } 1101 - &BIG { "r": 10 } 1102 - &SMALL { "r": 1 } 1103 1104# All the following maps are equal: 1105 1106plain: 1107 # Explicit keys 1108 "x": 1 1109 "y": 2 1110 "r": 10 1111 label: center/big 1112 1113mergeOne: 1114 # Merge one map 1115 << : *CENTER 1116 "r": 10 1117 label: center/big 1118 1119mergeMultiple: 1120 # Merge multiple maps 1121 << : [ *CENTER, *BIG ] 1122 label: center/big 1123 1124override: 1125 # Override 1126 << : [ *BIG, *LEFT, *SMALL ] 1127 "x": 1 1128 label: center/big 1129 1130shortTag: 1131 # Explicit short merge tag 1132 !!merge "<<" : [ *CENTER, *BIG ] 1133 label: center/big 1134 1135longTag: 1136 # Explicit merge long tag 1137 !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ] 1138 label: center/big 1139 1140inlineMap: 1141 # Inlined map 1142 << : {"x": 1, "y": 2, "r": 10} 1143 label: center/big 1144 1145inlineSequenceMap: 1146 # Inlined map in sequence 1147 << : [ *CENTER, {"r": 10} ] 1148 label: center/big 1149` 1150 1151func (s *S) TestMerge(c *C) { 1152 var want = map[interface{}]interface{}{ 1153 "x": 1, 1154 "y": 2, 1155 "r": 10, 1156 "label": "center/big", 1157 } 1158 1159 var m map[interface{}]interface{} 1160 err := yaml.Unmarshal([]byte(mergeTests), &m) 1161 c.Assert(err, IsNil) 1162 for name, test := range m { 1163 if name == "anchors" { 1164 continue 1165 } 1166 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) 1167 } 1168} 1169 1170func (s *S) TestMergeStruct(c *C) { 1171 type Data struct { 1172 X, Y, R int 1173 Label string 1174 } 1175 want := Data{1, 2, 10, "center/big"} 1176 1177 var m map[string]Data 1178 err := yaml.Unmarshal([]byte(mergeTests), &m) 1179 c.Assert(err, IsNil) 1180 for name, test := range m { 1181 if name == "anchors" { 1182 continue 1183 } 1184 c.Assert(test, Equals, want, Commentf("test %q failed", name)) 1185 } 1186} 1187 1188var unmarshalNullTests = []func() interface{}{ 1189 func() interface{} { var v interface{}; v = "v"; return &v }, 1190 func() interface{} { var s = "s"; return &s }, 1191 func() interface{} { var s = "s"; sptr := &s; return &sptr }, 1192 func() interface{} { var i = 1; return &i }, 1193 func() interface{} { var i = 1; iptr := &i; return &iptr }, 1194 func() interface{} { m := map[string]int{"s": 1}; return &m }, 1195 func() interface{} { m := map[string]int{"s": 1}; return m }, 1196} 1197 1198func (s *S) TestUnmarshalNull(c *C) { 1199 for _, test := range unmarshalNullTests { 1200 item := test() 1201 zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() 1202 err := yaml.Unmarshal([]byte("null"), item) 1203 c.Assert(err, IsNil) 1204 if reflect.TypeOf(item).Kind() == reflect.Map { 1205 c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) 1206 } else { 1207 c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) 1208 } 1209 } 1210} 1211 1212func (s *S) TestUnmarshalSliceOnPreset(c *C) { 1213 // Issue #48. 1214 v := struct{ A []int }{[]int{1}} 1215 yaml.Unmarshal([]byte("a: [2]"), &v) 1216 c.Assert(v.A, DeepEquals, []int{2}) 1217} 1218 1219var unmarshalStrictTests = []struct { 1220 data string 1221 value interface{} 1222 error string 1223}{{ 1224 data: "a: 1\nc: 2\n", 1225 value: struct{ A, B int }{A: 1}, 1226 error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`, 1227}, { 1228 data: "a: 1\nb: 2\na: 3\n", 1229 value: struct{ A, B int }{A: 3, B: 2}, 1230 error: `yaml: unmarshal errors:\n line 3: field a already set in type struct { A int; B int }`, 1231}, { 1232 data: "c: 3\na: 1\nb: 2\nc: 4\n", 1233 value: struct { 1234 A int 1235 inlineB `yaml:",inline"` 1236 }{ 1237 A: 1, 1238 inlineB: inlineB{ 1239 B: 2, 1240 inlineC: inlineC{ 1241 C: 4, 1242 }, 1243 }, 1244 }, 1245 error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`, 1246}, { 1247 data: "c: 0\na: 1\nb: 2\nc: 1\n", 1248 value: struct { 1249 A int 1250 inlineB `yaml:",inline"` 1251 }{ 1252 A: 1, 1253 inlineB: inlineB{ 1254 B: 2, 1255 inlineC: inlineC{ 1256 C: 1, 1257 }, 1258 }, 1259 }, 1260 error: `yaml: unmarshal errors:\n line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`, 1261}, { 1262 data: "c: 1\na: 1\nb: 2\nc: 3\n", 1263 value: struct { 1264 A int 1265 M map[string]interface{} `yaml:",inline"` 1266 }{ 1267 A: 1, 1268 M: map[string]interface{}{ 1269 "b": 2, 1270 "c": 3, 1271 }, 1272 }, 1273 error: `yaml: unmarshal errors:\n line 4: key "c" already set in map`, 1274}, { 1275 data: "a: 1\n9: 2\nnull: 3\n9: 4", 1276 value: map[interface{}]interface{}{ 1277 "a": 1, 1278 nil: 3, 1279 9: 4, 1280 }, 1281 error: `yaml: unmarshal errors:\n line 4: key 9 already set in map`, 1282}} 1283 1284func (s *S) TestUnmarshalStrict(c *C) { 1285 for i, item := range unmarshalStrictTests { 1286 c.Logf("test %d: %q", i, item.data) 1287 // First test that normal Unmarshal unmarshals to the expected value. 1288 t := reflect.ValueOf(item.value).Type() 1289 value := reflect.New(t) 1290 err := yaml.Unmarshal([]byte(item.data), value.Interface()) 1291 c.Assert(err, Equals, nil) 1292 c.Assert(value.Elem().Interface(), DeepEquals, item.value) 1293 1294 // Then test that UnmarshalStrict fails on the same thing. 1295 t = reflect.ValueOf(item.value).Type() 1296 value = reflect.New(t) 1297 err = yaml.UnmarshalStrict([]byte(item.data), value.Interface()) 1298 c.Assert(err, ErrorMatches, item.error) 1299 } 1300} 1301 1302type textUnmarshaler struct { 1303 S string 1304} 1305 1306func (t *textUnmarshaler) UnmarshalText(s []byte) error { 1307 t.S = string(s) 1308 return nil 1309} 1310 1311func (s *S) TestFuzzCrashers(c *C) { 1312 cases := []string{ 1313 // runtime error: index out of range 1314 "\"\\0\\\r\n", 1315 1316 // should not happen 1317 " 0: [\n] 0", 1318 "? ? \"\n\" 0", 1319 " - {\n000}0", 1320 "0:\n 0: [0\n] 0", 1321 " - \"\n000\"0", 1322 " - \"\n000\"\"", 1323 "0:\n - {\n000}0", 1324 "0:\n - \"\n000\"0", 1325 "0:\n - \"\n000\"\"", 1326 1327 // runtime error: index out of range 1328 " \ufeff\n", 1329 "? \ufeff\n", 1330 "? \ufeff:\n", 1331 "0: \ufeff\n", 1332 "? \ufeff: \ufeff\n", 1333 } 1334 for _, data := range cases { 1335 var v interface{} 1336 _ = yaml.Unmarshal([]byte(data), &v) 1337 } 1338} 1339 1340//var data []byte 1341//func init() { 1342// var err error 1343// data, err = ioutil.ReadFile("/tmp/file.yaml") 1344// if err != nil { 1345// panic(err) 1346// } 1347//} 1348// 1349//func (s *S) BenchmarkUnmarshal(c *C) { 1350// var err error 1351// for i := 0; i < c.N; i++ { 1352// var v map[string]interface{} 1353// err = yaml.Unmarshal(data, &v) 1354// } 1355// if err != nil { 1356// panic(err) 1357// } 1358//} 1359// 1360//func (s *S) BenchmarkMarshal(c *C) { 1361// var v map[string]interface{} 1362// yaml.Unmarshal(data, &v) 1363// c.ResetTimer() 1364// for i := 0; i < c.N; i++ { 1365// yaml.Marshal(&v) 1366// } 1367//} 1368