github.com/technosophos/deis@v1.7.1-0.20150915173815-f9005256004b/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go (about) 1 package yaml_test 2 3 import ( 4 "fmt" 5 "math" 6 "strconv" 7 "strings" 8 "time" 9 10 . "gopkg.in/check.v1" 11 "gopkg.in/yaml.v2" 12 "net" 13 ) 14 15 var marshalIntTest = 123 16 17 var marshalTests = []struct { 18 value interface{} 19 data string 20 }{ 21 { 22 nil, 23 "null\n", 24 }, { 25 &struct{}{}, 26 "{}\n", 27 }, { 28 map[string]string{"v": "hi"}, 29 "v: hi\n", 30 }, { 31 map[string]interface{}{"v": "hi"}, 32 "v: hi\n", 33 }, { 34 map[string]string{"v": "true"}, 35 "v: \"true\"\n", 36 }, { 37 map[string]string{"v": "false"}, 38 "v: \"false\"\n", 39 }, { 40 map[string]interface{}{"v": true}, 41 "v: true\n", 42 }, { 43 map[string]interface{}{"v": false}, 44 "v: false\n", 45 }, { 46 map[string]interface{}{"v": 10}, 47 "v: 10\n", 48 }, { 49 map[string]interface{}{"v": -10}, 50 "v: -10\n", 51 }, { 52 map[string]uint{"v": 42}, 53 "v: 42\n", 54 }, { 55 map[string]interface{}{"v": int64(4294967296)}, 56 "v: 4294967296\n", 57 }, { 58 map[string]int64{"v": int64(4294967296)}, 59 "v: 4294967296\n", 60 }, { 61 map[string]uint64{"v": 4294967296}, 62 "v: 4294967296\n", 63 }, { 64 map[string]interface{}{"v": "10"}, 65 "v: \"10\"\n", 66 }, { 67 map[string]interface{}{"v": 0.1}, 68 "v: 0.1\n", 69 }, { 70 map[string]interface{}{"v": float64(0.1)}, 71 "v: 0.1\n", 72 }, { 73 map[string]interface{}{"v": -0.1}, 74 "v: -0.1\n", 75 }, { 76 map[string]interface{}{"v": math.Inf(+1)}, 77 "v: .inf\n", 78 }, { 79 map[string]interface{}{"v": math.Inf(-1)}, 80 "v: -.inf\n", 81 }, { 82 map[string]interface{}{"v": math.NaN()}, 83 "v: .nan\n", 84 }, { 85 map[string]interface{}{"v": nil}, 86 "v: null\n", 87 }, { 88 map[string]interface{}{"v": ""}, 89 "v: \"\"\n", 90 }, { 91 map[string][]string{"v": []string{"A", "B"}}, 92 "v:\n- A\n- B\n", 93 }, { 94 map[string][]string{"v": []string{"A", "B\nC"}}, 95 "v:\n- A\n- |-\n B\n C\n", 96 }, { 97 map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, 98 "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", 99 }, { 100 map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, 101 "a:\n b: c\n", 102 }, { 103 map[string]interface{}{"a": "-"}, 104 "a: '-'\n", 105 }, 106 107 // Simple values. 108 { 109 &marshalIntTest, 110 "123\n", 111 }, 112 113 // Structures 114 { 115 &struct{ Hello string }{"world"}, 116 "hello: world\n", 117 }, { 118 &struct { 119 A struct { 120 B string 121 } 122 }{struct{ B string }{"c"}}, 123 "a:\n b: c\n", 124 }, { 125 &struct { 126 A *struct { 127 B string 128 } 129 }{&struct{ B string }{"c"}}, 130 "a:\n b: c\n", 131 }, { 132 &struct { 133 A *struct { 134 B string 135 } 136 }{}, 137 "a: null\n", 138 }, { 139 &struct{ A int }{1}, 140 "a: 1\n", 141 }, { 142 &struct{ A []int }{[]int{1, 2}}, 143 "a:\n- 1\n- 2\n", 144 }, { 145 &struct { 146 B int "a" 147 }{1}, 148 "a: 1\n", 149 }, { 150 &struct{ A bool }{true}, 151 "a: true\n", 152 }, 153 154 // Conditional flag 155 { 156 &struct { 157 A int "a,omitempty" 158 B int "b,omitempty" 159 }{1, 0}, 160 "a: 1\n", 161 }, { 162 &struct { 163 A int "a,omitempty" 164 B int "b,omitempty" 165 }{0, 0}, 166 "{}\n", 167 }, { 168 &struct { 169 A *struct{ X int } "a,omitempty" 170 B int "b,omitempty" 171 }{nil, 0}, 172 "{}\n", 173 }, 174 175 // Flow flag 176 { 177 &struct { 178 A []int "a,flow" 179 }{[]int{1, 2}}, 180 "a: [1, 2]\n", 181 }, { 182 &struct { 183 A map[string]string "a,flow" 184 }{map[string]string{"b": "c", "d": "e"}}, 185 "a: {b: c, d: e}\n", 186 }, { 187 &struct { 188 A struct { 189 B, D string 190 } "a,flow" 191 }{struct{ B, D string }{"c", "e"}}, 192 "a: {b: c, d: e}\n", 193 }, 194 195 // Unexported field 196 { 197 &struct { 198 u int 199 A int 200 }{0, 1}, 201 "a: 1\n", 202 }, 203 204 // Ignored field 205 { 206 &struct { 207 A int 208 B int "-" 209 }{1, 2}, 210 "a: 1\n", 211 }, 212 213 // Struct inlining 214 { 215 &struct { 216 A int 217 C inlineB `yaml:",inline"` 218 }{1, inlineB{2, inlineC{3}}}, 219 "a: 1\nb: 2\nc: 3\n", 220 }, 221 222 // Duration 223 { 224 map[string]time.Duration{"a": 3 * time.Second}, 225 "a: 3s\n", 226 }, 227 228 // Issue #24: bug in map merging logic. 229 { 230 map[string]string{"a": "<foo>"}, 231 "a: <foo>\n", 232 }, 233 234 // Issue #34: marshal unsupported base 60 floats quoted for compatibility 235 // with old YAML 1.1 parsers. 236 { 237 map[string]string{"a": "1:1"}, 238 "a: \"1:1\"\n", 239 }, 240 241 // Binary data. 242 { 243 map[string]string{"a": "\x00"}, 244 "a: \"\\0\"\n", 245 }, { 246 map[string]string{"a": "\x80\x81\x82"}, 247 "a: !!binary gIGC\n", 248 }, { 249 map[string]string{"a": strings.Repeat("\x90", 54)}, 250 "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", 251 }, 252 253 // Ordered maps. 254 { 255 &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, 256 "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n", 257 }, 258 259 // Encode unicode as utf-8 rather than in escaped form. 260 { 261 map[string]string{"a": "你好"}, 262 "a: 你好\n", 263 }, 264 265 // Support encoding.TextMarshaler. 266 { 267 map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, 268 "a: 1.2.3.4\n", 269 }, 270 } 271 272 func (s *S) TestMarshal(c *C) { 273 for _, item := range marshalTests { 274 data, err := yaml.Marshal(item.value) 275 c.Assert(err, IsNil) 276 c.Assert(string(data), Equals, item.data) 277 } 278 } 279 280 var marshalErrorTests = []struct { 281 value interface{} 282 error string 283 panic string 284 }{{ 285 value: &struct { 286 B int 287 inlineB ",inline" 288 }{1, inlineB{2, inlineC{3}}}, 289 panic: `Duplicated key 'b' in struct struct \{ B int; .*`, 290 }} 291 292 func (s *S) TestMarshalErrors(c *C) { 293 for _, item := range marshalErrorTests { 294 if item.panic != "" { 295 c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) 296 } else { 297 _, err := yaml.Marshal(item.value) 298 c.Assert(err, ErrorMatches, item.error) 299 } 300 } 301 } 302 303 func (s *S) TestMarshalTypeCache(c *C) { 304 var data []byte 305 var err error 306 func() { 307 type T struct{ A int } 308 data, err = yaml.Marshal(&T{}) 309 c.Assert(err, IsNil) 310 }() 311 func() { 312 type T struct{ B int } 313 data, err = yaml.Marshal(&T{}) 314 c.Assert(err, IsNil) 315 }() 316 c.Assert(string(data), Equals, "b: 0\n") 317 } 318 319 var marshalerTests = []struct { 320 data string 321 value interface{} 322 }{ 323 {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, 324 {"_:\n- 1\n- A\n", []interface{}{1, "A"}}, 325 {"_: 10\n", 10}, 326 {"_: null\n", nil}, 327 {"_: BAR!\n", "BAR!"}, 328 } 329 330 type marshalerType struct { 331 value interface{} 332 } 333 334 func (o marshalerType) MarshalYAML() (interface{}, error) { 335 return o.value, nil 336 } 337 338 type marshalerValue struct { 339 Field marshalerType "_" 340 } 341 342 func (s *S) TestMarshaler(c *C) { 343 for _, item := range marshalerTests { 344 obj := &marshalerValue{} 345 obj.Field.value = item.value 346 data, err := yaml.Marshal(obj) 347 c.Assert(err, IsNil) 348 c.Assert(string(data), Equals, string(item.data)) 349 } 350 } 351 352 func (s *S) TestMarshalerWholeDocument(c *C) { 353 obj := &marshalerType{} 354 obj.value = map[string]string{"hello": "world!"} 355 data, err := yaml.Marshal(obj) 356 c.Assert(err, IsNil) 357 c.Assert(string(data), Equals, "hello: world!\n") 358 } 359 360 type failingMarshaler struct{} 361 362 func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { 363 return nil, failingErr 364 } 365 366 func (s *S) TestMarshalerError(c *C) { 367 _, err := yaml.Marshal(&failingMarshaler{}) 368 c.Assert(err, Equals, failingErr) 369 } 370 371 func (s *S) TestSortedOutput(c *C) { 372 order := []interface{}{ 373 false, 374 true, 375 1, 376 uint(1), 377 1.0, 378 1.1, 379 1.2, 380 2, 381 uint(2), 382 2.0, 383 2.1, 384 "", 385 ".1", 386 ".2", 387 ".a", 388 "1", 389 "2", 390 "a!10", 391 "a/2", 392 "a/10", 393 "a~10", 394 "ab/1", 395 "b/1", 396 "b/01", 397 "b/2", 398 "b/02", 399 "b/3", 400 "b/03", 401 "b1", 402 "b01", 403 "b3", 404 "c2.10", 405 "c10.2", 406 "d1", 407 "d12", 408 "d12a", 409 } 410 m := make(map[interface{}]int) 411 for _, k := range order { 412 m[k] = 1 413 } 414 data, err := yaml.Marshal(m) 415 c.Assert(err, IsNil) 416 out := "\n" + string(data) 417 last := 0 418 for i, k := range order { 419 repr := fmt.Sprint(k) 420 if s, ok := k.(string); ok { 421 if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { 422 repr = `"` + repr + `"` 423 } 424 } 425 index := strings.Index(out, "\n"+repr+":") 426 if index == -1 { 427 c.Fatalf("%#v is not in the output: %#v", k, out) 428 } 429 if index < last { 430 c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) 431 } 432 last = index 433 } 434 }