14 type basicMarshalTestStruct struct {
15 String string `toml:"string"`
16 StringList []string `toml:"strlist"`
17 Sub basicMarshalTestSubStruct `toml:"subdoc"`
18 SubList []basicMarshalTestSubStruct `toml:"sublist"`
21 type basicMarshalTestSubStruct struct {
25 var basicTestData = basicMarshalTestStruct{
27 StringList: []string{"Howdy", "Hey There"},
28 Sub: basicMarshalTestSubStruct{"One"},
29 SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
32 var basicTestToml = []byte(`string = "Hello"
33 strlist = ["Howdy","Hey There"]
45 func TestBasicMarshal(t *testing.T) {
46 result, err := Marshal(basicTestData)
50 expected := basicTestToml
51 if !bytes.Equal(result, expected) {
52 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
56 func TestBasicUnmarshal(t *testing.T) {
57 result := basicMarshalTestStruct{}
58 err := Unmarshal(basicTestToml, &result)
59 expected := basicTestData
63 if !reflect.DeepEqual(result, expected) {
64 t.Errorf("Bad unmarshal: expected %v, got %v", expected, result)
69 Title string `toml:"title"`
70 Basics testDocBasics `toml:"basic"`
71 BasicLists testDocBasicLists `toml:"basic_lists"`
72 BasicMap map[string]string `toml:"basic_map"`
73 Subdocs testDocSubs `toml:"subdoc"`
74 SubDocList []testSubDoc `toml:"subdoclist"`
75 SubDocPtrs []*testSubDoc `toml:"subdocptrs"`
76 err int `toml:"shouldntBeHere"`
77 unexported int `toml:"shouldntBeHere"`
78 Unexported2 int `toml:"-"`
81 type testDocBasics struct {
82 Bool bool `toml:"bool"`
83 Date time.Time `toml:"date"`
84 Float float32 `toml:"float"`
86 Uint uint `toml:"uint"`
87 String *string `toml:"string"`
88 unexported int `toml:"shouldntBeHere"`
91 type testDocBasicLists struct {
92 Bools []bool `toml:"bools"`
93 Dates []time.Time `toml:"dates"`
94 Floats []*float32 `toml:"floats"`
95 Ints []int `toml:"ints"`
96 Strings []string `toml:"strings"`
97 UInts []uint `toml:"uints"`
100 type testDocSubs struct {
101 First testSubDoc `toml:"first"`
102 Second *testSubDoc `toml:"second"`
105 type testSubDoc struct {
106 Name string `toml:"name"`
107 unexported int `toml:"shouldntBeHere"`
110 var biteMe = "Bite me"
111 var float1 float32 = 12.3
112 var float2 float32 = 45.6
113 var float3 float32 = 78.9
114 var subdoc = testSubDoc{"Second", 0}
116 var docData = testDoc{
117 Title: "TOML Marshal Testing",
120 Basics: testDocBasics{
122 Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
129 BasicLists: testDocBasicLists{
130 Bools: []bool{true, false, true},
132 time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC),
133 time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC),
135 Floats: []*float32{&float1, &float2, &float3},
136 Ints: []int{8001, 8001, 8002},
137 Strings: []string{"One", "Two", "Three"},
138 UInts: []uint{5002, 5003},
140 BasicMap: map[string]string{
144 Subdocs: testDocSubs{
145 First: testSubDoc{"First", 0},
148 SubDocList: []testSubDoc{
149 testSubDoc{"List.First", 0},
150 testSubDoc{"List.Second", 0},
152 SubDocPtrs: []*testSubDoc{&subdoc},
155 func TestDocMarshal(t *testing.T) {
156 result, err := Marshal(docData)
160 expected, _ := ioutil.ReadFile("marshal_test.toml")
161 if !bytes.Equal(result, expected) {
162 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
166 func TestDocUnmarshal(t *testing.T) {
168 tomlData, _ := ioutil.ReadFile("marshal_test.toml")
169 err := Unmarshal(tomlData, &result)
174 if !reflect.DeepEqual(result, expected) {
175 resStr, _ := json.MarshalIndent(result, "", " ")
176 expStr, _ := json.MarshalIndent(expected, "", " ")
177 t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
181 func TestDocPartialUnmarshal(t *testing.T) {
182 result := testDocSubs{}
184 tree, _ := LoadFile("marshal_test.toml")
185 subTree := tree.Get("subdoc").(*Tree)
186 err := subTree.Unmarshal(&result)
187 expected := docData.Subdocs
191 if !reflect.DeepEqual(result, expected) {
192 resStr, _ := json.MarshalIndent(result, "", " ")
193 expStr, _ := json.MarshalIndent(expected, "", " ")
194 t.Errorf("Bad partial unmartial: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
198 type tomlTypeCheckTest struct {
201 typ int //0=primitive, 1=otherslice, 2=treeslice, 3=tree
204 func TestTypeChecks(t *testing.T) {
205 tests := []tomlTypeCheckTest{
207 {"time", time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC), 0},
208 {"stringlist", []string{"hello", "hi"}, 1},
209 {"timelist", []time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1},
210 {"objectlist", []tomlTypeCheckTest{}, 2},
211 {"object", tomlTypeCheckTest{}, 3},
214 for _, test := range tests {
215 expected := []bool{false, false, false, false}
216 expected[test.typ] = true
218 isPrimitive(reflect.TypeOf(test.item)),
219 isOtherSlice(reflect.TypeOf(test.item)),
220 isTreeSlice(reflect.TypeOf(test.item)),
221 isTree(reflect.TypeOf(test.item)),
223 if !reflect.DeepEqual(expected, result) {
224 t.Errorf("Bad type check on %q: expected %v, got %v", test.name, expected, result)
229 type unexportedMarshalTestStruct struct {
230 String string `toml:"string"`
231 StringList []string `toml:"strlist"`
232 Sub basicMarshalTestSubStruct `toml:"subdoc"`
233 SubList []basicMarshalTestSubStruct `toml:"sublist"`
234 unexported int `toml:"shouldntBeHere"`
235 Unexported2 int `toml:"-"`
238 var unexportedTestData = unexportedMarshalTestStruct{
240 StringList: []string{"Howdy", "Hey There"},
241 Sub: basicMarshalTestSubStruct{"One"},
242 SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}},
247 var unexportedTestToml = []byte(`string = "Hello"
248 strlist = ["Howdy","Hey There"]
262 func TestUnexportedUnmarshal(t *testing.T) {
263 result := unexportedMarshalTestStruct{}
264 err := Unmarshal(unexportedTestToml, &result)
265 expected := unexportedTestData
269 if !reflect.DeepEqual(result, expected) {
270 t.Errorf("Bad unexported unmarshal: expected %v, got %v", expected, result)
274 type errStruct struct {
275 Bool bool `toml:"bool"`
276 Date time.Time `toml:"date"`
277 Float float64 `toml:"float"`
278 Int int16 `toml:"int"`
279 String *string `toml:"string"`
282 var errTomls = []string{
283 "bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
284 "bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
285 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"",
286 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"",
287 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
288 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me",
289 "bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
290 "bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"",
291 "bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"",
292 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"",
293 "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1",
297 Vals map[string]float64
315 var intErrTomls = []string{
316 "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",
317 "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",
318 "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",
319 "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",
320 "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",
321 "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",
322 "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",
323 "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",
324 "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",
325 "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",
326 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0",
327 "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []",
330 func TestErrUnmarshal(t *testing.T) {
331 for ind, toml := range errTomls {
332 result := errStruct{}
333 err := Unmarshal([]byte(toml), &result)
335 t.Errorf("Expected err from case %d\n", ind)
339 err := Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2)
341 t.Errorf("Expected err from map")
343 for ind, toml := range intErrTomls {
345 err := Unmarshal([]byte(toml), &result3)
347 t.Errorf("Expected int err from case %d\n", ind)
352 type emptyMarshalTestStruct struct {
353 Title string `toml:"title"`
354 Bool bool `toml:"bool"`
356 String string `toml:"string"`
357 StringList []string `toml:"stringlist"`
358 Ptr *basicMarshalTestStruct `toml:"ptr"`
359 Map map[string]string `toml:"map"`
362 var emptyTestData = emptyMarshalTestStruct{
363 Title: "Placeholder",
367 StringList: []string{},
369 Map: map[string]string{},
372 var emptyTestToml = []byte(`bool = false
376 title = "Placeholder"
381 type emptyMarshalTestStruct2 struct {
382 Title string `toml:"title"`
383 Bool bool `toml:"bool,omitempty"`
384 Int int `toml:"int, omitempty"`
385 String string `toml:"string,omitempty "`
386 StringList []string `toml:"stringlist,omitempty"`
387 Ptr *basicMarshalTestStruct `toml:"ptr,omitempty"`
388 Map map[string]string `toml:"map,omitempty"`
391 var emptyTestData2 = emptyMarshalTestStruct2{
392 Title: "Placeholder",
396 StringList: []string{},
398 Map: map[string]string{},
401 var emptyTestToml2 = []byte(`title = "Placeholder"
404 func TestEmptyMarshal(t *testing.T) {
405 result, err := Marshal(emptyTestData)
409 expected := emptyTestToml
410 if !bytes.Equal(result, expected) {
411 t.Errorf("Bad empty marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
415 func TestEmptyMarshalOmit(t *testing.T) {
416 result, err := Marshal(emptyTestData2)
420 expected := emptyTestToml2
421 if !bytes.Equal(result, expected) {
422 t.Errorf("Bad empty omit marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
426 func TestEmptyUnmarshal(t *testing.T) {
427 result := emptyMarshalTestStruct{}
428 err := Unmarshal(emptyTestToml, &result)
429 expected := emptyTestData
433 if !reflect.DeepEqual(result, expected) {
434 t.Errorf("Bad empty unmarshal: expected %v, got %v", expected, result)
438 func TestEmptyUnmarshalOmit(t *testing.T) {
439 result := emptyMarshalTestStruct2{}
440 err := Unmarshal(emptyTestToml, &result)
441 expected := emptyTestData2
445 if !reflect.DeepEqual(result, expected) {
446 t.Errorf("Bad empty omit unmarshal: expected %v, got %v", expected, result)
450 type pointerMarshalTestStruct struct {
454 Map *map[string]string
455 MapPtr *map[string]*string
458 EmptyMap *map[string]string
462 var pointerStr = "Hello"
463 var pointerList = []string{"Hello back"}
464 var pointerListPtr = []*string{&pointerStr}
465 var pointerMap = map[string]string{"response": "Goodbye"}
466 var pointerMapPtr = map[string]*string{"alternate": &pointerStr}
467 var pointerTestData = pointerMarshalTestStruct{
470 ListPtr: &pointerListPtr,
472 MapPtr: &pointerMapPtr,
478 var pointerTestToml = []byte(`List = ["Hello back"]
489 func TestPointerMarshal(t *testing.T) {
490 result, err := Marshal(pointerTestData)
494 expected := pointerTestToml
495 if !bytes.Equal(result, expected) {
496 t.Errorf("Bad pointer marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
500 func TestPointerUnmarshal(t *testing.T) {
501 result := pointerMarshalTestStruct{}
502 err := Unmarshal(pointerTestToml, &result)
503 expected := pointerTestData
507 if !reflect.DeepEqual(result, expected) {
508 t.Errorf("Bad pointer unmarshal: expected %v, got %v", expected, result)
512 func TestUnmarshalTypeMismatch(t *testing.T) {
513 result := pointerMarshalTestStruct{}
514 err := Unmarshal([]byte("List = 123"), &result)
515 if !strings.HasPrefix(err.Error(), "(1, 1): Can't convert 123(int64) to []string(slice)") {
516 t.Errorf("Type mismatch must be reported: got %v", err.Error())
520 type nestedMarshalTestStruct struct {
522 //Struct [][]basicMarshalTestSubStruct
523 StringPtr *[]*[]*string
524 // StructPtr *[]*[]*basicMarshalTestSubStruct
529 var strPtr = []*string{&str1, &str2}
530 var strPtr2 = []*[]*string{&strPtr}
532 var nestedTestData = nestedMarshalTestStruct{
533 String: [][]string{[]string{"Five", "Six"}, []string{"One", "Two"}},
537 var nestedTestToml = []byte(`String = [["Five","Six"],["One","Two"]]
538 StringPtr = [["Three","Four"]]
541 func TestNestedMarshal(t *testing.T) {
542 result, err := Marshal(nestedTestData)
546 expected := nestedTestToml
547 if !bytes.Equal(result, expected) {
548 t.Errorf("Bad nested marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
552 func TestNestedUnmarshal(t *testing.T) {
553 result := nestedMarshalTestStruct{}
554 err := Unmarshal(nestedTestToml, &result)
555 expected := nestedTestData
559 if !reflect.DeepEqual(result, expected) {
560 t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result)
564 type customMarshalerParent struct {
565 Self customMarshaler `toml:"me"`
566 Friends []customMarshaler `toml:"friends"`
569 type customMarshaler struct {
574 func (c customMarshaler) MarshalTOML() ([]byte, error) {
575 fullName := fmt.Sprintf("%s %s", c.FirsName, c.LastName)
576 return []byte(fullName), nil
579 var customMarshalerData = customMarshaler{FirsName: "Sally", LastName: "Fields"}
580 var customMarshalerToml = []byte(`Sally Fields`)
581 var nestedCustomMarshalerData = customMarshalerParent{
582 Self: customMarshaler{FirsName: "Maiku", LastName: "Suteda"},
583 Friends: []customMarshaler{customMarshalerData},
585 var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"]
589 func TestCustomMarshaler(t *testing.T) {
590 result, err := Marshal(customMarshalerData)
594 expected := customMarshalerToml
595 if !bytes.Equal(result, expected) {
596 t.Errorf("Bad custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
600 func TestNestedCustomMarshaler(t *testing.T) {
601 result, err := Marshal(nestedCustomMarshalerData)
605 expected := nestedCustomMarshalerToml
606 if !bytes.Equal(result, expected) {
607 t.Errorf("Bad nested custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
611 var commentTestToml = []byte(`
612 # it's a comment on type
614 # isCommented = "dvalue"
617 # A comment on AttrB with a
626 # a comment on my on typeC
631 # a comment on my on typeC
635 func TestMarshalComment(t *testing.T) {
637 My string `comment:"a comment on my on typeC"`
640 AttrA string `toml:"user" comment:"A comment on AttrA"`
641 AttrB string `toml:"password" comment:"A comment on AttrB with a\n break line"`
642 AttrC string `toml:"noComment"`
643 AttrD string `toml:"isCommented" commented:"true"`
647 TypeB TypeB `toml:"postgres" comment:"it's a comment on type"`
650 ta := []TypeC{{My: "Foo"}, {My: "Baar"}}
651 config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", AttrC: "cvalue", AttrD: "dvalue", My: ta}}
652 result, err := Marshal(config)
656 expected := commentTestToml
657 if !bytes.Equal(result, expected) {
658 t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
662 type mapsTestStruct struct {
663 Simple map[string]string
664 Paths map[string]string
665 Other map[string]float64
673 var mapsTestData = mapsTestStruct{
674 Simple: map[string]string{
675 "one plus one": "two",
678 Paths: map[string]string{
679 "/this/is/a/path": "/this/is/also/a/path",
680 "/heloo.txt": "/tmp/lololo.txt",
682 Other: map[string]float64{
685 X: struct{ Y struct{ Z map[string]bool } }{
686 Y: struct{ Z map[string]bool }{
693 var mapsTestToml = []byte(`
698 "/heloo.txt" = "/tmp/lololo.txt"
699 "/this/is/a/path" = "/this/is/also/a/path"
703 "one plus one" = "two"
713 func TestEncodeQuotedMapKeys(t *testing.T) {
715 if err := NewEncoder(&buf).QuoteMapKeys(true).Encode(mapsTestData); err != nil {
718 result := buf.Bytes()
719 expected := mapsTestToml
720 if !bytes.Equal(result, expected) {
721 t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
724 func TestDecodeQuotedMapKeys(t *testing.T) {
725 result := mapsTestStruct{}
726 err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result)
727 expected := mapsTestData
731 if !reflect.DeepEqual(result, expected) {
732 t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result)