1 package toml
2
3 import (
4 "fmt"
5 "math"
6 "reflect"
7 "testing"
8 "time"
9 )
10
11 func assertSubTree(t *testing.T, path []string, tree *Tree, err error, ref map[string]interface{}) {
12 if err != nil {
13 t.Error("Non-nil error:", err.Error())
14 return
15 }
16 for k, v := range ref {
17 nextPath := append(path, k)
18 t.Log("asserting path", nextPath)
19
20
21 switch node := tree.GetPath([]string{k}).(type) {
22 case []*Tree:
23 t.Log("\tcomparing key", nextPath, "by array iteration")
24 for idx, item := range node {
25 assertSubTree(t, nextPath, item, err, v.([]map[string]interface{})[idx])
26 }
27 case *Tree:
28 t.Log("\tcomparing key", nextPath, "by subtree assestion")
29 assertSubTree(t, nextPath, node, err, v.(map[string]interface{}))
30 default:
31 t.Log("\tcomparing key", nextPath, "by string representation because it's of type", reflect.TypeOf(node))
32 if fmt.Sprintf("%v", node) != fmt.Sprintf("%v", v) {
33 t.Errorf("was expecting %v at %v but got %v", v, k, node)
34 }
35 }
36 }
37 }
38
39 func assertTree(t *testing.T, tree *Tree, err error, ref map[string]interface{}) {
40 t.Logf("Asserting tree:\n (%T)(%p)(%+v)", tree, tree, tree)
41 assertSubTree(t, []string{}, tree, err, ref)
42 t.Log("Finished tree assertion.")
43 }
44
45 func TestCreateSubTree(t *testing.T) {
46 tree := newTree()
47 tree.createSubTree([]string{"a", "b", "c"}, Position{})
48 tree.Set("a.b.c", 42)
49 if tree.Get("a.b.c") != 42 {
50 t.Fail()
51 }
52 }
53
54 func TestSimpleKV(t *testing.T) {
55 tree, err := Load("a = 42")
56 assertTree(t, tree, err, map[string]interface{}{
57 "a": int64(42),
58 })
59
60 tree, _ = Load("a = 42\nb = 21")
61 assertTree(t, tree, err, map[string]interface{}{
62 "a": int64(42),
63 "b": int64(21),
64 })
65 }
66
67 func TestNumberInKey(t *testing.T) {
68 tree, err := Load("hello2 = 42")
69 assertTree(t, tree, err, map[string]interface{}{
70 "hello2": int64(42),
71 })
72 }
73
74 func TestIncorrectKeyExtraSquareBracket(t *testing.T) {
75 _, err := Load(`[a]b]
76 zyx = 42`)
77 if err == nil {
78 t.Error("Error should have been returned.")
79 }
80 if err.Error() != "(1, 4): parsing error: keys cannot contain ] character" {
81 t.Error("Bad error message:", err.Error())
82 }
83 }
84
85 func TestSimpleNumbers(t *testing.T) {
86 tree, err := Load("a = +42\nb = -21\nc = +4.2\nd = -2.1")
87 assertTree(t, tree, err, map[string]interface{}{
88 "a": int64(42),
89 "b": int64(-21),
90 "c": float64(4.2),
91 "d": float64(-2.1),
92 })
93 }
94
95 func TestSpecialFloats(t *testing.T) {
96 tree, err := Load(`
97 normalinf = inf
98 plusinf = +inf
99 minusinf = -inf
100 normalnan = nan
101 plusnan = +nan
102 minusnan = -nan
103 `)
104 assertTree(t, tree, err, map[string]interface{}{
105 "normalinf": math.Inf(1),
106 "plusinf": math.Inf(1),
107 "minusinf": math.Inf(-1),
108 "normalnan": math.NaN(),
109 "plusnan": math.NaN(),
110 "minusnan": math.NaN(),
111 })
112 }
113
114 func TestHexIntegers(t *testing.T) {
115 tree, err := Load(`a = 0xDEADBEEF`)
116 assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
117
118 tree, err = Load(`a = 0xdeadbeef`)
119 assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
120
121 tree, err = Load(`a = 0xdead_beef`)
122 assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
123
124 _, err = Load(`a = 0x_1`)
125 if err.Error() != "(1, 5): invalid use of _ in hex number" {
126 t.Error("Bad error message:", err.Error())
127 }
128 }
129
130 func TestOctIntegers(t *testing.T) {
131 tree, err := Load(`a = 0o01234567`)
132 assertTree(t, tree, err, map[string]interface{}{"a": int64(342391)})
133
134 tree, err = Load(`a = 0o755`)
135 assertTree(t, tree, err, map[string]interface{}{"a": int64(493)})
136
137 _, err = Load(`a = 0o_1`)
138 if err.Error() != "(1, 5): invalid use of _ in number" {
139 t.Error("Bad error message:", err.Error())
140 }
141 }
142
143 func TestBinIntegers(t *testing.T) {
144 tree, err := Load(`a = 0b11010110`)
145 assertTree(t, tree, err, map[string]interface{}{"a": int64(214)})
146
147 _, err = Load(`a = 0b_1`)
148 if err.Error() != "(1, 5): invalid use of _ in number" {
149 t.Error("Bad error message:", err.Error())
150 }
151 }
152
153 func TestBadIntegerBase(t *testing.T) {
154 _, err := Load(`a = 0k1`)
155 if err.Error() != "(1, 5): unknown number base: k. possible options are x (hex) o (octal) b (binary)" {
156 t.Error("Error should have been returned.")
157 }
158 }
159
160 func TestIntegerNoDigit(t *testing.T) {
161 _, err := Load(`a = 0b`)
162 if err.Error() != "(1, 5): number needs at least one digit" {
163 t.Error("Bad error message:", err.Error())
164 }
165 }
166
167 func TestNumbersWithUnderscores(t *testing.T) {
168 tree, err := Load("a = 1_000")
169 assertTree(t, tree, err, map[string]interface{}{
170 "a": int64(1000),
171 })
172
173 tree, err = Load("a = 5_349_221")
174 assertTree(t, tree, err, map[string]interface{}{
175 "a": int64(5349221),
176 })
177
178 tree, err = Load("a = 1_2_3_4_5")
179 assertTree(t, tree, err, map[string]interface{}{
180 "a": int64(12345),
181 })
182
183 tree, err = Load("flt8 = 9_224_617.445_991_228_313")
184 assertTree(t, tree, err, map[string]interface{}{
185 "flt8": float64(9224617.445991228313),
186 })
187
188 tree, err = Load("flt9 = 1e1_00")
189 assertTree(t, tree, err, map[string]interface{}{
190 "flt9": float64(1e100),
191 })
192 }
193
194 func TestFloatsWithExponents(t *testing.T) {
195 tree, err := Load("a = 5e+22\nb = 5E+22\nc = -5e+22\nd = -5e-22\ne = 6.626e-34")
196 assertTree(t, tree, err, map[string]interface{}{
197 "a": float64(5e+22),
198 "b": float64(5e+22),
199 "c": float64(-5e+22),
200 "d": float64(-5e-22),
201 "e": float64(6.626e-34),
202 })
203 }
204
205 func TestSimpleDate(t *testing.T) {
206 tree, err := Load("a = 1979-05-27T07:32:00Z")
207 assertTree(t, tree, err, map[string]interface{}{
208 "a": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC),
209 })
210 }
211
212 func TestDateOffset(t *testing.T) {
213 tree, err := Load("a = 1979-05-27T00:32:00-07:00")
214 assertTree(t, tree, err, map[string]interface{}{
215 "a": time.Date(1979, time.May, 27, 0, 32, 0, 0, time.FixedZone("", -7*60*60)),
216 })
217 }
218
219 func TestDateNano(t *testing.T) {
220 tree, err := Load("a = 1979-05-27T00:32:00.999999999-07:00")
221 assertTree(t, tree, err, map[string]interface{}{
222 "a": time.Date(1979, time.May, 27, 0, 32, 0, 999999999, time.FixedZone("", -7*60*60)),
223 })
224 }
225
226 func TestLocalDateTime(t *testing.T) {
227 tree, err := Load("a = 1979-05-27T07:32:00")
228 assertTree(t, tree, err, map[string]interface{}{
229 "a": LocalDateTime{
230 Date: LocalDate{
231 Year: 1979,
232 Month: 5,
233 Day: 27,
234 },
235 Time: LocalTime{
236 Hour: 7,
237 Minute: 32,
238 Second: 0,
239 Nanosecond: 0,
240 },
241 },
242 })
243 }
244
245 func TestLocalDateTimeNano(t *testing.T) {
246 tree, err := Load("a = 1979-05-27T07:32:00.999999")
247 assertTree(t, tree, err, map[string]interface{}{
248 "a": LocalDateTime{
249 Date: LocalDate{
250 Year: 1979,
251 Month: 5,
252 Day: 27,
253 },
254 Time: LocalTime{
255 Hour: 7,
256 Minute: 32,
257 Second: 0,
258 Nanosecond: 999999000,
259 },
260 },
261 })
262 }
263
264 func TestLocalDate(t *testing.T) {
265 tree, err := Load("a = 1979-05-27")
266 assertTree(t, tree, err, map[string]interface{}{
267 "a": LocalDate{
268 Year: 1979,
269 Month: 5,
270 Day: 27,
271 },
272 })
273 }
274
275 func TestLocalDateError(t *testing.T) {
276 _, err := Load("a = 2020-09-31")
277 if err == nil {
278 t.Fatalf("should error")
279 }
280 }
281
282 func TestLocalTimeError(t *testing.T) {
283 _, err := Load("a = 07:99:00")
284 if err == nil {
285 t.Fatalf("should error")
286 }
287 }
288
289 func TestLocalDateTimeError(t *testing.T) {
290 _, err := Load("a = 2020-09-31T07:99:00")
291 if err == nil {
292 t.Fatalf("should error")
293 }
294 }
295
296 func TestDateTimeOffsetError(t *testing.T) {
297 _, err := Load("a = 2020-09-31T07:99:00Z")
298 if err == nil {
299 t.Fatalf("should error")
300 }
301 }
302
303 func TestLocalTime(t *testing.T) {
304 tree, err := Load("a = 07:32:00")
305 assertTree(t, tree, err, map[string]interface{}{
306 "a": LocalTime{
307 Hour: 7,
308 Minute: 32,
309 Second: 0,
310 Nanosecond: 0,
311 },
312 })
313 }
314
315 func TestLocalTimeNano(t *testing.T) {
316 tree, err := Load("a = 00:32:00.999999")
317 assertTree(t, tree, err, map[string]interface{}{
318 "a": LocalTime{
319 Hour: 0,
320 Minute: 32,
321 Second: 0,
322 Nanosecond: 999999000,
323 },
324 })
325 }
326
327 func TestSimpleString(t *testing.T) {
328 tree, err := Load("a = \"hello world\"")
329 assertTree(t, tree, err, map[string]interface{}{
330 "a": "hello world",
331 })
332 }
333
334 func TestSpaceKey(t *testing.T) {
335 tree, err := Load("\"a b\" = \"hello world\"")
336 assertTree(t, tree, err, map[string]interface{}{
337 "a b": "hello world",
338 })
339 }
340
341 func TestDoubleQuotedKey(t *testing.T) {
342 tree, err := Load(`
343 "key" = "a"
344 "\t" = "b"
345 "\U0001F914" = "c"
346 "\u2764" = "d"
347 `)
348 assertTree(t, tree, err, map[string]interface{}{
349 "key": "a",
350 "\t": "b",
351 "\U0001F914": "c",
352 "\u2764": "d",
353 })
354 }
355
356 func TestSingleQuotedKey(t *testing.T) {
357 tree, err := Load(`
358 'key' = "a"
359 '\t' = "b"
360 '\U0001F914' = "c"
361 '\u2764' = "d"
362 `)
363 assertTree(t, tree, err, map[string]interface{}{
364 `key`: "a",
365 `\t`: "b",
366 `\U0001F914`: "c",
367 `\u2764`: "d",
368 })
369 }
370
371 func TestStringEscapables(t *testing.T) {
372 tree, err := Load("a = \"a \\n b\"")
373 assertTree(t, tree, err, map[string]interface{}{
374 "a": "a \n b",
375 })
376
377 tree, err = Load("a = \"a \\t b\"")
378 assertTree(t, tree, err, map[string]interface{}{
379 "a": "a \t b",
380 })
381
382 tree, err = Load("a = \"a \\r b\"")
383 assertTree(t, tree, err, map[string]interface{}{
384 "a": "a \r b",
385 })
386
387 tree, err = Load("a = \"a \\\\ b\"")
388 assertTree(t, tree, err, map[string]interface{}{
389 "a": "a \\ b",
390 })
391 }
392
393 func TestEmptyQuotedString(t *testing.T) {
394 tree, err := Load(`[""]
395 "" = 1`)
396 assertTree(t, tree, err, map[string]interface{}{
397 "": map[string]interface{}{
398 "": int64(1),
399 },
400 })
401 }
402
403 func TestBools(t *testing.T) {
404 tree, err := Load("a = true\nb = false")
405 assertTree(t, tree, err, map[string]interface{}{
406 "a": true,
407 "b": false,
408 })
409 }
410
411 func TestNestedKeys(t *testing.T) {
412 tree, err := Load("[a.b.c]\nd = 42")
413 assertTree(t, tree, err, map[string]interface{}{
414 "a": map[string]interface{}{
415 "b": map[string]interface{}{
416 "c": map[string]interface{}{
417 "d": int64(42),
418 },
419 },
420 },
421 })
422 }
423
424 func TestNestedQuotedUnicodeKeys(t *testing.T) {
425 tree, err := Load("[ j . \"ʞ\" . l ]\nd = 42")
426 assertTree(t, tree, err, map[string]interface{}{
427 "j": map[string]interface{}{
428 "ʞ": map[string]interface{}{
429 "l": map[string]interface{}{
430 "d": int64(42),
431 },
432 },
433 },
434 })
435
436 tree, err = Load("[ g . h . i ]\nd = 42")
437 assertTree(t, tree, err, map[string]interface{}{
438 "g": map[string]interface{}{
439 "h": map[string]interface{}{
440 "i": map[string]interface{}{
441 "d": int64(42),
442 },
443 },
444 },
445 })
446
447 tree, err = Load("[ d.e.f ]\nk = 42")
448 assertTree(t, tree, err, map[string]interface{}{
449 "d": map[string]interface{}{
450 "e": map[string]interface{}{
451 "f": map[string]interface{}{
452 "k": int64(42),
453 },
454 },
455 },
456 })
457 }
458
459 func TestArrayOne(t *testing.T) {
460 tree, err := Load("a = [1]")
461 assertTree(t, tree, err, map[string]interface{}{
462 "a": []int64{int64(1)},
463 })
464 }
465
466 func TestArrayZero(t *testing.T) {
467 tree, err := Load("a = []")
468 assertTree(t, tree, err, map[string]interface{}{
469 "a": []interface{}{},
470 })
471 }
472
473 func TestArraySimple(t *testing.T) {
474 tree, err := Load("a = [42, 21, 10]")
475 assertTree(t, tree, err, map[string]interface{}{
476 "a": []int64{int64(42), int64(21), int64(10)},
477 })
478
479 tree, _ = Load("a = [42, 21, 10,]")
480 assertTree(t, tree, err, map[string]interface{}{
481 "a": []int64{int64(42), int64(21), int64(10)},
482 })
483 }
484
485 func TestArrayMultiline(t *testing.T) {
486 tree, err := Load("a = [42,\n21, 10,]")
487 assertTree(t, tree, err, map[string]interface{}{
488 "a": []int64{int64(42), int64(21), int64(10)},
489 })
490 }
491
492 func TestArrayNested(t *testing.T) {
493 tree, err := Load("a = [[42, 21], [10]]")
494 assertTree(t, tree, err, map[string]interface{}{
495 "a": [][]int64{{int64(42), int64(21)}, {int64(10)}},
496 })
497 }
498
499 func TestNestedArrayComment(t *testing.T) {
500 tree, err := Load(`
501 someArray = [
502 # does not work
503 ["entry1"]
504 ]`)
505 assertTree(t, tree, err, map[string]interface{}{
506 "someArray": [][]string{{"entry1"}},
507 })
508 }
509
510 func TestNestedEmptyArrays(t *testing.T) {
511 tree, err := Load("a = [[[]]]")
512 assertTree(t, tree, err, map[string]interface{}{
513 "a": [][][]interface{}{{{}}},
514 })
515 }
516
517 func TestArrayNestedStrings(t *testing.T) {
518 tree, err := Load("data = [ [\"gamma\", \"delta\"], [\"Foo\"] ]")
519 assertTree(t, tree, err, map[string]interface{}{
520 "data": [][]string{{"gamma", "delta"}, {"Foo"}},
521 })
522 }
523
524 func TestParseUnknownRvalue(t *testing.T) {
525 _, err := Load("a = !bssss")
526 if err == nil {
527 t.Error("Expecting a parse error")
528 }
529
530 _, err = Load("a = /b")
531 if err == nil {
532 t.Error("Expecting a parse error")
533 }
534 }
535
536 func TestMissingValue(t *testing.T) {
537 _, err := Load("a = ")
538 if err.Error() != "(1, 5): expecting a value" {
539 t.Error("Bad error message:", err.Error())
540 }
541 }
542
543 func TestUnterminatedArray(t *testing.T) {
544 _, err := Load("a = [1,")
545 if err.Error() != "(1, 8): unterminated array" {
546 t.Error("Bad error message:", err.Error())
547 }
548
549 _, err = Load("a = [1")
550 if err.Error() != "(1, 7): unterminated array" {
551 t.Error("Bad error message:", err.Error())
552 }
553
554 _, err = Load("a = [1 2")
555 if err.Error() != "(1, 8): missing comma" {
556 t.Error("Bad error message:", err.Error())
557 }
558 }
559
560 func TestNewlinesInArrays(t *testing.T) {
561 tree, err := Load("a = [1,\n2,\n3]")
562 assertTree(t, tree, err, map[string]interface{}{
563 "a": []int64{int64(1), int64(2), int64(3)},
564 })
565 }
566
567 func TestArrayWithExtraComma(t *testing.T) {
568 tree, err := Load("a = [1,\n2,\n3,\n]")
569 assertTree(t, tree, err, map[string]interface{}{
570 "a": []int64{int64(1), int64(2), int64(3)},
571 })
572 }
573
574 func TestArrayWithExtraCommaComment(t *testing.T) {
575 tree, err := Load("a = [1, # wow\n2, # such items\n3, # so array\n]")
576 assertTree(t, tree, err, map[string]interface{}{
577 "a": []int64{int64(1), int64(2), int64(3)},
578 })
579 }
580
581 func TestSimpleInlineGroup(t *testing.T) {
582 tree, err := Load("key = {a = 42}")
583 assertTree(t, tree, err, map[string]interface{}{
584 "key": map[string]interface{}{
585 "a": int64(42),
586 },
587 })
588 }
589
590 func TestDoubleInlineGroup(t *testing.T) {
591 tree, err := Load("key = {a = 42, b = \"foo\"}")
592 assertTree(t, tree, err, map[string]interface{}{
593 "key": map[string]interface{}{
594 "a": int64(42),
595 "b": "foo",
596 },
597 })
598 }
599
600 func TestNestedInlineGroup(t *testing.T) {
601 tree, err := Load("out = {block0 = {x = 99, y = 100}, block1 = {p = \"999\", q = \"1000\"}}")
602 assertTree(t, tree, err, map[string]interface{}{
603 "out": map[string]interface{}{
604 "block0": map[string]interface{}{
605 "x": int64(99),
606 "y": int64(100),
607 },
608 "block1": map[string]interface{}{
609 "p": "999",
610 "q": "1000",
611 },
612 },
613 })
614 }
615
616 func TestArrayInNestedInlineGroup(t *testing.T) {
617 tree, err := Load(`image = {name = "xxx", palette = {id = 100, colors = ["red", "blue", "green"]}}`)
618 assertTree(t, tree, err, map[string]interface{}{
619 "image": map[string]interface{}{
620 "name": "xxx",
621 "palette": map[string]interface{}{
622 "id": int64(100),
623 "colors": []string{
624 "red",
625 "blue",
626 "green",
627 },
628 },
629 },
630 })
631 }
632
633 func TestExampleInlineGroup(t *testing.T) {
634 tree, err := Load(`name = { first = "Tom", last = "Preston-Werner" }
635 point = { x = 1, y = 2 }`)
636 assertTree(t, tree, err, map[string]interface{}{
637 "name": map[string]interface{}{
638 "first": "Tom",
639 "last": "Preston-Werner",
640 },
641 "point": map[string]interface{}{
642 "x": int64(1),
643 "y": int64(2),
644 },
645 })
646 }
647
648 func TestInlineGroupBareKeysUnderscore(t *testing.T) {
649 tree, err := Load(`foo = { _bar = "buz" }`)
650 assertTree(t, tree, err, map[string]interface{}{
651 "foo": map[string]interface{}{
652 "_bar": "buz",
653 },
654 })
655 }
656
657 func TestInlineGroupBareKeysDash(t *testing.T) {
658 tree, err := Load(`foo = { -bar = "buz" }`)
659 assertTree(t, tree, err, map[string]interface{}{
660 "foo": map[string]interface{}{
661 "-bar": "buz",
662 },
663 })
664 }
665
666 func TestInlineGroupKeyQuoted(t *testing.T) {
667 tree, err := Load(`foo = { "bar" = "buz" }`)
668 assertTree(t, tree, err, map[string]interface{}{
669 "foo": map[string]interface{}{
670 "bar": "buz",
671 },
672 })
673 }
674
675 func TestExampleInlineGroupInArray(t *testing.T) {
676 tree, err := Load(`points = [{ x = 1, y = 2 }]`)
677 assertTree(t, tree, err, map[string]interface{}{
678 "points": []map[string]interface{}{
679 {
680 "x": int64(1),
681 "y": int64(2),
682 },
683 },
684 })
685 }
686
687 func TestInlineTableUnterminated(t *testing.T) {
688 _, err := Load("foo = {")
689 if err.Error() != "(1, 8): unterminated inline table" {
690 t.Error("Bad error message:", err.Error())
691 }
692 }
693
694 func TestInlineTableCommaExpected(t *testing.T) {
695 _, err := Load("foo = {hello = 53 test = foo}")
696 if err.Error() != "(1, 19): unexpected token type in inline table: no value can start with t" {
697 t.Error("Bad error message:", err.Error())
698 }
699 }
700
701 func TestInlineTableCommaStart(t *testing.T) {
702 _, err := Load("foo = {, hello = 53}")
703 if err.Error() != "(1, 8): unexpected token type in inline table: keys cannot contain , character" {
704 t.Error("Bad error message:", err.Error())
705 }
706 }
707
708 func TestInlineTableDoubleComma(t *testing.T) {
709 _, err := Load("foo = {hello = 53,, foo = 17}")
710 if err.Error() != "(1, 19): unexpected token type in inline table: keys cannot contain , character" {
711 t.Error("Bad error message:", err.Error())
712 }
713 }
714
715 func TestInlineTableTrailingComma(t *testing.T) {
716 _, err := Load("foo = {hello = 53, foo = 17,}")
717 if err.Error() != "(1, 28): trailing comma at the end of inline table" {
718 t.Error("Bad error message:", err.Error())
719 }
720 }
721
722 func TestAddKeyToInlineTable(t *testing.T) {
723 _, err := Load("type = { name = \"Nail\" }\ntype.edible = false")
724 if err.Error() != "(2, 1): could not add key or sub-table to exist inline table or its sub-table : type" {
725 t.Error("Bad error message:", err.Error())
726 }
727 }
728
729 func TestAddSubTableToInlineTable(t *testing.T) {
730 _, err := Load("a = { b = \"c\" }\na.d.e = \"f\"")
731 if err.Error() != "(2, 1): could not add key or sub-table to exist inline table or its sub-table : a.d" {
732 t.Error("Bad error message:", err.Error())
733 }
734 }
735
736 func TestAddKeyToSubTableOfInlineTable(t *testing.T) {
737 _, err := Load("a = { b = { c = \"d\" } }\na.b.e = \"f\"")
738 if err.Error() != "(2, 1): could not add key or sub-table to exist inline table or its sub-table : a.b" {
739 t.Error("Bad error message:", err.Error())
740 }
741 }
742
743 func TestReDefineInlineTable(t *testing.T) {
744 _, err := Load("a = { b = \"c\" }\n[a]\n d = \"e\"")
745 if err.Error() != "(2, 2): could not re-define exist inline table or its sub-table : a" {
746 t.Error("Bad error message:", err.Error())
747 }
748 }
749
750 func TestDuplicateGroups(t *testing.T) {
751 _, err := Load("[foo]\na=2\n[foo]b=3")
752 if err.Error() != "(3, 2): duplicated tables" {
753 t.Error("Bad error message:", err.Error())
754 }
755 }
756
757 func TestDuplicateKeys(t *testing.T) {
758 _, err := Load("foo = 2\nfoo = 3")
759 if err.Error() != "(2, 1): The following key was defined twice: foo" {
760 t.Error("Bad error message:", err.Error())
761 }
762 }
763
764 func TestEmptyIntermediateTable(t *testing.T) {
765 _, err := Load("[foo..bar]")
766 if err.Error() != "(1, 2): invalid table array key: expecting key part after dot" {
767 t.Error("Bad error message:", err.Error())
768 }
769 }
770
771 func TestImplicitDeclarationBefore(t *testing.T) {
772 tree, err := Load("[a.b.c]\nanswer = 42\n[a]\nbetter = 43")
773 assertTree(t, tree, err, map[string]interface{}{
774 "a": map[string]interface{}{
775 "b": map[string]interface{}{
776 "c": map[string]interface{}{
777 "answer": int64(42),
778 },
779 },
780 "better": int64(43),
781 },
782 })
783 }
784
785 func TestFloatsWithoutLeadingZeros(t *testing.T) {
786 _, err := Load("a = .42")
787 if err.Error() != "(1, 5): cannot start float with a dot" {
788 t.Error("Bad error message:", err.Error())
789 }
790
791 _, err = Load("a = -.42")
792 if err.Error() != "(1, 5): cannot start float with a dot" {
793 t.Error("Bad error message:", err.Error())
794 }
795 }
796
797 func TestMissingFile(t *testing.T) {
798 _, err := LoadFile("foo.toml")
799 if err.Error() != "open foo.toml: no such file or directory" &&
800 err.Error() != "open foo.toml: The system cannot find the file specified." {
801 t.Error("Bad error message:", err.Error())
802 }
803 }
804
805 func TestParseFile(t *testing.T) {
806 tree, err := LoadFile("example.toml")
807
808 assertTree(t, tree, err, map[string]interface{}{
809 "title": "TOML Example",
810 "owner": map[string]interface{}{
811 "name": "Tom Preston-Werner",
812 "organization": "GitHub",
813 "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.",
814 "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC),
815 },
816 "database": map[string]interface{}{
817 "server": "192.168.1.1",
818 "ports": []int64{8001, 8001, 8002},
819 "connection_max": 5000,
820 "enabled": true,
821 },
822 "servers": map[string]interface{}{
823 "alpha": map[string]interface{}{
824 "ip": "10.0.0.1",
825 "dc": "eqdc10",
826 },
827 "beta": map[string]interface{}{
828 "ip": "10.0.0.2",
829 "dc": "eqdc10",
830 },
831 },
832 "clients": map[string]interface{}{
833 "data": []interface{}{
834 []string{"gamma", "delta"},
835 []int64{1, 2},
836 },
837 "score": 4e-08,
838 },
839 })
840 }
841
842 func TestParseFileCRLF(t *testing.T) {
843 tree, err := LoadFile("example-crlf.toml")
844
845 assertTree(t, tree, err, map[string]interface{}{
846 "title": "TOML Example",
847 "owner": map[string]interface{}{
848 "name": "Tom Preston-Werner",
849 "organization": "GitHub",
850 "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.",
851 "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC),
852 },
853 "database": map[string]interface{}{
854 "server": "192.168.1.1",
855 "ports": []int64{8001, 8001, 8002},
856 "connection_max": 5000,
857 "enabled": true,
858 },
859 "servers": map[string]interface{}{
860 "alpha": map[string]interface{}{
861 "ip": "10.0.0.1",
862 "dc": "eqdc10",
863 },
864 "beta": map[string]interface{}{
865 "ip": "10.0.0.2",
866 "dc": "eqdc10",
867 },
868 },
869 "clients": map[string]interface{}{
870 "data": []interface{}{
871 []string{"gamma", "delta"},
872 []int64{1, 2},
873 },
874 "score": 4e-08,
875 },
876 })
877 }
878
879 func TestParseKeyGroupArray(t *testing.T) {
880 tree, err := Load("[[foo.bar]] a = 42\n[[foo.bar]] a = 69")
881 assertTree(t, tree, err, map[string]interface{}{
882 "foo": map[string]interface{}{
883 "bar": []map[string]interface{}{
884 {"a": int64(42)},
885 {"a": int64(69)},
886 },
887 },
888 })
889 }
890
891 func TestParseKeyGroupArrayUnfinished(t *testing.T) {
892 _, err := Load("[[foo.bar]\na = 42")
893 if err.Error() != "(1, 10): was expecting token [[, but got unclosed table array key instead" {
894 t.Error("Bad error message:", err.Error())
895 }
896
897 _, err = Load("[[foo.[bar]\na = 42")
898 if err.Error() != "(1, 3): unexpected token table array key cannot contain ']', was expecting a table array key" {
899 t.Error("Bad error message:", err.Error())
900 }
901 }
902
903 func TestParseKeyGroupArrayQueryExample(t *testing.T) {
904 tree, err := Load(`
905 [[book]]
906 title = "The Stand"
907 author = "Stephen King"
908 [[book]]
909 title = "For Whom the Bell Tolls"
910 author = "Ernest Hemmingway"
911 [[book]]
912 title = "Neuromancer"
913 author = "William Gibson"
914 `)
915
916 assertTree(t, tree, err, map[string]interface{}{
917 "book": []map[string]interface{}{
918 {"title": "The Stand", "author": "Stephen King"},
919 {"title": "For Whom the Bell Tolls", "author": "Ernest Hemmingway"},
920 {"title": "Neuromancer", "author": "William Gibson"},
921 },
922 })
923 }
924
925 func TestParseKeyGroupArraySpec(t *testing.T) {
926 tree, err := Load("[[fruit]]\n name=\"apple\"\n [fruit.physical]\n color=\"red\"\n shape=\"round\"\n [[fruit]]\n name=\"banana\"")
927 assertTree(t, tree, err, map[string]interface{}{
928 "fruit": []map[string]interface{}{
929 {"name": "apple", "physical": map[string]interface{}{"color": "red", "shape": "round"}},
930 {"name": "banana"},
931 },
932 })
933 }
934
935 func TestTomlValueStringRepresentation(t *testing.T) {
936 for idx, item := range []struct {
937 Value interface{}
938 Expect string
939 }{
940 {int64(12345), "12345"},
941 {uint64(50), "50"},
942 {float64(123.45), "123.45"},
943 {true, "true"},
944 {"hello world", "\"hello world\""},
945 {"\b\t\n\f\r\"\\", "\"\\b\\t\\n\\f\\r\\\"\\\\\""},
946 {"\x05", "\"\\u0005\""},
947 {time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), "1979-05-27T07:32:00Z"},
948 {[]interface{}{"gamma", "delta"}, "[\"gamma\", \"delta\"]"},
949 {nil, ""},
950 } {
951 result, err := tomlValueStringRepresentation(item.Value, "", "", OrderAlphabetical, false)
952 if err != nil {
953 t.Errorf("Test %d - unexpected error: %s", idx, err)
954 }
955 if result != item.Expect {
956 t.Errorf("Test %d - got '%s', expected '%s'", idx, result, item.Expect)
957 }
958 }
959 }
960
961 func TestToStringMapStringString(t *testing.T) {
962 tree, err := TreeFromMap(map[string]interface{}{"m": map[string]interface{}{"v": "abc"}})
963 if err != nil {
964 t.Fatalf("unexpected error: %s", err)
965 }
966 want := "\n[m]\n v = \"abc\"\n"
967 got := tree.String()
968
969 if got != want {
970 t.Errorf("want:\n%q\ngot:\n%q", want, got)
971 }
972 }
973
974 func assertPosition(t *testing.T, text string, ref map[string]Position) {
975 tree, err := Load(text)
976 if err != nil {
977 t.Errorf("Error loading document text: `%v`", text)
978 t.Errorf("Error: %v", err)
979 }
980 for path, pos := range ref {
981 testPos := tree.GetPosition(path)
982 if testPos.Invalid() {
983 t.Errorf("Failed to query tree path or path has invalid position: %s", path)
984 } else if pos != testPos {
985 t.Errorf("Expected position %v, got %v instead", pos, testPos)
986 }
987 }
988 }
989
990 func TestDocumentPositions(t *testing.T) {
991 assertPosition(t,
992 "[foo]\nbar=42\nbaz=69",
993 map[string]Position{
994 "": {1, 1},
995 "foo": {1, 1},
996 "foo.bar": {2, 1},
997 "foo.baz": {3, 1},
998 })
999 }
1000
1001 func TestDocumentPositionsWithSpaces(t *testing.T) {
1002 assertPosition(t,
1003 " [foo]\n bar=42\n baz=69",
1004 map[string]Position{
1005 "": {1, 1},
1006 "foo": {1, 3},
1007 "foo.bar": {2, 3},
1008 "foo.baz": {3, 3},
1009 })
1010 }
1011
1012 func TestDocumentPositionsWithGroupArray(t *testing.T) {
1013 assertPosition(t,
1014 "[[foo]]\nbar=42\nbaz=69",
1015 map[string]Position{
1016 "": {1, 1},
1017 "foo": {1, 1},
1018 "foo.bar": {2, 1},
1019 "foo.baz": {3, 1},
1020 })
1021 }
1022
1023 func TestNestedTreePosition(t *testing.T) {
1024 assertPosition(t,
1025 "[foo.bar]\na=42\nb=69",
1026 map[string]Position{
1027 "": {1, 1},
1028 "foo": {1, 1},
1029 "foo.bar": {1, 1},
1030 "foo.bar.a": {2, 1},
1031 "foo.bar.b": {3, 1},
1032 })
1033 }
1034
1035 func TestInvalidGroupArray(t *testing.T) {
1036 _, err := Load("[table#key]\nanswer = 42")
1037 if err == nil {
1038 t.Error("Should error")
1039 }
1040
1041 _, err = Load("[foo.[bar]\na = 42")
1042 if err.Error() != "(1, 2): unexpected token table key cannot contain ']', was expecting a table key" {
1043 t.Error("Bad error message:", err.Error())
1044 }
1045 }
1046
1047 func TestDoubleEqual(t *testing.T) {
1048 _, err := Load("foo= = 2")
1049 if err.Error() != "(1, 6): cannot have multiple equals for the same key" {
1050 t.Error("Bad error message:", err.Error())
1051 }
1052 }
1053
1054 func TestGroupArrayReassign(t *testing.T) {
1055 _, err := Load("[hello]\n[[hello]]")
1056 if err.Error() != "(2, 3): key \"hello\" is already assigned and not of type table array" {
1057 t.Error("Bad error message:", err.Error())
1058 }
1059 }
1060
1061 func TestInvalidFloatParsing(t *testing.T) {
1062 _, err := Load("a=1e_2")
1063 if err.Error() != "(1, 3): invalid use of _ in number" {
1064 t.Error("Bad error message:", err.Error())
1065 }
1066
1067 _, err = Load("a=1e2_")
1068 if err.Error() != "(1, 3): invalid use of _ in number" {
1069 t.Error("Bad error message:", err.Error())
1070 }
1071
1072 _, err = Load("a=1__2")
1073 if err.Error() != "(1, 3): invalid use of _ in number" {
1074 t.Error("Bad error message:", err.Error())
1075 }
1076
1077 _, err = Load("a=_1_2")
1078 if err.Error() != "(1, 3): no value can start with _" {
1079 t.Error("Bad error message:", err.Error())
1080 }
1081 }
1082
1083 func TestMapKeyIsNum(t *testing.T) {
1084 _, err := Load("table={2018=1,2019=2}")
1085 if err != nil {
1086 t.Error("should be passed")
1087 }
1088 _, err = Load(`table={"2018"=1,"2019"=2}`)
1089 if err != nil {
1090 t.Error("should be passed")
1091 }
1092 }
1093
1094 func TestInvalidKeyInlineTable(t *testing.T) {
1095 _, err := Load("table={invalid..key = 1}")
1096 if err.Error() != "(1, 8): invalid key: expecting key part after dot" {
1097 t.Error("Bad error message:", err.Error())
1098 }
1099 }
1100
1101 func TestDottedKeys(t *testing.T) {
1102 tree, err := Load(`
1103 name = "Orange"
1104 physical.color = "orange"
1105 physical.shape = "round"
1106 site."google.com" = true`)
1107
1108 assertTree(t, tree, err, map[string]interface{}{
1109 "name": "Orange",
1110 "physical": map[string]interface{}{
1111 "color": "orange",
1112 "shape": "round",
1113 },
1114 "site": map[string]interface{}{
1115 "google.com": true,
1116 },
1117 })
1118 }
1119
1120 func TestInvalidDottedKeyEmptyGroup(t *testing.T) {
1121 _, err := Load(`a..b = true`)
1122 if err == nil {
1123 t.Fatal("should return an error")
1124 }
1125 if err.Error() != "(1, 1): invalid key: expecting key part after dot" {
1126 t.Fatalf("invalid error message: %s", err)
1127 }
1128 }
1129
1130 func TestAccidentalNewlines(t *testing.T) {
1131 expected := "The quick brown fox jumps over the lazy dog."
1132 tree, err := Load(`str1 = "The quick brown fox jumps over the lazy dog."
1133
1134 str2 = """
1135 The quick brown \
1136
1137
1138 fox jumps over \
1139 the lazy dog."""
1140
1141 str3 = """\
1142 The quick brown \` + " " + `
1143 fox jumps over \` + " " + `
1144 the lazy dog.\` + " " + `
1145 """`)
1146 if err != nil {
1147 t.Fatalf("unexpected error: %v", err)
1148 }
1149
1150 got := tree.Get("str1")
1151 if got != expected {
1152 t.Errorf("expected '%s', got '%s'", expected, got)
1153 }
1154
1155 got = tree.Get("str2")
1156 if got != expected {
1157 t.Errorf("expected '%s', got '%s'", expected, got)
1158 }
1159
1160 got = tree.Get("str3")
1161 if got != expected {
1162 t.Errorf("expected '%s', got '%s'", expected, got)
1163 }
1164 }
1165
1166 func TestUint(t *testing.T) {
1167 tree, err := Load("hello = 18446744073709551615")
1168 assertTree(t, tree, err, map[string]interface{}{
1169 "hello": uint64(math.MaxUint64),
1170 })
1171 }
1172
View as plain text