OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / yaml.v2 / encode_test.go
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 }