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
1479type mapsTestStruct struct {
1480	Simple map[string]string
1481	Paths  map[string]string
1482	Other  map[string]float64
1483	X      struct {
1484		Y struct {
1485			Z map[string]bool
1486		}
1487	}
1488}
1489
1490var mapsTestData = mapsTestStruct{
1491	Simple: map[string]string{
1492		"one plus one": "two",
1493		"next":         "three",
1494	},
1495	Paths: map[string]string{
1496		"/this/is/a/path": "/this/is/also/a/path",
1497		"/heloo.txt":      "/tmp/lololo.txt",
1498	},
1499	Other: map[string]float64{
1500		"testing": 3.9999,
1501	},
1502	X: struct{ Y struct{ Z map[string]bool } }{
1503		Y: struct{ Z map[string]bool }{
1504			Z: map[string]bool{
1505				"is.Nested": true,
1506			},
1507		},
1508	},
1509}
1510var mapsTestToml = []byte(`
1511[Other]
1512  "testing" = 3.9999
1513
1514[Paths]
1515  "/heloo.txt" = "/tmp/lololo.txt"
1516  "/this/is/a/path" = "/this/is/also/a/path"
1517
1518[Simple]
1519  "next" = "three"
1520  "one plus one" = "two"
1521
1522[X]
1523
1524  [X.Y]
1525
1526    [X.Y.Z]
1527      "is.Nested" = true
1528`)
1529
1530func TestEncodeQuotedMapKeys(t *testing.T) {
1531	var buf bytes.Buffer
1532	if err := NewEncoder(&buf).QuoteMapKeys(true).Encode(mapsTestData); err != nil {
1533		t.Fatal(err)
1534	}
1535	result := buf.Bytes()
1536	expected := mapsTestToml
1537	if !bytes.Equal(result, expected) {
1538		t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1539	}
1540}
1541
1542func TestDecodeQuotedMapKeys(t *testing.T) {
1543	result := mapsTestStruct{}
1544	err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result)
1545	expected := mapsTestData
1546	if err != nil {
1547		t.Fatal(err)
1548	}
1549	if !reflect.DeepEqual(result, expected) {
1550		t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result)
1551	}
1552}
1553
1554type structArrayNoTag struct {
1555	A struct {
1556		B []int64
1557		C []int64
1558	}
1559}
1560
1561func TestMarshalArray(t *testing.T) {
1562	expected := []byte(`
1563[A]
1564  B = [1, 2, 3]
1565  C = [1]
1566`)
1567
1568	m := structArrayNoTag{
1569		A: struct {
1570			B []int64
1571			C []int64
1572		}{
1573			B: []int64{1, 2, 3},
1574			C: []int64{1},
1575		},
1576	}
1577
1578	b, err := Marshal(m)
1579
1580	if err != nil {
1581		t.Fatal(err)
1582	}
1583
1584	if !bytes.Equal(b, expected) {
1585		t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
1586	}
1587}
1588
1589func TestMarshalArrayOnePerLine(t *testing.T) {
1590	expected := []byte(`
1591[A]
1592  B = [
1593    1,
1594    2,
1595    3,
1596  ]
1597  C = [1]
1598`)
1599
1600	m := structArrayNoTag{
1601		A: struct {
1602			B []int64
1603			C []int64
1604		}{
1605			B: []int64{1, 2, 3},
1606			C: []int64{1},
1607		},
1608	}
1609
1610	var buf bytes.Buffer
1611	encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true)
1612	err := encoder.Encode(m)
1613
1614	if err != nil {
1615		t.Fatal(err)
1616	}
1617
1618	b := buf.Bytes()
1619
1620	if !bytes.Equal(b, expected) {
1621		t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
1622	}
1623}
1624
1625var customTagTestToml = []byte(`
1626[postgres]
1627  password = "bvalue"
1628  user = "avalue"
1629
1630  [[postgres.My]]
1631    My = "Foo"
1632
1633  [[postgres.My]]
1634    My = "Baar"
1635`)
1636
1637func TestMarshalCustomTag(t *testing.T) {
1638	type TypeC struct {
1639		My string
1640	}
1641	type TypeB struct {
1642		AttrA string `file:"user"`
1643		AttrB string `file:"password"`
1644		My    []TypeC
1645	}
1646	type TypeA struct {
1647		TypeB TypeB `file:"postgres"`
1648	}
1649
1650	ta := []TypeC{{My: "Foo"}, {My: "Baar"}}
1651	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", My: ta}}
1652	var buf bytes.Buffer
1653	err := NewEncoder(&buf).SetTagName("file").Encode(config)
1654	if err != nil {
1655		t.Fatal(err)
1656	}
1657	expected := customTagTestToml
1658	result := buf.Bytes()
1659	if !bytes.Equal(result, expected) {
1660		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1661	}
1662}
1663
1664var customCommentTagTestToml = []byte(`
1665# db connection
1666[postgres]
1667
1668  # db pass
1669  password = "bvalue"
1670
1671  # db user
1672  user = "avalue"
1673`)
1674
1675func TestMarshalCustomComment(t *testing.T) {
1676	type TypeB struct {
1677		AttrA string `toml:"user" descr:"db user"`
1678		AttrB string `toml:"password" descr:"db pass"`
1679	}
1680	type TypeA struct {
1681		TypeB TypeB `toml:"postgres" descr:"db connection"`
1682	}
1683
1684	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue"}}
1685	var buf bytes.Buffer
1686	err := NewEncoder(&buf).SetTagComment("descr").Encode(config)
1687	if err != nil {
1688		t.Fatal(err)
1689	}
1690	expected := customCommentTagTestToml
1691	result := buf.Bytes()
1692	if !bytes.Equal(result, expected) {
1693		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1694	}
1695}
1696
1697var customCommentedTagTestToml = []byte(`
1698[postgres]
1699  # password = "bvalue"
1700  # user = "avalue"
1701`)
1702
1703func TestMarshalCustomCommented(t *testing.T) {
1704	type TypeB struct {
1705		AttrA string `toml:"user" disable:"true"`
1706		AttrB string `toml:"password" disable:"true"`
1707	}
1708	type TypeA struct {
1709		TypeB TypeB `toml:"postgres"`
1710	}
1711
1712	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue"}}
1713	var buf bytes.Buffer
1714	err := NewEncoder(&buf).SetTagCommented("disable").Encode(config)
1715	if err != nil {
1716		t.Fatal(err)
1717	}
1718	expected := customCommentedTagTestToml
1719	result := buf.Bytes()
1720	if !bytes.Equal(result, expected) {
1721		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1722	}
1723}
1724
1725func TestMarshalDirectMultilineString(t *testing.T) {
1726	tree := newTree()
1727	tree.SetWithOptions("mykey", SetOptions{
1728		Multiline: true,
1729	}, "my\x11multiline\nstring\ba\tb\fc\rd\"e\\!")
1730	result, err := tree.Marshal()
1731	if err != nil {
1732		t.Fatal("marshal should not error:", err)
1733	}
1734	expected := []byte("mykey = \"\"\"\nmy\\u0011multiline\nstring\\ba\tb\\fc\rd\"e\\!\"\"\"\n")
1735	if !bytes.Equal(result, expected) {
1736		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1737	}
1738}
1739
1740func TestUnmarshalTabInStringAndQuotedKey(t *testing.T) {
1741	type Test struct {
1742		Field1 string `toml:"Fie	ld1"`
1743		Field2 string
1744	}
1745
1746	type TestCase struct {
1747		desc     string
1748		input    []byte
1749		expected Test
1750	}
1751
1752	testCases := []TestCase{
1753		{
1754			desc:  "multiline string with tab",
1755			input: []byte("Field2 = \"\"\"\nhello\tworld\"\"\""),
1756			expected: Test{
1757				Field2: "hello\tworld",
1758			},
1759		},
1760		{
1761			desc:  "quoted key with tab",
1762			input: []byte("\"Fie\tld1\" = \"key with tab\""),
1763			expected: Test{
1764				Field1: "key with tab",
1765			},
1766		},
1767		{
1768			desc:  "basic string tab",
1769			input: []byte("Field2 = \"hello\tworld\""),
1770			expected: Test{
1771				Field2: "hello\tworld",
1772			},
1773		},
1774	}
1775
1776	for i := range testCases {
1777		result := Test{}
1778		err := Unmarshal(testCases[i].input, &result)
1779		if err != nil {
1780			t.Errorf("%s test error:%v", testCases[i].desc, err)
1781			continue
1782		}
1783
1784		if !reflect.DeepEqual(result, testCases[i].expected) {
1785			t.Errorf("%s test error: expected\n-----\n%+v\n-----\ngot\n-----\n%+v\n-----\n",
1786				testCases[i].desc, testCases[i].expected, result)
1787		}
1788	}
1789}
1790
1791var customMultilineTagTestToml = []byte(`int_slice = [
1792  1,
1793  2,
1794  3,
1795]
1796`)
1797
1798func TestMarshalCustomMultiline(t *testing.T) {
1799	type TypeA struct {
1800		AttrA []int `toml:"int_slice" mltln:"true"`
1801	}
1802
1803	config := TypeA{AttrA: []int{1, 2, 3}}
1804	var buf bytes.Buffer
1805	err := NewEncoder(&buf).ArraysWithOneElementPerLine(true).SetTagMultiline("mltln").Encode(config)
1806	if err != nil {
1807		t.Fatal(err)
1808	}
1809	expected := customMultilineTagTestToml
1810	result := buf.Bytes()
1811	if !bytes.Equal(result, expected) {
1812		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1813	}
1814}
1815
1816func TestMultilineWithAdjacentQuotationMarks(t *testing.T) {
1817	type testStruct struct {
1818		Str string `multiline:"true"`
1819	}
1820	type testCase struct {
1821		expected []byte
1822		data     testStruct
1823	}
1824
1825	testCases := []testCase{
1826		{
1827			expected: []byte(`Str = """
1828hello\""""
1829`),
1830			data: testStruct{
1831				Str: "hello\"",
1832			},
1833		},
1834		{
1835			expected: []byte(`Str = """
1836""\"""\"""\""""
1837`),
1838			data: testStruct{
1839				Str: "\"\"\"\"\"\"\"\"\"",
1840			},
1841		},
1842	}
1843	for i := range testCases {
1844		result, err := Marshal(testCases[i].data)
1845		if err != nil {
1846			t.Fatal(err)
1847		}
1848
1849		if !bytes.Equal(result, testCases[i].expected) {
1850			t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n",
1851				testCases[i].expected, result)
1852		} else {
1853			var data testStruct
1854			if err = Unmarshal(result, &data); err != nil {
1855				t.Fatal(err)
1856			}
1857			if data.Str != testCases[i].data.Str {
1858				t.Errorf("Round trip test fail: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n",
1859					testCases[i].data.Str, data.Str)
1860			}
1861		}
1862	}
1863}
1864
1865func TestMarshalEmbedTree(t *testing.T) {
1866	expected := []byte(`OuterField1 = "Out"
1867OuterField2 = 1024
1868
1869[TreeField]
1870  InnerField1 = "In"
1871  InnerField2 = 2048
1872
1873  [TreeField.EmbedStruct]
1874    EmbedField = "Embed"
1875`)
1876	type InnerStruct struct {
1877		InnerField1 string
1878		InnerField2 int
1879		EmbedStruct struct {
1880			EmbedField string
1881		}
1882	}
1883
1884	type OuterStruct struct {
1885		OuterField1 string
1886		OuterField2 int
1887		TreeField   *Tree
1888	}
1889
1890	tree, err := Load(`
1891InnerField1 = "In"
1892InnerField2 = 2048
1893
1894[EmbedStruct]
1895	EmbedField = "Embed"
1896`)
1897	if err != nil {
1898		t.Fatal(err)
1899	}
1900
1901	out := OuterStruct{
1902		"Out",
1903		1024,
1904		tree,
1905	}
1906	actual, _ := Marshal(out)
1907
1908	if !bytes.Equal(actual, expected) {
1909		t.Errorf("Bad marshal: expected %s, got %s", expected, actual)
1910	}
1911}
1912
1913var testDocBasicToml = []byte(`
1914[document]
1915  bool_val = true
1916  date_val = 1979-05-27T07:32:00Z
1917  float_val = 123.4
1918  int_val = 5000
1919  string_val = "Bite me"
1920  uint_val = 5001
1921`)
1922
1923type testDocCustomTag struct {
1924	Doc testDocBasicsCustomTag `file:"document"`
1925}
1926type testDocBasicsCustomTag struct {
1927	Bool       bool      `file:"bool_val"`
1928	Date       time.Time `file:"date_val"`
1929	Float      float32   `file:"float_val"`
1930	Int        int       `file:"int_val"`
1931	Uint       uint      `file:"uint_val"`
1932	String     *string   `file:"string_val"`
1933	unexported int       `file:"shouldntBeHere"`
1934}
1935
1936var testDocCustomTagData = testDocCustomTag{
1937	Doc: testDocBasicsCustomTag{
1938		Bool:       true,
1939		Date:       time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
1940		Float:      123.4,
1941		Int:        5000,
1942		Uint:       5001,
1943		String:     &biteMe,
1944		unexported: 0,
1945	},
1946}
1947
1948func TestUnmarshalCustomTag(t *testing.T) {
1949	buf := bytes.NewBuffer(testDocBasicToml)
1950
1951	result := testDocCustomTag{}
1952	err := NewDecoder(buf).SetTagName("file").Decode(&result)
1953	if err != nil {
1954		t.Fatal(err)
1955	}
1956	expected := testDocCustomTagData
1957	if !reflect.DeepEqual(result, expected) {
1958		resStr, _ := json.MarshalIndent(result, "", "  ")
1959		expStr, _ := json.MarshalIndent(expected, "", "  ")
1960		t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
1961
1962	}
1963}
1964
1965func TestUnmarshalMap(t *testing.T) {
1966	testToml := []byte(`
1967		a = 1
1968		b = 2
1969		c = 3
1970		`)
1971	var result map[string]int
1972	err := Unmarshal(testToml, &result)
1973	if err != nil {
1974		t.Errorf("Received unexpected error: %s", err)
1975		return
1976	}
1977
1978	expected := map[string]int{
1979		"a": 1,
1980		"b": 2,
1981		"c": 3,
1982	}
1983
1984	if !reflect.DeepEqual(result, expected) {
1985		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
1986	}
1987}
1988
1989func TestUnmarshalMapWithTypedKey(t *testing.T) {
1990	testToml := []byte(`
1991		a = 1
1992		b = 2
1993		c = 3
1994		`)
1995
1996	type letter string
1997	var result map[letter]int
1998	err := Unmarshal(testToml, &result)
1999	if err != nil {
2000		t.Errorf("Received unexpected error: %s", err)
2001		return
2002	}
2003
2004	expected := map[letter]int{
2005		"a": 1,
2006		"b": 2,
2007		"c": 3,
2008	}
2009
2010	if !reflect.DeepEqual(result, expected) {
2011		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
2012	}
2013}
2014
2015func TestUnmarshalNonPointer(t *testing.T) {
2016	a := 1
2017	err := Unmarshal([]byte{}, a)
2018	if err == nil {
2019		t.Fatal("unmarshal should err when given a non pointer")
2020	}
2021}
2022
2023func TestUnmarshalInvalidPointerKind(t *testing.T) {
2024	a := 1
2025	err := Unmarshal([]byte{}, &a)
2026	if err == nil {
2027		t.Fatal("unmarshal should err when given an invalid pointer type")
2028	}
2029}
2030
2031func TestMarshalSlice(t *testing.T) {
2032	m := make([]int, 1)
2033	m[0] = 1
2034
2035	var buf bytes.Buffer
2036	err := NewEncoder(&buf).Encode(&m)
2037	if err == nil {
2038		t.Error("expected error, got nil")
2039		return
2040	}
2041	if err.Error() != "Only pointer to struct can be marshaled to TOML" {
2042		t.Fail()
2043	}
2044}
2045
2046func TestMarshalSlicePointer(t *testing.T) {
2047	m := make([]int, 1)
2048	m[0] = 1
2049
2050	var buf bytes.Buffer
2051	err := NewEncoder(&buf).Encode(m)
2052	if err == nil {
2053		t.Error("expected error, got nil")
2054		return
2055	}
2056	if err.Error() != "Only a struct or map can be marshaled to TOML" {
2057		t.Fail()
2058	}
2059}
2060
2061func TestMarshalNestedArrayInlineTables(t *testing.T) {
2062	type table struct {
2063		Value1 int `toml:"ZValue1"`
2064		Value2 int `toml:"YValue2"`
2065		Value3 int `toml:"XValue3"`
2066	}
2067
2068	type nestedTable struct {
2069		Table table
2070	}
2071
2072	nestedArray := struct {
2073		Simple        [][]table
2074		SimplePointer *[]*[]table
2075		Nested        [][]nestedTable
2076		NestedPointer *[]*[]nestedTable
2077	}{
2078		Simple:        [][]table{{{Value1: 1}, {Value1: 10}}},
2079		SimplePointer: &[]*[]table{{{Value2: 2}}},
2080		Nested:        [][]nestedTable{{{Table: table{Value3: 3}}}},
2081		NestedPointer: &[]*[]nestedTable{{{Table: table{Value3: -3}}}},
2082	}
2083
2084	expectedPreserve := `Simple = [[{ ZValue1 = 1, YValue2 = 0, XValue3 = 0 }, { ZValue1 = 10, YValue2 = 0, XValue3 = 0 }]]
2085SimplePointer = [[{ ZValue1 = 0, YValue2 = 2, XValue3 = 0 }]]
2086Nested = [[{ Table = { ZValue1 = 0, YValue2 = 0, XValue3 = 3 } }]]
2087NestedPointer = [[{ Table = { ZValue1 = 0, YValue2 = 0, XValue3 = -3 } }]]
2088`
2089
2090	expectedAlphabetical := `Nested = [[{ Table = { XValue3 = 3, YValue2 = 0, ZValue1 = 0 } }]]
2091NestedPointer = [[{ Table = { XValue3 = -3, YValue2 = 0, ZValue1 = 0 } }]]
2092Simple = [[{ XValue3 = 0, YValue2 = 0, ZValue1 = 1 }, { XValue3 = 0, YValue2 = 0, ZValue1 = 10 }]]
2093SimplePointer = [[{ XValue3 = 0, YValue2 = 2, ZValue1 = 0 }]]
2094`
2095
2096	var bufPreserve bytes.Buffer
2097	if err := NewEncoder(&bufPreserve).Order(OrderPreserve).Encode(nestedArray); err != nil {
2098		t.Fatalf("unexpected error: %s", err.Error())
2099	}
2100	if !bytes.Equal(bufPreserve.Bytes(), []byte(expectedPreserve)) {
2101		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expectedPreserve, bufPreserve.String())
2102	}
2103
2104	var bufAlphabetical bytes.Buffer
2105	if err := NewEncoder(&bufAlphabetical).Order(OrderAlphabetical).Encode(nestedArray); err != nil {
2106		t.Fatalf("unexpected error: %s", err.Error())
2107	}
2108	if !bytes.Equal(bufAlphabetical.Bytes(), []byte(expectedAlphabetical)) {
2109		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expectedAlphabetical, bufAlphabetical.String())
2110	}
2111}
2112
2113type testDuration struct {
2114	Nanosec   time.Duration  `toml:"nanosec"`
2115	Microsec1 time.Duration  `toml:"microsec1"`
2116	Microsec2 *time.Duration `toml:"microsec2"`
2117	Millisec  time.Duration  `toml:"millisec"`
2118	Sec       time.Duration  `toml:"sec"`
2119	Min       time.Duration  `toml:"min"`
2120	Hour      time.Duration  `toml:"hour"`
2121	Mixed     time.Duration  `toml:"mixed"`
2122	AString   string         `toml:"a_string"`
2123}
2124
2125var testDurationToml = []byte(`
2126nanosec = "1ns"
2127microsec1 = "1us"
2128microsec2 = "1µs"
2129millisec = "1ms"
2130sec = "1s"
2131min = "1m"
2132hour = "1h"
2133mixed = "1h1m1s1ms1µs1ns"
2134a_string = "15s"
2135`)
2136
2137func TestUnmarshalDuration(t *testing.T) {
2138	buf := bytes.NewBuffer(testDurationToml)
2139
2140	result := testDuration{}
2141	err := NewDecoder(buf).Decode(&result)
2142	if err != nil {
2143		t.Fatal(err)
2144	}
2145	ms := time.Duration(1) * time.Microsecond
2146	expected := testDuration{
2147		Nanosec:   1,
2148		Microsec1: time.Microsecond,
2149		Microsec2: &ms,
2150		Millisec:  time.Millisecond,
2151		Sec:       time.Second,
2152		Min:       time.Minute,
2153		Hour:      time.Hour,
2154		Mixed: time.Hour +
2155			time.Minute +
2156			time.Second +
2157			time.Millisecond +
2158			time.Microsecond +
2159			time.Nanosecond,
2160		AString: "15s",
2161	}
2162	if !reflect.DeepEqual(result, expected) {
2163		resStr, _ := json.MarshalIndent(result, "", "  ")
2164		expStr, _ := json.MarshalIndent(expected, "", "  ")
2165		t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
2166
2167	}
2168}
2169
2170var testDurationToml2 = []byte(`a_string = "15s"
2171hour = "1h0m0s"
2172microsec1 = "1µs"
2173microsec2 = "1µs"
2174millisec = "1ms"
2175min = "1m0s"
2176mixed = "1h1m1.001001001s"
2177nanosec = "1ns"
2178sec = "1s"
2179`)
2180
2181func TestMarshalDuration(t *testing.T) {
2182	ms := time.Duration(1) * time.Microsecond
2183	data := testDuration{
2184		Nanosec:   1,
2185		Microsec1: time.Microsecond,
2186		Microsec2: &ms,
2187		Millisec:  time.Millisecond,
2188		Sec:       time.Second,
2189		Min:       time.Minute,
2190		Hour:      time.Hour,
2191		Mixed: time.Hour +
2192			time.Minute +
2193			time.Second +
2194			time.Millisecond +
2195			time.Microsecond +
2196			time.Nanosecond,
2197		AString: "15s",
2198	}
2199
2200	var buf bytes.Buffer
2201	err := NewEncoder(&buf).Encode(data)
2202	if err != nil {
2203		t.Fatal(err)
2204	}
2205	expected := testDurationToml2
2206	result := buf.Bytes()
2207	if !bytes.Equal(result, expected) {
2208		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
2209	}
2210}
2211
2212type testBadDuration struct {
2213	Val time.Duration `toml:"val"`
2214}
2215
2216var testBadDurationToml = []byte(`val = "1z"`)
2217
2218func TestUnmarshalBadDuration(t *testing.T) {
2219	buf := bytes.NewBuffer(testBadDurationToml)
2220
2221	result := testBadDuration{}
2222	err := NewDecoder(buf).Decode(&result)
2223	if err == nil {
2224		t.Fatal("expected bad duration error")
2225	}
2226}
2227
2228var testCamelCaseKeyToml = []byte(`fooBar = 10`)
2229
2230func TestUnmarshalCamelCaseKey(t *testing.T) {
2231	var x struct {
2232		FooBar int
2233		B      int
2234	}
2235
2236	if err := Unmarshal(testCamelCaseKeyToml, &x); err != nil {
2237		t.Fatal(err)
2238	}
2239
2240	if x.FooBar != 10 {
2241		t.Fatal("Did not set camelCase'd key")
2242	}
2243}
2244
2245func TestUnmarshalNegativeUint(t *testing.T) {
2246	type check struct{ U uint }
2247
2248	tree, _ := Load("u = -1")
2249	err := tree.Unmarshal(&check{})
2250	if err.Error() != "(1, 1): -1(int64) is negative so does not fit in uint" {
2251		t.Error("expect err:(1, 1): -1(int64) is negative so does not fit in uint but got:", err)
2252	}
2253}
2254
2255func TestUnmarshalCheckConversionFloatInt(t *testing.T) {
2256	type conversionCheck struct {
2257		U uint
2258		I int
2259		F float64
2260	}
2261
2262	treeU, _ := Load("u = 1e300")
2263	treeI, _ := Load("i = 1e300")
2264	treeF, _ := Load("f = 9223372036854775806")
2265
2266	errU := treeU.Unmarshal(&conversionCheck{})
2267	errI := treeI.Unmarshal(&conversionCheck{})
2268	errF := treeF.Unmarshal(&conversionCheck{})
2269
2270	if errU.Error() != "(1, 1): Can't convert 1e+300(float64) to uint" {
2271		t.Error("expect err:(1, 1): Can't convert 1e+300(float64) to uint but got:", errU)
2272	}
2273	if errI.Error() != "(1, 1): Can't convert 1e+300(float64) to int" {
2274		t.Error("expect err:(1, 1): Can't convert 1e+300(float64) to int but got:", errI)
2275	}
2276	if errF.Error() != "(1, 1): Can't convert 9223372036854775806(int64) to float64" {
2277		t.Error("expect err:(1, 1): Can't convert 9223372036854775806(int64) to float64 but got:", errF)
2278	}
2279}
2280
2281func TestUnmarshalOverflow(t *testing.T) {
2282	type overflow struct {
2283		U8  uint8
2284		I8  int8
2285		F32 float32
2286	}
2287
2288	treeU8, _ := Load("u8 = 300")
2289	treeI8, _ := Load("i8 = 300")
2290	treeF32, _ := Load("f32 = 1e300")
2291
2292	errU8 := treeU8.Unmarshal(&overflow{})
2293	errI8 := treeI8.Unmarshal(&overflow{})
2294	errF32 := treeF32.Unmarshal(&overflow{})
2295
2296	if errU8.Error() != "(1, 1): 300(int64) would overflow uint8" {
2297		t.Error("expect err:(1, 1): 300(int64) would overflow uint8 but got:", errU8)
2298	}
2299	if errI8.Error() != "(1, 1): 300(int64) would overflow int8" {
2300		t.Error("expect err:(1, 1): 300(int64) would overflow int8 but got:", errI8)
2301	}
2302	if errF32.Error() != "(1, 1): 1e+300(float64) would overflow float32" {
2303		t.Error("expect err:(1, 1): 1e+300(float64) would overflow float32 but got:", errF32)
2304	}
2305}
2306
2307func TestUnmarshalDefault(t *testing.T) {
2308	type EmbeddedStruct struct {
2309		StringField string `default:"c"`
2310	}
2311
2312	type aliasUint uint
2313
2314	var doc struct {
2315		StringField       string        `default:"a"`
2316		BoolField         bool          `default:"true"`
2317		UintField         uint          `default:"1"`
2318		Uint8Field        uint8         `default:"8"`
2319		Uint16Field       uint16        `default:"16"`
2320		Uint32Field       uint32        `default:"32"`
2321		Uint64Field       uint64        `default:"64"`
2322		IntField          int           `default:"-1"`
2323		Int8Field         int8          `default:"-8"`
2324		Int16Field        int16         `default:"-16"`
2325		Int32Field        int32         `default:"-32"`
2326		Int64Field        int64         `default:"-64"`
2327		Float32Field      float32       `default:"32.1"`
2328		Float64Field      float64       `default:"64.1"`
2329		DurationField     time.Duration `default:"120ms"`
2330		DurationField2    time.Duration `default:"120000000"`
2331		NonEmbeddedStruct struct {
2332			StringField string `default:"b"`
2333		}
2334		EmbeddedStruct
2335		AliasUintField aliasUint `default:"1000"`
2336	}
2337
2338	err := Unmarshal([]byte(``), &doc)
2339	if err != nil {
2340		t.Fatal(err)
2341	}
2342	if doc.BoolField != true {
2343		t.Errorf("BoolField should be true, not %t", doc.BoolField)
2344	}
2345	if doc.StringField != "a" {
2346		t.Errorf("StringField should be \"a\", not %s", doc.StringField)
2347	}
2348	if doc.UintField != 1 {
2349		t.Errorf("UintField should be 1, not %d", doc.UintField)
2350	}
2351	if doc.Uint8Field != 8 {
2352		t.Errorf("Uint8Field should be 8, not %d", doc.Uint8Field)
2353	}
2354	if doc.Uint16Field != 16 {
2355		t.Errorf("Uint16Field should be 16, not %d", doc.Uint16Field)
2356	}
2357	if doc.Uint32Field != 32 {
2358		t.Errorf("Uint32Field should be 32, not %d", doc.Uint32Field)
2359	}
2360	if doc.Uint64Field != 64 {
2361		t.Errorf("Uint64Field should be 64, not %d", doc.Uint64Field)
2362	}
2363	if doc.IntField != -1 {
2364		t.Errorf("IntField should be -1, not %d", doc.IntField)
2365	}
2366	if doc.Int8Field != -8 {
2367		t.Errorf("Int8Field should be -8, not %d", doc.Int8Field)
2368	}
2369	if doc.Int16Field != -16 {
2370		t.Errorf("Int16Field should be -16, not %d", doc.Int16Field)
2371	}
2372	if doc.Int32Field != -32 {
2373		t.Errorf("Int32Field should be -32, not %d", doc.Int32Field)
2374	}
2375	if doc.Int64Field != -64 {
2376		t.Errorf("Int64Field should be -64, not %d", doc.Int64Field)
2377	}
2378	if doc.Float32Field != 32.1 {
2379		t.Errorf("Float32Field should be 32.1, not %f", doc.Float32Field)
2380	}
2381	if doc.Float64Field != 64.1 {
2382		t.Errorf("Float64Field should be 64.1, not %f", doc.Float64Field)
2383	}
2384	if doc.DurationField != 120*time.Millisecond {
2385		t.Errorf("DurationField should be 120ms, not %s", doc.DurationField.String())
2386	}
2387	if doc.DurationField2 != 120*time.Millisecond {
2388		t.Errorf("DurationField2 should be 120000000, not %d", doc.DurationField2)
2389	}
2390	if doc.NonEmbeddedStruct.StringField != "b" {
2391		t.Errorf("StringField should be \"b\", not %s", doc.NonEmbeddedStruct.StringField)
2392	}
2393	if doc.EmbeddedStruct.StringField != "c" {
2394		t.Errorf("StringField should be \"c\", not %s", doc.EmbeddedStruct.StringField)
2395	}
2396	if doc.AliasUintField != 1000 {
2397		t.Errorf("AliasUintField should be 1000, not %d", doc.AliasUintField)
2398	}
2399}
2400
2401func TestUnmarshalDefaultFailureBool(t *testing.T) {
2402	var doc struct {
2403		Field bool `default:"blah"`
2404	}
2405
2406	err := Unmarshal([]byte(``), &doc)
2407	if err == nil {
2408		t.Fatal("should error")
2409	}
2410}
2411
2412func TestUnmarshalDefaultFailureInt(t *testing.T) {
2413	var doc struct {
2414		Field int `default:"blah"`
2415	}
2416
2417	err := Unmarshal([]byte(``), &doc)
2418	if err == nil {
2419		t.Fatal("should error")
2420	}
2421}
2422
2423func TestUnmarshalDefaultFailureInt64(t *testing.T) {
2424	var doc struct {
2425		Field int64 `default:"blah"`
2426	}
2427
2428	err := Unmarshal([]byte(``), &doc)
2429	if err == nil {
2430		t.Fatal("should error")
2431	}
2432}
2433
2434func TestUnmarshalDefaultFailureFloat64(t *testing.T) {
2435	var doc struct {
2436		Field float64 `default:"blah"`
2437	}
2438
2439	err := Unmarshal([]byte(``), &doc)
2440	if err == nil {
2441		t.Fatal("should error")
2442	}
2443}
2444
2445func TestUnmarshalDefaultFailureDuration(t *testing.T) {
2446	var doc struct {
2447		Field time.Duration `default:"blah"`
2448	}
2449
2450	err := Unmarshal([]byte(``), &doc)
2451	if err == nil {
2452		t.Fatal("should error")
2453	}
2454}
2455
2456func TestUnmarshalDefaultFailureUnsupported(t *testing.T) {
2457	var doc struct {
2458		Field struct{} `default:"blah"`
2459	}
2460
2461	err := Unmarshal([]byte(``), &doc)
2462	if err == nil {
2463		t.Fatal("should error")
2464	}
2465}
2466
2467func TestMarshalNestedAnonymousStructs(t *testing.T) {
2468	type Embedded struct {
2469		Value string `toml:"value"`
2470		Top   struct {
2471			Value string `toml:"value"`
2472		} `toml:"top"`
2473	}
2474
2475	type Named struct {
2476		Value string `toml:"value"`
2477	}
2478
2479	var doc struct {
2480		Embedded
2481		Named     `toml:"named"`
2482		Anonymous struct {
2483			Value string `toml:"value"`
2484		} `toml:"anonymous"`
2485	}
2486
2487	expected := `value = ""
2488
2489[anonymous]
2490  value = ""
2491
2492[named]
2493  value = ""
2494
2495[top]
2496  value = ""
2497`
2498
2499	result, err := Marshal(doc)
2500	if err != nil {
2501		t.Fatalf("unexpected error: %s", err.Error())
2502	}
2503	if !bytes.Equal(result, []byte(expected)) {
2504		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, string(result))
2505	}
2506}
2507
2508func TestEncoderPromoteNestedAnonymousStructs(t *testing.T) {
2509	type Embedded struct {
2510		Value string `toml:"value"`
2511	}
2512
2513	var doc struct {
2514		Embedded
2515	}
2516
2517	expected := `
2518[Embedded]
2519  value = ""
2520`
2521	var buf bytes.Buffer
2522	if err := NewEncoder(&buf).PromoteAnonymous(true).Encode(doc); err != nil {
2523		t.Fatalf("unexpected error: %s", err.Error())
2524	}
2525	if !bytes.Equal(buf.Bytes(), []byte(expected)) {
2526		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, buf.String())
2527	}
2528}
2529
2530func TestMarshalNestedAnonymousStructs_DuplicateField(t *testing.T) {
2531	type Embedded struct {
2532		Value string `toml:"value"`
2533		Top   struct {
2534			Value string `toml:"value"`
2535		} `toml:"top"`
2536	}
2537
2538	var doc struct {
2539		Value string `toml:"value"`
2540		Embedded
2541	}
2542	doc.Embedded.Value = "shadowed"
2543	doc.Value = "shadows"
2544
2545	expected := `value = "shadows"
2546
2547[top]
2548  value = ""
2549`
2550
2551	result, err := Marshal(doc)
2552	if err != nil {
2553		t.Fatalf("unexpected error: %s", err.Error())
2554	}
2555	if !bytes.Equal(result, []byte(expected)) {
2556		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, string(result))
2557	}
2558}
2559
2560func TestUnmarshalNestedAnonymousStructs(t *testing.T) {
2561	type Nested struct {
2562		Value string `toml:"nested_field"`
2563	}
2564	type Deep struct {
2565		Nested
2566	}
2567	type Document struct {
2568		Deep
2569		Value string `toml:"own_field"`
2570	}
2571
2572	var doc Document
2573
2574	err := Unmarshal([]byte(`nested_field = "nested value"`+"\n"+`own_field = "own value"`), &doc)
2575	if err != nil {
2576		t.Fatal("should not error")
2577	}
2578	if doc.Value != "own value" || doc.Nested.Value != "nested value" {
2579		t.Fatal("unexpected values")
2580	}
2581}
2582
2583func TestUnmarshalNestedAnonymousStructs_Controversial(t *testing.T) {
2584	type Nested struct {
2585		Value string `toml:"nested"`
2586	}
2587	type Deep struct {
2588		Nested
2589	}
2590	type Document struct {
2591		Deep
2592		Value string `toml:"own"`
2593	}
2594
2595	var doc Document
2596
2597	err := Unmarshal([]byte(`nested = "nested value"`+"\n"+`own = "own value"`), &doc)
2598	if err == nil {
2599		t.Fatal("should error")
2600	}
2601}
2602
2603type unexportedFieldPreservationTest struct {
2604	Exported   string `toml:"exported"`
2605	unexported string
2606	Nested1    unexportedFieldPreservationTestNested    `toml:"nested1"`
2607	Nested2    *unexportedFieldPreservationTestNested   `toml:"nested2"`
2608	Nested3    *unexportedFieldPreservationTestNested   `toml:"nested3"`
2609	Slice1     []unexportedFieldPreservationTestNested  `toml:"slice1"`
2610	Slice2     []*unexportedFieldPreservationTestNested `toml:"slice2"`
2611}
2612
2613type unexportedFieldPreservationTestNested struct {
2614	Exported1   string `toml:"exported1"`
2615	unexported1 string
2616}
2617
2618func TestUnmarshalPreservesUnexportedFields(t *testing.T) {
2619	toml := `
2620	exported = "visible"
2621	unexported = "ignored"
2622
2623	[nested1]
2624	exported1 = "visible1"
2625	unexported1 = "ignored1"
2626
2627	[nested2]
2628	exported1 = "visible2"
2629	unexported1 = "ignored2"
2630
2631	[nested3]
2632	exported1 = "visible3"
2633	unexported1 = "ignored3"
2634
2635	[[slice1]]
2636	exported1 = "visible3"
2637
2638	[[slice1]]
2639	exported1 = "visible4"
2640
2641	[[slice2]]
2642	exported1 = "visible5"
2643	`
2644
2645	t.Run("unexported field should not be set from toml", func(t *testing.T) {
2646		var actual unexportedFieldPreservationTest
2647		err := Unmarshal([]byte(toml), &actual)
2648
2649		if err != nil {
2650			t.Fatal("did not expect an error")
2651		}
2652
2653		expect := unexportedFieldPreservationTest{
2654			Exported:   "visible",
2655			unexported: "",
2656			Nested1:    unexportedFieldPreservationTestNested{"visible1", ""},
2657			Nested2:    &unexportedFieldPreservationTestNested{"visible2", ""},
2658			Nested3:    &unexportedFieldPreservationTestNested{"visible3", ""},
2659			Slice1: []unexportedFieldPreservationTestNested{
2660				{Exported1: "visible3"},
2661				{Exported1: "visible4"},
2662			},
2663			Slice2: []*unexportedFieldPreservationTestNested{
2664				{Exported1: "visible5"},
2665			},
2666		}
2667
2668		if !reflect.DeepEqual(actual, expect) {
2669			t.Fatalf("%+v did not equal %+v", actual, expect)
2670		}
2671	})
2672
2673	t.Run("unexported field should be preserved", func(t *testing.T) {
2674		actual := unexportedFieldPreservationTest{
2675			Exported:   "foo",
2676			unexported: "bar",
2677			Nested1:    unexportedFieldPreservationTestNested{"baz", "bax"},
2678			Nested2:    nil,
2679			Nested3:    &unexportedFieldPreservationTestNested{"baz", "bax"},
2680		}
2681		err := Unmarshal([]byte(toml), &actual)
2682
2683		if err != nil {
2684			t.Fatal("did not expect an error")
2685		}
2686
2687		expect := unexportedFieldPreservationTest{
2688			Exported:   "visible",
2689			unexported: "bar",
2690			Nested1:    unexportedFieldPreservationTestNested{"visible1", "bax"},
2691			Nested2:    &unexportedFieldPreservationTestNested{"visible2", ""},
2692			Nested3:    &unexportedFieldPreservationTestNested{"visible3", "bax"},
2693			Slice1: []unexportedFieldPreservationTestNested{
2694				{Exported1: "visible3"},
2695				{Exported1: "visible4"},
2696			},
2697			Slice2: []*unexportedFieldPreservationTestNested{
2698				{Exported1: "visible5"},
2699			},
2700		}
2701
2702		if !reflect.DeepEqual(actual, expect) {
2703			t.Fatalf("%+v did not equal %+v", actual, expect)
2704		}
2705	})
2706}
2707
2708func TestTreeMarshal(t *testing.T) {
2709	cases := [][]byte{
2710		basicTestToml,
2711		marshalTestToml,
2712		emptyTestToml,
2713		pointerTestToml,
2714	}
2715	for _, expected := range cases {
2716		t.Run("", func(t *testing.T) {
2717			tree, err := LoadBytes(expected)
2718			if err != nil {
2719				t.Fatal(err)
2720			}
2721			result, err := tree.Marshal()
2722			if err != nil {
2723				t.Fatal(err)
2724			}
2725			if !bytes.Equal(result, expected) {
2726				t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
2727			}
2728		})
2729	}
2730}
2731
2732func TestMarshalArrays(t *testing.T) {
2733	cases := []struct {
2734		Data     interface{}
2735		Expected string
2736	}{
2737		{
2738			Data: struct {
2739				XY [2]int
2740			}{
2741				XY: [2]int{1, 2},
2742			},
2743			Expected: `XY = [1, 2]
2744`,
2745		},
2746		{
2747			Data: struct {
2748				XY [1][2]int
2749			}{
2750				XY: [1][2]int{{1, 2}},
2751			},
2752			Expected: `XY = [[1, 2]]
2753`,
2754		},
2755		{
2756			Data: struct {
2757				XY [1][]int
2758			}{
2759				XY: [1][]int{{1, 2}},
2760			},
2761			Expected: `XY = [[1, 2]]
2762`,
2763		},
2764		{
2765			Data: struct {
2766				XY [][2]int
2767			}{
2768				XY: [][2]int{{1, 2}},
2769			},
2770			Expected: `XY = [[1, 2]]
2771`,
2772		},
2773	}
2774	for _, tc := range cases {
2775		t.Run("", func(t *testing.T) {
2776			result, err := Marshal(tc.Data)
2777			if err != nil {
2778				t.Fatal(err)
2779			}
2780			if !bytes.Equal(result, []byte(tc.Expected)) {
2781				t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", []byte(tc.Expected), result)
2782			}
2783		})
2784	}
2785}
2786
2787func TestUnmarshalLocalDate(t *testing.T) {
2788	t.Run("ToLocalDate", func(t *testing.T) {
2789		type dateStruct struct {
2790			Date LocalDate
2791		}
2792
2793		toml := `date = 1979-05-27`
2794
2795		var obj dateStruct
2796
2797		err := Unmarshal([]byte(toml), &obj)
2798
2799		if err != nil {
2800			t.Fatal(err)
2801		}
2802
2803		if obj.Date.Year != 1979 {
2804			t.Errorf("expected year 1979, got %d", obj.Date.Year)
2805		}
2806		if obj.Date.Month != 5 {
2807			t.Errorf("expected month 5, got %d", obj.Date.Month)
2808		}
2809		if obj.Date.Day != 27 {
2810			t.Errorf("expected day 27, got %d", obj.Date.Day)
2811		}
2812	})
2813
2814	t.Run("ToLocalDate", func(t *testing.T) {
2815		type dateStruct struct {
2816			Date time.Time
2817		}
2818
2819		toml := `date = 1979-05-27`
2820
2821		var obj dateStruct
2822
2823		err := Unmarshal([]byte(toml), &obj)
2824
2825		if err != nil {
2826			t.Fatal(err)
2827		}
2828
2829		if obj.Date.Year() != 1979 {
2830			t.Errorf("expected year 1979, got %d", obj.Date.Year())
2831		}
2832		if obj.Date.Month() != 5 {
2833			t.Errorf("expected month 5, got %d", obj.Date.Month())
2834		}
2835		if obj.Date.Day() != 27 {
2836			t.Errorf("expected day 27, got %d", obj.Date.Day())
2837		}
2838	})
2839}
2840
2841func TestMarshalLocalDate(t *testing.T) {
2842	type dateStruct struct {
2843		Date LocalDate
2844	}
2845
2846	obj := dateStruct{Date: LocalDate{
2847		Year:  1979,
2848		Month: 5,
2849		Day:   27,
2850	}}
2851
2852	b, err := Marshal(obj)
2853
2854	if err != nil {
2855		t.Fatalf("unexpected error: %v", err)
2856	}
2857
2858	got := string(b)
2859	expected := `Date = 1979-05-27
2860`
2861
2862	if got != expected {
2863		t.Errorf("expected '%s', got '%s'", expected, got)
2864	}
2865}
2866
2867func TestUnmarshalLocalDateTime(t *testing.T) {
2868	examples := []struct {
2869		name string
2870		in   string
2871		out  LocalDateTime
2872	}{
2873		{
2874			name: "normal",
2875			in:   "1979-05-27T07:32:00",
2876			out: LocalDateTime{
2877				Date: LocalDate{
2878					Year:  1979,
2879					Month: 5,
2880					Day:   27,
2881				},
2882				Time: LocalTime{
2883					Hour:       7,
2884					Minute:     32,
2885					Second:     0,
2886					Nanosecond: 0,
2887				},
2888			}},
2889		{
2890			name: "with nanoseconds",
2891			in:   "1979-05-27T00:32:00.999999",
2892			out: LocalDateTime{
2893				Date: LocalDate{
2894					Year:  1979,
2895					Month: 5,
2896					Day:   27,
2897				},
2898				Time: LocalTime{
2899					Hour:       0,
2900					Minute:     32,
2901					Second:     0,
2902					Nanosecond: 999999000,
2903				},
2904			},
2905		},
2906	}
2907
2908	for i, example := range examples {
2909		toml := fmt.Sprintf(`date = %s`, example.in)
2910
2911		t.Run(fmt.Sprintf("ToLocalDateTime_%d_%s", i, example.name), func(t *testing.T) {
2912			type dateStruct struct {
2913				Date LocalDateTime
2914			}
2915
2916			var obj dateStruct
2917
2918			err := Unmarshal([]byte(toml), &obj)
2919
2920			if err != nil {
2921				t.Fatal(err)
2922			}
2923
2924			if obj.Date != example.out {
2925				t.Errorf("expected '%s', got '%s'", example.out, obj.Date)
2926			}
2927		})
2928
2929		t.Run(fmt.Sprintf("ToTime_%d_%s", i, example.name), func(t *testing.T) {
2930			type dateStruct struct {
2931				Date time.Time
2932			}
2933
2934			var obj dateStruct
2935
2936			err := Unmarshal([]byte(toml), &obj)
2937
2938			if err != nil {
2939				t.Fatal(err)
2940			}
2941
2942			if obj.Date.Year() != example.out.Date.Year {
2943				t.Errorf("expected year %d, got %d", example.out.Date.Year, obj.Date.Year())
2944			}
2945			if obj.Date.Month() != example.out.Date.Month {
2946				t.Errorf("expected month %d, got %d", example.out.Date.Month, obj.Date.Month())
2947			}
2948			if obj.Date.Day() != example.out.Date.Day {
2949				t.Errorf("expected day %d, got %d", example.out.Date.Day, obj.Date.Day())
2950			}
2951			if obj.Date.Hour() != example.out.Time.Hour {
2952				t.Errorf("expected hour %d, got %d", example.out.Time.Hour, obj.Date.Hour())
2953			}
2954			if obj.Date.Minute() != example.out.Time.Minute {
2955				t.Errorf("expected minute %d, got %d", example.out.Time.Minute, obj.Date.Minute())
2956			}
2957			if obj.Date.Second() != example.out.Time.Second {
2958				t.Errorf("expected second %d, got %d", example.out.Time.Second, obj.Date.Second())
2959			}
2960			if obj.Date.Nanosecond() != example.out.Time.Nanosecond {
2961				t.Errorf("expected nanoseconds %d, got %d", example.out.Time.Nanosecond, obj.Date.Nanosecond())
2962			}
2963		})
2964	}
2965}
2966
2967func TestMarshalLocalDateTime(t *testing.T) {
2968	type dateStruct struct {
2969		DateTime LocalDateTime
2970	}
2971
2972	examples := []struct {
2973		name string
2974		in   LocalDateTime
2975		out  string
2976	}{
2977		{
2978			name: "normal",
2979			out:  "DateTime = 1979-05-27T07:32:00\n",
2980			in: LocalDateTime{
2981				Date: LocalDate{
2982					Year:  1979,
2983					Month: 5,
2984					Day:   27,
2985				},
2986				Time: LocalTime{
2987					Hour:       7,
2988					Minute:     32,
2989					Second:     0,
2990					Nanosecond: 0,
2991				},
2992			}},
2993		{
2994			name: "with nanoseconds",
2995			out:  "DateTime = 1979-05-27T00:32:00.999999000\n",
2996			in: LocalDateTime{
2997				Date: LocalDate{
2998					Year:  1979,
2999					Month: 5,
3000					Day:   27,
3001				},
3002				Time: LocalTime{
3003					Hour:       0,
3004					Minute:     32,
3005					Second:     0,
3006					Nanosecond: 999999000,
3007				},
3008			},
3009		},
3010	}
3011
3012	for i, example := range examples {
3013		t.Run(fmt.Sprintf("%d_%s", i, example.name), func(t *testing.T) {
3014			obj := dateStruct{
3015				DateTime: example.in,
3016			}
3017			b, err := Marshal(obj)
3018
3019			if err != nil {
3020				t.Fatalf("unexpected error: %v", err)
3021			}
3022
3023			got := string(b)
3024
3025			if got != example.out {
3026				t.Errorf("expected '%s', got '%s'", example.out, got)
3027			}
3028		})
3029	}
3030}
3031
3032func TestUnmarshalLocalTime(t *testing.T) {
3033	examples := []struct {
3034		name string
3035		in   string
3036		out  LocalTime
3037	}{
3038		{
3039			name: "normal",
3040			in:   "07:32:00",
3041			out: LocalTime{
3042				Hour:       7,
3043				Minute:     32,
3044				Second:     0,
3045				Nanosecond: 0,
3046			},
3047		},
3048		{
3049			name: "with nanoseconds",
3050			in:   "00:32:00.999999",
3051			out: LocalTime{
3052				Hour:       0,
3053				Minute:     32,
3054				Second:     0,
3055				Nanosecond: 999999000,
3056			},
3057		},
3058	}
3059
3060	for i, example := range examples {
3061		toml := fmt.Sprintf(`Time = %s`, example.in)
3062
3063		t.Run(fmt.Sprintf("ToLocalTime_%d_%s", i, example.name), func(t *testing.T) {
3064			type dateStruct struct {
3065				Time LocalTime
3066			}
3067
3068			var obj dateStruct
3069
3070			err := Unmarshal([]byte(toml), &obj)
3071
3072			if err != nil {
3073				t.Fatal(err)
3074			}
3075
3076			if obj.Time != example.out {
3077				t.Errorf("expected '%s', got '%s'", example.out, obj.Time)
3078			}
3079		})
3080	}
3081}
3082
3083func TestMarshalLocalTime(t *testing.T) {
3084	type timeStruct struct {
3085		Time LocalTime
3086	}
3087
3088	examples := []struct {
3089		name string
3090		in   LocalTime
3091		out  string
3092	}{
3093		{
3094			name: "normal",
3095			out:  "Time = 07:32:00\n",
3096			in: LocalTime{
3097				Hour:       7,
3098				Minute:     32,
3099				Second:     0,
3100				Nanosecond: 0,
3101			}},
3102		{
3103			name: "with nanoseconds",
3104			out:  "Time = 00:32:00.999999000\n",
3105			in: LocalTime{
3106				Hour:       0,
3107				Minute:     32,
3108				Second:     0,
3109				Nanosecond: 999999000,
3110			},
3111		},
3112	}
3113
3114	for i, example := range examples {
3115		t.Run(fmt.Sprintf("%d_%s", i, example.name), func(t *testing.T) {
3116			obj := timeStruct{
3117				Time: example.in,
3118			}
3119			b, err := Marshal(obj)
3120
3121			if err != nil {
3122				t.Fatalf("unexpected error: %v", err)
3123			}
3124
3125			got := string(b)
3126
3127			if got != example.out {
3128				t.Errorf("expected '%s', got '%s'", example.out, got)
3129			}
3130		})
3131	}
3132}
3133
3134// test case for issue #339
3135func TestUnmarshalSameInnerField(t *testing.T) {
3136	type InterStruct2 struct {
3137		Test string
3138		Name string
3139		Age  int
3140	}
3141	type Inter2 struct {
3142		Name         string
3143		Age          int
3144		InterStruct2 InterStruct2
3145	}
3146	type Server struct {
3147		Name   string `toml:"name"`
3148		Inter2 Inter2 `toml:"inter2"`
3149	}
3150
3151	var server Server
3152
3153	if err := Unmarshal([]byte(`name = "123"
3154[inter2]
3155name = "inter2"
3156age = 222`), &server); err == nil {
3157		expected := Server{
3158			Name: "123",
3159			Inter2: Inter2{
3160				Name: "inter2",
3161				Age:  222,
3162			},
3163		}
3164		if !reflect.DeepEqual(server, expected) {
3165			t.Errorf("Bad unmarshal: expected %v, got %v", expected, server)
3166		}
3167	} else {
3168		t.Fatalf("unexpected error: %v", err)
3169	}
3170}
3171
3172func TestMarshalInterface(t *testing.T) {
3173	type InnerStruct struct {
3174		InnerField string
3175	}
3176
3177	type OuterStruct struct {
3178		PrimitiveField        interface{}
3179		ArrayField            interface{}
3180		StructArrayField      interface{}
3181		MapField              map[string]interface{}
3182		StructField           interface{}
3183		PointerField          interface{}
3184		NilField              interface{}
3185		InterfacePointerField *interface{}
3186	}
3187
3188	expected := []byte(`ArrayField = [1, 2, 3]
3189InterfacePointerField = "hello world"
3190PrimitiveField = "string"
3191
3192[MapField]
3193  key1 = "value1"
3194  key2 = false
3195
3196  [MapField.key3]
3197    InnerField = "value3"
3198
3199[PointerField]
3200  InnerField = "yyy"
3201
3202[[StructArrayField]]
3203  InnerField = "s1"
3204
3205[[StructArrayField]]
3206  InnerField = "s2"
3207
3208[StructField]
3209  InnerField = "xxx"
3210`)
3211
3212	var h interface{} = "hello world"
3213	if result, err := Marshal(OuterStruct{
3214		"string",
3215		[]int{1, 2, 3},
3216		[]InnerStruct{{"s1"}, {"s2"}},
3217		map[string]interface{}{
3218			"key1":      "value1",
3219			"key2":      false,
3220			"key3":      InnerStruct{"value3"},
3221			"nil value": nil,
3222		},
3223		InnerStruct{
3224			"xxx",
3225		},
3226		&InnerStruct{
3227			"yyy",
3228		},
3229		nil,
3230		&h,
3231	}); err == nil {
3232		if !bytes.Equal(result, expected) {
3233			t.Errorf("Bad marshal: expected\n----\n%s\n----\ngot\n----\n%s\n----\n", expected, result)
3234		}
3235	} else {
3236		t.Fatal(err)
3237	}
3238}
3239
3240func TestUnmarshalToNilInterface(t *testing.T) {
3241	toml := []byte(`
3242PrimitiveField = "Hello"
3243ArrayField = [1,2,3]
3244InterfacePointerField = "World"
3245
3246[StructField]
3247Field1 = 123
3248Field2 = "Field2"
3249
3250[MapField]
3251MapField1 = [4,5,6]
3252MapField2 = {A = "A"}
3253MapField3 = false
3254
3255[[StructArrayField]]
3256Name = "Allen"
3257Age = 20
3258
3259[[StructArrayField]]
3260Name = "Jack"
3261Age = 23
3262`)
3263
3264	type OuterStruct struct {
3265		PrimitiveField        interface{}
3266		ArrayField            interface{}
3267		StructArrayField      interface{}
3268		MapField              map[string]interface{}
3269		StructField           interface{}
3270		NilField              interface{}
3271		InterfacePointerField *interface{}
3272	}
3273
3274	var s interface{} = "World"
3275	expected := OuterStruct{
3276		PrimitiveField: "Hello",
3277		ArrayField:     []interface{}{int64(1), int64(2), int64(3)},
3278		StructField: map[string]interface{}{
3279			"Field1": int64(123),
3280			"Field2": "Field2",
3281		},
3282		MapField: map[string]interface{}{
3283			"MapField1": []interface{}{int64(4), int64(5), int64(6)},
3284			"MapField2": map[string]interface{}{
3285				"A": "A",
3286			},
3287			"MapField3": false,
3288		},
3289		NilField:              nil,
3290		InterfacePointerField: &s,
3291		StructArrayField: []map[string]interface{}{
3292			{
3293				"Name": "Allen",
3294				"Age":  int64(20),
3295			},
3296			{
3297				"Name": "Jack",
3298				"Age":  int64(23),
3299			},
3300		},
3301	}
3302	actual := OuterStruct{}
3303	if err := Unmarshal(toml, &actual); err == nil {
3304		if !reflect.DeepEqual(actual, expected) {
3305			t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3306		}
3307	} else {
3308		t.Fatal(err)
3309	}
3310}
3311
3312func TestUnmarshalToNonNilInterface(t *testing.T) {
3313	toml := []byte(`
3314PrimitiveField = "Allen"
3315ArrayField = [1,2,3]
3316
3317[StructField]
3318InnerField = "After1"
3319
3320[PointerField]
3321InnerField = "After2"
3322
3323[InterfacePointerField]
3324InnerField = "After"
3325
3326[MapField]
3327MapField1 = [4,5,6]
3328MapField2 = {A = "A"}
3329MapField3 = false
3330
3331[[StructArrayField]]
3332InnerField = "After3"
3333
3334[[StructArrayField]]
3335InnerField = "After4"
3336`)
3337	type InnerStruct struct {
3338		InnerField interface{}
3339	}
3340
3341	type OuterStruct struct {
3342		PrimitiveField        interface{}
3343		ArrayField            interface{}
3344		StructArrayField      interface{}
3345		MapField              map[string]interface{}
3346		StructField           interface{}
3347		PointerField          interface{}
3348		NilField              interface{}
3349		InterfacePointerField *interface{}
3350	}
3351
3352	var s interface{} = InnerStruct{"After"}
3353	expected := OuterStruct{
3354		PrimitiveField: "Allen",
3355		ArrayField:     []int{1, 2, 3},
3356		StructField:    InnerStruct{InnerField: "After1"},
3357		MapField: map[string]interface{}{
3358			"MapField1": []interface{}{int64(4), int64(5), int64(6)},
3359			"MapField2": map[string]interface{}{
3360				"A": "A",
3361			},
3362			"MapField3": false,
3363		},
3364		PointerField:          &InnerStruct{InnerField: "After2"},
3365		NilField:              nil,
3366		InterfacePointerField: &s,
3367		StructArrayField: []InnerStruct{
3368			{InnerField: "After3"},
3369			{InnerField: "After4"},
3370		},
3371	}
3372	actual := OuterStruct{
3373		PrimitiveField: "aaa",
3374		ArrayField:     []int{100, 200, 300, 400},
3375		StructField:    InnerStruct{InnerField: "Before1"},
3376		MapField: map[string]interface{}{
3377			"MapField1": []int{4, 5, 6},
3378			"MapField2": map[string]string{
3379				"B": "BBB",
3380			},
3381			"MapField3": true,
3382		},
3383		PointerField:          &InnerStruct{InnerField: "Before2"},
3384		NilField:              nil,
3385		InterfacePointerField: &s,
3386		StructArrayField: []InnerStruct{
3387			{InnerField: "Before3"},
3388			{InnerField: "Before4"},
3389		},
3390	}
3391	if err := Unmarshal(toml, &actual); err == nil {
3392		if !reflect.DeepEqual(actual, expected) {
3393			t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3394		}
3395	} else {
3396		t.Fatal(err)
3397	}
3398}
3399
3400func TestUnmarshalEmbedTree(t *testing.T) {
3401	toml := []byte(`
3402OuterField1 = "Out"
3403OuterField2 = 1024
3404
3405[TreeField]
3406InnerField1 = "In"
3407InnerField2 = 2048
3408
3409	[TreeField.EmbedStruct]
3410		EmbedField = "Embed"
3411
3412`)
3413	type InnerStruct struct {
3414		InnerField1 string
3415		InnerField2 int
3416		EmbedStruct struct {
3417			EmbedField string
3418		}
3419	}
3420
3421	type OuterStruct struct {
3422		OuterField1 string
3423		OuterField2 int
3424		TreeField   *Tree
3425	}
3426
3427	out := OuterStruct{}
3428	actual := InnerStruct{}
3429	expected := InnerStruct{
3430		"In",
3431		2048,
3432		struct {
3433			EmbedField string
3434		}{
3435			EmbedField: "Embed",
3436		},
3437	}
3438	if err := Unmarshal(toml, &out); err != nil {
3439		t.Fatal(err)
3440	}
3441	if err := out.TreeField.Unmarshal(&actual); err != nil {
3442		t.Fatal(err)
3443	}
3444
3445	if !reflect.DeepEqual(actual, expected) {
3446		t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3447	}
3448}
3449
3450func TestMarshalNil(t *testing.T) {
3451	if _, err := Marshal(nil); err == nil {
3452		t.Errorf("Expected err from nil marshal")
3453	}
3454	if _, err := Marshal((*struct{})(nil)); err == nil {
3455		t.Errorf("Expected err from nil marshal")
3456	}
3457}
3458
3459func TestUnmarshalNil(t *testing.T) {
3460	if err := Unmarshal([]byte(`whatever = "whatever"`), nil); err == nil {
3461		t.Errorf("Expected err from nil marshal")
3462	}
3463	if err := Unmarshal([]byte(`whatever = "whatever"`), (*struct{})(nil)); err == nil {
3464		t.Errorf("Expected err from nil marshal")
3465	}
3466}
3467
3468var sliceTomlDemo = []byte(`str_slice = ["Howdy","Hey There"]
3469str_slice_ptr= ["Howdy","Hey There"]
3470int_slice=[1,2]
3471int_slice_ptr=[1,2]
3472[[struct_slice]]
3473String2="1"
3474[[struct_slice]]
3475String2="2"
3476[[struct_slice_ptr]]
3477String2="1"
3478[[struct_slice_ptr]]
3479String2="2"
3480`)
3481
3482type sliceStruct struct {
3483	Slice          []string                     `  toml:"str_slice"  `
3484	SlicePtr       *[]string                    `  toml:"str_slice_ptr"  `
3485	IntSlice       []int                        `  toml:"int_slice"  `
3486	IntSlicePtr    *[]int                       `  toml:"int_slice_ptr"  `
3487	StructSlice    []basicMarshalTestSubStruct  `  toml:"struct_slice"  `
3488	StructSlicePtr *[]basicMarshalTestSubStruct `  toml:"struct_slice_ptr"  `
3489}
3490
3491type arrayStruct struct {
3492	Slice          [4]string                     `  toml:"str_slice"  `
3493	SlicePtr       *[4]string                    `  toml:"str_slice_ptr"  `
3494	IntSlice       [4]int                        `  toml:"int_slice"  `
3495	IntSlicePtr    *[4]int                       `  toml:"int_slice_ptr"  `
3496	StructSlice    [4]basicMarshalTestSubStruct  `  toml:"struct_slice"  `
3497	StructSlicePtr *[4]basicMarshalTestSubStruct `  toml:"struct_slice_ptr"  `
3498}
3499
3500type arrayTooSmallStruct struct {
3501	Slice       [1]string                    `  toml:"str_slice"  `
3502	StructSlice [1]basicMarshalTestSubStruct `  toml:"struct_slice"  `
3503}
3504
3505func TestUnmarshalSlice(t *testing.T) {
3506	tree, _ := LoadBytes(sliceTomlDemo)
3507	tree, _ = TreeFromMap(tree.ToMap())
3508
3509	var actual sliceStruct
3510	err := tree.Unmarshal(&actual)
3511	if err != nil {
3512		t.Error("shound not err", err)
3513	}
3514	expected := sliceStruct{
3515		Slice:          []string{"Howdy", "Hey There"},
3516		SlicePtr:       &[]string{"Howdy", "Hey There"},
3517		IntSlice:       []int{1, 2},
3518		IntSlicePtr:    &[]int{1, 2},
3519		StructSlice:    []basicMarshalTestSubStruct{{"1"}, {"2"}},
3520		StructSlicePtr: &[]basicMarshalTestSubStruct{{"1"}, {"2"}},
3521	}
3522	if !reflect.DeepEqual(actual, expected) {
3523		t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual)
3524	}
3525
3526}
3527
3528func TestUnmarshalSliceFail(t *testing.T) {
3529	tree, _ := TreeFromMap(map[string]interface{}{
3530		"str_slice": []int{1, 2},
3531	})
3532
3533	var actual sliceStruct
3534	err := tree.Unmarshal(&actual)
3535	if err.Error() != "(0, 0): Can't convert 1(int64) to string" {
3536		t.Error("expect err:(0, 0): Can't convert 1(int64) to string but got ", err)
3537	}
3538}
3539
3540func TestUnmarshalSliceFail2(t *testing.T) {
3541	tree, _ := Load(`str_slice=[1,2]`)
3542
3543	var actual sliceStruct
3544	err := tree.Unmarshal(&actual)
3545	if err.Error() != "(1, 1): Can't convert 1(int64) to string" {
3546		t.Error("expect err:(1, 1): Can't convert 1(int64) to string but got ", err)
3547	}
3548
3549}
3550
3551func TestMarshalMixedTypeArray(t *testing.T) {
3552	type InnerStruct struct {
3553		IntField int
3554		StrField string
3555	}
3556
3557	type TestStruct struct {
3558		ArrayField []interface{}
3559	}
3560
3561	expected := []byte(`ArrayField = [3.14, 100, true, "hello world", { IntField = 100, StrField = "inner1" }, [{ IntField = 200, StrField = "inner2" }, { IntField = 300, StrField = "inner3" }]]
3562`)
3563
3564	if result, err := Marshal(TestStruct{
3565		ArrayField: []interface{}{
3566			3.14,
3567			100,
3568			true,
3569			"hello world",
3570			InnerStruct{
3571				IntField: 100,
3572				StrField: "inner1",
3573			},
3574			[]InnerStruct{
3575				{IntField: 200, StrField: "inner2"},
3576				{IntField: 300, StrField: "inner3"},
3577			},
3578		},
3579	}); err == nil {
3580		if !bytes.Equal(result, expected) {
3581			t.Errorf("Bad marshal: expected\n----\n%s\n----\ngot\n----\n%s\n----\n", expected, result)
3582		}
3583	} else {
3584		t.Fatal(err)
3585	}
3586}
3587
3588func TestUnmarshalMixedTypeArray(t *testing.T) {
3589	type TestStruct struct {
3590		ArrayField []interface{}
3591	}
3592
3593	toml := []byte(`ArrayField = [3.14,100,true,"hello world",{Field = "inner1"},[{Field = "inner2"},{Field = "inner3"}]]
3594`)
3595
3596	actual := TestStruct{}
3597	expected := TestStruct{
3598		ArrayField: []interface{}{
3599			3.14,
3600			int64(100),
3601			true,
3602			"hello world",
3603			map[string]interface{}{
3604				"Field": "inner1",
3605			},
3606			[]map[string]interface{}{
3607				{"Field": "inner2"},
3608				{"Field": "inner3"},
3609			},
3610		},
3611	}
3612
3613	if err := Unmarshal(toml, &actual); err == nil {
3614		if !reflect.DeepEqual(actual, expected) {
3615			t.Errorf("Bad unmarshal: expected %#v, got %#v", expected, actual)
3616		}
3617	} else {
3618		t.Fatal(err)
3619	}
3620}
3621
3622func TestUnmarshalArray(t *testing.T) {
3623	var tree *Tree
3624	var err error
3625
3626	tree, _ = LoadBytes(sliceTomlDemo)
3627	var actual1 arrayStruct
3628	err = tree.Unmarshal(&actual1)
3629	if err != nil {
3630		t.Error("shound not err", err)
3631	}
3632
3633	tree, _ = TreeFromMap(tree.ToMap())
3634	var actual2 arrayStruct
3635	err = tree.Unmarshal(&actual2)
3636	if err != nil {
3637		t.Error("shound not err", err)
3638	}
3639
3640	expected := arrayStruct{
3641		Slice:          [4]string{"Howdy", "Hey There"},
3642		SlicePtr:       &[4]string{"Howdy", "Hey There"},
3643		IntSlice:       [4]int{1, 2},
3644		IntSlicePtr:    &[4]int{1, 2},
3645		StructSlice:    [4]basicMarshalTestSubStruct{{"1"}, {"2"}},
3646		StructSlicePtr: &[4]basicMarshalTestSubStruct{{"1"}, {"2"}},
3647	}
3648	if !reflect.DeepEqual(actual1, expected) {
3649		t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual1)
3650	}
3651	if !reflect.DeepEqual(actual2, expected) {
3652		t.Errorf("Bad unmarshal: expected %v, got %v", expected, actual2)
3653	}
3654}
3655
3656func TestUnmarshalArrayFail(t *testing.T) {
3657	tree, _ := TreeFromMap(map[string]interface{}{
3658		"str_slice": []string{"Howdy", "Hey There"},
3659	})
3660
3661	var actual arrayTooSmallStruct
3662	err := tree.Unmarshal(&actual)
3663	if err.Error() != "(0, 0): unmarshal: TOML array length (2) exceeds destination array length (1)" {
3664		t.Error("expect err:(0, 0): unmarshal: TOML array length (2) exceeds destination array length (1) but got ", err)
3665	}
3666}
3667
3668func TestUnmarshalArrayFail2(t *testing.T) {
3669	tree, _ := Load(`str_slice=["Howdy","Hey There"]`)
3670
3671	var actual arrayTooSmallStruct
3672	err := tree.Unmarshal(&actual)
3673	if err.Error() != "(1, 1): unmarshal: TOML array length (2) exceeds destination array length (1)" {
3674		t.Error("expect err:(1, 1): unmarshal: TOML array length (2) exceeds destination array length (1) but got ", err)
3675	}
3676}
3677
3678func TestUnmarshalArrayFail3(t *testing.T) {
3679	tree, _ := Load(`[[struct_slice]]
3680String2="1"
3681[[struct_slice]]
3682String2="2"`)
3683
3684	var actual arrayTooSmallStruct
3685	err := tree.Unmarshal(&actual)
3686	if err.Error() != "(3, 1): unmarshal: TOML array length (2) exceeds destination array length (1)" {
3687		t.Error("expect err:(3, 1): unmarshal: TOML array length (2) exceeds destination array length (1) but got ", err)
3688	}
3689}
3690
3691func TestDecoderStrict(t *testing.T) {
3692	input := `
3693[decoded]
3694  key = ""
3695
3696[undecoded]
3697  key = ""
3698
3699  [undecoded.inner]
3700	key = ""
3701
3702  [[undecoded.array]]
3703	key = ""
3704
3705  [[undecoded.array]]
3706	key = ""
3707
3708`
3709	var doc struct {
3710		Decoded struct {
3711			Key string
3712		}
3713	}
3714
3715	expected := `undecoded keys: ["undecoded.array.0.key" "undecoded.array.1.key" "undecoded.inner.key" "undecoded.key"]`
3716
3717	err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
3718	if err == nil {
3719		t.Error("expected error, got none")
3720	} else if err.Error() != expected {
3721		t.Errorf("expect err: %s, got: %s", expected, err.Error())
3722	}
3723
3724	if err := NewDecoder(bytes.NewReader([]byte(input))).Decode(&doc); err != nil {
3725		t.Errorf("unexpected err: %s", err)
3726	}
3727
3728	var m map[string]interface{}
3729	if err := NewDecoder(bytes.NewReader([]byte(input))).Decode(&m); err != nil {
3730		t.Errorf("unexpected err: %s", err)
3731	}
3732}
3733
3734func TestDecoderStrictValid(t *testing.T) {
3735	input := `
3736[decoded]
3737  key = ""
3738`
3739	var doc struct {
3740		Decoded struct {
3741			Key string
3742		}
3743	}
3744
3745	err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
3746	if err != nil {
3747		t.Fatal("unexpected error:", err)
3748	}
3749}
3750
3751type docUnmarshalTOML struct {
3752	Decoded struct {
3753		Key string
3754	}
3755}
3756
3757func (d *docUnmarshalTOML) UnmarshalTOML(i interface{}) error {
3758	if iMap, ok := i.(map[string]interface{}); !ok {
3759		return fmt.Errorf("type assertion error: wants %T, have %T", map[string]interface{}{}, i)
3760	} else if key, ok := iMap["key"]; !ok {
3761		return fmt.Errorf("key '%s' not in map", "key")
3762	} else if keyString, ok := key.(string); !ok {
3763		return fmt.Errorf("type assertion error: wants %T, have %T", "", key)
3764	} else {
3765		d.Decoded.Key = keyString
3766	}
3767	return nil
3768}
3769
3770func TestDecoderStrictCustomUnmarshal(t *testing.T) {
3771	input := `key = "ok"`
3772	var doc docUnmarshalTOML
3773	err := NewDecoder(bytes.NewReader([]byte(input))).Strict(true).Decode(&doc)
3774	if err != nil {
3775		t.Fatal("unexpected error:", err)
3776	}
3777	if doc.Decoded.Key != "ok" {
3778		t.Errorf("Bad unmarshal: expected ok, got %v", doc.Decoded.Key)
3779	}
3780}
3781
3782type parent struct {
3783	Doc        docUnmarshalTOML
3784	DocPointer *docUnmarshalTOML
3785}
3786
3787func TestCustomUnmarshal(t *testing.T) {
3788	input := `
3789[Doc]
3790    key = "ok1"
3791[DocPointer]
3792    key = "ok2"
3793`
3794
3795	var d parent
3796	if err := Unmarshal([]byte(input), &d); err != nil {
3797		t.Fatalf("unexpected err: %s", err.Error())
3798	}
3799	if d.Doc.Decoded.Key != "ok1" {
3800		t.Errorf("Bad unmarshal: expected ok, got %v", d.Doc.Decoded.Key)
3801	}
3802	if d.DocPointer.Decoded.Key != "ok2" {
3803		t.Errorf("Bad unmarshal: expected ok, got %v", d.DocPointer.Decoded.Key)
3804	}
3805}
3806
3807func TestCustomUnmarshalError(t *testing.T) {
3808	input := `
3809[Doc]
3810    key = 1
3811[DocPointer]
3812    key = "ok2"
3813`
3814
3815	expected := "(2, 1): unmarshal toml: type assertion error: wants string, have int64"
3816
3817	var d parent
3818	err := Unmarshal([]byte(input), &d)
3819	if err == nil {
3820		t.Error("expected error, got none")
3821	} else if err.Error() != expected {
3822		t.Errorf("expect err: %s, got: %s", expected, err.Error())
3823	}
3824}
3825
3826type intWrapper struct {
3827	Value int
3828}
3829
3830func (w *intWrapper) UnmarshalText(text []byte) error {
3831	var err error
3832	if w.Value, err = strconv.Atoi(string(text)); err == nil {
3833		return nil
3834	}
3835	if b, err := strconv.ParseBool(string(text)); err == nil {
3836		if b {
3837			w.Value = 1
3838		}
3839		return nil
3840	}
3841	if f, err := strconv.ParseFloat(string(text), 32); err == nil {
3842		w.Value = int(f)
3843		return nil
3844	}
3845	return fmt.Errorf("unsupported: %s", text)
3846}
3847
3848func TestTextUnmarshal(t *testing.T) {
3849	var doc struct {
3850		UnixTime intWrapper
3851		Version  *intWrapper
3852
3853		Bool  intWrapper
3854		Int   intWrapper
3855		Float intWrapper
3856	}
3857
3858	input := `
3859UnixTime = "12"
3860Version = "42"
3861Bool = true
3862Int = 21
3863Float = 2.0
3864`
3865
3866	if err := Unmarshal([]byte(input), &doc); err != nil {
3867		t.Fatalf("unexpected err: %s", err.Error())
3868	}
3869	if doc.UnixTime.Value != 12 {
3870		t.Fatalf("expected UnixTime: 12 got: %d", doc.UnixTime.Value)
3871	}
3872	if doc.Version.Value != 42 {
3873		t.Fatalf("expected Version: 42 got: %d", doc.Version.Value)
3874	}
3875	if doc.Bool.Value != 1 {
3876		t.Fatalf("expected Bool: 1 got: %d", doc.Bool.Value)
3877	}
3878	if doc.Int.Value != 21 {
3879		t.Fatalf("expected Int: 21 got: %d", doc.Int.Value)
3880	}
3881	if doc.Float.Value != 2 {
3882		t.Fatalf("expected Float: 2 got: %d", doc.Float.Value)
3883	}
3884}
3885
3886func TestTextUnmarshalError(t *testing.T) {
3887	var doc struct {
3888		Failer intWrapper
3889	}
3890
3891	input := `Failer = "hello"`
3892	if err := Unmarshal([]byte(input), &doc); err == nil {
3893		t.Fatalf("expected err, got none")
3894	}
3895}
3896
3897// issue406
3898func TestPreserveNotEmptyField(t *testing.T) {
3899	toml := []byte(`Field1 = "ccc"`)
3900	type Inner struct {
3901		InnerField1 string
3902		InnerField2 int
3903	}
3904	type TestStruct struct {
3905		Field1 string
3906		Field2 int
3907		Field3 Inner
3908	}
3909
3910	actual := TestStruct{
3911		"aaa",
3912		100,
3913		Inner{
3914			"bbb",
3915			200,
3916		},
3917	}
3918
3919	expected := TestStruct{
3920		"ccc",
3921		100,
3922		Inner{
3923			"bbb",
3924			200,
3925		},
3926	}
3927
3928	err := Unmarshal(toml, &actual)
3929	if err != nil {
3930		t.Fatal(err)
3931	}
3932
3933	if !reflect.DeepEqual(actual, expected) {
3934		t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
3935	}
3936}
3937
3938// github issue 432
3939func TestUnmarshalEmptyInterface(t *testing.T) {
3940	doc := []byte(`User = "pelletier"`)
3941
3942	var v interface{}
3943
3944	err := Unmarshal(doc, &v)
3945	if err != nil {
3946		t.Fatal(err)
3947	}
3948
3949	x, ok := v.(map[string]interface{})
3950	if !ok {
3951		t.Fatal(err)
3952	}
3953
3954	if x["User"] != "pelletier" {
3955		t.Fatalf("expected User=pelletier, but got %v", x)
3956	}
3957}
3958
3959func TestUnmarshalEmptyInterfaceDeep(t *testing.T) {
3960	doc := []byte(`
3961User = "pelletier"
3962Age = 99
3963
3964[foo]
3965bar = 42
3966`)
3967
3968	var v interface{}
3969
3970	err := Unmarshal(doc, &v)
3971	if err != nil {
3972		t.Fatal(err)
3973	}
3974
3975	x, ok := v.(map[string]interface{})
3976	if !ok {
3977		t.Fatal(err)
3978	}
3979
3980	expected := map[string]interface{}{
3981		"User": "pelletier",
3982		"Age":  99,
3983		"foo": map[string]interface{}{
3984			"bar": 42,
3985		},
3986	}
3987
3988	reflect.DeepEqual(x, expected)
3989}
3990
3991type Config struct {
3992	Key string `toml:"key"`
3993	Obj Custom `toml:"obj"`
3994}
3995
3996type Custom struct {
3997	v string
3998}
3999
4000func (c *Custom) UnmarshalTOML(v interface{}) error {
4001	c.v = "called"
4002	return nil
4003}
4004
4005func TestGithubIssue431(t *testing.T) {
4006	doc := `key = "value"`
4007	tree, err := LoadBytes([]byte(doc))
4008	if err != nil {
4009		t.Fatalf("unexpected error: %s", err)
4010	}
4011
4012	var c Config
4013	if err := tree.Unmarshal(&c); err != nil {
4014		t.Fatalf("unexpected error: %s", err)
4015	}
4016
4017	if c.Key != "value" {
4018		t.Errorf("expected c.Key='value', not '%s'", c.Key)
4019	}
4020
4021	if c.Obj.v == "called" {
4022		t.Errorf("UnmarshalTOML should not have been called")
4023	}
4024}
4025
4026type durationString struct {
4027	time.Duration
4028}
4029
4030func (d *durationString) UnmarshalTOML(v interface{}) error {
4031	d.Duration = 10 * time.Second
4032	return nil
4033}
4034
4035type config437Error struct {
4036}
4037
4038func (e *config437Error) UnmarshalTOML(v interface{}) error {
4039	return errors.New("expected")
4040}
4041
4042type config437 struct {
4043	HTTP struct {
4044		PingTimeout durationString `toml:"PingTimeout"`
4045		ErrorField  config437Error
4046	} `toml:"HTTP"`
4047}
4048
4049func TestGithubIssue437(t *testing.T) {
4050	src := `
4051[HTTP]
4052PingTimeout = "32m"
4053`
4054	cfg := &config437{}
4055	cfg.HTTP.PingTimeout = durationString{time.Second}
4056
4057	r := strings.NewReader(src)
4058	err := NewDecoder(r).Decode(cfg)
4059	if err != nil {
4060		t.Fatalf("unexpected errors %s", err)
4061	}
4062	expected := durationString{10 * time.Second}
4063	if cfg.HTTP.PingTimeout != expected {
4064		t.Fatalf("expected '%s', got '%s'", expected, cfg.HTTP.PingTimeout)
4065	}
4066}
4067
4068func TestLeafUnmarshalerError(t *testing.T) {
4069	src := `
4070[HTTP]
4071ErrorField = "foo"
4072`
4073	cfg := &config437{}
4074
4075	r := strings.NewReader(src)
4076	err := NewDecoder(r).Decode(cfg)
4077	if err == nil {
4078		t.Fatalf("error was expected")
4079	}
4080}
4081