1 package toml
2
3 import (
4 "reflect"
5 "strconv"
6 "testing"
7 "time"
8 )
9
10 type customString string
11
12 type stringer struct{}
13
14 func (s stringer) String() string {
15 return "stringer"
16 }
17
18 func validate(t *testing.T, path string, object interface{}) {
19 switch o := object.(type) {
20 case *Tree:
21 for key, tree := range o.values {
22 validate(t, path+"."+key, tree)
23 }
24 case []*Tree:
25 for index, tree := range o {
26 validate(t, path+"."+strconv.Itoa(index), tree)
27 }
28 case *tomlValue:
29 switch o.value.(type) {
30 case int64, uint64, bool, string, float64, time.Time,
31 []int64, []uint64, []bool, []string, []float64, []time.Time:
32 default:
33 t.Fatalf("tomlValue at key %s containing incorrect type %T", path, o.value)
34 }
35 default:
36 t.Fatalf("value at key %s is of incorrect type %T", path, object)
37 }
38 t.Logf("validation ok %s as %T", path, object)
39 }
40
41 func validateTree(t *testing.T, tree *Tree) {
42 validate(t, "", tree)
43 }
44
45 func TestTreeCreateToTree(t *testing.T) {
46 data := map[string]interface{}{
47 "a_string": "bar",
48 "an_int": 42,
49 "time": time.Now(),
50 "int8": int8(2),
51 "int16": int16(2),
52 "int32": int32(2),
53 "uint8": uint8(2),
54 "uint16": uint16(2),
55 "uint32": uint32(2),
56 "float32": float32(2),
57 "a_bool": false,
58 "stringer": stringer{},
59 "nested": map[string]interface{}{
60 "foo": "bar",
61 },
62 "array": []string{"a", "b", "c"},
63 "array_uint": []uint{uint(1), uint(2)},
64 "array_table": []map[string]interface{}{{"sub_map": 52}},
65 "array_times": []time.Time{time.Now(), time.Now()},
66 "map_times": map[string]time.Time{"now": time.Now()},
67 "custom_string_map_key": map[customString]interface{}{customString("custom"): "custom"},
68 }
69 tree, err := TreeFromMap(data)
70 if err != nil {
71 t.Fatal("unexpected error:", err)
72 }
73 validateTree(t, tree)
74 }
75
76 func TestTreeCreateToTreeInvalidLeafType(t *testing.T) {
77 _, err := TreeFromMap(map[string]interface{}{"foo": t})
78 expected := "cannot convert type *testing.T to Tree"
79 if err.Error() != expected {
80 t.Fatalf("expected error %s, got %s", expected, err.Error())
81 }
82 }
83
84 func TestTreeCreateToTreeInvalidMapKeyType(t *testing.T) {
85 _, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}})
86 expected := "map key needs to be a string, not int (int)"
87 if err.Error() != expected {
88 t.Fatalf("expected error %s, got %s", expected, err.Error())
89 }
90 }
91
92 func TestTreeCreateToTreeInvalidArrayMemberType(t *testing.T) {
93 _, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}})
94 expected := "cannot convert type *testing.T to Tree"
95 if err.Error() != expected {
96 t.Fatalf("expected error %s, got %s", expected, err.Error())
97 }
98 }
99
100 func TestTreeCreateToTreeInvalidTableGroupType(t *testing.T) {
101 _, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{{"hello": t}}})
102 expected := "cannot convert type *testing.T to Tree"
103 if err.Error() != expected {
104 t.Fatalf("expected error %s, got %s", expected, err.Error())
105 }
106 }
107
108 func TestRoundTripArrayOfTables(t *testing.T) {
109 orig := "\n[[stuff]]\n name = \"foo\"\n things = [\"a\", \"b\"]\n"
110 tree, err := Load(orig)
111 if err != nil {
112 t.Fatalf("unexpected error: %s", err)
113 }
114
115 m := tree.ToMap()
116
117 tree, err = TreeFromMap(m)
118 if err != nil {
119 t.Fatalf("unexpected error: %s", err)
120 }
121 want := orig
122 got := tree.String()
123
124 if got != want {
125 t.Errorf("want:\n%s\ngot:\n%s", want, got)
126 }
127 }
128
129 func TestTomlSliceOfSlice(t *testing.T) {
130 tree, err := Load(` hosts=[["10.1.0.107:9092","10.1.0.107:9093", "192.168.0.40:9094"] ] `)
131 m := tree.ToMap()
132 tree, err = TreeFromMap(m)
133 if err != nil {
134 t.Error("should not error", err)
135 }
136 type Struct struct {
137 Hosts [][]string
138 }
139 var actual Struct
140 tree.Unmarshal(&actual)
141
142 expected := Struct{Hosts: [][]string{[]string{"10.1.0.107:9092", "10.1.0.107:9093", "192.168.0.40:9094"}}}
143
144 if !reflect.DeepEqual(actual, expected) {
145 t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
146 }
147 }
148
149 func TestTomlSliceOfSliceOfSlice(t *testing.T) {
150 tree, err := Load(` hosts=[[["10.1.0.107:9092","10.1.0.107:9093", "192.168.0.40:9094"] ]] `)
151 m := tree.ToMap()
152 tree, err = TreeFromMap(m)
153 if err != nil {
154 t.Error("should not error", err)
155 }
156 type Struct struct {
157 Hosts [][][]string
158 }
159 var actual Struct
160 tree.Unmarshal(&actual)
161
162 expected := Struct{Hosts: [][][]string{[][]string{[]string{"10.1.0.107:9092", "10.1.0.107:9093", "192.168.0.40:9094"}}}}
163
164 if !reflect.DeepEqual(actual, expected) {
165 t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
166 }
167 }
168
169 func TestTomlSliceOfSliceInt(t *testing.T) {
170 tree, err := Load(` hosts=[[1,2,3],[4,5,6] ] `)
171 m := tree.ToMap()
172 tree, err = TreeFromMap(m)
173 if err != nil {
174 t.Error("should not error", err)
175 }
176 type Struct struct {
177 Hosts [][]int
178 }
179 var actual Struct
180 err = tree.Unmarshal(&actual)
181 if err != nil {
182 t.Error("should not error", err)
183 }
184
185 expected := Struct{Hosts: [][]int{[]int{1, 2, 3}, []int{4, 5, 6}}}
186
187 if !reflect.DeepEqual(actual, expected) {
188 t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
189 }
190
191 }
192 func TestTomlSliceOfSliceInt64(t *testing.T) {
193 tree, err := Load(` hosts=[[1,2,3],[4,5,6] ] `)
194 m := tree.ToMap()
195 tree, err = TreeFromMap(m)
196 if err != nil {
197 t.Error("should not error", err)
198 }
199 type Struct struct {
200 Hosts [][]int64
201 }
202 var actual Struct
203 err = tree.Unmarshal(&actual)
204 if err != nil {
205 t.Error("should not error", err)
206 }
207
208 expected := Struct{Hosts: [][]int64{[]int64{1, 2, 3}, []int64{4, 5, 6}}}
209
210 if !reflect.DeepEqual(actual, expected) {
211 t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
212 }
213
214 }
215
216 func TestTomlSliceOfSliceInt64FromMap(t *testing.T) {
217 tree, err := TreeFromMap(map[string]interface{}{"hosts": [][]interface{}{[]interface{}{int32(1), int8(2), 3}}})
218 if err != nil {
219 t.Error("should not error", err)
220 }
221 type Struct struct {
222 Hosts [][]int64
223 }
224 var actual Struct
225 err = tree.Unmarshal(&actual)
226 if err != nil {
227 t.Error("should not error", err)
228 }
229
230 expected := Struct{Hosts: [][]int64{[]int64{1, 2, 3}}}
231
232 if !reflect.DeepEqual(actual, expected) {
233 t.Errorf("Bad unmarshal: expected %+v, got %+v", expected, actual)
234 }
235
236 }
237 func TestTomlSliceOfSliceError(t *testing.T) {
238 _, err := TreeFromMap(map[string]interface{}{"hosts": [][]interface{}{[]interface{}{1, 2, []struct{}{}}}})
239 expected := "cannot convert type []struct {} to Tree"
240 if err.Error() != expected {
241 t.Fatalf("unexpected error: %s", err)
242 }
243 }
244
View as plain text