Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize and correct tests #2939

Closed
baterflyrity opened this issue Oct 31, 2023 · 44 comments
Closed

Normalize and correct tests #2939

baterflyrity opened this issue Oct 31, 2023 · 44 comments

Comments

@baterflyrity
Copy link

baterflyrity commented Oct 31, 2023

Describe the bug
There are several different test case syntaxes which do not follow single logick.

Current behavior
As for now you can look into jq.test and find syntaxes:

  1. Header describing file syntax - program + input + output. But this is totally wrong!
  2. %%FAIL - assert error with specified message (no program/output are provided).
  3. %%FAIL IGNORE MSG - assert error with any message.
  4. # Runtime error - comment that must be ignored but actually asserts fail.
  5. No output at all - actually this must be [] but somehow just no line generates successful pass for test.
  6. Multiline output - this is only one logical hack, but still is hack.
  7. BOM at line start - well, whole file is already parsed to memory so wtf?
  8. JSON unparsable values - mostly type overflow and incorrect values (likely from JSON5). This is very strange for json tool to have unsupported json values...
  9. {x: -1}null{"x": -1} - just wrong output. Can you see one extra space? This is false positive test.

Expected behavior
Each test case must be normalized to well-documented format. To my mind it should be JSON format with schema. Example:

true
null
true

should be converted to

{
  "filter": "true",
  "inputs": [null],
  "outputs": [true]
}

Notice that this is JSON but raw cli string.

@baterflyrity baterflyrity changed the title Normalize test files Normalize and correct tests Oct 31, 2023
@wader
Copy link
Member

wader commented Oct 31, 2023

Header describing file syntax - program + input + output. But this is totally wrong!

How is it wrong? should state that there are new lines between?

Runtime error - comment that must be ignored but actually asserts fail.

Not sure what is going on with these. Hack that uses no output to assert that it did fail? tests added in 0673dee

No output at all - actually this must be [] but somehow just no line generates successful pass for test.

But [] would assert that one empty array was outputted? you would want some kind of explicit indication for no output?

Multiline output - this is only one logical hack, but still is hack.

The format is a bit hackish but i would argue that it's designed to be convenient for writing jq tests and not much else. Also the same reason i think using JSON as test format would be annoying as you would have escape all string literals and whatnot.

BOM at line start - well, whole file is already parsed to memory so wtf?

BOM as in byte-order-marker? not sure i follow. You mean the <feff>"byte order mark" test that tests that jq is liberal about BOM:s in UTF-8?

JSON unparsable values - mostly type overflow and incorrect values (likely from JSON5). This is very strange for json tool to have unsupported json values...

Can you give some examples lines? you mean the lines that uses jq syntax and not JSON? no quotes for keys etc?

{x: -1}→null→{"x": -1} - just wrong output. Can you see one extra space? This is false positive test.

You mean it should always be using compact output? currently i think output lines are parsed as JSON and then compared. Looking at the code it seems to be done by serializing back to JSON and then compare with serialized output.

Could you give some background about why these things are a problem for you? are you implementing your own jq-test parser/runner?

@baterflyrity
Copy link
Author

baterflyrity commented Oct 31, 2023

@wader ,

How is it wrong? should state that there are new lines between?

Let me show example:

%%FAIL
{(0):1}
jq: error: Cannot use number (0) as object key at <top-level>, line 1:

This test results into:

$ echo {(0):1} | jq "%%FAIL"
jq: error: syntax error, unexpected '%', expecting end of file (Windows cmd shell quoting issues?) at <top-level>, line 1:
%%FAIL
jq: 1 compile error

Not sure what is going on with these. Hack that uses no output to assert that it did fail?

.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
[[3],[4],[5],6]
# Runtime error: "jq: Cannot index array with string \"c\""

I can only guess that this is like %%FAIL but in runtime (not in compilation).

$ echo [[3],[4],[5],6] | jq ".[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a"
jq: error (at <stdin>:1): Cannot index array with string "a"

But [] would assert that one empty array was outputted? you would want some kind of explicit indication for no output?

Sure, because two lines - not three lines stated in header.

The format is a bit hackish but i would argue that it's designed to be convenient for writing jq tests and not much else.

What about normalizing this format? I mean use explicit errors assertion, explicit markers/modifiers/e.t.c.

.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
[[3],[4],[5],6]
# Runtime error: "jq: Cannot index array with string \"c\""

It could be something like:

.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
[[3],[4],[5],6]
\e jq: Cannot index array with string \"c\"

or any other marker/header/escape sequence.

jq is liberal about BOM:s in UTF-8?

Sure, but again this is not obvious especially in raw bytes view. It should be line modifier like \r <feff>"byte order mark" (which means load the line in raw bytes mode rather than in file content encoding).

Can you give some examples lines? you mean the lines that uses jq syntax and not JSON? no quotes for keys etc?

Unquoted keys are ok, but:

  • 9999999999E999999990 - double overflow
  • -NaN - valid only in json5 as i remember

You mean it should always be using compact output? currently i think output lines are parsed as JSON and then compared.

I thought too unless -NaN and such values. Now I don't know how to deal with it:

$ echo 42 | jq "{x: -1}"
{
  "x": -1
}
$ echo 42 | jq "{x: -1}" --compact-output
{"x":-1}

@baterflyrity
Copy link
Author

baterflyrity commented Oct 31, 2023

Could you give some background about why these things are a problem for you? are you implementing your own jq-test parser/runner?

Sure. I use jq in my python applications and really tired of incompatible windows builds. What the heck jq runs on windows and python runs on windows but python bindings of jq do not support windows?

So I just want to rollout my own python binding that just works. Indeed, I implemented tests and pulled form this repo test files. But unfortunately I can not understand this floating syntax by only inner vision.

Wouldn't you be bothered helping a bit with this please?

p.s.
Currently I am using cli tests parser + runner written in python so it can even be integrated here if needed (guess not 😏).

@wader
Copy link
Member

wader commented Oct 31, 2023

Let me show example:

%%FAIL
{(0):1}
jq: error: Cannot use number (0) as object key at <top-level>, line 1:

This test results into:

$ echo {(0):1} | jq "%%FAIL"
jq: error: syntax error, unexpected '%', expecting end of file (Windows cmd shell quoting issues?) at <top-level>, line 1:
%%FAIL
jq: 1 compile error

Aha I see, %%FAIL and such things are part of the test syntax for --run-tests and is not part of the jq language.

Not sure what is going on with these. Hack that uses no output to assert that it did fail?

.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
[[3],[4],[5],6]
# Runtime error: "jq: Cannot index array with string \"c\""

I can only guess that this is like %%FAIL but in runtime (not in compilation).

Yes I think it might be a hacky way to assert that an error happens error. But I wonder why it's not done using try/catch intead?

$ echo [[3],[4],[5],6] | jq ".[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a"
jq: error (at <stdin>:1): Cannot index array with string "a"

But [] would assert that one empty array was outputted? you would want some kind of explicit indication for no output?

Sure, because two lines - not three lines stated in header.

Yes program, input, expected output is a but unclear that expected output can be empty. My jq-damaged brain read it as program, input, (expected output)* :)

The format is a bit hackish but i would argue that it's designed to be convenient for writing jq tests and not much else.

What about normalizing this format? I mean use explicit errors assertion, explicit markers/modifiers/e.t.c.
...

jq is liberal about BOM:s in UTF-8?

Sure, but again this is not obvious especially in raw bytes view. It should be line modifier like \r <feff>"byte order mark" (which means load the line in raw bytes mode rather than in file content encoding).

Yes it can probably be improved a lot. Maybe @nicowilliams can give some history why it works the way it does?

Can you give some examples lines? you mean the lines that uses jq syntax and not JSON? no quotes for keys etc?

Unquoted keys are ok, but:

  • 9999999999E999999990 - double overflow

This probably because jq support to preserve big integers. There has been talks about having some arguments to configure this like #2643

  • -NaN - valid only in json5 as i remember

You mean it should always be using compact output? currently i think output lines are parsed as JSON and then compared.

I thought too unless -NaN and such values. Now I don't know how to deal with it:

Huh yes something is a bit fishy with this:

$ echo '[nan,nAn,NAN]' | jq -c
[null,null,null]

@wader
Copy link
Member

wader commented Oct 31, 2023

Sure. I use jq in my python applications and really tired of incompatible windows builds. What the heck jq runs on windows and python runs on windows but python bindings of jq do not support windows?

So I just want to rollout my own python binding that just works. Indeed, I implemented tests and pulled form this repo test files. But unfortunately I can not understand this floating syntax by only inner vision.

I see. Is there some public URL for the project?

So you want to use the tests in jq.test to test the bindings?

Yeah i've kind of reverse-engineered the syntax also by looking at the code. Why it's a bit floating i guess is because it has only been designed to test jq itself.

Wouldn't you be bothered helping a bit with this please?

p.s. Currently I am using cli tests parser + runner written in python so it can even be integrated here if needed (guess not 😏).

Can promise anything but i can try. What do you need help with? there are probably others that can help also

@nicowilliams
Copy link
Contributor

@baterflyrity if you use --run-tests, as you should, do all your questions get answered?

@nicowilliams
Copy link
Contributor

As for BOMs, we don't have any BOM in jq --run-tests test files -- there's no need, and they're not JSON anyways.

@nicowilliams
Copy link
Contributor

Also, regarding (8) I get the feeling that you don't understand what jq is. jq is a programming language, and jq programs are not JSON texts, though JSON texts are jq programs. Of course jq programs exist that are not parseable as JSON -- that's OK! But the output of jq should always be parseable JSON unless the -r option is used.

I don't understand (9) at all.

(1) through (6) should be addressed by using --run-tests when running jq.test. But note that you need other command-line options -- see tests/jqtest (which runs jq.tests like this $VALGRIND $Q $JQ -L "$mods" --run-tests $JQTESTDIR/jq.test).

@baterflyrity
Copy link
Author

baterflyrity commented Nov 1, 2023

@nicowilliams Thanks, now I definitely understand how to run tests. But my question is about how to read and write these tests. Do you have any specification?

As I can see tests are intended to be stdin + filter = stdout but actually are like black magical boxes.

@emanuele6
Copy link
Member

https://jqlang.github.io/jq/manual/v1.7/#invoking-jq

--run-tests [filename]:
Runs the tests in the given file or standard input. This must be the last option given and does not honor all preceding options. The input consists of comment lines, empty lines, and program lines followed by one input line, as many lines of output as are expected (one per output), and a terminating empty line. Compilation failure tests start with a line containing only %%FAIL, then a line containing the program to compile, then a line containing an error message to compare to the actual.

Be warned that this option can change backwards-incompatibly.

@baterflyrity
Copy link
Author

https://jqlang.github.io/jq/manual/v1.7/#invoking-jq

--run-tests [filename]:
Runs the tests in the given file or standard input. This must be the last option given and does not honor all preceding options. The input consists of comment lines, empty lines, and program lines followed by one input line, as many lines of output as are expected (one per output), and a terminating empty line. Compilation failure tests start with a line containing only %%FAIL, then a line containing the program to compile, then a line containing an error message to compare to the actual.
Be warned that this option can change backwards-incompatibly.

Unfortunately this description is simply wrong. Please checkout unstated syntaxes in discussion header.

@baterflyrity
Copy link
Author

@wader Thanks. Yes, I would like to integrate jq tests into my python bindings as end-to-end. But I really do not understand how to check correctness when some cases are wrong in stdout, others - in json values. All in all It would be cool to see at least test file specification.

@nicowilliams
Copy link
Contributor

Unfortunately this description is simply wrong. Please checkout unstated syntaxes in discussion header.

Your original issue description is not useful to me to understand what you mean about the quoted manual text being wrong.

@nicowilliams
Copy link
Contributor

@wader Thanks. Yes, I would like to integrate jq tests into my python bindings as end-to-end. But I really do not understand how to check correctness when some cases are wrong in stdout, others - in json values. All in all It would be cool to see at least test file specification.

I don't see why you would need this. You need tests, but you don't need to use all of jq's own tests.

@emanuele6
Copy link
Member

emanuele6 commented Nov 1, 2023

Unfortunately this description is simply wrong. Please checkout unstated syntaxes in discussion header.

I saw them, and I don't understand how you mean that description is wrong.

jq reading nan from inputs as NaN, but then convertining it to null on output is something it does normally, it is not specific to tests.

%%FAIL IGNORE MSG is not specified in the manual, but it is basically the same as %%FAIL except it ignores the error message line, it checks for failure without checking that the error message is exactly the same.

The test runner is not comparing the outputs of the script with the lines that would be printed by jq if you ran jq -n " $input | $script" literally. It is comparing them as json values with jq's== so it does not matter if you write {"x": -1} or {"x":-1} or { "x": - 1 } in the expectations.

@nicowilliams
Copy link
Contributor

You Python bindings should be tested using the bound API, and jq does NOT export an API for --run-tests, therefore you cannot use it. You'll have to write your own tests of your API, possibly using our tests for inspiration.

@baterflyrity
Copy link
Author

baterflyrity commented Nov 1, 2023

Your original issue description is not useful to me to understand what you mean about the quoted manual text being wrong.
I saw them, and I don't understand how you mean that description is wrong.

.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
[[3],[4],[5],6]
# Runtime error: "jq: Cannot index array with string \"c\""

According to the description this test must fail because since comment lines are ignore result must be asserted as empty output.

.
<FEFF>"byte order mark"
"byte order mark"

This is just magical prefix.

It is comparing them as json values with jq's== so it does not matter if you write {"x": -1} or {"x":-1} or { "x": - 1 } in the expectations.

So values like [9999999999E999999990, -NaN] in most libraries are neither valid as json nor as json5. Is it json5 with bigint?


You'll have to write your own tests of your API, possibly using our tests for inspiration.

Am i right there is no chance structured tests can appear soon in jq? It's a pity but really seems like writing my own tests will be more efficient than parsing random syntax.

@nicowilliams
Copy link
Contributor

nicowilliams commented Nov 1, 2023

Your original issue description is not useful to me to understand what you mean about the quoted manual text being wrong.
I saw them, and I don't understand how you mean that description is wrong.

