2019-03-25 09:52:36 -05:00
#!/bin/sh -x
2013-05-08 02:30:08 +01:00
2016-01-17 12:23:05 -06:00
. " ${ 0 %/* } /setup" " $@ "
2014-07-13 19:00:37 -05:00
2023-09-06 08:52:37 -05:00
msys = false
mingw = false
2026-04-08 16:02:41 +02:00
sunos = false
2023-09-06 08:52:37 -05:00
case " $( uname -s) " in
MSYS*) msys = true;;
MINGW*) mingw = true;;
2026-04-08 16:02:41 +02:00
SunOS*) sunos = true;;
2023-09-06 08:52:37 -05:00
esac
2023-08-12 20:18:45 +02:00
JQ_NO_B = $JQ
JQ = " $JQ -b"
2026-04-08 16:02:41 +02:00
# On Solaris, GNU tools are available in /usr/gnu. This script should prefer
# them over the native tools, because the native versions may lack some
# command-line options the script relies on.
$sunos && PATH = "/usr/gnu/bin: $PATH "
2015-12-14 23:43:22 -06:00
PATH = $JQBASEDIR :$PATH $JQBASEDIR /tests/jq-f-test.sh > /dev/null
2024-11-13 12:35:22 +01:00
SHELL = /bin/sh
export SHELL
2025-03-04 22:59:46 +00:00
unset JQ_COLORS
unset NO_COLOR
2015-06-18 19:38:25 -07:00
if [ -f " $JQBASEDIR /.libs/libinject_errors.so" ] ; then
2015-05-03 19:23:37 -05:00
# Do some simple error injection tests to check that we're handling
# I/O errors correctly.
(
2015-06-18 19:38:25 -07:00
libinject = $JQBASEDIR /.libs/libinject_errors.so
2015-05-03 19:23:37 -05:00
cd $d
2015-06-18 19:38:25 -07:00
LD_PRELOAD = $libinject $JQ . /dev/null
2015-05-03 19:23:37 -05:00
touch fail_read
2015-06-18 19:38:25 -07:00
LD_PRELOAD = $libinject $JQ . fail_read && exit 2
2015-05-03 19:23:37 -05:00
touch fail_close
2015-06-18 19:38:25 -07:00
LD_PRELOAD = $libinject $JQ . fail_close && exit 2
2015-05-03 19:23:37 -05:00
true
)
fi
2015-04-23 18:27:53 -05:00
printf 'a\0b\nc\0d\ne' > $d /input
2015-06-18 19:38:25 -07:00
$VALGRIND $Q $JQ -Rse '. == "a\u0000b\nc\u0000d\ne"' $d /input
$VALGRIND $Q $JQ -Rne '[inputs] == ["a\u0000b", "c\u0000d", "e"]' $d /input
2015-04-23 18:27:53 -05:00
2014-07-27 17:33:22 -05:00
## Test constant folding
2017-10-28 10:51:59 -04:00
nref = $( $VALGRIND $Q $JQ -n --debug-dump-disasm '"foo"' | wc -l)
2025-01-25 13:58:47 +09:00
for exp in '1+1' '1-1' '2*3' '9/3' '9%3' '9==3' '9!=3' \
'9<3' '9>3' '9<=3' '9>=3' '1+2*3-4/5%6' '"foo" + "bar"' ; do
n = $( $VALGRIND $Q $JQ -n --debug-dump-disasm " $exp " | wc -l)
if [ $n -ne $nref ] ; then
echo "Constant expression folding didn't work: $exp "
exit 1
fi
done
2014-07-27 17:33:22 -05:00
2014-10-10 22:19:38 -05:00
## Test JSON sequence support
cat > $d /expected <<EOF
2019-03-25 09:52:36 -05:00
jq: ignoring parse error: Truncated value at line 2, column 5
jq: ignoring parse error: Truncated value at line 2, column 25
jq: ignoring parse error: Truncated value at line 2, column 41
2014-10-10 22:19:38 -05:00
EOF
2015-06-18 19:38:25 -07:00
printf '1\0362 3\n[0,1\036[4,5]true"ab"{"c":4\036{}{"d":5,"e":6"\036false\n' | $VALGRIND $Q $JQ -ces --seq '. == [2,3,[4,5],true,"ab",{},false]' > /dev/null 2> $d /out
2014-10-10 22:19:38 -05:00
cmp $d /out $d /expected
cat > $d /expected <<EOF
2019-03-25 09:52:36 -05:00
jq: ignoring parse error: Truncated value at line 2, column 5
jq: ignoring parse error: Truncated value at line 2, column 25
jq: ignoring parse error: Truncated value at line 3, column 1
2014-10-10 22:19:38 -05:00
EOF
2015-06-18 19:38:25 -07:00
printf '1\0362 3\n[0,1\036[4,5]true"ab"{"c":4\036{}{"d":5,"e":6"false\n\036null' | $VALGRIND $Q $JQ -ces --seq '. == [2,3,[4,5],true,"ab",{},null]' > /dev/null 2> $d /out
2014-10-10 22:19:38 -05:00
cmp $d /out $d /expected
# Note that here jq sees no inputs at all but it still succeeds because
# --seq ignores parse errors
cat > $d /expected <<EOF
2019-03-25 09:52:36 -05:00
jq: ignoring parse error: Unfinished abandoned text at EOF at line 1, column 4
2014-10-10 22:19:38 -05:00
EOF
2018-07-29 12:50:28 -07:00
printf '"foo' | $JQ -c --seq . > $d /out 2>& 1
cmp $d /out $d /expected
# with -e option should give 4 here as there's no valid output after
# ignoring parse errors with --seq.
printf '"foo' | $JQ -ce --seq . > $d /out 2>& 1 || ret = $?
[ $ret -eq 4 ]
2014-10-10 22:19:38 -05:00
cmp $d /out $d /expected
# Numeric values truncated by EOF are ignored
cat > $d /expected <<EOF
2019-03-25 09:52:36 -05:00
jq: ignoring parse error: Unfinished abandoned text at EOF at line 1, column 1
2014-10-10 22:19:38 -05:00
EOF
2018-07-29 12:50:28 -07:00
printf '1' | $JQ -c --seq . > $d /out 2>& 1
2014-10-10 22:19:38 -05:00
cmp $d /out $d /expected
cat > $d /expected <<EOF
2015-09-21 23:24:08 -05:00
jq: error (at <stdin>:1): Unfinished abandoned text at EOF at line 2, column 0
2014-10-10 22:19:38 -05:00
EOF
2015-09-21 23:24:08 -05:00
if printf '1\n' | $JQ -cen --seq '[inputs] == []' >/dev/null 2> $d /out; then
printf 'Error expected but jq exited successfully\n' 1>& 2
exit 2
fi
2014-10-10 22:19:38 -05:00
cmp $d /out $d /expected
2025-02-18 07:52:58 +09:00
# Test control characters for #2909
cat > $d /expected <<EOF
jq: parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 1, column 3
EOF
for i in 1 2 30 31; do
if printf "\" $( printf '\\%03o' $i ) \"" | $JQ '.' > $d /out 2>& 1; then
printf 'Error expected but jq exited successfully\n' 1>& 2
exit 2
fi
cmp $d /out $d /expected
done
printf '" ~\\u007f"\n' > $d /expected
printf "\" $( printf '\\%03o' 32 126 127) \"" | $JQ '.' > $d /out 2>& 1
cmp $d /out $d /expected
2018-07-29 12:50:28 -07:00
## Test --exit-status
data = '{"i": 1}\n{"i": 2}\n{"i": 3}\n'
2019-02-26 18:45:32 -05:00
printf " $data " | $JQ --exit-status 'select(.i==1)' > /dev/null 2>& 1
printf " $data " | $JQ --exit-status 'select(.i==2)' > /dev/null 2>& 1
printf " $data " | $JQ --exit-status 'select(.i==3)' > /dev/null 2>& 1
2018-07-29 12:50:28 -07:00
ret = 0
2019-02-26 18:45:32 -05:00
printf " $data " | $JQ --exit-status 'select(.i==4)' > /dev/null 2>& 1 || ret = $?
2018-07-29 12:50:28 -07:00
[ $ret -eq 4 ]
ret = 0
2019-02-26 18:45:32 -05:00
printf " $data " | $JQ --exit-status 'select(.i==2) | false' > /dev/null 2>& 1 || ret = $?
2018-07-29 12:50:28 -07:00
[ $ret -eq 1 ]
2019-02-26 18:45:32 -05:00
printf " $data " | $JQ --exit-status 'select(.i==2) | true' > /dev/null 2>& 1
2018-07-29 12:50:28 -07:00
2015-09-21 23:24:08 -05:00
# Regression test for #951
printf '"a\n' > $d /input
if $VALGRIND $Q $JQ -e . $d /input; then
printf 'Issue #951 is back?\n' 1>& 2
exit 2
fi
2023-07-06 10:01:59 +09:00
# Regression test for #2146
if echo "foobar" | $JQ .; then
printf 'Issue #2146 is back?\n' 1>& 2
exit 1
elif [ $? -ne 5 ] ; then
echo "Invalid input had wrong error code" 1>& 2
exit 1
fi
2023-07-06 21:44:17 +09:00
# Regression test for #2367; make sure to call jq twice
if ! echo '{"a": 1E9999999999}' | $JQ . | $JQ -e .a; then
printf 'Issue #2367 is back?\n' 1>& 2
exit 1
fi
2017-12-04 19:20:58 -05:00
# Regression test for #1534
echo "[1,2,3,4]" > $d /expected
printf "[1,2][3,4]" | $JQ -cs add > $d /out 2>& 1
cmp $d /out $d /expected
2017-12-04 20:10:56 -05:00
printf "[1,2][3,4]\n" | $JQ -cs add > $d /out 2>& 1
cmp $d /out $d /expected
2017-12-04 19:20:58 -05:00
2025-05-22 08:04:05 +09:00
# Regression test for #3273
echo "[[[0],1],[[0]],[[0],2],[[0]]]" > $d /expected
printf "[1][2]" | $JQ -c -s --stream . > $d /out 2>& 1
cmp $d /out $d /expected
printf "[1][2]\n" | $JQ -c -s --stream . > $d /out 2>& 1
cmp $d /out $d /expected
2023-07-10 07:30:50 +09:00
# Regression test for --raw-output0
2023-06-06 07:19:43 -04:00
printf "a\0b\0" > $d /expected
2025-01-26 08:08:31 +09:00
printf '["a", "b"]' | $VALGRIND $Q $JQ --raw-output0 '.[]' > $d /out
2023-06-06 07:19:43 -04:00
cmp $d /out $d /expected
2023-07-10 07:30:50 +09:00
printf "a\0" > $d /expected
2025-01-26 08:08:31 +09:00
if printf '["a", "c\\u0000d", "b"]' | $VALGRIND $Q $JQ --raw-output0 '.[]' > $d /out; then
2023-07-10 07:30:50 +09:00
echo "Should exit error on string containing NUL with --raw-output0" 1>& 2
exit 1
elif [ $? -ne 5 ] ; then
echo "Invalid error code" 1>& 2
exit 1
else
cmp $d /out $d /expected
fi
2017-12-04 19:20:58 -05:00
2024-10-28 21:30:58 -07:00
# Regression tests for #3194
echo 42 > $d /expected
$JQ -nn 42 > $d /out 2>& 1
cmp $d /out $d /expected
$JQ -nL. 42 > $d /out 2>& 1
cmp $d /out $d /expected
$JQ -nL . 42 > $d /out 2>& 1
cmp $d /out $d /expected
$JQ -h > $d /expected 2>& 1
$JQ -hV > $d /out 2>& 1
cmp $d /out $d /expected
$JQ -h -V > $d /out 2>& 1
cmp $d /out $d /expected
$JQ -V > $d /expected 2>& 1
$JQ -Vh > $d /out 2>& 1
cmp $d /out $d /expected
$JQ -V -h > $d /out 2>& 1
cmp $d /out $d /expected
2025-03-04 22:11:40 +09:00
# CRLF line break support #1219
if ! x = $( $JQ -n " $( printf '1\r\n+\r\n2' ) " ) || [ " $x " != '3' ] ; then
echo 'CRLF line break support failed?' 1>& 2
exit 1
fi
2014-12-22 23:06:27 -06:00
## Test streaming parser
2015-01-02 19:15:57 -06:00
## If we add an option to stream to the `import ... as $symbol;` directive
## then we can move these tests into tests/all.test.
2019-02-25 23:53:21 -05:00
$VALGRIND $Q $JQ -c '. as $d|path(..) as $p|$d|getpath($p)|select((type|. != "array" and . != "object") or length==0)|[$p,.]' < " $JQTESTDIR /torture/input0.json" > $d /out0
2015-06-18 19:38:25 -07:00
$VALGRIND $Q $JQ --stream -c '.|select(length==2)' < " $JQTESTDIR /torture/input0.json" > $d /out1
2014-12-22 23:06:27 -06:00
diff $d /out0 $d /out1
2023-07-23 00:01:52 -05:00
printf '["Unfinished JSON term at EOF at line 1, column 1",[0]]\n' > $d /expected
printf '[' | $VALGRIND $Q $JQ --stream-errors -c . > $d /out 2>& 1
diff $d /out $d /expected
2015-01-02 19:15:57 -06:00
## XXX This test can be moved to tests/all.test _now_
2014-12-26 21:28:31 -06:00
clean = false
if which seq > /dev/null 2>& 1; then
# XXX We should try every prefix of input0.json, but that makes this
# test very, very slow when run with valgrind, and the whole point
# is to run it with valgrind.
#
2017-10-28 10:51:59 -04:00
#len=$(wc -c < "$JQTESTDIR/torture/input0.json")
2014-12-26 21:28:31 -06:00
if [ -z " $VALGRIND " ] ; then
start = 1
2017-10-28 10:51:59 -04:00
end = $( wc -c < " $JQTESTDIR /torture/input0.json" )
2014-12-26 21:28:31 -06:00
else
start = 120
end = 151
fi
2017-10-28 10:51:59 -04:00
for i in $( seq $start $end ) ; do
2014-12-26 21:28:31 -06:00
dd "if=tests/torture/input0.json" bs = $i count = 1 2>/dev/null |
2015-06-18 19:38:25 -07:00
$VALGRIND $JQ -c . > $d /out0 2>$d /err || true
2014-12-26 21:28:31 -06:00
if [ -n " $VALGRIND " ] ; then
grep '^==[0-9][0-9]*== ERROR SUMMARY: 0 errors' $d /err > /dev/null
else
2023-12-11 20:46:54 +01:00
tail -n1 -- " $d /err" | grep -Ei 'assert|abort|core' && false
2014-12-26 21:28:31 -06:00
fi
dd "if=tests/torture/input0.json" bs = $i count = 1 2>/dev/null |
2015-06-26 20:16:23 -05:00
$VALGRIND $JQ -cn --stream 'fromstream(inputs)' > $d /out1 2>$d /err || true
2014-12-26 21:28:31 -06:00
if [ -n " $VALGRIND " ] ; then
grep '^==[0-9][0-9]*== ERROR SUMMARY: 0 errors' $d /err > /dev/null
else
2023-12-11 20:46:54 +01:00
tail -n1 -- " $d /err" | grep -Ei 'assert|abort|core' && false
2014-12-26 21:28:31 -06:00
fi
diff $d /out0 $d /out1
done
else
echo "Not doing torture tests"
fi
2023-07-04 21:23:52 +02:00
## Regression test for issue #2378 assert when stream parse broken object pair
2023-07-06 10:01:59 +09:00
echo '{"a":1,"b",' | $JQ --stream > /dev/null 2> $d /err || true
2023-07-04 21:23:52 +02:00
grep 'Objects must consist of key:value pairs' $d /err > /dev/null
2023-07-16 11:56:36 +02:00
## Regression tests for issue #2463 assert when stream parse non-scalar object key
echo '{{"a":"b"}}' | $JQ --stream > /dev/null 2> $d /err || true
grep "Expected string key after '{', not '{'" $d /err > /dev/null
echo '{"x":"y",{"a":"b"}}' | $JQ --stream > /dev/null 2> $d /err || true
grep "Expected string key after ',' in object, not '{'" $d /err > /dev/null
echo '{["a","b"]}' | $JQ --stream > /dev/null 2> $d /err || true
grep "Expected string key after '{', not '\\['" $d /err > /dev/null
echo '{"x":"y",["a","b"]}' | $JQ --stream > /dev/null 2> $d /err || true
grep "Expected string key after ',' in object, not '\\['" $d /err > /dev/null
2023-07-23 11:47:20 +09:00
# debug, stderr
$VALGRIND $Q $JQ -n '"test", {} | debug, stderr' >/dev/null
$JQ -n -c -j '"hello\nworld", null, [false, 0], {"foo":["bar"]}, "\n" | stderr' >$d /out 2>$d /err
cat > $d /expected <<'EOF'
hello
worldnull[false,0]{"foo":["bar"]}
EOF
cmp $d /out $d /expected
cmp $d /err $d /expected
2023-07-23 00:24:22 +09:00
# --arg, --argjson, $ARGS.named
$VALGRIND $JQ -n -c --arg foo 1 --argjson bar 2 '{$foo, $bar} | ., . == $ARGS.named' > $d /out
printf '{"foo":"1","bar":2}\ntrue\n' > $d /expected
cmp $d /out $d /expected
# --slurpfile, --rawfile
$VALGRIND $JQ -n --slurpfile foo $JQBASEDIR /tests/modules/data.json \
--rawfile bar $JQBASEDIR /tests/modules/data.json '{$foo, $bar}' > $d /out
cat > $d /expected <<'EOF'
{
"foo": [
{
"this": "is a test",
"that": "is too"
}
],
"bar": "{\n \"this\": \"is a test\",\n \"that\": \"is too\"\n}\n"
}
EOF
cmp $d /out $d /expected
# --args, --jsonargs, $ARGS.positional
$VALGRIND $JQ -n -c --args '$ARGS.positional' foo bar baz > $d /out
printf '["foo","bar","baz"]\n' > $d /expected
cmp $d /out $d /expected
$VALGRIND $JQ -n -c --jsonargs '$ARGS.positional' null true '[]' '{}' > $d /out
printf '[null,true,[],{}]\n' > $d /expected
cmp $d /out $d /expected
$VALGRIND $JQ -n -c '$ARGS.positional' --args foo 1 --jsonargs 2 '{}' --args 3 4 > $d /out
printf '["foo","1",2,{},"3","4"]\n' > $d /expected
cmp $d /out $d /expected
$VALGRIND $JQ -n -c '$ARGS.positional' --args --jsonargs > $d /out
printf '[]\n' > $d /expected
cmp $d /out $d /expected
2023-07-05 18:26:06 +02:00
## Regression test for issue #2572 assert when using --jsonargs and invalid JSON
2023-07-23 00:24:22 +09:00
$VALGRIND $JQ -n --jsonargs null invalid && EC = $? || EC = $?
2023-07-05 18:26:06 +02:00
if [ " $EC " -ne 2 ] ; then
echo "--jsonargs exited with wrong exit code, expected 2 got $EC " 1>& 2
exit 1
fi
# this tests the args_done code path "--"
2023-07-23 00:24:22 +09:00
$VALGRIND $JQ -n --jsonargs null -- invalid && EC = $? || EC = $?
2023-07-05 18:26:06 +02:00
if [ " $EC " -ne 2 ] ; then
echo "--jsonargs exited with wrong exit code, expected 2 got $EC " 1>& 2
exit 1
fi
2014-12-26 19:31:47 -06:00
## Fuzz parser
2017-10-28 10:51:59 -04:00
## XXX With a $(urandom) builtin we could move this test into tests/all.test
2014-12-26 21:28:31 -06:00
clean = false
2014-12-26 19:31:47 -06:00
if dd if = /dev/urandom bs = 16 count = 1024 > $d /rand 2>/dev/null; then
# Have a /dev/urandom, good
2015-06-18 19:38:25 -07:00
$VALGRIND $Q $JQ --seq . $d /rand >/dev/null 2>& 1
$VALGRIND $Q $JQ --seq --stream . $d /rand >/dev/null 2>& 1
2014-12-26 19:31:47 -06:00
dd if = /dev/urandom bs = 16 count = 1024 > $d /rand 2>/dev/null
2015-06-18 19:38:25 -07:00
$VALGRIND $Q $JQ --seq . $d /rand >/dev/null 2>& 1
$VALGRIND $Q $JQ --seq --stream . $d /rand >/dev/null 2>& 1
2014-12-26 19:31:47 -06:00
dd if = /dev/urandom bs = 16 count = 1024 > $d /rand 2>/dev/null
2015-06-18 19:38:25 -07:00
$VALGRIND $Q $JQ --seq . $d /rand >/dev/null 2>& 1
$VALGRIND $Q $JQ --seq --stream . $d /rand >/dev/null 2>& 1
2014-12-26 19:31:47 -06:00
fi
2014-12-26 21:28:31 -06:00
clean = true
2014-12-26 19:31:47 -06:00
2014-07-27 17:33:22 -05:00
## Test library/module system
2014-12-31 19:21:45 -06:00
# Check handling of ~/.jq; these can't move into jq_test.c yet because
# they depend on $HOME
2019-02-20 22:53:37 -05:00
if [ " $( HOME = " $mods /home1" $VALGRIND $Q $JQ -nr fg ) " != foobar ] ; then
2014-07-13 19:00:37 -05:00
echo "Bug #479 appears to be back" 1>& 2
exit 1
fi
2024-08-23 19:44:08 -04:00
if $msys || $mingw ; then
HOME_BAK = $HOME
unset HOME
if [ " $( USERPROFILE = " $mods /home1" $VALGRIND $Q $JQ -nr foo) " != baz ] ; then
echo "Bug #3104 regressed (sourcing %USERPROFILE%/.jq on Windows)" 1>& 2
exit 1
fi
export HOME = $HOME_BAK
unset HOME_BAK
fi
2019-02-20 22:53:37 -05:00
if [ $( HOME = " $mods /home1" $VALGRIND $Q $JQ --debug-dump-disasm -n fg | grep '^[a-z]' | wc -l) -ne 3 ] ; then
2014-07-13 19:00:37 -05:00
echo "Binding too many defs into program" 1>& 2
exit 1
fi
2019-02-20 22:53:37 -05:00
if ! HOME = " $mods /home2" $VALGRIND $Q $JQ -n 'include "g"; empty' ; then
2023-06-13 07:01:20 -04:00
echo "Mishandling directory ~/.jq" 1>& 2
2019-02-20 22:53:37 -05:00
exit 1
fi
2015-08-11 17:40:39 -05:00
cd " $JQBASEDIR " # so that relative library paths are guaranteed correct
if ! $VALGRIND $Q $JQ -L ./tests/modules -ne 'import "test_bind_order" as check; check::check==true' ; then
echo "Issue #817 regression?" 1>& 2
exit 1
fi
cd " $JQBASEDIR "
if ! $VALGRIND $Q $JQ -L tests/modules -ne 'import "test_bind_order" as check; check::check==true' ; then
echo "Issue #817 regression?" 1>& 2
exit 1
fi
2017-02-22 23:01:56 -06:00
## Halt
if ! $VALGRIND $Q $JQ -n halt; then
echo "jq halt didn't work as expected" 1>& 2
exit 1
fi
if $VALGRIND $Q $VG_EXIT0 $JQ -n 'halt_error(1)' ; then
echo "jq halt_error(1) didn't work as expected" 1>& 2
exit 1
elif [ $? -ne 1 ] ; then
echo "jq halt_error(1) had wrong error code" 1>& 2
exit 1
fi
if $VALGRIND $Q $VG_EXIT0 $JQ -n 'halt_error(11)' ; then
echo "jq halt_error(11) didn't work as expected" 1>& 2
exit 1
elif [ $? -ne 11 ] ; then
echo "jq halt_error(11) had wrong error code" 1>& 2
exit 1
fi
2017-10-28 10:51:59 -04:00
if [ -n " $( $VALGRIND $Q $JQ -n 'halt_error(1)' 2>& 1) " ] ; then
2017-02-22 23:01:56 -06:00
echo "jq halt_error(1) had unexpected output" 1>& 2
exit 1
fi
2023-06-27 07:33:21 +09:00
if [ -n " $( $VALGRIND $Q $JQ -n '"xyz\n" | halt_error(1)' 2>/dev/null) " ] ; then
2017-02-22 23:01:56 -06:00
echo "jq halt_error(1) had unexpected output on stdout" 1>& 2
exit 1
fi
2023-06-27 07:33:21 +09:00
if [ " $( $VALGRIND $Q $JQ -n '"xy" | halt_error(1)' 2>& 1 || echo "z" ) " != "xyz" ] ; then
echo "jq halt_error(1) had unexpected output" 1>& 2
exit 1
fi
if [ " $( $VALGRIND $Q $JQ -n '"x\u0000y\u0000z" | halt_error(1)' 2>& 1 | tr '\0' '.' ) " != "x.y.z" ] ; then
echo "jq halt_error(1) had unexpected output" 1>& 2
exit 1
fi
if [ " $( $VALGRIND $Q $JQ -n '{"a":"xyz"} | halt_error(1)' 2>& 1) " != '{"a":"xyz"}' ] ; then
2017-02-22 23:01:56 -06:00
echo "jq halt_error(1) had unexpected output" 1>& 2
exit 1
fi
2017-04-29 13:00:52 -05:00
# Check $JQ_COLORS
2023-07-12 09:31:26 +09:00
## Default colors, null input
2017-04-29 13:00:52 -05:00
$JQ -Ccn . > $d /color
2023-08-05 19:18:07 +09:00
printf '\033[0;90mnull\033[0m\n' > $d /expect
2017-04-29 13:00:52 -05:00
cmp $d /color $d /expect
2023-07-12 09:31:26 +09:00
## Set non-default color, null input
2017-04-29 13:00:52 -05:00
JQ_COLORS = '4;31' $JQ -Ccn . > $d /color
printf '\033[4;31mnull\033[0m\n' > $d /expect
cmp $d /color $d /expect
2023-07-12 09:31:26 +09:00
2025-05-31 06:49:17 +00:00
## Set implicit empty color, null input
$JQ -Ccn . > $d /color
printf '\033[0;90mnull\033[0m\n' > $d /expect
cmp $d /color $d /expect
## Set explicit empty color, null input
JQ_COLORS = ':' $JQ -Ccn . > $d /color
printf '\033[mnull\033[0m\n' > $d /expect
cmp $d /color $d /expect
## Extra colors, null input
JQ_COLORS = '::::::::' $JQ -Ccn . > $d /color
printf '\033[mnull\033[0m\n' > $d /expect
cmp $d /color $d /expect
2023-07-12 09:31:26 +09:00
## Default colors, complex input
2024-02-07 13:38:01 -08:00
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d /color
2023-07-12 09:31:26 +09:00
{
2024-02-06 21:47:12 -08:00
printf '\033[1;39m[\033[0m'
printf '\033[1;39m{\033[0m'
printf '\033[1;34m"a"\033[0m'
printf '\033[1;39m:\033[0m'
printf '\033[0;39mtrue\033[0m'
printf '\033[1;39m,\033[0m'
printf '\033[1;34m"b"\033[0m'
printf '\033[1;39m:\033[0m'
printf '\033[0;39mfalse\033[0m'
printf '\033[1;39m}\033[0m'
printf '\033[1;39m,\033[0m'
2024-02-07 13:38:01 -08:00
printf '\033[0;32m"abc"\033[0m'
printf '\033[1;39m,\033[0m'
2024-02-06 21:47:12 -08:00
printf '\033[0;39m123\033[0m'
printf '\033[1;39m,\033[0m'
printf '\033[0;90mnull\033[0m'
printf '\033[1;39m]\033[0m\n'
2023-07-12 09:31:26 +09:00
} > $d /expect
cmp $d /color $d /expect
## Set non-default colors, complex input
2023-08-05 19:18:07 +09:00
JQ_COLORS = '0;30:0;31:0;32:0;33:0;34:1;35:1;36:1;37' \
2024-02-07 13:38:01 -08:00
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d /color
2023-07-12 09:31:26 +09:00
{
2024-02-06 21:47:12 -08:00
printf '\033[1;35m[\033[0m'
printf '\033[1;36m{\033[0m'
printf '\033[1;37m"a"\033[0m'
printf '\033[1;36m:\033[0m'
printf '\033[0;32mtrue\033[0m'
printf '\033[1;36m,\033[0m'
printf '\033[1;37m"b"\033[0m'
printf '\033[1;36m:\033[0m'
printf '\033[0;31mfalse\033[0m'
printf '\033[1;36m}\033[0m'
printf '\033[1;35m,\033[0m'
2024-02-07 13:38:01 -08:00
printf '\033[0;34m"abc"\033[0m'
printf '\033[1;35m,\033[0m'
2024-02-06 21:47:12 -08:00
printf '\033[0;33m123\033[0m'
printf '\033[1;35m,\033[0m'
printf '\033[0;30mnull\033[0m'
printf '\033[1;35m]\033[0m\n'
} > $d /expect
cmp $d /color $d /expect
2025-05-31 16:29:02 +09:00
## Set non-default colors only for literals, complex input
JQ_COLORS = '0;37:0;31:0;35:0;34:0;36' \
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d /color
{
printf '\033[1;39m[\033[0m'
printf '\033[1;39m{\033[0m'
printf '\033[1;34m"a"\033[0m'
printf '\033[1;39m:\033[0m'
printf '\033[0;35mtrue\033[0m'
printf '\033[1;39m,\033[0m'
printf '\033[1;34m"b"\033[0m'
printf '\033[1;39m:\033[0m'
printf '\033[0;31mfalse\033[0m'
printf '\033[1;39m}\033[0m'
printf '\033[1;39m,\033[0m'
printf '\033[0;36m"abc"\033[0m'
printf '\033[1;39m,\033[0m'
printf '\033[0;34m123\033[0m'
printf '\033[1;39m,\033[0m'
printf '\033[0;37mnull\033[0m'
printf '\033[1;39m]\033[0m\n'
} > $d /expect
cmp $d /color $d /expect
2024-02-06 21:47:12 -08:00
## Default colors, complex input, indented
2024-02-07 13:38:01 -08:00
$JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d /color
2024-02-06 21:47:12 -08:00
{
printf '\033[1;39m[\033[0m\n'
printf ' \033[1;39m{\033[0m\n'
printf ' \033[1;34m"a"\033[0m'
2024-02-07 13:05:23 -08:00
printf '\033[1;39m:\033[0m '
2024-02-06 21:47:12 -08:00
printf '\033[0;39mtrue\033[0m'
printf '\033[1;39m,\033[0m\n'
printf ' \033[1;34m"b"\033[0m'
2024-02-07 13:05:23 -08:00
printf '\033[1;39m:\033[0m '
2024-02-06 21:47:12 -08:00
printf '\033[0;39mfalse\033[0m\n'
printf ' \033[1;39m}\033[0m'
printf '\033[1;39m,\033[0m\n'
2024-02-07 13:38:01 -08:00
printf ' \033[0;32m"abc"\033[0m'
printf '\033[1;39m,\033[0m\n'
2024-02-06 21:47:12 -08:00
printf ' \033[0;39m123\033[0m'
printf '\033[1;39m,\033[0m\n'
printf ' \033[0;90mnull\033[0m\n'
printf '\033[1;39m]\033[0m\n'
} > $d /expect
cmp $d /color $d /expect
## Set non-default colors, complex input, indented
JQ_COLORS = '0;30:0;31:0;32:0;33:0;34:1;35:1;36:1;37' \
2024-02-07 13:38:01 -08:00
$JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d /color
2024-02-06 21:47:12 -08:00
{
printf '\033[1;35m[\033[0m\n'
printf ' \033[1;36m{\033[0m\n'
printf ' \033[1;37m"a"\033[0m'
2024-02-07 13:05:23 -08:00
printf '\033[1;36m:\033[0m '
2024-02-06 21:47:12 -08:00
printf '\033[0;32mtrue\033[0m'
printf '\033[1;36m,\033[0m\n'
printf ' \033[1;37m"b"\033[0m'
2024-02-07 13:05:23 -08:00
printf '\033[1;36m:\033[0m '
2024-02-06 21:47:12 -08:00
printf '\033[0;31mfalse\033[0m\n'
printf ' \033[1;36m}\033[0m'
printf '\033[1;35m,\033[0m\n'
2024-02-07 13:38:01 -08:00
printf ' \033[0;34m"abc"\033[0m'
printf '\033[1;35m,\033[0m\n'
2024-02-06 21:47:12 -08:00
printf ' \033[0;33m123\033[0m'
printf '\033[1;35m,\033[0m\n'
printf ' \033[0;30mnull\033[0m\n'
printf '\033[1;35m]\033[0m\n'
2023-07-12 09:31:26 +09:00
} > $d /expect
2017-04-29 13:00:52 -05:00
cmp $d /color $d /expect
2025-05-31 16:29:02 +09:00
## Set truecolor, complex input, indented
JQ_COLORS = $( printf '38;2;%s:' \
'255;173;173' '255;214;165' '253;255;182' '202;255;191' \
'155;246;255' '160;196;255' '189;178;255' '255;198;255' ) \
$JQ -Cn '[{"a":true,"b":false},"abc",123,null]' > $d /color
{
printf '\033[38;2;160;196;255m[\033[0m\n'
printf ' \033[38;2;189;178;255m{\033[0m\n'
printf ' \033[38;2;255;198;255m"a"\033[0m'
printf '\033[38;2;189;178;255m:\033[0m '
printf '\033[38;2;253;255;182mtrue\033[0m'
printf '\033[38;2;189;178;255m,\033[0m\n'
printf ' \033[38;2;255;198;255m"b"\033[0m'
printf '\033[38;2;189;178;255m:\033[0m '
printf '\033[38;2;255;214;165mfalse\033[0m\n'
printf ' \033[38;2;189;178;255m}\033[0m'
printf '\033[38;2;160;196;255m,\033[0m\n'
printf ' \033[38;2;155;246;255m"abc"\033[0m'
printf '\033[38;2;160;196;255m,\033[0m\n'
printf ' \033[38;2;202;255;191m123\033[0m'
printf '\033[38;2;160;196;255m,\033[0m\n'
printf ' \033[38;2;255;173;173mnull\033[0m\n'
printf '\033[38;2;160;196;255m]\033[0m\n'
} > $d /expect
cmp $d /color $d /expect
# Check invalid JQ_COLORS
2017-04-29 13:00:52 -05:00
echo 'Failed to set $JQ_COLORS' > $d /expect_warning
2024-02-07 13:38:01 -08:00
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d /expect
2025-05-31 16:29:02 +09:00
for colors in '/' '[30' '30m' '30:31m:32' '30:*:31' 'invalid' ; do
2026-04-08 16:02:41 +02:00
export JQ_COLORS = $colors
$JQ -Ccn '[{"a":true,"b":false},"abc",123,null]' > $d /color 2>$d /warning
2025-05-31 16:29:02 +09:00
cmp $d /color $d /expect
cmp $d /warning $d /expect_warning
done
2026-04-08 16:02:41 +02:00
unset JQ_COLORS
2017-04-29 13:00:52 -05:00
2023-07-19 09:21:16 +09:00
# Check $NO_COLOR
2023-09-06 08:52:37 -05:00
test_no_color = true
$msys && test_no_color = false
$mingw && test_no_color = false
2026-04-08 16:02:41 +02:00
$sunos && test_no_color = false
2023-08-12 20:18:45 +02:00
if $test_no_color && command -v script >/dev/null 2>& 1; then
2023-07-19 09:21:16 +09:00
if script -qc echo /dev/null >/dev/null 2>& 1; then
faketty() { script -qec " $* " /dev/null; }
else # macOS
faketty() { script -q /dev/null " $@ " /dev/null |
sed 's/^\x5E\x44\x08\x08//' ; }
fi
2023-08-12 20:18:45 +02:00
faketty $JQ_NO_B -n . > $d /color
2023-08-05 19:18:07 +09:00
printf '\033[0;90mnull\033[0m\r\n' > $d /expect
2023-10-05 15:37:44 +02:00
od -tc $d /expect
od -tc $d /color
2023-07-19 09:21:16 +09:00
cmp $d /color $d /expect
2024-11-13 12:35:22 +01:00
faketty env NO_COLOR = $JQ_NO_B -n . > $d /color
2023-08-05 19:18:07 +09:00
printf '\033[0;90mnull\033[0m\r\n' > $d /expect
2023-10-05 15:37:44 +02:00
od -tc $d /expect
od -tc $d /color
2023-07-19 09:21:16 +09:00
cmp $d /color $d /expect
2024-11-13 12:35:22 +01:00
faketty env NO_COLOR = 1 $JQ_NO_B -n . > $d /color
2023-07-19 09:21:16 +09:00
printf 'null\r\n' > $d /expect
2023-10-05 15:37:44 +02:00
od -tc $d /expect
od -tc $d /color
2023-07-19 09:21:16 +09:00
cmp $d /color $d /expect
2024-11-13 12:35:22 +01:00
faketty env NO_COLOR = 1 $JQ_NO_B -Cn . > $d /color
2023-08-05 19:18:07 +09:00
printf '\033[0;90mnull\033[0m\r\n' > $d /expect
2023-10-05 15:37:44 +02:00
od -tc $d /expect
od -tc $d /color
2023-07-19 09:21:16 +09:00
cmp $d /color $d /expect
fi
2023-07-29 13:44:14 -05:00
# #2785
if $VALGRIND $Q $JQ -n -f " $JQTESTDIR /no-main-program.jq" > $d /out 2>& 1; then
echo "jq -f $JQTESTDIR /no-main-program.jq succeeded"
exit 1
else
EC = $?
if [ $EC -eq 1 ] ; then
echo "jq -f $JQTESTDIR /no-main-program.jq failed with memory errors"
exit 1
fi
if [ $EC -ne 3 ] ; then
echo "jq -f $JQTESTDIR /no-main-program.jq failed with wrong exit code ( $EC )"
exit 1
fi
fi
cat > $d /expected <<EOF
jq: error: Top-level program not given (try ".")
jq: 1 compile error
EOF
if ! diff $d /expected $d /out; then
echo "jq -f $JQTESTDIR /no-main-program.jq failed but its error message is not the expected one"
exit 1
fi
if ! $VALGRIND $Q $JQ -n -f " $JQTESTDIR /yes-main-program.jq" > $d /out 2>& 1; then
echo "jq -f $JQTESTDIR /yes-main-program.jq failed"
exit 1
fi
2023-12-11 20:45:14 +01:00
if ! $msys && ! $mingw && locales = $( locale -a) ; then
{ l = $( grep -Ev '^(C|LANG|POSIX|en)' | grep -Ei '\.utf-?8$' | head -n1) ; } \
<<EOF
$locales
EOF
if [ -z " $l " ] ; then
2023-09-06 08:52:37 -05:00
echo "WARNING: Not testing localization"
else
2025-09-15 07:48:02 +09:00
dt1 = $( LC_ALL = $l date +'%a %d %b %Y at %H:%M:%S' )
2026-04-08 16:02:41 +02:00
dt2 = $( LC_ALL = $l $JQ -nr 'now | strflocaltime("%a %d %b %Y at %H:%M:%S")' )
2025-09-15 07:48:02 +09:00
dt3 = $( LC_ALL = $l date +'%a %d %b %Y at %H:%M:%S' )
if [ " $dt1 " != " $dt2 " ] && [ " $dt2 " != " $dt3 " ] ; then
echo "jq does not honor LC_ALL environment variable ( $dt1 , $dt2 , $dt3 )"
2023-12-11 20:45:14 +01:00
exit 1
2023-09-06 08:52:37 -05:00
fi
fi
fi
2025-05-18 16:36:32 +09:00
# Test syntax error messages of multiline filter (we can't test in jq.test)
if $VALGRIND $Q $JQ -n '[
try if .
then 1
else 2
catch ]' > $d /out 2>& 1; then
echo 'syntax error not detected'
exit 1
fi
cat > $d /expected <<EOF
jq: error: syntax error, unexpected catch, expecting end or '|' or ',' at <top-level>, line 5, column 3:
catch ]
^^^^^
jq: error: Possibly unterminated 'if' statement at <top-level>, line 2, column 7:
try if .
^^^^
jq: error: Possibly unterminated 'try' statement at <top-level>, line 2, column 3:
try if .
^^^^^^^^
jq: 3 compile errors
EOF
diff $d /out $d /expected
2025-06-17 15:25:46 +09:00
# Test syntax error messages when error happens at the end.
if $VALGRIND $Q $JQ -n 'if
' > $d /out 2>& 1; then
echo 'syntax error not detected'
exit 1
fi
cat > $d /expected <<EOF
jq: error: syntax error, unexpected end of file at <top-level>, line 1, column 3:
if
^
jq: 1 compile error
EOF
diff $d /out $d /expected
2023-11-03 19:53:33 +01:00
# Comments!
if ! x = $( $JQ -n '123 # comment' ) || [ " $x " != 123 ] ; then
echo 'comment did not work'
exit 1
fi
cr = $( printf \\ r)
if ! x = $( $JQ -n "1 # foo $cr + 2" ) || [ " $x " != 1 ] ; then
echo 'regression: carriage return terminates comment'
exit 1
fi
2023-12-13 21:24:52 +01:00
if ! x = $( $JQ -cn '[
1,
# foo \
2,
# bar \\
3,
4, # baz \\\
5, \
6,
7
# comment \
comment \
comment
]' ) || [ " $x " != '[1,3,4,7]' ] ; then
echo 'multiline comment was not handled correctly'
exit 1
fi
2025-03-04 22:11:40 +09:00
if ! x = $( $JQ -cn " $( printf '[\r\n1,# comment\r\n2,# comment\\\r\ncomment\r\n3\r\n]' ) " ) \
|| [ " $x " != '[1,2,3]' ] ; then
echo 'multiline comment with CRLF line breaks was not handled correctly'
exit 1
fi
2023-10-03 04:39:42 +02:00
# Allow passing the inline jq script before -- #2919
if ! r = $( $JQ --args -rn -- '$ARGS.positional[0]' bar) || [ " $r " != bar ] ; then
echo "passing the inline script after -- didn't work"
exit 1
fi
if ! r = $( $JQ --args -rn 1 -- '$ARGS.positional[0]' bar) || [ " $r " != 1 ] ; then
echo "passing the inline script before -- didn't work"
exit 1
fi
2023-12-13 20:20:22 +01:00
# CVE-2023-50246: No heap overflow for '-10E-1000000001'
$VALGRIND $Q $JQ . <<\NUM
-10E-1000000001
NUM
2025-02-01 15:09:30 +09:00
# test for --indent and --compact-output -- #1465
printf '[1,2]\n' > $d /expected
$JQ --compact-output -n "[1,2]" > $d /out
cmp $d /out $d /expected
printf '[\n1,\n2\n]\n' > $d /expected
$JQ --indent 0 -n "[1,2]" > $d /out
cmp $d /out $d /expected
printf '[\n 1,\n 2\n]\n' > $d /expected
$JQ --indent 1 -n "[1,2]" > $d /out
cmp $d /out $d /expected
printf '[\n 1,\n 2\n]\n' > $d /expected
$JQ --indent 5 -n "[1,2]" > $d /out
cmp $d /out $d /expected
printf '[\n{\n"a": 1\n}\n]\n' > $d /expected
$JQ --indent 0 -n "[{a:1}]" > $d /out
cmp $d /out $d /expected
printf '[\n {\n "a": 1\n }\n]\n' > $d /expected
$JQ --indent 1 -n "[{a:1}]" > $d /out
cmp $d /out $d /expected
printf '[\n {\n "a": 1\n }\n]\n' > $d /expected
$JQ --indent 6 -n "[{a:1}]" > $d /out
cmp $d /out $d /expected
2025-02-17 13:41:01 +01:00
if ! $msys && ! $mingw ; then
# Test handling of timezones -- #2429, #2475
if ! r = $( TZ = Asia/Tokyo $JQ -rn '1731627341 | strflocaltime("%F %T %z %Z")' ) \
|| [ " $r " != "2024-11-15 08:35:41 +0900 JST" ] ; then
echo "Incorrectly formatted local time"
exit 1
fi
2025-03-04 22:11:40 +09:00
2025-02-17 13:41:01 +01:00
if ! r = $( TZ = Europe/Paris $JQ -rn '1731627341 | strflocaltime("%F %T %z %Z")' ) \
|| [ " $r " != "2024-11-15 00:35:41 +0100 CET" ] ; then
echo "Incorrectly formatted local time"
exit 1
fi
2025-03-04 22:11:40 +09:00
2025-05-14 15:16:25 -07:00
# Test when DST is in effect: #1912
if ! r = $( TZ = Europe/Paris $JQ -rn '1750500000 | strflocaltime("%F %T %z %Z")' ) \
|| [ " $r " != "2025-06-21 12:00:00 +0200 CEST" ] ; then
echo "Incorrectly formatted local time"
exit 1
fi
2025-02-17 13:41:01 +01:00
if ! r = $( TZ = Europe/Paris $JQ -rn '1731627341 | strftime("%F %T %z %Z")' ) \
|| ( [ " $r " != "2024-11-14 23:35:41 +0000 UTC" ] \
&& [ " $r " != "2024-11-14 23:35:41 +0000 GMT" ] ) ; then
echo "Incorrectly formatted universal time"
exit 1
fi
2025-03-04 22:11:40 +09:00
2025-02-17 23:54:13 +01:00
if ! r = $( TZ = Etc/GMT+7 $JQ -nc '1731627341 | .,. | [strftime("%FT%T"),strflocaltime("%FT%T%z")]'
) \
|| [ " $r " != '["2024-11-14T23:35:41","2024-11-14T16:35:41-0700"]
["2024-11-14T23:35:41","2024-11-14T16:35:41-0700"]' ] ; then
echo "strftime or strftimelocal are not pure functions"
exit 1
fi
2025-02-17 13:41:01 +01:00
fi
2026-02-24 16:49:40 -06:00
# Test ARG_NEWCLOSURE overflow protection (issue #3458)
# Test 1: Too many function parameters (4097 params triggers the limit)
echo "Testing function parameter limit..."
cat > $d /expected <<EOF
jq: error: too many function parameters or local function definitions (max 4095)
jq: 1 compile error
EOF
$JQ -rn '"def f(\([range(4097) | "a\(.)"] | join(";"))): .; f(\([range(4097)] | join(";")))"' > $d /prog.jq
$JQ -nf $d /prog.jq 2> $d /out && {
echo "Expected compile error for too many parameters"
exit 1
}
diff $d /out $d /expected
# Test 2: Too many local functions (4097 functions triggers the limit)
echo "Testing local function limit..."
cat > $d /expected <<EOF
jq: error: too many function parameters or local function definitions (max 4095)
jq: 1 compile error
EOF
$JQ -rn '"\([range(4097) | "def f\(.): \(.)"] | join("; ")); \([range(4097) | "f\(.)"] | join(" + "))"' > $d /prog.jq
$JQ -nf $d /prog.jq 2> $d /out && {
echo "Expected compile error for too many local functions"
exit 1
}
diff $d /out $d /expected
2026-04-13 08:46:11 +09:00
# CVE-2026-33948: No NUL truncation in the JSON parser
if printf '{}\x00{}' | $JQ >/dev/null 2> /dev/null; then
printf 'Error expected but jq exited successfully\n' 1>& 2
exit 1
fi
2026-04-24 22:15:08 +09:00
# CVE-2026-41256: No NUL truncation in program files loaded with -f
printf '.\x00invalid' > " $d /nul_prog.jq"
if echo '42' | $JQ -f " $d /nul_prog.jq" >/dev/null 2>/dev/null; then
printf 'Error expected for program file with NUL bytes\n' 1>& 2
exit 1
fi
2014-12-26 21:28:31 -06:00
exit 0