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