github.com/trevoraustin/hub@v2.2.0-preview1.0.20141105230840-96d8bfc654cc+incompatible/Godeps/_workspace/src/gopkg.in/yaml.v1/decode_test.go (about) 1 package yaml_test 2 3 import ( 4 . "gopkg.in/check.v1" 5 "gopkg.in/yaml.v1" 6 "math" 7 "reflect" 8 "time" 9 ) 10 11 var unmarshalIntTest = 123 12 13 var unmarshalTests = []struct { 14 data string 15 value interface{} 16 }{ 17 { 18 "", 19 &struct{}{}, 20 }, { 21 "{}", &struct{}{}, 22 }, { 23 "v: hi", 24 map[string]string{"v": "hi"}, 25 }, { 26 "v: hi", map[string]interface{}{"v": "hi"}, 27 }, { 28 "v: true", 29 map[string]string{"v": "true"}, 30 }, { 31 "v: true", 32 map[string]interface{}{"v": true}, 33 }, { 34 "v: 10", 35 map[string]interface{}{"v": 10}, 36 }, { 37 "v: 0b10", 38 map[string]interface{}{"v": 2}, 39 }, { 40 "v: 0xA", 41 map[string]interface{}{"v": 10}, 42 }, { 43 "v: 4294967296", 44 map[string]int64{"v": 4294967296}, 45 }, { 46 "v: 0.1", 47 map[string]interface{}{"v": 0.1}, 48 }, { 49 "v: .1", 50 map[string]interface{}{"v": 0.1}, 51 }, { 52 "v: .Inf", 53 map[string]interface{}{"v": math.Inf(+1)}, 54 }, { 55 "v: -.Inf", 56 map[string]interface{}{"v": math.Inf(-1)}, 57 }, { 58 "v: -10", 59 map[string]interface{}{"v": -10}, 60 }, { 61 "v: -.1", 62 map[string]interface{}{"v": -0.1}, 63 }, 64 65 // Simple values. 66 { 67 "123", 68 &unmarshalIntTest, 69 }, 70 71 // Floats from spec 72 { 73 "canonical: 6.8523e+5", 74 map[string]interface{}{"canonical": 6.8523e+5}, 75 }, { 76 "expo: 685.230_15e+03", 77 map[string]interface{}{"expo": 685.23015e+03}, 78 }, { 79 "fixed: 685_230.15", 80 map[string]interface{}{"fixed": 685230.15}, 81 }, { 82 "neginf: -.inf", 83 map[string]interface{}{"neginf": math.Inf(-1)}, 84 }, { 85 "fixed: 685_230.15", 86 map[string]float64{"fixed": 685230.15}, 87 }, 88 //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 89 //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 90 91 // Bools from spec 92 { 93 "canonical: y", 94 map[string]interface{}{"canonical": true}, 95 }, { 96 "answer: NO", 97 map[string]interface{}{"answer": false}, 98 }, { 99 "logical: True", 100 map[string]interface{}{"logical": true}, 101 }, { 102 "option: on", 103 map[string]interface{}{"option": true}, 104 }, { 105 "option: on", 106 map[string]bool{"option": true}, 107 }, 108 // Ints from spec 109 { 110 "canonical: 685230", 111 map[string]interface{}{"canonical": 685230}, 112 }, { 113 "decimal: +685_230", 114 map[string]interface{}{"decimal": 685230}, 115 }, { 116 "octal: 02472256", 117 map[string]interface{}{"octal": 685230}, 118 }, { 119 "hexa: 0x_0A_74_AE", 120 map[string]interface{}{"hexa": 685230}, 121 }, { 122 "bin: 0b1010_0111_0100_1010_1110", 123 map[string]interface{}{"bin": 685230}, 124 }, { 125 "bin: -0b101010", 126 map[string]interface{}{"bin": -42}, 127 }, { 128 "decimal: +685_230", 129 map[string]int{"decimal": 685230}, 130 }, 131 132 //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 133 134 // Nulls from spec 135 { 136 "empty:", 137 map[string]interface{}{"empty": nil}, 138 }, { 139 "canonical: ~", 140 map[string]interface{}{"canonical": nil}, 141 }, { 142 "english: null", 143 map[string]interface{}{"english": nil}, 144 }, { 145 "~: null key", 146 map[interface{}]string{nil: "null key"}, 147 }, { 148 "empty:", 149 map[string]*bool{"empty": nil}, 150 }, 151 152 // Flow sequence 153 { 154 "seq: [A,B]", 155 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 156 }, { 157 "seq: [A,B,C,]", 158 map[string][]string{"seq": []string{"A", "B", "C"}}, 159 }, { 160 "seq: [A,1,C]", 161 map[string][]string{"seq": []string{"A", "1", "C"}}, 162 }, { 163 "seq: [A,1,C]", 164 map[string][]int{"seq": []int{1}}, 165 }, { 166 "seq: [A,1,C]", 167 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 168 }, 169 // Block sequence 170 { 171 "seq:\n - A\n - B", 172 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 173 }, { 174 "seq:\n - A\n - B\n - C", 175 map[string][]string{"seq": []string{"A", "B", "C"}}, 176 }, { 177 "seq:\n - A\n - 1\n - C", 178 map[string][]string{"seq": []string{"A", "1", "C"}}, 179 }, { 180 "seq:\n - A\n - 1\n - C", 181 map[string][]int{"seq": []int{1}}, 182 }, { 183 "seq:\n - A\n - 1\n - C", 184 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 185 }, 186 187 // Literal block scalar 188 { 189 "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 190 map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, 191 }, 192 193 // Folded block scalar 194 { 195 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 196 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, 197 }, 198 199 // Map inside interface with no type hints. 200 { 201 "a: {b: c}", 202 map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 203 }, 204 205 // Structs and type conversions. 206 { 207 "hello: world", 208 &struct{ Hello string }{"world"}, 209 }, { 210 "a: {b: c}", 211 &struct{ A struct{ B string } }{struct{ B string }{"c"}}, 212 }, { 213 "a: {b: c}", 214 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, 215 }, { 216 "a: {b: c}", 217 &struct{ A map[string]string }{map[string]string{"b": "c"}}, 218 }, { 219 "a: {b: c}", 220 &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, 221 }, { 222 "a:", 223 &struct{ A map[string]string }{}, 224 }, { 225 "a: 1", 226 &struct{ A int }{1}, 227 }, { 228 "a: 1", 229 &struct{ A float64 }{1}, 230 }, { 231 "a: 1.0", 232 &struct{ A int }{1}, 233 }, { 234 "a: 1.0", 235 &struct{ A uint }{1}, 236 }, { 237 "a: [1, 2]", 238 &struct{ A []int }{[]int{1, 2}}, 239 }, { 240 "a: 1", 241 &struct{ B int }{0}, 242 }, { 243 "a: 1", 244 &struct { 245 B int "a" 246 }{1}, 247 }, { 248 "a: y", 249 &struct{ A bool }{true}, 250 }, 251 252 // Some cross type conversions 253 { 254 "v: 42", 255 map[string]uint{"v": 42}, 256 }, { 257 "v: -42", 258 map[string]uint{}, 259 }, { 260 "v: 4294967296", 261 map[string]uint64{"v": 4294967296}, 262 }, { 263 "v: -4294967296", 264 map[string]uint64{}, 265 }, 266 267 // Overflow cases. 268 { 269 "v: 4294967297", 270 map[string]int32{}, 271 }, { 272 "v: 128", 273 map[string]int8{}, 274 }, 275 276 // Quoted values. 277 { 278 "'1': '\"2\"'", 279 map[interface{}]interface{}{"1": "\"2\""}, 280 }, { 281 "v:\n- A\n- 'B\n\n C'\n", 282 map[string][]string{"v": []string{"A", "B\nC"}}, 283 }, 284 285 // Explicit tags. 286 { 287 "v: !!float '1.1'", 288 map[string]interface{}{"v": 1.1}, 289 }, { 290 "v: !!null ''", 291 map[string]interface{}{"v": nil}, 292 }, { 293 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 294 map[string]interface{}{"v": 1}, 295 }, 296 297 // Anchors and aliases. 298 { 299 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 300 &struct{ A, B, C, D int }{1, 2, 1, 2}, 301 }, { 302 "a: &a {c: 1}\nb: *a", 303 &struct { 304 A, B struct { 305 C int 306 } 307 }{struct{ C int }{1}, struct{ C int }{1}}, 308 }, { 309 "a: &a [1, 2]\nb: *a", 310 &struct{ B []int }{[]int{1, 2}}, 311 }, 312 313 // Bug #1133337 314 { 315 "foo: ''", 316 map[string]*string{"foo": new(string)}, 317 }, { 318 "foo: null", 319 map[string]string{}, 320 }, 321 322 // Ignored field 323 { 324 "a: 1\nb: 2\n", 325 &struct { 326 A int 327 B int "-" 328 }{1, 0}, 329 }, 330 331 // Bug #1191981 332 { 333 "" + 334 "%YAML 1.1\n" + 335 "--- !!str\n" + 336 `"Generic line break (no glyph)\n\` + "\n" + 337 ` Generic line break (glyphed)\n\` + "\n" + 338 ` Line separator\u2028\` + "\n" + 339 ` Paragraph separator\u2029"` + "\n", 340 "" + 341 "Generic line break (no glyph)\n" + 342 "Generic line break (glyphed)\n" + 343 "Line separator\u2028Paragraph separator\u2029", 344 }, 345 346 // Struct inlining 347 { 348 "a: 1\nb: 2\nc: 3\n", 349 &struct { 350 A int 351 C inlineB `yaml:",inline"` 352 }{1, inlineB{2, inlineC{3}}}, 353 }, 354 355 // bug 1243827 356 { 357 "a: -b_c", 358 map[string]interface{}{"a": "-b_c"}, 359 }, 360 { 361 "a: +b_c", 362 map[string]interface{}{"a": "+b_c"}, 363 }, 364 { 365 "a: 50cent_of_dollar", 366 map[string]interface{}{"a": "50cent_of_dollar"}, 367 }, 368 369 // Duration 370 { 371 "a: 3s", 372 map[string]time.Duration{"a": 3 * time.Second}, 373 }, 374 375 // Issue #24. 376 { 377 "a: <foo>", 378 map[string]string{"a": "<foo>"}, 379 }, 380 } 381 382 type inlineB struct { 383 B int 384 inlineC `yaml:",inline"` 385 } 386 387 type inlineC struct { 388 C int 389 } 390 391 func (s *S) TestUnmarshal(c *C) { 392 for i, item := range unmarshalTests { 393 t := reflect.ValueOf(item.value).Type() 394 var value interface{} 395 switch t.Kind() { 396 case reflect.Map: 397 value = reflect.MakeMap(t).Interface() 398 case reflect.String: 399 t := reflect.ValueOf(item.value).Type() 400 v := reflect.New(t) 401 value = v.Interface() 402 default: 403 pt := reflect.ValueOf(item.value).Type() 404 pv := reflect.New(pt.Elem()) 405 value = pv.Interface() 406 } 407 err := yaml.Unmarshal([]byte(item.data), value) 408 c.Assert(err, IsNil, Commentf("Item #%d", i)) 409 if t.Kind() == reflect.String { 410 c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i)) 411 } else { 412 c.Assert(value, DeepEquals, item.value, Commentf("Item #%d", i)) 413 } 414 } 415 } 416 417 func (s *S) TestUnmarshalNaN(c *C) { 418 value := map[string]interface{}{} 419 err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) 420 c.Assert(err, IsNil) 421 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 422 } 423 424 var unmarshalErrorTests = []struct { 425 data, error string 426 }{ 427 {"v: !!float 'error'", "YAML error: Can't decode !!str 'error' as a !!float"}, 428 {"v: [A,", "YAML error: line 1: did not find expected node content"}, 429 {"v:\n- [A,", "YAML error: line 2: did not find expected node content"}, 430 {"a: *b\n", "YAML error: Unknown anchor 'b' referenced"}, 431 {"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"}, 432 {"value: -", "YAML error: block sequence entries are not allowed in this context"}, 433 } 434 435 func (s *S) TestUnmarshalErrors(c *C) { 436 for _, item := range unmarshalErrorTests { 437 var value interface{} 438 err := yaml.Unmarshal([]byte(item.data), &value) 439 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 440 } 441 } 442 443 var setterTests = []struct { 444 data, tag string 445 value interface{} 446 }{ 447 {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 448 {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 449 {"_: 10", "!!int", 10}, 450 {"_: null", "!!null", nil}, 451 {`_: BAR!`, "!!str", "BAR!"}, 452 {`_: "BAR!"`, "!!str", "BAR!"}, 453 {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 454 } 455 456 var setterResult = map[int]bool{} 457 458 type typeWithSetter struct { 459 tag string 460 value interface{} 461 } 462 463 func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) { 464 o.tag = tag 465 o.value = value 466 if i, ok := value.(int); ok { 467 if result, ok := setterResult[i]; ok { 468 return result 469 } 470 } 471 return true 472 } 473 474 type setterPointerType struct { 475 Field *typeWithSetter "_" 476 } 477 478 type setterValueType struct { 479 Field typeWithSetter "_" 480 } 481 482 func (s *S) TestUnmarshalWithPointerSetter(c *C) { 483 for _, item := range setterTests { 484 obj := &setterPointerType{} 485 err := yaml.Unmarshal([]byte(item.data), obj) 486 c.Assert(err, IsNil) 487 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 488 c.Assert(obj.Field.tag, Equals, item.tag) 489 c.Assert(obj.Field.value, DeepEquals, item.value) 490 } 491 } 492 493 func (s *S) TestUnmarshalWithValueSetter(c *C) { 494 for _, item := range setterTests { 495 obj := &setterValueType{} 496 err := yaml.Unmarshal([]byte(item.data), obj) 497 c.Assert(err, IsNil) 498 c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) 499 c.Assert(obj.Field.tag, Equals, item.tag) 500 c.Assert(obj.Field.value, DeepEquals, item.value) 501 } 502 } 503 504 func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) { 505 obj := &typeWithSetter{} 506 err := yaml.Unmarshal([]byte(setterTests[0].data), obj) 507 c.Assert(err, IsNil) 508 c.Assert(obj.tag, Equals, setterTests[0].tag) 509 value, ok := obj.value.(map[interface{}]interface{}) 510 c.Assert(ok, Equals, true) 511 c.Assert(value["_"], DeepEquals, setterTests[0].value) 512 } 513 514 func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) { 515 setterResult[2] = false 516 setterResult[4] = false 517 defer func() { 518 delete(setterResult, 2) 519 delete(setterResult, 4) 520 }() 521 522 m := map[string]*typeWithSetter{} 523 data := `{abc: 1, def: 2, ghi: 3, jkl: 4}` 524 err := yaml.Unmarshal([]byte(data), m) 525 c.Assert(err, IsNil) 526 c.Assert(m["abc"], NotNil) 527 c.Assert(m["def"], IsNil) 528 c.Assert(m["ghi"], NotNil) 529 c.Assert(m["jkl"], IsNil) 530 531 c.Assert(m["abc"].value, Equals, 1) 532 c.Assert(m["ghi"].value, Equals, 3) 533 } 534 535 // From http://yaml.org/type/merge.html 536 var mergeTests = ` 537 anchors: 538 - &CENTER { "x": 1, "y": 2 } 539 - &LEFT { "x": 0, "y": 2 } 540 - &BIG { "r": 10 } 541 - &SMALL { "r": 1 } 542 543 # All the following maps are equal: 544 545 plain: 546 # Explicit keys 547 "x": 1 548 "y": 2 549 "r": 10 550 label: center/big 551 552 mergeOne: 553 # Merge one map 554 << : *CENTER 555 "r": 10 556 label: center/big 557 558 mergeMultiple: 559 # Merge multiple maps 560 << : [ *CENTER, *BIG ] 561 label: center/big 562 563 override: 564 # Override 565 << : [ *BIG, *LEFT, *SMALL ] 566 "x": 1 567 label: center/big 568 569 shortTag: 570 # Explicit short merge tag 571 !!merge "<<" : [ *CENTER, *BIG ] 572 label: center/big 573 574 longTag: 575 # Explicit merge long tag 576 !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ] 577 label: center/big 578 579 inlineMap: 580 # Inlined map 581 << : {"x": 1, "y": 2, "r": 10} 582 label: center/big 583 584 inlineSequenceMap: 585 # Inlined map in sequence 586 << : [ *CENTER, {"r": 10} ] 587 label: center/big 588 ` 589 590 func (s *S) TestMerge(c *C) { 591 var want = map[interface{}]interface{}{ 592 "x": 1, 593 "y": 2, 594 "r": 10, 595 "label": "center/big", 596 } 597 598 var m map[string]interface{} 599 err := yaml.Unmarshal([]byte(mergeTests), &m) 600 c.Assert(err, IsNil) 601 for name, test := range m { 602 if name == "anchors" { 603 continue 604 } 605 c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) 606 } 607 } 608 609 func (s *S) TestMergeStruct(c *C) { 610 type Data struct { 611 X, Y, R int 612 Label string 613 } 614 want := Data{1, 2, 10, "center/big"} 615 616 var m map[string]Data 617 err := yaml.Unmarshal([]byte(mergeTests), &m) 618 c.Assert(err, IsNil) 619 for name, test := range m { 620 if name == "anchors" { 621 continue 622 } 623 c.Assert(test, Equals, want, Commentf("test %q failed", name)) 624 } 625 } 626 627 //var data []byte 628 //func init() { 629 // var err error 630 // data, err = ioutil.ReadFile("/tmp/file.yaml") 631 // if err != nil { 632 // panic(err) 633 // } 634 //} 635 // 636 //func (s *S) BenchmarkUnmarshal(c *C) { 637 // var err error 638 // for i := 0; i < c.N; i++ { 639 // var v map[string]interface{} 640 // err = yaml.Unmarshal(data, &v) 641 // } 642 // if err != nil { 643 // panic(err) 644 // } 645 //} 646 // 647 //func (s *S) BenchmarkMarshal(c *C) { 648 // var v map[string]interface{} 649 // yaml.Unmarshal(data, &v) 650 // c.ResetTimer() 651 // for i := 0; i < c.N; i++ { 652 // yaml.Marshal(&v) 653 // } 654 //}