Skip to content

Testpq/tap pq session/v16#6

Open
adunstan wants to merge 5 commits into
masterfrom
testpq/tap_pq_session/v16
Open

Testpq/tap pq session/v16#6
adunstan wants to merge 5 commits into
masterfrom
testpq/tap_pq_session/v16

Conversation

@adunstan

Copy link
Copy Markdown
Owner

No description provided.

adunstan added 5 commits June 14, 2026 11:30
Introduce a session object for TAP tests that talks to the server
directly through libpq instead of spawning a psql child process for
each background session.  Connecting in-process avoids the overhead and
fragility of driving psql over pipes and gives tests synchronous and
asynchronous query interfaces, notice capture, and pipelined queries.

libpq is reached through an FFI::Platypus wrapper, so no compiled XS
module is required.  The new modules are:

  PostgreSQL::Test::Session  - the libpq session object
  PostgreSQL::PqFFI          - FFI bindings to libpq
  PostgreSQL::PqConstants    - libpq constants
  PostgreSQL::PGTypes        - libpq type OID definitions
  PostgreSQL::FindLib        - locate the libpq shared library

Unless the connection string already names a role, the session pins the
connecting user to the operating-system user rather than letting a stray
PGUSER in the environment select it; this matches how the rest of the
test framework connects and, in particular, the SSPI usermap used on
Windows.  A failed connection records the libpq error message (in
$PostgreSQL::Test::Session::connect_error) before returning undef, so
callers that treat the failure as fatal can report why.

Install the new modules from both the make and meson builds.
Make the test framework itself benefit from in-process libpq access:

  * PostgreSQL::Test::Cluster::safe_psql() runs a single, parameterless
    statement through a Session instead of spawning psql, and reports the
    libpq connection error if the session cannot be established.  It falls
    back to psql for multi-statement or parameterized calls, and also when
    PGOPTIONS is set: PGOPTIONS injects connection-time GUCs the caller
    relies on, and an FFI-loaded libpq does not reliably see a PGOPTIONS
    set in %ENV at run time on Windows (separate C runtime), whereas a
    spawned psql inherits it.
  * poll_query_until() polls through a Session.
  * add poll_until_connection() to wait for the server to accept
    connections.

Also harden PostgreSQL::Test::Utils against errors raised during global
destruction.  Such errors happen after the test body has finished (for
example FFI::Platypus bindings or callback closures being freed in an
unpredictable order as the process exits); reporting them by calling
done_testing() a second time would spuriously fail an otherwise-passing
test, so they are now logged and ignored.
Convert tests that drove a long-lived background psql process (or
repeatedly spawned psql) to use the libpq Session object instead.  This
covers concurrent-session and asynchronous-query tests across contrib,
src/bin and src/test: amcheck, bloom, pg_visibility, test_decoding,
pg_amcheck, pg_upgrade, authentication, oauth_validator, test_aio,
test_checksums, test_misc, test_slru, xid_wraparound, postmaster,
recovery and subscription.

Where a test must load libpq from a different installation than the one
it connects to (pg_upgrade's cross-version workload), it passes that
node so Session locates the library correctly on all platforms.
PostgreSQL::Test::Session loads libpq in-process via FFI::Platypus,
which the CI environments do not yet provide, and the switch exposed
several other gaps in the CI setups:

* Install FFI::Platypus at job setup time: from the Debian package on
  the Linux containers, via MacPorts on macOS, and from CPAN on MinGW
  (MSYS2 does not package it).  The Windows VS job needs nothing, as
  Strawberry Perl already bundles FFI::Platypus.

* Linux - Meson (64-bit) builds with -fsanitize=address.  Loading the
  ASan-instrumented libpq into the uninstrumented perl aborts every
  TAP test with "ASan runtime does not come first in initial library
  list" (reported as exit status 250 via testwrap).  Preload the ASan
  runtime for that job's "Test world" step, scoped to the step so the
  build and ccache are unaffected.

* Linux - Meson (32-bit) runs its TAP tests with the image's i386
  perl, so it needs the i386 build of libffi-platypus-perl.  That
  package cannot be installed alongside the amd64 one (it depends on
  perl:i386, which conflicts with the installed amd64 perl), so
  download it and extract it into place with dpkg -x, the same way
  the image provides the i386 perl itself.  Verified against the
  linux_debian_trixie_ci container image.

* Adding p5.34-ffi-platypus to the macOS package list changed the
  MacPorts cache key, and the resulting fresh MacPorts installation
  revealed that curl and libuuid were never in the package list even
  though the job configures with -Dlibcurl=enabled and -Duuid=e2fs;
  both had been supplied by stale cached installations.  Add curl and
  libuuid (MacPorts' build of util-linux's libuuid, which installs
  uuid/uuid.h and uuid.pc).

Eventually the Linux requirements should instead be handled in the
pg-vm-images container builds.
PostgreSQL::Test::Session, used throughout the TAP test framework,
requires FFI::Platypus, but neither build system checked for it at
configure time; a missing module surfaced as hundreds of individual
test failures instead.  Add the module to config/check_modules.pl,
which both configure and meson already run when TAP tests are
requested, requiring at least version 1.00 (PostgreSQL::PqFFI uses
the api => 1 interface and record_layout_1).  Mention the new
requirement in the documentation and in src/test/perl/README.

The generated configure was re-created with Autoconf 2.69.
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