Added additional parser tests
diff --git a/jpath/parser_test.go b/jpath/parser_test.go index 2e16a2f..6daba44 100644 --- a/jpath/parser_test.go +++ b/jpath/parser_test.go
@@ -19,7 +19,7 @@ } path := parse(flow) result := processPath(path, tree) - assertValue(t, result, ref, "") + assertValue(t, result, ref, "((" + query + ")) -> ") } func assertValue(t *testing.T, result, ref interface{}, location string) { @@ -84,387 +84,152 @@ }) } -/* -// NOTE: from the BurntSushi test suite -// NOTE: this test is pure evil due to the embedded '.' -func TestSpecialKV(t *testing.T) { - tree, err := Load("~!@#$^&*()_+-`1234567890[]\\|/?><.,;: = 1") - assertTree(t, tree, err, map[string]interface{}{ - "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:": int64(1), - }) +func TestQueryKey(t *testing.T) { + assertQuery(t, + "[foo]\na = 42", + "$.foo.a", + []interface{}{ + int64(42), + }) } -func TestSimpleNumbers(t *testing.T) { - tree, err := Load("a = +42\nb = -21\nc = +4.2\nd = -2.1") - assertTree(t, tree, err, map[string]interface{}{ - "a": int64(42), - "b": int64(-21), - "c": float64(4.2), - "d": float64(-2.1), - }) +func TestQueryKeyString(t *testing.T) { + assertQuery(t, + "[foo]\na = 42", + "$.foo['a']", + []interface{}{ + int64(42), + }) } -func TestSimpleDate(t *testing.T) { - tree, err := Load("a = 1979-05-27T07:32:00Z") - assertTree(t, tree, err, map[string]interface{}{ - "a": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), - }) +func TestQueryIndex(t *testing.T) { + assertQuery(t, + "[foo]\na = [1,2,3,4,5,6,7,8,9,0]", + "$.foo.a[0]", + []interface{}{ + int64(1), + }) } -func TestSimpleString(t *testing.T) { - tree, err := Load("a = \"hello world\"") - assertTree(t, tree, err, map[string]interface{}{ - "a": "hello world", - }) +func TestQuerySliceRange(t *testing.T) { + assertQuery(t, + "[foo]\na = [1,2,3,4,5,6,7,8,9,0]", + "$.foo.a[0:5]", + []interface{}{ + int64(1), + int64(2), + int64(3), + int64(4), + int64(5), + }) } -func TestStringEscapables(t *testing.T) { - tree, err := Load("a = \"a \\n b\"") - assertTree(t, tree, err, map[string]interface{}{ - "a": "a \n b", - }) - - tree, err = Load("a = \"a \\t b\"") - assertTree(t, tree, err, map[string]interface{}{ - "a": "a \t b", - }) - - tree, err = Load("a = \"a \\r b\"") - assertTree(t, tree, err, map[string]interface{}{ - "a": "a \r b", - }) - - tree, err = Load("a = \"a \\\\ b\"") - assertTree(t, tree, err, map[string]interface{}{ - "a": "a \\ b", - }) +func TestQuerySliceStep(t *testing.T) { + assertQuery(t, + "[foo]\na = [1,2,3,4,5,6,7,8,9,0]", + "$.foo.a[0:5:2]", + []interface{}{ + int64(1), + int64(3), + int64(5), + }) } -func TestBools(t *testing.T) { - tree, err := Load("a = true\nb = false") - assertTree(t, tree, err, map[string]interface{}{ - "a": true, - "b": false, - }) +func TestQueryAny(t *testing.T) { + assertQuery(t, + "[foo.bar]\na=1\nb=2\n[foo.baz]\na=3\nb=4", + "$.foo.*", + []interface{}{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + }) +} +func TestQueryUnionSimple(t *testing.T) { + assertQuery(t, + "[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", + "$.*[bar,foo]", + []interface{}{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, + }) } -func TestNestedKeys(t *testing.T) { - tree, err := Load("[a.b.c]\nd = 42") - assertTree(t, tree, err, map[string]interface{}{ - "a": map[string]interface{}{ - "b": map[string]interface{}{ - "c": map[string]interface{}{ - "d": int64(42), - }, - }, - }, - }) +func TestQueryRecursionAll(t *testing.T) { + assertQuery(t, + "[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", + "$..*", + []interface{}{ + map[string]interface{}{ + "bar": map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + }, + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + int64(1), + int64(2), + map[string]interface{}{ + "foo": map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + }, + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + int64(3), + int64(4), + map[string]interface{}{ + "foo": map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, + }, + map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, + int64(5), + int64(6), + }) } -func TestArrayOne(t *testing.T) { - tree, err := Load("a = [1]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(1)}, - }) +func TestQueryRecursionUnionSimple(t *testing.T) { + assertQuery(t, + "[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", + "$..['foo','bar']", + []interface{}{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, + }) } - -func TestArrayZero(t *testing.T) { - tree, err := Load("a = []") - assertTree(t, tree, err, map[string]interface{}{ - "a": []interface{}{}, - }) -} - -func TestArraySimple(t *testing.T) { - tree, err := Load("a = [42, 21, 10]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(42), int64(21), int64(10)}, - }) - - tree, _ = Load("a = [42, 21, 10,]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(42), int64(21), int64(10)}, - }) -} - -func TestArrayMultiline(t *testing.T) { - tree, err := Load("a = [42,\n21, 10,]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(42), int64(21), int64(10)}, - }) -} - -func TestArrayNested(t *testing.T) { - tree, err := Load("a = [[42, 21], [10]]") - assertTree(t, tree, err, map[string]interface{}{ - "a": [][]int64{[]int64{int64(42), int64(21)}, []int64{int64(10)}}, - }) -} - -func TestNestedEmptyArrays(t *testing.T) { - tree, err := Load("a = [[[]]]") - assertTree(t, tree, err, map[string]interface{}{ - "a": [][][]interface{}{[][]interface{}{[]interface{}{}}}, - }) -} - -func TestArrayMixedTypes(t *testing.T) { - _, err := Load("a = [42, 16.0]") - if err.Error() != "(1, 10): mixed types in array" { - t.Error("Bad error message:", err.Error()) - } - - _, err = Load("a = [42, \"hello\"]") - if err.Error() != "(1, 11): mixed types in array" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestArrayNestedStrings(t *testing.T) { - tree, err := Load("data = [ [\"gamma\", \"delta\"], [\"Foo\"] ]") - assertTree(t, tree, err, map[string]interface{}{ - "data": [][]string{[]string{"gamma", "delta"}, []string{"Foo"}}, - }) -} - -func TestMissingValue(t *testing.T) { - _, err := Load("a = ") - if err.Error() != "(1, 4): expecting a value" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestUnterminatedArray(t *testing.T) { - _, err := Load("a = [1,") - if err.Error() != "(1, 8): unterminated array" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestNewlinesInArrays(t *testing.T) { - tree, err := Load("a = [1,\n2,\n3]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(1), int64(2), int64(3)}, - }) -} - -func TestArrayWithExtraComma(t *testing.T) { - tree, err := Load("a = [1,\n2,\n3,\n]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(1), int64(2), int64(3)}, - }) -} - -func TestArrayWithExtraCommaComment(t *testing.T) { - tree, err := Load("a = [1, # wow\n2, # such items\n3, # so array\n]") - assertTree(t, tree, err, map[string]interface{}{ - "a": []int64{int64(1), int64(2), int64(3)}, - }) -} - -func TestDuplicateGroups(t *testing.T) { - _, err := Load("[foo]\na=2\n[foo]b=3") - if err.Error() != "(3, 2): duplicated tables" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestDuplicateKeys(t *testing.T) { - _, err := Load("foo = 2\nfoo = 3") - if err.Error() != "(2, 1): The following key was defined twice: foo" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestEmptyIntermediateTable(t *testing.T) { - _, err := Load("[foo..bar]") - if err.Error() != "(1, 2): empty intermediate table" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestImplicitDeclarationBefore(t *testing.T) { - tree, err := Load("[a.b.c]\nanswer = 42\n[a]\nbetter = 43") - assertTree(t, tree, err, map[string]interface{}{ - "a": map[string]interface{}{ - "b": map[string]interface{}{ - "c": map[string]interface{}{ - "answer": int64(42), - }, - }, - "better": int64(43), - }, - }) -} - -func TestFloatsWithoutLeadingZeros(t *testing.T) { - _, err := Load("a = .42") - if err.Error() != "(1, 4): cannot start float with a dot" { - t.Error("Bad error message:", err.Error()) - } - - _, err = Load("a = -.42") - if err.Error() != "(1, 5): cannot start float with a dot" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestMissingFile(t *testing.T) { - _, err := LoadFile("foo.toml") - if err.Error() != "open foo.toml: no such file or directory" { - t.Error("Bad error message:", err.Error()) - } -} - -func TestParseFile(t *testing.T) { - tree, err := LoadFile("example.toml") - - assertTree(t, tree, err, map[string]interface{}{ - "title": "TOML Example", - "owner": map[string]interface{}{ - "name": "Tom Preston-Werner", - "organization": "GitHub", - "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.", - "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), - }, - "database": map[string]interface{}{ - "server": "192.168.1.1", - "ports": []int64{8001, 8001, 8002}, - "connection_max": 5000, - "enabled": true, - }, - "servers": map[string]interface{}{ - "alpha": map[string]interface{}{ - "ip": "10.0.0.1", - "dc": "eqdc10", - }, - "beta": map[string]interface{}{ - "ip": "10.0.0.2", - "dc": "eqdc10", - }, - }, - "clients": map[string]interface{}{ - "data": []interface{}{ - []string{"gamma", "delta"}, - []int64{1, 2}, - }, - }, - }) -} - -func TestParseKeyGroupArray(t *testing.T) { - tree, err := Load("[[foo.bar]] a = 42\n[[foo.bar]] a = 69") - assertTree(t, tree, err, map[string]interface{}{ - "foo": map[string]interface{}{ - "bar": []map[string]interface{}{ - {"a": int64(42)}, - {"a": int64(69)}, - }, - }, - }) -} - -func TestParseKeyGroupArraySpec(t *testing.T) { - tree, err := Load("[[fruit]]\n name=\"apple\"\n [fruit.physical]\n color=\"red\"\n shape=\"round\"\n [[fruit]]\n name=\"banana\"") - assertTree(t, tree, err, map[string]interface{}{ - "fruit": []map[string]interface{}{ - {"name": "apple", "physical": map[string]interface{}{"color": "red", "shape": "round"}}, - {"name": "banana"}, - }, - }) -} - -func TestToTomlValue(t *testing.T) { - for idx, item := range []struct { - Value interface{} - Expect string - }{ - {int64(12345), "12345"}, - {float64(123.45), "123.45"}, - {bool(true), "true"}, - {"hello world", "\"hello world\""}, - {"\b\t\n\f\r\"\\", "\"\\b\\t\\n\\f\\r\\\"\\\\\""}, - {"\x05", "\"\\u0005\""}, - {time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), - "1979-05-27T07:32:00Z"}, - {[]interface{}{"gamma", "delta"}, - "[\n \"gamma\",\n \"delta\",\n]"}, - } { - result := toTomlValue(item.Value, 0) - if result != item.Expect { - t.Errorf("Test %d - got '%s', expected '%s'", idx, result, item.Expect) - } - } -} - -func TestToString(t *testing.T) { - tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n") - if err != nil { - t.Errorf("Test failed to parse: %v", err) - return - } - result := tree.ToString() - expected := "\n[foo]\n\n [[foo.bar]]\n a = 42\n\n [[foo.bar]]\n a = 69\n" - if result != expected { - t.Errorf("Expected got '%s', expected '%s'", result, expected) - } -} - -func assertPosition(t *testing.T, text string, ref map[string]Position) { - tree, err := Load(text) - if err != nil { - t.Errorf("Error loading document text: `%v`", text) - t.Errorf("Error: %v", err) - } - for path, pos := range ref { - testPos := tree.GetPosition(path) - if testPos.Invalid() { - t.Errorf("Failed to query tree path: %s", path) - } else if pos != testPos { - t.Errorf("Expected position %v, got %v instead", pos, testPos) - } - } -} - -func TestDocumentPositions(t *testing.T) { - assertPosition(t, - "[foo]\nbar=42\nbaz=69", - map[string]Position{ - "foo": Position{1, 1}, - "foo.bar": Position{2, 1}, - "foo.baz": Position{3, 1}, - }) -} - -func TestDocumentPositionsWithSpaces(t *testing.T) { - assertPosition(t, - " [foo]\n bar=42\n baz=69", - map[string]Position{ - "foo": Position{1, 3}, - "foo.bar": Position{2, 3}, - "foo.baz": Position{3, 3}, - }) -} - -func TestDocumentPositionsWithGroupArray(t *testing.T) { - assertPosition(t, - "[[foo]]\nbar=42\nbaz=69", - map[string]Position{ - "foo": Position{1, 1}, - "foo.bar": Position{2, 1}, - "foo.baz": Position{3, 1}, - }) -} - -func TestDocumentPositionsEmptyPath(t *testing.T) { - text := "[foo]\nbar=42\nbaz=69" - tree, err := Load(text) - if err != nil { - t.Errorf("Error loading document text: `%v`", text) - t.Errorf("Error: %v", err) - } - if pos := tree.GetPosition(""); !pos.Invalid() { - t.Errorf("Valid position was returned for empty path") - } -} -*/