End-to-end integration tests for the RexxHTTP servlet processor. They
exercise the whole pipeline via Apache + curl: a request goes through
Apache to the wrapper, which Calls
RexxHTTP.rex, which runs a servlet; the generated response
(status, headers, body) is then verified.
These are not unit tests of the classes in isolation. The point is to catch what only shows up through the real stack — lazy headers, cookie serialisation at commit time, the error page, stdin handling — the same things that bit earlier sessions when verified any other way.
cgid and actions
modulesOn Debian/Ubuntu:
apt-get install -y apache2
a2enmod cgid actions
ooRexx is installed from the epbcn package:
curl -sO https://rexx.epbcn.com/oorexx-latest.deb
dpkg -i oorexx-latest.deb
The simplest way is the runner, which checks prerequisites, deploys the sources and fixtures, configures and starts Apache, runs the suite, then stops Apache and cleans up what it created:
rexx tests/http/RunHTTPTests.rex
Two flags are available:
--setup-only deploys everything and leaves Apache
running, but does not run the tests (it prints the manual command
instead).--no-stop runs the tests but leaves Apache running
afterwards.The runner targets Linux (including WSL): it uses
apt-get and Apache paths specific to Debian/Ubuntu, and it
uses sudo for the steps that touch /var/www
and /etc/apache2.
With Apache already set up, the suite can also be run by hand from
the tests directory:
cd tests
PATH="framework:http:$PATH" rexx http/RexxHTTP.testGroup
The tests use http://127.0.0.1 as the base URL (not
localhost, to avoid DNS/proxy surprises). Both the base URL
and the path under which the fixtures are served can be overridden from
the environment, so the runner can point the suite at whatever
deployment it set up:
REXXHTTP_TEST_BASEURL (default
http://127.0.0.1)REXXHTTP_TEST_PATH (default /test/)The runner deploys the five sources plus a one-line wrapper to
/var/www/html/RexxHTTP/, and configures Apache so that the
Action points at the wrapper, not at
RexxHTTP.rex directly:
Action RexxHTTPCGI /RexxHTTP/wrapper
The wrapper is a one-line LF Rexx script whose only job is to
Call "/var/www/html/RexxHTTP/RexxHTTP.rex". This mirrors
the production deployment and sidesteps the CRLF-shebang problem: the
sources are stored and checked out CRLF (see the repository's
.gitattributes), so the kernel cannot exec
RexxHTTP.rex directly (its #! line ends in
CR). Reached via Call from the LF wrapper, that shebang is
just an inert comment, and ooRexx reads the CRLF body fine.
The fixtures are deployed to /var/www/html/test/ with a
whitelist .htaccess: only the listed files are handled as
servlets; anything else is served statically.
The real production montage may differ in detail. When
setup.md is rewritten to the real deployment, the
VirtualHost/wrapper resources in RunHTTPTests.rex should be
aligned with it.
All fixtures are in fixtures/. Each is a small servlet
exercising one facet of the processor:
| File | Purpose |
|---|---|
hola |
Minimal hello-world servlet |
multi |
Echo GET/POST args in order, including duplicates |
qs |
Named-argument lookup (Value, Exists) |
check |
Report method, script_name, uri |
setck |
Set a plain session cookie via HTTP.Cookie |
readck |
Read cookies back from the request |
setckopts |
Cookie with Max-Age, SameSite, HttpOnly |
badck |
Inconsistent cookie (SameSite=None without Secure) |
late |
Set a header after writing body (lazy headers) |
partial |
Explicit early flush, then more body |
boom |
Deliberate runtime error (error page) |
htmltype |
Override Content-Type to text/html |
addcookie), so RexxHTTP's own error
page renders rather than a bare Apache 500.HTTPTestCase.cls extends the official ooTest
ooTestCase with:
httpGet(url [, jar]) — HTTP GET via
curl; returns a Directory with status, body,
and the raw headers block. An optional cookie-jar file
makes successive calls share cookies (real round trips).httpPost(url, data [, jar]) — HTTP
POST with a urlencoded body.assertContains /
assertNotContains — caseless body substring
checks.assertHeader(headers, name, valueSubstring, label)
— assert a response header line matches name + value substring (both
caseless).assertNoHeader(headers, name, label) —
assert no such header.The ooTest framework itself lives in ../framework/ (the
Rexx Language Association's official files, carried verbatim).
RexxHTTP.rex guards
against being run as a servlet itself (returning a 404). That guard is
not tested here: in this montage a direct request to the processor is
intercepted by the ScriptAlias and fails the CRLF-shebang exec before
ooRexx runs. Reaching the guard needs a request routed through the
wrapper whose request_uri contains the processor name, which is a
montage concern.