| # Tests are groups of three lines: program, input, expected output |
| # Blank lines and lines starting with # are ignored |
| |
| # |
| # Simple value tests to check parser. Input is irrelevant |
| # |
| |
| true |
| null |
| true |
| |
| false |
| null |
| false |
| |
| null |
| 42 |
| null |
| |
| 1 |
| null |
| 1 |
| |
| # FIXME: much more number testing needed |
| |
| {} |
| null |
| {} |
| |
| [] |
| null |
| [] |
| |
| # We test escapes by matching them against Unicode codepoints |
| # FIXME: more tests needed for weird unicode stuff (e.g. utf16 pairs) |
| "Aa\r\n\t\b\f\u03bc" |
| null |
| "Aa\u000d\u000a\u0009\u0008\u000c\u03bc" |
| |
| . |
| "Aa\r\n\t\b\f\u03bc" |
| "Aa\u000d\u000a\u0009\u0008\u000c\u03bc" |
| |
| "inter\("pol" + "ation")" |
| null |
| "interpolation" |
| |
| # |
| # Dictionary construction syntax |
| # |
| |
| {a: 1} |
| null |
| {"a":1} |
| |
| {a,b,(.d):.a,e:.b} |
| {"a":1, "b":2, "c":3, "d":"c"} |
| {"a":1, "b":2, "c":1, "e":2} |
| |
| # |
| # Field access, piping |
| # |
| |
| .foo |
| {"foo": 42, "bar": 43} |
| 42 |
| |
| .foo | .bar |
| {"foo": {"bar": 42}, "bar": "badvalue"} |
| 42 |
| |
| .foo.bar |
| {"foo": {"bar": 42}, "bar": "badvalue"} |
| 42 |
| |
| .foo_bar |
| {"foo_bar": 2} |
| 2 |
| |
| .["foo"].bar |
| {"foo": {"bar": 42}, "bar": "badvalue"} |
| 42 |
| |
| |
| # |
| # Multiple outputs, iteration |
| # |
| |
| .[] |
| [1,2,3] |
| 1 |
| 2 |
| 3 |
| |
| 1,1 |
| [] |
| 1 |
| 1 |
| |
| [.] |
| [2] |
| [[2]] |
| |
| [[2]] |
| [3] |
| [[2]] |
| |
| [{}] |
| [2] |
| [{}] |
| |
| [.[]] |
| ["a"] |
| ["a"] |
| |
| [(.,1),((.,.[]),(2,3))] |
| ["a","b"] |
| [["a","b"],1,["a","b"],"a","b",2,3] |
| |
| [([5,5][]),.,.[]] |
| [1,2,3] |
| [5,5,[1,2,3],1,2,3] |
| |
| {x: (1,2)},{x:3} | .x |
| null |
| 1 |
| 2 |
| 3 |
| |
| # |
| # Variables |
| # |
| |
| 1 as $x | 2 as $y | [$x,$y,$x] |
| null |
| [1,2,1] |
| |
| [1,2,3][] as $x | [[4,5,6,7][$x]] |
| null |
| [5] |
| [6] |
| [7] |
| |
| 1 as $x | [$x,$x,$x as $x | $x] |
| null |
| [1,1,1] |
| |
| # [.,(.[] | {x:.},.),.,.[]] |
| |
| # |
| # Builtin functions |
| # |
| |
| 1+1 |
| null |
| 2 |
| |
| 1+1 |
| "wtasdf" |
| 2.0 |
| |
| 1e+0+0.001e3 |
| "I wonder what this will be?" |
| 20e-1 |
| |
| .+4 |
| 15 |
| 19.0 |
| |
| [1,2,3] + [.] |
| null |
| [1,2,3,null] |
| |
| {"a":1} + {"b":2} + {"c":3} |
| "asdfasdf" |
| {"a":1, "b":2, "c":3} |
| |
| "asdf" + "jkl;" + . + . + . |
| "some string" |
| "asdfjkl;some stringsome stringsome string" |
| |
| "\u0000\u0020\u0000" + . |
| "\u0000\u0020\u0000" |
| "\u0000 \u0000\u0000 \u0000" |
| |
| 42 - . |
| 11 |
| 31 |
| |
| [1,2,3,4,1] - [.,3] |
| 1 |
| [2,4] |
| |
| [10 * 20, 20 / .] |
| 4 |
| [200, 5] |
| |
| 1 + 2 * 2 + 10 / 2 |
| null |
| 10 |
| |
| [16 / 4 / 2, 16 / 4 * 2, 16 - 4 - 2, 16 - 4 + 2] |
| null |
| [2, 8, 10, 14] |
| |
| 1 + tonumber + ("10" | tonumber) |
| 4 |
| 15 |
| |
| [{"a":42},.object,10,.num,false,true,null,"b",[1,4]] | .[] as $x | [$x == .[]] |
| {"object": {"a":42}, "num":10.0} |
| [true, true, false, false, false, false, false, false, false] |
| [true, true, false, false, false, false, false, false, false] |
| [false, false, true, true, false, false, false, false, false] |
| [false, false, true, true, false, false, false, false, false] |
| [false, false, false, false, true, false, false, false, false] |
| [false, false, false, false, false, true, false, false, false] |
| [false, false, false, false, false, false, true, false, false] |
| [false, false, false, false, false, false, false, true, false] |
| [false, false, false, false, false, false, false, false, true ] |
| |
| [.[] | length] |
| [[], {}, [1,2], {"a":42}, "asdf"] |
| [0, 0, 2, 1, 4] |
| |
| map(keys) |
| [{}, {"abcd":1,"abc":2,"abcde":3}, {"x":1, "z": 3, "y":2}] |
| [[], ["abc","abcd","abcde"], ["x","y","z"]] |
| |
| [1,2,empty,3,empty,4] |
| null |
| [1,2,3,4] |
| |
| map(add) |
| [[], [1,2,3], ["a","b","c"], [[3],[4,5],[6]], [{"a":1}, {"b":2}, {"a":3}]] |
| [null, 6, "abc", [3,4,5,6], {"a":3, "b": 2}] |
| |
| # |
| # User-defined functions |
| # Oh god. |
| # |
| |
| def f: . + 1; def g: def g: . + 100; f | g | f; (f | g), g |
| 3.0 |
| 106.0 |
| 105.0 |
| |
| def f: (1000,2000); f |
| 123412345 |
| 1000 |
| 2000 |
| |
| ([1,2] + [4,5]) |
| [1,2,3] |
| [1,2,4,5] |
| |
| true |
| [1] |
| true |
| |
| null,1,null |
| "hello" |
| null |
| 1 |
| null |
| |
| [1,2,3] |
| [5,6] |
| [1,2,3] |
| |
| def f(x): x | x; f([.], . + [42]) |
| [1,2,3] |
| [[[1,2,3]]] |
| [[1,2,3],42] |
| [[1,2,3,42]] |
| [1,2,3,42,42] |
| |
| # test closures and lexical scoping |
| def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x | f($x,$x+x); g($x) |
| "more testing" |
| [1,100,2100.0,100,2100.0] |
| |
| # test backtracking through function calls and returns |
| # this test is *evil* |
| [[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f] |
| 999999999 |
| [[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]] |
| |
| # test recursion |
| def fac: if . == 1 then 1 else . * (. - 1 | fac) end; [.[] | fac] |
| [1,2,3,4] |
| [1,2,6,24] |
| |
| |
| # |
| # Assignment |
| # |
| .message = "goodbye" |
| {"message": "hello"} |
| {"message": "goodbye"} |
| |
| .foo = .bar |
| {"bar":42} |
| {"foo":42, "bar":42} |
| |
| .foo |= .+1 |
| {"foo": 42} |
| {"foo": 43} |
| |
| .[] += 2, .[] *= 2, .[] -= 2, .[] /= 2 |
| [1,3,5] |
| [3,5,7] |
| [2,6,10] |
| [-1,1,3] |
| [0.5, 1.5, 2.5] |
| |
| .[0].a |= {"old":., "new":(.+1)} |
| [{"a":1,"b":2}] |
| [{"a":{"old":1, "new":2},"b":2}] |
| |
| def inc(x): x |= .+1; inc(.[].a) |
| [{"a":1,"b":2},{"a":2,"b":4},{"a":7,"b":8}] |
| [{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}] |
| |
| .[2][3] = 1 |
| [4] |
| [4, null, [null, null, null, 1]] |
| |
| .foo[2].bar = 1 |
| {"foo":[11], "bar":42} |
| {"foo":[11,null,{"bar":1}], "bar":42} |
| |
| # |
| # Conditionals |
| # |
| |
| [.[] | if .foo then "yep" else "nope" end] |
| [{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}] |
| ["yep","yep","yep","yep","nope","nope","yep","nope"] |
| |
| [.[] | if .baz then "strange" elif .foo then "yep" else "nope" end] |
| [{"foo":0},{"foo":1},{"foo":[]},{"foo":true},{"foo":false},{"foo":null},{"foo":"foo"},{}] |
| ["yep","yep","yep","yep","nope","nope","yep","nope"] |
| |
| |
| # FIXME: define/test behaviour of 'if (.foo,.bar) then A else B end' |
| |
| [.[] | [.foo[] // .bar]] |
| [{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}] |
| [[1,2], [1], [3], [42], [41]] |
| |
| # FIXME: behaviour of update operators |
| # .[] //= .[0] |
| # ["hello",true,false,[false],null] |
| # ["hello",true,"hello",[false],"hello"] |
| |
| .[] | [.[0] and .[1], .[0] or .[1]] |
| [[true,[]], [false,1], [42,null], [null,false]] |
| [true,true] |
| [false,true] |
| [false,true] |
| [false,false] |
| |
| [.[] | not] |
| [1,0,false,null,true,"hello"] |
| [false,false,true,true,false,false] |
| |
| # Check numeric comparison binops |
| [10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20] |
| {} |
| [true,false,false,false,false,true] |
| |
| [10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20] |
| {} |
| [true,true,false,false,true,true] |