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