.[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a
[[3],[4],[5],6]
# Runtime error: "jq: Cannot index array with string \"c\""

According to the description this test must fail because since comment lines are ignore result must be asserted as empty output.

What's happening here is that this test declares that there is no output, and indeed, there isn't. The run-time error is being ignored. The # Runtime error: ... is just a comment.

What we should have done here is used try/catch to check that we get that particular error. But this is not a bug in the docs anyways.

--run-tests is really a bit of a feature for jq maintainers, not for users. I recommend that you don't use it.

.
<FEFF>"byte order mark"
"byte order mark"

This is just magical prefix.

What of this? What's the problem with this? Yes, it's at the start of a line, so what? This is NOT a JSON file. This is NOT a file with any format that any other tool should support. This is a file used internally by jq. Bindings for Python or whatever language should NOT use this file. You can adapt tests from this file to test your bindings, sure, but with some care.

It is comparing them as json values with jq's== so it does not matter if you write {"x": -1} or {"x":-1} or { "x": - 1 } in the expectations.

So values like [9999999999E999999990, -NaN] in most libraries are neither valid as json nor as json5. Is it json5 with bigint?

It's JSON. RFC 7259 JSON. We should make sure it's also RFC 8259 JSON. It is NOT JSON5. I don't believe we've ever claimed that jq supports JSON5 -- it does not.

EDIT: I should point out that we don't actually test conformance to RFC 7259 / 8259, but that is what we aim to support at this time.

You'll have to write your own tests of your API, possibly using our tests for inspiration.

Am i right there is no chance structured tests can appear soon in jq? It's a pity but really seems like writing my own tests will be more efficient than parsing random syntax.

You can use try/catch in valid programs to write tests. Please spend some time reading through the manual.

@emanuele6
Copy link
Member

emanuele6 commented Nov 1, 2023

[[3],[4],[5],6]
# Runtime error: "jq: Cannot index array with string \"c\""

According to the description this test must fail because since comment lines are ignore result must be asserted as empty output.

What do you mean? Do you know what FOO as { a: $a } does in jq? It is a descructing binding that bind the value of the a key in the objects returned by FOO to $a; effectively a short-hand for FOO.a as $a. With ?// you can specify multiple deconstruction patterns e.g. FOO as { $a } ?// [ { b: $a } ] will bind $a to .a if the input is an object (FOO.a as $a), otherwise if the input is an array, it will bind $a to the "b" field of the first element of that array (FOO[0].b as $a). In this test, there are three patterns that are exactly the same because that is what is being tested.

The input is [[3],[4],[5],6], and you are looping it with .[] and trying to bind it to $a with {a:$a} as deconstruction. [3] cannot be deconstructed with any of the patterns, so the binding returns nothing, and throws a runtime error, and returns no output.

$ jq -n '[[3]] | .[] as { $a } | $a'
jq: error (at <unknown>): Cannot index array with string "a"
$ jq -n '[[3]] | try .[] as { $a } | $a catch .'
"Cannot index array with string \"a\""

The comment has nothing to do with test, that script for the given input returns nothing, and that is correct because no outputs are listed. Without the comment it would work the same.

The output part of a test case is optional, you may have something like this for example:

numbers
"hello"

"hello" is not a number, so the numbers function returns nothing with it as input, so you list no outputs in the test case. If you wrote some value as output, the test would fail because the script outputted nothing, but you have listed a value in the outputs.

numbers
"hello"
[123]

If you mean that you should have used %%FAIL to test that, that is not correct.
%%FAIL is only used to test compilation failure, as mentioned in the manual.
For example a EXPR as BINDING expression is not valid syntax in jq; it must be followed by | EXPR:

$ jq -n '. as $a'
jq: error: syntax error, unexpected end of file, expecting '|' (Unix shell quoting issues?) at <top-level>, line 1:
. as $a     
jq: 1 compile error
$ jq -n '. as $a | 12'
12

Or using a variable outside of the scope in which it is defined does not compile:

$ jq -n '(tostring | length as $a | $a) + $a * 10, .'
jq: error: $a is not defined at <top-level>, line 1:
(tostring | length as $a | $a) + $a * 10, .
jq: 1 compile error
$ jq -n '(tostring | length) as $a | $a + $a * 10, .'
44
null

You use %%FAIL to write tests for these things:

%%FAIL
. as $a
jq: error: syntax error, unexpected end of file, expecting '|' (Unix shell quoting issues?) at <top-level>, line 1:

. as $a | 12
null
12

%%FAIL
(tostring | length as $a | $a) + $a * 10, .
jq: error: $a is not defined at <top-level>, line 1:

(tostring | length) as $a | $a + $a * 10, .
null
44
null

If you want to write a test for a runtime error, you write jq code to do that using try to catch the error as a string.


jq ignore the first character of the first input file if it is U+feff

$ jq . <<< $'\ufeff''1'
1
$ jq . <<< $'\ufeff\ufeff''1'
jq: parse error: Invalid numeric literal at line 2, column 0

The input line of a test case is treated as the content of an input file (though only one input value will be accepted from that input; basically the same as calling fromjson with a string as input in jq).

This is just magical prefix.

What is a magic prefix? It is just:

SCRIPT
INPUT
OUTPUT0

. is code that returns the input;
from the input you read "byte order mark" correctly because U+FEFF is skipped correctly;
so . outputs one value, "byte order mark", which is what you expect in OUTPUT0.

That is exactly what that test is trying to test, and there is nothing special about that test.

If you don't understand that because you think <feff> is actually literally in the file as text that gets expanded to the U+feff, that is not correct, it is a literal U+feff character; it is probably your editor (e.g. vim) that is displaying it as <feff>.

Note that jq only skips U+feff in input files, not jq code.

$ jq -n $'\ufeff''1'
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting end of file (Unix shell quoting issues?) at <top-level>, line 1:
1
jq: 1 compile error
$ jq -nf /dev/stdin <<< $'\ufeff''1'
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting end of file (Unix shell quoting issues?) at <top-level>, line 1:
1
jq: 1 compile error

You'll have to write your own tests of your API, possibly using our tests for inspiration.

Am i right there is no chance structured tests can appear soon in jq? It's a pity but really seems like writing my own tests will be more efficient than parsing random syntax.

That is a weird question.
What would be the point of changing the format of tests, and writing a different interpreter to evluate that new test format?
You keep saying the current test executor does things wrong or not as documented, but you just seem to be misunderstanding how things should work when you say that.
Anyway, if you need to convert jq's test cases to JSON for some reason, it is easy to write a converter with jq:

$ jq -sR 'gsub("^\\s+$|[[:blank:]]*#.*"; "") | scan("(?s)(.*?)(?:\n{2,}|\n*$)")[] / "\n" | if first | IN ("%%FAIL"|.,.+" IGNORE MSG") then { script: .[1], input: null, outputs: null, error: (if first != "%%FAIL" then null else .[2] end) } else select(. != []) | { script: .[0], input: .[1], outputs: [ .[2:][] | fromjson ], error: null } end' tests/jq.test
{
  "script": "true",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "false",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "null",
  "input": "42",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": "1",
  "input": "null",
  "outputs": [
    1
  ],
[...]
full output

{
  "script": "true",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "false",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "null",
  "input": "42",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": "1",
  "input": "null",
  "outputs": [
    1
  ],
  "error": null
}
{
  "script": "-1",
  "input": "null",
  "outputs": [
    -1
  ],
  "error": null
}
{
  "script": "{}",
  "input": "null",
  "outputs": [
    {}
  ],
  "error": null
}
{
  "script": "[]",
  "input": "null",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "{x: -1}",
  "input": "null",
  "outputs": [
    {
      "x": -1
    }
  ],
  "error": null
}
{
  "script": ".",
  "input": "\"byte order mark\"",
  "outputs": [
    "byte order mark"
  ],
  "error": null
}
{
  "script": "\"Aa\\r\\n\\t\\b\\f\\u03bc\"",
  "input": "null",
  "outputs": [
    "Aa\r\n\t\b\fμ"
  ],
  "error": null
}
{
  "script": ".",
  "input": "\"Aa\\r\\n\\t\\b\\f\\u03bc\"",
  "outputs": [
    "Aa\r\n\t\b\fμ"
  ],
  "error": null
}
{
  "script": "\"inter\\(\"pol\" + \"ation\")\"",
  "input": "null",
  "outputs": [
    "interpolation"
  ],
  "error": null
}
{
  "script": "@text,@json,([1,.]|@csv,@tsv),@html,@uri,@sh,(@base64|.,@base64d)",
  "input": "\"!()<>&'\\\"\\t\"",
  "outputs": [
    "!()<>&'\"\t",
    "\"!()<>&'\\\"\\t\"",
    "1,\"!()<>&'\"\"\t\"",
    "1\t!()<>&'\"\\t",
    "!()&lt;&gt;&amp;&apos;&quot;\t",
    "%21%28%29%3C%3E%26%27%22%09",
    "'!()<>&'\\''\"\t'",
    "ISgpPD4mJyIJ",
    "!()<>&'\"\t"
  ],
  "error": null
}
{
  "script": "@base64",
  "input": "\"foóbar\\n\"",
  "outputs": [
    "Zm/Ds2Jhcgo="
  ],
  "error": null
}
{
  "script": "@base64d",
  "input": "\"Zm/Ds2Jhcgo=\"",
  "outputs": [
    "foóbar\n"
  ],
  "error": null
}
{
  "script": "@uri",
  "input": "\"\\u03bc\"",
  "outputs": [
    "%CE%BC"
  ],
  "error": null
}
{
  "script": "@html \"<b>\\(.)</b>\"",
  "input": "\"<script>hax</script>\"",
  "outputs": [
    "<b>&lt;script&gt;hax&lt;/script&gt;</b>"
  ],
  "error": null
}
{
  "script": "[.[]|tojson|fromjson]",
  "input": "[\"foo\", 1, [\"a\", 1, \"b\", 2, {\"foo\":\"bar\"}]]",
  "outputs": [
    [
      "foo",
      1,
      [
        "a",
        1,
        "b",
        2,
        {
          "foo": "bar"
        }
      ]
    ]
  ],
  "error": null
}
{
  "script": "{a: 1}",
  "input": "null",
  "outputs": [
    {
      "a": 1
    }
  ],
  "error": null
}
{
  "script": "{a,b,(.d):.a,e:.b}",
  "input": "{\"a\":1, \"b\":2, \"c\":3, \"d\":\"c\"}",
  "outputs": [
    {
      "a": 1,
      "b": 2,
      "c": 1,
      "e": 2
    }
  ],
  "error": null
}
{
  "script": "{\"a\",b,\"a$\\(1+1)\"}",
  "input": "{\"a\":1, \"b\":2, \"c\":3, \"a$2\":4}",
  "outputs": [
    {
      "a": 1,
      "b": 2,
      "a$2": 4
    }
  ],
  "error": null
}
{
  "script": "{(0):1}",
  "input": null,
  "outputs": null,
  "error": "jq: error: Cannot use number (0) as object key at <top-level>, line 1:"
}
{
  "script": "{non_const:., (0):1}",
  "input": null,
  "outputs": null,
  "error": "jq: error: Cannot use number (0) as object key at <top-level>, line 1:"
}
{
  "script": ".foo",
  "input": "{\"foo\": 42, \"bar\": 43}",
  "outputs": [
    42
  ],
  "error": null
}
{
  "script": ".foo | .bar",
  "input": "{\"foo\": {\"bar\": 42}, \"bar\": \"badvalue\"}",
  "outputs": [
    42
  ],
  "error": null
}
{
  "script": ".foo.bar",
  "input": "{\"foo\": {\"bar\": 42}, \"bar\": \"badvalue\"}",
  "outputs": [
    42
  ],
  "error": null
}
{
  "script": ".foo_bar",
  "input": "{\"foo_bar\": 2}",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": ".[\"foo\"].bar",
  "input": "{\"foo\": {\"bar\": 42}, \"bar\": \"badvalue\"}",
  "outputs": [
    42
  ],
  "error": null
}
{
  "script": ".\"foo\".\"bar\"",
  "input": "{\"foo\": {\"bar\": 20}}",
  "outputs": [
    20
  ],
  "error": null
}
{
  "script": ".e0, .E1, .E-1, .E+1",
  "input": "{\"e0\": 1, \"E1\": 2, \"E\": 3}",
  "outputs": [
    1,
    2,
    2,
    4
  ],
  "error": null
}
{
  "script": "[.[]|.foo?]",
  "input": "[1,[2],{\"foo\":3,\"bar\":4},{},{\"foo\":5}]",
  "outputs": [
    [
      3,
      null,
      5
    ]
  ],
  "error": null
}
{
  "script": "[.[]|.foo?.bar?]",
  "input": "[1,[2],[],{\"foo\":3},{\"foo\":{\"bar\":4}},{}]",
  "outputs": [
    [
      4,
      null
    ]
  ],
  "error": null
}
{
  "script": "[..]",
  "input": "[1,[[2]],{ \"a\":[1]}]",
  "outputs": [
    [
      [
        1,
        [
          [
            2
          ]
        ],
        {
          "a": [
            1
          ]
        }
      ],
      1,
      [
        [
          2
        ]
      ],
      [
        2
      ],
      2,
      {
        "a": [
          1
        ]
      },
      [
        1
      ],
      1
    ]
  ],
  "error": null
}
{
  "script": "[.[]|.[]?]",
  "input": "[1,null,[],[1,[2,[[3]]]],[{}],[{\"a\":[1,[2]]}]]",
  "outputs": [
    [
      1,
      [
        2,
        [
          [
            3
          ]
        ]
      ],
      {},
      {
        "a": [
          1,
          [
            2
          ]
        ]
      }
    ]
  ],
  "error": null
}
{
  "script": "[.[]|.[1:3]?]",
  "input": "[1,null,true,false,\"abcdef\",{},{\"a\":1,\"b\":2},[],[1,2,3,4,5],[1,2]]",
  "outputs": [
    [
      null,
      "bc",
      [],
      [
        2,
        3
      ],
      [
        2
      ]
    ]
  ],
  "error": null
}
{
  "script": "map(try .a[] catch ., try .a.[] catch ., .a[]?, .a.[]?)",
  "input": "[{\"a\": [1,2]}, {\"a\": 123}]",
  "outputs": [
    [
      1,
      2,
      1,
      2,
      1,
      2,
      1,
      2,
      "Cannot iterate over number (123)",
      "Cannot iterate over number (123)"
    ]
  ],
  "error": null
}
{
  "script": "try (.foo[-1] = 0) catch .",
  "input": "null",
  "outputs": [
    "Out of bounds negative array index"
  ],
  "error": null
}
{
  "script": "try (.foo[-2] = 0) catch .",
  "input": "null",
  "outputs": [
    "Out of bounds negative array index"
  ],
  "error": null
}
{
  "script": ".[-1] = 5",
  "input": "[0,1,2]",
  "outputs": [
    [
      0,
      1,
      5
    ]
  ],
  "error": null
}
{
  "script": ".[-2] = 5",
  "input": "[0,1,2]",
  "outputs": [
    [
      0,
      5,
      2
    ]
  ],
  "error": null
}
{
  "script": ".[]",
  "input": "[1,2,3]",
  "outputs": [
    1,
    2,
    3
  ],
  "error": null
}
{
  "script": "1,1",
  "input": "[]",
  "outputs": [
    1,
    1
  ],
  "error": null
}
{
  "script": "1,.",
  "input": "[]",
  "outputs": [
    1,
    []
  ],
  "error": null
}
{
  "script": "[.]",
  "input": "[2]",
  "outputs": [
    [
      [
        2
      ]
    ]
  ],
  "error": null
}
{
  "script": "[[2]]",
  "input": "[3]",
  "outputs": [
    [
      [
        2
      ]
    ]
  ],
  "error": null
}
{
  "script": "[{}]",
  "input": "[2]",
  "outputs": [
    [
      {}
    ]
  ],
  "error": null
}
{
  "script": "[.[]]",
  "input": "[\"a\"]",
  "outputs": [
    [
      "a"
    ]
  ],
  "error": null
}
{
  "script": "[(.,1),((.,.[]),(2,3))]",
  "input": "[\"a\",\"b\"]",
  "outputs": [
    [
      [
        "a",
        "b"
      ],
      1,
      [
        "a",
        "b"
      ],
      "a",
      "b",
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "[([5,5][]),.,.[]]",
  "input": "[1,2,3]",
  "outputs": [
    [
      5,
      5,
      [
        1,
        2,
        3
      ],
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "{x: (1,2)},{x:3} | .x",
  "input": "null",
  "outputs": [
    1,
    2,
    3
  ],
  "error": null
}
{
  "script": "[.[-4,-3,-2,-1,0,1,2,3]]",
  "input": "[1,2,3]",
  "outputs": [
    [
      null,
      1,
      2,
      3,
      1,
      2,
      3,
      null
    ]
  ],
  "error": null
}
{
  "script": "[range(0;10)]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9
    ]
  ],
  "error": null
}
{
  "script": "[range(0,1;3,4)]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      0,
      1,
      2,
      3,
      1,
      2,
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "[range(0;10;3)]",
  "input": "null",
  "outputs": [
    [
      0,
      3,
      6,
      9
    ]
  ],
  "error": null
}
{
  "script": "[range(0;10;-1)]",
  "input": "null",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "[range(0;-5;-1)]",
  "input": "null",
  "outputs": [
    [
      0,
      -1,
      -2,
      -3,
      -4
    ]
  ],
  "error": null
}
{
  "script": "[range(0,1;4,5;1,2)]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      3,
      0,
      2,
      0,
      1,
      2,
      3,
      4,
      0,
      2,
      4,
      1,
      2,
      3,
      1,
      3,
      1,
      2,
      3,
      4,
      1,
      3
    ]
  ],
  "error": null
}
{
  "script": "[while(.<100; .*2)]",
  "input": "1",
  "outputs": [
    [
      1,
      2,
      4,
      8,
      16,
      32,
      64
    ]
  ],
  "error": null
}
{
  "script": "[(label $here | .[] | if .>1 then break $here else . end), \"hi!\"]",
  "input": "[0,1,2]",
  "outputs": [
    [
      0,
      1,
      "hi!"
    ]
  ],
  "error": null
}
{
  "script": "[(label $here | .[] | if .>1 then break $here else . end), \"hi!\"]",
  "input": "[0,2,1]",
  "outputs": [
    [
      0,
      "hi!"
    ]
  ],
  "error": null
}
{
  "script": ". as $foo | break $foo",
  "input": null,
  "outputs": null,
  "error": "jq: error: $*label-foo is not defined at <top-level>, line 1:"
}
{
  "script": "[.[]|[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]]",
  "input": "[1,2,3,4,5]",
  "outputs": [
    [
      1,
      2,
      6,
      24,
      120
    ]
  ],
  "error": null
}
{
  "script": "[label $out | foreach .[] as $item ([3, null]; if .[0] < 1 then break $out else [.[0] -1, $item] end; .[1])]",
  "input": "[11,22,33,44,55,66,77,88,99]",
  "outputs": [
    [
      11,
      22,
      33
    ]
  ],
  "error": null
}
{
  "script": "[foreach range(5) as $item (0; $item)]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      3,
      4
    ]
  ],
  "error": null
}
{
  "script": "[foreach .[] as [$i, $j] (0; . + $i - $j)]",
  "input": "[[2,1], [5,3], [6,4]]",
  "outputs": [
    [
      1,
      3,
      5
    ]
  ],
  "error": null
}
{
  "script": "[foreach .[] as {a:$a} (0; . + $a; -.)]",
  "input": "[{\"a\":1}, {\"b\":2}, {\"a\":3, \"b\":4}]",
  "outputs": [
    [
      -1,
      -1,
      -4
    ]
  ],
  "error": null
}
{
  "script": "[limit(3; .[])]",
  "input": "[11,22,33,44,55,66,77,88,99]",
  "outputs": [
    [
      11,
      22,
      33
    ]
  ],
  "error": null
}
{
  "script": "[limit(0; error)]",
  "input": "\"badness\"",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "[limit(1; 1, error)]",
  "input": "\"badness\"",
  "outputs": [
    [
      1
    ]
  ],
  "error": null
}
{
  "script": "[first(range(.)), last(range(.))]",
  "input": "10",
  "outputs": [
    [
      0,
      9
    ]
  ],
  "error": null
}
{
  "script": "[nth(0,5,9,10,15; range(.)), try nth(-1; range(.)) catch .]",
  "input": "10",
  "outputs": [
    [
      0,
      5,
      9,
      "nth doesn't support negative indices"
    ]
  ],
  "error": null
}
{
  "script": "first(1,error(\"foo\"))",
  "input": "null",
  "outputs": [
    1
  ],
  "error": null
}
{
  "script": "[limit(5,7; range(9))]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      3,
      4,
      0,
      1,
      2,
      3,
      4,
      5,
      6
    ]
  ],
  "error": null
}
{
  "script": "[nth(5,7; range(9;0;-1))]",
  "input": "null",
  "outputs": [
    [
      4,
      2
    ]
  ],
  "error": null
}
{
  "script": "[range(0,1,2;4,3,2;2,3)]",
  "input": "null",
  "outputs": [
    [
      0,
      2,
      0,
      3,
      0,
      2,
      0,
      0,
      0,
      1,
      3,
      1,
      1,
      1,
      1,
      1,
      2,
      2,
      2,
      2
    ]
  ],
  "error": null
}
{
  "script": "[range(3,5)]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      0,
      1,
      2,
      3,
      4
    ]
  ],
  "error": null
}
{
  "script": "[(index(\",\",\"|\"), rindex(\",\",\"|\")), indices(\",\",\"|\")]",
  "input": "\"a,b|c,d,e||f,g,h,|,|,i,j\"",
  "outputs": [
    [
      1,
      3,
      22,
      19,
      [
        1,
        5,
        7,
        12,
        14,
        16,
        18,
        20,
        22
      ],
      [
        3,
        9,
        10,
        17,
        19
      ]
    ]
  ],
  "error": null
}
{
  "script": "join(\",\",\"/\")",
  "input": "[\"a\",\"b\",\"c\",\"d\"]",
  "outputs": [
    "a,b,c,d",
    "a/b/c/d"
  ],
  "error": null
}
{
  "script": "[.[]|join(\"a\")]",
  "input": "[[],[\"\"],[\"\",\"\"],[\"\",\"\",\"\"]]",
  "outputs": [
    [
      "",
      "",
      "a",
      "aa"
    ]
  ],
  "error": null
}
{
  "script": "flatten(3,2,1)",
  "input": "[0, [1], [[2]], [[[3]]]]",
  "outputs": [
    [
      0,
      1,
      2,
      3
    ],
    [
      0,
      1,
      2,
      [
        3
      ]
    ],
    [
      0,
      1,
      [
        2
      ],
      [
        [
          3
        ]
      ]
    ]
  ],
  "error": null
}
{
  "script": "[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]",
  "input": "[0,1,2,3,4,5,6]",
  "outputs": [
    [
      [],
      [
        2,
        3
      ],
      [
        0,
        1,
        2,
        3,
        4
      ],
      [
        5,
        6
      ],
      [],
      []
    ]
  ],
  "error": null
}
{
  "script": "[.[3:2], .[-5:4], .[:-2], .[-2:], .[3:3][1:], .[10:]]",
  "input": "\"abcdefghi\"",
  "outputs": [
    [
      "",
      "",
      "abcdefg",
      "hi",
      "",
      ""
    ]
  ],
  "error": null
}
{
  "script": "del(.[2:4],.[0],.[-2:])",
  "input": "[0,1,2,3,4,5,6,7]",
  "outputs": [
    [
      1,
      4,
      5
    ]
  ],
  "error": null
}
{
  "script": ".[2:4] = ([], [\"a\",\"b\"], [\"a\",\"b\",\"c\"])",
  "input": "[0,1,2,3,4,5,6,7]",
  "outputs": [
    [
      0,
      1,
      4,
      5,
      6,
      7
    ],
    [
      0,
      1,
      "a",
      "b",
      4,
      5,
      6,
      7
    ],
    [
      0,
      1,
      "a",
      "b",
      "c",
      4,
      5,
      6,
      7
    ]
  ],
  "error": null
}
{
  "script": "reduce range(65540;65536;-1) as $i ([]; .[$i] = $i)|.[65536:]",
  "input": "null",
  "outputs": [
    [
      null,
      65537,
      65538,
      65539,
      65540
    ]
  ],
  "error": null
}
{
  "script": "1 as $x | 2 as $y | [$x,$y,$x]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      1
    ]
  ],
  "error": null
}
{
  "script": "[1,2,3][] as $x | [[4,5,6,7][$x]]",
  "input": "null",
  "outputs": [
    [
      5
    ],
    [
      6
    ],
    [
      7
    ]
  ],
  "error": null
}
{
  "script": "42 as $x | . | . | . + 432 | $x + 1",
  "input": "34324",
  "outputs": [
    43
  ],
  "error": null
}
{
  "script": "1 as $x | [$x,$x,$x as $x | $x]",
  "input": "null",
  "outputs": [
    [
      1,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "[1, {c:3, d:4}] as [$a, {c:$b, b:$c}] | $a, $b, $c",
  "input": "null",
  "outputs": [
    1,
    3,
    null
  ],
  "error": null
}
{
  "script": ". as {as: $kw, \"str\": $str, (\"e\"+\"x\"+\"p\"): $exp} | [$kw, $str, $exp]",
  "input": "{\"as\": 1, \"str\": 2, \"exp\": 3}",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": ".[] as [$a, $b] | [$b, $a]",
  "input": "[[1], [1, 2, 3]]",
  "outputs": [
    [
      null,
      1
    ],
    [
      2,
      1
    ]
  ],
  "error": null
}
{
  "script": ". as $i | . as [$i] | $i",
  "input": "[0]",
  "outputs": [
    0
  ],
  "error": null
}
{
  "script": ". as [$i] | . as $i | $i",
  "input": "[0]",
  "outputs": [
    [
      0
    ]
  ],
  "error": null
}
{
  "script": ". as [] | null",
  "input": null,
  "outputs": null,
  "error": null
}
{
  "script": ". as {} | null",
  "input": null,
  "outputs": null,
  "error": null
}
{
  "script": "1+1",
  "input": "null",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": "1+1",
  "input": "\"wtasdf\"",
  "outputs": [
    2.0
  ],
  "error": null
}
{
  "script": "2-1",
  "input": "null",
  "outputs": [
    1
  ],
  "error": null
}
{
  "script": "2-(-1)",
  "input": "null",
  "outputs": [
    3
  ],
  "error": null
}
{
  "script": "1e+0+0.001e3",
  "input": "\"I wonder what this will be?\"",
  "outputs": [
    2.0
  ],
  "error": null
}
{
  "script": ".+4",
  "input": "15",
  "outputs": [
    19.0
  ],
  "error": null
}
{
  "script": ".+null",
  "input": "{\"a\":42}",
  "outputs": [
    {
      "a": 42
    }
  ],
  "error": null
}
{
  "script": "null+.",
  "input": "null",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": ".a+.b",
  "input": "{\"a\":42}",
  "outputs": [
    42
  ],
  "error": null
}
{
  "script": "[1,2,3] + [.]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      3,
      null
    ]
  ],
  "error": null
}
{
  "script": "{\"a\":1} + {\"b\":2} + {\"c\":3}",
  "input": "\"asdfasdf\"",
  "outputs": [
    {
      "a": 1,
      "b": 2,
      "c": 3
    }
  ],
  "error": null
}
{
  "script": "\"asdf\" + \"jkl;\" + . + . + .",
  "input": "\"some string\"",
  "outputs": [
    "asdfjkl;some stringsome stringsome string"
  ],
  "error": null
}
{
  "script": "\"\\u0000\\u0020\\u0000\" + .",
  "input": "\"\\u0000\\u0020\\u0000\"",
  "outputs": [
    "\u0000 \u0000\u0000 \u0000"
  ],
  "error": null
}
{
  "script": "42 - .",
  "input": "11",
  "outputs": [
    31
  ],
  "error": null
}
{
  "script": "[1,2,3,4,1] - [.,3]",
  "input": "1",
  "outputs": [
    [
      2,
      4
    ]
  ],
  "error": null
}
{
  "script": "[10 * 20, 20 / .]",
  "input": "4",
  "outputs": [
    [
      200,
      5
    ]
  ],
  "error": null
}
{
  "script": "1 + 2 * 2 + 10 / 2",
  "input": "null",
  "outputs": [
    10
  ],
  "error": null
}
{
  "script": "[16 / 4 / 2, 16 / 4 * 2, 16 - 4 - 2, 16 - 4 + 2]",
  "input": "null",
  "outputs": [
    [
      2,
      8,
      10,
      14
    ]
  ],
  "error": null
}
{
  "script": "1e-19 + 1e-20 - 5e-21",
  "input": "null",
  "outputs": [
    1.05E-19
  ],
  "error": null
}
{
  "script": "1 / 1e-17",
  "input": "null",
  "outputs": [
    1E+17
  ],
  "error": null
}
{
  "script": "9E999999999, 9999999999E999999990, 1E-999999999, 0.000000001E-999999990",
  "input": "null",
  "outputs": [
    9E+999999999,
    9.999999999E+999999999,
    1E-999999999,
    1E-999999999
  ],
  "error": null
}
{
  "script": "5E500000000 > 5E-5000000000, 10000E500000000 > 10000E-5000000000",
  "input": "null",
  "outputs": [
    true,
    true
  ],
  "error": null
}
{
  "script": "(1e999999999, 10e999999999) > (1e-1147483646, 0.1e-1147483646)",
  "input": "null",
  "outputs": [
    true,
    true,
    true,
    true
  ],
  "error": null
}
{
  "script": "25 % 7",
  "input": "null",
  "outputs": [
    4
  ],
  "error": null
}
{
  "script": "49732 % 472",
  "input": "null",
  "outputs": [
    172
  ],
  "error": null
}
{
  "script": "[(infinite, -infinite) % (1, -1, infinite)]",
  "input": "null",
  "outputs": [
    [
      0,
      0,
      0,
      0,
      0,
      -1
    ]
  ],
  "error": null
}
{
  "script": "[nan % 1, 1 % nan | isnan]",
  "input": "null",
  "outputs": [
    [
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "1 + tonumber + (\"10\" | tonumber)",
  "input": "4",
  "outputs": [
    15
  ],
  "error": null
}
{
  "script": "[{\"a\":42},.object,10,.num,false,true,null,\"b\",[1,4]] | .[] as $x | [$x == .[]]",
  "input": "{\"object\": {\"a\":42}, \"num\":10.0}",
  "outputs": [
    [
      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
    ]
  ],
  "error": null
}
{
  "script": "[.[] | length]",
  "input": "[[], {}, [1,2], {\"a\":42}, \"asdf\", \"\\u03bc\"]",
  "outputs": [
    [
      0,
      0,
      2,
      1,
      4,
      1
    ]
  ],
  "error": null
}
{
  "script": "utf8bytelength",
  "input": "\"asdf\\u03bc\"",
  "outputs": [
    6
  ],
  "error": null
}
{
  "script": "[.[] | try utf8bytelength catch .]",
  "input": "[[], {}, [1,2], 55, true, false]",
  "outputs": [
    [
      "array ([]) only strings have UTF-8 byte length",
      "object ({}) only strings have UTF-8 byte length",
      "array ([1,2]) only strings have UTF-8 byte length",
      "number (55) only strings have UTF-8 byte length",
      "boolean (true) only strings have UTF-8 byte length",
      "boolean (false) only strings have UTF-8 byte length"
    ]
  ],
  "error": null
}
{
  "script": "map(keys)",
  "input": "[{}, {\"abcd\":1,\"abc\":2,\"abcde\":3}, {\"x\":1, \"z\": 3, \"y\":2}]",
  "outputs": [
    [
      [],
      [
        "abc",
        "abcd",
        "abcde"
      ],
      [
        "x",
        "y",
        "z"
      ]
    ]
  ],
  "error": null
}
{
  "script": "[1,2,empty,3,empty,4]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      3,
      4
    ]
  ],
  "error": null
}
{
  "script": "map(add)",
  "input": "[[], [1,2,3], [\"a\",\"b\",\"c\"], [[3],[4,5],[6]], [{\"a\":1}, {\"b\":2}, {\"a\":3}]]",
  "outputs": [
    [
      null,
      6,
      "abc",
      [
        3,
        4,
        5,
        6
      ],
      {
        "a": 3,
        "b": 2
      }
    ]
  ],
  "error": null
}
{
  "script": "map_values(.+1)",
  "input": "[0,1,2]",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "def f: . + 1; def g: def g: . + 100; f | g | f; (f | g), g",
  "input": "3.0",
  "outputs": [
    106.0,
    105.0
  ],
  "error": null
}
{
  "script": "def f: (1000,2000); f",
  "input": "123412345",
  "outputs": [
    1000,
    2000
  ],
  "error": null
}
{
  "script": "def f(a;b;c;d;e;f): [a+1,b,c,d,e,f]; f(.[0];.[1];.[0];.[0];.[0];.[0])",
  "input": "[1,2]",
  "outputs": [
    [
      2,
      2,
      1,
      1,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "def f: 1; def g: f, def f: 2; def g: 3; f, def f: g; f, g; def f: 4; [f, def f: g; def g: 5; f, g]+[f,g]",
  "input": "null",
  "outputs": [
    [
      4,
      1,
      2,
      3,
      3,
      5,
      4,
      1,
      2,
      3,
      3
    ]
  ],
  "error": null
}
{
  "script": "def a: 0; . | a",
  "input": "null",
  "outputs": [
    0
  ],
  "error": null
}
{
  "script": "def f(a;b;c;d;e;f;g;h;i;j): [j,i,h,g,f,e,d,c,b,a]; f(.[0];.[1];.[2];.[3];.[4];.[5];.[6];.[7];.[8];.[9])",
  "input": "[0,1,2,3,4,5,6,7,8,9]",
  "outputs": [
    [
      9,
      8,
      7,
      6,
      5,
      4,
      3,
      2,
      1,
      0
    ]
  ],
  "error": null
}
{
  "script": "([1,2] + [4,5])",
  "input": "[1,2,3]",
  "outputs": [
    [
      1,
      2,
      4,
      5
    ]
  ],
  "error": null
}
{
  "script": "true",
  "input": "[1]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "null,1,null",
  "input": "\"hello\"",
  "outputs": [
    null,
    1,
    null
  ],
  "error": null
}
{
  "script": "[1,2,3]",
  "input": "[5,6]",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "[.[]|floor]",
  "input": "[-1.1,1.1,1.9]",
  "outputs": [
    [
      -2,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "[.[]|sqrt]",
  "input": "[4,9]",
  "outputs": [
    [
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "(add / length) as $m | map((. - $m) as $d | $d * $d) | add / length | sqrt",
  "input": "[2,4,4,4,5,5,7,9]",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": "atan * 4 * 1000000|floor / 1000000",
  "input": "1",
  "outputs": [
    3.141592
  ],
  "error": null
}
{
  "script": "[(3.141592 / 2) * (range(0;20) / 20)|cos * 1000000|floor / 1000000]",
  "input": "null",
  "outputs": [
    [
      1,
      0.996917,
      0.987688,
      0.972369,
      0.951056,
      0.923879,
      0.891006,
      0.85264,
      0.809017,
      0.760406,
      0.707106,
      0.649448,
      0.587785,
      0.522498,
      0.45399,
      0.382683,
      0.309017,
      0.233445,
      0.156434,
      0.078459
    ]
  ],
  "error": null
}
{
  "script": "[(3.141592 / 2) * (range(0;20) / 20)|sin * 1000000|floor / 1000000]",
  "input": "null",
  "outputs": [
    [
      0,
      0.078459,
      0.156434,
      0.233445,
      0.309016,
      0.382683,
      0.45399,
      0.522498,
      0.587785,
      0.649447,
      0.707106,
      0.760405,
      0.809016,
      0.85264,
      0.891006,
      0.923879,
      0.951056,
      0.972369,
      0.987688,
      0.996917
    ]
  ],
  "error": null
}
{
  "script": "def f(x): x | x; f([.], . + [42])",
  "input": "[1,2,3]",
  "outputs": [
    [
      [
        [
          1,
          2,
          3
        ]
      ]
    ],
    [
      [
        1,
        2,
        3
      ],
      42
    ],
    [
      [
        1,
        2,
        3,
        42
      ]
    ],
    [
      1,
      2,
      3,
      42,
      42
    ]
  ],
  "error": null
}
{
  "script": "def f: .+1; def g: f; def f: .+100; def f(a):a+.+11; [(g|f(20)), f]",
  "input": "1",
  "outputs": [
    [
      33,
      101
    ]
  ],
  "error": null
}
{
  "script": "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)",
  "input": "\"more testing\"",
  "outputs": [
    [
      1,
      100,
      2100.0,
      100,
      2100.0
    ]
  ],
  "error": null
}
{
  "script": "def x(a;b): a as $a | b as $b | $a + $b; def y($a;$b): $a + $b; def check(a;b): [x(a;b)] == [y(a;b)]; check(.[];.[]*2)",
  "input": "[1,2,3]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "[[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]",
  "input": "999999999",
  "outputs": [
    [
      [
        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
      ]
    ]
  ],
  "error": null
}
{
  "script": "def fac: if . == 1 then 1 else . * (. - 1 | fac) end; [.[] | fac]",
  "input": "[1,2,3,4]",
  "outputs": [
    [
      1,
      2,
      6,
      24
    ]
  ],
  "error": null
}
{
  "script": "reduce .[] as $x (0; . + $x)",
  "input": "[1,2,4]",
  "outputs": [
    7
  ],
  "error": null
}
{
  "script": "reduce .[] as [$i, {j:$j}] (0; . + $i - $j)",
  "input": "[[2,{\"j\":1}], [5,{\"j\":3}], [6,{\"j\":4}]]",
  "outputs": [
    5
  ],
  "error": null
}
{
  "script": "reduce [[1,2,10], [3,4,10]][] as [$i,$j] (0; . + $i * $j)",
  "input": "null",
  "outputs": [
    14
  ],
  "error": null
}
{
  "script": "reduce . as $n (.; .)",
  "input": "null",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": ". as {$a, b: [$c, {$d}]} | [$a, $c, $d]",
  "input": "{\"a\":1, \"b\":[2,{\"d\":3}]}",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": ". as {$a, $b:[$c, $d]}| [$a, $b, $c, $d]",
  "input": "{\"a\":1, \"b\":[2,{\"d\":3}]}",
  "outputs": [
    [
      1,
      [
        2,
        {
          "d": 3
        }
      ],
      2,
      {
        "d": 3
      }
    ]
  ],
  "error": null
}
{
  "script": ".[] | . as {$a, b: [$c, {$d}]} ?// [$a, {$b}, $e] ?// $f | [$a, $b, $c, $d, $e, $f]",
  "input": "[{\"a\":1, \"b\":[2,{\"d\":3}]}, [4, {\"b\":5, \"c\":6}, 7, 8, 9], \"foo\"]",
  "outputs": [
    [
      1,
      null,
      2,
      3,
      null,
      null
    ],
    [
      4,
      5,
      null,
      null,
      7,
      null
    ],
    [
      null,
      null,
      null,
      null,
      null,
      "foo"
    ]
  ],
  "error": null
}
{
  "script": ".[] | . as {a:$a} ?// {a:$a} ?// {a:$a} | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [],
  "error": null
}
{
  "script": ".[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [],
  "error": null
}
{
  "script": "[[3],[4],[5],6][] | . as {a:$a} ?// {a:$a} ?// {a:$a} | $a",
  "input": "null",
  "outputs": [],
  "error": null
}
{
  "script": "[[3],[4],[5],6] | .[] as {a:$a} ?// {a:$a} ?// {a:$a} | $a",
  "input": "null",
  "outputs": [],
  "error": null
}
{
  "script": ".[] | . as {a:$a} ?// {a:$a} ?// $a | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": ".[] as {a:$a} ?// {a:$a} ?// $a | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": "[[3],[4],[5],6][] | . as {a:$a} ?// {a:$a} ?// $a | $a",
  "input": "null",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": "[[3],[4],[5],6] | .[] as {a:$a} ?// {a:$a} ?// $a | $a",
  "input": "null",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": ".[] | . as {a:$a} ?// $a ?// {a:$a} | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": ".[] as {a:$a} ?// $a ?// {a:$a} | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": "[[3],[4],[5],6][] | . as {a:$a} ?// $a ?// {a:$a} | $a",
  "input": "null",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": "[[3],[4],[5],6] | .[] as {a:$a} ?// $a ?// {a:$a} | $a",
  "input": "null",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": ".[] | . as $a ?// {a:$a} ?// {a:$a} | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": ".[] as $a ?// {a:$a} ?// {a:$a} | $a",
  "input": "[[3],[4],[5],6]",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": "[[3],[4],[5],6][] | . as $a ?// {a:$a} ?// {a:$a} | $a",
  "input": "null",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": "[[3],[4],[5],6] | .[] as $a ?// {a:$a} ?// {a:$a} | $a",
  "input": "null",
  "outputs": [
    [
      3
    ],
    [
      4
    ],
    [
      5
    ],
    6
  ],
  "error": null
}
{
  "script": ". as $dot|any($dot[];not)",
  "input": "[1,2,3,4,true,false,1,2,3,4,5]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": ". as $dot|any($dot[];not)",
  "input": "[1,2,3,4,true]",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": ". as $dot|all($dot[];.)",
  "input": "[1,2,3,4,true,false,1,2,3,4,5]",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": ". as $dot|all($dot[];.)",
  "input": "[1,2,3,4,true]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "any(true, error; .)",
  "input": "\"badness\"",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "all(false, error; .)",
  "input": "\"badness\"",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "any(not)",
  "input": "[]",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "all(not)",
  "input": "[]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "any(not)",
  "input": "[false]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "all(not)",
  "input": "[false]",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "[any,all]",
  "input": "[]",
  "outputs": [
    [
      false,
      true
    ]
  ],
  "error": null
}
{
  "script": "[any,all]",
  "input": "[true]",
  "outputs": [
    [
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "[any,all]",
  "input": "[false]",
  "outputs": [
    [
      false,
      false
    ]
  ],
  "error": null
}
{
  "script": "[any,all]",
  "input": "[true,false]",
  "outputs": [
    [
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[any,all]",
  "input": "[null,null,true]",
  "outputs": [
    [
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "path(.foo[0,1])",
  "input": "null",
  "outputs": [
    [
      "foo",
      0
    ],
    [
      "foo",
      1
    ]
  ],
  "error": null
}
{
  "script": "path(.[] | select(.>3))",
  "input": "[1,5,3]",
  "outputs": [
    [
      1
    ]
  ],
  "error": null
}
{
  "script": "path(.)",
  "input": "42",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "try path(.a | map(select(.b == 0))) catch .",
  "input": "{\"a\":[{\"b\":0}]}",
  "outputs": [
    "Invalid path expression with result [{\"b\":0}]"
  ],
  "error": null
}
{
  "script": "try path(.a | map(select(.b == 0)) | .[0]) catch .",
  "input": "{\"a\":[{\"b\":0}]}",
  "outputs": [
    "Invalid path expression near attempt to access element 0 of [{\"b\":0}]"
  ],
  "error": null
}
{
  "script": "try path(.a | map(select(.b == 0)) | .c) catch .",
  "input": "{\"a\":[{\"b\":0}]}",
  "outputs": [
    "Invalid path expression near attempt to access element \"c\" of [{\"b\":0}]"
  ],
  "error": null
}
{
  "script": "try path(.a | map(select(.b == 0)) | .[]) catch .",
  "input": "{\"a\":[{\"b\":0}]}",
  "outputs": [
    "Invalid path expression near attempt to iterate through [{\"b\":0}]"
  ],
  "error": null
}
{
  "script": "path(.a[path(.b)[0]])",
  "input": "{\"a\":{\"b\":0}}",
  "outputs": [
    [
      "a",
      "b"
    ]
  ],
  "error": null
}
{
  "script": "[paths]",
  "input": "[1,[[],{\"a\":2}]]",
  "outputs": [
    [
      [
        0
      ],
      [
        1
      ],
      [
        1,
        0
      ],
      [
        1,
        1
      ],
      [
        1,
        1,
        "a"
      ]
    ]
  ],
  "error": null
}
{
  "script": "[\"foo\",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])",
  "input": "{\"bar\": 42, \"foo\": [\"a\", \"b\", \"c\", \"d\"]}",
  "outputs": [
    "b",
    {
      "bar": 42,
      "foo": [
        "a",
        20,
        "c",
        "d"
      ]
    },
    {
      "bar": 42,
      "foo": [
        "a",
        "c",
        "d"
      ]
    }
  ],
  "error": null
}
{
  "script": "map(getpath([2])), map(setpath([2]; 42)), map(delpaths([[2]]))",
  "input": "[[0], [0,1], [0,1,2]]",
  "outputs": [
    [
      null,
      null,
      2
    ],
    [
      [
        0,
        null,
        42
      ],
      [
        0,
        1,
        42
      ],
      [
        0,
        1,
        42
      ]
    ],
    [
      [
        0
      ],
      [
        0,
        1
      ],
      [
        0,
        1
      ]
    ]
  ],
  "error": null
}
{
  "script": "map(delpaths([[0,\"foo\"]]))",
  "input": "[[{\"foo\":2, \"x\":1}], [{\"bar\":2}]]",
  "outputs": [
    [
      [
        {
          "x": 1
        }
      ],
      [
        {
          "bar": 2
        }
      ]
    ]
  ],
  "error": null
}
{
  "script": "[\"foo\",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])",
  "input": "{\"bar\":false}",
  "outputs": [
    null,
    {
      "bar": false,
      "foo": [
        null,
        20
      ]
    },
    {
      "bar": false
    }
  ],
  "error": null
}
{
  "script": "delpaths([[-200]])",
  "input": "[1,2,3]",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "try delpaths(0) catch .",
  "input": "{}",
  "outputs": [
    "Paths must be specified as an array"
  ],
  "error": null
}
{
  "script": "del(.), del(empty), del((.foo,.bar,.baz) | .[2,3,0]), del(.foo[0], .bar[0], .foo, .baz.bar[0].x)",
  "input": "{\"foo\": [0,1,2,3,4], \"bar\": [0,1]}",
  "outputs": [
    null,
    {
      "foo": [
        0,
        1,
        2,
        3,
        4
      ],
      "bar": [
        0,
        1
      ]
    },
    {
      "foo": [
        1,
        4
      ],
      "bar": [
        1
      ]
    },
    {
      "bar": [
        1
      ]
    }
  ],
  "error": null
}
{
  "script": "del(.[1], .[-6], .[2], .[-3:9])",
  "input": "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]",
  "outputs": [
    [
      0,
      3,
      5,
      6,
      9
    ]
  ],
  "error": null
}
{
  "script": "setpath([-1]; 1)",
  "input": "[0]",
  "outputs": [
    [
      1
    ]
  ],
  "error": null
}
{
  "script": "pick(.a.b.c)",
  "input": "null",
  "outputs": [
    {
      "a": {
        "b": {
          "c": null
        }
      }
    }
  ],
  "error": null
}
{
  "script": "pick(first)",
  "input": "[1,2]",
  "outputs": [
    [
      1
    ]
  ],
  "error": null
}
{
  "script": "pick(first|first)",
  "input": "[[10,20],30]",
  "outputs": [
    [
      [
        10
      ]
    ]
  ],
  "error": null
}
{
  "script": "try pick(last) catch .",
  "input": "[1,2]",
  "outputs": [
    "Out of bounds negative array index"
  ],
  "error": null
}
{
  "script": ".message = \"goodbye\"",
  "input": "{\"message\": \"hello\"}",
  "outputs": [
    {
      "message": "goodbye"
    }
  ],
  "error": null
}
{
  "script": ".foo = .bar",
  "input": "{\"bar\":42}",
  "outputs": [
    {
      "foo": 42,
      "bar": 42
    }
  ],
  "error": null
}
{
  "script": ".foo |= .+1",
  "input": "{\"foo\": 42}",
  "outputs": [
    {
      "foo": 43
    }
  ],
  "error": null
}
{
  "script": ".[] += 2, .[] *= 2, .[] -= 2, .[] /= 2, .[] %=2",
  "input": "[1,3,5]",
  "outputs": [
    [
      3,
      5,
      7
    ],
    [
      2,
      6,
      10
    ],
    [
      -1,
      1,
      3
    ],
    [
      0.5,
      1.5,
      2.5
    ],
    [
      1,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "[.[] % 7]",
  "input": "[-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7]",
  "outputs": [
    [
      0,
      -6,
      -5,
      -4,
      -3,
      -2,
      -1,
      0,
      1,
      2,
      3,
      4,
      5,
      6,
      0
    ]
  ],
  "error": null
}
{
  "script": ".foo += .foo",
  "input": "{\"foo\":2}",
  "outputs": [
    {
      "foo": 4
    }
  ],
  "error": null
}
{
  "script": ".[0].a |= {\"old\":., \"new\":(.+1)}",
  "input": "[{\"a\":1,\"b\":2}]",
  "outputs": [
    [
      {
        "a": {
          "old": 1,
          "new": 2
        },
        "b": 2
      }
    ]
  ],
  "error": null
}
{
  "script": "def inc(x): x |= .+1; inc(.[].a)",
  "input": "[{\"a\":1,\"b\":2},{\"a\":2,\"b\":4},{\"a\":7,\"b\":8}]",
  "outputs": [
    [
      {
        "a": 2,
        "b": 2
      },
      {
        "a": 3,
        "b": 4
      },
      {
        "a": 8,
        "b": 8
      }
    ]
  ],
  "error": null
}
{
  "script": ".[] | try (getpath([\"a\",0,\"b\"]) |= 5) catch .",
  "input": "[null,{\"b\":0},{\"a\":0},{\"a\":null},{\"a\":[0,1]},{\"a\":{\"b\":1}},{\"a\":[{}]},{\"a\":[{\"c\":3}]}]",
  "outputs": [
    {
      "a": [
        {
          "b": 5
        }
      ]
    },
    {
      "b": 0,
      "a": [
        {
          "b": 5
        }
      ]
    },
    "Cannot index number with number",
    {
      "a": [
        {
          "b": 5
        }
      ]
    },
    "Cannot index number with string \"b\"",
    "Cannot index object with number",
    {
      "a": [
        {
          "b": 5
        }
      ]
    },
    {
      "a": [
        {
          "c": 3,
          "b": 5
        }
      ]
    }
  ],
  "error": null
}
{
  "script": "(.[] | select(. >= 2)) |= empty",
  "input": "[1,5,3,0,7]",
  "outputs": [
    [
      1,
      0
    ]
  ],
  "error": null
}
{
  "script": ".[] |= select(. % 2 == 0)",
  "input": "[0,1,2,3,4,5]",
  "outputs": [
    [
      0,
      2,
      4
    ]
  ],
  "error": null
}
{
  "script": ".foo[1,4,2,3] |= empty",
  "input": "{\"foo\":[0,1,2,3,4,5]}",
  "outputs": [
    {
      "foo": [
        0,
        5
      ]
    }
  ],
  "error": null
}
{
  "script": ".[2][3] = 1",
  "input": "[4]",
  "outputs": [
    [
      4,
      null,
      [
        null,
        null,
        null,
        1
      ]
    ]
  ],
  "error": null
}
{
  "script": ".foo[2].bar = 1",
  "input": "{\"foo\":[11], \"bar\":42}",
  "outputs": [
    {
      "foo": [
        11,
        null,
        {
          "bar": 1
        }
      ],
      "bar": 42
    }
  ],
  "error": null
}
{
  "script": "try ((map(select(.a == 1))[].b) = 10) catch .",
  "input": "[{\"a\":0},{\"a\":1}]",
  "outputs": [
    "Invalid path expression near attempt to iterate through [{\"a\":1}]"
  ],
  "error": null
}
{
  "script": "try ((map(select(.a == 1))[].a) |= .+1) catch .",
  "input": "[{\"a\":0},{\"a\":1}]",
  "outputs": [
    "Invalid path expression near attempt to iterate through [{\"a\":1}]"
  ],
  "error": null
}
{
  "script": "def x: .[1,2]; x=10",
  "input": "[0,1,2]",
  "outputs": [
    [
      0,
      10,
      10
    ]
  ],
  "error": null
}
{
  "script": "try (def x: reverse; x=10) catch .",
  "input": "[0,1,2]",
  "outputs": [
    "Invalid path expression with result [2,1,0]"
  ],
  "error": null
}
{
  "script": ".[] = 1",
  "input": "[1,null,Infinity,-Infinity,NaN,-NaN]",
  "outputs": [
    [
      1,
      1,
      1,
      1,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "[.[] | if .foo then \"yep\" else \"nope\" end]",
  "input": "[{\"foo\":0},{\"foo\":1},{\"foo\":[]},{\"foo\":true},{\"foo\":false},{\"foo\":null},{\"foo\":\"foo\"},{}]",
  "outputs": [
    [
      "yep",
      "yep",
      "yep",
      "yep",
      "nope",
      "nope",
      "yep",
      "nope"
    ]
  ],
  "error": null
}
{
  "script": "[.[] | if .baz then \"strange\" elif .foo then \"yep\" else \"nope\" end]",
  "input": "[{\"foo\":0},{\"foo\":1},{\"foo\":[]},{\"foo\":true},{\"foo\":false},{\"foo\":null},{\"foo\":\"foo\"},{}]",
  "outputs": [
    [
      "yep",
      "yep",
      "yep",
      "yep",
      "nope",
      "nope",
      "yep",
      "nope"
    ]
  ],
  "error": null
}
{
  "script": "[if 1,null,2 then 3 else 4 end]",
  "input": "null",
  "outputs": [
    [
      3,
      4,
      3
    ]
  ],
  "error": null
}
{
  "script": "[if empty then 3 else 4 end]",
  "input": "null",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "[if 1 then 3,4 else 5 end]",
  "input": "null",
  "outputs": [
    [
      3,
      4
    ]
  ],
  "error": null
}
{
  "script": "[if null then 3 else 5,6 end]",
  "input": "null",
  "outputs": [
    [
      5,
      6
    ]
  ],
  "error": null
}
{
  "script": "[if true then 3 end]",
  "input": "7",
  "outputs": [
    [
      3
    ]
  ],
  "error": null
}
{
  "script": "[if false then 3 end]",
  "input": "7",
  "outputs": [
    [
      7
    ]
  ],
  "error": null
}
{
  "script": "[if false then 3 else . end]",
  "input": "7",
  "outputs": [
    [
      7
    ]
  ],
  "error": null
}
{
  "script": "[if false then 3 elif false then 4 end]",
  "input": "7",
  "outputs": [
    [
      7
    ]
  ],
  "error": null
}
{
  "script": "[if false then 3 elif false then 4 else . end]",
  "input": "7",
  "outputs": [
    [
      7
    ]
  ],
  "error": null
}
{
  "script": "[.[] | [.foo[] // .bar]]",
  "input": "[{\"foo\":[1,2], \"bar\": 42}, {\"foo\":[1], \"bar\": null}, {\"foo\":[null,false,3], \"bar\": 18}, {\"foo\":[], \"bar\":42}, {\"foo\": [null,false,null], \"bar\": 41}]",
  "outputs": [
    [
      [
        1,
        2
      ],
      [
        1
      ],
      [
        3
      ],
      [
        42
      ],
      [
        41
      ]
    ]
  ],
  "error": null
}
{
  "script": ".[] //= .[0]",
  "input": "[\"hello\",true,false,[false],null]",
  "outputs": [
    [
      "hello",
      true,
      "hello",
      [
        false
      ],
      "hello"
    ]
  ],
  "error": null
}
{
  "script": ".[] | [.[0] and .[1], .[0] or .[1]]",
  "input": "[[true,[]], [false,1], [42,null], [null,false]]",
  "outputs": [
    [
      true,
      true
    ],
    [
      false,
      true
    ],
    [
      false,
      true
    ],
    [
      false,
      false
    ]
  ],
  "error": null
}
{
  "script": "[.[] | not]",
  "input": "[1,0,false,null,true,\"hello\"]",
  "outputs": [
    [
      false,
      false,
      true,
      true,
      false,
      false
    ]
  ],
  "error": null
}
{
  "script": "[10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20]",
  "input": "{}",
  "outputs": [
    [
      true,
      false,
      false,
      false,
      false,
      true
    ]
  ],
  "error": null
}
{
  "script": "[10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20]",
  "input": "{}",
  "outputs": [
    [
      true,
      true,
      false,
      false,
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "[ 10 == 10, 10 != 10, 10 != 11, 10 == 11]",
  "input": "{}",
  "outputs": [
    [
      true,
      false,
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[\"hello\" == \"hello\", \"hello\" != \"hello\", \"hello\" == \"world\", \"hello\" != \"world\" ]",
  "input": "{}",
  "outputs": [
    [
      true,
      false,
      false,
      true
    ]
  ],
  "error": null
}
{
  "script": "[[1,2,3] == [1,2,3], [1,2,3] != [1,2,3], [1,2,3] == [4,5,6], [1,2,3] != [4,5,6]]",
  "input": "{}",
  "outputs": [
    [
      true,
      false,
      false,
      true
    ]
  ],
  "error": null
}
{
  "script": "[{\"foo\":42} == {\"foo\":42},{\"foo\":42} != {\"foo\":42}, {\"foo\":42} != {\"bar\":42}, {\"foo\":42} == {\"bar\":42}]",
  "input": "{}",
  "outputs": [
    [
      true,
      false,
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[{\"foo\":[1,2,{\"bar\":18},\"world\"]} == {\"foo\":[1,2,{\"bar\":18},\"world\"]},{\"foo\":[1,2,{\"bar\":18},\"world\"]} == {\"foo\":[1,2,{\"bar\":19},\"world\"]}]",
  "input": "{}",
  "outputs": [
    [
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[(\"foo\" | contains(\"foo\")), (\"foobar\" | contains(\"foo\")), (\"foo\" | contains(\"foobar\"))]",
  "input": "{}",
  "outputs": [
    [
      true,
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[contains(\"\"), contains(\"\\u0000\")]",
  "input": "\"\\u0000\"",
  "outputs": [
    [
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "[contains(\"\"), contains(\"a\"), contains(\"ab\"), contains(\"c\"), contains(\"d\")]",
  "input": "\"ab\\u0000cd\"",
  "outputs": [
    [
      true,
      true,
      true,
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "[contains(\"cd\"), contains(\"b\\u0000\"), contains(\"ab\\u0000\")]",
  "input": "\"ab\\u0000cd\"",
  "outputs": [
    [
      true,
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "[contains(\"b\\u0000c\"), contains(\"b\\u0000cd\"), contains(\"b\\u0000cd\")]",
  "input": "\"ab\\u0000cd\"",
  "outputs": [
    [
      true,
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": "[contains(\"@\"), contains(\"\\u0000@\"), contains(\"\\u0000what\")]",
  "input": "\"ab\\u0000cd\"",
  "outputs": [
    [
      false,
      false,
      false
    ]
  ],
  "error": null
}
{
  "script": "[.[]|try if . == 0 then error(\"foo\") elif . == 1 then .a elif . == 2 then empty else . end catch .]",
  "input": "[0,1,2,3]",
  "outputs": [
    [
      "foo",
      "Cannot index number with string \"a\"",
      3
    ]
  ],
  "error": null
}
{
  "script": "[.[]|(.a, .a)?]",
  "input": "[null,true,{\"a\":1}]",
  "outputs": [
    [
      null,
      null,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "[[.[]|[.a,.a]]?]",
  "input": "[null,true,{\"a\":1}]",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": ".[] | try error catch .",
  "input": "[1,null,2]",
  "outputs": [
    1,
    null,
    2
  ],
  "error": null
}
{
  "script": "try error(\"\\($__loc__)\") catch .",
  "input": "null",
  "outputs": [
    "{\"file\":\"<top-level>\",\"line\":1}"
  ],
  "error": null
}
{
  "script": "[.[]|startswith(\"foo\")]",
  "input": "[\"fo\", \"foo\", \"barfoo\", \"foobar\", \"barfoob\"]",
  "outputs": [
    [
      false,
      true,
      false,
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[.[]|endswith(\"foo\")]",
  "input": "[\"fo\", \"foo\", \"barfoo\", \"foobar\", \"barfoob\"]",
  "outputs": [
    [
      false,
      true,
      true,
      false,
      false
    ]
  ],
  "error": null
}
{
  "script": "[.[] | split(\", \")]",
  "input": "[\"a,b, c, d, e,f\",\", a,b, c, d, e,f, \"]",
  "outputs": [
    [
      [
        "a,b",
        "c",
        "d",
        "e,f"
      ],
      [
        "",
        "a,b",
        "c",
        "d",
        "e,f",
        ""
      ]
    ]
  ],
  "error": null
}
{
  "script": "split(\"\")",
  "input": "\"abc\"",
  "outputs": [
    [
      "a",
      "b",
      "c"
    ]
  ],
  "error": null
}
{
  "script": "[.[]|ltrimstr(\"foo\")]",
  "input": "[\"fo\", \"foo\", \"barfoo\", \"foobar\", \"afoo\"]",
  "outputs": [
    [
      "fo",
      "",
      "barfoo",
      "bar",
      "afoo"
    ]
  ],
  "error": null
}
{
  "script": "[.[]|rtrimstr(\"foo\")]",
  "input": "[\"fo\", \"foo\", \"barfoo\", \"foobar\", \"foob\"]",
  "outputs": [
    [
      "fo",
      "",
      "bar",
      "foobar",
      "foob"
    ]
  ],
  "error": null
}
{
  "script": "[(index(\",\"), rindex(\",\")), indices(\",\")]",
  "input": "\"a,bc,def,ghij,klmno\"",
  "outputs": [
    [
      1,
      13,
      [
        1,
        4,
        8,
        13
      ]
    ]
  ],
  "error": null
}
{
  "script": "[ index(\"aba\"), rindex(\"aba\"), indices(\"aba\") ]",
  "input": "\"xababababax\"",
  "outputs": [
    [
      1,
      7,
      [
        1,
        3,
        5,
        7
      ]
    ]
  ],
  "error": null
}
{
  "script": "indices(1)",
  "input": "[0,1,1,2,3,4,1,5]",
  "outputs": [
    [
      1,
      2,
      6
    ]
  ],
  "error": null
}
{
  "script": "indices([1,2])",
  "input": "[0,1,2,3,1,4,2,5,1,2,6,7]",
  "outputs": [
    [
      1,
      8
    ]
  ],
  "error": null
}
{
  "script": "indices([1,2])",
  "input": "[1]",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "indices(\", \")",
  "input": "\"a,b, cd,e, fgh, ijkl\"",
  "outputs": [
    [
      3,
      9,
      14
    ]
  ],
  "error": null
}
{
  "script": "[.[]|split(\",\")]",
  "input": "[\"a, bc, def, ghij, jklmn, a,b, c,d, e,f\", \"a,b,c,d, e,f,g,h\"]",
  "outputs": [
    [
      [
        "a",
        " bc",
        " def",
        " ghij",
        " jklmn",
        " a",
        "b",
        " c",
        "d",
        " e",
        "f"
      ],
      [
        "a",
        "b",
        "c",
        "d",
        " e",
        "f",
        "g",
        "h"
      ]
    ]
  ],
  "error": null
}
{
  "script": "[.[]|split(\", \")]",
  "input": "[\"a, bc, def, ghij, jklmn, a,b, c,d, e,f\", \"a,b,c,d, e,f,g,h\"]",
  "outputs": [
    [
      [
        "a",
        "bc",
        "def",
        "ghij",
        "jklmn",
        "a,b",
        "c,d",
        "e,f"
      ],
      [
        "a,b,c,d",
        "e,f,g,h"
      ]
    ]
  ],
  "error": null
}
{
  "script": "[.[] * 3]",
  "input": "[\"a\", \"ab\", \"abc\"]",
  "outputs": [
    [
      "aaa",
      "ababab",
      "abcabcabc"
    ]
  ],
  "error": null
}
{
  "script": "[.[] * \"abc\"]",
  "input": "[-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 3.7, 10.0]",
  "outputs": [
    [
      null,
      null,
      "",
      "",
      "abc",
      "abc",
      "abcabcabc",
      "abcabcabcabcabcabcabcabcabcabc"
    ]
  ],
  "error": null
}
{
  "script": "[. * (nan,-nan)]",
  "input": "\"abc\"",
  "outputs": [
    [
      null,
      null
    ]
  ],
  "error": null
}
{
  "script": "[.[] / \",\"]",
  "input": "[\"a, bc, def, ghij, jklmn, a,b, c,d, e,f\", \"a,b,c,d, e,f,g,h\"]",
  "outputs": [
    [
      [
        "a",
        " bc",
        " def",
        " ghij",
        " jklmn",
        " a",
        "b",
        " c",
        "d",
        " e",
        "f"
      ],
      [
        "a",
        "b",
        "c",
        "d",
        " e",
        "f",
        "g",
        "h"
      ]
    ]
  ],
  "error": null
}
{
  "script": "[.[] / \", \"]",
  "input": "[\"a, bc, def, ghij, jklmn, a,b, c,d, e,f\", \"a,b,c,d, e,f,g,h\"]",
  "outputs": [
    [
      [
        "a",
        "bc",
        "def",
        "ghij",
        "jklmn",
        "a,b",
        "c,d",
        "e,f"
      ],
      [
        "a,b,c,d",
        "e,f,g,h"
      ]
    ]
  ],
  "error": null
}
{
  "script": "map(.[1] as $needle | .[0] | contains($needle))",
  "input": "[[[],[]], [[1,2,3], [1,2]], [[1,2,3], [3,1]], [[1,2,3], [4]], [[1,2,3], [1,4]]]",
  "outputs": [
    [
      true,
      true,
      true,
      false,
      false
    ]
  ],
  "error": null
}
{
  "script": "map(.[1] as $needle | .[0] | contains($needle))",
  "input": "[[[\"foobar\", \"foobaz\"], [\"baz\", \"bar\"]], [[\"foobar\", \"foobaz\"], [\"foo\"]], [[\"foobar\", \"foobaz\"], [\"blap\"]]]",
  "outputs": [
    [
      true,
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[({foo: 12, bar:13} | contains({foo: 12})), ({foo: 12} | contains({})), ({foo: 12, bar:13} | contains({baz:14}))]",
  "input": "{}",
  "outputs": [
    [
      true,
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {}}})",
  "input": "{}",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "{foo: {baz: 12, blap: {bar: 13}}, bar: 14} | contains({bar: 14, foo: {blap: {bar: 14}}})",
  "input": "{}",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "sort",
  "input": "[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]",
  "outputs": [
    [
      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
      }
    ]
  ],
  "error": null
}
{
  "script": "(sort_by(.b) | sort_by(.a)), sort_by(.a, .b), sort_by(.b, .c), group_by(.b), group_by(.a + .b - .c == 2)",
  "input": "[{\"a\": 1, \"b\": 4, \"c\": 14}, {\"a\": 4, \"b\": 1, \"c\": 3}, {\"a\": 1, \"b\": 4, \"c\": 3}, {\"a\": 0, \"b\": 2, \"c\": 43}]",
  "outputs": [
    [
      {
        "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
        }
      ]
    ]
  ],
  "error": null
}
{
  "script": "unique",
  "input": "[1,2,5,3,5,3,1,3]",
  "outputs": [
    [
      1,
      2,
      3,
      5
    ]
  ],
  "error": null
}
{
  "script": "unique",
  "input": "[]",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "[min, max, min_by(.[1]), max_by(.[1]), min_by(.[2]), max_by(.[2])]",
  "input": "[[4,2,\"a\"],[3,1,\"a\"],[2,4,\"a\"],[1,3,\"a\"]]",
  "outputs": [
    [
      [
        1,
        3,
        "a"
      ],
      [
        4,
        2,
        "a"
      ],
      [
        3,
        1,
        "a"
      ],
      [
        2,
        4,
        "a"
      ],
      [
        4,
        2,
        "a"
      ],
      [
        1,
        3,
        "a"
      ]
    ]
  ],
  "error": null
}
{
  "script": "[min,max,min_by(.),max_by(.)]",
  "input": "[]",
  "outputs": [
    [
      null,
      null,
      null,
      null
    ]
  ],
  "error": null
}
{
  "script": ".foo[.baz]",
  "input": "{\"foo\":{\"bar\":4},\"baz\":\"bar\"}",
  "outputs": [
    4
  ],
  "error": null
}
{
  "script": ".[] | .error = \"no, it's OK\"",
  "input": "[{\"error\":true}]",
  "outputs": [
    {
      "error": "no, it's OK"
    }
  ],
  "error": null
}
{
  "script": "[{a:1}] | .[] | .a=999",
  "input": "null",
  "outputs": [
    {
      "a": 999
    }
  ],
  "error": null
}
{
  "script": "to_entries",
  "input": "{\"a\": 1, \"b\": 2}",
  "outputs": [
    [
      {
        "key": "a",
        "value": 1
      },
      {
        "key": "b",
        "value": 2
      }
    ]
  ],
  "error": null
}
{
  "script": "from_entries",
  "input": "[{\"key\":\"a\", \"value\":1}, {\"Key\":\"b\", \"Value\":2}, {\"name\":\"c\", \"value\":3}, {\"Name\":\"d\", \"Value\":4}]",
  "outputs": [
    {
      "a": 1,
      "b": 2,
      "c": 3,
      "d": 4
    }
  ],
  "error": null
}
{
  "script": "with_entries(.key |= \"KEY_\" + .)",
  "input": "{\"a\": 1, \"b\": 2}",
  "outputs": [
    {
      "KEY_a": 1,
      "KEY_b": 2
    }
  ],
  "error": null
}
{
  "script": "map(has(\"foo\"))",
  "input": "[{\"foo\": 42}, {}]",
  "outputs": [
    [
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "map(has(2))",
  "input": "[[0,1], [\"a\",\"b\",\"c\"]]",
  "outputs": [
    [
      false,
      true
    ]
  ],
  "error": null
}
{
  "script": "has(nan)",
  "input": "[0,1,2]",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "keys",
  "input": "[42,3,35]",
  "outputs": [
    [
      0,
      1,
      2
    ]
  ],
  "error": null
}
{
  "script": "[][.]",
  "input": "1000000000000000000",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": "map([1,2][0:.])",
  "input": "[-1, 1, 2, 3, 1000000000000000000]",
  "outputs": [
    [
      [
        1
      ],
      [
        1
      ],
      [
        1,
        2
      ],
      [
        1,
        2
      ],
      [
        1,
        2
      ]
    ]
  ],
  "error": null
}
{
  "script": "{\"k\": {\"a\": 1, \"b\": 2}} * .",
  "input": "{\"k\": {\"a\": 0,\"c\": 3}}",
  "outputs": [
    {
      "k": {
        "a": 0,
        "b": 2,
        "c": 3
      }
    }
  ],
  "error": null
}
{
  "script": "{\"k\": {\"a\": 1, \"b\": 2}, \"hello\": {\"x\": 1}} * .",
  "input": "{\"k\": {\"a\": 0,\"c\": 3}, \"hello\": 1}",
  "outputs": [
    {
      "k": {
        "a": 0,
        "b": 2,
        "c": 3
      },
      "hello": 1
    }
  ],
  "error": null
}
{
  "script": "{\"k\": {\"a\": 1, \"b\": 2}, \"hello\": 1} * .",
  "input": "{\"k\": {\"a\": 0,\"c\": 3}, \"hello\": {\"x\": 1}}",
  "outputs": [
    {
      "k": {
        "a": 0,
        "b": 2,
        "c": 3
      },
      "hello": {
        "x": 1
      }
    }
  ],
  "error": null
}
{
  "script": "{\"a\": {\"b\": 1}, \"c\": {\"d\": 2}, \"e\": 5} * .",
  "input": "{\"a\": {\"b\": 2}, \"c\": {\"d\": 3, \"f\": 9}}",
  "outputs": [
    {
      "a": {
        "b": 2
      },
      "c": {
        "d": 3,
        "f": 9
      },
      "e": 5
    }
  ],
  "error": null
}
{
  "script": "[.[]|arrays]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      [],
      [
        3,
        []
      ]
    ]
  ],
  "error": null
}
{
  "script": "[.[]|objects]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      {}
    ]
  ],
  "error": null
}
{
  "script": "[.[]|iterables]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      [],
      [
        3,
        []
      ],
      {}
    ]
  ],
  "error": null
}
{
  "script": "[.[]|scalars]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      1,
      2,
      "foo",
      true,
      false,
      null
    ]
  ],
  "error": null
}
{
  "script": "[.[]|values]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      1,
      2,
      "foo",
      [],
      [
        3,
        []
      ],
      {},
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[.[]|booleans]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      true,
      false
    ]
  ],
  "error": null
}
{
  "script": "[.[]|nulls]",
  "input": "[1,2,\"foo\",[],[3,[]],{},true,false,null]",
  "outputs": [
    [
      null
    ]
  ],
  "error": null
}
{
  "script": "flatten",
  "input": "[0, [1], [[2]], [[[3]]]]",
  "outputs": [
    [
      0,
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "flatten(0)",
  "input": "[0, [1], [[2]], [[[3]]]]",
  "outputs": [
    [
      0,
      [
        1
      ],
      [
        [
          2
        ]
      ],
      [
        [
          [
            3
          ]
        ]
      ]
    ]
  ],
  "error": null
}
{
  "script": "flatten(2)",
  "input": "[0, [1], [[2]], [[[3]]]]",
  "outputs": [
    [
      0,
      1,
      2,
      [
        3
      ]
    ]
  ],
  "error": null
}
{
  "script": "flatten(2)",
  "input": "[0, [1, [2]], [1, [[3], 2]]]",
  "outputs": [
    [
      0,
      1,
      2,
      1,
      [
        3
      ],
      2
    ]
  ],
  "error": null
}
{
  "script": "try flatten(-1) catch .",
  "input": "[0, [1], [[2]], [[[3]]]]",
  "outputs": [
    "flatten depth must not be negative"
  ],
  "error": null
}
{
  "script": "transpose",
  "input": "[[1], [2,3]]",
  "outputs": [
    [
      [
        1,
        2
      ],
      [
        null,
        3
      ]
    ]
  ],
  "error": null
}
{
  "script": "transpose",
  "input": "[]",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "ascii_upcase",
  "input": "\"useful but not for é\"",
  "outputs": [
    "USEFUL BUT NOT FOR é"
  ],
  "error": null
}
{
  "script": "bsearch(0,2,4)",
  "input": "[1,2,3]",
  "outputs": [
    -1,
    1,
    -4
  ],
  "error": null
}
{
  "script": "strftime(\"%Y-%m-%dT%H:%M:%SZ\")",
  "input": "[2015,2,5,23,51,47,4,63]",
  "outputs": [
    "2015-03-05T23:51:47Z"
  ],
  "error": null
}
{
  "script": "strftime(\"%A, %B %d, %Y\")",
  "input": "1435677542.822351",
  "outputs": [
    "Tuesday, June 30, 2015"
  ],
  "error": null
}
{
  "script": "gmtime",
  "input": "1425599507",
  "outputs": [
    [
      2015,
      2,
      5,
      23,
      51,
      47,
      4,
      63
    ]
  ],
  "error": null
}
{
  "script": "try strftime(\"%Y-%m-%dT%H:%M:%SZ\") catch .",
  "input": "[\"a\",1,2,3,4,5,6,7]",
  "outputs": [
    "strftime/1 requires parsed datetime inputs"
  ],
  "error": null
}
{
  "script": "try strflocaltime(\"%Y-%m-%dT%H:%M:%SZ\") catch .",
  "input": "[\"a\",1,2,3,4,5,6,7]",
  "outputs": [
    "strflocaltime/1 requires parsed datetime inputs"
  ],
  "error": null
}
{
  "script": "try mktime catch .",
  "input": "[\"a\",1,2,3,4,5,6,7]",
  "outputs": [
    "mktime requires parsed datetime inputs"
  ],
  "error": null
}
{
  "script": "import \"a\" as foo; import \"b\" as bar; def fooa: foo::a; [fooa, bar::a, bar::b, foo::a]",
  "input": "null",
  "outputs": [
    [
      "a",
      "b",
      "c",
      "a"
    ]
  ],
  "error": null
}
{
  "script": "import \"c\" as foo; [foo::a, foo::c]",
  "input": "null",
  "outputs": [
    [
      0,
      "acmehbah"
    ]
  ],
  "error": null
}
{
  "script": "include \"c\"; [a, c]",
  "input": "null",
  "outputs": [
    [
      0,
      "acmehbah"
    ]
  ],
  "error": null
}
{
  "script": "import \"data\" as $e; import \"data\" as $d; [$d[].this,$e[].that,$d::d[].this,$e::e[].that]|join(\";\")",
  "input": "null",
  "outputs": [
    "is a test;is too;is a test;is too"
  ],
  "error": null
}
{
  "script": "import \"data\" as $a; import \"data\" as $b; def f: {$a, $b}; f",
  "input": "null",
  "outputs": [
    {
      "a": [
        {
          "this": "is a test",
          "that": "is too"
        }
      ],
      "b": [
        {
          "this": "is a test",
          "that": "is too"
        }
      ]
    }
  ],
  "error": null
}
{
  "script": "include \"shadow1\"; e",
  "input": "null",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": "include \"shadow1\"; include \"shadow2\"; e",
  "input": "null",
  "outputs": [
    3
  ],
  "error": null
}
{
  "script": "import \"shadow1\" as f; import \"shadow2\" as f; import \"shadow1\" as e; [e::e, f::e]",
  "input": "null",
  "outputs": [
    [
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "module (.+1); 0",
  "input": null,
  "outputs": null,
  "error": "jq: error: Module metadata must be constant at <top-level>, line 1:"
}
{
  "script": "module []; 0",
  "input": null,
  "outputs": null,
  "error": "jq: error: Module metadata must be an object at <top-level>, line 1:"
}
{
  "script": "include \"a\" (.+1); 0",
  "input": null,
  "outputs": null,
  "error": "jq: error: Module metadata must be constant at <top-level>, line 1:"
}
{
  "script": "include \"a\" []; 0",
  "input": null,
  "outputs": null,
  "error": "jq: error: Module metadata must be an object at <top-level>, line 1:"
}
{
  "script": "include \"\\ \"; 0",
  "input": null,
  "outputs": null,
  "error": "jq: error: Invalid escape at line 1, column 4 (while parsing '\"\\ \"') at <top-level>, line 1:"
}
{
  "script": "include \"\\(a)\"; 0",
  "input": null,
  "outputs": null,
  "error": "jq: error: Import path must be constant at <top-level>, line 1:"
}
{
  "script": "modulemeta",
  "input": "\"c\"",
  "outputs": [
    {
      "whatever": null,
      "deps": [
        {
          "as": "foo",
          "is_data": false,
          "relpath": "a"
        },
        {
          "search": "./",
          "as": "d",
          "is_data": false,
          "relpath": "d"
        },
        {
          "search": "./",
          "as": "d2",
          "is_data": false,
          "relpath": "d"
        },
        {
          "search": "./../lib/jq",
          "as": "e",
          "is_data": false,
          "relpath": "e"
        },
        {
          "search": "./../lib/jq",
          "as": "f",
          "is_data": false,
          "relpath": "f"
        },
        {
          "as": "d",
          "is_data": true,
          "relpath": "data"
        }
      ],
      "defs": [
        "a/0",
        "c/0"
      ]
    }
  ],
  "error": null
}
{
  "script": "modulemeta | .deps | length",
  "input": "\"c\"",
  "outputs": [
    6
  ],
  "error": null
}
{
  "script": "modulemeta | .defs | length",
  "input": "\"c\"",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": "import \"syntaxerror\" as e; .",
  "input": null,
  "outputs": null,
  "error": null
}
{
  "script": "%::wat",
  "input": null,
  "outputs": null,
  "error": null
}
{
  "script": "import \"test_bind_order\" as check; check::check",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "try -. catch .",
  "input": "\"very-long-string\"",
  "outputs": [
    "string (\"very-long-...) cannot be negated"
  ],
  "error": null
}
{
  "script": "join(\",\")",
  "input": "[\"1\",2,true,false,3.4]",
  "outputs": [
    "1,2,true,false,3.4"
  ],
  "error": null
}
{
  "script": ".[] | join(\",\")",
  "input": "[[], [null], [null,null], [null,null,null]]",
  "outputs": [
    "",
    "",
    ",",
    ",,"
  ],
  "error": null
}
{
  "script": ".[] | join(\",\")",
  "input": "[[\"a\",null], [null,\"a\"]]",
  "outputs": [
    "a,",
    ",a"
  ],
  "error": null
}
{
  "script": "try join(\",\") catch .",
  "input": "[\"1\",\"2\",{\"a\":{\"b\":{\"c\":33}}}]",
  "outputs": [
    "string (\"1,2,\") and object ({\"a\":{\"b\":{...) cannot be added"
  ],
  "error": null
}
{
  "script": "try join(\",\") catch .",
  "input": "[\"1\",\"2\",[3,4,5]]",
  "outputs": [
    "string (\"1,2,\") and array ([3,4,5]) cannot be added"
  ],
  "error": null
}
{
  "script": "{if:0,and:1,or:2,then:3,else:4,elif:5,end:6,as:7,def:8,reduce:9,foreach:10,try:11,catch:12,label:13,import:14,include:15,module:16}",
  "input": "null",
  "outputs": [
    {
      "if": 0,
      "and": 1,
      "or": 2,
      "then": 3,
      "else": 4,
      "elif": 5,
      "end": 6,
      "as": 7,
      "def": 8,
      "reduce": 9,
      "foreach": 10,
      "try": 11,
      "catch": 12,
      "label": 13,
      "import": 14,
      "include": 15,
      "module": 16
    }
  ],
  "error": null
}
{
  "script": "try (1/.) catch .",
  "input": "0",
  "outputs": [
    "number (1) and number (0) cannot be divided because the divisor is zero"
  ],
  "error": null
}
{
  "script": "try (1/0) catch .",
  "input": "0",
  "outputs": [
    "number (1) and number (0) cannot be divided because the divisor is zero"
  ],
  "error": null
}
{
  "script": "try (0/0) catch .",
  "input": "0",
  "outputs": [
    "number (0) and number (0) cannot be divided because the divisor is zero"
  ],
  "error": null
}
{
  "script": "try (1%.) catch .",
  "input": "0",
  "outputs": [
    "number (1) and number (0) cannot be divided (remainder) because the divisor is zero"
  ],
  "error": null
}
{
  "script": "try (1%0) catch .",
  "input": "0",
  "outputs": [
    "number (1) and number (0) cannot be divided (remainder) because the divisor is zero"
  ],
  "error": null
}
{
  "script": "[range(-52;52;1)] as $powers | [$powers[]|pow(2;.)|log2|round] == $powers",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "[range(-99/2;99/2;1)] as $orig | [$orig[]|pow(2;.)|log2] as $back | ($orig|keys)[]|. as $k | (($orig|.[$k])-($back|.[$k]))|if . < 0 then . * -1 else . end|select(.>.00005)",
  "input": "null",
  "outputs": [],
  "error": null
}
{
  "script": "}",
  "input": null,
  "outputs": null,
  "error": null
}
{
  "script": "(.[{}] = 0)?",
  "input": "null",
  "outputs": [],
  "error": null
}
{
  "script": "INDEX(range(5)|[., \"foo\\(.)\"]; .[0])",
  "input": "null",
  "outputs": [
    {
      "0": [
        0,
        "foo0"
      ],
      "1": [
        1,
        "foo1"
      ],
      "2": [
        2,
        "foo2"
      ],
      "3": [
        3,
        "foo3"
      ],
      "4": [
        4,
        "foo4"
      ]
    }
  ],
  "error": null
}
{
  "script": "JOIN({\"0\":[0,\"abc\"],\"1\":[1,\"bcd\"],\"2\":[2,\"def\"],\"3\":[3,\"efg\"],\"4\":[4,\"fgh\"]}; .[0]|tostring)",
  "input": "[[5,\"foo\"],[3,\"bar\"],[1,\"foobar\"]]",
  "outputs": [
    [
      [
        [
          5,
          "foo"
        ],
        null
      ],
      [
        [
          3,
          "bar"
        ],
        [
          3,
          "efg"
        ]
      ],
      [
        [
          1,
          "foobar"
        ],
        [
          1,
          "bcd"
        ]
      ]
    ]
  ],
  "error": null
}
{
  "script": "range(5;10)|IN(range(10))",
  "input": "null",
  "outputs": [
    true,
    true,
    true,
    true,
    true
  ],
  "error": null
}
{
  "script": "range(5;13)|IN(range(0;10;3))",
  "input": "null",
  "outputs": [
    false,
    true,
    false,
    false,
    true,
    false,
    false,
    false
  ],
  "error": null
}
{
  "script": "range(10;12)|IN(range(10))",
  "input": "null",
  "outputs": [
    false,
    false
  ],
  "error": null
}
{
  "script": "IN(range(10;20); range(10))",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "IN(range(5;20); range(10))",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "(.a as $x | .b) = \"b\"",
  "input": "{\"a\":null,\"b\":null}",
  "outputs": [
    {
      "a": null,
      "b": "b"
    }
  ],
  "error": null
}
{
  "script": "(.. | select(type == \"object\" and has(\"b\") and (.b | type) == \"array\")|.b) |= .[0]",
  "input": "{\"a\": {\"b\": [1, {\"b\": 3}]}}",
  "outputs": [
    {
      "a": {
        "b": 1
      }
    }
  ],
  "error": null
}
{
  "script": "isempty(empty)",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "isempty(range(3))",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "isempty(1,error(\"foo\"))",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "index(\"\")",
  "input": "\"\"",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": "builtins|length > 10",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "\"-1\"|IN(builtins[] / \"/\"|.[1])",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "all(builtins[] / \"/\"; .[1]|tonumber >= 0)",
  "input": "null",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "builtins|any(.[:1] == \"_\")",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": "map(. == 1)",
  "input": "[1, 1.0, 1.000, 100e-2, 1e+0, 0.0001e4]",
  "outputs": [
    [
      true,
      true,
      true,
      true,
      true,
      true
    ]
  ],
  "error": null
}
{
  "script": ".[0] | tostring",
  "input": "[13911860366432393]",
  "outputs": [
    "13911860366432393"
  ],
  "error": null
}
{
  "script": ".x | tojson",
  "input": "{\"x\":13911860366432393}",
  "outputs": [
    "13911860366432393"
  ],
  "error": null
}
{
  "script": "13911860366432393 == 13911860366432392",
  "input": "null",
  "outputs": [
    false
  ],
  "error": null
}
{
  "script": ". - 10",
  "input": "13911860366432393",
  "outputs": [
    13911860366432382
  ],
  "error": null
}
{
  "script": ".[0] - 10",
  "input": "[13911860366432393]",
  "outputs": [
    13911860366432382
  ],
  "error": null
}
{
  "script": ".x - 10",
  "input": "{\"x\":13911860366432393}",
  "outputs": [
    13911860366432382
  ],
  "error": null
}
{
  "script": ". |= try . catch .",
  "input": "1",
  "outputs": [
    1
  ],
  "error": null
}
{
  "script": "abs",
  "input": "\"abc\"",
  "outputs": [
    "abc"
  ],
  "error": null
}
{
  "script": "map(abs)",
  "input": "[-0, 0, -10, -1.1]",
  "outputs": [
    [
      0,
      0,
      10,
      1.1
    ]
  ],
  "error": null
}
{
  "script": "map(fabs == length) | unique",
  "input": "[-10, -1.1, -1e-1, 1000000000000000002]",
  "outputs": [
    [
      true
    ]
  ],
  "error": null
}
{
  "script": "map(abs)",
  "input": "[0.1,1000000000000000002]",
  "outputs": [
    [
      0.1,
      1000000000000000002
    ]
  ],
  "error": null
}
{
  "script": "123 as $label | $label",
  "input": "null",
  "outputs": [
    123
  ],
  "error": null
}
{
  "script": "[ label $if | range(10) | ., (select(. == 5) | break $if) ]",
  "input": "null",
  "outputs": [
    [
      0,
      1,
      2,
      3,
      4,
      5
    ]
  ],
  "error": null
}
{
  "script": "reduce .[] as $then (4 as $else | $else; . as $elif | . + $then * $elif)",
  "input": "[1,2,3]",
  "outputs": [
    96
  ],
  "error": null
}
{
  "script": "1 as $foreach | 2 as $and | 3 as $or | { $foreach, $and, $or, a }",
  "input": "{\"a\":4,\"b\":5}",
  "outputs": [
    {
      "foreach": 1,
      "and": 2,
      "or": 3,
      "a": 4
    }
  ],
  "error": null
}
{
  "script": "[ foreach .[] as $try (1 as $catch | $catch - 1; . + $try; .) ]",
  "input": "[10,9,8,7]",
  "outputs": [
    [
      10,
      19,
      27,
      34
    ]
  ],
  "error": null
}
{
  "script": "{ a, $__loc__, c }",
  "input": "{\"a\":[1,2,3],\"b\":\"foo\",\"c\":{\"hi\":\"hey\"}}",
  "outputs": [
    {
      "a": [
        1,
        2,
        3
      ],
      "__loc__": {
        "file": "<top-level>",
        "line": 1
      },
      "c": {
        "hi": "hey"
      }
    }
  ],
  "error": null
}
{
  "script": "1 as $x | \"2\" as $y | \"3\" as $z | { $x, as, $y: 4, ($z): 5, if: 6, foo: 7 }",
  "input": "{\"as\":8}",
  "outputs": [
    {
      "x": 1,
      "as": 8,
      "2": 4,
      "3": 5,
      "if": 6,
      "foo": 7
    }
  ],
  "error": null
}
{
  "script": "fromjson | isnan",
  "input": "\"nan\"",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "tojson | fromjson",
  "input": "{\"a\":nan}",
  "outputs": [
    {
      "a": null
    }
  ],
  "error": null
}
{
  "script": "try input catch .",
  "input": "null",
  "outputs": [
    "break"
  ],
  "error": null
}
{
  "script": "debug",
  "input": "1",
  "outputs": [
    1
  ],
  "error": null
}
{
  "script": "\"foo\" | try ((try . catch \"caught too much\") | error) catch \"caught just right\"",
  "input": "null",
  "outputs": [
    "caught just right"
  ],
  "error": null
}
{
  "script": ".[]|(try (if .==\"hi\" then . else error end) catch empty) | \"\\(.) there!\"",
  "input": "[\"hi\",\"ho\"]",
  "outputs": [
    "hi there!"
  ],
  "error": null
}
{
  "script": "try ([\"hi\",\"ho\"]|.[]|(try . catch (if .==\"ho\" then \"BROKEN\"|error else empty end)) | if .==\"ho\" then error else \"\\(.) there!\" end) catch \"caught outside \\(.)\"",
  "input": "null",
  "outputs": [
    "hi there!",
    "caught outside ho"
  ],
  "error": null
}
{
  "script": ".[]|(try . catch (if .==\"ho\" then \"BROKEN\"|error else empty end)) | if .==\"ho\" then error else \"\\(.) there!\" end",
  "input": "[\"hi\",\"ho\"]",
  "outputs": [
    "hi there!"
  ],
  "error": null
}
{
  "script": "try (try error catch \"inner catch \\(.)\") catch \"outer catch \\(.)\"",
  "input": "\"foo\"",
  "outputs": [
    "inner catch foo"
  ],
  "error": null
}
{
  "script": "try ((try error catch \"inner catch \\(.)\")|error) catch \"outer catch \\(.)\"",
  "input": "\"foo\"",
  "outputs": [
    "outer catch inner catch foo"
  ],
  "error": null
}
{
  "script": "first(.?,.?)",
  "input": "null",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": "{foo: \"bar\"} | .foo |= .?",
  "input": "null",
  "outputs": [
    {
      "foo": "bar"
    }
  ],
  "error": null
}
{
  "script": ". |= try 2",
  "input": "1",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": ". |= try 2 catch 3",
  "input": "1",
  "outputs": [
    2
  ],
  "error": null
}
{
  "script": ".[] |= try tonumber",
  "input": "[\"1\", \"2a\", \"3\", 4]",
  "outputs": [
    [
      1,
      3,
      4
    ]
  ],
  "error": null
}
{
  "script": "any(keys[]|tostring?;true)",
  "input": "{\"a\":\"1\",\"b\":\"2\",\"c\":\"3\"}",
  "outputs": [
    true
  ],
  "error": null
}
{
  "script": "implode|explode",
  "input": "[-1,0,1,2,3,1114111,1114112,55295,55296,57343,57344,1.1,1.9]",
  "outputs": [
    [
      65533,
      0,
      1,
      2,
      3,
      1114111,
      65533,
      55295,
      65533,
      65533,
      57344,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "map(try implode catch .)",
  "input": "[123,[\"a\"],[nan]]",
  "outputs": [
    [
      "implode input must be an array",
      "string (\"a\") can't be imploded, unicode codepoint needs to be numeric",
      "number (null) can't be imploded, unicode codepoint needs to be numeric"
    ]
  ],
  "error": null
}
{
  "script": "walk(.)",
  "input": "{\"x\":0}",
  "outputs": [
    {
      "x": 0
    }
  ],
  "error": null
}
{
  "script": "walk(1)",
  "input": "{\"x\":0}",
  "outputs": [
    1
  ],
  "error": null
}
{
  "script": "[walk(.,1)]",
  "input": "{\"x\":0}",
  "outputs": [
    [
      {
        "x": 0
      },
      1
    ]
  ],
  "error": null
}
{
  "script": "walk(select(IN({}, []) | not))",
  "input": "{\"a\":1,\"b\":[]}",
  "outputs": [
    {
      "a": 1
    }
  ],
  "error": null
}
{
  "script": "[range(10)] | .[1.2:3.5]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "[range(10)] | .[1.5:3.5]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "[range(10)] | .[1.7:3.5]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      3
    ]
  ],
  "error": null
}
{
  "script": "[range(10)] | .[1.7:4294967295]",
  "input": "null",
  "outputs": [
    [
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9
    ]
  ],
  "error": null
}
{
  "script": "[range(10)] | .[1.7:-4294967296]",
  "input": "null",
  "outputs": [
    []
  ],
  "error": null
}
{
  "script": "[[range(10)] | .[1.1,1.5,1.7]]",
  "input": "null",
  "outputs": [
    [
      1,
      1,
      1
    ]
  ],
  "error": null
}
{
  "script": "[range(5)] | .[1.1] = 5",
  "input": "null",
  "outputs": [
    [
      0,
      5,
      2,
      3,
      4
    ]
  ],
  "error": null
}
{
  "script": "[range(3)] | .[nan:1]",
  "input": "null",
  "outputs": [
    [
      0
    ]
  ],
  "error": null
}
{
  "script": "[range(3)] | .[1:nan]",
  "input": "null",
  "outputs": [
    [
      1,
      2
    ]
  ],
  "error": null
}
{
  "script": "[range(3)] | .[nan]",
  "input": "null",
  "outputs": [
    null
  ],
  "error": null
}
{
  "script": "try ([range(3)] | .[nan] = 9) catch .",
  "input": "null",
  "outputs": [
    "Cannot set array element at NaN index"
  ],
  "error": null
}
{
  "script": "try (\"foobar\" | .[1.5:3.5] = \"xyz\") catch .",
  "input": "null",
  "outputs": [
    "Cannot update string slices"
  ],
  "error": null
}
{
  "script": "try ([range(10)] | .[1.5:3.5] = [\"xyz\"]) catch .",
  "input": "null",
  "outputs": [
    [
      0,
      "xyz",
      4,
      5,
      6,
      7,
      8,
      9
    ]
  ],
  "error": null
}
{
  "script": "try (\"foobar\" | .[1.5]) catch .",
  "input": "null",
  "outputs": [
    "Cannot index string with number"
  ],
  "error": null
}

@emanuele6
Copy link
Member

emanuele6 commented Nov 1, 2023

@nicowilliams

It's JSON. RFC 7259 JSON. We should make sure it's also RFC 8259 JSON. It is NOT JSON5. I don't believe we've ever claimed that jq supports JSON5 -- it does not.

EDIT: I should point out that we don't actually test conformance to RFC 7259 / 8259, but that is what we aim to support at this time.

NaN/Infinity etc are not standard JSON, they are not valid in JSON grammar, not even RFC 7259. It's a jq extensions to allow them in inputs. jq can read them from inputs thanks to decNumber.

jq will never write NaN or Infinity or similar in its JSON output or in the return value of tojson/tostring. They get converted to valid JSON "equivalents", null for NaNs, DBL_MAX for Infinity and -DBL_MAX for -Infinity.

@nicowilliams
Copy link
Contributor

@nicowilliams

It's JSON. RFC 7259 JSON. We should make sure it's also RFC 8259 JSON. It is NOT JSON5. I don't believe we've ever claimed that jq supports JSON5 -- it does not.
EDIT: I should point out that we don't actually test conformance to RFC 7259 / 8259, but that is what we aim to support at this time.

NaN/Infinity etc are not standard JSON, they are not valid in JSON grammar, not even RFC 7259. It's a jq extensions to allow them in inputs. jq can read them from inputs thanks to decNumber.

jq will never write NaN or Infinity or similar in its JSON output or in the return value of tojson/tostring. They get converted to valid JSON "equivalents", null for NaNs, DBL_MAX for Infinity and -DBL_MAX for -Infinity.

Yes, we have extensions. I was referring to what we output, but indeed we accept more than what we output.

@baterflyrity
Copy link
Author

Thanks, I got more appropriate understanding of syntax.

One more question. How to distinguish runtime errors and empty output cases?

@nicowilliams
Copy link
Contributor

One more question. How to distinguish runtime errors and empty output cases?

try/catch

@baterflyrity
Copy link
Author

One more question. How to distinguish runtime errors and empty output cases?

try/catch

So stderr and exit code are fully ignored until %%FAIL directive?

@nicowilliams
Copy link
Contributor

So stderr and exit code are fully ignored until %%FAIL directive?

%%FAIL is for compilation errors. There's no exit code involved here. Output to stderr is not an error. I'm not sure you understand what you're doing. Please, for your bindings, do not attempt to use the --run-tests input file format.

@baterflyrity
Copy link
Author

Hi! Can you please point out what is wrong with my jq-1.7-dirty tests in windows cmd?

  1. Why does -13 is applied? Ive checked double limit on my machine and it is still 1.8e308/
$ echo 13911860366432393 | jq ".-10"
13911860366432380

Corresponding test is:

. - 10
13911860366432393
13911860366432382

which correctly passes as Test #392: '. - 10' at line number 1854.

  1. I can not obtain good encoding for strftime. Consume this test:
strftime("%A, %B %d, %Y")
1435677542.822351
"Tuesday, June 30, 2015"

which fails as *** Expected "Tuesday, June 30, 2015", but got "пїЅпїЅпїЅпїЅпїЅпїЅпїЅ, пїЅпїЅпїЅпїЅ 30, 2015" for test at line number 1564: strftime("%A, %B %d, %Y").

I can get �������, ���� via windows-1251 encoding or �������, ���� via utf-8 encoding.

@wader
Copy link
Member

wader commented Nov 15, 2023

Hi! Can you please point out what is wrong with my jq-1.7-dirty tests in windows cmd?

  1. Why does -13 is applied? Ive checked double limit on my machine and it is still 1.8e308/
$ echo 13911860366432393 | jq ".-10"
13911860366432380

This is probably because a 64 bit double can only store integers exactly for -2^53 to 2^53.

Corresponding test is:

. - 10
13911860366432393
13911860366432382

which correctly passes as Test #392: '. - 10' at line number 1854.

As some some arithmetics is done i think this boils down to that the numbers are compared as doubles.

@baterflyrity
Copy link
Author

baterflyrity commented Nov 16, 2023

@wader

This is probably because a 64 bit double can only store integers exactly for -2^53 to 2^53.

Thanks. Maybe I do not understand something but 64 bits of double can store 18446744073709551616 and 53 bits of mantissa fraction can store 9007199254740992 while 13911860366432393 is actually 2^53.6. Moreover the closest double (according to random online calculator) is 1.3911860366432394E16=13911860366432394.

So if math uses 53 fraction bits It should be 13911860366432393-10→9007199254740992 -10=9007199254740982 but jq binary prints 13911860366432380. Alternatively if math converts int to double it should be 13911860366432393-10→13911860366432394-10=13911860366432384.

Can you please explain jq math?

@emanuele6
Copy link
Member

It is like javascript maths:

$ node -p '13911860366432393 - 10'
13911860366432382

@baterflyrity
Copy link
Author

$ echo 13911860366432393 | jq ".-10"
13911860366432380

Ok, thanks, i will read more about it.

But what about this?

$ echo 13911860366432393 | jq ".-10"
13911860366432380

@wader
Copy link
Member

wader commented Nov 16, 2023

@wader

This is probably because a 64 bit double can only store integers exactly for -2^53 to 2^53.

Thanks. Maybe I do not understand something but 64 bits of double can store 18446744073709551616 and 53 bits of mantissa fraction can store 9007199254740992 while 13911860366432393 is actually 2^53.6. Moreover the closest double (according to random online calculator) is 1.3911860366432394E16=13911860366432394.

So if math uses 53 fraction bits It should be 13911860366432393-10→9007199254740992 -10=9007199254740982 but jq binary prints 13911860366432380. Alternatively if math converts int to double it should be 13911860366432393-10→13911860366432394-10=13911860366432384.

Can you please explain jq math?

If you don't do any arithmetic then jq will preserve and "passthru" big integers but once you do any operations on them they will behave as 64bit floats.

Sorry i'm far from a floating point math expert so can't really help explain why the minus operation behave the way it does but i'm quite sure both 18446744073709551616 and 13911860366432393 are beyond the range for storing integers exactly so might get truncated and things might behave unexpectedly.

You can use node to observe the same behaviour:

$ node -e 'console.log(18446744073709551616)'
18446744073709552000
$ node -e 'console.log(13911860366432393)'
13911860366432392

Why node and jq differ in this case below can't explain. Maybe we have our own float parser or printer that behave differently when beyond the integer range?

$ node -e 'console.log(13911860366432393-10)'
13911860366432382
$ jq -n '13911860366432393-10'
13911860366432380

@wader
Copy link
Member

wader commented Nov 17, 2023

jq built with --disable-decnum gives same result as node. Is there something fishy going on in the decnum code or is this just ok wiggle room for a float implementation?

$ echo 13911860366432393 | ./jq '.-10'
13911860366432382

@baterflyrity
Copy link
Author

baterflyrity commented Nov 17, 2023

@wader, yes, this is really out of my mind. Moreover Ive tested downloadable binaries and they give me 13911860366432380 in both windows and linux while I can not see failed tests in github ci.

Maybe it is worth to create separate issue for this?

@wader
Copy link
Member

wader commented Nov 17, 2023

Yeap i think so. I dugg a bit more and it seems like this is a change/regression since 680baef before that jq behaved the same as node (and gojq):

# node
$ node -p '13911860366432393'
13911860366432392

# gojq
$ gojq -n '13911860366432393 + 0.0'
13911860366432392

# jq 1.7
$ echo 13911860366432393 | jq '.+0'
13911860366432390

# jq 680baeffeb7983e7570b5e68db07fe47f94db8c7~1
$ echo 13911860366432393 | ./jq '.+0'
13911860366432392

The breaking change seem to be the change of dec_ctx_dbl_key's decContext.digits from 17 to 16. Before we set it explicit to 17 (via the constant BIN64_DEC_PRECISION) but now we use decContextDefault(ctx, DEC_INIT_DECIMAL64) which will set it to 16. With a modify DEC_INIT_DECIMAL64 case in decContextDefault to set context->digits=17 and set DEC_NUBMER_DOUBLE_PRECISION to 17 it seems to work as before again.

I'm not familiar with the decnum code at all so don't know if there is something else needed or if there is a better way? maybe this just fixes these partiuclar cases?

@wader
Copy link
Member

wader commented Nov 22, 2023

make check with valgrind enabled seem to work fine with this patch

diff --git a/src/decNumber/decContext.c b/src/decNumber/decContext.c
index 9f99759..9806cbd 100644
--- a/src/decNumber/decContext.c
+++ b/src/decNumber/decContext.c
@@ -97,7 +97,7 @@ decContext * decContextDefault(decContext *context, Int kind) {
       #endif
       break;
     case DEC_INIT_DECIMAL64:
-      context->digits=16;                    // digits
+      context->digits=17;                    // digits
       context->emax=384;                     // Emax
       context->emin=-383;                    // Emin
       context->round=DEC_ROUND_HALF_EVEN;    // 0.5 to nearest even
diff --git a/src/jv.c b/src/jv.c
index ada15fe..811c569 100644
--- a/src/jv.c
+++ b/src/jv.c
@@ -213,7 +213,7 @@ enum {
 #define JVP_FLAGS_NUMBER_LITERAL      JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
 
 // the decimal precision of binary double
-#define DEC_NUBMER_DOUBLE_PRECISION   (16)
+#define DEC_NUBMER_DOUBLE_PRECISION   (17)
 #define DEC_NUMBER_STRING_GUARD       (14)
 #define DEC_NUBMER_DOUBLE_EXTRA_UNITS ((DEC_NUBMER_DOUBLE_PRECISION - DECNUMDIGITS + DECDPUN - 1)/DECDPUN)

I think the reason why the jq test pass with and without the patch is becuase it ends up comparing a double and decnum so the decnum will be converted and truncated to a double also.

# 1.7
$ jq -n '13911860366432393-10 | ., . == 13911860366432382'
13911860366432380
true

# master with patch
$ ./jq -n '13911860366432393-10 | ., . == 13911860366432382'
13911860366432382
true

@baterflyrity
Copy link
Author

Great job!

I think the reason why the jq test pass with and without the patch is becuase it ends up comparing a double and decnum so the decnum will be converted and truncated to a double also.

I think so too. Hence the test actually checks truncation instead of arithmetic. Guess it should be rewritten into multiple "single responsibility" tests.

@wader
Copy link
Member

wader commented Nov 22, 2023

@leonid-s-usov any ideas?

@leonid-s-usov
Copy link
Contributor

@wader I've spent some time refreshing my memory about this. There were several changes and fixes that got us to this point.

It's true that the Wikipedia states that the decimal representation of a double precision that carries 17 digits should be sufficient to convert from the floating point to decimal and back arriving at the same floating point number.

The original implementation of the decimal number support has used 17 as the conversion setting.

Later @itchyny discovered and fixed an issue with the conversion, and along with that change we've also updated the double decimal representation of the number to 16 digits.

The formal document analyzing the decimal64 format claims that 16 is the correct number of decimal digits, see https://speleotrove.com/decimal/dbspec.html

Here we may be confusing the double precision floating point and decimal64. So, given that we want to be consistent with the double floating point math, we may want to bump up the decimal representation digit count to 17 again, though losing formal consistency with the decimal64 format (not an issue, but important to mention). I think you can proceed with your patch above, given of course that we don't see any regression, specifically with #2804

@leonid-s-usov
Copy link
Contributor

leonid-s-usov commented Nov 23, 2023

@wader just one thing I missed: please don't change the DEC_INIT_DECIMAL64 case in the decNumber library. It's correct as it's following the IEEE standard for the DECIMAL64 type.
We only want to change the conversion settings used in our jq code, and for that, technically, it should be sufficient to only update the corresponding constant DEC_NUBMER_DOUBLE_PRECISION in the jv.c

This means that we should not use the decContextDefault(ctx, DEC_INIT_DECIMAL64); to initialize our dec context but rather manually set it up with the values we need.

@leonid-s-usov
Copy link
Contributor

Sorry, I keep going :)

So, we could argue that the observed behavior was "as designed" if we also mentioned that by using --enable-decnum one accepts that internally the numbers will be represented by an IEEE decimal64 instead of a binary64 (aka double)

Please note that apart from the number of decimal digits, there's also a different exponent range between decimal and binary formats: [−383 to +384] vs [−1022 to +1023]. When fixing #2804 we haven't thought of this side effect of moving to the standard decimal64 representation.

But given this thread of discussion, and also generally taking the original jq as the desired behavior, we should probably revise our DEC_CONTEXT_TO_DOUBLE initialization and make sure that it supports seamless conversion from/to binary64, and we should then add tests that verify that behavior.

@wader
Copy link
Member

wader commented Nov 23, 2023

@wader I've spent some time refreshing my memory about this. There were several changes and fixes that got us to this point.

Thanks, very appreciated!

It's true that the Wikipedia states that the decimal representation of a double precision that carries 17 digits should be sufficient to convert from the floating point to decimal and back arriving at the same floating point number.

The original implementation of the decimal number support has used 17 as the conversion setting.

Later @itchyny discovered and fixed an issue with the conversion, and along with that change we've also updated the double decimal representation of the number to 16 digits.

The formal document analyzing the decimal64 format claims that 16 is the correct number of decimal digits, see https://speleotrove.com/decimal/dbspec.html

Here we may be confusing the double precision floating point and decimal64. So, given that we want to be consistent with the double floating point math, we may want to bump up the decimal representation digit count to 17 again, though losing formal consistency with the decimal64 format (not an issue, but important to mention). I think you can proceed with your patch above, given of course that we don't see any regression, specifically with #2804

Ok that makes sense. I was also confused and also didn't noticed this was about decimal64, not that I know much how they are different... but now based on the their names it makes much more sense :)

@wader just one thing I missed: please don't change the DEC_INIT_DECIMAL64 case in the decNumber library. It's correct as it's following the IEEE standard for the DECIMAL64 type. We only want to change the conversion settings used in our jq code, and for that, technically, it should be sufficient to only update the corresponding constant DEC_NUBMER_DOUBLE_PRECISION in the jv.c

This means that we should not use the decContextDefault(ctx, DEC_INIT_DECIMAL64); to initialize our dec context but rather manually set it up with the values we need.

Yeap that was mostly to test :) now I copied out the DEC_INIT_DECIMAL64 values and changed digits to DEC_NUBMER_DOUBLE_PRECISION (17).

Sorry, I keep going :)

No worries, much approved

So, we could argue that the observed behavior was "as designed" if we also mentioned that by using --enable-decnum one accepts that internally the numbers will be represented by an IEEE decimal64 instead of a binary64 (aka double)

Please note that apart from the number of decimal digits, there's also a different exponent range between decimal and binary formats: [−383 to +384] vs [−1022 to +1023]. When fixing #2804 we haven't thought of this side effect of moving to the standard decimal64 representation.

Ok! how come it seems to work so well with the decimal64 values?

But given this thread of discussion, and also generally taking the original jq as the desired behavior, we should probably revise our DEC_CONTEXT_TO_DOUBLE initialization and make sure that it supports seamless conversion from/to binary64, and we should then add tests that verify that behavior.

Yes I think for least amount of confusion we should stick with binary64 behaviour. Also the JSON spec does not require it but do seem to suggest doing so.

From https://datatracker.ietf.org/doc/html/rfc8259

This specification allows implementations to set limits on the range and precision of numbers accepted. Since software that implements IEEE 754 binary64 (double precision) numbers [IEEE754] is generally available and widely used, good interoperability can be achieved by implementations that expect no more precision or range than these provide, in the sense that implementations will approximate JSON numbers within the expected precision.

Also added some more tests but it feels like we should probably have even more?

Two related decnum things i thought about while looking into this:

Currently we convert to decimal64 but won't we end up storing it in a C double that on most hardware and C implemenations will be in binary64 representation? if so, did we loose even more precision because of that? ... also makes you wonder the opposite: how would the new version behave on some hardware that uses decimal64? :)

Would it be possible to implement jvp_literal_number_to_double

jq/src/jv.c

Line 611 in 88f01a7

static double jvp_literal_number_to_double(jv j) {
without going thru a string representation?

wader added a commit to wader/jq that referenced this issue Nov 23, 2023
This is what the JSON spec suggests and will also be less confusing compared to other jq implementations and langauges.

Related to jqlang#2939
wader added a commit to wader/jq that referenced this issue Nov 23, 2023
This is what the JSON spec suggests and will also be less confusing compared to other jq implementations and langauges.

Related to jqlang#2939
@leonid-s-usov
Copy link
Contributor

@wader thanks so much for your attention to the problem. As I have commented on #2949, I have caused some confusion with my last comment. The exponent range of a binary64, [-1022,1023], is in terms of base-2 binary mantissa, so we should not use those numbers to initialize a dec context. Sorry for that 🙏🏻

Would it be possible to implement jvp_literal_number_to_double without going through a string representation?

I had this concern as well, but eventually, I realized that it was the only way. Creating a binary floating point number involves calculating the log base 2 of the decimal number, and really, that's exactly what jvp_strtod is doing. Conversion of a decNumber to a string is a relatively simple operation since the number is already base-10.

@wader
Copy link
Member

wader commented Nov 26, 2023

@wader thanks so much for your attention to the problem. As I have commented on #2949, I have caused some confusion with my last comment. The exponent range of a binary64, [-1022,1023], is in terms of base-2 binary mantissa, so we should not use those numbers to initialize a dec context. Sorry for that 🙏🏻

No worries! greatful that your spending time on this. I didn't know much about floating point representations and after learning more about them i understand that i know even less than i thought :)

Doh that makes total sense that decnum is base-10. Maybe I should have noticed that there was no base config in the context struct.

Would it be possible to implement jvp_literal_number_to_double without going through a string representation?

I had this concern as well, but eventually, I realized that it was the only way. Creating a binary floating point number involves calculating the log base 2 of the decimal number, and really, that's exactly what jvp_strtod is doing. Conversion of a decNumber to a string is a relatively simple operation since the number is already base-10.

I see 👍

wader added a commit to wader/jq that referenced this issue Nov 26, 2023
This is what the JSON spec suggests and will also be less confusing compared to other jq implementations and langauges.

Related to jqlang#2939
wader added a commit to wader/jq that referenced this issue Nov 26, 2023
This is what the JSON spec suggests and will also be less confusing compared to other jq implementations and langauges.

Related to jqlang#2939
emanuele6 pushed a commit that referenced this issue Nov 29, 2023
This is what the JSON spec suggests and will also be less confusing compared to other jq implementations and langauges.

Related to #2939
@baterflyrity
Copy link
Author

Sure. I use jq in my python applications and really tired of incompatible windows builds. What the heck jq runs on windows and python runs on windows but python bindings of jq do not support windows?
So I just want to rollout my own python binding that just works. Indeed, I implemented tests and pulled form this repo test files. But unfortunately I can not understand this floating syntax by only inner vision.

I see. Is there some public URL for the project?

So you want to use the tests in jq.test to test the bindings?

Yeah i've kind of reverse-engineered the syntax also by looking at the code. Why it's a bit floating i guess is because it has only been designed to test jq itself.

Wouldn't you be bothered helping a bit with this please?
p.s. Currently I am using cli tests parser + runner written in python so it can even be integrated here if needed (guess not 😏).

Can promise anything but i can try. What do you need help with? there are probably others that can help also

Hi!
Just want to notice that pushed public URL for my own tests parser.
https://github.com/baterflyrity/jqpy/tree/master/tests#creating-jq-test-file

Feel free to use or extend it if any needs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants