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