Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions HISTORY.asc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ command, to any value; `\include` and `\include_relative` count as including `ps
`test/install/*.out` was never really compared against anything, and is
rewritten by every run, it's now gitignored -- stop committing it.

== Reject invalid `PGXNTOOL_VERIFY_RESULTS_MODE` values
Any value other than exactly `pgtap` silently selected `diffs` mode, so a
typo like `pgTap` quietly weakened the `make results` safeguard. The value
is now case-insensitive, and anything other than `pgtap` or `diffs` is a
hard `make` error.

== Guarantee `test/install/*.sql` ordering
Install files now always run in byte-value (ASCII) filename order,
regardless of filesystem or locale. If one install file depends on another,
Expand Down
4 changes: 2 additions & 2 deletions README.asc
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ IMPORTANT: *`make results` requires manual verification first*. The correct work
Never run `make results` without first verifying the test changes are correct. The `results` target copies files from `test/results/` to `test/expected/`, so running it blindly will make incorrect output become the new expected behavior.

==== verify-results safeguard
By default, `make results` will refuse to run if your tests are failing, so you can't accidentally promote incorrect output into the new expected results. Which failures it looks for is controlled by `PGXNTOOL_VERIFY_RESULTS_MODE`:
By default, `make results` will refuse to run if your tests are failing, so you can't accidentally promote incorrect output into the new expected results. Which failures it looks for is controlled by `PGXNTOOL_VERIFY_RESULTS_MODE`, which must be one of these two values (case-insensitive; anything else is a hard `make` error):

`pgtap` (the default):: Scans `test/results/*.out` for pgTAP `not ok` lines (ignoring `# TODO` items) and plan-count mismatches, then also checks `test/regression.diffs` for any output mismatch pgTAP itself wouldn't catch. A test that has no expected output file yet is the one exception: it always shows up in `regression.diffs` (pgxntool creates an empty expected file for it, because `pg_regress` aborts on a missing one), so `make results` is allowed to create its first expected output — provided its own pgTAP output is clean and free of SQL errors. If a new test legitimately needs output containing a SQL error blessed, use `PGXNTOOL_ENABLE_VERIFY_RESULTS=no` for that one run.
`diffs`:: Only checks whether `test/regression.diffs` exists, so it can't create a new test's first expected output; use `pgtap` mode, or `PGXNTOOL_ENABLE_VERIFY_RESULTS=no` for that one run.
Expand Down Expand Up @@ -786,7 +786,7 @@ Default: `$(TESTDIR)`. Directory `pg_regress` writes actual test output to -- `$

=== PGXNTOOL_VERIFY_RESULTS_MODE

Default: `pgtap`. Controls how the <<_verify_results_safeguard,verify-results safeguard>> decides whether tests are failing.
Default: `pgtap`. Controls how the <<_verify_results_safeguard,verify-results safeguard>> decides whether tests are failing. Must be `pgtap` or `diffs` (case-insensitive) when given explicitly; any other value, including an empty one, is a hard `make` error.

==== pgtap

Expand Down
6 changes: 3 additions & 3 deletions README.html
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,7 @@ <h3 id="_results"><a class="anchor" href="#_results"></a><a class="link" href="#
<div class="sect3">
<h4 id="_verify_results_safeguard"><a class="anchor" href="#_verify_results_safeguard"></a><a class="link" href="#_verify_results_safeguard">4.7.1. verify-results safeguard</a></h4>
<div class="paragraph">
<p>By default, <code>make results</code> will refuse to run if your tests are failing, so you can&#8217;t accidentally promote incorrect output into the new expected results. Which failures it looks for is controlled by <code>PGXNTOOL_VERIFY_RESULTS_MODE</code>:</p>
<p>By default, <code>make results</code> will refuse to run if your tests are failing, so you can&#8217;t accidentally promote incorrect output into the new expected results. Which failures it looks for is controlled by <code>PGXNTOOL_VERIFY_RESULTS_MODE</code>, which must be one of these two values (case-insensitive; anything else is a hard <code>make</code> error):</p>
</div>
<div class="dlist">
<dl>
Expand Down Expand Up @@ -2118,7 +2118,7 @@ <h3 id="_testout"><a class="anchor" href="#_testout"></a><a class="link" href="#
<div class="sect2">
<h3 id="_pgxntool_verify_results_mode"><a class="anchor" href="#_pgxntool_verify_results_mode"></a><a class="link" href="#_pgxntool_verify_results_mode">8.9. PGXNTOOL_VERIFY_RESULTS_MODE</a></h3>
<div class="paragraph">
<p>Default: <code>pgtap</code>. Controls how the <a href="#_verify_results_safeguard">verify-results safeguard</a> decides whether tests are failing.</p>
<p>Default: <code>pgtap</code>. Controls how the <a href="#_verify_results_safeguard">verify-results safeguard</a> decides whether tests are failing. Must be <code>pgtap</code> or <code>diffs</code> (case-insensitive) when given explicitly; any other value, including an empty one, is a hard <code>make</code> error.</p>
</div>
<div class="sect3">
<h4 id="_pgtap"><a class="anchor" href="#_pgtap"></a><a class="link" href="#_pgtap">8.9.1. pgtap</a></h4>
Expand Down Expand Up @@ -2217,7 +2217,7 @@ <h2 id="_copyright"><a class="anchor" href="#_copyright"></a><a class="link" hre
</div>
<div id="footer">
<div id="footer-text">
Last updated 2026-10-07 16:35:22 -0500
Last updated 2026-10-07 16:52:43 -0500
</div>
</div>
</body>
Expand Down
12 changes: 12 additions & 0 deletions base.mk
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ pgxntool_validate_yesno = $(strip \
$(shell echo "$(1)" | tr '[:upper:]' '[:lower:]'),\
$(error $(2) must be "yes" or "no", got "$(1)")))

# Helper function: normalize a single-word variable to lowercase and validate
# it against a list of allowed values.
# Usage: $(call pgxntool_validate_choice,VALUE,VARIABLE_NAME,ALLOWED_VALUES)
# Returns the lowercase value, or errors if it isn't exactly one of ALLOWED_VALUES.
pgxntool_validate_choice = $(strip \
$(if $(and $(filter 1,$(words $(1))),$(filter $(3),$(shell echo "$(1)" | tr '[:upper:]' '[:lower:]'))),\
$(shell echo "$(1)" | tr '[:upper:]' '[:lower:]'),\
$(error $(2) must be one of: $(3); got "$(1)")))

# ------------------------------------------------------------------------------
# test-build: Sanity check extension files before running full test suite
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -288,6 +297,8 @@ _CHECK_TEST_INSTALL_ERROR_STOP_SCRIPT ?= $(PGXNTOOL_DIR)/test/bin/check-test-ins
#
# Variable: PGXNTOOL_VERIFY_RESULTS_MODE
# - Controls how verify-results detects test failures
# - Allowed values: "pgtap" or "diffs" (case-insensitive); anything else,
# including an empty value, is a parse-time error
# - "pgtap" (default): scans test/results/*.out for "not ok" lines and plan
# mismatches (TAP failures). Also checks regression.diffs as a fallback.
# Use this mode when your test suite uses pgTap.
Expand All @@ -306,6 +317,7 @@ endif

# Default mode: pgtap (scans results/*.out for TAP failures)
PGXNTOOL_VERIFY_RESULTS_MODE ?= pgtap
override PGXNTOOL_VERIFY_RESULTS_MODE := $(call pgxntool_validate_choice,$(PGXNTOOL_VERIFY_RESULTS_MODE),PGXNTOOL_VERIFY_RESULTS_MODE,pgtap diffs)

# ------------------------------------------------------------------------------
# check-stale-expected: catch orphaned/unexpected test/expected/ files
Expand Down
Loading