See: story index | Dev docs: dev/testing
The transport infrastructure touches low-level POSIX (fork, socketpair, mmap, /proc), libcurl WebDAV protocol, and wxWidgets UI. Tests were written at each layer to keep the blast radius of a regression small. All four suites are independent of the full cmake build; they compile with a single g++ command and produce standalone binaries. The Makefile (Makefile.transport-tests) drives them.
File: src/test/TransportTest.cpp → compiled into coretest binary
The existing gtest suite that runs in CI. Tests cover pws_is_transport_url, extract_scheme, and the file: plugin end-to-end.
Run: cd build && ctest -R Coretests --output-on-failure
File: src/test/transport_standalone_test.cpp
No network required. Covers plugin loading for both file and https schemes, pws_is_transport_url / extract_scheme edge cases, file: plugin round-trip (fetch, store, exists), cache path generation.
File: src/test/transport_webdav_test.cpp — 11 sections, 59 assertions.
Tests the full plugin API against a real WebDAV server. Skips (exit 77) if PWSAFE_WEBDAV_TEST_URL is unset.
• §7 — store while locked: the If: (<token>) header regression. The server returns 423 if the header is missing; this was the original data-loss bug.
• §11 — lock contention: EBUSY when another client holds the lock; failed lock must not populate token_out or affect the internal map.
File: src/test/transport_lock_lifecycle_test.cpp — 6 sections (A–F), 49 assertions (15 offline, 34 live).
Links transport.cpp and transport_lockd.cpp directly — tests the full daemon IPC.
• §A — registry unit tests: pws_lock_register/has_lock/unregister in isolation, no network.
• §C — crash simulation: registry cleared without plugin unlock → server lock still held; subsequent lock() returns EBUSY.
• §D — SafeUnlockFile simulation: the exact guard (if IsLockedFile → UnlockFile) that was broken before the fix.
• §E — daemon EBUSY path: lock contention propagated correctly through the pipe round-trip.
• §F — store regression: t->store() directly in parent → EBUSY (demonstrates the bug); pws_lockd_store() → 0 (demonstrates the fix).
# Offline tests only (default):
make -f Makefile.transport-tests
# All suites with a local wsgidav server (no remote dependency):
make -f Makefile.transport-tests local-live
# All suites against the remote server:
make -f Makefile.transport-tests live
Initially all live tests depended on webdav.critchley.biz — a real remote server. This is fine for manual testing but fragile for development (network outages, server downtime, DNS issues from ISP).
Added: src/test/webdav_test_server.py — takes <port> and <root_dir> args, serves with anonymous write access and DAV class 2 (locking), pre-seeds pwsafe_test.psafe3, prints READY once the port accepts connections. Uses wsgidav 4.3.3 + cheroot 11.1.2.
Added: src/test/run_local_webdav_tests.sh — starts the server in the background, polls for readiness, runs suites 2 and 3 with PWSAFE_WEBDAV_TEST_URL=http://127.0.0.1:18080, tears everything down via trap cleanup EXIT.