~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/yaml.v1/encode_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}