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