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