forgectrl f8ddb17 puts the lens frame in one place and writes the focus window before the card's controller starts, after two commissioning cards ended in ALARM:2 on a Z the wizard sent from one source while the controller's Z limit stood on another. The acceptance run had passed only because the bench's settings already held the stops from an earlier focus run, so the run is now a fresh machine's. commission.sheet clears the three lens settings inside its Restore before the cards, checks that the frame runs in the fallback window, and, after the focus card, that the settings hold the window the ladder ran in (the stops found or the fallback), that every ladder height lies in that window's reach, and that the program served now agrees with /status. Every served program's Z is checked against the reach /status reports before the card starts, so a stray Z fails the test with nothing burned. The test covers src/lens.*. The host mock in tests/test_commission_sheet.py mirrors the daemon (the /status lens block from the settings, the ladder served from the settings, the window written at the focus start); two regression tests reproduce the defects: a focus result naming a window the settings do not hold, and a served program with a Z beyond the reach. 10/10 green. scripts/bench/z_envelope_test.py, the grblHAL CI harness, adds the referenced-lens cases: with forgectrl's marker and the shared settings, the fallback window and a 14/20 window run to the ends of their reach and two half-steps past either end alarms, and a count of 41 falls back on its side alone. Passed on the null-sink build. The bench page's description of the harness follows. The forgectrl pin moves to f8ddb17 (0.1.18); every test covering forgectrl re-runs.
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.