encode_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package goyaml_test
  2. import (
  3. "fmt"
  4. . "launchpad.net/gocheck"
  5. "launchpad.net/goyaml"
  6. "math"
  7. "strings"
  8. )
  9. var marshalIntTest = 123
  10. var marshalTests = []struct {
  11. data string
  12. value interface{}
  13. }{
  14. {"{}\n", &struct{}{}},
  15. {"v: hi\n", map[string]string{"v": "hi"}},
  16. {"v: hi\n", map[string]interface{}{"v": "hi"}},
  17. {"v: \"true\"\n", map[string]string{"v": "true"}},
  18. {"v: \"false\"\n", map[string]string{"v": "false"}},
  19. {"v: true\n", map[string]interface{}{"v": true}},
  20. {"v: false\n", map[string]interface{}{"v": false}},
  21. {"v: 10\n", map[string]interface{}{"v": 10}},
  22. {"v: -10\n", map[string]interface{}{"v": -10}},
  23. {"v: 42\n", map[string]uint{"v": 42}},
  24. {"v: 4294967296\n", map[string]interface{}{"v": int64(4294967296)}},
  25. {"v: 4294967296\n", map[string]int64{"v": int64(4294967296)}},
  26. {"v: 4294967296\n", map[string]uint64{"v": 4294967296}},
  27. {"v: \"10\"\n", map[string]interface{}{"v": "10"}},
  28. {"v: 0.1\n", map[string]interface{}{"v": 0.1}},
  29. {"v: 0.1\n", map[string]interface{}{"v": float64(0.1)}},
  30. {"v: -0.1\n", map[string]interface{}{"v": -0.1}},
  31. {"v: .inf\n", map[string]interface{}{"v": math.Inf(+1)}},
  32. {"v: -.inf\n", map[string]interface{}{"v": math.Inf(-1)}},
  33. {"v: .nan\n", map[string]interface{}{"v": math.NaN()}},
  34. {"v: null\n", map[string]interface{}{"v": nil}},
  35. {"v: \"\"\n", map[string]interface{}{"v": ""}},
  36. {"v:\n- A\n- B\n", map[string][]string{"v": []string{"A", "B"}}},
  37. {"v:\n- A\n- 1\n", map[string][]interface{}{"v": []interface{}{"A", 1}}},
  38. {"a:\n b: c\n",
  39. map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}},
  40. // Simple values.
  41. {"123\n", &marshalIntTest},
  42. // Structures
  43. {"hello: world\n", &struct{ Hello string }{"world"}},
  44. {"a:\n b: c\n", &struct {
  45. A struct {
  46. B string
  47. }
  48. }{struct{ B string }{"c"}}},
  49. {"a:\n b: c\n", &struct {
  50. A *struct {
  51. B string
  52. }
  53. }{&struct{ B string }{"c"}}},
  54. {"a: null\n", &struct {
  55. A *struct {
  56. B string
  57. }
  58. }{}},
  59. {"a: 1\n", &struct{ A int }{1}},
  60. {"a:\n- 1\n- 2\n", &struct{ A []int }{[]int{1, 2}}},
  61. {"a: 1\n", &struct {
  62. B int "a"
  63. }{1}},
  64. {"a: true\n", &struct{ A bool }{true}},
  65. // Conditional flag
  66. {"a: 1\n", &struct {
  67. A int "a,omitempty"
  68. B int "b,omitempty"
  69. }{1, 0}},
  70. {"{}\n", &struct {
  71. A int "a,omitempty"
  72. B int "b,omitempty"
  73. }{0, 0}},
  74. {"{}\n", &struct {
  75. A *struct{ X int } "a,omitempty"
  76. B int "b,omitempty"
  77. }{nil, 0}},
  78. // Flow flag
  79. {"a: [1, 2]\n", &struct {
  80. A []int "a,flow"
  81. }{[]int{1, 2}}},
  82. {"a: {b: c}\n",
  83. &struct {
  84. A map[string]string "a,flow"
  85. }{map[string]string{"b": "c"}}},
  86. {"a: {b: c}\n",
  87. &struct {
  88. A struct {
  89. B string
  90. } "a,flow"
  91. }{struct{ B string }{"c"}}},
  92. }
  93. func (s *S) TestMarshal(c *C) {
  94. for _, item := range marshalTests {
  95. data, err := goyaml.Marshal(item.value)
  96. c.Assert(err, IsNil)
  97. c.Assert(string(data), Equals, item.data)
  98. }
  99. }
  100. //var unmarshalErrorTests = []struct{data, error string}{
  101. // {"v: !!float 'error'", "Can't decode !!str 'error' as a !!float"},
  102. //}
  103. //
  104. //func (s *S) TestUnmarshalErrors(c *C) {
  105. // for _, item := range unmarshalErrorTests {
  106. // var value interface{}
  107. // err := goyaml.Unmarshal([]byte(item.data), &value)
  108. // c.Assert(err, Matches, item.error)
  109. // }
  110. //}
  111. var marshalTaggedIfaceTest interface{} = &struct{ A string }{"B"}
  112. var getterTests = []struct {
  113. data, tag string
  114. value interface{}
  115. }{
  116. {"_:\n hi: there\n", "", map[interface{}]interface{}{"hi": "there"}},
  117. {"_:\n- 1\n- A\n", "", []interface{}{1, "A"}},
  118. {"_: 10\n", "", 10},
  119. {"_: null\n", "", nil},
  120. {"_: !foo BAR!\n", "!foo", "BAR!"},
  121. {"_: !foo 1\n", "!foo", "1"},
  122. {"_: !foo '\"1\"'\n", "!foo", "\"1\""},
  123. {"_: !foo 1.1\n", "!foo", 1.1},
  124. {"_: !foo 1\n", "!foo", 1},
  125. {"_: !foo 1\n", "!foo", uint(1)},
  126. {"_: !foo true\n", "!foo", true},
  127. {"_: !foo\n- A\n- B\n", "!foo", []string{"A", "B"}},
  128. {"_: !foo\n A: B\n", "!foo", map[string]string{"A": "B"}},
  129. {"_: !foo\n a: B\n", "!foo", &marshalTaggedIfaceTest},
  130. }
  131. type typeWithGetter struct {
  132. tag string
  133. value interface{}
  134. }
  135. func (o typeWithGetter) GetYAML() (tag string, value interface{}) {
  136. return o.tag, o.value
  137. }
  138. type typeWithGetterField struct {
  139. Field typeWithGetter "_"
  140. }
  141. func (s *S) TestMashalWithGetter(c *C) {
  142. for _, item := range getterTests {
  143. obj := &typeWithGetterField{}
  144. obj.Field.tag = item.tag
  145. obj.Field.value = item.value
  146. data, err := goyaml.Marshal(obj)
  147. c.Assert(err, IsNil)
  148. c.Assert(string(data), Equals, string(item.data))
  149. }
  150. }
  151. func (s *S) TestUnmarshalWholeDocumentWithGetter(c *C) {
  152. obj := &typeWithGetter{}
  153. obj.tag = ""
  154. obj.value = map[string]string{"hello": "world!"}
  155. data, err := goyaml.Marshal(obj)
  156. c.Assert(err, IsNil)
  157. c.Assert(string(data), Equals, "hello: world!\n")
  158. }
  159. func (s *S) TestSortedOutput(c *C) {
  160. order := []interface{}{
  161. 1,
  162. 1.0,
  163. 1.1,
  164. 1.2,
  165. 2,
  166. 2.0,
  167. 2.1,
  168. "a!10",
  169. "a/2",
  170. "a/10",
  171. "a~10",
  172. "ab/1",
  173. "b/1",
  174. "b/01",
  175. "b/2",
  176. "b/02",
  177. "b/3",
  178. "b/03",
  179. "b1",
  180. "b01",
  181. "b3",
  182. "c2.10",
  183. "c10.2",
  184. "d1",
  185. "d12",
  186. "d12a",
  187. }
  188. m := make(map[interface{}]int)
  189. for _, k := range order {
  190. m[k] = 1
  191. }
  192. data, err := goyaml.Marshal(m)
  193. c.Assert(err, IsNil)
  194. out := "\n" + string(data)
  195. last := 0
  196. for i, k := range order {
  197. repr := fmt.Sprint(k)
  198. index := strings.Index(out, "\n"+repr+":")
  199. if index == -1 {
  200. c.Fatalf("%#v is not in the output: %#v", k, out)
  201. }
  202. if index < last {
  203. c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out)
  204. }
  205. last = index
  206. }
  207. }