This guide covers all testing scenarios for pg_durable.
| What | Command |
|---|---|
| Unit tests | ./scripts/test-unit.sh |
| pg_regress tests | make test-regress |
| E2E tests (local) | ./scripts/test-e2e-local.sh |
| E2E tests (Docker) | ./scripts/test-e2e-docker.sh |
| Worker lifecycle regressions | ./scripts/test-shutdown.sh, ./scripts/test-epoch-race.sh |
| Stop PostgreSQL | ./scripts/pg-stop.sh |
| Deploy to ACR | ./scripts/deploy-acr.sh |
pg_durable has three test suites:
- Unit Tests — Rust tests using pgrx (
#[pg_test]) - pg_regress Tests — Standard PostgreSQL regression tests (deterministic, fast)
- E2E Tests — Comprehensive scenario tests with Docker (complex scenarios)
| Suite | Use For | Characteristics |
|---|---|---|
| Unit | Testing individual Rust functions | Fast, isolated |
| pg_regress | Core DSL operators/functions | Deterministic, standard PostgreSQL testing |
| E2E | Complex scenarios, HTTP, timing | Comprehensive, may include variable timing |
Runs Rust unit tests using cargo pgrx test. These test individual functions in isolation.
# Run all unit tests
./scripts/test-unit.sh
# Run tests matching a pattern
./scripts/test-unit.sh simpleWhat it does:
- Compiles the extension
- Starts a temporary PostgreSQL instance
- Runs
#[pg_test]annotated functions - Cleans up automatically
Standard PostgreSQL regression tests for core DSL functionality. These tests are fast, deterministic, and use PostgreSQL's industry-standard testing framework.
# Recommended: reset the dedicated local cluster, install, and run all tests
make test-regress
# Run against an already-running disposable test cluster
PGHOST=localhost \
PGPORT=28817 \
PGUSER=postgres \
PG_CONFIG=/path/to/pg_config \
CONTRIB_TESTDB=contrib_regression \
make installcheck
# Run specific test
make installcheck REGRESS=simple
# View test output
cat regression.out
# View diffs (on failure)
cat regression.diffsDirect make installcheck uses PGXS against an installed PostgreSQL server. By
default, pg_regress drops and recreates CONTRIB_TESTDB; never point it at a
database containing valuable data. The server must already have the current
pg_durable artifacts installed, shared_preload_libraries = 'pg_durable', and
pg_durable.database set to the same database as CONTRIB_TESTDB, followed by
a restart. The test user must be able to create databases, roles, and
extensions. Use make test-regress for the managed local test cluster.
What it tests:
- Core DSL operators:
~>,|=>,&,?>,!> - DSL functions:
df.sql(),df.seq(),df.as(),df.join(),df.if() - Helper functions:
df.await_instance()
Key features:
- Deterministic output (no UUIDs, timestamps, or variable timing)
- Fast feedback (< 10 seconds for all tests)
- Standard PostgreSQL testing approach
- Familiar to PostgreSQL developers
Test SQL files are in sql/, expected output in expected/, and PGXS is configured in the root Makefile.
End-to-end tests that exercise the full system including the background worker.
Fast iteration using local pgrx PostgreSQL. Best for development.
# Run all tests (starts/stops server automatically)
./scripts/test-e2e-local.sh
# Run specific test
./scripts/test-e2e-local.sh 04_parallel
# Run only the phases that share the standard build artifact
./scripts/test-e2e-local.sh --default-build-phases
# Run test multiple times (stability check)
./scripts/test-e2e-local.sh 04_parallel 5
# Keep server running after tests (for investigation)
./scripts/test-e2e-local.sh --keep
# Start fresh (wipe database)
./scripts/test-e2e-local.sh --cleanInvestigation mode (--keep):
# Run tests, keep server running
./scripts/test-e2e-local.sh --keep 04_parallel
# Connect to database
~/.pgrx/17.*/pgrx-install/bin/psql -h localhost -p 28817 -d postgres
# View logs
tail -f ~/.pgrx/17.log
# When done, stop server
./scripts/pg-stop.shTests in a linux/amd64 container. Runs all the local e2e tests that don't require special settings.
# Run all tests (builds image if needed)
./scripts/test-e2e-docker.sh
# Run specific test
./scripts/test-e2e-docker.sh 04_parallel
# Run test multiple times
./scripts/test-e2e-docker.sh 04_parallel 5
# Keep container running after tests
./scripts/test-e2e-docker.sh --keep
# Force rebuild image
./scripts/test-e2e-docker.sh --rebuild
⚠️ Important: If you change Rust code (src/), you must use--rebuildto rebuild the Docker image. Test SQL file changes are picked up automatically.
Docker intentionally skips 00_requires_shared_preload.sql and connection-limit tests 44 through 46. Use ./scripts/test-e2e-local.sh for the full phased SQL E2E coverage.
Investigation mode (--keep):
# Run tests, keep container running
./scripts/test-e2e-docker.sh --keep
# Connect to database
docker exec -it pg_durable_e2e psql -U postgres
# View logs
docker logs -f pg_durable_e2e
# When done, stop container
./scripts/pg-stop.sh --dockerTwo standalone scripts cover background-worker behaviour that the SQL suites cannot
express, because they need to control the postmaster itself. Both run in CI and both
require an exclusive local cluster — stop any server you started with --keep first.
# Graceful shutdown: SIGTERM latency and stale postmaster.pid (issue #308)
./scripts/test-shutdown.sh
# Extension epoch race: DROP/CREATE EXTENSION during worker init (issue #333)
./scripts/test-epoch-race.shtest-epoch-race.sh builds with the test-hooks cargo feature, which compiles in
PG_DURABLE_TEST_PAUSE_BEFORE_READY_MS — the pause that makes the race
reproducible. That feature must never be enabled in a shipped build; the script
enables it for its own install only.
Both scripts accept --pg-version and --verbose.
# Stop local PostgreSQL
./scripts/pg-stop.sh
# Stop Docker container
./scripts/pg-stop.sh --docker
# Stop both
./scripts/pg-stop.sh --allAfter running Docker E2E tests, deploy the same image to Azure Container Registry:
# Login to ACR (one time)
az acr login --name ${ACR_REGISTRY%%.*}
# Deploy existing image (fast - no rebuild)
./scripts/deploy-acr.sh
# Deploy with specific tag
./scripts/deploy-acr.sh --tag v0.1.0
# Force rebuild and deploy
./scripts/deploy-acr.sh --rebuildTests are in tests/e2e/sql/:
| File | Description |
|---|---|
00_setup_playground.sql |
Creates test schema and data |
01_simple_sql.sql |
Basic SQL execution |
02_sequence.sql |
Sequential execution (~>) |
03_variables.sql |
Variable substitution (|=>) |
04_parallel_join.sql |
Parallel execution (durable.join) |
05_conditional_true.sql |
Conditional (true branch) |
06_conditional_false.sql |
Conditional (false branch) |
07_sleep.sql |
Timer/delay |
08_loop_cancel.sql |
Loop and cancellation |
09_monitoring.sql |
Monitoring functions |
10_explain.sql |
Visualization |
11-16_scenario_*.sql |
User guide scenarios |
Create a new .sql file in tests/e2e/sql/:
-- Test: Description
-- Expected: What should happen
-- Start function (auto-commits, visible to background worker)
SELECT durable.start(
'SELECT 42',
'test-label'
);
-- Wait for completion
SELECT pg_sleep(2);
-- Verify result
DO $$
DECLARE
inst_status TEXT;
BEGIN
SELECT status INTO inst_status
FROM durable.instances
WHERE label = 'test-label';
IF lower(inst_status) != 'completed' THEN
RAISE EXCEPTION 'TEST FAILED: status = %', inst_status;
END IF;
RAISE NOTICE 'TEST PASSED';
END $$;
SELECT 'TEST PASSED' AS result;Important: durable.start() must be a standalone SELECT (not inside DO block) so it auto-commits and the background worker can see the instance.
The instance wasn't committed before the background worker looked for it. Make sure durable.start() is outside any DO block.
Restart with logging:
~/.pgrx/17.*/pgrx-install/bin/pg_ctl -D ~/.pgrx/data-17 -l ~/.pgrx/17.log restartRebuild and restart:
cargo pgrx install --pg-config=$(ls ~/.pgrx/17.*/pgrx-install/bin/pg_config)
~/.pgrx/17.*/pgrx-install/bin/pg_ctl -D ~/.pgrx/data-17 restartCheck Docker is running and has enough resources. Try:
docker system prune -f
./scripts/test-e2e-docker.sh --rebuild