Development and verification
Prerequisites
The declared minimum is Perl 5.36.0. The full development and FitNesse
acceptance suites have been exercised locally with Perl 5.40.1. CI targets
the Perl 5.36 release line with development tests, a build and installation,
and installed-service checks on Linux and macOS.
Runtime use requires HTML::TreeBuilder. Development tests use the additional
requirements listed under test dependencies in Build.PL and cpanfile.
FitNesse acceptance gates require the pinned FitNesse v20251025 JAR at
/opt/fitnesse/fitnesse.jar or at the path in FITNESSE_JAR.
Test commands
Run the Perl suite and documentation checks with:
bin/test-dev
bin/check-docs
Build, install, and exercise the release archive with:
bin/test-install
That gate builds from MANIFEST, installs into a temporary prefix, runs
the installed executable from outside the checkout with a fixture copied
to a separate directory, checks pipe and TCP sessions, and tests the
installed process through FitNesse using the pinned JAR.
Run all acceptance combinations and reports with:
bin/test-fitnesse --transport pipe
bin/test-fitnesse --transport tcp
bin/test-fitnesse-suite --transport pipe
bin/test-fitnesse-suite --transport tcp
bin/report-fitnesse-coverage
bin/report-fitnesse-matrix
The separate business-oriented installed-distribution example is checked by:
bin/test-example-order-management
bin/test-example-order-management --transport tcp
It runs nine example pages, verifies their exact results, and performs wiki-only authoring exercises in an isolated temporary FitNesse root. The pipe run is part of CI; the TCP form is available for local transport checks.
The isolated runner executes its deliberate 50-page inventory one page at a time. The native runner executes FitNesse's 93-page suite responder. Each runner validates exact per-page counts and confirms the selected Perl backend. Pipe and TCP have distinct reviewed expectations for startup tests because they establish different process preconditions.
Results and failures
Acceptance logs, raw responses, and per-transport result files are written
to the ignored .runtime/ directory. A missing result, child-process
failure, wrong backend, count change, or inventory change fails the gate
and requires investigation before any baseline change.
GitHub Actions runs the Perl tests and pipe acceptance gates, the native
pipe suite, both TCP acceptance gates, and coverage/matrix reports. It also
runs bin/test-install so the packaged executable is exercised from an
independent prefix. Report CI conclusions only after inspecting the
actual workflow run.
The exact 50-page and 93-page populations, their intersection, and the different evidence each mode provides are documented in acceptance coverage.
The main GitHub Actions workflow runs these platform checks:
| Platform | Coverage | |---|---| | Linux | Comprehensive development, documentation, installation, and FitNesse acceptance tests | | Linux Perl 5.36 | Minimum-version development tests, installation, and installed pipe smoke test | | macOS 15 | Native development tests and independent installation with pipe, TCP, and FitNesse smoke tests | | Windows Server 2025 / Strawberry Perl 5.36 | Focused tests, pipe/TCP smoke tests, and independent installation with both transports |
The Windows job runs automatically with the main workflow on pushes and pull requests. Windows pipe and single-client TCP behavior are smoke-tested; the Windows concurrency test and full FitNesse acceptance matrix are not validated. These checks do not replace the comprehensive Linux acceptance gates or the native macOS checks.
Windows does not support Perl select polling on ordinary child-process
pipes. The full t/pipe-transport.t integration test uses IO::Select to
drain IPC::Open3 pipes and remains part of Linux/macOS development testing.
For cross-platform transport smoke checks, t/portable-transport-smoke.t uses
IPC::Run with a complete prebuilt pipe request and bounded execution, then
uses IO::Select only for a single TCP socket session. It checks the v0.5
greeting, exact framed fixture results, bye, child exit, and module paths.
The harness requires test-only IPC::Run 20260322.0 or later, which provides
the process-state API used by the TCP cleanup path. The Windows job preflights
the loaded version and required methods, then uses this Perl test for checkout
and installed pipe/TCP smokes.
PowerShell only orchestrates the workflow; protocol framing is tested in Perl.
The installed-distribution check uses the installed runner and modules plus an
external fixture; it does not establish that FitNesse itself launches Perl on
Windows. The Windows workflow skips t/server-concurrency.t explicitly:
that test starts its listener with fork(), redirects child output to
/dev/null, then sends TERM and performs a blocking waitpid. Strawberry
Perl emulates fork() with pseudo-processes. The
Perl 5.36 perlfork documentation
warns that TERM may not be delivered while a pseudo-process blocks in I/O;
the caller must avoid an unbounded wait in that situation. This test remains
active on Linux and macOS. The Windows transport smoke covers one TCP client;
concurrent TCP clients remain unvalidated there. The TCP listener retains
SO_REUSEADDR on Linux and macOS but disables it on Windows, where Winsock
allows a reuse-enabled socket to bind an occupied endpoint. This is not the
stronger SO_EXCLUSIVEADDRUSE setting; it only avoids the permissive reuse
option that caused the occupied-port regression.