1package toml
2
3import (
4	"bytes"
5	"encoding/json"
6	"fmt"
7	"io/ioutil"
8	"reflect"
9	"strings"
10	"testing"
11	"time"
12)
13
14type basicMarshalTestStruct struct {
15	String     string                      `toml:"Zstring"`
16	StringList []string                    `toml:"Ystrlist"`
17	Sub        basicMarshalTestSubStruct   `toml:"Xsubdoc"`
18	SubList    []basicMarshalTestSubStruct `toml:"Wsublist"`
19}
20
21type basicMarshalTestSubStruct struct {
22	String2 string
23}
24
25var basicTestData = basicMarshalTestStruct{
26	String:     "Hello",
27	StringList: []string{"Howdy", "Hey There"},
28	Sub:        basicMarshalTestSubStruct{"One"},
29	SubList:    []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
30}
31
32var basicTestToml = []byte(`Ystrlist = ["Howdy","Hey There"]
33Zstring = "Hello"
34
35[[Wsublist]]
36  String2 = "Two"
37
38[[Wsublist]]
39  String2 = "Three"
40
41[Xsubdoc]
42  String2 = "One"
43`)
44
45var basicTestTomlOrdered = []byte(`Zstring = "Hello"
46Ystrlist = ["Howdy","Hey There"]
47
48[Xsubdoc]
49  String2 = "One"
50
51[[Wsublist]]
52  String2 = "Two"
53
54[[Wsublist]]
55  String2 = "Three"
56`)
57
58func TestBasicMarshal(t *testing.T) {
59	result, err := Marshal(basicTestData)
60	if err != nil {
61		t.Fatal(err)
62	}
63	expected := basicTestToml
64	if !bytes.Equal(result, expected) {
65		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
66	}
67}
68
69func TestBasicMarshalOrdered(t *testing.T) {
70	var result bytes.Buffer
71	err := NewEncoder(&result).Order(OrderPreserve).Encode(basicTestData)
72	if err != nil {
73		t.Fatal(err)
74	}
75	expected := basicTestTomlOrdered
76	if !bytes.Equal(result.Bytes(), expected) {
77		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
78	}
79}
80
81func TestBasicMarshalWithPointer(t *testing.T) {
82	result, err := Marshal(&basicTestData)
83	if err != nil {
84		t.Fatal(err)
85	}
86	expected := basicTestToml
87	if !bytes.Equal(result, expected) {
88		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
89	}
90}
91
92func TestBasicMarshalOrderedWithPointer(t *testing.T) {
93	var result bytes.Buffer
94	err := NewEncoder(&result).Order(OrderPreserve).Encode(&basicTestData)
95	if err != nil {
96		t.Fatal(err)
97	}
98	expected := basicTestTomlOrdered
99	if !bytes.Equal(result.Bytes(), expected) {
100		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
101	}
102}
103
104func TestBasicUnmarshal(t *testing.T) {
105	result := basicMarshalTestStruct{}
106	err := Unmarshal(basicTestToml, &result)
107	expected := basicTestData
108	if err != nil {
109		t.Fatal(err)
110	}
111	if !reflect.DeepEqual(result, expected) {
112		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
113	}
114}
115
116type testDoc struct {
117	Title       string            `toml:"title"`
118	BasicLists  testDocBasicLists `toml:"basic_lists"`
119	SubDocPtrs  []*testSubDoc     `toml:"subdocptrs"`
120	BasicMap    map[string]string `toml:"basic_map"`
121	Subdocs     testDocSubs       `toml:"subdoc"`
122	Basics      testDocBasics     `toml:"basic"`
123	SubDocList  []testSubDoc      `toml:"subdoclist"`
124	err         int               `toml:"shouldntBeHere"`
125	unexported  int               `toml:"shouldntBeHere"`
126	Unexported2 int               `toml:"-"`
127}
128
129type testMapDoc struct {
130	Title    string            `toml:"title"`
131	BasicMap map[string]string `toml:"basic_map"`
132	LongMap  map[string]string `toml:"long_map"`
133}
134
135type testDocBasics struct {
136	Uint       uint      `toml:"uint"`
137	Bool       bool      `toml:"bool"`
138	Float      float32   `toml:"float"`
139	Int        int       `toml:"int"`
140	String     *string   `toml:"string"`
141	Date       time.Time `toml:"date"`
142	unexported int       `toml:"shouldntBeHere"`
143}
144
145type testDocBasicLists struct {
146	Floats  []*float32  `toml:"floats"`
147	Bools   []bool      `toml:"bools"`
148	Dates   []time.Time `toml:"dates"`
149	Ints    []int       `toml:"ints"`
150	UInts   []uint      `toml:"uints"`
151	Strings []string    `toml:"strings"`
152}
153
154type testDocSubs struct {
155	Second *testSubDoc `toml:"second"`
156	First  testSubDoc  `toml:"first"`
157}
158
159type testSubDoc struct {
160	Name       string `toml:"name"`
161	unexported int    `toml:"shouldntBeHere"`
162}
163
164var biteMe = "Bite me"
165var float1 float32 = 12.3
166var float2 float32 = 45.6
167var float3 float32 = 78.9
168var subdoc = testSubDoc{"Second", 0}
169
170var docData = testDoc{
171	Title:       "TOML Marshal Testing",
172	unexported:  0,
173	Unexported2: 0,
174	Basics: testDocBasics{
175		Bool:       true,
176		Date:       time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
177		Float:      123.4,
178		Int:        5000,
179		Uint:       5001,
180		String:     &biteMe,
181		unexported: 0,
182	},
183	BasicLists: testDocBasicLists{
184		Bools: []bool{true, false, true},
185		Dates: []time.Time{
186			time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
187			time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC),
188		},
189		Floats:  []*float32{&float1, &float2, &float3},
190		Ints:    []int{8001, 8001, 8002},
191		Strings: []string{"One", "Two", "Three"},
192		UInts:   []uint{5002, 5003},
193	},
194	BasicMap: map[string]string{
195		"one": "one",
196		"two": "two",
197	},
198	Subdocs: testDocSubs{
199		First:  testSubDoc{"First", 0},
200		Second: &subdoc,
201	},
202	SubDocList: []testSubDoc{
203		{"List.First", 0},
204		{"List.Second", 0},
205	},
206	SubDocPtrs: []*testSubDoc{&subdoc},
207}
208
209var mapTestDoc = testMapDoc{
210	Title: "TOML Marshal Testing",
211	BasicMap: map[string]string{
212		"one": "one",
213		"two": "two",
214	},
215	LongMap: map[string]string{
216		"h1":  "8",
217		"i2":  "9",
218		"b3":  "2",
219		"d4":  "4",
220		"f5":  "6",
221		"e6":  "5",
222		"a7":  "1",
223		"c8":  "3",
224		"j9":  "10",
225		"g10": "7",
226	},
227}
228
229func TestDocMarshal(t *testing.T) {
230	result, err := Marshal(docData)
231	if err != nil {
232		t.Fatal(err)
233	}
234	expected, _ := ioutil.ReadFile("marshal_test.toml")
235	if !bytes.Equal(result, expected) {
236		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
237	}
238}
239
240func TestDocMarshalOrdered(t *testing.T) {
241	var result bytes.Buffer
242	err := NewEncoder(&result).Order(OrderPreserve).Encode(docData)
243	if err != nil {
244		t.Fatal(err)
245	}
246	expected, _ := ioutil.ReadFile("marshal_OrderPreserve_test.toml")
247	if !bytes.Equal(result.Bytes(), expected) {
248		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
249	}
250}
251
252func TestDocMarshalMaps(t *testing.T) {
253	result, err := Marshal(mapTestDoc)
254	if err != nil {
255		t.Fatal(err)
256	}
257	expected, _ := ioutil.ReadFile("marshal_OrderPreserve_Map_test.toml")
258	if !bytes.Equal(result, expected) {
259		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
260	}
261}
262
263func TestDocMarshalOrderedMaps(t *testing.T) {
264	var result bytes.Buffer
265	err := NewEncoder(&result).Order(OrderPreserve).Encode(mapTestDoc)
266	if err != nil {
267		t.Fatal(err)
268	}
269	expected, _ := ioutil.ReadFile("marshal_OrderPreserve_Map_test.toml")
270	if !bytes.Equal(result.Bytes(), expected) {
271		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result.Bytes())
272	}
273}
274
275func TestDocMarshalPointer(t *testing.T) {
276	result, err := Marshal(&docData)
277	if err != nil {
278		t.Fatal(err)
279	}
280	expected, _ := ioutil.ReadFile("marshal_test.toml")
281	if !bytes.Equal(result, expected) {
282		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
283	}
284}
285
286func TestDocUnmarshal(t *testing.T) {
287	result := testDoc{}
288	tomlData, _ := ioutil.ReadFile("marshal_test.toml")
289	err := Unmarshal(tomlData, &result)
290	expected := docData
291	if err != nil {
292		t.Fatal(err)
293	}
294	if !reflect.DeepEqual(result, expected) {
295		resStr, _ := json.MarshalIndent(result, "", "  ")
296		expStr, _ := json.MarshalIndent(expected, "", "  ")
297		t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
298	}
299}
300
301func TestDocPartialUnmarshal(t *testing.T) {
302	result := testDocSubs{}
303
304	tree, _ := LoadFile("marshal_test.toml")
305	subTree := tree.Get("subdoc").(*Tree)
306	err := subTree.Unmarshal(&result)
307	expected := docData.Subdocs
308	if err != nil {
309		t.Fatal(err)
310	}
311	if !reflect.DeepEqual(result, expected) {
312		resStr, _ := json.MarshalIndent(result, "", "  ")
313		expStr, _ := json.MarshalIndent(expected, "", "  ")
314		t.Errorf("Bad partial unmartial: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
315	}
316}
317
318type tomlTypeCheckTest struct {
319	name string
320	item interface{}
321	typ  int //0=primitive, 1=otherslice, 2=treeslice, 3=tree
322}
323
324func TestTypeChecks(t *testing.T) {
325	tests := []tomlTypeCheckTest{
326		{"integer", 2, 0},
327		{"time", time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC), 0},
328		{"stringlist", []string{"hello", "hi"}, 1},
329		{"timelist", []time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
330		{"objectlist", []tomlTypeCheckTest{}, 2},
331		{"object", tomlTypeCheckTest{}, 3},
332	}
333
334	for _, test := range tests {
335		expected := []bool{false, false, false, false}
336		expected[test.typ] = true
337		result := []bool{
338			isPrimitive(reflect.TypeOf(test.item)),
339			isOtherSlice(reflect.TypeOf(test.item)),
340			isTreeSlice(reflect.TypeOf(test.item)),
341			isTree(reflect.TypeOf(test.item)),
342		}
343		if !reflect.DeepEqual(expected, result) {
344			t.Errorf("Bad type check on %q: expected %v, got %v", test.name, expected, result)
345		}
346	}
347}
348
349type unexportedMarshalTestStruct struct {
350	String      string                      `toml:"string"`
351	StringList  []string                    `toml:"strlist"`
352	Sub         basicMarshalTestSubStruct   `toml:"subdoc"`
353	SubList     []basicMarshalTestSubStruct `toml:"sublist"`
354	unexported  int                         `toml:"shouldntBeHere"`
355	Unexported2 int                         `toml:"-"`
356}
357
358var unexportedTestData = unexportedMarshalTestStruct{
359	String:      "Hello",
360	StringList:  []string{"Howdy", "Hey There"},
361	Sub:         basicMarshalTestSubStruct{"One"},
362	SubList:     []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
363	unexported:  0,
364	Unexported2: 0,
365}
366
367var unexportedTestToml = []byte(`string = "Hello"
368strlist = ["Howdy","Hey There"]
369unexported = 1
370shouldntBeHere = 2
371
372[subdoc]
373  String2 = "One"
374
375[[sublist]]
376  String2 = "Two"
377
378[[sublist]]
379  String2 = "Three"
380`)
381
382func TestUnexportedUnmarshal(t *testing.T) {
383	result := unexportedMarshalTestStruct{}
384	err := Unmarshal(unexportedTestToml, &result)
385	expected := unexportedTestData
386	if err != nil {
387		t.Fatal(err)
388	}
389	if !reflect.DeepEqual(result, expected) {
390		t.Errorf("Bad unexported unmarshal: expected %v, got %v", expected, result)
391	}
392}
393
394type errStruct struct {
395	Bool   bool      `toml:"bool"`
396	Date   time.Time `toml:"date"`
397	Float  float64   `toml:"float"`
398	Int    int16     `toml:"int"`
399	String *string   `toml:"string"`
400}
401
402var errTomls = []string{
403	"bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
404	"bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
405	"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"",
406	"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"",
407	"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
408	"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
409	"bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
410	"bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
411	"bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"",
412	"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"",
413	"bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1",
414}
415
416type mapErr struct {
417	Vals map[string]float64
418}
419
420type intErr struct {
421	Int1  int
422	Int2  int8
423	Int3  int16
424	Int4  int32
425	Int5  int64
426	UInt1 uint
427	UInt2 uint8
428	UInt3 uint16
429	UInt4 uint32
430	UInt5 uint64
431	Flt1  float32
432	Flt2  float64
433}
434
435var intErrTomls = []string{
436	"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",
437	"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",
438	"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",
439	"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",
440	"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",
441	"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",
442	"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",
443	"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",
444	"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",
445	"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",
446	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0",
447	"Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []",
448}
449
450func TestErrUnmarshal(t *testing.T) {
451	for ind, toml := range errTomls {
452		result := errStruct{}
453		err := Unmarshal([]byte(toml), &result)
454		if err == nil {
455			t.Errorf("Expected err from case %d\n", ind)
456		}
457	}
458	result2 := mapErr{}
459	err := Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2)
460	if err == nil {
461		t.Errorf("Expected err from map")
462	}
463	for ind, toml := range intErrTomls {
464		result3 := intErr{}
465		err := Unmarshal([]byte(toml), &result3)
466		if err == nil {
467			t.Errorf("Expected int err from case %d\n", ind)
468		}
469	}
470}
471
472type emptyMarshalTestStruct struct {
473	Title      string                  `toml:"title"`
474	Bool       bool                    `toml:"bool"`
475	Int        int                     `toml:"int"`
476	String     string                  `toml:"string"`
477	StringList []string                `toml:"stringlist"`
478	Ptr        *basicMarshalTestStruct `toml:"ptr"`
479	Map        map[string]string       `toml:"map"`
480}
481
482var emptyTestData = emptyMarshalTestStruct{
483	Title:      "Placeholder",
484	Bool:       false,
485	Int:        0,
486	String:     "",
487	StringList: []string{},
488	Ptr:        nil,
489	Map:        map[string]string{},
490}
491
492var emptyTestToml = []byte(`bool = false
493int = 0
494string = ""
495stringlist = []
496title = "Placeholder"
497
498[map]
499`)
500
501type emptyMarshalTestStruct2 struct {
502	Title      string                  `toml:"title"`
503	Bool       bool                    `toml:"bool,omitempty"`
504	Int        int                     `toml:"int, omitempty"`
505	String     string                  `toml:"string,omitempty "`
506	StringList []string                `toml:"stringlist,omitempty"`
507	Ptr        *basicMarshalTestStruct `toml:"ptr,omitempty"`
508	Map        map[string]string       `toml:"map,omitempty"`
509}
510
511var emptyTestData2 = emptyMarshalTestStruct2{
512	Title:      "Placeholder",
513	Bool:       false,
514	Int:        0,
515	String:     "",
516	StringList: []string{},
517	Ptr:        nil,
518	Map:        map[string]string{},
519}
520
521var emptyTestToml2 = []byte(`title = "Placeholder"
522`)
523
524func TestEmptyMarshal(t *testing.T) {
525	result, err := Marshal(emptyTestData)
526	if err != nil {
527		t.Fatal(err)
528	}
529	expected := emptyTestToml
530	if !bytes.Equal(result, expected) {
531		t.Errorf("Bad empty marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
532	}
533}
534
535func TestEmptyMarshalOmit(t *testing.T) {
536	result, err := Marshal(emptyTestData2)
537	if err != nil {
538		t.Fatal(err)
539	}
540	expected := emptyTestToml2
541	if !bytes.Equal(result, expected) {
542		t.Errorf("Bad empty omit marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
543	}
544}
545
546func TestEmptyUnmarshal(t *testing.T) {
547	result := emptyMarshalTestStruct{}
548	err := Unmarshal(emptyTestToml, &result)
549	expected := emptyTestData
550	if err != nil {
551		t.Fatal(err)
552	}
553	if !reflect.DeepEqual(result, expected) {
554		t.Errorf("Bad empty unmarshal: expected %v, got %v", expected, result)
555	}
556}
557
558func TestEmptyUnmarshalOmit(t *testing.T) {
559	result := emptyMarshalTestStruct2{}
560	err := Unmarshal(emptyTestToml, &result)
561	expected := emptyTestData2
562	if err != nil {
563		t.Fatal(err)
564	}
565	if !reflect.DeepEqual(result, expected) {
566		t.Errorf("Bad empty omit unmarshal: expected %v, got %v", expected, result)
567	}
568}
569
570type pointerMarshalTestStruct struct {
571	Str       *string
572	List      *[]string
573	ListPtr   *[]*string
574	Map       *map[string]string
575	MapPtr    *map[string]*string
576	EmptyStr  *string
577	EmptyList *[]string
578	EmptyMap  *map[string]string
579	DblPtr    *[]*[]*string
580}
581
582var pointerStr = "Hello"
583var pointerList = []string{"Hello back"}
584var pointerListPtr = []*string{&pointerStr}
585var pointerMap = map[string]string{"response": "Goodbye"}
586var pointerMapPtr = map[string]*string{"alternate": &pointerStr}
587var pointerTestData = pointerMarshalTestStruct{
588	Str:       &pointerStr,
589	List:      &pointerList,
590	ListPtr:   &pointerListPtr,
591	Map:       &pointerMap,
592	MapPtr:    &pointerMapPtr,
593	EmptyStr:  nil,
594	EmptyList: nil,
595	EmptyMap:  nil,
596}
597
598var pointerTestToml = []byte(`List = ["Hello back"]
599ListPtr = ["Hello"]
600Str = "Hello"
601
602[Map]
603  response = "Goodbye"
604
605[MapPtr]
606  alternate = "Hello"
607`)
608
609func TestPointerMarshal(t *testing.T) {
610	result, err := Marshal(pointerTestData)
611	if err != nil {
612		t.Fatal(err)
613	}
614	expected := pointerTestToml
615	if !bytes.Equal(result, expected) {
616		t.Errorf("Bad pointer marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
617	}
618}
619
620func TestPointerUnmarshal(t *testing.T) {
621	result := pointerMarshalTestStruct{}
622	err := Unmarshal(pointerTestToml, &result)
623	expected := pointerTestData
624	if err != nil {
625		t.Fatal(err)
626	}
627	if !reflect.DeepEqual(result, expected) {
628		t.Errorf("Bad pointer unmarshal: expected %v, got %v", expected, result)
629	}
630}
631
632func TestUnmarshalTypeMismatch(t *testing.T) {
633	result := pointerMarshalTestStruct{}
634	err := Unmarshal([]byte("List = 123"), &result)
635	if !strings.HasPrefix(err.Error(), "(1, 1): Can't convert 123(int64) to []string(slice)") {
636		t.Errorf("Type mismatch must be reported: got %v", err.Error())
637	}
638}
639
640type nestedMarshalTestStruct struct {
641	String [][]string
642	//Struct [][]basicMarshalTestSubStruct
643	StringPtr *[]*[]*string
644	// StructPtr *[]*[]*basicMarshalTestSubStruct
645}
646
647var str1 = "Three"
648var str2 = "Four"
649var strPtr = []*string{&str1, &str2}
650var strPtr2 = []*[]*string{&strPtr}
651
652var nestedTestData = nestedMarshalTestStruct{
653	String:    [][]string{{"Five", "Six"}, {"One", "Two"}},
654	StringPtr: &strPtr2,
655}
656
657var nestedTestToml = []byte(`String = [["Five","Six"],["One","Two"]]
658StringPtr = [["Three","Four"]]
659`)
660
661func TestNestedMarshal(t *testing.T) {
662	result, err := Marshal(nestedTestData)
663	if err != nil {
664		t.Fatal(err)
665	}
666	expected := nestedTestToml
667	if !bytes.Equal(result, expected) {
668		t.Errorf("Bad nested marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
669	}
670}
671
672func TestNestedUnmarshal(t *testing.T) {
673	result := nestedMarshalTestStruct{}
674	err := Unmarshal(nestedTestToml, &result)
675	expected := nestedTestData
676	if err != nil {
677		t.Fatal(err)
678	}
679	if !reflect.DeepEqual(result, expected) {
680		t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result)
681	}
682}
683
684type customMarshalerParent struct {
685	Self    customMarshaler   `toml:"me"`
686	Friends []customMarshaler `toml:"friends"`
687}
688
689type customMarshaler struct {
690	FirsName string
691	LastName string
692}
693
694func (c customMarshaler) MarshalTOML() ([]byte, error) {
695	fullName := fmt.Sprintf("%s %s", c.FirsName, c.LastName)
696	return []byte(fullName), nil
697}
698
699var customMarshalerData = customMarshaler{FirsName: "Sally", LastName: "Fields"}
700var customMarshalerToml = []byte(`Sally Fields`)
701var nestedCustomMarshalerData = customMarshalerParent{
702	Self:    customMarshaler{FirsName: "Maiku", LastName: "Suteda"},
703	Friends: []customMarshaler{customMarshalerData},
704}
705var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"]
706me = "Maiku Suteda"
707`)
708
709func TestCustomMarshaler(t *testing.T) {
710	result, err := Marshal(customMarshalerData)
711	if err != nil {
712		t.Fatal(err)
713	}
714	expected := customMarshalerToml
715	if !bytes.Equal(result, expected) {
716		t.Errorf("Bad custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
717	}
718}
719
720func TestNestedCustomMarshaler(t *testing.T) {
721	result, err := Marshal(nestedCustomMarshalerData)
722	if err != nil {
723		t.Fatal(err)
724	}
725	expected := nestedCustomMarshalerToml
726	if !bytes.Equal(result, expected) {
727		t.Errorf("Bad nested custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
728	}
729}
730
731var commentTestToml = []byte(`
732# it's a comment on type
733[postgres]
734  # isCommented = "dvalue"
735  noComment = "cvalue"
736
737  # A comment on AttrB with a
738  # break line
739  password = "bvalue"
740
741  # A comment on AttrA
742  user = "avalue"
743
744  [[postgres.My]]
745
746    # a comment on my on typeC
747    My = "Foo"
748
749  [[postgres.My]]
750
751    # a comment on my on typeC
752    My = "Baar"
753`)
754
755func TestMarshalComment(t *testing.T) {
756	type TypeC struct {
757		My string `comment:"a comment on my on typeC"`
758	}
759	type TypeB struct {
760		AttrA string `toml:"user" comment:"A comment on AttrA"`
761		AttrB string `toml:"password" comment:"A comment on AttrB with a\n break line"`
762		AttrC string `toml:"noComment"`
763		AttrD string `toml:"isCommented" commented:"true"`
764		My    []TypeC
765	}
766	type TypeA struct {
767		TypeB TypeB `toml:"postgres" comment:"it's a comment on type"`
768	}
769
770	ta := []TypeC{{My: "Foo"}, {My: "Baar"}}
771	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", AttrC: "cvalue", AttrD: "dvalue", My: ta}}
772	result, err := Marshal(config)
773	if err != nil {
774		t.Fatal(err)
775	}
776	expected := commentTestToml
777	if !bytes.Equal(result, expected) {
778		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
779	}
780}
781
782type mapsTestStruct struct {
783	Simple map[string]string
784	Paths  map[string]string
785	Other  map[string]float64
786	X      struct {
787		Y struct {
788			Z map[string]bool
789		}
790	}
791}
792
793var mapsTestData = mapsTestStruct{
794	Simple: map[string]string{
795		"one plus one": "two",
796		"next":         "three",
797	},
798	Paths: map[string]string{
799		"/this/is/a/path": "/this/is/also/a/path",
800		"/heloo.txt":      "/tmp/lololo.txt",
801	},
802	Other: map[string]float64{
803		"testing": 3.9999,
804	},
805	X: struct{ Y struct{ Z map[string]bool } }{
806		Y: struct{ Z map[string]bool }{
807			Z: map[string]bool{
808				"is.Nested": true,
809			},
810		},
811	},
812}
813var mapsTestToml = []byte(`
814[Other]
815  "testing" = 3.9999
816
817[Paths]
818  "/heloo.txt" = "/tmp/lololo.txt"
819  "/this/is/a/path" = "/this/is/also/a/path"
820
821[Simple]
822  "next" = "three"
823  "one plus one" = "two"
824
825[X]
826
827  [X.Y]
828
829    [X.Y.Z]
830      "is.Nested" = true
831`)
832
833func TestEncodeQuotedMapKeys(t *testing.T) {
834	var buf bytes.Buffer
835	if err := NewEncoder(&buf).QuoteMapKeys(true).Encode(mapsTestData); err != nil {
836		t.Fatal(err)
837	}
838	result := buf.Bytes()
839	expected := mapsTestToml
840	if !bytes.Equal(result, expected) {
841		t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
842	}
843}
844
845func TestDecodeQuotedMapKeys(t *testing.T) {
846	result := mapsTestStruct{}
847	err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result)
848	expected := mapsTestData
849	if err != nil {
850		t.Fatal(err)
851	}
852	if !reflect.DeepEqual(result, expected) {
853		t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result)
854	}
855}
856
857type structArrayNoTag struct {
858	A struct {
859		B []int64
860		C []int64
861	}
862}
863
864func TestMarshalArray(t *testing.T) {
865	expected := []byte(`
866[A]
867  B = [1,2,3]
868  C = [1]
869`)
870
871	m := structArrayNoTag{
872		A: struct {
873			B []int64
874			C []int64
875		}{
876			B: []int64{1, 2, 3},
877			C: []int64{1},
878		},
879	}
880
881	b, err := Marshal(m)
882
883	if err != nil {
884		t.Fatal(err)
885	}
886
887	if !bytes.Equal(b, expected) {
888		t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
889	}
890}
891
892func TestMarshalArrayOnePerLine(t *testing.T) {
893	expected := []byte(`
894[A]
895  B = [
896    1,
897    2,
898    3,
899  ]
900  C = [1]
901`)
902
903	m := structArrayNoTag{
904		A: struct {
905			B []int64
906			C []int64
907		}{
908			B: []int64{1, 2, 3},
909			C: []int64{1},
910		},
911	}
912
913	var buf bytes.Buffer
914	encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true)
915	err := encoder.Encode(m)
916
917	if err != nil {
918		t.Fatal(err)
919	}
920
921	b := buf.Bytes()
922
923	if !bytes.Equal(b, expected) {
924		t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
925	}
926}
927
928var customTagTestToml = []byte(`
929[postgres]
930  password = "bvalue"
931  user = "avalue"
932
933  [[postgres.My]]
934    My = "Foo"
935
936  [[postgres.My]]
937    My = "Baar"
938`)
939
940func TestMarshalCustomTag(t *testing.T) {
941	type TypeC struct {
942		My string
943	}
944	type TypeB struct {
945		AttrA string `file:"user"`
946		AttrB string `file:"password"`
947		My    []TypeC
948	}
949	type TypeA struct {
950		TypeB TypeB `file:"postgres"`
951	}
952
953	ta := []TypeC{{My: "Foo"}, {My: "Baar"}}
954	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", My: ta}}
955	var buf bytes.Buffer
956	err := NewEncoder(&buf).SetTagName("file").Encode(config)
957	if err != nil {
958		t.Fatal(err)
959	}
960	expected := customTagTestToml
961	result := buf.Bytes()
962	if !bytes.Equal(result, expected) {
963		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
964	}
965}
966
967var customCommentTagTestToml = []byte(`
968# db connection
969[postgres]
970
971  # db pass
972  password = "bvalue"
973
974  # db user
975  user = "avalue"
976`)
977
978func TestMarshalCustomComment(t *testing.T) {
979	type TypeB struct {
980		AttrA string `toml:"user" descr:"db user"`
981		AttrB string `toml:"password" descr:"db pass"`
982	}
983	type TypeA struct {
984		TypeB TypeB `toml:"postgres" descr:"db connection"`
985	}
986
987	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue"}}
988	var buf bytes.Buffer
989	err := NewEncoder(&buf).SetTagComment("descr").Encode(config)
990	if err != nil {
991		t.Fatal(err)
992	}
993	expected := customCommentTagTestToml
994	result := buf.Bytes()
995	if !bytes.Equal(result, expected) {
996		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
997	}
998}
999
1000var customCommentedTagTestToml = []byte(`
1001[postgres]
1002  # password = "bvalue"
1003  # user = "avalue"
1004`)
1005
1006func TestMarshalCustomCommented(t *testing.T) {
1007	type TypeB struct {
1008		AttrA string `toml:"user" disable:"true"`
1009		AttrB string `toml:"password" disable:"true"`
1010	}
1011	type TypeA struct {
1012		TypeB TypeB `toml:"postgres"`
1013	}
1014
1015	config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue"}}
1016	var buf bytes.Buffer
1017	err := NewEncoder(&buf).SetTagCommented("disable").Encode(config)
1018	if err != nil {
1019		t.Fatal(err)
1020	}
1021	expected := customCommentedTagTestToml
1022	result := buf.Bytes()
1023	if !bytes.Equal(result, expected) {
1024		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1025	}
1026}
1027
1028var customMultilineTagTestToml = []byte(`int_slice = [
1029  1,
1030  2,
1031  3,
1032]
1033`)
1034
1035func TestMarshalCustomMultiline(t *testing.T) {
1036	type TypeA struct {
1037		AttrA []int `toml:"int_slice" mltln:"true"`
1038	}
1039
1040	config := TypeA{AttrA: []int{1, 2, 3}}
1041	var buf bytes.Buffer
1042	err := NewEncoder(&buf).ArraysWithOneElementPerLine(true).SetTagMultiline("mltln").Encode(config)
1043	if err != nil {
1044		t.Fatal(err)
1045	}
1046	expected := customMultilineTagTestToml
1047	result := buf.Bytes()
1048	if !bytes.Equal(result, expected) {
1049		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1050	}
1051}
1052
1053var testDocBasicToml = []byte(`
1054[document]
1055  bool_val = true
1056  date_val = 1979-05-27T07:32:00Z
1057  float_val = 123.4
1058  int_val = 5000
1059  string_val = "Bite me"
1060  uint_val = 5001
1061`)
1062
1063type testDocCustomTag struct {
1064	Doc testDocBasicsCustomTag `file:"document"`
1065}
1066type testDocBasicsCustomTag struct {
1067	Bool       bool      `file:"bool_val"`
1068	Date       time.Time `file:"date_val"`
1069	Float      float32   `file:"float_val"`
1070	Int        int       `file:"int_val"`
1071	Uint       uint      `file:"uint_val"`
1072	String     *string   `file:"string_val"`
1073	unexported int       `file:"shouldntBeHere"`
1074}
1075
1076var testDocCustomTagData = testDocCustomTag{
1077	Doc: testDocBasicsCustomTag{
1078		Bool:       true,
1079		Date:       time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
1080		Float:      123.4,
1081		Int:        5000,
1082		Uint:       5001,
1083		String:     &biteMe,
1084		unexported: 0,
1085	},
1086}
1087
1088func TestUnmarshalCustomTag(t *testing.T) {
1089	buf := bytes.NewBuffer(testDocBasicToml)
1090
1091	result := testDocCustomTag{}
1092	err := NewDecoder(buf).SetTagName("file").Decode(&result)
1093	if err != nil {
1094		t.Fatal(err)
1095	}
1096	expected := testDocCustomTagData
1097	if !reflect.DeepEqual(result, expected) {
1098		resStr, _ := json.MarshalIndent(result, "", "  ")
1099		expStr, _ := json.MarshalIndent(expected, "", "  ")
1100		t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
1101
1102	}
1103}
1104
1105func TestUnmarshalMap(t *testing.T) {
1106	testToml := []byte(`
1107		a = 1
1108		b = 2
1109		c = 3
1110		`)
1111	var result map[string]int
1112	err := Unmarshal(testToml, &result)
1113	if err != nil {
1114		t.Errorf("Received unexpected error: %s", err)
1115		return
1116	}
1117
1118	expected := map[string]int{
1119		"a": 1,
1120		"b": 2,
1121		"c": 3,
1122	}
1123
1124	if !reflect.DeepEqual(result, expected) {
1125		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
1126	}
1127}
1128
1129func TestUnmarshalMapWithTypedKey(t *testing.T) {
1130	testToml := []byte(`
1131		a = 1
1132		b = 2
1133		c = 3
1134		`)
1135
1136	type letter string
1137	var result map[letter]int
1138	err := Unmarshal(testToml, &result)
1139	if err != nil {
1140		t.Errorf("Received unexpected error: %s", err)
1141		return
1142	}
1143
1144	expected := map[letter]int{
1145		"a": 1,
1146		"b": 2,
1147		"c": 3,
1148	}
1149
1150	if !reflect.DeepEqual(result, expected) {
1151		t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
1152	}
1153}
1154
1155func TestUnmarshalNonPointer(t *testing.T) {
1156	a := 1
1157	err := Unmarshal([]byte{}, a)
1158	if err == nil {
1159		t.Fatal("unmarshal should err when given a non pointer")
1160	}
1161}
1162
1163func TestUnmarshalInvalidPointerKind(t *testing.T) {
1164	a := 1
1165	err := Unmarshal([]byte{}, &a)
1166	if err == nil {
1167		t.Fatal("unmarshal should err when given an invalid pointer type")
1168	}
1169}
1170
1171func TestMarshalSlice(t *testing.T) {
1172	m := make([]int, 1)
1173	m[0] = 1
1174
1175	var buf bytes.Buffer
1176	err := NewEncoder(&buf).Encode(&m)
1177	if err == nil {
1178		t.Error("expected error, got nil")
1179		return
1180	}
1181	if err.Error() != "Only pointer to struct can be marshaled to TOML" {
1182		t.Fail()
1183	}
1184}
1185
1186func TestMarshalSlicePointer(t *testing.T) {
1187	m := make([]int, 1)
1188	m[0] = 1
1189
1190	var buf bytes.Buffer
1191	err := NewEncoder(&buf).Encode(m)
1192	if err == nil {
1193		t.Error("expected error, got nil")
1194		return
1195	}
1196	if err.Error() != "Only a struct or map can be marshaled to TOML" {
1197		t.Fail()
1198	}
1199}
1200
1201type testDuration struct {
1202	Nanosec   time.Duration  `toml:"nanosec"`
1203	Microsec1 time.Duration  `toml:"microsec1"`
1204	Microsec2 *time.Duration `toml:"microsec2"`
1205	Millisec  time.Duration  `toml:"millisec"`
1206	Sec       time.Duration  `toml:"sec"`
1207	Min       time.Duration  `toml:"min"`
1208	Hour      time.Duration  `toml:"hour"`
1209	Mixed     time.Duration  `toml:"mixed"`
1210	AString   string         `toml:"a_string"`
1211}
1212
1213var testDurationToml = []byte(`
1214nanosec = "1ns"
1215microsec1 = "1us"
1216microsec2 = "1µs"
1217millisec = "1ms"
1218sec = "1s"
1219min = "1m"
1220hour = "1h"
1221mixed = "1h1m1s1ms1µs1ns"
1222a_string = "15s"
1223`)
1224
1225func TestUnmarshalDuration(t *testing.T) {
1226	buf := bytes.NewBuffer(testDurationToml)
1227
1228	result := testDuration{}
1229	err := NewDecoder(buf).Decode(&result)
1230	if err != nil {
1231		t.Fatal(err)
1232	}
1233	ms := time.Duration(1) * time.Microsecond
1234	expected := testDuration{
1235		Nanosec:   1,
1236		Microsec1: time.Microsecond,
1237		Microsec2: &ms,
1238		Millisec:  time.Millisecond,
1239		Sec:       time.Second,
1240		Min:       time.Minute,
1241		Hour:      time.Hour,
1242		Mixed: time.Hour +
1243			time.Minute +
1244			time.Second +
1245			time.Millisecond +
1246			time.Microsecond +
1247			time.Nanosecond,
1248		AString: "15s",
1249	}
1250	if !reflect.DeepEqual(result, expected) {
1251		resStr, _ := json.MarshalIndent(result, "", "  ")
1252		expStr, _ := json.MarshalIndent(expected, "", "  ")
1253		t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
1254
1255	}
1256}
1257
1258var testDurationToml2 = []byte(`a_string = "15s"
1259hour = "1h0m0s"
1260microsec1 = "1µs"
1261microsec2 = "1µs"
1262millisec = "1ms"
1263min = "1m0s"
1264mixed = "1h1m1.001001001s"
1265nanosec = "1ns"
1266sec = "1s"
1267`)
1268
1269func TestMarshalDuration(t *testing.T) {
1270	ms := time.Duration(1) * time.Microsecond
1271	data := testDuration{
1272		Nanosec:   1,
1273		Microsec1: time.Microsecond,
1274		Microsec2: &ms,
1275		Millisec:  time.Millisecond,
1276		Sec:       time.Second,
1277		Min:       time.Minute,
1278		Hour:      time.Hour,
1279		Mixed: time.Hour +
1280			time.Minute +
1281			time.Second +
1282			time.Millisecond +
1283			time.Microsecond +
1284			time.Nanosecond,
1285		AString: "15s",
1286	}
1287
1288	var buf bytes.Buffer
1289	err := NewEncoder(&buf).Encode(data)
1290	if err != nil {
1291		t.Fatal(err)
1292	}
1293	expected := testDurationToml2
1294	result := buf.Bytes()
1295	if !bytes.Equal(result, expected) {
1296		t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
1297	}
1298}
1299
1300type testBadDuration struct {
1301	Val time.Duration `toml:"val"`
1302}
1303
1304var testBadDurationToml = []byte(`val = "1z"`)
1305
1306func TestUnmarshalBadDuration(t *testing.T) {
1307	buf := bytes.NewBuffer(testBadDurationToml)
1308
1309	result := testBadDuration{}
1310	err := NewDecoder(buf).Decode(&result)
1311	if err == nil {
1312		t.Fatal()
1313	}
1314	if err.Error() != "(1, 1): Can't convert 1z(string) to time.Duration. time: unknown unit z in duration 1z" {
1315		t.Fatalf("unexpected error: %s", err)
1316	}
1317}
1318
1319var testCamelCaseKeyToml = []byte(`fooBar = 10`)
1320
1321func TestUnmarshalCamelCaseKey(t *testing.T) {
1322	var x struct {
1323		FooBar int
1324		B      int
1325	}
1326
1327	if err := Unmarshal(testCamelCaseKeyToml, &x); err != nil {
1328		t.Fatal(err)
1329	}
1330
1331	if x.FooBar != 10 {
1332		t.Fatal("Did not set camelCase'd key")
1333	}
1334}
1335
1336func TestUnmarshalDefault(t *testing.T) {
1337	var doc struct {
1338		StringField  string  `default:"a"`
1339		BoolField    bool    `default:"true"`
1340		IntField     int     `default:"1"`
1341		Int64Field   int64   `default:"2"`
1342		Float64Field float64 `default:"3.1"`
1343	}
1344
1345	err := Unmarshal([]byte(``), &doc)
1346	if err != nil {
1347		t.Fatal(err)
1348	}
1349	if doc.BoolField != true {
1350		t.Errorf("BoolField should be true, not %t", doc.BoolField)
1351	}
1352	if doc.StringField != "a" {
1353		t.Errorf("StringField should be \"a\", not %s", doc.StringField)
1354	}
1355	if doc.IntField != 1 {
1356		t.Errorf("IntField should be 1, not %d", doc.IntField)
1357	}
1358	if doc.Int64Field != 2 {
1359		t.Errorf("Int64Field should be 2, not %d", doc.Int64Field)
1360	}
1361	if doc.Float64Field != 3.1 {
1362		t.Errorf("Float64Field should be 3.1, not %f", doc.Float64Field)
1363	}
1364}
1365
1366func TestUnmarshalDefaultFailureBool(t *testing.T) {
1367	var doc struct {
1368		Field bool `default:"blah"`
1369	}
1370
1371	err := Unmarshal([]byte(``), &doc)
1372	if err == nil {
1373		t.Fatal("should error")
1374	}
1375}
1376
1377func TestUnmarshalDefaultFailureInt(t *testing.T) {
1378	var doc struct {
1379		Field int `default:"blah"`
1380	}
1381
1382	err := Unmarshal([]byte(``), &doc)
1383	if err == nil {
1384		t.Fatal("should error")
1385	}
1386}
1387
1388func TestUnmarshalDefaultFailureInt64(t *testing.T) {
1389	var doc struct {
1390		Field int64 `default:"blah"`
1391	}
1392
1393	err := Unmarshal([]byte(``), &doc)
1394	if err == nil {
1395		t.Fatal("should error")
1396	}
1397}
1398
1399func TestUnmarshalDefaultFailureFloat64(t *testing.T) {
1400	var doc struct {
1401		Field float64 `default:"blah"`
1402	}
1403
1404	err := Unmarshal([]byte(``), &doc)
1405	if err == nil {
1406		t.Fatal("should error")
1407	}
1408}
1409
1410func TestUnmarshalDefaultFailureUnsupported(t *testing.T) {
1411	var doc struct {
1412		Field struct{} `default:"blah"`
1413	}
1414
1415	err := Unmarshal([]byte(``), &doc)
1416	if err == nil {
1417		t.Fatal("should error")
1418	}
1419}
1420