github.com/mfpierre/corectl@v0.5.6/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go (about) 1 package yaml_test 2 3 import ( 4 "errors" 5 . "gopkg.in/check.v1" 6 "gopkg.in/yaml.v2" 7 "math" 8 "net" 9 "reflect" 10 "strings" 11 "time" 12 ) 13 14 var unmarshalIntTest = 123 15 16 var unmarshalTests = []struct { 17 data string 18 value interface{} 19 }{ 20 { 21 "", 22 &struct{}{}, 23 }, { 24 "{}", &struct{}{}, 25 }, { 26 "v: hi", 27 map[string]string{"v": "hi"}, 28 }, { 29 "v: hi", map[string]interface{}{"v": "hi"}, 30 }, { 31 "v: true", 32 map[string]string{"v": "true"}, 33 }, { 34 "v: true", 35 map[string]interface{}{"v": true}, 36 }, { 37 "v: 10", 38 map[string]interface{}{"v": 10}, 39 }, { 40 "v: 0b10", 41 map[string]interface{}{"v": 2}, 42 }, { 43 "v: 0xA", 44 map[string]interface{}{"v": 10}, 45 }, { 46 "v: 4294967296", 47 map[string]int64{"v": 4294967296}, 48 }, { 49 "v: 0.1", 50 map[string]interface{}{"v": 0.1}, 51 }, { 52 "v: .1", 53 map[string]interface{}{"v": 0.1}, 54 }, { 55 "v: .Inf", 56 map[string]interface{}{"v": math.Inf(+1)}, 57 }, { 58 "v: -.Inf", 59 map[string]interface{}{"v": math.Inf(-1)}, 60 }, { 61 "v: -10", 62 map[string]interface{}{"v": -10}, 63 }, { 64 "v: -.1", 65 map[string]interface{}{"v": -0.1}, 66 }, 67 68 // Simple values. 69 { 70 "123", 71 &unmarshalIntTest, 72 }, 73 74 // Floats from spec 75 { 76 "canonical: 6.8523e+5", 77 map[string]interface{}{"canonical": 6.8523e+5}, 78 }, { 79 "expo: 685.230_15e+03", 80 map[string]interface{}{"expo": 685.23015e+03}, 81 }, { 82 "fixed: 685_230.15", 83 map[string]interface{}{"fixed": 685230.15}, 84 }, { 85 "neginf: -.inf", 86 map[string]interface{}{"neginf": math.Inf(-1)}, 87 }, { 88 "fixed: 685_230.15", 89 map[string]float64{"fixed": 685230.15}, 90 }, 91 //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 92 //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 93 94 // Bools from spec 95 { 96 "canonical: y", 97 map[string]interface{}{"canonical": true}, 98 }, { 99 "answer: NO", 100 map[string]interface{}{"answer": false}, 101 }, { 102 "logical: True", 103 map[string]interface{}{"logical": true}, 104 }, { 105 "option: on", 106 map[string]interface{}{"option": true}, 107 }, { 108 "option: on", 109 map[string]bool{"option": true}, 110 }, 111 // Ints from spec 112 { 113 "canonical: 685230", 114 map[string]interface{}{"canonical": 685230}, 115 }, { 116 "decimal: +685_230", 117 map[string]interface{}{"decimal": 685230}, 118 }, { 119 "octal: 02472256", 120 map[string]interface{}{"octal": 685230}, 121 }, { 122 "hexa: 0x_0A_74_AE", 123 map[string]interface{}{"hexa": 685230}, 124 }, { 125 "bin: 0b1010_0111_0100_1010_1110", 126 map[string]interface{}{"bin": 685230}, 127 }, { 128 "bin: -0b101010", 129 map[string]interface{}{"bin": -42}, 130 }, { 131 "decimal: +685_230", 132 map[string]int{"decimal": 685230}, 133 }, 134 135 //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 136 137 // Nulls from spec 138 { 139 "empty:", 140 map[string]interface{}{"empty": nil}, 141 }, { 142 "canonical: ~", 143 map[string]interface{}{"canonical": nil}, 144 }, { 145 "english: null", 146 map[string]interface{}{"english": nil}, 147 }, { 148 "~: null key", 149 map[interface{}]string{nil: "null key"}, 150 }, { 151 "empty:", 152 map[string]*bool{"empty": nil}, 153 }, 154 155 // Flow sequence 156 { 157 "seq: [A,B]", 158 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 159 }, { 160 "seq: [A,B,C,]", 161 map[string][]string{"seq": []string{"A", "B", "C"}}, 162 }, { 163 "seq: [A,1,C]", 164 map[string][]string{"seq": []string{"A", "1", "C"}}, 165 }, { 166 "seq: [A,1,C]", 167 map[string][]int{"seq": []int{1}}, 168 }, { 169 "seq: [A,1,C]", 170 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 171 }, 172 // Block sequence 173 { 174 "seq:\n - A\n - B", 175 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 176 }, { 177 "seq:\n - A\n - B\n - C", 178 map[string][]string{"seq": []string{"A", "B", "C"}}, 179 }, { 180 "seq:\n - A\n - 1\n - C", 181 map[string][]string{"seq": []string{"A", "1", "C"}}, 182 }, { 183 "seq:\n - A\n - 1\n - C", 184 map[string][]int{"seq": []int{1}}, 185 }, { 186 "seq:\n - A\n - 1\n - C", 187 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 188 }, 189 190 // Literal block scalar 191 { 192 "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 193 map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, 194 }, 195 196 // Folded block scalar 197 { 198 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 199 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, 200 }, 201 202 // Map inside interface with no type hints. 203 { 204 "a: {b: c}", 205 map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 206 }, 207 208 // Structs and type conversions. 209 { 210 "hello: world", 211 &struct{ Hello string }{"world"}, 212 }, { 213 "a: {b: c}", 214 &struct{ A struct{ B string } }{struct{ B string }{"c"}}, 215 }, { 216 "a: {b: c}", 217 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, 218 }, { 219 "a: {b: c}", 220 &struct{ A map[string]string }{map[string]string{"b": "c"}}, 221 }, { 222 "a: {b: c}", 223 &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, 224 }, { 225 "a:", 226 &struct{ A map[string]string }{}, 227 }, { 228 "a: 1", 229 &struct{ A int }{1}, 230 }, { 231 "a: 1", 232 &struct{ A float64 }{1}, 233 }, { 234 "a: 1.0", 235 &struct{ A int }{1}, 236 }, { 237 "a: 1.0", 238 &struct{ A uint }{1}, 239 }, { 240 "a: [1, 2]", 241 &struct{ A []int }{[]int{1, 2}}, 242 }, { 243 "a: 1", 244 &struct{ B int }{0}, 245 }, { 246 "a: 1", 247 &struct { 248 B int "a" 249 }{1}, 250 }, { 251 "a: y", 252 &struct{ A bool }{true}, 253 }, 254 255 // Some cross type conversions 256 { 257 "v: 42", 258 map[string]uint{"v": 42}, 259 }, { 260 "v: -42", 261 map[string]uint{}, 262 }, { 263 "v: 4294967296", 264 map[string]uint64{"v": 4294967296}, 265 }, { 266 "v: -4294967296", 267 map[string]uint64{}, 268 }, 269 270 // int 271 { 272 "int_max: 2147483647", 273 map[string]int{"int_max": math.MaxInt32}, 274 }, 275 { 276 "int_min: -2147483648", 277 map[string]int{"int_min": math.MinInt32}, 278 }, 279 { 280 "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 281 map[string]int{}, 282 }, 283 284 // int64 285 { 286 "int64_max: 9223372036854775807", 287 map[string]int64{"int64_max": math.MaxInt64}, 288 }, 289 { 290 "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", 291 map[string]int64{"int64_max_base2": math.MaxInt64}, 292 }, 293 { 294 "int64_min: -9223372036854775808", 295 map[string]int64{"int64_min": math.MinInt64}, 296 }, 297 { 298 "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", 299 map[string]int64{"int64_neg_base2": -math.MaxInt64}, 300 }, 301 { 302 "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 303 map[string]int64{}, 304 }, 305 306 // uint 307 { 308 "uint_min: 0", 309 map[string]uint{"uint_min": 0}, 310 }, 311 { 312 "uint_max: 4294967295", 313 map[string]uint{"uint_max": math.MaxUint32}, 314 }, 315 { 316 "uint_underflow: -1", 317 map[string]uint{}, 318 }, 319 320 // uint64 321 { 322 "uint64_min: 0", 323 map[string]uint{"uint64_min": 0}, 324 }, 325 { 326 "uint64_max: 18446744073709551615", 327 map[string]uint64{"uint64_max": math.MaxUint64}, 328 }, 329 { 330 "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", 331 map[string]uint64{"uint64_max_base2": math.MaxUint64}, 332 }, 333 { 334 "uint64_maxint64: 9223372036854775807", 335 map[string]uint64{"uint64_maxint64": math.MaxInt64}, 336 }, 337 { 338 "uint64_underflow: -1", 339 map[string]uint64{}, 340 }, 341 342 // float32 343 { 344 "float32_max: 3.40282346638528859811704183484516925440e+38", 345 map[string]float32{"float32_max": math.MaxFloat32}, 346 }, 347 { 348 "float32_nonzero: 1.401298464324817070923729583289916131280e-45", 349 map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, 350 }, 351 { 352 "float32_maxuint64: 18446744073709551615", 353 map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, 354 }, 355 { 356 "float32_maxuint64+1: 18446744073709551616", 357 map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, 358 }, 359 360 // float64 361 { 362 "float64_max: 1.797693134862315708145274237317043567981e+308", 363 map[string]float64{"float64_max": math.MaxFloat64}, 364 }, 365 { 366 "float64_nonzero: 4.940656458412465441765687928682213723651e-324", 367 map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, 368 }, 369 { 370 "float64_maxuint64: 18446744073709551615", 371 map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, 372 }, 373 { 374 "float64_maxuint64+1: 18446744073709551616", 375 map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, 376 }, 377 378 // Overflow cases. 379 { 380 "v: 4294967297", 381 map[string]int32{}, 382 }, { 383 "v: 128", 384 map[string]int8{}, 385 }, 386 387 // Quoted values. 388 { 389 "'1': '\"2\"'", 390 map[interface{}]interface{}{"1": "\"2\""}, 391 }, { 392 "v:\n- A\n- 'B\n\n C'\n", 393 map[string][]string{"v": []string{"A", "B\nC"}}, 394 }, 395 396 // Explicit tags. 397 { 398 "v: !!float '1.1'", 399 map[string]interface{}{"v": 1.1}, 400 }, { 401 "v: !!null ''", 402 map[string]interface{}{"v": nil}, 403 }, { 404 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 405 map[string]interface{}{"v": 1}, 406 }, 407 408 // Anchors and aliases. 409 { 410 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 411 &struct{ A, B, C, D int }{1, 2, 1, 2}, 412 }, { 413 "a: &a {c: 1}\nb: *a", 414 &struct { 415 A, B struct { 416 C int 417 } 418 }{struct{ C int }{1}, struct{ C int }{1}}, 419 }, { 420 "a: &a [1, 2]\nb: *a", 421 &struct{ B []int }{[]int{1, 2}}, 422 }, { 423 "b: *a\na: &a {c: 1}", 424 &struct { 425 A, B struct { 426 C int 427 } 428 }{struct{ C int }{1}, struct{ C int }{1}}, 429 }, 430 431 // Bug #1133337 432 { 433 "foo: ''", 434 map[string]*string{"foo": new(string)}, 435 }, { 436 "foo: null", 437 map[string]string{"foo": ""}, 438 }, { 439 "foo: null", 440 map[string]interface{}{"foo": nil}, 441 }, 442 443 // Ignored field 444 { 445 "a: 1\nb: 2\n", 446 &struct { 447 A int 448 B int "-" 449 }{1, 0}, 450 }, 451 452 // Bug #1191981 453 { 454 "" + 455 "%YAML 1.1\n" + 456 "--- !!str\n" + 457 `"Generic line break (no glyph)\n\` + "\n" + 458 ` Generic line break (glyphed)\n\` + "\n" + 459 ` Line separator\u2028\` + "\n" + 460 ` Paragraph separator\u2029"` + "\n", 461 "" + 462 "Generic line break (no glyph)\n" + 463 "Generic line break (glyphed)\n" + 464 "Line separator\u2028Paragraph separator\u2029", 465 }, 466 467 // Struct inlining 468 { 469 "a: 1\nb: 2\nc: 3\n", 470 &struct { 471 A int 472 C inlineB `yaml:",inline"` 473 }{1, inlineB{2, inlineC{3}}}, 474 }, 475 476 // Map inlining 477 { 478 "a: 1\nb: 2\nc: 3\n", 479 &struct { 480 A int 481 C map[string]int `yaml:",inline"` 482 }{1, map[string]int{"b": 2, "c": 3}}, 483 }, 484 485 // bug 1243827 486 { 487 "a: -b_c", 488 map[string]interface{}{"a": "-b_c"}, 489 }, 490 { 491 "a: +b_c", 492 map[string]interface{}{"a": "+b_c"}, 493 }, 494 { 495 "a: 50cent_of_dollar", 496 map[string]interface{}{"a": "50cent_of_dollar"}, 497 }, 498 499 // Duration 500 { 501 "a: 3s", 502 map[string]time.Duration{"a": 3 * time.Second}, 503 }, 504 505 // Issue #24. 506 { 507 "a: <foo>", 508 map[string]string{"a": "<foo>"}, 509 }, 510 511 // Base 60 floats are obsolete and unsupported. 512 { 513 "a: 1:1\n", 514 map[string]string{"a": "1:1"}, 515 }, 516 517 // Binary data. 518 { 519 "a: !!binary gIGC\n", 520 map[string]string{"a": "\x80\x81\x82"}, 521 }, { 522 "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 523 map[string]string{"a": strings.Repeat("\x90", 54)}, 524 }, { 525 "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", 526 map[string]string{"a": strings.Repeat("\x00", 52)}, 527 }, 528 529 // Ordered maps. 530 { 531 "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", 532 &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, 533 }, 534 535 // Issue #39. 536 { 537 "a:\n b:\n c: d\n", 538 map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}}, 539 }, 540 541 // Custom map type. 542 { 543 "a: {b: c}", 544 M{"a": M{"b": "c"}}, 545 }, 546 547 // Support encoding.TextUnmarshaler. 548 { 549 "a: 1.2.3.4\n", 550 map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, 551 }, 552 { 553 "a: 2015-02-24T18:19:39Z\n", 554 map[string]time.Time{"a": time.Unix(1424801979, 0)}, 555 }, 556 557 // Encode empty lists as zero-length slices. 558 { 559 "a: []", 560 &struct{ A []int }{[]int{}}, 561 }, 562 563 // UTF-16-LE 564 { 565 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", 566 M{"ñoño": "very yes"}, 567 }, 568 // UTF-16-LE with surrogate. 569 { 570 "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", 571 M{"ñoño": "very yes 🟔"}, 572 }, 573 574 // UTF-16-BE 575 { 576 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", 577 M{"ñoño": "very yes"}, 578 }, 579 // UTF-16-BE with surrogate. 580 { 581 "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", 582 M{"ñoño": "very yes 🟔"}, 583 }, 584 } 585 586 type M map[interface{}]interface{} 587 588 type inlineB struct { 589 B int 590 inlineC `yaml:",inline"` 591 } 592 593 type inlineC struct { 594 C int 595 } 596 597 func (s *S) TestUnmarshal(c *C) { 598 for _, item := range unmarshalTests { 599 t := reflect.ValueOf(item.value).Type() 600 var value interface{} 601 switch t.Kind() { 602 case reflect.Map: 603 value = reflect.MakeMap(t).Interface() 604 case reflect.String: 605 value = reflect.New(t).Interface() 606 case reflect.Ptr: 607 value = reflect.New(t.Elem()).Interface() 608 default: 609 c.Fatalf("missing case for %s", t) 610 } 611 err := yaml.Unmarshal([]byte(item.data), value) 612 if _, ok := err.(*yaml.TypeError); !ok { 613 c.Assert(err, IsNil) 614 } 615 if t.Kind() == reflect.String { 616 c.Assert(*value.(*string), Equals, item.value) 617 } else { 618 c.Assert(value, DeepEquals, item.value) 619 } 620 } 621 } 622 623 func (s *S) TestUnmarshalNaN(c *C) { 624 value := map[string]interface{}{} 625 err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) 626 c.Assert(err, IsNil) 627 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 628 } 629 630 var unmarshalErrorTests = []struct { 631 data, error string 632 }{ 633 {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, 634 {"v: [A,", "yaml: line 1: did not find expected node content"}, 635 {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, 636 {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, 637 {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, 638 {"value: -", "yaml: block sequence entries are not allowed in this context"}, 639 {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, 640 {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, 641 {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, 642 } 643 644 func (s *S) TestUnmarshalErrors(c *C) { 645 for _, item := range unmarshalErrorTests { 646 var value interface{} 647 err := yaml.Unmarshal([]byte(item.data), &value) 648 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 649 } 650 } 651 652 var unmarshalerTests = []struct { 653 data, tag string 654 value interface{} 655 }{ 656 {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 657 {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 658 {"_: 10", "!!int", 10}, 659 {"_: null", "!!null", nil}, 660 {`_: BAR!`, "!!str", "BAR!"}, 661 {`_: "BAR!"`, "!!str", "BAR!"}, 662 {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 663 } 664 665 var unmarshalerResult = map[int]error{} 666 667 type unmarshalerType struct { 668 value interface{} 669 } 670 671 func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { 672 if err := unmarshal(&o.value); err != nil { 673 return err 674 } 675 if i, ok := o.value.(int); ok { 676 if result, ok := unmarshalerResult[i]; ok { 677 return result 678 } 679 } 680 return nil 681 } 682 683 type unmarshalerPointer struct { 684 Field *unmarshalerType "_" 685 } 686 687 type unmarshalerValue struct { 688 Field unmarshalerType "_" 689 } 690 691 func (s *S) TestUnmarshalerPointerField(c *C) { 692 for _, item := range unmarshalerTests { 693 obj := &unmarshalerPointer{} 694 err := yaml.Unmarshal([]byte(item.data), obj) 695 c.Assert(err, IsNil) 696 if item.value == nil { 697 c.Assert(obj.Field, IsNil) 698 } else { 699 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 700 c.Assert(obj.Field.value, DeepEquals, item.value) 701 } 702 } 703 } 704 705 func (s *S) TestUnmarshalerValueField(c *C) { 706 for _, item := range unmarshalerTests { 707 obj := &unmarshalerValue{} 708 err := yaml.Unmarshal([]byte(item.data), obj) 709 c.Assert(err, IsNil) 710 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 711 c.Assert(obj.Field.value, DeepEquals, item.value) 712 } 713 } 714 715 func (s *S) TestUnmarshalerWholeDocument(c *C) { 716 obj := &unmarshalerType{} 717 err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) 718 c.Assert(err, IsNil) 719 value, ok := obj.value.(map[interface{}]interface{}) 720 c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) 721 c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) 722 } 723 724 func (s *S) TestUnmarshalerTypeError(c *C) { 725 unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} 726 unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} 727 defer func() { 728 delete(unmarshalerResult, 2) 729 delete(unmarshalerResult, 4) 730 }() 731 732 type T struct { 733 Before int 734 After int 735 M map[string]*unmarshalerType 736 } 737 var v T 738 data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` 739 err := yaml.Unmarshal([]byte(data), &v) 740 c.Assert(err, ErrorMatches, ""+ 741 "yaml: unmarshal errors:\n"+ 742 " line 1: cannot unmarshal !!str `A` into int\n"+ 743 " foo\n"+ 744 " bar\n"+ 745 " line 1: cannot unmarshal !!str `B` into int") 746 c.Assert(v.M["abc"], NotNil) 747 c.Assert(v.M["def"], IsNil) 748 c.Assert(v.M["ghi"], NotNil) 749 c.Assert(v.M["jkl"], IsNil) 750 751 c.Assert(v.M["abc"].value, Equals, 1) 752 c.Assert(v.M["ghi"].value, Equals, 3) 753 } 754 755 type proxyTypeError struct{} 756 757 func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { 758 var s string 759 var a int32 760 var b int64 761 if err := unmarshal(&s); err != nil { 762 panic(err) 763 } 764 if s == "a" { 765 if err := unmarshal(&b); err == nil { 766 panic("should have failed") 767 } 768 return unmarshal(&a) 769 } 770 if err := unmarshal(&a); err == nil { 771 panic("should have failed") 772 } 773 return unmarshal(&b) 774 } 775 776 func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { 777 type T struct { 778 Before int 779 After int 780 M map[string]*proxyTypeError 781 } 782 var v T 783 data := `{before: A, m: {abc: a, def: b}, after: B}` 784 err := yaml.Unmarshal([]byte(data), &v) 785 c.Assert(err, ErrorMatches, ""+ 786 "yaml: unmarshal errors:\n"+ 787 " line 1: cannot unmarshal !!str `A` into int\n"+ 788 " line 1: cannot unmarshal !!str `a` into int32\n"+ 789 " line 1: cannot unmarshal !!str `b` into int64\n"+ 790 " line 1: cannot unmarshal !!str `B` into int") 791 } 792 793 type failingUnmarshaler struct{} 794 795 var failingErr = errors.New("failingErr") 796 797 func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 798 return failingErr 799 } 800 801 func (s *S) TestUnmarshalerError(c *C) { 802 err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) 803 c.Assert(err, Equals, failingErr) 804 } 805 806 type sliceUnmarshaler []int 807 808 func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { 809 var slice []int 810 err := unmarshal(&slice) 811 if err == nil { 812 *su = slice 813 return nil 814 } 815 816 var intVal int 817 err = unmarshal(&intVal) 818 if err == nil { 819 *su = []int{intVal} 820 return nil 821 } 822 823 return err 824 } 825 826 func (s *S) TestUnmarshalerRetry(c *C) { 827 var su sliceUnmarshaler 828 err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) 829 c.Assert(err, IsNil) 830 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) 831 832 err = yaml.Unmarshal([]byte("1"), &su) 833 c.Assert(err, IsNil) 834 c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) 835 } 836 837 // From http://yaml.org/type/merge.html 838 var mergeTests = ` 839 anchors: 840 list: 841 - &CENTER { "x": 1, "y": 2 } 842 - &LEFT { "x": 0, "y": 2 } 843 - &BIG { "r": 10 } 844 - &SMALL { "r": 1 } 845 846 # All the following maps are equal: 847 848 plain: 849 # Explicit keys 850 "x": 1 851 "y": 2 852 "r": 10 853 label: center/big 854 855 mergeOne: 856 # Merge one map 857 << : *CENTER 858 "r": 10 859 label: center/big 860 861 mergeMultiple: 862 # Merge multiple maps 863 << : [ *CENTER, *BIG ] 864 label: center/big 865 866 override: 867 # Override 868 << : [ *BIG, *LEFT, *SMALL ] 869 "x": 1 870 label: center/big 871 872 shortTag: 873 # Explicit short merge tag 874 !!merge "<<" : [ *CENTER, *BIG ] 875 label: center/big 876 877 longTag: 878 # Explicit merge long tag 879 !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ] 880 label: center/big 881 882 inlineMap: 883 # Inlined map 884 << : {"x": 1, "y": 2, "r": 10} 885 label: center/big 886 887 inlineSequenceMap: 888 # Inlined map in sequence 889 << : [ *CENTER, {"r": 10} ] 890 label: center/big 891 ` 892 893 func (s *S) TestMerge(c *C) { 894 var want = map[interface{}]interface{}{ 895 "x": 1, 896 "y": 2, 897 "r": 10, 898 "label": "center/big", 899 } 900 901 var m map[interface{}]interface{} 902 err := yaml.Unmarshal([]byte(mergeTests), &m) 903 c.Assert(err, IsNil) 904 for name, test := range m { 905 if name == "anchors" { 906 continue 907 } 908 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) 909 } 910 } 911 912 func (s *S) TestMergeStruct(c *C) { 913 type Data struct { 914 X, Y, R int 915 Label string 916 } 917 want := Data{1, 2, 10, "center/big"} 918 919 var m map[string]Data 920 err := yaml.Unmarshal([]byte(mergeTests), &m) 921 c.Assert(err, IsNil) 922 for name, test := range m { 923 if name == "anchors" { 924 continue 925 } 926 c.Assert(test, Equals, want, Commentf("test %q failed", name)) 927 } 928 } 929 930 var unmarshalNullTests = []func() interface{}{ 931 func() interface{} { var v interface{}; v = "v"; return &v }, 932 func() interface{} { var s = "s"; return &s }, 933 func() interface{} { var s = "s"; sptr := &s; return &sptr }, 934 func() interface{} { var i = 1; return &i }, 935 func() interface{} { var i = 1; iptr := &i; return &iptr }, 936 func() interface{} { m := map[string]int{"s": 1}; return &m }, 937 func() interface{} { m := map[string]int{"s": 1}; return m }, 938 } 939 940 func (s *S) TestUnmarshalNull(c *C) { 941 for _, test := range unmarshalNullTests { 942 item := test() 943 zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() 944 err := yaml.Unmarshal([]byte("null"), item) 945 c.Assert(err, IsNil) 946 if reflect.TypeOf(item).Kind() == reflect.Map { 947 c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) 948 } else { 949 c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) 950 } 951 } 952 } 953 954 func (s *S) TestUnmarshalSliceOnPreset(c *C) { 955 // Issue #48. 956 v := struct{ A []int }{[]int{1}} 957 yaml.Unmarshal([]byte("a: [2]"), &v) 958 c.Assert(v.A, DeepEquals, []int{2}) 959 } 960 961 //var data []byte 962 //func init() { 963 // var err error 964 // data, err = ioutil.ReadFile("/tmp/file.yaml") 965 // if err != nil { 966 // panic(err) 967 // } 968 //} 969 // 970 //func (s *S) BenchmarkUnmarshal(c *C) { 971 // var err error 972 // for i := 0; i < c.N; i++ { 973 // var v map[string]interface{} 974 // err = yaml.Unmarshal(data, &v) 975 // } 976 // if err != nil { 977 // panic(err) 978 // } 979 //} 980 // 981 //func (s *S) BenchmarkMarshal(c *C) { 982 // var v map[string]interface{} 983 // yaml.Unmarshal(data, &v) 984 // c.ResetTimer() 985 // for i := 0; i < c.N; i++ { 986 // yaml.Marshal(&v) 987 // } 988 //}