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