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