Skip to content

Commit 32a7000

Browse files
jnasbyupgradeclaude
andcommitted
Add update+upgrade (U&U) test infrastructure: 0.1.0->stable update script,
test/install/load.sql three-mode loader, dependency-guard anchor, and a permanent schema-qualification pgTAP assertion Implements advanced-extension-testing.md checklist items 1-6 on top of PR #17 (reconcile-object-functions): - PGXNTOOL_ENABLE_TEST_INSTALL / PGXNTOOL_ENABLE_VERIFY_RESULTS set explicitly; TEST_LOAD_SOURCE (fresh/update/existing) + TEST_UPDATE_FROM/TO make vars, parse-time validated, propagated as placeholder GUCs via PGOPTIONS; `make test-update` wrapper. - test/install/load.sql: single committed-once installer for the extension, covering all three load modes, including a drop-first reset (with pg_temp.drop_role() for the extension's own global roles) and an existing-mode presence/version assertion. - sql/object_reference--0.1.0--stable.sql: hand-authored update script (there was previously no update path at all from the only real historical release to current). Recreates every function/view that changed via the same private-helper-schema bootstrap/teardown convention the fresh install uses, so the update path is verified byte-for-byte structurally identical to a fresh install (function bodies, comments, ACLs, table/view columns). - Makefile: DATA += sql/object_reference--0.1.0.sql (pgxntool#48 workaround, needed for CREATE EXTENSION ... VERSION '0.1.0' to work at all); a conditional count_nulls install step for the update-mode floor only (0.1.0's own install script still needs it, even though current object_reference no longer requires it). - test/finish.sql: one permanent pgTAP assertion (modeled on pg_count_nulls'/extension_tools' own schema-qualification checks) proving object_reference/_object_reference are never resolved via search_path. - Moved the pre-existing raw-source-load sanity check (test/sql/zzz_build.sql) to test/build/, pgxntool's own test-build feature: it needs a schema-free database to create `object_reference` manually in, which the committed-once installer above no longer provides in the shared main-suite database. Dependency-guard anchor for a future existing-mode CI job: a view typed on _object_reference.object's row type (object_reference-owned, never dropped or redefined by the update script) blocks a non-CASCADE DROP EXTENSION; manually proven to block the drop (and to keep blocking it after the update path) as part of this PR's own verification, not committed as CI machinery yet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 105ee2d commit 32a7000

20 files changed

Lines changed: 1088 additions & 14 deletions

Makefile

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,107 @@
1+
# Committed-once install of the extension (test/install/load.sql), run before
2+
# the main pgTAP suite in its own pg_regress session so its state persists
3+
# (committed) into every per-test file. Must be set (and set to exactly
4+
# "yes"/"no", not auto-detected) BEFORE base.mk is included below, since
5+
# base.mk reads it at parse time.
6+
PGXNTOOL_ENABLE_TEST_INSTALL = yes
7+
8+
# Safeguard for `make results`: refuses to copy test/results/*.out over
9+
# test/expected/*.out while a real regression is showing. This is already
10+
# pgxntool's own default, but set it explicitly so that stays true even if a
11+
# future pgxntool default ever changes.
12+
PGXNTOOL_ENABLE_VERIFY_RESULTS = yes
13+
14+
# TEST_LOAD_SOURCE selects how test/install/load.sql installs the extension:
15+
# - fresh (default): CREATE EXTENSION object_reference (current version).
16+
# - update: CREATE EXTENSION at TEST_UPDATE_FROM (default 0.1.0, the only
17+
# real historical PGXN release) then ALTER EXTENSION UPDATE -- to
18+
# TEST_UPDATE_TO if set, otherwise to the current default_version
19+
# ("stable"). Running the SAME suite with the SAME expected output
20+
# against the updated database verifies it behaves identically to a
21+
# fresh install.
22+
# - existing: the extension is ALREADY installed in the target database (by
23+
# a binary pg_upgrade, or an ALTER EXTENSION UPDATE done outside the
24+
# suite). load.sql does not touch it; it only asserts presence + current
25+
# version. Pair with CONTRIB_TESTDB=<db> and
26+
# EXTRA_REGRESS_OPTS=--use-existing so pg_regress runs against that
27+
# database instead of dropping and recreating a throwaway one.
28+
#
29+
# The mode (and the update from/to versions) are signalled to load.sql via
30+
# placeholder GUCs. pg_regress does not forward make variables, but the psql
31+
# processes it spawns inherit the environment, so PGOPTIONS reaches load.sql.
32+
#
33+
# The GUCs are exported UNCONDITIONALLY, so load.sql can read them WITHOUT
34+
# missing_ok and fail loudly if they did not propagate. Relying on an absent
35+
# GUC to mean "fresh" is unsafe: a silent break anywhere in the
36+
# make -> PGOPTIONS -> env -> psql chain would quietly run the wrong mode.
37+
#
38+
# TEST_LOAD_SOURCE must be exactly `fresh`, `update` or `existing`; anything
39+
# else is a hard error at parse time (so e.g. `make test
40+
# TEST_LOAD_SOURCE=typo` fails fast rather than defaulting).
41+
TEST_LOAD_SOURCE ?= fresh
42+
ifeq ($(filter $(TEST_LOAD_SOURCE),fresh update existing),)
43+
$(error TEST_LOAD_SOURCE must be 'fresh', 'update' or 'existing', got '$(TEST_LOAD_SOURCE)')
44+
endif
45+
46+
# update-mode version range (read by load.sql only in update mode). Empty
47+
# TEST_UPDATE_TO means "update to the current default_version" (stable).
48+
TEST_UPDATE_FROM ?= 0.1.0
49+
TEST_UPDATE_TO ?=
50+
51+
export PGOPTIONS := $(PGOPTIONS) -c object_reference.test_load_mode=$(TEST_LOAD_SOURCE) -c object_reference.test_update_from=$(TEST_UPDATE_FROM) -c object_reference.test_update_to=$(TEST_UPDATE_TO)
52+
53+
# Convenience wrapper: `make test-update` == `make test TEST_LOAD_SOURCE=update`.
54+
# Must recurse (a fresh $(MAKE)) rather than depend on `test`, so the
55+
# parse-time TEST_LOAD_SOURCE conditional above re-evaluates with update set.
56+
.PHONY: test-update
57+
test-update:
58+
$(MAKE) test TEST_LOAD_SOURCE=update
59+
160
include pgxntool/base.mk
261

