Files
forgefirm/forgetest
ScottW514 83686fc712 forgectrl.tls-records: a window another client connected in is measured again
The test judges each connection by the kernel's TLS counters and the
crypto engine's interrupt, and both are the machine's, not the
connection's. On image 20260928175056's campaign the test before it
restarted forgectrl, the operator's panel (six HTTPS connections from
the bench PC) reconnected in the same second as aes-1.3#1, and the
kernel counted 7 sessions each way where the test wanted exactly 1; the
connection itself chose AES-128-GCM, carried the page byte for byte, and
counted no decrypt error. _fetch now also reads the machine's accepted
TCP connections (PassiveOpens, shared by both families); a case whose
window saw any connection but its own is measured again, up to 30 times
after a pause drawn from 0.1 to 0.9 s (so no steady poller, such as a
page polling this suite once a second, stays in step with it), and
fails if every window was contested. The judgments are unchanged: exactly one session each way for a cipher the kernel seals,
none for CBC, the engine's interrupt counting the AES records and not
the ChaCha20 ones.

Proof: pyflakes clean. On the bench reference, image 20260928175056,
with an openssl client connecting to :443 every 0.25 s for the first
6 s of the run and the drill polling this suite once a second: the
image's test fails (desktop-1.2 counted 2 sessions each way), the fixed
test passes with contested windows measured again (at most 4 attempts a
case), and passes again without the extra clients (at most 4).

Acceptance: the change is forgectrl.tls-records itself; tlsrec.py holds
no other test, so no other fingerprint moves.
2026-09-28 14:23:04 -04:00
..
2026-09-18 12:14:22 -04:00
2026-09-18 12:14:22 -04:00

forgetest - the ForgeFIRM release acceptance tool

The daemon behind http://<machine>:8090/ on the dev image: runs the acceptance catalog against the machine, keeps the append-only result log, decides which results still apply to the image that is running, exports the release artifact scripts/release.sh gates on, and serves the bench diagnostics page. The contract - catalog, campaigns, fingerprints, inheritance, the gate, the coverage rule - is the Acceptance page of the documentation site.

Run the host tests

cd forgetest
python3 -m unittest discover -s tests -v

Run the daemon on a workstation (against a mock or a manifest file)

FORGETEST_DATA=/tmp/ft FORGETEST_MANIFEST=../tree-manifest.json \
FORGECTRL_URL=http://<machine> python3 -m forgetest --port 8090

scripts/manifest-from-tree.py produces tree-manifest.json from the recipe pins; the coverage lint is python3 -m forgetest.coverage --manifest ....

Environment

Variable Default Purpose
FORGETEST_DATA /data/forgetest results.jsonl, bench.jsonl, token, export/
FORGETEST_MANIFEST /etc/forgefirm-manifest.json the image manifest
FORGETEST_PORT, FORGETEST_HOST 8090, 0.0.0.0 listener
FORGETEST_BENCH_DIR /usr/share/forgetest/bench the installed bench scripts
FORGETEST_BENCH_DATA <FORGETEST_DATA>/bench passed to bench tools: where they keep their data files (with GF_HOST=127.0.0.1 and the panel token in GF_TOKEN)
FORGETEST_MARKER /run/forgetest.active takeover marker
FORGECTRL_URL, FORGECTRL_TOKEN_FILE http://127.0.0.1, /data/forgefirm/panel.token forgectrl client (HTTP; the token authorizes writes from the board)
FORGECTRL_TLS_URL https://127.0.0.1 forgectrl over HTTPS (self-signed, unverified), for the login test
GF_SYSFS_ROOT /sys/glowforge/ kernel module sysfs
GRBL_HOST, GRBL_PORT 127.0.0.1, 23 Grbl TCP

Adding a test

Register it in the subsystem module under forgetest/suite/ with @test(...): id subsystem.name, kind, hardware, mode (the controller mode the test needs; the runner switches to it first), covers, requires, always, steps. The body gets a Context (log, check, fail, prompt, confirm, instruct, sleep, evidence, forgectrl, sysfs, grbl, takeover). Return normally for PASS, raise runner.Failed for FAIL. Then run the unit tests and the coverage lint.