diff --git a/test/bin/check-test-install-error-stop.sh b/test/bin/check-test-install-error-stop.sh index 26c98e5..61f2700 100755 --- a/test/bin/check-test-install-error-stop.sh +++ b/test/bin/check-test-install-error-stop.sh @@ -12,8 +12,13 @@ # net so its absence is caught at build time instead of discovered the hard # way (issue #97). # -# A file passes if it either sets ON_ERROR_STOP itself, or sources -# test/pgxntool/psql.sql (which already sets it, among other things). +# A file passes if it explicitly turns ON_ERROR_STOP on at some point -- +# directly (`\set ON_ERROR_STOP on`/true/1/yes) or by sourcing +# test/pgxntool/psql.sql (which already turns it on, among other things). A +# later explicit turn-off doesn't undo an earlier turn-on. A file that only +# ever turns it off, or never mentions it at all, fails: a bare substring +# match on "ON_ERROR_STOP" would wrongly pass a file that only turns it off, +# so each `\set` needs its value read, in file order. # # Usage: check-test-install-error-stop.sh @@ -30,13 +35,30 @@ testdir="$1" install_dir="$testdir/install" missing=() +# Scans $1 in file order, tracking whether ON_ERROR_STOP has been explicitly +# turned on. Succeeds (exit 0) once an on-value is seen; a later off-value +# doesn't reset that. Sourcing psql.sql counts as turning it on, wherever it +# occurs in the file. +file_turns_error_stop_on() { + local f="$1" line value + while IFS= read -r line; do + if [[ "$line" =~ \\ir?[[:space:]]+.*psql\.sql ]]; then + return 0 + fi + if [[ "$line" =~ \\set[[:space:]]+ON_ERROR_STOP[[:space:]]+([^[:space:]]+) ]]; then + value="${BASH_REMATCH[1],,}" + case "$value" in + on|true|1|yes) return 0 ;; + esac + fi + done < "$f" + return 1 +} + for f in "$install_dir"/*.sql; do [ -f "$f" ] || continue - if grep -q 'ON_ERROR_STOP' "$f"; then - continue - fi - if grep -qE '\\ir? +.*psql\.sql' "$f"; then + if file_turns_error_stop_on "$f"; then continue fi