github.com/marinho/drone@v0.2.1-0.20140504195434-d3ba962e89a7/Godeps/_workspace/src/launchpad.net/goyaml/decode_test.go (about) 1 package goyaml_test 2 3 import ( 4 . "launchpad.net/gocheck" 5 "launchpad.net/goyaml" 6 "math" 7 "reflect" 8 ) 9 10 var unmarshalIntTest = 123 11 12 var unmarshalTests = []struct { 13 data string 14 value interface{} 15 }{ 16 { 17 "", 18 &struct{}{}, 19 }, { 20 "{}", &struct{}{}, 21 }, { 22 "v: hi", 23 map[string]string{"v": "hi"}, 24 }, { 25 "v: hi", map[string]interface{}{"v": "hi"}, 26 }, { 27 "v: true", 28 map[string]string{"v": "true"}, 29 }, { 30 "v: true", 31 map[string]interface{}{"v": true}, 32 }, { 33 "v: 10", 34 map[string]interface{}{"v": 10}, 35 }, { 36 "v: 0b10", 37 map[string]interface{}{"v": 2}, 38 }, { 39 "v: 0xA", 40 map[string]interface{}{"v": 10}, 41 }, { 42 "v: 4294967296", 43 map[string]int64{"v": 4294967296}, 44 }, { 45 "v: 0.1", 46 map[string]interface{}{"v": 0.1}, 47 }, { 48 "v: .1", 49 map[string]interface{}{"v": 0.1}, 50 }, { 51 "v: .Inf", 52 map[string]interface{}{"v": math.Inf(+1)}, 53 }, { 54 "v: -.Inf", 55 map[string]interface{}{"v": math.Inf(-1)}, 56 }, { 57 "v: -10", 58 map[string]interface{}{"v": -10}, 59 }, { 60 "v: -.1", 61 map[string]interface{}{"v": -0.1}, 62 }, 63 64 // Simple values. 65 { 66 "123", 67 &unmarshalIntTest, 68 }, 69 70 // Floats from spec 71 { 72 "canonical: 6.8523e+5", 73 map[string]interface{}{"canonical": 6.8523e+5}, 74 }, { 75 "expo: 685.230_15e+03", 76 map[string]interface{}{"expo": 685.23015e+03}, 77 }, { 78 "fixed: 685_230.15", 79 map[string]interface{}{"fixed": 685230.15}, 80 }, { 81 "neginf: -.inf", 82 map[string]interface{}{"neginf": math.Inf(-1)}, 83 }, { 84 "fixed: 685_230.15", 85 map[string]float64{"fixed": 685230.15}, 86 }, 87 //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported 88 //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. 89 90 // Bools from spec 91 { 92 "canonical: y", 93 map[string]interface{}{"canonical": true}, 94 }, { 95 "answer: NO", 96 map[string]interface{}{"answer": false}, 97 }, { 98 "logical: True", 99 map[string]interface{}{"logical": true}, 100 }, { 101 "option: on", 102 map[string]interface{}{"option": true}, 103 }, { 104 "option: on", 105 map[string]bool{"option": true}, 106 }, 107 // Ints from spec 108 { 109 "canonical: 685230", 110 map[string]interface{}{"canonical": 685230}, 111 }, { 112 "decimal: +685_230", 113 map[string]interface{}{"decimal": 685230}, 114 }, { 115 "octal: 02472256", 116 map[string]interface{}{"octal": 685230}, 117 }, { 118 "hexa: 0x_0A_74_AE", 119 map[string]interface{}{"hexa": 685230}, 120 }, { 121 "bin: 0b1010_0111_0100_1010_1110", 122 map[string]interface{}{"bin": 685230}, 123 }, { 124 "bin: -0b101010", 125 map[string]interface{}{"bin": -42}, 126 }, { 127 "decimal: +685_230", 128 map[string]int{"decimal": 685230}, 129 }, 130 131 //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported 132 133 // Nulls from spec 134 { 135 "empty:", 136 map[string]interface{}{"empty": nil}, 137 }, { 138 "canonical: ~", 139 map[string]interface{}{"canonical": nil}, 140 }, { 141 "english: null", 142 map[string]interface{}{"english": nil}, 143 }, { 144 "~: null key", 145 map[interface{}]string{nil: "null key"}, 146 }, { 147 "empty:", 148 map[string]*bool{"empty": nil}, 149 }, 150 151 // Flow sequence 152 { 153 "seq: [A,B]", 154 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 155 }, { 156 "seq: [A,B,C,]", 157 map[string][]string{"seq": []string{"A", "B", "C"}}, 158 }, { 159 "seq: [A,1,C]", 160 map[string][]string{"seq": []string{"A", "1", "C"}}, 161 }, { 162 "seq: [A,1,C]", 163 map[string][]int{"seq": []int{1}}, 164 }, { 165 "seq: [A,1,C]", 166 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 167 }, 168 // Block sequence 169 { 170 "seq:\n - A\n - B", 171 map[string]interface{}{"seq": []interface{}{"A", "B"}}, 172 }, { 173 "seq:\n - A\n - B\n - C", 174 map[string][]string{"seq": []string{"A", "B", "C"}}, 175 }, { 176 "seq:\n - A\n - 1\n - C", 177 map[string][]string{"seq": []string{"A", "1", "C"}}, 178 }, { 179 "seq:\n - A\n - 1\n - C", 180 map[string][]int{"seq": []int{1}}, 181 }, { 182 "seq:\n - A\n - 1\n - C", 183 map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, 184 }, 185 186 // Literal block scalar 187 { 188 "scalar: | # Comment\n\n literal\n\n \ttext\n\n", 189 map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, 190 }, 191 192 // Folded block scalar 193 { 194 "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", 195 map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, 196 }, 197 198 // Map inside interface with no type hints. 199 { 200 "a: {b: c}", 201 map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 202 }, 203 204 // Structs and type conversions. 205 { 206 "hello: world", 207 &struct{ Hello string }{"world"}, 208 }, { 209 "a: {b: c}", 210 &struct{ A struct{ B string } }{struct{ B string }{"c"}}, 211 }, { 212 "a: {b: c}", 213 &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, 214 }, { 215 "a: {b: c}", 216 &struct{ A map[string]string }{map[string]string{"b": "c"}}, 217 }, { 218 "a: {b: c}", 219 &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, 220 }, { 221 "a:", 222 &struct{ A map[string]string }{}, 223 }, { 224 "a: 1", 225 &struct{ A int }{1}, 226 }, { 227 "a: 1", 228 &struct{ A float64 }{1}, 229 }, { 230 "a: 1.0", 231 &struct{ A int }{1}, 232 }, { 233 "a: 1.0", 234 &struct{ A uint }{1}, 235 }, { 236 "a: [1, 2]", 237 &struct{ A []int }{[]int{1, 2}}, 238 }, { 239 "a: 1", 240 &struct{ B int }{0}, 241 }, { 242 "a: 1", 243 &struct { 244 B int "a" 245 }{1}, 246 }, { 247 "a: y", 248 &struct{ A bool }{true}, 249 }, 250 251 // Some cross type conversions 252 { 253 "v: 42", 254 map[string]uint{"v": 42}, 255 }, { 256 "v: -42", 257 map[string]uint{}, 258 }, { 259 "v: 4294967296", 260 map[string]uint64{"v": 4294967296}, 261 }, { 262 "v: -4294967296", 263 map[string]uint64{}, 264 }, 265 266 // Overflow cases. 267 { 268 "v: 4294967297", 269 map[string]int32{}, 270 }, { 271 "v: 128", 272 map[string]int8{}, 273 }, 274 275 // Quoted values. 276 { 277 "'1': '\"2\"'", 278 map[interface{}]interface{}{"1": "\"2\""}, 279 }, { 280 "v:\n- A\n- 'B\n\n C'\n", 281 map[string][]string{"v": []string{"A", "B\nC"}}, 282 }, 283 284 // Explicit tags. 285 { 286 "v: !!float '1.1'", 287 map[string]interface{}{"v": 1.1}, 288 }, { 289 "v: !!null ''", 290 map[string]interface{}{"v": nil}, 291 }, { 292 "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", 293 map[string]interface{}{"v": 1}, 294 }, 295 296 // Anchors and aliases. 297 { 298 "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", 299 &struct{ A, B, C, D int }{1, 2, 1, 2}, 300 }, { 301 "a: &a {c: 1}\nb: *a", 302 &struct { 303 A, B struct { 304 C int 305 } 306 }{struct{ C int }{1}, struct{ C int }{1}}, 307 }, { 308 "a: &a [1, 2]\nb: *a", 309 &struct{ B []int }{[]int{1, 2}}, 310 }, 311 312 // Bug #1133337 313 { 314 "foo: ''", 315 map[string]*string{"foo": new(string)}, 316 }, { 317 "foo: null", 318 map[string]string{}, 319 }, 320 321 // Ignored field 322 { 323 "a: 1\nb: 2\n", 324 &struct { 325 A int 326 B int "-" 327 }{1, 0}, 328 }, 329 330 // Bug #1191981 331 { 332 "" + 333 "%YAML 1.1\n" + 334 "--- !!str\n" + 335 `"Generic line break (no glyph)\n\` + "\n" + 336 ` Generic line break (glyphed)\n\` + "\n" + 337 ` Line separator\u2028\` + "\n" + 338 ` Paragraph separator\u2029"` + "\n", 339 "" + 340 "Generic line break (no glyph)\n" + 341 "Generic line break (glyphed)\n" + 342 "Line separator\u2028Paragraph separator\u2029", 343 }, 344 345 // Struct inlining 346 { 347 "a: 1\nb: 2\nc: 3\n", 348 &struct { 349 A int 350 C inlineB `yaml:",inline"` 351 }{1, inlineB{2, inlineC{3}}}, 352 }, 353 } 354 355 type inlineB struct { 356 B int 357 inlineC `yaml:",inline"` 358 } 359 360 type inlineC struct { 361 C int 362 } 363 364 func (s *S) TestUnmarshal(c *C) { 365 for i, item := range unmarshalTests { 366 t := reflect.ValueOf(item.value).Type() 367 var value interface{} 368 switch t.Kind() { 369 case reflect.Map: 370 value = reflect.MakeMap(t).Interface() 371 case reflect.String: 372 t := reflect.ValueOf(item.value).Type() 373 v := reflect.New(t) 374 value = v.Interface() 375 default: 376 pt := reflect.ValueOf(item.value).Type() 377 pv := reflect.New(pt.Elem()) 378 value = pv.Interface() 379 } 380 err := goyaml.Unmarshal([]byte(item.data), value) 381 c.Assert(err, IsNil, Commentf("Item #%d", i)) 382 if t.Kind() == reflect.String { 383 c.Assert(*value.(*string), Equals, item.value, Commentf("Item #%d", i)) 384 } else { 385 c.Assert(value, DeepEquals, item.value, Commentf("Item #%d", i)) 386 } 387 } 388 } 389 390 func (s *S) TestUnmarshalNaN(c *C) { 391 value := map[string]interface{}{} 392 err := goyaml.Unmarshal([]byte("notanum: .NaN"), &value) 393 c.Assert(err, IsNil) 394 c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) 395 } 396 397 var unmarshalErrorTests = []struct { 398 data, error string 399 }{ 400 {"v: !!float 'error'", "YAML error: Can't decode !!str 'error' as a !!float"}, 401 {"v: [A,", "YAML error: line 1: did not find expected node content"}, 402 {"v:\n- [A,", "YAML error: line 2: did not find expected node content"}, 403 {"a: *b\n", "YAML error: Unknown anchor 'b' referenced"}, 404 {"a: &a\n b: *a\n", "YAML error: Anchor 'a' value contains itself"}, 405 {"value: -", "YAML error: block sequence entries are not allowed in this context"}, 406 } 407 408 func (s *S) TestUnmarshalErrors(c *C) { 409 for _, item := range unmarshalErrorTests { 410 var value interface{} 411 err := goyaml.Unmarshal([]byte(item.data), &value) 412 c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) 413 } 414 } 415 416 var setterTests = []struct { 417 data, tag string 418 value interface{} 419 }{ 420 {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, 421 {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, 422 {"_: 10", "!!int", 10}, 423 {"_: null", "!!null", nil}, 424 {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, 425 } 426 427 var setterResult = map[int]bool{} 428 429 type typeWithSetter struct { 430 tag string 431 value interface{} 432 } 433 434 func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) { 435 o.tag = tag 436 o.value = value 437 if i, ok := value.(int); ok { 438 if result, ok := setterResult[i]; ok { 439 return result 440 } 441 } 442 return true 443 } 444 445 type typeWithSetterField struct { 446 Field *typeWithSetter "_" 447 } 448 449 func (s *S) TestUnmarshalWithSetter(c *C) { 450 for _, item := range setterTests { 451 obj := &typeWithSetterField{} 452 err := goyaml.Unmarshal([]byte(item.data), obj) 453 c.Assert(err, IsNil) 454 c.Assert(obj.Field, NotNil, 455 Commentf("Pointer not initialized (%#v)", item.value)) 456 c.Assert(obj.Field.tag, Equals, item.tag) 457 c.Assert(obj.Field.value, DeepEquals, item.value) 458 } 459 } 460 461 func (s *S) TestUnmarshalWholeDocumentWithSetter(c *C) { 462 obj := &typeWithSetter{} 463 err := goyaml.Unmarshal([]byte(setterTests[0].data), obj) 464 c.Assert(err, IsNil) 465 c.Assert(obj.tag, Equals, setterTests[0].tag) 466 value, ok := obj.value.(map[interface{}]interface{}) 467 c.Assert(ok, Equals, true) 468 c.Assert(value["_"], DeepEquals, setterTests[0].value) 469 } 470 471 func (s *S) TestUnmarshalWithFalseSetterIgnoresValue(c *C) { 472 setterResult[2] = false 473 setterResult[4] = false 474 defer func() { 475 delete(setterResult, 2) 476 delete(setterResult, 4) 477 }() 478 479 m := map[string]*typeWithSetter{} 480 data := "{abc: 1, def: 2, ghi: 3, jkl: 4}" 481 err := goyaml.Unmarshal([]byte(data), m) 482 c.Assert(err, IsNil) 483 c.Assert(m["abc"], NotNil) 484 c.Assert(m["def"], IsNil) 485 c.Assert(m["ghi"], NotNil) 486 c.Assert(m["jkl"], IsNil) 487 488 c.Assert(m["abc"].value, Equals, 1) 489 c.Assert(m["ghi"].value, Equals, 3) 490 } 491 492 //var data []byte 493 //func init() { 494 // var err error 495 // data, err = ioutil.ReadFile("/tmp/file.yaml") 496 // if err != nil { 497 // panic(err) 498 // } 499 //} 500 // 501 //func (s *S) BenchmarkUnmarshal(c *C) { 502 // var err error 503 // for i := 0; i < c.N; i++ { 504 // var v map[string]interface{} 505 // err = goyaml.Unmarshal(data, &v) 506 // } 507 // if err != nil { 508 // panic(err) 509 // } 510 //} 511 // 512 //func (s *S) BenchmarkMarshal(c *C) { 513 // var v map[string]interface{} 514 // goyaml.Unmarshal(data, &v) 515 // c.ResetTimer() 516 // for i := 0; i < c.N; i++ { 517 // goyaml.Marshal(&v) 518 // } 519 //}