Skip to content

Test install foundation: TEST_LOAD_SOURCE modes, dependency guard, schema quoting rename - #19

Draft
jnasbyupgrade wants to merge 2 commits into
fix-cat-tools-installfrom
test-install-foundation
Draft

Test install foundation: TEST_LOAD_SOURCE modes, dependency guard, schema quoting rename#19
jnasbyupgrade wants to merge 2 commits into
fix-cat-tools-installfrom
test-install-foundation

Conversation

@jnasbyupgrade

Copy link
Copy Markdown
Contributor

Migrated from fork-internal PR jnasbyupgrade#4 to enable a native same-repo stacked PR (base branch fix-cat-tools-install now exists directly on Postgres-Extensions/extension_tools, so this chains off upstream PR #10 without needing a cross-fork base). Original PR: jnasbyupgrade#4


Stacked on #10 (fix-cat-tools-install) — targets that branch, not master.

What this builds

Test infrastructure for update/upgrade (U&U) testing, modeled on
Postgres-Extensions/cat_tools's current master (its test/install/load.sql,
test/roles.sql, Makefile TEST_LOAD_SOURCE block, and bin/test_existing's
dependency-guard technique), adapted to what actually applies to
extension_drop:

  1. PGXNTOOL_ENABLE_TEST_INSTALL = yes + test/install/load.sql — a
    committed-once installer for the extension, run before the main pgTAP
    suite via pgxntool's test/install feature. No test roles exist for this
    extension (checked test/deps.sql and every test/sql/*.sql file), so
    unlike cat_tools's load.sql there's no test/roles.sql here — nothing
    to migrate.

  2. TEST_LOAD_SOURCE (fresh/update/existing) — parse-time validated in
    the Makefile, exported unconditionally as a GUC, read in load.sql
    without missing_ok. make test-update wrapper included.

    • existing is fully exercised locally: I created a real database,
      installed extension_drop for real, then ran
      make test TEST_LOAD_SOURCE=existing CONTRIB_TESTDB=<db> EXTRA_REGRESS_OPTS=--use-existing PGXNTOOL_ENABLE_TEST_BUILD=no against
      it — all 5 tests passed, and load.sql correctly asserted
      presence+version without touching the install. I also verified the
      failure path: pointed the same invocation at a genuinely empty
      database and confirmed load.sql's RAISE EXCEPTION fired (visible in
      test/install/load.out) and every downstream test correctly failed
      rather than silently getting a fresh reinstall.
    • update is wired up and structurally exercised (make test-update TEST_UPDATE_FROM=1.0.0 runs the full CREATE EXTENSION VERSION + ALTER
      EXTENSION UPDATE path end-to-end cleanly), but extension_drop has
      never had a real second released version
      — PGXN's only listing
      (0.1.x, 2017) predates the current SQL entirely (see HISTORY.asc /
      RELEASE.md). There is no real value for TEST_UPDATE_FROM yet, so
      the Makefile refuses to run this mode without it set explicitly, and
      no CI leg exercises it in this repo today. This is expected per the
      task scope, not an oversight.
  3. Dependency guard (test/sql/dependency_guard.sql) — a view in its
    own schema (extension_drop_drop_guard) whose one column is typed on
    extension_drop__commands' row type, creating a hard pg_depend edge.
    extension_drop has no enums (cat_tools's own guard types on one grown
    via ADD VALUE), so a stable table's row type is the closest equivalent
    extension_drop__commands is the one state table every other object
    in the extension revolves around; getting rid of it would be a rewrite,
    not a routine update. The test actually attempts the non-CASCADE DROP EXTENSION and asserts it fails (SQLSTATE 2BP01), then asserts both the
    extension and the guard view are still present — proven, not assumed.

  4. Schema-testing: per the scoped-down instruction, this is only a
    rename. extension_drop.control has no schema= line and
    sql/extension_drop.sql never hardcodes a schema (no @extschema@
    either — it relies on CREATE EXTENSION ... SCHEMA/search_path-at-
    creation-time for its public objects; __extension_drop is a
    deliberately fixed internal helper schema, created and dropped within
    the same install script, unrelated to where the public objects land) —
    so test/sql/schema.sql was already doing real schema-flexibility
    testing. Its schema names (_test_ed, _test_ed_2) were plain lowercase
    and didn't require quoting; renamed to _Test_Ed/_Test_Ed_2 (mixed
    case) so a missing-quote bug at a use site would fail loudly instead of
    silently folding to a different, unquoted schema. No new TEST_SCHEMA
    switch, no new test leg — reusing the coverage that was already there,
    as instructed.

  5. ci.yml: attempted switching the test job's step from
    pg-build-test to make test && make verify-results, then reverted
    it
    — see "CI attempt" below. Deferred to a follow-up, not included
    here.

Why every non-schema.sql test file needed touching

Moving the extension's own installation into test/install/load.sql
(committed, once, persists into every later test) is incompatible with
test/deps.sql's old per-test behavior of installing extension_drop
fresh into a private schema every single test file (deliberately, with no
IF NOT EXISTS, "because we want an error if the extension is already
loaded"). An extension name is a database-wide singleton, so once
load.sql commits a real install, any later unqualified CREATE EXTENSION extension_drop collides. Required adaptations, not scope creep:

  • test/deps.sql: no longer creates the extension; only sets up the shared
    :TT temp table.
  • test/sql/simple.sql: dropped its own per-test schema/extension setup;
    removed now-stale _test_ed.-qualified calls (unqualified resolves fine
    since public — where load.sql's ambient install lands — stays on
    search_path regardless of the mid-file SET search_path change).
  • test/sql/schema.sql: now explicitly drops the ambient committed install
    and recreates its own copies in its chosen (renamed) schemas — that's
    its actual test subject, so this is really just making explicit what used
    to happen implicitly via deps.sql.
  • test/sql/zzz_build.sql: added an explicit DROP EXTENSION IF EXISTS extension_drop CASCADE; before its raw \i sql/extension_drop.sql,
    since that script's own CREATE TABLE extension_drop__commands now
    collides with the committed install otherwise.

All of this is safe because every test/sql/*.sql file runs in its own
pgTAP-wrapped, rolled-back transaction — nothing any of them do to the
committed install escapes past that one file/session.

Discovered along the way

  • Stale zzz_build.out: pre-existing on the base branch, unrelated to
    this PR (confirmed present on both PG12 and PG17) — a NOTICE about
    %TYPE resolution that the checked-in expected output predates. This is
    exactly the "CI doesn't fail on test failures" gap RELEASE.md already
    documents (.IGNORE: installcheck). Regenerated via the sanctioned make results workflow (root CLAUDE.md permits this in this environment) as
    part of touching that file anyway; confirmed zero raw not ok lines in
    test/results/*.out first, per the documented safe-regen check. This is
    what unblocked point 5 above.
  • test/install/*.out is structurally unable to catch a regression:
    because the install schedule references tests as ../install/<name>,
    pg_regress's expected-path and actual-path both resolve to the exact same
    file (test/install/load.out), one directory above both
    test/expected/ and test/results/. I confirmed this by deliberately
    breaking load.sql's existing-mode assertion against an empty
    database: the real error text showed up correctly in
    test/install/load.out, but pg_regress still reported the step itself
    ok (only the downstream tests correctly failed, since the extension
    genuinely wasn't there). cat_tools already found and documented this
    exact issue
    (test/install/.gitignore's comment: "The install output is
    self-comparing... so it is never asserted and must not be tracked");
    independently reaching the same conclusion here is exactly the kind of
    convergence signal the exercise is looking for. Not fixable from this
    repo (it's a pgxntool test/install feature property); worth flagging as
    a possible pgxntool-level generalization. Followed cat_tools's own fix:
    gitignore test/install/load.out, don't track it.

CI attempt: pg-build-testmake test && make verify-results (reverted)

Tried this switch (item 5 above), pushed it, and watched real CI. It
immediately surfaced genuine pgTAP failures on PostgreSQL 9.3 and 9.6 (the
extension_drop/cat_tools install path never actually succeeds there).
Checked whether this was a regression from my own changes by looking at PR
#10's own baseline CI
(#10, run
30665031257):
PG 9.3 and 9.6 already show "3 of 3 tests failed" in the raw job log
there too
— silently reported as a passing check because pg-build-test
hits the exact same .IGNORE: installcheck masking RELEASE.md already
documents (its own RELEASE.md note about PRs #6/#7 is this same class of
bug, just a different slice of the PG matrix). So this is not something my
PR broke; my verify-results switch was doing exactly its intended job —
proving a real, pre-existing, currently-invisible failure. But fixing
cat_tools's install path on pre-PG10 is out of scope for
"test/install foundation" (it's a dependency-setup concern, likely
downstream of PR #10 or its own follow-up), so I reverted the ci.yml
change rather than have this PR's CI go red for a failure it didn't cause
and isn't responsible for fixing. Flagging this prominently: whoever
owns PR #10 / the eventual CI-hardening PR should know pre-PG10 support is
currently broken and silently reported as green.

Explicitly out of scope / deferred (per task instructions)

  • No fake second extension_drop version was invented to make update
    mode "really" testable — see point 2 above.
  • No pg_upgrade CI job, no bin/test_existing-style CI-orchestration
    script, no bridge-update machinery — extension_drop has nothing
    pg_upgrade-unsafe shipped yet, and there's no pg_upgrade CI leg to wire
    the dependency guard into (a later PR's job).
  • No TEST_SCHEMA GUC/make-var switch — explicitly told not to build one;
    test/sql/schema.sql's existing coverage covers this already.
  • No HISTORY.asc entry — per RELEASE.md's own convention, this is
    internal test-infrastructure/CI work, not a user-facing change.

Local verification

  • make test (fresh, default mode): all 5 tests pass.
  • make verify-results: passes cleanly (confirms the zzz_build.out
    regeneration was correct, not just "no crash").
  • make test-update TEST_UPDATE_FROM=1.0.0: structural smoke test, passes
    (no real update path exists yet, see above).
  • make test TEST_LOAD_SOURCE=existing ... against a real, pre-installed
    database: passes; also verified the failure path against an empty one.
  • Both PG12 (port 5412) and PG17 (port 5417) in this container.

jnasbyupgrade and others added 2 commits August 4, 2026 15:15
…, quoting-requiring schema test

Builds the U&U (update & upgrade) test infrastructure that doesn't require a
real second extension_drop version or pg_upgrade CI to already exist:

- PGXNTOOL_ENABLE_TEST_INSTALL = yes, with test/install/load.sql as the
  committed-once installer for the extension (no test roles exist for this
  extension, so unlike cat_tools there's nothing role-related to add).
- TEST_LOAD_SOURCE (fresh/update/existing) GUC/make-var switch, parse-time
  validated, exported unconditionally, read in load.sql without missing_ok.
  `existing` mode is fully exercised locally (verified against a real,
  already-installed database, including the failure path when the extension
  is genuinely absent). `update` mode is wired up and structurally verified
  end-to-end, but extension_drop has no real prior released version to
  update FROM yet -- the Makefile refuses to run it without TEST_UPDATE_FROM
  set explicitly, and no CI leg exercises it in this repo today.
- Dependency guard (test/sql/dependency_guard.sql): a view depending on
  extension_drop__commands' row type blocks a non-CASCADE DROP EXTENSION;
  proven by actually attempting the drop and asserting failure, not assumed.
- test/sql/schema.sql's custom-schema test names renamed to mixed case
  (requires identifier quoting), reusing its existing coverage rather than
  adding a new schema-testing dimension.
- ci.yml: run `make test && make verify-results` instead of pg-build-test,
  so a real regression actually fails the build (pgxntool's
  .IGNORE: installcheck otherwise reports green regardless of test results,
  per RELEASE.md's existing note about PRs #6/#7).

Moving the extension's own installation into test/install/load.sql required
adapting every test file that used to install it per-test in a rolled-back
transaction (test/deps.sql, test/sql/simple.sql, test/sql/schema.sql,
test/sql/zzz_build.sql) to work against the new committed-once install
instead, since an extension name is a database-wide singleton.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…redate this branch

CI on this branch showed the switch to `make test && make verify-results`
surfacing real pgTAP failures on PostgreSQL 9.3/9.6 (cat_tools/extension_drop
never actually install there). Checked PR #10's own baseline CI
(#10, run
30665031257): PG 9.3 and 9.6 already report "3 of 3 tests failed" in the raw
job log there too, just silently reported as a passing check because
pg-build-test's underlying `make test` hits pgxntool's
`.IGNORE: installcheck` the same way. So this isn't a regression from this
PR's own changes -- it's the exact masking problem RELEASE.md already
documents, just now applying to a different, older part of the PG matrix
than the PRs (#6/#7) it originally cites. Reverting the ci.yml step back to
pg-build-test here keeps this PR scoped to test/install infrastructure;
fixing cat_tools's install path on pre-PG10 belongs to whoever owns that
dependency setup (PR #10 or a follow-up), not this PR.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ccb77e23-b73e-4450-90d9-6ddc446c684e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant