decode_test.go 13 KB

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