OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / pelletier / go-toml / tomltree_write_test.go
1 package toml
2
3 import (
4         "bytes"
5         "errors"
6         "fmt"
7         "reflect"
8         "strings"
9         "testing"
10         "time"
11 )
12
13 type failingWriter struct {
14         failAt  int
15         written int
16         buffer  bytes.Buffer
17 }
18
19 func (f *failingWriter) Write(p []byte) (n int, err error) {
20         count := len(p)
21         toWrite := f.failAt - (count + f.written)
22         if toWrite < 0 {
23                 toWrite = 0
24         }
25         if toWrite > count {
26                 f.written += count
27                 f.buffer.Write(p)
28                 return count, nil
29         }
30
31         f.buffer.Write(p[:toWrite])
32         f.written = f.failAt
33         return toWrite, fmt.Errorf("failingWriter failed after writing %d bytes", f.written)
34 }
35
36 func assertErrorString(t *testing.T, expected string, err error) {
37         expectedErr := errors.New(expected)
38         if err == nil || err.Error() != expectedErr.Error() {
39                 t.Errorf("expecting error %s, but got %s instead", expected, err)
40         }
41 }
42
43 func TestTreeWriteToEmptyTable(t *testing.T) {
44         doc := `[[empty-tables]]
45 [[empty-tables]]`
46
47         toml, err := Load(doc)
48         if err != nil {
49                 t.Fatal("Unexpected Load error:", err)
50         }
51         tomlString, err := toml.ToTomlString()
52         if err != nil {
53                 t.Fatal("Unexpected ToTomlString error:", err)
54         }
55
56         expected := `
57 [[empty-tables]]
58
59 [[empty-tables]]
60 `
61
62         if tomlString != expected {
63                 t.Fatalf("Expected:\n%s\nGot:\n%s", expected, tomlString)
64         }
65 }
66
67 func TestTreeWriteToTomlString(t *testing.T) {
68         toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" }
69 points = { x = 1, y = 2 }`)
70
71         if err != nil {
72                 t.Fatal("Unexpected error:", err)
73         }
74
75         tomlString, _ := toml.ToTomlString()
76         reparsedTree, err := Load(tomlString)
77
78         assertTree(t, reparsedTree, err, map[string]interface{}{
79                 "name": map[string]interface{}{
80                         "first": "Tom",
81                         "last":  "Preston-Werner",
82                 },
83                 "points": map[string]interface{}{
84                         "x": int64(1),
85                         "y": int64(2),
86                 },
87         })
88 }
89
90 func TestTreeWriteToTomlStringSimple(t *testing.T) {
91         tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n")
92         if err != nil {
93                 t.Errorf("Test failed to parse: %v", err)
94                 return
95         }
96         result, err := tree.ToTomlString()
97         if err != nil {
98                 t.Errorf("Unexpected error: %s", err)
99         }
100         expected := "\n[foo]\n\n  [[foo.bar]]\n    a = 42\n\n  [[foo.bar]]\n    a = 69\n"
101         if result != expected {
102                 t.Errorf("Expected got '%s', expected '%s'", result, expected)
103         }
104 }
105
106 func TestTreeWriteToTomlStringKeysOrders(t *testing.T) {
107         for i := 0; i < 100; i++ {
108                 tree, _ := Load(`
109                 foobar = true
110                 bar = "baz"
111                 foo = 1
112                 [qux]
113                   foo = 1
114                   bar = "baz2"`)
115
116                 stringRepr, _ := tree.ToTomlString()
117
118                 t.Log("Intermediate string representation:")
119                 t.Log(stringRepr)
120
121                 r := strings.NewReader(stringRepr)
122                 toml, err := LoadReader(r)
123
124                 if err != nil {
125                         t.Fatal("Unexpected error:", err)
126                 }
127
128                 assertTree(t, toml, err, map[string]interface{}{
129                         "foobar": true,
130                         "bar":    "baz",
131                         "foo":    1,
132                         "qux": map[string]interface{}{
133                                 "foo": 1,
134                                 "bar": "baz2",
135                         },
136                 })
137         }
138 }
139
140 func testMaps(t *testing.T, actual, expected map[string]interface{}) {
141         if !reflect.DeepEqual(actual, expected) {
142                 t.Fatal("trees aren't equal.\n", "Expected:\n", expected, "\nActual:\n", actual)
143         }
144 }
145
146 func TestTreeWriteToMapSimple(t *testing.T) {
147         tree, _ := Load("a = 42\nb = 17")
148
149         expected := map[string]interface{}{
150                 "a": int64(42),
151                 "b": int64(17),
152         }
153
154         testMaps(t, tree.ToMap(), expected)
155 }
156
157 func TestTreeWriteToInvalidTreeSimpleValue(t *testing.T) {
158         tree := Tree{values: map[string]interface{}{"foo": int8(1)}}
159         _, err := tree.ToTomlString()
160         assertErrorString(t, "invalid value type at foo: int8", err)
161 }
162
163 func TestTreeWriteToInvalidTreeTomlValue(t *testing.T) {
164         tree := Tree{values: map[string]interface{}{"foo": &tomlValue{value: int8(1), comment: "", position: Position{}}}}
165         _, err := tree.ToTomlString()
166         assertErrorString(t, "unsupported value type int8: 1", err)
167 }
168
169 func TestTreeWriteToInvalidTreeTomlValueArray(t *testing.T) {
170         tree := Tree{values: map[string]interface{}{"foo": &tomlValue{value: int8(1), comment: "", position: Position{}}}}
171         _, err := tree.ToTomlString()
172         assertErrorString(t, "unsupported value type int8: 1", err)
173 }
174
175 func TestTreeWriteToFailingWriterInSimpleValue(t *testing.T) {
176         toml, _ := Load(`a = 2`)
177         writer := failingWriter{failAt: 0, written: 0}
178         _, err := toml.WriteTo(&writer)
179         assertErrorString(t, "failingWriter failed after writing 0 bytes", err)
180 }
181
182 func TestTreeWriteToFailingWriterInTable(t *testing.T) {
183         toml, _ := Load(`
184 [b]
185 a = 2`)
186         writer := failingWriter{failAt: 2, written: 0}
187         _, err := toml.WriteTo(&writer)
188         assertErrorString(t, "failingWriter failed after writing 2 bytes", err)
189
190         writer = failingWriter{failAt: 13, written: 0}
191         _, err = toml.WriteTo(&writer)
192         assertErrorString(t, "failingWriter failed after writing 13 bytes", err)
193 }
194
195 func TestTreeWriteToFailingWriterInArray(t *testing.T) {
196         toml, _ := Load(`
197 [[b]]
198 a = 2`)
199         writer := failingWriter{failAt: 2, written: 0}
200         _, err := toml.WriteTo(&writer)
201         assertErrorString(t, "failingWriter failed after writing 2 bytes", err)
202
203         writer = failingWriter{failAt: 15, written: 0}
204         _, err = toml.WriteTo(&writer)
205         assertErrorString(t, "failingWriter failed after writing 15 bytes", err)
206 }
207
208 func TestTreeWriteToMapExampleFile(t *testing.T) {
209         tree, _ := LoadFile("example.toml")
210         expected := map[string]interface{}{
211                 "title": "TOML Example",
212                 "owner": map[string]interface{}{
213                         "name":         "Tom Preston-Werner",
214                         "organization": "GitHub",
215                         "bio":          "GitHub Cofounder & CEO\nLikes tater tots and beer.",
216                         "dob":          time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC),
217                 },
218                 "database": map[string]interface{}{
219                         "server":         "192.168.1.1",
220                         "ports":          []interface{}{int64(8001), int64(8001), int64(8002)},
221                         "connection_max": int64(5000),
222                         "enabled":        true,
223                 },
224                 "servers": map[string]interface{}{
225                         "alpha": map[string]interface{}{
226                                 "ip": "10.0.0.1",
227                                 "dc": "eqdc10",
228                         },
229                         "beta": map[string]interface{}{
230                                 "ip": "10.0.0.2",
231                                 "dc": "eqdc10",
232                         },
233                 },
234                 "clients": map[string]interface{}{
235                         "data": []interface{}{
236                                 []interface{}{"gamma", "delta"},
237                                 []interface{}{int64(1), int64(2)},
238                         },
239                 },
240         }
241         testMaps(t, tree.ToMap(), expected)
242 }
243
244 func TestTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
245         tree, _ := Load(`
246         [[menu.main]]
247         a = "menu 1"
248         b = "menu 2"
249         [[menu.main]]
250         c = "menu 3"
251         d = "menu 4"`)
252         expected := map[string]interface{}{
253                 "menu": map[string]interface{}{
254                         "main": []interface{}{
255                                 map[string]interface{}{"a": "menu 1", "b": "menu 2"},
256                                 map[string]interface{}{"c": "menu 3", "d": "menu 4"},
257                         },
258                 },
259         }
260         treeMap := tree.ToMap()
261
262         testMaps(t, treeMap, expected)
263 }
264
265 func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) {
266         tree, _ := Load(`
267         [params]
268         language_tabs = [
269                 { key = "shell", name = "Shell" },
270                 { key = "ruby", name = "Ruby" },
271                 { key = "python", name = "Python" }
272         ]`)
273
274         expected := map[string]interface{}{
275                 "params": map[string]interface{}{
276                         "language_tabs": []interface{}{
277                                 map[string]interface{}{
278                                         "key":  "shell",
279                                         "name": "Shell",
280                                 },
281                                 map[string]interface{}{
282                                         "key":  "ruby",
283                                         "name": "Ruby",
284                                 },
285                                 map[string]interface{}{
286                                         "key":  "python",
287                                         "name": "Python",
288                                 },
289                         },
290                 },
291         }
292
293         treeMap := tree.ToMap()
294         testMaps(t, treeMap, expected)
295 }
296
297 func TestTreeWriteToFloat(t *testing.T) {
298         tree, err := Load(`a = 3.0`)
299         if err != nil {
300                 t.Fatal(err)
301         }
302         str, err := tree.ToTomlString()
303         if err != nil {
304                 t.Fatal(err)
305         }
306         expected := `a = 3.0`
307         if strings.TrimSpace(str) != strings.TrimSpace(expected) {
308                 t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str)
309         }
310 }
311
312 func BenchmarkTreeToTomlString(b *testing.B) {
313         toml, err := Load(sampleHard)
314         if err != nil {
315                 b.Fatal("Unexpected error:", err)
316         }
317
318         for i := 0; i < b.N; i++ {
319                 _, err := toml.ToTomlString()
320                 if err != nil {
321                         b.Fatal(err)
322                 }
323         }
324 }
325
326 var sampleHard = `# Test file for TOML
327 # Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate
328 # This part you'll really hate
329
330 [the]
331 test_string = "You'll hate me after this - #"          # " Annoying, isn't it?
332
333     [the.hard]
334     test_array = [ "] ", " # "]      # ] There you go, parse this!
335     test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ]
336     # You didn't think it'd as easy as chucking out the last #, did you?
337     another_test_string = " Same thing, but with a string #"
338     harder_test_string = " And when \"'s are in the string, along with # \""   # "and comments are there too"
339     # Things will get harder
340
341         [the.hard."bit#"]
342         "what?" = "You don't think some user won't do that?"
343         multi_line_array = [
344             "]",
345             # ] Oh yes I did
346             ]
347
348 # Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test
349
350 #[error]   if you didn't catch this, your parser is broken
351 #string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment"   like this
352 #array = [
353 #         "This might most likely happen in multiline arrays",
354 #         Like here,
355 #         "or here,
356 #         and here"
357 #         ]     End of array comment, forgot the #
358 #number = 3.14  pi <--again forgot the #         `