62+
# pgxntool's base.mk DATA wildcard ($(EXTENSION__CURRENT_VERSION__FILES)
63+
# $(wildcard sql/*--*--*.sql)) only picks up the CURRENT version file and
64+
# two-dash update-diff scripts -- it never matches a one-dash historical
65+
# full-install file like sql/object_reference--0.1.0.sql, so `make install`
66+
# would silently never place it in the extension directory and `CREATE
67+
# EXTENSION object_reference VERSION '0.1.0'` (needed by TEST_UPDATE_FROM
68+
# above) would fail with "extension control file ... does not exist".
69+
# Same gap already filed upstream: Postgres-Extensions/pgxntool#48.
70+
DATA += sql/object_reference--0.1.0.sql
71+
372
testdeps: $(wildcard test/*.sql test/helpers/*.sql) # Be careful not to include directories in this
473
testdeps: test_factory
574

675
install: cat_tools
776

77+
# 0.1.0 (TEST_UPDATE_FROM's default -- the update-mode floor, see above) needs
78+
# count_nulls too: its install script's _object_oid.null_count trigger calls
79+
# count_nulls' not_null_count_trigger(), and object_reference.control's
80+
# `requires` (cat_tools only -- count_nulls was dropped once the reg*
81+
# pseudotype removal made that trigger unnecessary) no longer CASCADEs it in.
82+
# Only needed for update-mode testing against that floor -- current
83+
# object_reference has no runtime dependency on count_nulls at all -- so this
84+
# is conditional, not folded into the unconditional `install: cat_tools` above.
85+
ifeq ($(TEST_LOAD_SOURCE),update)
86+
install: count_nulls
87+
endif
88+
89+
.PHONY: count_nulls
90+
count_nulls: $(DESTDIR)$(datadir)/extension/count_nulls.control
91+
$(DESTDIR)$(datadir)/extension/count_nulls.control:
92+
pgxn install count_nulls
93+
894
# pgxntool's check-stale-expected target (added in pgxntool 2.2.0) depends on
995
# installcheck but is listed before install in TEST_DEPS, and Make evaluates a
1096
# target's prerequisites in file-parse order across stanzas -- so plain
1197
# `make test` ran installcheck before install ever happened. Force installcheck
1298
# to require install locally until that's fixed upstream.
1399
installcheck: install
14100

101+
# Clean the cruft pg_regress writes into test/install/ (the self-comparing
102+
# result .out and its diff), which is listed in test/install/.gitignore.
103+
extra_clean += $(addprefix test/install/,$(shell grep -v '^\#' test/install/.gitignore 2>/dev/null))
104+
15105
test: dump_test
16106
extra_clean += $(wildcard test/dump/*.log)
17107
dump_test: test/dump/run.sh test/helpers/object_table.sql $(wildcard test/dump/*.sql)

0 commit comments

Comments
 (0)