-! stderr=$(invoke_bfs basic -execdir "$TESTS/nonexistent" {} + 2>&1 >/dev/null)
-[ -n "$stderr" ]
-
-! bfs_diff basic -execdir "$TESTS/nonexistent" {} + -print
+bfs_diff basic -execdir "$TESTS/nonexistent" {} + -print 2>"$TEST/err" && fail
+test -s "$TEST/err"
-! stderr=$(invoke_bfs basic -execdir "$TESTS/nonexistent" {} \; 2>&1 >/dev/null)
-[ -n "$stderr" ]
-
-! bfs_diff basic -print -execdir "$TESTS/nonexistent" {} \; -print
+bfs_diff basic -print -execdir "$TESTS/nonexistent" {} \; -print 2>"$TEST/err" && fail
+test -s "$TEST/err"
# POSIX says it's okay to either stop or keep going on seeing a filesystem
# loop, as long as a diagnostic is printed
-! errors=$(invoke_bfs -L loops 2>&1 >/dev/null)
-[ -n "$errors" ]
+invoke_bfs -L loops >/dev/null 2>"$OUT" && fail
+test -s "$OUT"
# Failure to execute the command should lead to an error message and
# non-zero exit status. See https://unix.stackexchange.com/q/704522/56202
-
-! stderr=$(invoke_bfs basic -exec "$TESTS/nonexistent" {} \; 2>&1 >/dev/null)
-[ -n "$stderr" ]
-
-! bfs_diff basic -print -exec "$TESTS/nonexistent" {} \; -print
+bfs_diff basic -print -exec "$TESTS/nonexistent" {} \; -print 2>"$TEST/err" && fail
+test -s "$TEST/err"
-! stderr=$(invoke_bfs basic -exec "$TESTS/nonexistent" {} + 2>&1 >/dev/null)
-[ -n "$stderr" ]
-
-! bfs_diff basic -exec "$TESTS/nonexistent" {} + -print
+bfs_diff basic -exec "$TESTS/nonexistent" {} + -print 2>"$TEST/err" && fail
+test -s "$TEST/err"
if ((VERBOSE_ERRORS)); then
run_test "$1"
else
- run_test "$1" 2>"$TMP/TEST.err"
+ run_test "$1" 2>"$TMP/$TEST.err"
fi
ret=$?
return $ret
}
-# Reap a background job
-reap() {
- wait -n
+# Wait for any background job to complete
+if ((BASH_VERSINFO[0] > 4 || (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 3))); then
+ wait_any() {
+ wait -n
+ }
+else
+ wait_any() {
+ read -ra jobs < <(jobs -p)
+ wait ${jobs[0]}
+ }
+fi
+
+# Wait for a background test to finish
+wait_test() {
+ wait_any
ret=$?
((BG--))
OUT="$TMP/$TEST.out"
if ((BG >= JOBS)); then
- reap
+ wait_test
fi
((++BG))
done
while ((BG > 0)); do
- reap
+ wait_test
done
printf "${BOL}"
## Utilities for the tests themselves
+# Default return value for failed tests
+EX_FAIL=1
+
+# Fail the current test
+fail() {
+ exit $EX_FAIL
+}
+
# Return value when a test is skipped
EX_SKIP=77
# Run a command and check its exit status
check_exit() {
local expected="$1"
- local actual="0"
+ local actual=0
shift
- "$@" || actual="$?"
+ "$@" || actual=$?
((actual == expected))
}
# Allow bfs to fail, but not crash
if ((ret > 125)); then
- exit "$ret"
+ exit $ret
else
- return "$ret"
+ return $ret
fi
}
"$UNBUFFER" bash -c 'stty cols 80 rows 24 && "$@"' bash "${BFS[@]}" "$@" || ret=$?
if ((ret > 125)); then
- exit "$ret"
+ exit $ret
else
- return "$ret"
+ return $ret
fi
}
# Print a message including path, line number, and command
debug() {
- local file="${1/#*\/tests\//tests\/}"
+ local file="${1/#*\/tests\//tests/}"
set -- "$file" "${@:2}"
color printf "${BLD}%s:%d:${RST} %s\n %s\n" "$@"
}
fi
}
+DEFER_LEVEL=-1
+
# Run a command when this (sub)shell exits
defer() {
- # Refresh trap state before trap -p
- # See https://unix.stackexchange.com/a/556888/56202
- trap -- KILL
-
# Check if the EXIT trap is already set
- if ! trap -p EXIT | grep -q pop_defers; then
+ if ((DEFER_LEVEL != BASH_SUBSHELL)); then
+ DEFER_LEVEL=$BASH_SUBSHELL
DEFER_CMDS=()
DEFER_LINES=()
DEFER_FILES=()