1 package toml
2
3 import (
4 "bytes"
5 "encoding/json"
6 "errors"
7 "fmt"
8 "io/ioutil"
9 "os"
10 "reflect"
11 "strconv"
12 "strings"
13 "testing"
14 "time"
15 )
16
17 type basicMarshalTestStruct struct {
18 String string `toml:"Zstring"`
19 StringList []string `toml:"Ystrlist"`
20 BasicMarshalTestSubAnonymousStruct
21 Sub basicMarshalTestSubStruct `toml:"Xsubdoc"`
22 SubList []basicMarshalTestSubStruct `toml:"Wsublist"`
23 }
24
25 type basicMarshalTestSubStruct struct {
26 String2 string
27 }
28
29 type BasicMarshalTestSubAnonymousStruct struct {
30 String3 string
31 }
32
33 var basicTestData = basicMarshalTestStruct{
34 String: "Hello",
35 StringList: []string{"Howdy", "Hey There"},
36 BasicMarshalTestSubAnonymousStruct: BasicMarshalTestSubAnonymousStruct{"One"},
37 Sub: basicMarshalTestSubStruct{"Two"},
38 SubList: []basicMarshalTestSubStruct{{"Three"}, {"Four"}},
39 }
40
41 var basicTestToml = []byte(`String3 = "One"
42 Ystrlist = ["Howdy", "Hey There"]
43 Zstring = "Hello"
44
45 [[Wsublist]]
46 String2 = "Three"
47
48 [[Wsublist]]
49 String2 = "Four"
50
51 [Xsubdoc]
52 String2 = "Two"
53 `)
54
55 var basicTestTomlCustomIndentation = []byte(`String3 = "One"
56 Ystrlist = ["Howdy", "Hey There"]
57 Zstring = "Hello"
58
59 [[Wsublist]]
60 String2 = "Three"
61
62 [[Wsublist]]
63 String2 = "Four"
64
65 [Xsubdoc]
66 String2 = "Two"
67 `)
68
69 var basicTestTomlOrdered = []byte(`Zstring = "Hello"
70 Ystrlist = ["Howdy", "Hey There"]
71 String3 = "One"
72
73 [Xsubdoc]
74 String2 = "Two"
75
76 [[Wsublist]]
77 String2 = "Three"
78
79 [[Wsublist]]
80 String2 = "Four"
81 `)
82
83 var marshalTestToml = []byte(`title = "TOML Marshal Testing"
84
85 [basic]
86 bool = true
87 date = 1979-05-27T07:32:00Z
88 float = 123.4
89 float64 = 123.456782132399
90 int = 5000
91 string = "Bite me"
92 uint = 5001
93
94 [basic_lists]
95 bools = [true, false, true]
96 dates = [1979-05-27T07:32:00Z, 1980-05-27T07:32:00Z]
97 floats = [12.3, 45.6, 78.9]
98 ints = [8001, 8001, 8002]
99 strings = ["One", "Two", "Three"]
100 uints = [5002, 5003]
101
102 [basic_map]
103 one = "one"
104 two = "two"
105
106 [subdoc]
107
108 [subdoc.first]
109 name = "First"
110
111 [subdoc.second]
112 name = "Second"
113
114 [[subdoclist]]
115 name = "List.First"
116
117 [[subdoclist]]
118 name = "List.Second"
119
120 [[subdocptrs]]
121 name = "Second"
122 `)
123
124 var marshalOrderPreserveToml = []byte(`title = "TOML Marshal Testing"
125
126 [basic_lists]
127 floats = [12.3, 45.6, 78.9]
128 bools = [true, false, true]
129 dates = [1979-05-27T07:32:00Z, 1980-05-27T07:32:00Z]
130 ints = [8001, 8001, 8002]
131 uints = [5002, 5003]
132 strings = ["One", "Two", "Three"]
133
134 [[subdocptrs]]
135 name = "Second"
136
137 [basic_map]
138 one = "one"
139 two = "two"
140
141 [subdoc]
142
143 [subdoc.second]
144 name = "Second"
145
146 [subdoc.first]
147 name = "First"
148
149 [basic]
150 uint = 5001
151 bool = true
152 float = 123.4
153 float64 = 123.456782132399
154 int = 5000
155 string = "Bite me"
156 date = 1979-05-27T07:32:00Z
157
158 [[subdoclist]]
159 name = "List.First"
160
161 [[subdoclist]]
162 name = "List.Second"
163 `)
164
165 var mashalOrderPreserveMapToml = []byte(`title = "TOML Marshal Testing"
166
167 [basic_map]
168 one = "one"
169 two = "two"
170
171 [long_map]
172 a7 = "1"
173 b3 = "2"
174 c8 = "3"
175 d4 = "4"
176 e6 = "5"
177 f5 = "6"
178 g10 = "7"
179 h1 = "8"
180 i2 = "9"
181 j9 = "10"
182 `)
183
184 type Conf struct {
185 Name string
186 Age int
187 Inter interface{}
188 }
189
190 type NestedStruct struct {
191 FirstName string
192 LastName string
193 Age int
194 }
195
196 var doc = []byte(`Name = "rui"
197 Age = 18
198
199 [Inter]
200 FirstName = "wang"
201 LastName = "jl"
202 Age = 100`)
203
204 func TestInterface(t *testing.T) {
205 var config Conf
206 config.Inter = &NestedStruct{}
207 err := Unmarshal(doc, &config)
208 expected := Conf{
209 Name: "rui",
210 Age: 18,
211 Inter: &NestedStruct{
212 FirstName: "wang",
213 LastName: "jl",
214 Age: 100,
215 },
216 }
217 if err != nil || !reflect.DeepEqual(config, expected) {
218 t.Errorf("Bad unmarshal: expected %v, got %v", expected, config)
219 }
220 }
221
222 func TestBasicMarshal(t *testing.T) {
223 result, err := Marshal(basicTestData)
224 if err != nil {
225 t.Fatal(err)
226 }
227 expected := basicTestToml
228 if !bytes.Equal(result, expected) {
229 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
230 }
231 }
232
233 func TestBasicMarshalCustomIndentation(t *testing.T) {
234 var result bytes.Buffer
235 err := NewEncoder(&result).Indentation("\t").Encode(basicTestData)
236 if err != nil {
237 t.Fatal(err)
238 }
239 expected := basicTestTomlCustomIndentation
240 if !bytes.Equal(result.Bytes(), expected) {
241 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
242 }
243 }
244
245 func TestBasicMarshalWrongIndentation(t *testing.T) {
246 var result bytes.Buffer
247 err := NewEncoder(&result).Indentation(" \n").Encode(basicTestData)
248 if err.Error() != "invalid indentation: must only contains space or tab characters" {
249 t.Error("expect err:invalid indentation: must only contains space or tab characters but got:", err)
250 }
251 }
252
253 func TestBasicMarshalOrdered(t *testing.T) {
254 var result bytes.Buffer
255 err := NewEncoder(&result).Order(OrderPreserve).Encode(basicTestData)
256 if err != nil {
257 t.Fatal(err)
258 }
259 expected := basicTestTomlOrdered
260 if !bytes.Equal(result.Bytes(), expected) {
261 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
262 }
263 }
264
265 func TestBasicMarshalWithPointer(t *testing.T) {
266 result, err := Marshal(&basicTestData)
267 if err != nil {
268 t.Fatal(err)
269 }
270 expected := basicTestToml
271 if !bytes.Equal(result, expected) {
272 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
273 }
274 }
275
276 func TestBasicMarshalOrderedWithPointer(t *testing.T) {
277 var result bytes.Buffer
278 err := NewEncoder(&result).Order(OrderPreserve).Encode(&basicTestData)
279 if err != nil {
280 t.Fatal(err)
281 }
282 expected := basicTestTomlOrdered
283 if !bytes.Equal(result.Bytes(), expected) {
284 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
285 }
286 }
287
288 func TestBasicUnmarshal(t *testing.T) {
289 result := basicMarshalTestStruct{}
290 err := Unmarshal(basicTestToml, &result)
291 expected := basicTestData
292 if err != nil {
293 t.Fatal(err)
294 }
295 if !reflect.DeepEqual(result, expected) {
296 t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
297 }
298 }
299
300 type quotedKeyMarshalTestStruct struct {
301 String string `toml:"Z.string-àéù"`
302 Float float64 `toml:"Yfloat-𝟘"`
303 Sub basicMarshalTestSubStruct `toml:"Xsubdoc-àéù"`
304 SubList []basicMarshalTestSubStruct `toml:"W.sublist-𝟘"`
305 }
306
307 var quotedKeyMarshalTestData = quotedKeyMarshalTestStruct{
308 String: "Hello",
309 Float: 3.5,
310 Sub: basicMarshalTestSubStruct{"One"},
311 SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
312 }
313
314 var quotedKeyMarshalTestToml = []byte(`"Yfloat-𝟘" = 3.5
315 "Z.string-àéù" = "Hello"
316
317 [["W.sublist-𝟘"]]
318 String2 = "Two"
319
320 [["W.sublist-𝟘"]]
321 String2 = "Three"
322
323 ["Xsubdoc-àéù"]
324 String2 = "One"
325 `)
326
327 func TestBasicMarshalQuotedKey(t *testing.T) {
328 result, err := Marshal(quotedKeyMarshalTestData)
329 if err != nil {
330 t.Fatal(err)
331 }
332 expected := quotedKeyMarshalTestToml
333 if !bytes.Equal(result, expected) {
334 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
335 }
336 }
337
338 func TestBasicUnmarshalQuotedKey(t *testing.T) {
339 tree, err := LoadBytes(quotedKeyMarshalTestToml)
340 if err != nil {
341 t.Fatal(err)
342 }
343
344 var q quotedKeyMarshalTestStruct
345 tree.Unmarshal(&q)
346 fmt.Println(q)
347
348 if !reflect.DeepEqual(quotedKeyMarshalTestData, q) {
349 t.Errorf("Bad unmarshal: expected\n-----\n%v\n-----\ngot\n-----\n%v\n-----\n", quotedKeyMarshalTestData, q)
350 }
351 }
352
353 type testDoc struct {
354 Title string `toml:"title"`
355 BasicLists testDocBasicLists `toml:"basic_lists"`
356 SubDocPtrs []*testSubDoc `toml:"subdocptrs"`
357 BasicMap map[string]string `toml:"basic_map"`
358 Subdocs testDocSubs `toml:"subdoc"`
359 Basics testDocBasics `toml:"basic"`
360 SubDocList []testSubDoc `toml:"subdoclist"`
361 err int `toml:"shouldntBeHere"`
362 unexported int `toml:"shouldntBeHere"`
363 Unexported2 int `toml:"-"`
364 }
365
366 type testMapDoc struct {
367 Title string `toml:"title"`
368 BasicMap map[string]string `toml:"basic_map"`
369 LongMap map[string]string `toml:"long_map"`
370 }
371
372 type testDocBasics struct {
373 Uint uint `toml:"uint"`
374 Bool bool `toml:"bool"`
375 Float32 float32 `toml:"float"`
376 Float64 float64 `toml:"float64"`
377 Int int `toml:"int"`
378 String *string `toml:"string"`
379 Date time.Time `toml:"date"`
380 unexported int `toml:"shouldntBeHere"`
381 }
382
383 type testDocBasicLists struct {
384 Floats []*float32 `toml:"floats"`
385 Bools []bool `toml:"bools"`
386 Dates []time.Time `toml:"dates"`
387 Ints []int `toml:"ints"`
388 UInts []uint `toml:"uints"`
389 Strings []string `toml:"strings"`
390 }
391
392 type testDocSubs struct {
393 Second *testSubDoc `toml:"second"`
394 First testSubDoc `toml:"first"`
395 }
396
397 type testSubDoc struct {
398 Name string `toml:"name"`
399 unexported int `toml:"shouldntBeHere"`
400 }
401
402 var biteMe = "Bite me"
403 var float1 float32 = 12.3
404 var float2 float32 = 45.6
405 var float3 float32 = 78.9
406 var subdoc = testSubDoc{"Second", 0}
407
408 var docData = testDoc{
409 Title: "TOML Marshal Testing",
410 unexported: 0,
411 Unexported2: 0,
412 Basics: testDocBasics{
413 Bool: true,
414 Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
415 Float32: 123.4,
416 Float64: 123.456782132399,
417 Int: 5000,
418 Uint: 5001,
419 String: &biteMe,
420 unexported: 0,
421 },
422 BasicLists: testDocBasicLists{
423 Bools: []bool{true, false, true},
424 Dates: []time.Time{
425 time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
426 time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC),
427 },
428 Floats: []*float32{&float1, &float2, &float3},
429 Ints: []int{8001, 8001, 8002},
430 Strings: []string{"One", "Two", "Three"},
431 UInts: []uint{5002, 5003},
432 },
433 BasicMap: map[string]string{
434 "one": "one",
435 "two": "two",
436 },
437 Subdocs: testDocSubs{
438 First: testSubDoc{"First", 0},
439 Second: &subdoc,
440 },
441 SubDocList: []testSubDoc{
442 {"List.First", 0},
443 {"List.Second", 0},
444 },
445 SubDocPtrs: []*testSubDoc{&subdoc},
446 }
447
448 var mapTestDoc = testMapDoc{
449 Title: "TOML Marshal Testing",
450 BasicMap: map[string]string{
451 "one": "one",
452 "two": "two",
453 },
454 LongMap: map[string]string{
455 "h1": "8",
456 "i2": "9",
457 "b3": "2",
458 "d4": "4",
459 "f5": "6",
460 "e6": "5",
461 "a7": "1",
462 "c8": "3",
463 "j9": "10",
464 "g10": "7",
465 },
466 }
467
468 func TestDocMarshal(t *testing.T) {
469 result, err := Marshal(docData)
470 if err != nil {
471 t.Fatal(err)
472 }
473 if !bytes.Equal(result, marshalTestToml) {
474 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", marshalTestToml, result)
475 }
476 }
477
478 func TestDocMarshalOrdered(t *testing.T) {
479 var result bytes.Buffer
480 err := NewEncoder(&result).Order(OrderPreserve).Encode(docData)
481 if err != nil {
482 t.Fatal(err)
483 }
484 if !bytes.Equal(result.Bytes(), marshalOrderPreserveToml) {
485 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", marshalOrderPreserveToml, result.Bytes())
486 }
487 }
488
489 func TestDocMarshalMaps(t *testing.T) {
490 result, err := Marshal(mapTestDoc)
491 if err != nil {
492 t.Fatal(err)
493 }
494 if !bytes.Equal(result, mashalOrderPreserveMapToml) {
495 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", mashalOrderPreserveMapToml, result)
496 }
497 }
498
499 func TestDocMarshalOrderedMaps(t *testing.T) {
500 var result bytes.Buffer
501 err := NewEncoder(&result).Order(OrderPreserve).Encode(mapTestDoc)
502 if err != nil {
503 t.Fatal(err)
504 }
505 if !bytes.Equal(result.Bytes(), mashalOrderPreserveMapToml) {
506 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", mashalOrderPreserveMapToml, result.Bytes())
507 }
508 }
509
510 func TestDocMarshalPointer(t *testing.T) {
511 result, err := Marshal(&docData)
512 if err != nil {
513 t.Fatal(err)
514 }
515
516 if !bytes.Equal(result, marshalTestToml) {
517 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", marshalTestToml, result)
518 }
519 }
520
521 func TestDocUnmarshal(t *testing.T) {
522 result := testDoc{}
523 err := Unmarshal(marshalTestToml, &result)
524 expected := docData
525 if err != nil {
526 t.Fatal(err)
527 }
528 if !reflect.DeepEqual(result, expected) {
529 resStr, _ := json.MarshalIndent(result, "", " ")
530 expStr, _ := json.MarshalIndent(expected, "", " ")
531 t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
532 }
533 }
534
535 func TestDocPartialUnmarshal(t *testing.T) {
536 file, err := ioutil.TempFile("", "test-*.toml")
537 if err != nil {
538 t.Fatal(err)
539 }
540 defer os.Remove(file.Name())
541
542 err = ioutil.WriteFile(file.Name(), marshalTestToml, 0)
543 if err != nil {
544 t.Fatal(err)
545 }
546
547 tree, _ := LoadFile(file.Name())
548 subTree := tree.Get("subdoc").(*Tree)
549
550 result := testDocSubs{}
551 err = subTree.Unmarshal(&result)
552 expected := docData.Subdocs
553 if err != nil {
554 t.Fatal(err)
555 }
556 if !reflect.DeepEqual(result, expected) {
557 resStr, _ := json.MarshalIndent(result, "", " ")
558 expStr, _ := json.MarshalIndent(expected, "", " ")
559 t.Errorf("Bad partial unmartial: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
560 }
561 }
562
563 type tomlTypeCheckTest struct {
564 name string
565 item interface{}
566 typ int
567 }
568
569 func TestTypeChecks(t *testing.T) {
570 tests := []tomlTypeCheckTest{
571 {"bool", true, 0},
572 {"bool", false, 0},
573 {"int", int(2), 0},
574 {"int8", int8(2), 0},
575 {"int16", int16(2), 0},
576 {"int32", int32(2), 0},
577 {"int64", int64(2), 0},
578 {"uint", uint(2), 0},
579 {"uint8", uint8(2), 0},
580 {"uint16", uint16(2), 0},
581 {"uint32", uint32(2), 0},
582 {"uint64", uint64(2), 0},
583 {"float32", float32(3.14), 0},
584 {"float64", float64(3.14), 0},
585 {"string", "lorem ipsum", 0},
586 {"time", time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC), 0},
587 {"stringlist", []string{"hello", "hi"}, 1},
588 {"stringlistptr", &[]string{"hello", "hi"}, 1},
589 {"stringarray", [2]string{"hello", "hi"}, 1},
590 {"stringarrayptr", &[2]string{"hello", "hi"}, 1},
591 {"timelist", []time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
592 {"timelistptr", &[]time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
593 {"timearray", [1]time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
594 {"timearrayptr", &[1]time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
595 {"objectlist", []tomlTypeCheckTest{}, 2},
596 {"objectlistptr", &[]tomlTypeCheckTest{}, 2},
597 {"objectarray", [2]tomlTypeCheckTest{{}, {}}, 2},
598 {"objectlistptr", &[2]tomlTypeCheckTest{{}, {}}, 2},
599 {"object", tomlTypeCheckTest{}, 3},
600 {"objectptr", &tomlTypeCheckTest{}, 3},
601 }
602
603 for _, test := range tests {
604 expected := []bool{false, false, false, false}
605 expected[test.typ] = true
606 result := []bool{
607 isPrimitive(reflect.TypeOf(test.item)),
608 isOtherSequence(reflect.TypeOf(test.item)),
609 isTreeSequence(reflect.TypeOf(test.item)),
610 isTree(reflect.TypeOf(test.item)),
611 }
612 if !reflect.DeepEqual(expected, result) {
613 t.Errorf("Bad type check on %q: expected %v, got %v", test.name, expected, result)
614 }
615 }
616 }
617
618 type unexportedMarshalTestStruct struct {
619 String string `toml:"string"`
620 StringList []string `toml:"strlist"`
621 Sub basicMarshalTestSubStruct `toml:"subdoc"`
622 SubList []basicMarshalTestSubStruct `toml:"sublist"`
623 unexported int `toml:"shouldntBeHere"`
624 Unexported2 int `toml:"-"`
625 }
626
627 var unexportedTestData = unexportedMarshalTestStruct{
628 String: "Hello",
629 StringList: []string{"Howdy", "Hey There"},
630 Sub: basicMarshalTestSubStruct{"One"},
631 SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
632 unexported: 0,
633 Unexported2: 0,
634 }
635
636 var unexportedTestToml = []byte(`string = "Hello"
637 strlist = ["Howdy","Hey There"]
638 unexported = 1
639 shouldntBeHere = 2
640
641 [subdoc]
642 String2 = "One"
643
644 [[sublist]]
645 String2 = "Two"
646
647 [[sublist]]
648 String2 = "Three"
649 `)
650
651 func TestUnexportedUnmarshal(t *testing.T) {
652 result := unexportedMarshalTestStruct{}
653 err := Unmarshal(unexportedTestToml, &result)
654 expected := unexportedTestData
655 if err != nil {
656 t.Fatal(err)
657 }
658 if !reflect.DeepEqual(result, expected) {
659 t.Errorf("Bad unexported unmarshal: expected %v, got %v", expected, result)
660 }
661 }
662
663 type errStruct struct {
664 Bool bool `toml:"bool"`
665 Date time.Time `toml:"date"`
666 Float float64 `toml:"float"`
667 Int int16 `toml:"int"`
668 String *string `toml:"string"`
669 }
670
671 var errTomls = []string{
672 "bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
673 "bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
674 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"",
675 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"",
676 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
677 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
678 "bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
679 "bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
680 "bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"",
681 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"",
682 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1",
683 }
684
685 type mapErr struct {
686 Vals map[string]float64
687 }
688
689 type intErr struct {
690 Int1 int
691 Int2 int8
692 Int3 int16
693 Int4 int32
694 Int5 int64
695 UInt1 uint
696 UInt2 uint8
697 UInt3 uint16
698 UInt4 uint32
699 UInt5 uint64
700 Flt1 float32
701 Flt2 float64
702 }
703
704 var intErrTomls = []string{
705 "Int1 = []\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
706 "Int1 = 1\nInt2 = []\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
707 "Int1 = 1\nInt2 = 2\nInt3 = []\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
708 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = []\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
709 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = []\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
710 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = []\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
711 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = []\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
712 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = []\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
713 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = []\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0",
714 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = []\nFlt1 = 1.0\nFlt2 = 2.0",
715 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0",
716 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []",
717 }
718
719 func TestErrUnmarshal(t *testing.T) {
720 for ind, toml := range errTomls {
721 result := errStruct{}
722 err := Unmarshal([]byte(toml), &result)
723 if err == nil {
724 t.Errorf("Expected err from case %d\n", ind)
725 }
726 }
727 result2 := mapErr{}
728 err := Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2)
729 if err == nil {
730 t.Errorf("Expected err from map")
731 }
732 for ind, toml := range intErrTomls {
733 result3 := intErr{}
734 err := Unmarshal([]byte(toml), &result3)
735 if err == nil {
736 t.Errorf("Expected int err from case %d\n", ind)
737 }
738 }
739 }
740
741 type emptyMarshalTestStruct struct {
742 Title string `toml:"title"`
743 Bool bool `toml:"bool"`
744 Int int `toml:"int"`
745 String string `toml:"string"`
746 StringList []string `toml:"stringlist"`
747 Ptr *basicMarshalTestStruct `toml:"ptr"`
748 Map map[string]string `toml:"map"`
749 }
750
751 var emptyTestData = emptyMarshalTestStruct{
752 Title: "Placeholder",
753 Bool: false,
754 Int: 0,
755 String: "",
756 StringList: []string{},
757 Ptr: nil,
758 Map: map[string]string{},
759 }
760
761 var emptyTestToml = []byte(`bool = false
762 int = 0
763 string = ""
764 stringlist = []
765 title = "Placeholder"
766
767 [map]
768 `)
769
770 type emptyMarshalTestStruct2 struct {
771 Title string `toml:"title"`
772 Bool bool `toml:"bool,omitempty"`
773 Int int `toml:"int, omitempty"`
774 String string `toml:"string,omitempty "`
775 StringList []string `toml:"stringlist,omitempty"`
776 Ptr *basicMarshalTestStruct `toml:"ptr,omitempty"`
777 Map map[string]string `toml:"map,omitempty"`
778 }
779
780 var emptyTestData2 = emptyMarshalTestStruct2{
781 Title: "Placeholder",
782 Bool: false,
783 Int: 0,
784 String: "",
785 StringList: []string{},
786 Ptr: nil,
787 Map: map[string]string{},
788 }
789
790 var emptyTestToml2 = []byte(`title = "Placeholder"
791 `)
792
793 func TestEmptyMarshal(t *testing.T) {
794 result, err := Marshal(emptyTestData)
795 if err != nil {
796 t.Fatal(err)
797 }
798 expected := emptyTestToml
799 if !bytes.Equal(result, expected) {
800 t.Errorf("Bad empty marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
801 }
802 }
803
804 func TestEmptyMarshalOmit(t *testing.T) {
805 result, err := Marshal(emptyTestData2)
806 if err != nil {
807 t.Fatal(err)
808 }
809 expected := emptyTestToml2
810 if !bytes.Equal(result, expected) {
811 t.Errorf("Bad empty omit marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
812 }
813 }
814
815 func TestEmptyUnmarshal(t *testing.T) {
816 result := emptyMarshalTestStruct{}
817 err := Unmarshal(emptyTestToml, &result)
818 expected := emptyTestData
819 if err != nil {
820 t.Fatal(err)
821 }
822 if !reflect.DeepEqual(result, expected) {
823 t.Errorf("Bad empty unmarshal: expected %v, got %v", expected, result)
824 }
825 }
826
827 func TestEmptyUnmarshalOmit(t *testing.T) {
828 result := emptyMarshalTestStruct2{}
829 err := Unmarshal(emptyTestToml, &result)
830 expected := emptyTestData2
831 if err != nil {
832 t.Fatal(err)
833 }
834 if !reflect.DeepEqual(result, expected) {
835 t.Errorf("Bad empty omit unmarshal: expected %v, got %v", expected, result)
836 }
837 }
838
839 type pointerMarshalTestStruct struct {
840 Str *string
841 List *[]string
842 ListPtr *[]*string
843 Map *map[string]string
844 MapPtr *map[string]*string
845 EmptyStr *string
846 EmptyList *[]string
847 EmptyMap *map[string]string
848 DblPtr *[]*[]*string
849 }
850
851 var pointerStr = "Hello"
852 var pointerList = []string{"Hello back"}
853 var pointerListPtr = []*string{&pointerStr}
854 var pointerMap = map[string]string{"response": "Goodbye"}
855 var pointerMapPtr = map[string]*string{"alternate": &pointerStr}
856 var pointerTestData = pointerMarshalTestStruct{
857 Str: &pointerStr,
858 List: &pointerList,
859 ListPtr: &pointerListPtr,
860 Map: &pointerMap,
861 MapPtr: &pointerMapPtr,
862 EmptyStr: nil,
863 EmptyList: nil,
864 EmptyMap: nil,
865 }
866
867 var pointerTestToml = []byte(`List = ["Hello back"]
868 ListPtr = ["Hello"]
869 Str = "Hello"
870
871 [Map]
872 response = "Goodbye"
873
874 [MapPtr]
875 alternate = "Hello"
876 `)
877
878 func TestPointerMarshal(t *testing.T) {
879 result, err := Marshal(pointerTestData)
880 if err != nil {
881 t.Fatal(err)
882 }
883 expected := pointerTestToml
884 if !bytes.Equal(result, expected) {
885 t.Errorf("Bad pointer marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
886 }
887 }
888
889 func TestPointerUnmarshal(t *testing.T) {
890 result := pointerMarshalTestStruct{}
891 err := Unmarshal(pointerTestToml, &result)
892 expected := pointerTestData
893 if err != nil {
894 t.Fatal(err)
895 }
896 if !reflect.DeepEqual(result, expected) {
897 t.Errorf("Bad pointer unmarshal: expected %v, got %v", expected, result)
898 }
899 }
900
901 func TestUnmarshalTypeMismatch(t *testing.T) {
902 result := pointerMarshalTestStruct{}
903 err := Unmarshal([]byte("List = 123"), &result)
904 if !strings.HasPrefix(err.Error(), "(1, 1): Can't convert 123(int64) to []string(slice)") {
905 t.Errorf("Type mismatch must be reported: got %v", err.Error())
906 }
907 }
908
909 type nestedMarshalTestStruct struct {
910 String [][]string
911
912 StringPtr *[]*[]*string
913
914 }
915
916 var str1 = "Three"
917 var str2 = "Four"
918 var strPtr = []*string{&str1, &str2}
919 var strPtr2 = []*[]*string{&strPtr}
920
921 var nestedTestData = nestedMarshalTestStruct{
922 String: [][]string{{"Five", "Six"}, {"One", "Two"}},
923 StringPtr: &strPtr2,
924 }
925
926 var nestedTestToml = []byte(`String = [["Five", "Six"], ["One", "Two"]]
927 StringPtr = [["Three", "Four"]]
928 `)
929
930 func TestNestedMarshal(t *testing.T) {
931 result, err := Marshal(nestedTestData)
932 if err != nil {
933 t.Fatal(err)
934 }
935 expected := nestedTestToml
936 if !bytes.Equal(result, expected) {
937 t.Errorf("Bad nested marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
938 }
939 }
940
941 func TestNestedUnmarshal(t *testing.T) {
942 result := nestedMarshalTestStruct{}
943 err := Unmarshal(nestedTestToml, &result)
944 expected := nestedTestData
945 if err != nil {
946 t.Fatal(err)
947 }
948 if !reflect.DeepEqual(result, expected) {
949 t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result)
950 }
951 }
952
953 type customMarshalerParent struct {
954 Self customMarshaler `toml:"me"`
955 Friends []customMarshaler `toml:"friends"`
956 }
957
958 type customMarshaler struct {
959 FirstName string
960 LastName string
961 }
962
963 func (c customMarshaler) MarshalTOML() ([]byte, error) {
964 fullName := fmt.Sprintf("%s %s", c.FirstName, c.LastName)
965 return []byte(fullName), nil
966 }
967
968 var customMarshalerData = customMarshaler{FirstName: "Sally", LastName: "Fields"}
969 var customMarshalerToml = []byte(`Sally Fields`)
970 var nestedCustomMarshalerData = customMarshalerParent{
971 Self: customMarshaler{FirstName: "Maiku", LastName: "Suteda"},
972 Friends: []customMarshaler{customMarshalerData},
973 }
974 var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"]
975 me = "Maiku Suteda"
976 `)
977 var nestedCustomMarshalerTomlForUnmarshal = []byte(`[friends]
978 FirstName = "Sally"
979 LastName = "Fields"`)
980
981 func TestCustomMarshaler(t *testing.T) {
982 result, err := Marshal(customMarshalerData)
983 if err != nil {
984 t.Fatal(err)
985 }
986 expected := customMarshalerToml
987 if !bytes.Equal(result, expected) {
988 t.Errorf("Bad custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
989 }
990 }
991
992 type IntOrString string
993
994 func (x *IntOrString) MarshalTOML() ([]byte, error) {
995 s := *(*string)(x)
996 _, err := strconv.Atoi(s)
997 if err != nil {
998 return []byte(fmt.Sprintf(`"%s"`, s)), nil
999 }
1000 return []byte(s), nil
1001 }
1002
1003 func TestNestedCustomMarshaler(t *testing.T) {
1004 num := IntOrString("100")
1005 str := IntOrString("hello")
1006 var parent = struct {
1007 IntField *IntOrString `toml:"int"`
1008 StringField *IntOrString `toml:"string"`
1009 }{
1010 &num,
1011 &str,
1012 }
1013
1014 result, err := Marshal(parent)
1015 if err != nil {
1016 t.Fatal(err)
1017 }
1018 expected := `int = 100
1019 string = "hello"
1020 `
1021 if !bytes.Equal(result, []byte(expected)) {
1022 t.Errorf("Bad nested text marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1023 }
1024 }
1025
1026 type textMarshaler struct {
1027 FirstName string
1028 LastName string
1029 }
1030
1031 func (m textMarshaler) MarshalText() ([]byte, error) {
1032 fullName := fmt.Sprintf("%s %s", m.FirstName, m.LastName)
1033 return []byte(fullName), nil
1034 }
1035
1036 func TestTextMarshaler(t *testing.T) {
1037 m := textMarshaler{FirstName: "Sally", LastName: "Fields"}
1038
1039 result, err := Marshal(m)
1040 if err != nil {
1041 t.Fatal(err)
1042 }
1043 expected := `Sally Fields`
1044 if !bytes.Equal(result, []byte(expected)) {
1045 t.Errorf("Bad text marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1046 }
1047 }
1048
1049 func TestUnmarshalTextMarshaler(t *testing.T) {
1050 var nested = struct {
1051 Friends textMarshaler `toml:"friends"`
1052 }{}
1053
1054 var expected = struct {
1055 Friends textMarshaler `toml:"friends"`
1056 }{
1057 Friends: textMarshaler{FirstName: "Sally", LastName: "Fields"},
1058 }
1059
1060 err := Unmarshal(nestedCustomMarshalerTomlForUnmarshal, &nested)
1061 if err != nil {
1062 t.Fatal(err)
1063 }
1064 if !reflect.DeepEqual(nested, expected) {
1065 t.Errorf("Bad unmarshal: expected %v, got %v", expected, nested)
1066 }
1067 }
1068
1069 func TestNestedTextMarshaler(t *testing.T) {
1070 var parent = struct {
1071 Self textMarshaler `toml:"me"`
1072 Friends []textMarshaler `toml:"friends"`
1073 Stranger *textMarshaler `toml:"stranger"`
1074 }{
1075 Self: textMarshaler{FirstName: "Maiku", LastName: "Suteda"},
1076 Friends: []textMarshaler{textMarshaler{FirstName: "Sally", LastName: "Fields"}},
1077 Stranger: &textMarshaler{FirstName: "Earl", LastName: "Henson"},
1078 }
1079
1080 result, err := Marshal(parent)
1081 if err != nil {
1082 t.Fatal(err)
1083 }
1084 expected := `friends = ["Sally Fields"]
1085 me = "Maiku Suteda"
1086 stranger = "Earl Henson"
1087 `
1088 if !bytes.Equal(result, []byte(expected)) {
1089 t.Errorf("Bad nested text marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1090 }
1091 }
1092
1093 type precedentMarshaler struct {
1094 FirstName string
1095 LastName string
1096 }
1097
1098 func (m precedentMarshaler) MarshalText() ([]byte, error) {
1099 return []byte("shadowed"), nil
1100 }
1101
1102 func (m precedentMarshaler) MarshalTOML() ([]byte, error) {
1103 fullName := fmt.Sprintf("%s %s", m.FirstName, m.LastName)
1104 return []byte(fullName), nil
1105 }
1106
1107 func TestPrecedentMarshaler(t *testing.T) {
1108 m := textMarshaler{FirstName: "Sally", LastName: "Fields"}
1109
1110 result, err := Marshal(m)
1111 if err != nil {
1112 t.Fatal(err)
1113 }
1114 expected := `Sally Fields`
1115 if !bytes.Equal(result, []byte(expected)) {
1116 t.Errorf("Bad text marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1117 }
1118 }
1119
1120 type customPointerMarshaler struct {
1121 FirstName string
1122 LastName string
1123 }
1124
1125 func (m *customPointerMarshaler) MarshalTOML() ([]byte, error) {
1126 return []byte(`"hidden"`), nil
1127 }
1128
1129 type textPointerMarshaler struct {
1130 FirstName string
1131 LastName string
1132 }
1133
1134 func (m *textPointerMarshaler) MarshalText() ([]byte, error) {
1135 return []byte("hidden"), nil
1136 }
1137
1138 func TestPointerMarshaler(t *testing.T) {
1139 var parent = struct {
1140 Self customPointerMarshaler `toml:"me"`
1141 Stranger *customPointerMarshaler `toml:"stranger"`
1142 Friend textPointerMarshaler `toml:"friend"`
1143 Fiend *textPointerMarshaler `toml:"fiend"`
1144 }{
1145 Self: customPointerMarshaler{FirstName: "Maiku", LastName: "Suteda"},
1146 Stranger: &customPointerMarshaler{FirstName: "Earl", LastName: "Henson"},
1147 Friend: textPointerMarshaler{FirstName: "Sally", LastName: "Fields"},
1148 Fiend: &textPointerMarshaler{FirstName: "Casper", LastName: "Snider"},
1149 }
1150
1151 result, err := Marshal(parent)
1152 if err != nil {
1153 t.Fatal(err)
1154 }
1155 expected := `fiend = "hidden"
1156 stranger = "hidden"
1157
1158 [friend]
1159 FirstName = "Sally"
1160 LastName = "Fields"
1161
1162 [me]
1163 FirstName = "Maiku"
1164 LastName = "Suteda"
1165 `
1166 if !bytes.Equal(result, []byte(expected)) {
1167 t.Errorf("Bad nested text marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1168 }
1169 }
1170
1171 func TestPointerCustomMarshalerSequence(t *testing.T) {
1172 var customPointerMarshalerSlice *[]*customPointerMarshaler
1173 var customPointerMarshalerArray *[2]*customPointerMarshaler
1174
1175 if !isCustomMarshalerSequence(reflect.TypeOf(customPointerMarshalerSlice)) {
1176 t.Errorf("error: should be a sequence of custom marshaler interfaces")
1177 }
1178 if !isCustomMarshalerSequence(reflect.TypeOf(customPointerMarshalerArray)) {
1179 t.Errorf("error: should be a sequence of custom marshaler interfaces")
1180 }
1181 }
1182
1183 func TestPointerTextMarshalerSequence(t *testing.T) {
1184 var textPointerMarshalerSlice *[]*textPointerMarshaler
1185 var textPointerMarshalerArray *[2]*textPointerMarshaler
1186
1187 if !isTextMarshalerSequence(reflect.TypeOf(textPointerMarshalerSlice)) {
1188 t.Errorf("error: should be a sequence of text marshaler interfaces")
1189 }
1190 if !isTextMarshalerSequence(reflect.TypeOf(textPointerMarshalerArray)) {
1191 t.Errorf("error: should be a sequence of text marshaler interfaces")
1192 }
1193 }
1194
1195 var commentTestToml = []byte(`
1196 # it's a comment on type
1197 [postgres]
1198 # isCommented = "dvalue"
1199 noComment = "cvalue"
1200
1201 # A comment on AttrB with a
1202 # break line
1203 password = "bvalue"
1204
1205 # A comment on AttrA
1206 user = "avalue"
1207
1208 [[postgres.My]]
1209
1210 # a comment on my on typeC
1211 My = "Foo"
1212
1213 [[postgres.My]]
1214
1215 # a comment on my on typeC
1216 My = "Baar"
1217 `)
1218
1219 func TestMarshalComment(t *testing.T) {
1220 type TypeC struct {
1221 My string `comment:"a comment on my on typeC"`
1222 }
1223 type TypeB struct {
1224 AttrA string `toml:"user" comment:"A comment on AttrA"`
1225 AttrB string `toml:"password" comment:"A comment on AttrB with a\n break line"`
1226 AttrC string `toml:"noComment"`
1227 AttrD string `toml:"isCommented" commented:"true"`
1228 My []TypeC
1229 }
1230 type TypeA struct {
1231 TypeB TypeB `toml:"postgres" comment:"it's a comment on type"`
1232 }
1233
1234 ta := []TypeC{{My: "Foo"}, {My: "Baar"}}
1235 config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", AttrC: "cvalue", AttrD: "dvalue", My: ta}}
1236 result, err := Marshal(config)
1237 if err != nil {
1238 t.Fatal(err)
1239 }
1240 expected := commentTestToml
1241 if !bytes.Equal(result, expected) {
1242 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1243 }
1244 }
1245
1246 func TestMarshalMultilineCommented(t *testing.T) {
1247 expectedToml := []byte(`# MultilineArray = [
1248 # 100,
1249 # 200,
1250 # 300,
1251 # ]
1252 # MultilineNestedArray = [
1253 # [
1254 # "a",
1255 # "b",
1256 # "c",
1257 # ],
1258 # [
1259 # "d",
1260 # "e",
1261 # "f",
1262 # ],
1263 # ]
1264 # MultilineString = """
1265 # I
1266 # am
1267 # Allen"""
1268 NonCommented = "Not commented line"
1269 `)
1270 type StructWithMultiline struct {
1271 NonCommented string
1272 MultilineString string `commented:"true" multiline:"true"`
1273 MultilineArray []int `commented:"true"`
1274 MultilineNestedArray [][]string `commented:"true"`
1275 }
1276
1277 var buf bytes.Buffer
1278 enc := NewEncoder(&buf)
1279 if err := enc.ArraysWithOneElementPerLine(true).Encode(StructWithMultiline{
1280 NonCommented: "Not commented line",
1281 MultilineString: "I\nam\nAllen",
1282 MultilineArray: []int{100, 200, 300},
1283 MultilineNestedArray: [][]string{
1284 {"a", "b", "c"},
1285 {"d", "e", "f"},
1286 },
1287 }); err == nil {
1288 result := buf.Bytes()
1289 if !bytes.Equal(result, expectedToml) {
1290 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expectedToml, result)
1291 }
1292 } else {
1293 t.Fatal(err)
1294 }
1295 }
1296
1297 func TestMarshalMultilineLiteral(t *testing.T) {
1298 type Doc struct {
1299 Value string `multiline:"true" literal:"true"`
1300 }
1301
1302 d := Doc{
1303 Value: "hello\nworld\ttest\nend",
1304 }
1305
1306 expected := []byte(`Value = '''
1307 hello
1308 world test
1309 end
1310 '''
1311 `)
1312
1313 b, err := Marshal(d)
1314 if err != nil {
1315 t.Fatal("unexpected error")
1316 }
1317
1318 if !bytes.Equal(b, expected) {
1319 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
1320 }
1321 }
1322
1323 func TestMarshalNonPrimitiveTypeCommented(t *testing.T) {
1324 expectedToml := []byte(`
1325 # [CommentedMapField]
1326
1327 # [CommentedMapField.CommentedMapField1]
1328 # SingleLineString = "This line should be commented out"
1329
1330 # [CommentedMapField.CommentedMapField2]
1331 # SingleLineString = "This line should be commented out"
1332
1333 # [CommentedStructField]
1334
1335 # [CommentedStructField.CommentedStructField]
1336 # MultilineArray = [
1337 # 1,
1338 # 2,
1339 # ]
1340 # MultilineNestedArray = [
1341 # [
1342 # 10,
1343 # 20,
1344 # ],
1345 # [
1346 # 100,
1347 # 200,
1348 # ],
1349 # ]
1350 # MultilineString = """
1351 # This line
1352 # should be
1353 # commented out"""
1354
1355 # [CommentedStructField.NotCommentedStructField]
1356 # MultilineArray = [
1357 # 1,
1358 # 2,
1359 # ]
1360 # MultilineNestedArray = [
1361 # [
1362 # 10,
1363 # 20,
1364 # ],
1365 # [
1366 # 100,
1367 # 200,
1368 # ],
1369 # ]
1370 # MultilineString = """
1371 # This line
1372 # should be
1373 # commented out"""
1374
1375 [NotCommentedStructField]
1376
1377 # [NotCommentedStructField.CommentedStructField]
1378 # MultilineArray = [
1379 # 1,
1380 # 2,
1381 # ]
1382 # MultilineNestedArray = [
1383 # [
1384 # 10,
1385 # 20,
1386 # ],
1387 # [
1388 # 100,
1389 # 200,
1390 # ],
1391 # ]
1392 # MultilineString = """
1393 # This line
1394 # should be
1395 # commented out"""
1396
1397 [NotCommentedStructField.NotCommentedStructField]
1398 MultilineArray = [
1399 3,
1400 4,
1401 ]
1402 MultilineNestedArray = [
1403 [
1404 30,
1405 40,
1406 ],
1407 [
1408 300,
1409 400,
1410 ],
1411 ]
1412 MultilineString = """
1413 This line
1414 should NOT be
1415 commented out"""
1416 `)
1417 type InnerStruct struct {
1418 MultilineString string `multiline:"true"`
1419 MultilineArray []int
1420 MultilineNestedArray [][]int
1421 }
1422 type MiddleStruct struct {
1423 NotCommentedStructField InnerStruct
1424 CommentedStructField InnerStruct `commented:"true"`
1425 }
1426 type OuterStruct struct {
1427 CommentedStructField MiddleStruct `commented:"true"`
1428 NotCommentedStructField MiddleStruct
1429 CommentedMapField map[string]struct{ SingleLineString string } `commented:"true"`
1430 }
1431
1432 commentedTestStruct := OuterStruct{
1433 CommentedStructField: MiddleStruct{
1434 NotCommentedStructField: InnerStruct{
1435 MultilineString: "This line\nshould be\ncommented out",
1436 MultilineArray: []int{1, 2},
1437 MultilineNestedArray: [][]int{{10, 20}, {100, 200}},
1438 },
1439 CommentedStructField: InnerStruct{
1440 MultilineString: "This line\nshould be\ncommented out",
1441 MultilineArray: []int{1, 2},
1442 MultilineNestedArray: [][]int{{10, 20}, {100, 200}},
1443 },
1444 },
1445 NotCommentedStructField: MiddleStruct{
1446 NotCommentedStructField: InnerStruct{
1447 MultilineString: "This line\nshould NOT be\ncommented out",
1448 MultilineArray: []int{3, 4},
1449 MultilineNestedArray: [][]int{{30, 40}, {300, 400}},
1450 },
1451 CommentedStructField: InnerStruct{
1452 MultilineString: "This line\nshould be\ncommented out",
1453 MultilineArray: []int{1, 2},
1454 MultilineNestedArray: [][]int{{10, 20}, {100, 200}},
1455 },
1456 },
1457 CommentedMapField: map[string]struct{ SingleLineString string }{
1458 "CommentedMapField1": {
1459 SingleLineString: "This line should be commented out",
1460 },
1461 "CommentedMapField2": {
1462 SingleLineString: "This line should be commented out",
1463 },
1464 },
1465 }
1466
1467 var buf bytes.Buffer
1468 enc := NewEncoder(&buf)
1469 if err := enc.ArraysWithOneElementPerLine(true).Encode(commentedTestStruct); err == nil {
1470 result := buf.Bytes()
1471 if !bytes.Equal(result, expectedToml) {
1472 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expectedToml, result)
1473 }
1474 } else {
1475 t.Fatal(err)
1476 }
1477 }
1478
1479 func TestCompactComments(t *testing.T) {
1480 expected := []byte(`
1481 [first-section]
1482 # comment for first-key
1483 first-key = 1
1484 # comment for second-key
1485 second-key = "value"
1486 # comment for commented third-key
1487 # third-key = []
1488
1489 [second-section]
1490 # comment for first-key
1491 first-key = 2
1492 # comment for second-key
1493 second-key = "another value"
1494 # comment for commented third-key
1495 # third-key = ["value1", "value2"]
1496 `)
1497 type Settings struct {
1498 FirstKey int `toml:"first-key" comment:"comment for first-key"`
1499 SecondKey string `toml:"second-key" comment:"comment for second-key"`
1500 ThirdKey []string `toml:"third-key" comment:"comment for commented third-key" commented:"true"`
1501 }
1502 type Config struct {
1503 FirstSection Settings `toml:"first-section"`
1504 SecondSection Settings `toml:"second-section"`
1505 }
1506 data := Config{
1507 FirstSection: Settings{1, "value", []string{}},
1508 SecondSection: Settings{2, "another value", []string{"value1", "value2"}},
1509 }
1510 buf := new(bytes.Buffer)
1511 if err := NewEncoder(buf).CompactComments(true).Encode(data); err != nil {
1512 t.Fatal(err)
1513 }
1514
1515 if !bytes.Equal(expected, buf.Bytes()) {
1516 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, buf.Bytes())
1517 }
1518 }
1519
1520 type mapsTestStruct struct {
1521 Simple map[string]string
1522 Paths map[string]string
1523 Other map[string]float64
1524 X struct {
1525 Y struct {
1526 Z map[string]bool
1527 }
1528 }
1529 }
1530
1531 var mapsTestData = mapsTestStruct{
1532 Simple: map[string]string{
1533 "one plus one": "two",
1534 "next": "three",
1535 },
1536 Paths: map[string]string{
1537 "/this/is/a/path": "/this/is/also/a/path",
1538 "/heloo.txt": "/tmp/lololo.txt",
1539 },
1540 Other: map[string]float64{
1541 "testing": 3.9999,
1542 },
1543 X: struct{ Y struct{ Z map[string]bool } }{
1544 Y: struct{ Z map[string]bool }{
1545 Z: map[string]bool{
1546 "is.Nested": true,
1547 },
1548 },
1549 },
1550 }
1551 var mapsTestToml = []byte(`
1552 [Other]
1553 "testing" = 3.9999
1554
1555 [Paths]
1556 "/heloo.txt" = "/tmp/lololo.txt"
1557 "/this/is/a/path" = "/this/is/also/a/path"
1558
1559 [Simple]
1560 "next" = "three"
1561 "one plus one" = "two"
1562
1563 [X]
1564
1565 [X.Y]
1566
1567 [X.Y.Z]
1568 "is.Nested" = true
1569 `)
1570
1571 func TestEncodeQuotedMapKeys(t *testing.T) {
1572 var buf bytes.Buffer
1573 if err := NewEncoder(&buf).QuoteMapKeys(true).Encode(mapsTestData); err != nil {
1574 t.Fatal(err)
1575 }
1576 result := buf.Bytes()
1577 expected := mapsTestToml
1578 if !bytes.Equal(result, expected) {
1579 t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1580 }
1581 }
1582
1583 func TestDecodeQuotedMapKeys(t *testing.T) {
1584 result := mapsTestStruct{}
1585 err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result)
1586 expected := mapsTestData
1587 if err != nil {
1588 t.Fatal(err)
1589 }
1590 if !reflect.DeepEqual(result, expected) {
1591 t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result)
1592 }
1593 }
1594
1595 type structArrayNoTag struct {
1596 A struct {
1597 B []int64
1598 C []int64
1599 }
1600 }
1601
1602 func TestMarshalArray(t *testing.T) {
1603 expected := []byte(`
1604 [A]
1605 B = [1, 2, 3]
1606 C = [1]
1607 `)
1608
1609 m := structArrayNoTag{
1610 A: struct {
1611 B []int64
1612 C []int64
1613 }{
1614 B: []int64{1, 2, 3},
1615 C: []int64{1},
1616 },
1617 }
1618
1619 b, err := Marshal(m)
1620
1621 if err != nil {
1622 t.Fatal(err)
1623 }
1624
1625 if !bytes.Equal(b, expected) {
1626 t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
1627 }
1628 }
1629
1630 func TestMarshalArrayOnePerLine(t *testing.T) {
1631 expected := []byte(`
1632 [A]
1633 B = [
1634 1,
1635 2,
1636 3,
1637 ]
1638 C = [1]
1639 `)
1640
1641 m := structArrayNoTag{
1642 A: struct {
1643 B []int64
1644 C []int64
1645 }{
1646 B: []int64{1, 2, 3},
1647 C: []int64{1},
1648 },
1649 }
1650
1651 var buf bytes.Buffer
1652 encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true)
1653 err := encoder.Encode(m)
1654
1655 if err != nil {
1656 t.Fatal(err)
1657 }
1658
1659 b := buf.Bytes()
1660
1661 if !bytes.Equal(b, expected) {
1662 t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
1663 }
1664 }
1665
1666 var customTagTestToml = []byte(`
1667 [postgres]
1668 password = "bvalue"
1669 user = "avalue"
1670
1671 [[postgres.My]]
1672 My = "Foo"
1673
1674 [[postgres.My]]
1675 My = "Baar"
1676 `)
1677
1678 func TestMarshalCustomTag(t *testing.T) {
1679 type TypeC struct {
1680 My string
1681 }
1682 type TypeB struct {
1683 AttrA string `file:"user"`
1684 AttrB string `file:"password"`
1685 My []TypeC
1686 }
1687 type TypeA struct {
1688 TypeB TypeB `file:"postgres"`
1689 }
1690
1691 ta := []TypeC{{My: "Foo"}, {My: "Baar"}}
1692 config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", My: ta}}
1693 var buf bytes.Buffer
1694 err := NewEncoder(&buf).SetTagName("file").Encode(config)
1695 if err != nil {
1696 t.Fatal(err)
1697 }
1698 expected := customTagTestToml
1699 result := buf.Bytes()
1700 if !bytes.Equal(result, expected) {
1701 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1702 }
1703 }
1704
1705 var customCommentTagTestToml = []byte(`
1706 # db connection
1707 [postgres]
1708
1709 # db pass
1710 password = "bvalue"
1711
1712 # db user
1713 user = "avalue"
1714 `)
1715
1716 func TestMarshalCustomComment(t *testing.T) {
1717 type TypeB struct {
1718 AttrA string `toml:"user" descr:"db user"`
1719 AttrB string `toml:"password" descr:"db pass"`
1720 }
1721 type TypeA struct {
1722 TypeB TypeB `toml:"postgres" descr:"db connection"`
1723 }
1724
1725 config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue"}}
1726 var buf bytes.Buffer
1727 err := NewEncoder(&buf).SetTagComment("descr").Encode(config)
1728 if err != nil {
1729 t.Fatal(err)
1730 }
1731 expected := customCommentTagTestToml
1732 result := buf.Bytes()
1733 if !bytes.Equal(result, expected) {
1734 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1735 }
1736 }
1737
1738 var customCommentedTagTestToml = []byte(`
1739 [postgres]
1740 # password = "bvalue"
1741 # user = "avalue"
1742 `)
1743
1744 func TestMarshalCustomCommented(t *testing.T) {
1745 type TypeB struct {
1746 AttrA string `toml:"user" disable:"true"`
1747 AttrB string `toml:"password" disable:"true"`
1748 }
1749 type TypeA struct {
1750 TypeB TypeB `toml:"postgres"`
1751 }
1752
1753 config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue"}}
1754 var buf bytes.Buffer
1755 err := NewEncoder(&buf).SetTagCommented("disable").Encode(config)
1756 if err != nil {
1757 t.Fatal(err)
1758 }
1759 expected := customCommentedTagTestToml
1760 result := buf.Bytes()
1761 if !bytes.Equal(result, expected) {
1762 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1763 }
1764 }
1765
1766 func TestMarshalDirectMultilineString(t *testing.T) {
1767 tree := newTree()
1768 tree.SetWithOptions("mykey", SetOptions{
1769 Multiline: true,
1770 }, "my\x11multiline\nstring\ba\tb\fc\rd\"e\\!")
1771 result, err := tree.Marshal()
1772 if err != nil {
1773 t.Fatal("marshal should not error:", err)
1774 }
1775 expected := []byte("mykey = \"\"\"\nmy\\u0011multiline\nstring\\ba\tb\\fc\rd\"e\\!\"\"\"\n")
1776 if !bytes.Equal(result, expected) {
1777 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1778 }
1779 }
1780
1781 func TestUnmarshalTabInStringAndQuotedKey(t *testing.T) {
1782 type Test struct {
1783 Field1 string `toml:"Fie ld1"`
1784 Field2 string
1785 }
1786
1787 type TestCase struct {
1788 desc string
1789 input []byte
1790 expected Test
1791 }
1792
1793 testCases := []TestCase{
1794 {
1795 desc: "multiline string with tab",
1796 input: []byte("Field2 = \"\"\"\nhello\tworld\"\"\""),
1797 expected: Test{
1798 Field2: "hello\tworld",
1799 },
1800 },
1801 {
1802 desc: "quoted key with tab",
1803 input: []byte("\"Fie\tld1\" = \"key with tab\""),
1804 expected: Test{
1805 Field1: "key with tab",
1806 },
1807 },
1808 {
1809 desc: "basic string tab",
1810 input: []byte("Field2 = \"hello\tworld\""),
1811 expected: Test{
1812 Field2: "hello\tworld",
1813 },
1814 },
1815 }
1816
1817 for i := range testCases {
1818 result := Test{}
1819 err := Unmarshal(testCases[i].input, &result)
1820 if err != nil {
1821 t.Errorf("%s test error:%v", testCases[i].desc, err)
1822 continue
1823 }
1824
1825 if !reflect.DeepEqual(result, testCases[i].expected) {
1826 t.Errorf("%s test error: expected\n-----\n%+v\n-----\ngot\n-----\n%+v\n-----\n",
1827 testCases[i].desc, testCases[i].expected, result)
1828 }
1829 }
1830 }
1831
1832 var customMultilineTagTestToml = []byte(`int_slice = [
1833 1,
1834 2,
1835 3,
1836 ]
1837 `)
1838
1839 func TestMarshalCustomMultiline(t *testing.T) {
1840 type TypeA struct {
1841 AttrA []int `toml:"int_slice" mltln:"true"`
1842 }
1843
1844 config := TypeA{AttrA: []int{1, 2, 3}}
1845 var buf bytes.Buffer
1846 err := NewEncoder(&buf).ArraysWithOneElementPerLine(true).SetTagMultiline("mltln").Encode(config)
1847 if err != nil {
1848 t.Fatal(err)
1849 }
1850 expected := customMultilineTagTestToml
1851 result := buf.Bytes()
1852 if !bytes.Equal(result, expected) {
1853 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1854 }
1855 }
1856
1857 func TestMultilineWithAdjacentQuotationMarks(t *testing.T) {
1858 type testStruct struct {
1859 Str string `multiline:"true"`
1860 }
1861 type testCase struct {
1862 expected []byte
1863 data testStruct
1864 }
1865
1866 testCases := []testCase{
1867 {
1868 expected: []byte(`Str = """
1869 hello\""""
1870 `),
1871 data: testStruct{
1872 Str: "hello\"",
1873 },
1874 },
1875 {
1876 expected: []byte(`Str = """
1877 ""\"""\"""\""""
1878 `),
1879 data: testStruct{
1880 Str: "\"\"\"\"\"\"\"\"\"",
1881 },
1882 },
1883 }
1884 for i := range testCases {
1885 result, err := Marshal(testCases[i].data)
1886 if err != nil {
1887 t.Fatal(err)
1888 }
1889
1890 if !bytes.Equal(result, testCases[i].expected) {
1891 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n",
1892 testCases[i].expected, result)
1893 } else {
1894 var data testStruct
1895 if err = Unmarshal(result, &data); err != nil {
1896 t.Fatal(err)
1897 }
1898 if data.Str != testCases[i].data.Str {
1899 t.Errorf("Round trip test fail: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n",
1900 testCases[i].data.Str, data.Str)
1901 }
1902 }
1903 }
1904 }
1905
1906 func TestMarshalEmbedTree(t *testing.T) {
1907 expected := []byte(`OuterField1 = "Out"
1908 OuterField2 = 1024
1909
1910 [TreeField]
1911 InnerField1 = "In"
1912 InnerField2 = 2048
1913
1914 [TreeField.EmbedStruct]
1915 EmbedField = "Embed"
1916 `)
1917 type InnerStruct struct {
1918 InnerField1 string
1919 InnerField2 int
1920 EmbedStruct struct {
1921 EmbedField string
1922 }
1923 }
1924
1925 type OuterStruct struct {
1926 OuterField1 string
1927 OuterField2 int
1928 TreeField *Tree
1929 }
1930
1931 tree, err := Load(`
1932 InnerField1 = "In"
1933 InnerField2 = 2048
1934
1935 [EmbedStruct]
1936 EmbedField = "Embed"
1937 `)
1938 if err != nil {
1939 t.Fatal(err)
1940 }
1941
1942 out := OuterStruct{
1943 "Out",
1944 1024,
1945 tree,
1946 }
1947 actual, _ := Marshal(out)
1948
1949 if !bytes.Equal(actual, expected) {
1950 t.Errorf("Bad marshal: expected %s, got %s", expected, actual)
1951 }
1952 }
1953
1954 var testDocBasicToml = []byte(`
1955 [document]
1956 bool_val = true
1957 date_val = 1979-05-27T07:32:00Z
1958 float_val = 123.4
1959 int_val = 5000
1960 string_val = "Bite me"
1961 uint_val = 5001
1962 `)
1963
1964 type testDocCustomTag struct {
1965 Doc testDocBasicsCustomTag `file:"document"`
1966 }
1967 type testDocBasicsCustomTag struct {
1968 Bool bool `file:"bool_val"`
1969 Date time.Time `file:"date_val"`
1970 Float float32 `file:"float_val"`
1971 Int int `file:"int_val"`
1972 Uint uint `file:"uint_val"`
1973 String *string `file:"string_val"`
1974 unexported int `file:"shouldntBeHere"`
1975 }
1976
1977 var testDocCustomTagData = testDocCustomTag{
1978 Doc: testDocBasicsCustomTag{
1979 Bool: true,
1980 Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
1981 Float: 123.4,
1982 Int: 5000,
1983 Uint: 5001,
1984 String: &biteMe,
1985 unexported: 0,
1986 },
1987 }
1988
1989 func TestUnmarshalCustomTag(t *testing.T) {
1990 buf := bytes.NewBuffer(testDocBasicToml)
1991
1992 result := testDocCustomTag{}
1993 err := NewDecoder(buf).SetTagName("file").Decode(&result)
1994 if err != nil {
1995 t.Fatal(err)
1996 }
1997 expected := testDocCustomTagData
1998 if !reflect.DeepEqual(result, expected) {
1999 resStr, _ := json.MarshalIndent(result, "", " ")
2000 expStr, _ := json.MarshalIndent(expected, "", " ")
2001 t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
2002
2003 }
2004 }
2005
2006 func TestUnmarshalMap(t *testing.T) {
2007 testToml := []byte(`
2008 a = 1
2009 b = 2
2010 c = 3
2011 `)
2012 var result map[string]int
2013 err := Unmarshal(testToml, &result)
2014 if err != nil {
2015 t.Errorf("Received unexpected error: %s", err)
2016 return
2017 }
2018
2019 expected := map[string]int{
2020 "a": 1,
2021 "b": 2,
2022 "c": 3,
2023 }
2024
2025 if !reflect.DeepEqual(result, expected) {
2026 t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
2027 }
2028 }
2029
2030 func TestUnmarshalMapWithTypedKey(t *testing.T) {
2031 testToml := []byte(`
2032 a = 1
2033 b = 2
2034 c = 3
2035 `)
2036
2037 type letter string
2038 var result map[letter]int
2039 err := Unmarshal(testToml, &result)
2040 if err != nil {
2041 t.Errorf("Received unexpected error: %s", err)
2042 return
2043 }
2044
2045 expected := map[letter]int{
2046 "a": 1,
2047 "b": 2,
2048 "c": 3,
2049 }
2050
2051 if !reflect.DeepEqual(result, expected) {
2052 t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
2053 }
2054 }
2055
2056 func TestUnmarshalNonPointer(t *testing.T) {
2057 a := 1
2058 err := Unmarshal([]byte{}, a)
2059 if err == nil {
2060 t.Fatal("unmarshal should err when given a non pointer")
2061 }
2062 }
2063
2064 func TestUnmarshalInvalidPointerKind(t *testing.T) {
2065 a := 1
2066 err := Unmarshal([]byte{}, &a)
2067 if err == nil {
2068 t.Fatal("unmarshal should err when given an invalid pointer type")
2069 }
2070 }
2071
2072 func TestMarshalSlice(t *testing.T) {
2073 m := make([]int, 1)
2074 m[0] = 1
2075
2076 var buf bytes.Buffer
2077 err := NewEncoder(&buf).Encode(&m)
2078 if err == nil {
2079 t.Error("expected error, got nil")
2080 return
2081 }
2082 if err.Error() != "Only pointer to struct can be marshaled to TOML" {
2083 t.Fail()
2084 }
2085 }
2086
2087 func TestMarshalSlicePointer(t *testing.T) {
2088 m := make([]int, 1)
2089 m[0] = 1
2090
2091 var buf bytes.Buffer
2092 err := NewEncoder(&buf).Encode(m)
2093 if err == nil {
2094 t.Error("expected error, got nil")
2095 return
2096 }
2097 if err.Error() != "Only a struct or map can be marshaled to TOML" {
2098 t.Fail()
2099 }
2100 }
2101
2102 func TestMarshalNestedArrayInlineTables(t *testing.T) {
2103 type table struct {
2104 Value1 int `toml:"ZValue1"`
2105 Value2 int `toml:"YValue2"`
2106 Value3 int `toml:"XValue3"`
2107 }
2108
2109 type nestedTable struct {
2110 Table table
2111 }
2112
2113 nestedArray := struct {
2114 Simple [][]table
2115 SimplePointer *[]*[]table
2116 Nested [][]nestedTable
2117 NestedPointer *[]*[]nestedTable
2118 }{
2119 Simple: [][]table{{{Value1: 1}, {Value1: 10}}},
2120 SimplePointer: &[]*[]table{{{Value2: 2}}},
2121 Nested: [][]nestedTable{{{Table: table{Value3: 3}}}},
2122 NestedPointer: &[]*[]nestedTable{{{Table: table{Value3: -3}}}},
2123 }
2124
2125 expectedPreserve := `Simple = [[{ ZValue1 = 1, YValue2 = 0, XValue3 = 0 }, { ZValue1 = 10, YValue2 = 0, XValue3 = 0 }]]
2126 SimplePointer = [[{ ZValue1 = 0, YValue2 = 2, XValue3 = 0 }]]
2127 Nested = [[{ Table = { ZValue1 = 0, YValue2 = 0, XValue3 = 3 } }]]
2128 NestedPointer = [[{ Table = { ZValue1 = 0, YValue2 = 0, XValue3 = -3 } }]]
2129 `
2130
2131 expectedAlphabetical := `Nested = [[{ Table = { XValue3 = 3, YValue2 = 0, ZValue1 = 0 } }]]
2132 NestedPointer = [[{ Table = { XValue3 = -3, YValue2 = 0, ZValue1 = 0 } }]]
2133 Simple = [[{ XValue3 = 0, YValue2 = 0, ZValue1 = 1 }, { XValue3 = 0, YValue2 = 0, ZValue1 = 10 }]]
2134 SimplePointer = [[{ XValue3 = 0, YValue2 = 2, ZValue1 = 0 }]]
2135 `
2136
2137 var bufPreserve bytes.Buffer
2138 if err := NewEncoder(&bufPreserve).Order(OrderPreserve).Encode(nestedArray); err != nil {
2139 t.Fatalf("unexpected error: %s", err.Error())
2140 }
2141 if !bytes.Equal(bufPreserve.Bytes(), []byte(expectedPreserve)) {
2142 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expectedPreserve, bufPreserve.String())
2143 }
2144
2145 var bufAlphabetical bytes.Buffer
2146 if err := NewEncoder(&bufAlphabetical).Order(OrderAlphabetical).Encode(nestedArray); err != nil {
2147 t.Fatalf("unexpected error: %s", err.Error())
2148 }
2149 if !bytes.Equal(bufAlphabetical.Bytes(), []byte(expectedAlphabetical)) {
2150 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expectedAlphabetical, bufAlphabetical.String())
2151 }
2152 }
2153
2154 type testDuration struct {
2155 Nanosec time.Duration `toml:"nanosec"`
2156 Microsec1 time.Duration `toml:"microsec1"`
2157 Microsec2 *time.Duration `toml:"microsec2"`
2158 Millisec time.Duration `toml:"millisec"`
2159 Sec time.Duration `toml:"sec"`
2160 Min time.Duration `toml:"min"`
2161 Hour time.Duration `toml:"hour"`
2162 Mixed time.Duration `toml:"mixed"`
2163 AString string `toml:"a_string"`
2164 }
2165
2166 var testDurationToml = []byte(`
2167 nanosec = "1ns"
2168 microsec1 = "1us"
2169 microsec2 = "1µs"
2170 millisec = "1ms"
2171 sec = "1s"
2172 min = "1m"
2173 hour = "1h"
2174 mixed = "1h1m1s1ms1µs1ns"
2175 a_string = "15s"
2176 `)
2177
2178 func TestUnmarshalDuration(t *testing.T) {
2179 buf := bytes.NewBuffer(testDurationToml)
2180
2181 result := testDuration{}
2182 err := NewDecoder(buf).Decode(&result)
2183 if err != nil {
2184 t.Fatal(err)
2185 }
2186 ms := time.Duration(1) * time.Microsecond
2187 expected := testDuration{
2188 Nanosec: 1,
2189 Microsec1: time.Microsecond,
2190 Microsec2: &ms,
2191 Millisec: time.Millisecond,
2192 Sec: time.Second,
2193 Min: time.Minute,
2194 Hour: time.Hour,
2195 Mixed: time.Hour +
2196 time.Minute +
2197 time.Second +
2198 time.Millisecond +
2199 time.Microsecond +
2200 time.Nanosecond,
2201 AString: "15s",
2202 }
2203 if !reflect.DeepEqual(result, expected) {
2204 resStr, _ := json.MarshalIndent(result, "", " ")
2205 expStr, _ := json.MarshalIndent(expected, "", " ")
2206 t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
2207
2208 }
2209 }
2210
2211 var testDurationToml2 = []byte(`a_string = "15s"
2212 hour = "1h0m0s"
2213 microsec1 = "1µs"
2214 microsec2 = "1µs"
2215 millisec = "1ms"
2216 min = "1m0s"
2217 mixed = "1h1m1.001001001s"
2218 nanosec = "1ns"
2219 sec = "1s"
2220 `)
2221
2222 func TestMarshalDuration(t *testing.T) {
2223 ms := time.Duration(1) * time.Microsecond
2224 data := testDuration{
2225 Nanosec: 1,
2226 Microsec1: time.Microsecond,
2227 Microsec2: &ms,
2228 Millisec: time.Millisecond,
2229 Sec: time.Second,
2230 Min: time.Minute,
2231 Hour: time.Hour,
2232 Mixed: time.Hour +
2233 time.Minute +
2234 time.Second +
2235 time.Millisecond +
2236 time.Microsecond +
2237 time.Nanosecond,
2238 AString: "15s",
2239 }
2240
2241 var buf bytes.Buffer
2242 err := NewEncoder(&buf).Encode(data)
2243 if err != nil {
2244 t.Fatal(err)
2245 }
2246 expected := testDurationToml2
2247 result := buf.Bytes()
2248 if !bytes.Equal(result, expected) {
2249 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
2250 }
2251 }
2252
2253 type testBadDuration struct {
2254 Val time.Duration `toml:"val"`
2255 }
2256
2257 var testBadDurationToml = []byte(`val = "1z"`)
2258
2259 func TestUnmarshalBadDuration(t *testing.T) {
2260 buf := bytes.NewBuffer(testBadDurationToml)
2261
2262 result := testBadDuration{}
2263 err := NewDecoder(buf).Decode(&result)
2264 if err == nil {
2265 t.Fatal("expected bad duration error")
2266 }
2267 }
2268
2269 var testCamelCaseKeyToml = []byte(`fooBar = 10`)
2270
2271 func TestUnmarshalCamelCaseKey(t *testing.T) {
2272 var x struct {
2273 FooBar int
2274 B int
2275 }
2276
2277 if err := Unmarshal(testCamelCaseKeyToml, &x); err != nil {
2278 t.Fatal(err)
2279 }
2280
2281 if x.FooBar != 10 {
2282 t.Fatal("Did not set camelCase'd key")
2283 }
2284 }
2285
2286 func TestUnmarshalNegativeUint(t *testing.T) {
2287 type check struct{ U uint }
2288
2289 tree, _ := Load("u = -1")
2290 err := tree.Unmarshal(&check{})
2291 if err.Error() != "(1, 1): -1(int64) is negative so does not fit in uint" {
2292 t.Error("expect err:(1, 1): -1(int64) is negative so does not fit in uint but got:", err)
2293 }
2294 }
2295
2296 func TestUnmarshalCheckConversionFloatInt(t *testing.T) {
2297 type conversionCheck struct {
2298 U uint
2299 I int
2300 F float64
2301 }
2302
2303 treeU, _ := Load("u = 1e300")
2304 treeI, _ := Load("i = 1e300")
2305 treeF, _ := Load("f = 9223372036854775806")
2306
2307 errU := treeU.Unmarshal(&conversionCheck{})
2308 errI := treeI.Unmarshal(&conversionCheck{})
2309 errF := treeF.Unmarshal(&conversionCheck{})
2310
2311 if errU.Error() != "(1, 1): Can't convert 1e+300(float64) to uint" {
2312 t.Error("expect err:(1, 1): Can't convert 1e+300(float64) to uint but got:", errU)
2313 }
2314 if errI.Error() != "(1, 1): Can't convert 1e+300(float64) to int" {
2315 t.Error("expect err:(1, 1): Can't convert 1e+300(float64) to int but got:", errI)
2316 }
2317 if errF.Error() != "(1, 1): Can't convert 9223372036854775806(int64) to float64" {
2318 t.Error("expect err:(1, 1): Can't convert 9223372036854775806(int64) to float64 but got:", errF)
2319 }
2320 }
2321
2322 func TestUnmarshalOverflow(t *testing.T) {
2323 type overflow struct {
2324 U8 uint8
2325 I8 int8
2326 F32 float32
2327 }
2328
2329 treeU8, _ := Load("u8 = 300")
2330 treeI8, _ := Load("i8 = 300")
2331 treeF32, _ := Load("f32 = 1e300")
2332
2333 errU8 := treeU8.Unmarshal(&overflow{})
2334 errI8 := treeI8.Unmarshal(&overflow{})
2335 errF32 := treeF32.Unmarshal(&overflow{})
2336
2337 if errU8.Error() != "(1, 1): 300(int64) would overflow uint8" {
2338 t.Error("expect err:(1, 1): 300(int64) would overflow uint8 but got:", errU8)
2339 }
2340 if errI8.Error() != "(1, 1): 300(int64) would overflow int8" {
2341 t.Error("expect err:(1, 1): 300(int64) would overflow int8 but got:", errI8)
2342 }
2343 if errF32.Error() != "(1, 1): 1e+300(float64) would overflow float32" {
2344 t.Error("expect err:(1, 1): 1e+300(float64) would overflow float32 but got:", errF32)
2345 }
2346 }
2347
2348 func TestUnmarshalDefault(t *testing.T) {
2349 type EmbeddedStruct struct {
2350 StringField string `default:"c"`
2351 }
2352
2353 type aliasUint uint
2354
2355 var doc struct {
2356 StringField string `default:"a"`
2357 BoolField bool `default:"true"`
2358 UintField uint `default:"1"`
2359 Uint8Field uint8 `default:"8"`
2360 Uint16Field uint16 `default:"16"`
2361 Uint32Field uint32 `default:"32"`
2362 Uint64Field uint64 `default:"64"`
2363 IntField int `default:"-1"`
2364 Int8Field int8 `default:"-8"`
2365 Int16Field int16 `default:"-16"`
2366 Int32Field int32 `default:"-32"`
2367 Int64Field int64 `default:"-64"`
2368 Float32Field float32 `default:"32.1"`
2369 Float64Field float64 `default:"64.1"`
2370 DurationField time.Duration `default:"120ms"`
2371 DurationField2 time.Duration `default:"120000000"`
2372 NonEmbeddedStruct struct {
2373 StringField string `default:"b"`
2374 }
2375 EmbeddedStruct
2376 AliasUintField aliasUint `default:"1000"`
2377 }
2378
2379 err := Unmarshal([]byte(``), &doc)
2380 if err != nil {
2381 t.Fatal(err)
2382 }
2383 if doc.BoolField != true {
2384 t.Errorf("BoolField should be true, not %t", doc.BoolField)
2385 }
2386 if doc.StringField != "a" {
2387 t.Errorf("StringField should be \"a\", not %s", doc.StringField)
2388 }
2389 if doc.UintField != 1 {
2390 t.Errorf("UintField should be 1, not %d", doc.UintField)
2391 }
2392 if doc.Uint8Field != 8 {
2393 t.Errorf("Uint8Field should be 8, not %d", doc.Uint8Field)
2394 }
2395 if doc.Uint16Field != 16 {
2396 t.Errorf("Uint16Field should be 16, not %d", doc.Uint16Field)
2397 }
2398 if doc.Uint32Field != 32 {
2399 t.Errorf("Uint32Field should be 32, not %d", doc.Uint32Field)
2400 }
2401 if doc.Uint64Field != 64 {
2402 t.Errorf("Uint64Field should be 64, not %d", doc.Uint64Field)
2403 }
2404 if doc.IntField != -1 {
2405 t.Errorf("IntField should be -1, not %d", doc.IntField)
2406 }
2407 if doc.Int8Field != -8 {
2408 t.Errorf("Int8Field should be -8, not %d", doc.Int8Field)
2409 }
2410 if doc.Int16Field != -16 {
2411 t.Errorf("Int16Field should be -16, not %d", doc.Int16Field)
2412 }
2413 if doc.Int32Field != -32 {
2414 t.Errorf("Int32Field should be -32, not %d", doc.Int32Field)
2415 }
2416 if doc.Int64Field != -64 {
2417 t.Errorf("Int64Field should be -64, not %d", doc.Int64Field)
2418 }
2419 if doc.Float32Field != 32.1 {
2420 t.Errorf("Float32Field should be 32.1, not %f", doc.Float32Field)
2421 }
2422 if doc.Float64Field != 64.1 {
2423 t.Errorf("Float64Field should be 64.1, not %f", doc.Float64Field)
2424 }
2425 if doc.DurationField != 120*time.Millisecond {
2426 t.Errorf("DurationField should be 120ms, not %s", doc.DurationField.String())
2427 }
2428 if doc.DurationField2 != 120*time.Millisecond {
2429 t.Errorf("DurationField2 should be 120000000, not %d", doc.DurationField2)
2430 }
2431 if doc.NonEmbeddedStruct.StringField != "b" {
2432 t.Errorf("StringField should be \"b\", not %s", doc.NonEmbeddedStruct.StringField)
2433 }
2434 if doc.EmbeddedStruct.StringField != "c" {
2435 t.Errorf("StringField should be \"c\", not %s", doc.EmbeddedStruct.StringField)
2436 }
2437 if doc.AliasUintField != 1000 {
2438 t.Errorf("AliasUintField should be 1000, not %d", doc.AliasUintField)
2439 }
2440 }
2441
2442 func TestUnmarshalDefaultFailureBool(t *testing.T) {
2443 var doc struct {
2444 Field bool `default:"blah"`
2445 }
2446
2447 err := Unmarshal([]byte(``), &doc)
2448 if err == nil {
2449 t.Fatal("should error")
2450 }
2451 }
2452
2453 func TestUnmarshalDefaultFailureInt(t *testing.T) {
2454 var doc struct {
2455 Field int `default:"blah"`
2456 }
2457
2458 err := Unmarshal([]byte(``), &doc)
2459 if err == nil {
2460 t.Fatal("should error")
2461 }
2462 }
2463
2464 func TestUnmarshalDefaultFailureInt64(t *testing.T) {
2465 var doc struct {
2466 Field int64 `default:"blah"`
2467 }
2468
2469 err := Unmarshal([]byte(``), &doc)
2470 if err == nil {
2471 t.Fatal("should error")
2472 }
2473 }
2474
2475 func TestUnmarshalDefaultFailureFloat64(t *testing.T) {
2476 var doc struct {
2477 Field float64 `default:"blah"`
2478 }
2479
2480 err := Unmarshal([]byte(``), &doc)
2481 if err == nil {
2482 t.Fatal("should error")
2483 }
2484 }
2485
2486 func TestUnmarshalDefaultFailureDuration(t *testing.T) {
2487 var doc struct {
2488 Field time.Duration `default:"blah"`
2489 }
2490
2491 err := Unmarshal([]byte(``), &doc)
2492 if err == nil {
2493 t.Fatal("should error")
2494 }
2495 }
2496
2497 func TestUnmarshalDefaultFailureUnsupported(t *testing.T) {
2498 var doc struct {
2499 Field struct{} `default:"blah"`
2500 }
2501
2502 err := Unmarshal([]byte(``), &doc)
2503 if err == nil {
2504 t.Fatal("should error")
2505 }
2506 }
2507
2508 func TestMarshalNestedAnonymousStructs(t *testing.T) {
2509 type Embedded struct {
2510 Value string `toml:"value"`
2511 Top struct {
2512 Value string `toml:"value"`
2513 } `toml:"top"`
2514 }
2515
2516 type Named struct {
2517 Value string `toml:"value"`
2518 }
2519
2520 var doc struct {
2521 Embedded
2522 Named `toml:"named"`
2523 Anonymous struct {
2524 Value string `toml:"value"`
2525 } `toml:"anonymous"`
2526 }
2527
2528 expected := `value = ""
2529
2530 [anonymous]
2531 value = ""
2532
2533 [named]
2534 value = ""
2535
2536 [top]
2537 value = ""
2538 `
2539
2540 result, err := Marshal(doc)
2541 if err != nil {
2542 t.Fatalf("unexpected error: %s", err.Error())
2543 }
2544 if !bytes.Equal(result, []byte(expected)) {
2545 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, string(result))
2546 }
2547 }
2548
2549 func TestEncoderPromoteNestedAnonymousStructs(t *testing.T) {
2550 type Embedded struct {
2551 Value string `toml:"value"`
2552 }
2553
2554 var doc struct {
2555 Embedded
2556 }
2557
2558 expected := `
2559 [Embedded]
2560 value = ""
2561 `
2562 var buf bytes.Buffer
2563 if err := NewEncoder(&buf).PromoteAnonymous(true).Encode(doc); err != nil {
2564 t.Fatalf("unexpected error: %s", err.Error())
2565 }
2566 if !bytes.Equal(buf.Bytes(), []byte(expected)) {
2567 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, buf.String())
2568 }
2569 }
2570
2571 func TestMarshalNestedAnonymousStructs_DuplicateField(t *testing.T) {
2572 type Embedded struct {
2573 Value string `toml:"value"`
2574 Top struct {
2575 Value string `toml:"value"`
2576 } `toml:"top"`
2577 }
2578
2579 var doc struct {
2580 Value string `toml:"value"`
2581 Embedded
2582 }
2583 doc.Embedded.Value = "shadowed"
2584 doc.Value = "shadows"
2585
2586 expected := `value = "shadows"
2587
2588 [top]
2589 value = ""
2590 `
2591
2592 result, err := Marshal(doc)
2593 if err != nil {
2594 t.Fatalf("unexpected error: %s", err.Error())
2595 }
2596 if !bytes.Equal(result, []byte(expected)) {
2597 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, string(result))
2598 }
2599 }
2600
2601 func TestUnmarshalNestedAnonymousStructs(t *testing.T) {
2602 type Nested struct {
2603 Value string `toml:"nested_field"`
2604 }
2605 type Deep struct {
2606 Nested
2607 }
2608 type Document struct {
2609 Deep
2610 Value string `toml:"own_field"`
2611 }
2612
2613 var doc Document
2614
2615 err := Unmarshal([]byte(`nested_field = "nested value"`+"\n"+`own_field = "own value"`), &doc)
2616 if err != nil {
2617 t.Fatal("should not error")
2618 }
2619 if doc.Value != "own value" || doc.Nested.Value != "nested value" {
2620 t.Fatal("unexpected values")
2621 }
2622 }
2623
2624 func TestUnmarshalNestedAnonymousStructs_Controversial(t *testing.T) {
2625 type Nested struct {
2626 Value string `toml:"nested"`
2627 }
2628 type Deep struct {
2629 Nested
2630 }
2631 type Document struct {
2632 Deep
2633 Value string `toml:"own"`
2634 }
2635
2636 var doc Document
2637
2638 err := Unmarshal([]byte(`nested = "nested value"`+"\n"+`own = "own value"`), &doc)
2639 if err == nil {
2640 t.Fatal("should error")
2641 }
2642 }
2643
2644 type unexportedFieldPreservationTest struct {
2645 Exported string `toml:"exported"`
2646 unexported string
2647 Nested1 unexportedFieldPreservationTestNested `toml:"nested1"`
2648 Nested2 *unexportedFieldPreservationTestNested `toml:"nested2"`
2649 Nested3 *unexportedFieldPreservationTestNested `toml:"nested3"`
2650 Slice1 []unexportedFieldPreservationTestNested `toml:"slice1"`
2651 Slice2 []*unexportedFieldPreservationTestNested `toml:"slice2"`
2652 }
2653
2654 type unexportedFieldPreservationTestNested struct {
2655 Exported1 string `toml:"exported1"`
2656 unexported1 string
2657 }
2658
2659 func TestUnmarshalPreservesUnexportedFields(t *testing.T) {
2660 toml := `
2661 exported = "visible"
2662 unexported = "ignored"
2663
2664 [nested1]
2665 exported1 = "visible1"
2666 unexported1 = "ignored1"
2667
2668 [nested2]
2669 exported1 = "visible2"
2670 unexported1 = "ignored2"
2671
2672 [nested3]
2673 exported1 = "visible3"
2674 unexported1 = "ignored3"
2675
2676 [[slice1]]
2677 exported1 = "visible3"
2678
2679 [[slice1]]
2680 exported1 = "visible4"
2681
2682 [[slice2]]
2683 exported1 = "visible5"
2684 `
2685
2686 t.Run("unexported field should not be set from toml", func(t *testing.T) {
2687 var actual unexportedFieldPreservationTest
2688 err := Unmarshal([]byte(toml), &actual)
2689
2690 if err != nil {
2691 t.Fatal("did not expect an error")
2692 }
2693
2694 expect := unexportedFieldPreservationTest{
2695 Exported: "visible",
2696 unexported: "",
2697 Nested1: unexportedFieldPreservationTestNested{"visible1", ""},
2698 Nested2: &unexportedFieldPreservationTestNested{"visible2", ""},
2699 Nested3: &unexportedFieldPreservationTestNested{"visible3", ""},
2700 Slice1: []unexportedFieldPreservationTestNested{
2701 {Exported1: "visible3"},
2702 {Exported1: "visible4"},
2703 },
2704 Slice2: []*unexportedFieldPreservationTestNested{
2705 {Exported1: "visible5"},
2706 },
2707 }
2708
2709 if !reflect.DeepEqual(actual, expect) {
2710 t.Fatalf("%+v did not equal %+v", actual, expect)
2711 }
2712 })
2713
2714 t.Run("unexported field should be preserved", func(t *testing.T) {
2715 actual := unexportedFieldPreservationTest{
2716 Exported: "foo",
2717 unexported: "bar",
2718 Nested1: unexportedFieldPreservationTestNested{"baz", "bax"},
2719 Nested2: nil,
2720 Nested3: &unexportedFieldPreservationTestNested{"baz", "bax"},
2721 }
2722 err := Unmarshal([]byte(toml), &actual)
2723
2724 if err != nil {
2725 t.Fatal("did not expect an error")
2726 }
2727
2728 expect := unexportedFieldPreservationTest{
2729 Exported: "visible",
2730 unexported: "bar",
2731 Nested1: unexportedFieldPreservationTestNested{"visible1", "bax"},
2732 Nested2: &unexportedFieldPreservationTestNested{"visible2", ""},
2733 Nested3: &unexportedFieldPreservationTestNested{"visible3", "bax"},
2734 Slice1: []unexportedFieldPreservationTestNested{
2735 {Exported1: "visible3"},
2736 {Exported1: "visible4"},
2737 },
2738 Slice2: []*unexportedFieldPreservationTestNested{
2739 {Exported1: "visible5"},
2740 },
2741 }
2742
2743 if !reflect.DeepEqual(actual, expect) {
2744 t.Fatalf("%+v did not equal %+v", actual, expect)
2745 }
2746 })
2747 }
2748
2749 func TestTreeMarshal(t *testing.T) {
2750 cases := [][]byte{
2751 basicTestToml,
2752 marshalTestToml,
2753 emptyTestToml,
2754 pointerTestToml,
2755 }
2756 for _, expected := range cases {
2757 t.Run("", func(t *testing.T) {
2758 tree, err := LoadBytes(expected)
2759 if err != nil {
2760 t.Fatal(err)
2761 }
2762 result, err := tree.Marshal()
2763 if err != nil {
2764 t.Fatal(err)
2765 }
2766 if !bytes.Equal(result, expected) {
2767 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
2768 }
2769 })
2770 }
2771 }
2772
2773 func TestMarshalArrays(t *testing.T) {
2774 cases := []struct {
2775 Data interface{}
2776 Expected string
2777 }{
2778 {
2779 Data: struct {
2780 XY [2]int
2781 }{
2782 XY: [2]int{1, 2},
2783 },
2784 Expected: `XY = [1, 2]
2785 `,
2786 },
2787 {
2788 Data: struct {
2789 XY [1][2]int
2790 }{
2791 XY: [1][2]int{{1, 2}},
2792 },
2793 Expected: `XY = [[1, 2]]
2794 `,
2795 },
2796 {
2797 Data: struct {
2798 XY [1][]int
2799 }{
2800 XY: [1][]int{{1, 2}},
2801 },
2802 Expected: `XY = [[1, 2]]
2803 `,
2804 },
2805 {
2806 Data: struct {
2807 XY [][2]int
2808 }{
2809 XY: [][2]int{{1, 2}},
2810 },
2811 Expected: `XY = [[1, 2]]
2812 `,
2813 },
2814 }
2815 for _, tc := range cases {
2816 t.Run("", func(t *testing.T) {
2817 result, err := Marshal(tc.Data)
2818 if err != nil {
2819 t.Fatal(err)
2820 }
2821 if !bytes.Equal(result, []byte(tc.Expected)) {
2822 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", []byte(tc.Expected), result)
2823 }
2824 })
2825 }
2826 }
2827
2828 func TestUnmarshalLocalDate(t *testing.T) {
2829 t.Run("ToLocalDate", func(t *testing.T) {
2830 type dateStruct struct {
2831 Date LocalDate
2832 }
2833
2834 toml := `date = 1979-05-27`
2835
2836 var obj dateStruct
2837
2838 err := Unmarshal([]byte(toml), &obj)
2839
2840 if err != nil {
2841 t.Fatal(err)
2842 }
2843
2844 if obj.Date.Year != 1979 {
2845 t.Errorf("expected year 1979, got %d", obj.Date.Year)
2846 }
2847 if obj.Date.Month != 5 {
2848 t.Errorf("expected month 5, got %d", obj.Date.Month)
2849 }
2850 if obj.Date.Day != 27 {
2851 t.Errorf("expected day 27, got %d", obj.Date.Day)
2852 }
2853 })
2854
2855 t.Run("ToLocalDate", func(t *testing.T) {
2856 type dateStruct struct {
2857 Date time.Time
2858 }
2859
2860 toml := `date = 1979-05-27`
2861
2862 var obj dateStruct
2863
2864 err := Unmarshal([]byte(toml), &obj)
2865
2866 if err != nil {
2867 t.Fatal(err)
2868 }
2869
2870 if obj.Date.Year() != 1979 {
2871 t.Errorf("expected year 1979, got %d", obj.Date.Year())
2872 }
2873 if obj.Date.Month() != 5 {
2874 t.Errorf("expected month 5, got %d", obj.Date.Month())
2875 }
2876 if obj.Date.Day() != 27 {
2877 t.Errorf("expected day 27, got %d", obj.Date.Day())
2878 }
2879 })
2880 }
2881
2882 func TestMarshalLocalDate(t *testing.T) {
2883 type dateStruct struct {
2884 Date LocalDate
2885 }
2886
2887 obj := dateStruct{Date: LocalDate{
2888 Year: 1979,
2889 Month: 5,
2890 Day: 27,
2891 }}
2892
2893 b, err := Marshal(obj)
2894
2895 if err != nil {
2896 t.Fatalf("unexpected error: %v", err)
2897 }
2898
2899 got := string(b)
2900 expected := `Date = 1979-05-27
2901 `
2902
2903 if got != expected {
2904 t.Errorf("expected '%s', got '%s'", expected, got)
2905 }
2906 }
2907
2908 func TestUnmarshalLocalDateTime(t *testing.T) {
2909 examples := []struct {
2910 name string
2911 in string
2912 out LocalDateTime
2913 }{
2914 {
2915 name: "normal",
2916 in: "1979-05-27T07:32:00",
2917 out: LocalDateTime{
2918 Date: LocalDate{
2919 Year: 1979,
2920 Month: 5,
2921 Day: 27,
2922 },
2923 Time: LocalTime{
2924 Hour: 7,
2925 Minute: 32,
2926 Second: 0,
2927 Nanosecond: 0,
2928 },
2929 }},
2930 {
2931 name: "with nanoseconds",
2932 in: "1979-05-27T00:32:00.999999",
2933 out: LocalDateTime{
2934 Date: LocalDate{
2935 Year: 1979,
2936 Month: 5,
2937 Day: 27,
2938 },
2939 Time: LocalTime{
2940 Hour: 0,
2941 Minute: 32,
2942 Second: 0,
2943 Nanosecond: 999999000,
2944 },
2945 },
2946 },
2947 }
2948
2949 for i, example := range examples {
2950 toml := fmt.Sprintf(`date = %s`, example.in)
2951
2952 t.Run(fmt.Sprintf("ToLocalDateTime_%d_%s", i, example.name), func(t *testing.T) {
2953 type dateStruct struct {
2954 Date LocalDateTime
2955 }
2956
2957 var obj dateStruct
2958
2959 err := Unmarshal([]byte(toml), &obj)
2960
2961 if err != nil {
2962 t.Fatal(err)
2963 }
2964
2965 if obj.Date != example.out {
2966 t.Errorf("expected '%s', got '%s'", example.out, obj.Date)
2967 }
2968 })
2969
2970 t.Run(fmt.Sprintf("ToTime_%d_%s", i, example.name), func(t *testing.T) {
2971 type dateStruct struct {
2972 Date time.Time
2973 }
2974
2975 var obj dateStruct
2976
2977 err := Unmarshal([]byte(toml), &obj)
2978
2979 if err != nil {
2980 t.Fatal(err)
2981 }
2982
2983 if obj.Date.Year() != example.out.Date.Year {
2984 t.Errorf("expected year %d, got %d", example.out.Date.Year, obj.Date.Year())
2985 }
2986 if obj.Date.Month() != example.out.Date.Month {
2987 t.Errorf("expected month %d, got %d", example.out.Date.Month, obj.Date.Month())
2988 }
2989 if obj.Date.Day() != example.out.Date.Day {
2990 t.Errorf("expected day %d, got %d", example.out.Date.Day, obj.Date.Day())
2991 }
2992 if obj.Date.Hour() != example.out.Time.Hour {
2993 t.Errorf("expected hour %d, got %d", example.out.Time.Hour, obj.Date.Hour())
2994 }
2995 if obj.Date.Minute() != example.out.Time.Minute {
2996 t.Errorf("expected minute %d, got %d", example.out.Time.Minute, obj.Date.Minute())
2997 }
2998 if obj.Date.Second() != example.out.Time.Second {
2999 t.Errorf("expected second %d, got %d", example.out.Time.Second, obj.Date.Second())
3000 }
3001 if obj.Date.Nanosecond() != example.out.Time.Nanosecond {
3002 t.Errorf("expected nanoseconds %d, got %d", example.out.Time.Nanosecond, obj.Date.Nanosecond())
3003 }
3004 })
3005 }
3006 }
3007
3008 func TestMarshalLocalDateTime(t *testing.T) {
3009 type dateStruct struct {
3010 DateTime LocalDateTime
3011 }
3012
3013 examples := []struct {
3014 name string
3015 in LocalDateTime
3016 out string
3017 }{
3018 {
3019 name: "normal",
3020 out: "DateTime = 1979-05-27T07:32:00\n",
3021 in: LocalDateTime{
3022 Date: LocalDate{
3023 Year: 1979,
3024 Month: 5,
3025 Day: 27,
3026 },
3027 Time: LocalTime{
3028 Hour: 7,
3029 Minute: 32,
3030 Second: 0,
3031 Nanosecond: 0,
3032 },
3033 }},
3034 {
3035 name: "with nanoseconds",
3036 out: "DateTime = 1979-05-27T00:32:00.999999000\n",
3037 in: LocalDateTime{
3038 Date: LocalDate{
3039 Year: 1979,
3040 Month: 5,
3041 Day: 27,
3042 },
3043 Time: LocalTime{
3044 Hour: 0,
3045 Minute: 32,
3046 Second: 0,
3047 Nanosecond: 999999000,
3048 },
3049 },
3050 },
3051 }
3052
3053 for i, example := range examples {
3054 t.Run(fmt.Sprintf("%d_%s", i, example.name), func(t *testing.T) {
3055 obj := dateStruct{
3056 DateTime: example.in,
3057 }
3058 b, err := Marshal(obj)
3059
3060 if err != nil {
3061 t.Fatalf("unexpected error: %v", err)
3062 }
3063
3064 got := string(b)
3065
3066 if got != example.out {
3067 t.Errorf("expected '%s', got '%s'", example.out, got)
3068 }
3069 })
3070 }
3071 }
3072
3073 func TestUnmarshalLocalTime(t *testing.T) {
3074 examples := []struct {
3075 name string
3076 in string
3077 out LocalTime
3078 }{
3079 {
3080 name: "normal",
3081 in: "07:32:00",
3082 out: LocalTime{
3083 Hour: 7,
3084 Minute: 32,
3085 Second: 0,
3086 Nanosecond: 0,
3087 },
3088 },
3089 {
3090 name: "with nanoseconds",
3091 in: "00:32:00.999999",
3092 out: LocalTime{
3093 Hour: 0,
3094 Minute: 32,
3095 Second: 0,
3096 Nanosecond: 999999000,
3097 },
3098 },
3099 }
3100
3101 for i, example := range examples {
3102 toml := fmt.Sprintf(`Time = %s`, example.in)
3103
3104 t.Run(fmt.Sprintf("ToLocalTime_%d_%s", i, example.name), func(t *testing.T) {
3105 type dateStruct struct {
3106 Time LocalTime
3107 }
3108
3109 var obj dateStruct
3110
3111 err := Unmarshal([]byte(toml), &obj)
3112
3113 if err != nil {
3114 t.Fatal(err)
3115 }
3116
3117 if obj.Time != example.out {
3118 t.Errorf("expected '%s', got '%s'", example.out, obj.Time)
3119 }
3120 })
3121 }
3122 }
3123
3124 func TestMarshalLocalTime(t *testing.T) {
3125 type timeStruct struct {
3126 Time LocalTime
3127 }
3128
3129 examples := []struct {
3130 name string
3131 in LocalTime
3132 out string
3133 }{
3134 {
3135 name: "normal",
3136 out: "Time = 07:32:00\n",
3137 in: LocalTime{
3138 Hour: 7,
3139 Minute: 32,
3140 Second: 0,
3141 Nanosecond: 0,
3142 }},
3143 {
3144 name: "with nanoseconds",
3145 out: "Time = 00:32:00.999999000\n",
3146 in: LocalTime{
3147 Hour: 0,
3148 Minute: 32,
3149 Second: 0,
3150 Nanosecond: 999999000,
3151 },
3152 },
3153 }
3154
3155 for i, example := range examples {
3156 t.Run(fmt.Sprintf("%d_%s", i, example.name), func(t *testing.T) {
3157 obj := timeStruct{
3158 Time: example.in,
3159 }
3160 b, err := Marshal(obj)
3161
3162 if err != nil {
3163 t.Fatalf("unexpected error: %v", err)
3164 }
3165
3166 got := string(b)
3167
3168 if got != example.out {
3169 t.Errorf("expected '%s', got '%s'", example.out, got)
3170 }
3171 })
3172 }
3173 }
3174
3175
3176 func TestUnmarshalSameInnerField(t *testing.T) {
3177 type InterStruct2 struct {
3178 Test string
3179 Name string
3180 Age int
3181 }
3182 type Inter2 struct {
3183 Name string
3184 Age int
3185 InterStruct2 InterStruct2
3186 }
3187 type Server struct {
3188 Name string `toml:"name"`
3189 Inter2 Inter2 `toml:"inter2"`
3190 }
3191
3192 var server Server
3193
3194 if err := Unmarshal([]byte(`name = "123"
3195 [inter2]
3196 name = "inter2"
3197 age = 222`), &server); err == nil {
3198 expected := Server{
3199 Name: "123",
3200 Inter2: Inter2{
3201 Name: "inter2",
3202 Age: 222,
3203 },
3204 }
3205 if !reflect.DeepEqual(server, expected) {
3206 t.Errorf("Bad unmarshal: expected %v, got %v", expected, server)
3207 }
3208 } else {
3209 t.Fatalf("unexpected error: %v", err)
3210 }
3211 }
3212
3213 func TestMarshalInterface(t *testing.T) {
3214 type InnerStruct struct {
3215 InnerField string
3216 }
3217
3218 type OuterStruct struct {
3219 PrimitiveField interface{}
3220 ArrayField interface{}
3221 StructArrayField interface{}
3222 MapField map[string]interface{}
3223 StructField interface{}
3224 PointerField interface{}
3225 NilField interface{}
3226 InterfacePointerField *interface{}
3227 }
3228
3229 expected := []byte(`ArrayField = [1, 2, 3]
3230 InterfacePointerField = "hello world"
3231 PrimitiveField = "string"
3232
3233 [MapField]
3234 key1 = "value1"
3235 key2 = false
3236
3237 [MapField.key3]
3238 InnerField = "value3"
3239
3240 [PointerField]
3241 InnerField = "yyy"
3242
3243 [[StructArrayField]]
3244 InnerField = "s1"
3245
3246 [[StructArrayField]]
3247 InnerField = "s2"
3248
3249 [StructField]
3250 InnerField = "xxx"
3251 `)
3252
3253 var h interface{} = "hello world"
3254 if result, err := Marshal(OuterStruct{
3255 "string",
3256 []int{1, 2, 3},
3257 []InnerStruct{{"s1"}, {"s2"}},
3258 map[string]interface{}{
3259 "key1": "value1",
3260 "key2": false,
3261 "key3": InnerStruct{"value3"},
3262 "nil value": nil,
3263 },
3264 InnerStruct{
3265 "xxx",
3266 },
3267 &InnerStruct{
3268 "yyy",
3269 },
3270 nil,
3271 &h,
3272 }); err == nil {
3273 if !bytes.Equal(result, expected) {
3274 t.Errorf("Bad marshal: expected\n----\n%s\n----\ngot\n----\n%s\n----\n", expected, result)
3275 }
3276 } else {
3277 t.Fatal(err)
3278 }
3279 }
3280
3281 func TestUnmarshalToNilInterface(t *testing.T) {
3282 toml := []byte(`
3283 PrimitiveField = "Hello"
3284 ArrayField = [1,2,3]
3285 InterfacePointerField = "World"
3286
3287 [StructField]
3288 Field1 = 123
3289 Field2 = "Field2"
3290
3291 [MapField]
3292 MapField1 = [4,5,6]
3293 MapField2 = {A = "A"}
3294 MapField3 = false
3295
3296 [[StructArrayField]]
3297 Name = "Allen"
3298 Age = 20
3299
3300 [[StructArrayField]]
3301 Name = "Jack"
3302 Age = 23
3303 `)
3304
3305 type OuterStruct struct {
3306 PrimitiveField interface{}
3307 ArrayField interface{}
3308 StructArrayField interface{}
3309 MapField map[string]interface{}
3310 StructField interface{}
3311 NilField interface{}
3312 InterfacePointerField *interface{}
3313 }
3314
3315 var s interface{} = "World"
3316 expected := OuterStruct{
3317 PrimitiveField: "Hello",
3318 ArrayField: []interface{}{int64(1), int64(2), int64(3)},
3319 StructField: map[string]interface{}{
3320 "Field1": int64(123),
3321 "Field2": "Field2",
3322 },
3323 MapField: map[string]interface{}{
3324 "MapField1": []interface{}{int64(4), int64(5), int64(6)},
3325 "MapField2": map[string]interface{}{
3326 "A": "A",
3327 },
3328 "MapField3": false,
3329 },
3330 NilField: nil,
3331 InterfacePointerField: &s,
3332 StructArrayField: []map[string]interface{}{
3333 {
3334 "Name": "Allen",
3335 "Age": int64(20),
3336 },
3337 {
3338 "Name": "Jack",
3339 "Age": int64(23),
3340 },
3341 },
3342 }
3343 actual := OuterStruct{}
3344 if err := Unmarshal(toml, &actual); err == nil {
3345 if !reflect.DeepEqual(actual, expected) {
3346 t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3347 }
3348 } else {
3349 t.Fatal(err)
3350 }
3351 }
3352
3353 func TestUnmarshalToNonNilInterface(t *testing.T) {
3354 toml := []byte(`
3355 PrimitiveField = "Allen"
3356 ArrayField = [1,2,3]
3357
3358 [StructField]
3359 InnerField = "After1"
3360
3361 [PointerField]
3362 InnerField = "After2"
3363
3364 [InterfacePointerField]
3365 InnerField = "After"
3366
3367 [MapField]
3368 MapField1 = [4,5,6]
3369 MapField2 = {A = "A"}
3370 MapField3 = false
3371
3372 [[StructArrayField]]
3373 InnerField = "After3"
3374
3375 [[StructArrayField]]
3376 InnerField = "After4"
3377 `)
3378 type InnerStruct struct {
3379 InnerField interface{}
3380 }
3381
3382 type OuterStruct struct {
3383 PrimitiveField interface{}
3384 ArrayField interface{}
3385 StructArrayField interface{}
3386 MapField map[string]interface{}
3387 StructField interface{}
3388 PointerField interface{}
3389 NilField interface{}
3390 InterfacePointerField *interface{}
3391 }
3392
3393 var s interface{} = InnerStruct{"After"}
3394 expected := OuterStruct{
3395 PrimitiveField: "Allen",
3396 ArrayField: []int{1, 2, 3},
3397 StructField: InnerStruct{InnerField: "After1"},
3398 MapField: map[string]interface{}{
3399 "MapField1": []interface{}{int64(4), int64(5), int64(6)},
3400 "MapField2": map[string]interface{}{
3401 "A": "A",
3402 },
3403 "MapField3": false,
3404 },
3405 PointerField: &InnerStruct{InnerField: "After2"},
3406 NilField: nil,
3407 InterfacePointerField: &s,
3408 StructArrayField: []InnerStruct{
3409 {InnerField: "After3"},
3410 {InnerField: "After4"},
3411 },
3412 }
3413 actual := OuterStruct{
3414 PrimitiveField: "aaa",
3415 ArrayField: []int{100, 200, 300, 400},
3416 StructField: InnerStruct{InnerField: "Before1"},
3417 MapField: map[string]interface{}{
3418 "MapField1": []int{4, 5, 6},
3419 "MapField2": map[string]string{
3420 "B": "BBB",
3421 },
3422 "MapField3": true,
3423 },
3424 PointerField: &InnerStruct{InnerField: "Before2"},
3425 NilField: nil,
3426 InterfacePointerField: &s,
3427 StructArrayField: []InnerStruct{
3428 {InnerField: "Before3"},
3429 {InnerField: "Before4"},
3430 },
3431 }
3432 if err := Unmarshal(toml, &actual); err == nil {
3433 if !reflect.DeepEqual(actual, expected) {
3434 t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3435 }
3436 } else {
3437 t.Fatal(err)
3438 }
3439 }
3440
3441 func TestUnmarshalEmbedTree(t *testing.T) {
3442 toml := []byte(`
3443 OuterField1 = "Out"
3444 OuterField2 = 1024
3445
3446 [TreeField]
3447 InnerField1 = "In"
3448 InnerField2 = 2048
3449
3450 [TreeField.EmbedStruct]
3451 EmbedField = "Embed"
3452
3453 `)
3454 type InnerStruct struct {
3455 InnerField1 string
3456 InnerField2 int
3457 EmbedStruct struct {
3458 EmbedField string
3459 }
3460 }
3461
3462 type OuterStruct struct {
3463 OuterField1 string
3464 OuterField2 int
3465 TreeField *Tree
3466 }
3467
3468 out := OuterStruct{}
3469 actual := InnerStruct{}
3470 expected := InnerStruct{
3471 "In",
3472 2048,
3473 struct {
3474 EmbedField string
3475 }{
3476 EmbedField: "Embed",
3477 },
3478 }
3479 if err := Unmarshal(toml, &out); err != nil {
3480 t.Fatal(err)
3481 }
3482 if err := out.TreeField.Unmarshal(&actual); err != nil {
3483 t.Fatal(err)
3484 }
3485
3486 if !reflect.DeepEqual(actual, expected) {
3487 t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3488 }
3489 }
3490
3491 func TestMarshalNil(t *testing.T) {
3492 if _, err := Marshal(nil); err == nil {
3493 t.Errorf("Expected err from nil marshal")
3494 }
3495 if _, err := Marshal((*struct{})(nil)); err == nil {
3496 t.Errorf("Expected err from nil marshal")
3497 }
3498 }
3499
3500 func TestUnmarshalNil(t *testing.T) {
3501 if err := Unmarshal([]byte(`whatever = "whatever"`), nil); err == nil {
3502 t.Errorf("Expected err from nil marshal")
3503 }
3504 if err := Unmarshal([]byte(`whatever = "whatever"`), (*struct{})(nil)); err == nil {
3505 t.Errorf("Expected err from nil marshal")
3506 }
3507 }
3508
3509 var sliceTomlDemo = []byte(`str_slice = ["Howdy","Hey There"]
3510 str_slice_ptr= ["Howdy","Hey There"]
3511 int_slice=[1,2]
3512 int_slice_ptr=[1,2]
3513 [[struct_slice]]
3514 String2="1"
3515 [[struct_slice]]
3516 String2="2"
3517 [[struct_slice_ptr]]
3518 String2="1"
3519 [[struct_slice_ptr]]
3520 String2="2"
3521 `)
3522
3523 type sliceStruct struct {
3524 Slice []string ` toml:"str_slice" `
3525 SlicePtr *[]string ` toml:"str_slice_ptr" `
3526 IntSlice []int ` toml:"int_slice" `
3527 IntSlicePtr *[]int ` toml:"int_slice_ptr" `
3528 StructSlice []basicMarshalTestSubStruct ` toml:"struct_slice" `
3529 StructSlicePtr *[]basicMarshalTestSubStruct ` toml:"struct_slice_ptr" `
3530 }
3531
3532 type arrayStruct struct {
3533 Slice [4]string ` toml:"str_slice" `
3534 SlicePtr *[4]string ` toml:"str_slice_ptr" `
3535 IntSlice [4]int ` toml:"int_slice" `
3536 IntSlicePtr *[4]int ` toml:"int_slice_ptr" `
3537 StructSlice [4]basicMarshalTestSubStruct ` toml:"struct_slice" `
3538 StructSlicePtr *[4]basicMarshalTestSubStruct ` toml:"struct_slice_ptr" `
3539 }
3540
3541 type arrayTooSmallStruct struct {
3542 Slice [1]string ` toml:"str_slice" `
3543 StructSlice [1]basicMarshalTestSubStruct ` toml:"struct_slice" `
3544 }
3545
3546 func TestUnmarshalSlice(t *testing.T) {
3547 tree, _ := LoadBytes(sliceTomlDemo)
3548 tree, _ = TreeFromMap(tree.ToMap())
3549
3550 var actual sliceStruct
3551 err := tree.Unmarshal(&actual)
3552 if err != nil {
3553 t.Error("shound not err", err)
3554 }
3555 expected := sliceStruct{
3556 Slice: []string{"Howdy", "Hey There"},
3557 SlicePtr: &[]string{"Howdy", "Hey There"},
3558 IntSlice: []int{1, 2},
3559 IntSlicePtr: &[]int{1, 2},
3560 StructSlice: []basicMarshalTestSubStruct{{"1"}, {"2"}},
3561 StructSlicePtr: &[]basicMarshalTestSubStruct{{"1"}, {"2"}},
3562 }
3563 if !reflect.DeepEqual(actual, expected) {
3564 t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3565 }
3566
3567 }
3568
3569 func TestUnmarshalSliceFail(t *testing.T) {
3570 tree, _ := TreeFromMap(map[string]interface{}{
3571 "str_slice": []int{1, 2},
3572 })
3573
3574 var actual sliceStruct
3575 err := tree.Unmarshal(&actual)
3576 if err.Error() != "(0, 0): Can't convert 1(int64) to string" {
3577 t.Error("expect err:(0, 0): Can't convert 1(int64) to string but got ", err)
3578 }
3579 }
3580
3581 func TestUnmarshalSliceFail2(t *testing.T) {
3582 tree, _ := Load(`str_slice=[1,2]`)
3583
3584 var actual sliceStruct
3585 err := tree.Unmarshal(&actual)
3586 if err.Error() != "(1, 1): Can't convert 1(int64) to string" {
3587 t.Error("expect err:(1, 1): Can't convert 1(int64) to string but got ", err)
3588 }
3589
3590 }
3591
3592 func TestMarshalMixedTypeArray(t *testing.T) {
3593 type InnerStruct struct {
3594 IntField int
3595 StrField string
3596 }
3597
3598 type TestStruct struct {
3599 ArrayField []interface{}
3600 }
3601
3602 expected := []byte(`ArrayField = [3.14, 100, true, "hello world", { IntField = 100, StrField = "inner1" }, [{ IntField = 200, StrField = "inner2" }, { IntField = 300, StrField = "inner3" }]]
3603 `)
3604
3605 if result, err := Marshal(TestStruct{
3606 ArrayField: []interface{}{
3607 3.14,
3608 100,
3609 true,
3610 "hello world",
3611 InnerStruct{
3612 IntField: 100,
3613 StrField: "inner1",
3614 },
3615 []InnerStruct{
3616 {IntField: 200, StrField: "inner2"},
3617 {IntField: 300, StrField: "inner3"},
3618 },
3619 },
3620 }); err == nil {
3621 if !bytes.Equal(result, expected) {
3622 t.Errorf("Bad marshal: expected\n----\n%s\n----\ngot\n----\n%s\n----\n", expected, result)
3623 }
3624 } else {
3625 t.Fatal(err)
3626 }
3627 }
3628
3629 func TestUnmarshalMixedTypeArray(t *testing.T) {
3630 type TestStruct struct {
3631 ArrayField []interface{}
3632 }
3633
3634 toml := []byte(`ArrayField = [3.14,100,true,"hello world",{Field = "inner1"},[{Field = "inner2"},{Field = "inner3"}]]
3635 `)
3636
3637 actual := TestStruct{}
3638 expected := TestStruct{
3639 ArrayField: []interface{}{
3640 3.14,
3641 int64(100),
3642 true,
3643 "hello world",
3644 map[string]interface{}{
3645 "Field": "inner1",
3646 },
3647 []map[string]interface{}{
3648 {"Field": "inner2"},
3649 {"Field": "inner3"},
3650 },
3651 },
3652 }
3653
3654 if err := Unmarshal(toml, &actual); err == nil {
3655 if !reflect.DeepEqual(actual, expected) {
3656 t.Errorf("Bad unmarshal: expected %#v, got %#v", expected, actual)
3657 }
3658 } else {
3659 t.Fatal(err)
3660 }
3661 }
3662
3663 func TestUnmarshalArray(t *testing.T) {
3664 var tree *Tree
3665 var err error
3666
3667 tree, _ = LoadBytes(sliceTomlDemo)
3668 var actual1 arrayStruct
3669 err = tree.Unmarshal(&actual1)
3670 if err != nil {
3671 t.Error("shound not err", err)
3672 }
3673
3674 tree, _ = TreeFromMap(tree.ToMap())
3675 var actual2 arrayStruct
3676 err = tree.Unmarshal(&actual2)
3677 if err != nil {
3678 t.Error("shound not err", err)
3679 }
3680
3681 expected := arrayStruct{
3682 Slice: [4]string{"Howdy", "Hey There"},
3683 SlicePtr: &[4]string{"Howdy", "Hey There"},
3684 IntSlice: [4]int{1, 2},
3685 IntSlicePtr: &[4]int{1, 2},
3686 StructSlice: [4]basicMarshalTestSubStruct{{"1"}, {"2"}},
3687 StructSlicePtr: &[4]basicMarshalTestSubStruct{{"1"}, {"2"}},
3688 }
3689 if !reflect.DeepEqual(actual1, expected) {
3690 t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual1)
3691 }
3692 if !reflect.DeepEqual(actual2, expected) {
3693 t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual2)
3694 }
3695 }
3696
3697 func TestUnmarshalArrayFail(t *testing.T) {
3698 tree, _ := TreeFromMap(map[string]interface{}{
3699 "str_slice": []string{"Howdy", "Hey There"},
3700 })
3701
3702 var actual arrayTooSmallStruct
3703 err := tree.Unmarshal(&actual)
3704 if err.Error() != "(0, 0): unmarshal: TOML array length (2) exceeds destination array length (1)" {
3705 t.Error("expect err:(0, 0): unmarshal: TOML array length (2) exceeds destination array length (1) but got ", err)
3706 }
3707 }
3708
3709 func TestUnmarshalArrayFail2(t *testing.T) {
3710 tree, _ := Load(`str_slice=["Howdy","Hey There"]`)
3711
3712 var actual arrayTooSmallStruct
3713 err := tree.Unmarshal(&actual)
3714 if err.Error() != "(1, 1): unmarshal: TOML array length (2) exceeds destination array length (1)" {
3715 t.Error("expect err:(1, 1): unmarshal: TOML array length (2) exceeds destination array length (1) but got ", err)
3716 }
3717 }
3718
3719 func TestUnmarshalArrayFail3(t *testing.T) {
3720 tree, _ := Load(`[[struct_slice]]
3721 String2="1"
3722 [[struct_slice]]
3723 String2="2"`)
3724
3725 var actual arrayTooSmallStruct
3726 err := tree.Unmarshal(&actual)
3727 if err.Error() != "(3, 1): unmarshal: TOML array length (2) exceeds destination array length (1)" {
3728 t.Error("expect err:(3, 1): unmarshal: TOML array length (2) exceeds destination array length (1) but got ", err)
3729 }
3730 }
3731
3732 func TestDecoderStrict(t *testing.T) {
3733 input := `
3734 [decoded]
3735 key = ""
3736
3737 [undecoded]
3738 key = ""
3739
3740 [undecoded.inner]
3741 key = ""
3742
3743 [[undecoded.array]]
3744 key = ""
3745
3746 [[undecoded.array]]
3747 key = ""
3748
3749 `
3750 var doc struct {
3751 Decoded struct {
3752 Key string
3753 }
3754 }
3755
3756 expected := `undecoded keys: ["undecoded.array.0.key" "undecoded.array.1.key" "undecoded.inner.key" "undecoded.key"]`
3757
3758 err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
3759 if err == nil {
3760 t.Error("expected error, got none")
3761 } else if err.Error() != expected {
3762 t.Errorf("expect err: %s, got: %s", expected, err.Error())
3763 }
3764
3765 if err := NewDecoder(bytes.NewReader([]byte(input))).Decode(&doc); err != nil {
3766 t.Errorf("unexpected err: %s", err)
3767 }
3768
3769 var m map[string]interface{}
3770 if err := NewDecoder(bytes.NewReader([]byte(input))).Decode(&m); err != nil {
3771 t.Errorf("unexpected err: %s", err)
3772 }
3773 }
3774
3775 func TestDecoderStrictValid(t *testing.T) {
3776 input := `
3777 [decoded]
3778 key = ""
3779 `
3780 var doc struct {
3781 Decoded struct {
3782 Key string
3783 }
3784 }
3785
3786 err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
3787 if err != nil {
3788 t.Fatal("unexpected error:", err)
3789 }
3790 }
3791
3792 type docUnmarshalTOML struct {
3793 Decoded struct {
3794 Key string
3795 }
3796 }
3797
3798 func (d *docUnmarshalTOML) UnmarshalTOML(i interface{}) error {
3799 if iMap, ok := i.(map[string]interface{}); !ok {
3800 return fmt.Errorf("type assertion error: wants %T, have %T", map[string]interface{}{}, i)
3801 } else if key, ok := iMap["key"]; !ok {
3802 return fmt.Errorf("key '%s' not in map", "key")
3803 } else if keyString, ok := key.(string); !ok {
3804 return fmt.Errorf("type assertion error: wants %T, have %T", "", key)
3805 } else {
3806 d.Decoded.Key = keyString
3807 }
3808 return nil
3809 }
3810
3811 func TestDecoderStrictCustomUnmarshal(t *testing.T) {
3812 input := `key = "ok"`
3813 var doc docUnmarshalTOML
3814 err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
3815 if err != nil {
3816 t.Fatal("unexpected error:", err)
3817 }
3818 if doc.Decoded.Key != "ok" {
3819 t.Errorf("Bad unmarshal: expected ok, got %v", doc.Decoded.Key)
3820 }
3821 }
3822
3823 type parent struct {
3824 Doc docUnmarshalTOML
3825 DocPointer *docUnmarshalTOML
3826 }
3827
3828 func TestCustomUnmarshal(t *testing.T) {
3829 input := `
3830 [Doc]
3831 key = "ok1"
3832 [DocPointer]
3833 key = "ok2"
3834 `
3835
3836 var d parent
3837 if err := Unmarshal([]byte(input), &d); err != nil {
3838 t.Fatalf("unexpected err: %s", err.Error())
3839 }
3840 if d.Doc.Decoded.Key != "ok1" {
3841 t.Errorf("Bad unmarshal: expected ok, got %v", d.Doc.Decoded.Key)
3842 }
3843 if d.DocPointer.Decoded.Key != "ok2" {
3844 t.Errorf("Bad unmarshal: expected ok, got %v", d.DocPointer.Decoded.Key)
3845 }
3846 }
3847
3848 func TestCustomUnmarshalError(t *testing.T) {
3849 input := `
3850 [Doc]
3851 key = 1
3852 [DocPointer]
3853 key = "ok2"
3854 `
3855
3856 expected := "(2, 1): unmarshal toml: type assertion error: wants string, have int64"
3857
3858 var d parent
3859 err := Unmarshal([]byte(input), &d)
3860 if err == nil {
3861 t.Error("expected error, got none")
3862 } else if err.Error() != expected {
3863 t.Errorf("expect err: %s, got: %s", expected, err.Error())
3864 }
3865 }
3866
3867 type intWrapper struct {
3868 Value int
3869 }
3870
3871 func (w *intWrapper) UnmarshalText(text []byte) error {
3872 var err error
3873 if w.Value, err = strconv.Atoi(string(text)); err == nil {
3874 return nil
3875 }
3876 if b, err := strconv.ParseBool(string(text)); err == nil {
3877 if b {
3878 w.Value = 1
3879 }
3880 return nil
3881 }
3882 if f, err := strconv.ParseFloat(string(text), 32); err == nil {
3883 w.Value = int(f)
3884 return nil
3885 }
3886 return fmt.Errorf("unsupported: %s", text)
3887 }
3888
3889 func TestTextUnmarshal(t *testing.T) {
3890 var doc struct {
3891 UnixTime intWrapper
3892 Version *intWrapper
3893
3894 Bool intWrapper
3895 Int intWrapper
3896 Float intWrapper
3897 }
3898
3899 input := `
3900 UnixTime = "12"
3901 Version = "42"
3902 Bool = true
3903 Int = 21
3904 Float = 2.0
3905 `
3906
3907 if err := Unmarshal([]byte(input), &doc); err != nil {
3908 t.Fatalf("unexpected err: %s", err.Error())
3909 }
3910 if doc.UnixTime.Value != 12 {
3911 t.Fatalf("expected UnixTime: 12 got: %d", doc.UnixTime.Value)
3912 }
3913 if doc.Version.Value != 42 {
3914 t.Fatalf("expected Version: 42 got: %d", doc.Version.Value)
3915 }
3916 if doc.Bool.Value != 1 {
3917 t.Fatalf("expected Bool: 1 got: %d", doc.Bool.Value)
3918 }
3919 if doc.Int.Value != 21 {
3920 t.Fatalf("expected Int: 21 got: %d", doc.Int.Value)
3921 }
3922 if doc.Float.Value != 2 {
3923 t.Fatalf("expected Float: 2 got: %d", doc.Float.Value)
3924 }
3925 }
3926
3927 func TestTextUnmarshalError(t *testing.T) {
3928 var doc struct {
3929 Failer intWrapper
3930 }
3931
3932 input := `Failer = "hello"`
3933 if err := Unmarshal([]byte(input), &doc); err == nil {
3934 t.Fatalf("expected err, got none")
3935 }
3936 }
3937
3938
3939 func TestPreserveNotEmptyField(t *testing.T) {
3940 toml := []byte(`Field1 = "ccc"`)
3941 type Inner struct {
3942 InnerField1 string
3943 InnerField2 int
3944 }
3945 type TestStruct struct {
3946 Field1 string
3947 Field2 int
3948 Field3 Inner
3949 }
3950
3951 actual := TestStruct{
3952 "aaa",
3953 100,
3954 Inner{
3955 "bbb",
3956 200,
3957 },
3958 }
3959
3960 expected := TestStruct{
3961 "ccc",
3962 100,
3963 Inner{
3964 "bbb",
3965 200,
3966 },
3967 }
3968
3969 err := Unmarshal(toml, &actual)
3970 if err != nil {
3971 t.Fatal(err)
3972 }
3973
3974 if !reflect.DeepEqual(actual, expected) {
3975 t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
3976 }
3977 }
3978
3979
3980 func TestUnmarshalEmptyInterface(t *testing.T) {
3981 doc := []byte(`User = "pelletier"`)
3982
3983 var v interface{}
3984
3985 err := Unmarshal(doc, &v)
3986 if err != nil {
3987 t.Fatal(err)
3988 }
3989
3990 x, ok := v.(map[string]interface{})
3991 if !ok {
3992 t.Fatal(err)
3993 }
3994
3995 if x["User"] != "pelletier" {
3996 t.Fatalf("expected User=pelletier, but got %v", x)
3997 }
3998 }
3999
4000 func TestUnmarshalEmptyInterfaceDeep(t *testing.T) {
4001 doc := []byte(`
4002 User = "pelletier"
4003 Age = 99
4004
4005 [foo]
4006 bar = 42
4007 `)
4008
4009 var v interface{}
4010
4011 err := Unmarshal(doc, &v)
4012 if err != nil {
4013 t.Fatal(err)
4014 }
4015
4016 x, ok := v.(map[string]interface{})
4017 if !ok {
4018 t.Fatal(err)
4019 }
4020
4021 expected := map[string]interface{}{
4022 "User": "pelletier",
4023 "Age": 99,
4024 "foo": map[string]interface{}{
4025 "bar": 42,
4026 },
4027 }
4028
4029 reflect.DeepEqual(x, expected)
4030 }
4031
4032 type Config struct {
4033 Key string `toml:"key"`
4034 Obj Custom `toml:"obj"`
4035 }
4036
4037 type Custom struct {
4038 v string
4039 }
4040
4041 func (c *Custom) UnmarshalTOML(v interface{}) error {
4042 c.v = "called"
4043 return nil
4044 }
4045
4046 func TestGithubIssue431(t *testing.T) {
4047 doc := `key = "value"`
4048 tree, err := LoadBytes([]byte(doc))
4049 if err != nil {
4050 t.Fatalf("unexpected error: %s", err)
4051 }
4052
4053 var c Config
4054 if err := tree.Unmarshal(&c); err != nil {
4055 t.Fatalf("unexpected error: %s", err)
4056 }
4057
4058 if c.Key != "value" {
4059 t.Errorf("expected c.Key='value', not '%s'", c.Key)
4060 }
4061
4062 if c.Obj.v == "called" {
4063 t.Errorf("UnmarshalTOML should not have been called")
4064 }
4065 }
4066
4067 type durationString struct {
4068 time.Duration
4069 }
4070
4071 func (d *durationString) UnmarshalTOML(v interface{}) error {
4072 d.Duration = 10 * time.Second
4073 return nil
4074 }
4075
4076 type config437Error struct {
4077 }
4078
4079 func (e *config437Error) UnmarshalTOML(v interface{}) error {
4080 return errors.New("expected")
4081 }
4082
4083 type config437 struct {
4084 HTTP struct {
4085 PingTimeout durationString `toml:"PingTimeout"`
4086 ErrorField config437Error
4087 } `toml:"HTTP"`
4088 }
4089
4090 func TestGithubIssue437(t *testing.T) {
4091 src := `
4092 [HTTP]
4093 PingTimeout = "32m"
4094 `
4095 cfg := &config437{}
4096 cfg.HTTP.PingTimeout = durationString{time.Second}
4097
4098 r := strings.NewReader(src)
4099 err := NewDecoder(r).Decode(cfg)
4100 if err != nil {
4101 t.Fatalf("unexpected errors %s", err)
4102 }
4103 expected := durationString{10 * time.Second}
4104 if cfg.HTTP.PingTimeout != expected {
4105 t.Fatalf("expected '%s', got '%s'", expected, cfg.HTTP.PingTimeout)
4106 }
4107 }
4108
4109 func TestLeafUnmarshalerError(t *testing.T) {
4110 src := `
4111 [HTTP]
4112 ErrorField = "foo"
4113 `
4114 cfg := &config437{}
4115
4116 r := strings.NewReader(src)
4117 err := NewDecoder(r).Decode(cfg)
4118 if err == nil {
4119 t.Fatalf("error was expected")
4120 }
4121 }
4122
4123 func TestGithubIssue732(t *testing.T) {
4124 var v interface{}
4125 data := []byte("a=\nb=0")
4126
4127 err := Unmarshal(data, &v)
4128 if err == nil {
4129 t.Fatalf("error was expected")
4130 }
4131 }
4132
View as plain text