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