Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / github.com / !burnt!sushi / toml@v0.3.1 / encode_test.go
1 package toml
2
3 import (
4         "bytes"
5         "fmt"
6         "log"
7         "net"
8         "testing"
9         "time"
10 )
11
12 func TestEncodeRoundTrip(t *testing.T) {
13         type Config struct {
14                 Age        int
15                 Cats       []string
16                 Pi         float64
17                 Perfection []int
18                 DOB        time.Time
19                 Ipaddress  net.IP
20         }
21
22         var inputs = Config{
23                 13,
24                 []string{"one", "two", "three"},
25                 3.145,
26                 []int{11, 2, 3, 4},
27                 time.Now(),
28                 net.ParseIP("192.168.59.254"),
29         }
30
31         var firstBuffer bytes.Buffer
32         e := NewEncoder(&firstBuffer)
33         err := e.Encode(inputs)
34         if err != nil {
35                 t.Fatal(err)
36         }
37         var outputs Config
38         if _, err := Decode(firstBuffer.String(), &outputs); err != nil {
39                 t.Logf("Could not decode:\n-----\n%s\n-----\n",
40                         firstBuffer.String())
41                 t.Fatal(err)
42         }
43
44         // could test each value individually, but I'm lazy
45         var secondBuffer bytes.Buffer
46         e2 := NewEncoder(&secondBuffer)
47         err = e2.Encode(outputs)
48         if err != nil {
49                 t.Fatal(err)
50         }
51         if firstBuffer.String() != secondBuffer.String() {
52                 t.Error(
53                         firstBuffer.String(),
54                         "\n\n is not identical to\n\n",
55                         secondBuffer.String())
56         }
57 }
58
59 // XXX(burntsushi)
60 // I think these tests probably should be removed. They are good, but they
61 // ought to be obsolete by toml-test.
62 func TestEncode(t *testing.T) {
63         type Embedded struct {
64                 Int int `toml:"_int"`
65         }
66         type NonStruct int
67
68         date := time.Date(2014, 5, 11, 20, 30, 40, 0, time.FixedZone("IST", 3600))
69         dateStr := "2014-05-11T19:30:40Z"
70
71         tests := map[string]struct {
72                 input      interface{}
73                 wantOutput string
74                 wantError  error
75         }{
76                 "bool field": {
77                         input: struct {
78                                 BoolTrue  bool
79                                 BoolFalse bool
80                         }{true, false},
81                         wantOutput: "BoolTrue = true\nBoolFalse = false\n",
82                 },
83                 "int fields": {
84                         input: struct {
85                                 Int   int
86                                 Int8  int8
87                                 Int16 int16
88                                 Int32 int32
89                                 Int64 int64
90                         }{1, 2, 3, 4, 5},
91                         wantOutput: "Int = 1\nInt8 = 2\nInt16 = 3\nInt32 = 4\nInt64 = 5\n",
92                 },
93                 "uint fields": {
94                         input: struct {
95                                 Uint   uint
96                                 Uint8  uint8
97                                 Uint16 uint16
98                                 Uint32 uint32
99                                 Uint64 uint64
100                         }{1, 2, 3, 4, 5},
101                         wantOutput: "Uint = 1\nUint8 = 2\nUint16 = 3\nUint32 = 4" +
102                                 "\nUint64 = 5\n",
103                 },
104                 "float fields": {
105                         input: struct {
106                                 Float32 float32
107                                 Float64 float64
108                         }{1.5, 2.5},
109                         wantOutput: "Float32 = 1.5\nFloat64 = 2.5\n",
110                 },
111                 "string field": {
112                         input:      struct{ String string }{"foo"},
113                         wantOutput: "String = \"foo\"\n",
114                 },
115                 "string field and unexported field": {
116                         input: struct {
117                                 String     string
118                                 unexported int
119                         }{"foo", 0},
120                         wantOutput: "String = \"foo\"\n",
121                 },
122                 "datetime field in UTC": {
123                         input:      struct{ Date time.Time }{date},
124                         wantOutput: fmt.Sprintf("Date = %s\n", dateStr),
125                 },
126                 "datetime field as primitive": {
127                         // Using a map here to fail if isStructOrMap() returns true for
128                         // time.Time.
129                         input: map[string]interface{}{
130                                 "Date": date,
131                                 "Int":  1,
132                         },
133                         wantOutput: fmt.Sprintf("Date = %s\nInt = 1\n", dateStr),
134                 },
135                 "array fields": {
136                         input: struct {
137                                 IntArray0 [0]int
138                                 IntArray3 [3]int
139                         }{[0]int{}, [3]int{1, 2, 3}},
140                         wantOutput: "IntArray0 = []\nIntArray3 = [1, 2, 3]\n",
141                 },
142                 "slice fields": {
143                         input: struct{ IntSliceNil, IntSlice0, IntSlice3 []int }{
144                                 nil, []int{}, []int{1, 2, 3},
145                         },
146                         wantOutput: "IntSlice0 = []\nIntSlice3 = [1, 2, 3]\n",
147                 },
148                 "datetime slices": {
149                         input: struct{ DatetimeSlice []time.Time }{
150                                 []time.Time{date, date},
151                         },
152                         wantOutput: fmt.Sprintf("DatetimeSlice = [%s, %s]\n",
153                                 dateStr, dateStr),
154                 },
155                 "nested arrays and slices": {
156                         input: struct {
157                                 SliceOfArrays         [][2]int
158                                 ArrayOfSlices         [2][]int
159                                 SliceOfArraysOfSlices [][2][]int
160                                 ArrayOfSlicesOfArrays [2][][2]int
161                                 SliceOfMixedArrays    [][2]interface{}
162                                 ArrayOfMixedSlices    [2][]interface{}
163                         }{
164                                 [][2]int{{1, 2}, {3, 4}},
165                                 [2][]int{{1, 2}, {3, 4}},
166                                 [][2][]int{
167                                         {
168                                                 {1, 2}, {3, 4},
169                                         },
170                                         {
171                                                 {5, 6}, {7, 8},
172                                         },
173                                 },
174                                 [2][][2]int{
175                                         {
176                                                 {1, 2}, {3, 4},
177                                         },
178                                         {
179                                                 {5, 6}, {7, 8},
180                                         },
181                                 },
182                                 [][2]interface{}{
183                                         {1, 2}, {"a", "b"},
184                                 },
185                                 [2][]interface{}{
186                                         {1, 2}, {"a", "b"},
187                                 },
188                         },
189                         wantOutput: `SliceOfArrays = [[1, 2], [3, 4]]
190 ArrayOfSlices = [[1, 2], [3, 4]]
191 SliceOfArraysOfSlices = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
192 ArrayOfSlicesOfArrays = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
193 SliceOfMixedArrays = [[1, 2], ["a", "b"]]
194 ArrayOfMixedSlices = [[1, 2], ["a", "b"]]
195 `,
196                 },
197                 "empty slice": {
198                         input:      struct{ Empty []interface{} }{[]interface{}{}},
199                         wantOutput: "Empty = []\n",
200                 },
201                 "(error) slice with element type mismatch (string and integer)": {
202                         input:     struct{ Mixed []interface{} }{[]interface{}{1, "a"}},
203                         wantError: errArrayMixedElementTypes,
204                 },
205                 "(error) slice with element type mismatch (integer and float)": {
206                         input:     struct{ Mixed []interface{} }{[]interface{}{1, 2.5}},
207                         wantError: errArrayMixedElementTypes,
208                 },
209                 "slice with elems of differing Go types, same TOML types": {
210                         input: struct {
211                                 MixedInts   []interface{}
212                                 MixedFloats []interface{}
213                         }{
214                                 []interface{}{
215                                         int(1), int8(2), int16(3), int32(4), int64(5),
216                                         uint(1), uint8(2), uint16(3), uint32(4), uint64(5),
217                                 },
218                                 []interface{}{float32(1.5), float64(2.5)},
219                         },
220                         wantOutput: "MixedInts = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]\n" +
221                                 "MixedFloats = [1.5, 2.5]\n",
222                 },
223                 "(error) slice w/ element type mismatch (one is nested array)": {
224                         input: struct{ Mixed []interface{} }{
225                                 []interface{}{1, []interface{}{2}},
226                         },
227                         wantError: errArrayMixedElementTypes,
228                 },
229                 "(error) slice with 1 nil element": {
230                         input:     struct{ NilElement1 []interface{} }{[]interface{}{nil}},
231                         wantError: errArrayNilElement,
232                 },
233                 "(error) slice with 1 nil element (and other non-nil elements)": {
234                         input: struct{ NilElement []interface{} }{
235                                 []interface{}{1, nil},
236                         },
237                         wantError: errArrayNilElement,
238                 },
239                 "simple map": {
240                         input:      map[string]int{"a": 1, "b": 2},
241                         wantOutput: "a = 1\nb = 2\n",
242                 },
243                 "map with interface{} value type": {
244                         input:      map[string]interface{}{"a": 1, "b": "c"},
245                         wantOutput: "a = 1\nb = \"c\"\n",
246                 },
247                 "map with interface{} value type, some of which are structs": {
248                         input: map[string]interface{}{
249                                 "a": struct{ Int int }{2},
250                                 "b": 1,
251                         },
252                         wantOutput: "b = 1\n\n[a]\n  Int = 2\n",
253                 },
254                 "nested map": {
255                         input: map[string]map[string]int{
256                                 "a": {"b": 1},
257                                 "c": {"d": 2},
258                         },
259                         wantOutput: "[a]\n  b = 1\n\n[c]\n  d = 2\n",
260                 },
261                 "nested struct": {
262                         input: struct{ Struct struct{ Int int } }{
263                                 struct{ Int int }{1},
264                         },
265                         wantOutput: "[Struct]\n  Int = 1\n",
266                 },
267                 "nested struct and non-struct field": {
268                         input: struct {
269                                 Struct struct{ Int int }
270                                 Bool   bool
271                         }{struct{ Int int }{1}, true},
272                         wantOutput: "Bool = true\n\n[Struct]\n  Int = 1\n",
273                 },
274                 "2 nested structs": {
275                         input: struct{ Struct1, Struct2 struct{ Int int } }{
276                                 struct{ Int int }{1}, struct{ Int int }{2},
277                         },
278                         wantOutput: "[Struct1]\n  Int = 1\n\n[Struct2]\n  Int = 2\n",
279                 },
280                 "deeply nested structs": {
281                         input: struct {
282                                 Struct1, Struct2 struct{ Struct3 *struct{ Int int } }
283                         }{
284                                 struct{ Struct3 *struct{ Int int } }{&struct{ Int int }{1}},
285                                 struct{ Struct3 *struct{ Int int } }{nil},
286                         },
287                         wantOutput: "[Struct1]\n  [Struct1.Struct3]\n    Int = 1" +
288                                 "\n\n[Struct2]\n",
289                 },
290                 "nested struct with nil struct elem": {
291                         input: struct {
292                                 Struct struct{ Inner *struct{ Int int } }
293                         }{
294                                 struct{ Inner *struct{ Int int } }{nil},
295                         },
296                         wantOutput: "[Struct]\n",
297                 },
298                 "nested struct with no fields": {
299                         input: struct {
300                                 Struct struct{ Inner struct{} }
301                         }{
302                                 struct{ Inner struct{} }{struct{}{}},
303                         },
304                         wantOutput: "[Struct]\n  [Struct.Inner]\n",
305                 },
306                 "struct with tags": {
307                         input: struct {
308                                 Struct struct {
309                                         Int int `toml:"_int"`
310                                 } `toml:"_struct"`
311                                 Bool bool `toml:"_bool"`
312                         }{
313                                 struct {
314                                         Int int `toml:"_int"`
315                                 }{1}, true,
316                         },
317                         wantOutput: "_bool = true\n\n[_struct]\n  _int = 1\n",
318                 },
319                 "embedded struct": {
320                         input:      struct{ Embedded }{Embedded{1}},
321                         wantOutput: "_int = 1\n",
322                 },
323                 "embedded *struct": {
324                         input:      struct{ *Embedded }{&Embedded{1}},
325                         wantOutput: "_int = 1\n",
326                 },
327                 "nested embedded struct": {
328                         input: struct {
329                                 Struct struct{ Embedded } `toml:"_struct"`
330                         }{struct{ Embedded }{Embedded{1}}},
331                         wantOutput: "[_struct]\n  _int = 1\n",
332                 },
333                 "nested embedded *struct": {
334                         input: struct {
335                                 Struct struct{ *Embedded } `toml:"_struct"`
336                         }{struct{ *Embedded }{&Embedded{1}}},
337                         wantOutput: "[_struct]\n  _int = 1\n",
338                 },
339                 "embedded non-struct": {
340                         input:      struct{ NonStruct }{5},
341                         wantOutput: "NonStruct = 5\n",
342                 },
343                 "array of tables": {
344                         input: struct {
345                                 Structs []*struct{ Int int } `toml:"struct"`
346                         }{
347                                 []*struct{ Int int }{{1}, {3}},
348                         },
349                         wantOutput: "[[struct]]\n  Int = 1\n\n[[struct]]\n  Int = 3\n",
350                 },
351                 "array of tables order": {
352                         input: map[string]interface{}{
353                                 "map": map[string]interface{}{
354                                         "zero": 5,
355                                         "arr": []map[string]int{
356                                                 {
357                                                         "friend": 5,
358                                                 },
359                                         },
360                                 },
361                         },
362                         wantOutput: "[map]\n  zero = 5\n\n  [[map.arr]]\n    friend = 5\n",
363                 },
364                 "(error) top-level slice": {
365                         input:     []struct{ Int int }{{1}, {2}, {3}},
366                         wantError: errNoKey,
367                 },
368                 "(error) slice of slice": {
369                         input: struct {
370                                 Slices [][]struct{ Int int }
371                         }{
372                                 [][]struct{ Int int }{{{1}}, {{2}}, {{3}}},
373                         },
374                         wantError: errArrayNoTable,
375                 },
376                 "(error) map no string key": {
377                         input:     map[int]string{1: ""},
378                         wantError: errNonString,
379                 },
380                 "(error) empty key name": {
381                         input:     map[string]int{"": 1},
382                         wantError: errAnything,
383                 },
384                 "(error) empty map name": {
385                         input: map[string]interface{}{
386                                 "": map[string]int{"v": 1},
387                         },
388                         wantError: errAnything,
389                 },
390         }
391         for label, test := range tests {
392                 encodeExpected(t, label, test.input, test.wantOutput, test.wantError)
393         }
394 }
395
396 func TestEncodeNestedTableArrays(t *testing.T) {
397         type song struct {
398                 Name string `toml:"name"`
399         }
400         type album struct {
401                 Name  string `toml:"name"`
402                 Songs []song `toml:"songs"`
403         }
404         type springsteen struct {
405                 Albums []album `toml:"albums"`
406         }
407         value := springsteen{
408                 []album{
409                         {"Born to Run",
410                                 []song{{"Jungleland"}, {"Meeting Across the River"}}},
411                         {"Born in the USA",
412                                 []song{{"Glory Days"}, {"Dancing in the Dark"}}},
413                 },
414         }
415         expected := `[[albums]]
416   name = "Born to Run"
417
418   [[albums.songs]]
419     name = "Jungleland"
420
421   [[albums.songs]]
422     name = "Meeting Across the River"
423
424 [[albums]]
425   name = "Born in the USA"
426
427   [[albums.songs]]
428     name = "Glory Days"
429
430   [[albums.songs]]
431     name = "Dancing in the Dark"
432 `
433         encodeExpected(t, "nested table arrays", value, expected, nil)
434 }
435
436 func TestEncodeArrayHashWithNormalHashOrder(t *testing.T) {
437         type Alpha struct {
438                 V int
439         }
440         type Beta struct {
441                 V int
442         }
443         type Conf struct {
444                 V int
445                 A Alpha
446                 B []Beta
447         }
448
449         val := Conf{
450                 V: 1,
451                 A: Alpha{2},
452                 B: []Beta{{3}},
453         }
454         expected := "V = 1\n\n[A]\n  V = 2\n\n[[B]]\n  V = 3\n"
455         encodeExpected(t, "array hash with normal hash order", val, expected, nil)
456 }
457
458 func TestEncodeWithOmitEmpty(t *testing.T) {
459         type simple struct {
460                 Bool   bool              `toml:"bool,omitempty"`
461                 String string            `toml:"string,omitempty"`
462                 Array  [0]byte           `toml:"array,omitempty"`
463                 Slice  []int             `toml:"slice,omitempty"`
464                 Map    map[string]string `toml:"map,omitempty"`
465         }
466
467         var v simple
468         encodeExpected(t, "fields with omitempty are omitted when empty", v, "", nil)
469         v = simple{
470                 Bool:   true,
471                 String: " ",
472                 Slice:  []int{2, 3, 4},
473                 Map:    map[string]string{"foo": "bar"},
474         }
475         expected := `bool = true
476 string = " "
477 slice = [2, 3, 4]
478
479 [map]
480   foo = "bar"
481 `
482         encodeExpected(t, "fields with omitempty are not omitted when non-empty",
483                 v, expected, nil)
484 }
485
486 func TestEncodeWithOmitZero(t *testing.T) {
487         type simple struct {
488                 Number   int     `toml:"number,omitzero"`
489                 Real     float64 `toml:"real,omitzero"`
490                 Unsigned uint    `toml:"unsigned,omitzero"`
491         }
492
493         value := simple{0, 0.0, uint(0)}
494         expected := ""
495
496         encodeExpected(t, "simple with omitzero, all zero", value, expected, nil)
497
498         value.Number = 10
499         value.Real = 20
500         value.Unsigned = 5
501         expected = `number = 10
502 real = 20.0
503 unsigned = 5
504 `
505         encodeExpected(t, "simple with omitzero, non-zero", value, expected, nil)
506 }
507
508 func TestEncodeOmitemptyWithEmptyName(t *testing.T) {
509         type simple struct {
510                 S []int `toml:",omitempty"`
511         }
512         v := simple{[]int{1, 2, 3}}
513         expected := "S = [1, 2, 3]\n"
514         encodeExpected(t, "simple with omitempty, no name, non-empty field",
515                 v, expected, nil)
516 }
517
518 func TestEncodeAnonymousStruct(t *testing.T) {
519         type Inner struct{ N int }
520         type Outer0 struct{ Inner }
521         type Outer1 struct {
522                 Inner `toml:"inner"`
523         }
524
525         v0 := Outer0{Inner{3}}
526         expected := "N = 3\n"
527         encodeExpected(t, "embedded anonymous untagged struct", v0, expected, nil)
528
529         v1 := Outer1{Inner{3}}
530         expected = "[inner]\n  N = 3\n"
531         encodeExpected(t, "embedded anonymous tagged struct", v1, expected, nil)
532 }
533
534 func TestEncodeAnonymousStructPointerField(t *testing.T) {
535         type Inner struct{ N int }
536         type Outer0 struct{ *Inner }
537         type Outer1 struct {
538                 *Inner `toml:"inner"`
539         }
540
541         v0 := Outer0{}
542         expected := ""
543         encodeExpected(t, "nil anonymous untagged struct pointer field", v0, expected, nil)
544
545         v0 = Outer0{&Inner{3}}
546         expected = "N = 3\n"
547         encodeExpected(t, "non-nil anonymous untagged struct pointer field", v0, expected, nil)
548
549         v1 := Outer1{}
550         expected = ""
551         encodeExpected(t, "nil anonymous tagged struct pointer field", v1, expected, nil)
552
553         v1 = Outer1{&Inner{3}}
554         expected = "[inner]\n  N = 3\n"
555         encodeExpected(t, "non-nil anonymous tagged struct pointer field", v1, expected, nil)
556 }
557
558 func TestEncodeIgnoredFields(t *testing.T) {
559         type simple struct {
560                 Number int `toml:"-"`
561         }
562         value := simple{}
563         expected := ""
564         encodeExpected(t, "ignored field", value, expected, nil)
565 }
566
567 func encodeExpected(
568         t *testing.T, label string, val interface{}, wantStr string, wantErr error,
569 ) {
570         var buf bytes.Buffer
571         enc := NewEncoder(&buf)
572         err := enc.Encode(val)
573         if err != wantErr {
574                 if wantErr != nil {
575                         if wantErr == errAnything && err != nil {
576                                 return
577                         }
578                         t.Errorf("%s: want Encode error %v, got %v", label, wantErr, err)
579                 } else {
580                         t.Errorf("%s: Encode failed: %s", label, err)
581                 }
582         }
583         if err != nil {
584                 return
585         }
586         if got := buf.String(); wantStr != got {
587                 t.Errorf("%s: want\n-----\n%q\n-----\nbut got\n-----\n%q\n-----\n",
588                         label, wantStr, got)
589         }
590 }
591
592 func ExampleEncoder_Encode() {
593         date, _ := time.Parse(time.RFC822, "14 Mar 10 18:00 UTC")
594         var config = map[string]interface{}{
595                 "date":   date,
596                 "counts": []int{1, 1, 2, 3, 5, 8},
597                 "hash": map[string]string{
598                         "key1": "val1",
599                         "key2": "val2",
600                 },
601         }
602         buf := new(bytes.Buffer)
603         if err := NewEncoder(buf).Encode(config); err != nil {
604                 log.Fatal(err)
605         }
606         fmt.Println(buf.String())
607
608         // Output:
609         // counts = [1, 1, 2, 3, 5, 8]
610         // date = 2010-03-14T18:00:00Z
611         //
612         // [hash]
613         //   key1 = "val1"
614         //   key2 = "val2"
615 }