We can't know how many bytes fgets() read when we reach EOF and fgets() didn't see a newline; we can only assume that at least strlen(buf) bytes were read. This is quite obnoxious if one wants to use NULs in raw input, but at least we can make reading "a\0b\0c\0" with no newline yield "a\0b\0c", losing only the final sequence of NULs. We can't use getline() either, since it will want to allocate a buffer big enough for an entire line, and we might not have any newlines in our input. A complete fix will have to use getc() or read(), preferably the latter.
213 lines
6.8 KiB
Bash
Executable File
213 lines
6.8 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
set -e
|
|
|
|
if which valgrind > /dev/null; then
|
|
VALGRIND='valgrind --error-exitcode=1 --leak-check=full --suppressions=tests/onig.supp'
|
|
Q=-q
|
|
else
|
|
VALGRIND=
|
|
Q=
|
|
fi
|
|
|
|
mods=$PWD/tests/modules
|
|
|
|
# jq-coded tests here:
|
|
cat $@ | $VALGRIND $Q ./jq -L "$mods" --run-tests
|
|
|
|
clean=true
|
|
d=
|
|
clean () {
|
|
if ! $clean; then
|
|
echo "See temp files in $d!"
|
|
elif [ -n "$d" ]; then
|
|
rm -rf "$d"
|
|
fi
|
|
}
|
|
trap clean EXIT
|
|
d=`mktemp -d -t || true`
|
|
if [ -z "$d" ]; then
|
|
echo "Your OS does not support mktemp(1) -d" 1>&2
|
|
exit 0
|
|
fi
|
|
|
|
printf 'a\0b\nc\0d\ne' > $d/input
|
|
$VALGRIND $Q ./jq -Rse '. == "a\u0000b\nc\u0000d\ne"' $d/input
|
|
$VALGRIND $Q ./jq -Rne '[inputs] == ["a\u0000b", "c\u0000d", "e"]' $d/input
|
|
|
|
## Test constant folding
|
|
|
|
## XXX If we add a builtin to list the program's disassembly then we can
|
|
## move all of these into tests/all.test
|
|
|
|
# String constant folding (addition only)
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '"foo"' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
|
|
# Numeric constant folding (not all ops yet)
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '1+1' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '1-1' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '2*3' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '9/3' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '9==3' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '9!=3' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '9<=3' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
n=`$VALGRIND $Q ./jq -n --debug-dump-disasm '9>=3' | wc -l`
|
|
if [ $n -ne 5 ]; then
|
|
echo "Constant expression folding for strings didn't work"
|
|
exit 1
|
|
fi
|
|
|
|
## Test JSON sequence support
|
|
|
|
## XXX If we add a `stream_fromjson` builtin then we can move these tests
|
|
## into tests/all.test
|
|
|
|
cat > $d/expected <<EOF
|
|
ignoring parse error: Potentially truncated top-level numeric value at line 1, column 2
|
|
ignoring parse error: Truncated value at line 2, column 5
|
|
ignoring parse error: Truncated value at line 2, column 25
|
|
ignoring parse error: Truncated value at line 2, column 41
|
|
EOF
|
|
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
|
|
cmp $d/out $d/expected
|
|
|
|
cat > $d/expected <<EOF
|
|
ignoring parse error: Potentially truncated top-level numeric value at line 1, column 2
|
|
ignoring parse error: Truncated value at line 2, column 5
|
|
ignoring parse error: Truncated value at line 2, column 25
|
|
ignoring parse error: Truncated value at line 3, column 1
|
|
EOF
|
|
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
|
|
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
|
|
ignoring parse error: Unfinished string at EOF at line 1, column 4
|
|
EOF
|
|
printf '"foo'|./jq -ce --seq . > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
# Numeric values truncated by EOF are ignored
|
|
cat > $d/expected <<EOF
|
|
ignoring parse error: Potentially truncated top-level numeric value at EOF at line 1, column 1
|
|
EOF
|
|
printf '1'|./jq -ce --seq . > $d/out 2>&1
|
|
cmp $d/out $d/expected
|
|
|
|
cat > $d/expected <<EOF
|
|
EOF
|
|
printf '1\n'|./jq -ces --seq '. == [1]' >/dev/null 2> $d/out
|
|
cmp $d/out $d/expected
|
|
|
|
## Test streaming parser
|
|
|
|
## If we add an option to stream to the `import ... as $symbol;` directive
|
|
## then we can move these tests into tests/all.test.
|
|
$VALGRIND $Q ./jq -c '. as $d|path(..) as $p|$d|getpath($p)|scalars_or_empty|[$p,.]' < "$PWD/tests/torture/input0.json" > $d/out0
|
|
$VALGRIND $Q ./jq --stream -c '.|select(length==2)' < "$PWD/tests/torture/input0.json" > $d/out1
|
|
diff $d/out0 $d/out1
|
|
|
|
## XXX This test can be moved to tests/all.test _now_
|
|
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.
|
|
#
|
|
#len=`wc -c < "$PWD/tests/torture/input0.json"`
|
|
if [ -z "$VALGRIND" ]; then
|
|
start=1
|
|
end=`wc -c < "$PWD/tests/torture/input0.json"`
|
|
else
|
|
start=120
|
|
end=151
|
|
fi
|
|
for i in `seq $start $end`; do
|
|
dd "if=tests/torture/input0.json" bs=$i count=1 2>/dev/null |
|
|
$VALGRIND ./jq -c . > $d/out0 2>$d/err || true
|
|
if [ -n "$VALGRIND" ]; then
|
|
grep '^==[0-9][0-9]*== ERROR SUMMARY: 0 errors' $d/err > /dev/null
|
|
else
|
|
tail -1 $d/err | egrep -i 'assert|abort|core' && false
|
|
fi
|
|
|
|
dd "if=tests/torture/input0.json" bs=$i count=1 2>/dev/null |
|
|
$VALGRIND ./jq -cn --stream -L "$mods" 'import "streaming" as streaming; streaming::tovalues(inputs)' > $d/out1 2>$d/err || true
|
|
if [ -n "$VALGRIND" ]; then
|
|
grep '^==[0-9][0-9]*== ERROR SUMMARY: 0 errors' $d/err > /dev/null
|
|
else
|
|
tail -1 $d/err | egrep -i 'assert|abort|core' && false
|
|
fi
|
|
|
|
diff $d/out0 $d/out1
|
|
done
|
|
else
|
|
echo "Not doing torture tests"
|
|
fi
|
|
|
|
## Fuzz parser
|
|
|
|
## XXX With a `urandom` builtin we could move this test into tests/all.test
|
|
clean=false
|
|
if dd if=/dev/urandom bs=16 count=1024 > $d/rand 2>/dev/null; then
|
|
# Have a /dev/urandom, good
|
|
$VALGRIND $Q ./jq --seq . $d/rand >/dev/null 2>&1
|
|
$VALGRIND $Q ./jq --seq --stream . $d/rand >/dev/null 2>&1
|
|
dd if=/dev/urandom bs=16 count=1024 > $d/rand 2>/dev/null
|
|
$VALGRIND $Q ./jq --seq . $d/rand >/dev/null 2>&1
|
|
$VALGRIND $Q ./jq --seq --stream . $d/rand >/dev/null 2>&1
|
|
dd if=/dev/urandom bs=16 count=1024 > $d/rand 2>/dev/null
|
|
$VALGRIND $Q ./jq --seq . $d/rand >/dev/null 2>&1
|
|
$VALGRIND $Q ./jq --seq --stream . $d/rand >/dev/null 2>&1
|
|
fi
|
|
clean=true
|
|
|
|
## Test library/module system
|
|
|
|
# Check handling of ~/.jq; these can't move into jq_test.c yet because
|
|
# they depend on $HOME
|
|
if [ "`HOME="$mods" $VALGRIND $Q ./jq -nr fg`" != foobar ]; then
|
|
echo "Bug #479 appears to be back" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ `HOME="$mods" $VALGRIND $Q ./jq --debug-dump-disasm -n fg | grep '^[a-z]' | wc -l` -gt 3 ]; then
|
|
echo "Binding too many defs into program" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
exit 0
|