# 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 [] # The input line starts with a 0xFEFF (byte order mark) codepoint # No, there is no reason to have a byte order mark in UTF8 text. # But apparently people do, so jq shouldn't break on it. . "byte order mark" "byte order mark" # 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} {"a",b,"a$\(1+1)"} {"a":1, "b":2, "c":3, "a$2":4} {"a":1, "b":2, "a$2":4} # # 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 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] 42 as $x | . | . | . + 432 | $x + 1 34324 43 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] # test stack overflow and reallocation # this test is disabled for now, it takes a realllllly long time. # def f: if length > 1000 then . else .+[1]|f end; f | length # [] # 1001 # # 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] # And some in/equality tests [ 10 == 10, 10 != 10, 10 != 11, 10 == 11] {} [true,false,true,false] ["hello" == "hello", "hello" != "hello", "hello" == "world", "hello" != "world" ] {} [true,false,false,true] [[1,2,3] == [1,2,3], [1,2,3] != [1,2,3], [1,2,3] == [4,5,6], [1,2,3] != [4,5,6]] {} [true,false,false,true] [{"foo":42} == {"foo":42},{"foo":42} != {"foo":42}, {"foo":42} != {"bar":42}, {"foo":42} == {"bar":42}] {} [true,false,true,false] # ugly complicated thing [{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":18},"world"]},{"foo":[1,2,{"bar":18},"world"]} == {"foo":[1,2,{"bar":19},"world"]}] {} [true,false] # containment operator [("foo" | contains("foo")), ("foobar" | contains("foo")), ("foo" | contains("foobar"))] {} [true, true, false] map(.[1] as $needle | .[0] | contains($needle)) [[[],[]], [[1,2,3], [1,2]], [[1,2,3], [3,1]], [[1,2,3], [4]], [[1,2,3], [1,4]]] [true, true, true, false, false] map(.[1] as $needle | .[0] | contains($needle)) [[["foobar", "foobaz"], ["baz", "bar"]], [["foobar", "foobaz"], ["foo"]], [["foobar", "foobaz"], ["blap"]]] [true, true, false] [({foo: 12, bar:13} | contains({foo: 12})), ({foo: 12} | contains({})), ({foo: 12, bar:13} | contains({baz:14}))] {} [true, true, false] {foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {}}}) {} true {foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {bar: 14}}}) {} false sort [42,[2,5,3,11],10,{"a":42,"b":2},{"a":42},true,2,[2,6],"hello",null,[2,5,6],{"a":[],"b":1},"abc","ab",[3,10],{},false,"abcd",null] [null,null,false,true,2,10,42,"ab","abc","abcd","hello",[2,5,3,11],[2,5,6],[2,6],[3,10],{},{"a":42},{"a":42,"b":2},{"a":[],"b":1}] (sort_by(.b) | sort_by(.a)), sort_by(.a, .b), sort_by(.b, .c), group_by(.b), group_by(.a + .b - .c == 2) [{"a": 1, "b": 4, "c": 14}, {"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}, {"a": 0, "b": 2, "c": 43}] [{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}] [{"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}, {"a": 4, "b": 1, "c": 3}] [{"a": 4, "b": 1, "c": 3}, {"a": 0, "b": 2, "c": 43}, {"a": 1, "b": 4, "c": 3}, {"a": 1, "b": 4, "c": 14}] [[{"a": 4, "b": 1, "c": 3}], [{"a": 0, "b": 2, "c": 43}], [{"a": 1, "b": 4, "c": 14}, {"a": 1, "b": 4, "c": 3}]] [[{"a": 1, "b": 4, "c": 14}, {"a": 0, "b": 2, "c": 43}], [{"a": 4, "b": 1, "c": 3}, {"a": 1, "b": 4, "c": 3}]] unique [1,2,5,3,5,3,1,3] [1,2,3,5] [min, max, min_by(.[1]), max_by(.[1]), min_by(.[2]), max_by(.[2])] [[4,2,"a"],[3,1,"a"],[2,4,"a"],[1,3,"a"]] [[1,3,"a"],[4,2,"a"],[3,1,"a"],[2,4,"a"],[4,2,"a"],[1,3,"a"]] [min,max,min_by(.),max_by(.)] [] [null,null,null,null] .foo[.baz] {"foo":{"bar":4},"baz":"bar"} 4