mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-10-16 01:29:55 -07:00
Catalog: forgectrl.panel-serves, setup.ssh-until-reboot, setup.first-run-flow and logs.routing leave
Each leaves for a host proof that forgectrl's build.yml runs at the pinned 22a2cfc, and that run passed (38728407038): - forgectrl.panel-serves: tests/host_routes.sh serves the panel page bundled, with the theme and the save bar and the policy frame-src 'none', and answers /status, /cam/status and the dose-curve reads. Rows: src/ui.h. - setup.ssh-until-reboot: tests/host_routes.sh, GET and POST /system/ssh with the flag in the run directory and sshd's init a stand-in told start and stop; enable=2 refused. Rows: src/paths.h. - setup.first-run-flow: tests/host_setup.sh, the first run in the page's order: the four documents accepted at their hashes, the press step breathing teal on a scratch LED tree, the press taken as the acceptance, the account and its cookie, the gate's reason after each form step, the run completed. Rows: src/advisories.*, src/button.*, src/led.*, src/hooks.h and the four first-run documents, one row each (docs/advisories/extensions.md stays with exthost.service); src/sheetid.* to tests/sheetid_test.c, the golden ids, because host_setup.sh does not read the sheet id. - logs.routing: tests/fflog_e2e.sh, the image's rsyslog.conf and the rendered rules, each logger in its own file at its level, a stray tag in system/, the kern facility in kernel/. Rows: src/fflog.*. logs.py held logs.routing alone and goes with its import. The five camera tests no longer require forgectrl.panel-serves. test_setup_suite.py keeps setup.account-login and setup.machine-name in its ids; the cases that described setup.first-run-flow (takeover, fixture, covers) go, with the cases of the helpers that left with the two tests (breathes_teal, first_run_record, sshd_policy). test_manifest's behavioral-path case runs the report with no host-tested rows: the real table now names the first-run documents, and the case is about the allowlist. exthost.motion-job stays. It is the only catalog test that grants motion.job and posts /v0/motion/job, the path that reads machine_host_token() on the default token file, and it stays the bench proof of that path until an image carries forgeext's token-file change. src/jobpost.* stays in its covers, with no row. Fingerprints: every test in forgectrl.py, setup.py and camera.py moves with the module text. The next image cannot inherit a campaign. Proof: the coverage lint over the tree manifest from the pins finds 0 uncovered paths and 0 host-tested row problems (49 tests); pyflakes on the touched files is clean; forgetest's unit suite under Linux passes.
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
|
||||
"""The setup.* suite on the host: the registration (ids, kinds, the
|
||||
takeover tests, the operator tests' hands), the record builders, the
|
||||
machine's name, the cookie parsing, the LED cue, and the settle rule
|
||||
for a gated supervisor."""
|
||||
machine's name, the cookie parsing, and the settle rule for a gated
|
||||
supervisor."""
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
@@ -19,9 +19,7 @@ import helpers # noqa: E402
|
||||
from forgetest import baseline, catalog # noqa: E402
|
||||
from forgetest.suite import setup # noqa: E402
|
||||
|
||||
IDS = ("setup.account-login",
|
||||
"setup.ssh-until-reboot", "setup.machine-name", "setup.first-run-flow")
|
||||
OPERATOR = ("setup.first-run-flow",)
|
||||
IDS = ("setup.account-login", "setup.machine-name")
|
||||
|
||||
|
||||
class RegistrationTests(unittest.TestCase):
|
||||
@@ -31,14 +29,8 @@ class RegistrationTests(unittest.TestCase):
|
||||
def test_every_test_is_registered_with_its_kind(self):
|
||||
kinds = {tid: self.reg[tid].kind for tid in IDS if tid in self.reg}
|
||||
self.assertEqual(sorted(kinds), sorted(IDS))
|
||||
for tid in OPERATOR:
|
||||
self.assertEqual(kinds[tid], "operator", tid)
|
||||
for tid in IDS:
|
||||
if tid not in OPERATOR:
|
||||
self.assertEqual(kinds[tid], "auto", tid)
|
||||
|
||||
def test_the_record_swapping_tests_are_takeovers(self):
|
||||
self.assertEqual(self.reg["setup.first-run-flow"].hardware, "takeover")
|
||||
self.assertEqual(kinds[tid], "auto", tid)
|
||||
|
||||
def test_recommended_reads_the_status_document(self):
|
||||
w = {"recommended": [{"id": "laser.floor", "reason": "the tube was replaced"},
|
||||
@@ -60,18 +52,6 @@ class RegistrationTests(unittest.TestCase):
|
||||
from forgetest.suite import setup_dark
|
||||
self.assertIs(reg["setup.check-airflow"].precheck, setup_dark.intakes_counted)
|
||||
|
||||
def test_the_first_run_flow_runs_unattended_with_the_fixture(self):
|
||||
flow = self.reg["setup.first-run-flow"]
|
||||
self.assertEqual(list(flow.actions), ["button"])
|
||||
self.assertFalse(flow.hands)
|
||||
self.assertTrue(flow.fixture_runnable(("button", "lid", "interlock")))
|
||||
|
||||
def test_the_first_run_flow_covers_the_backend(self):
|
||||
flow = set(self.reg["setup.first-run-flow"].covers)
|
||||
for want in (("forgectrl", "src/wiz.*"), ("forgectrl", "src/setup.*"), ("forgectrl", "src/users.*"),
|
||||
("forgectrl", "src/button.*"), ("forgectrl", "src/led.*"), ("forgectrl", "src/advisories.*")):
|
||||
self.assertIn(want, flow, want)
|
||||
|
||||
def test_the_only_attended_tests_need_a_workstation_or_a_scrap(self):
|
||||
# With the bench actuator up, two setup tests keep a person: the
|
||||
# print from the Glowforge app, and the focus burn on a fresh
|
||||
@@ -240,16 +220,6 @@ class SmallHelpersTests(unittest.TestCase):
|
||||
self.assertIsNone(setup.session_from_cookie("ffsid=; Path=/; Max-Age=0"))
|
||||
self.assertIsNone(setup.session_from_cookie(""))
|
||||
|
||||
def test_the_teal_breathe_cue(self):
|
||||
self.assertTrue(setup.breathes_teal({"target": [0, 180, 200], "pulse_on": [0, 1400, 1400],
|
||||
"pulse_off": [0, 1400, 1400]}))
|
||||
self.assertFalse(setup.breathes_teal({"target": [0, 255, 40], "pulse_on": [0, 0, 0],
|
||||
"pulse_off": [0, 0, 0]})) # solid green
|
||||
self.assertFalse(setup.breathes_teal({"target": [200, 200, 200], "pulse_on": [1800, 1800, 1800],
|
||||
"pulse_off": [1800] * 3})) # white
|
||||
self.assertFalse(setup.breathes_teal({"target": [None, None, None], "pulse_on": [None] * 3}))
|
||||
self.assertFalse(setup.breathes_teal({}))
|
||||
|
||||
def test_decode(self):
|
||||
self.assertEqual(setup.decode(b'{"a": 1}'), {"a": 1})
|
||||
self.assertEqual(setup.decode(b"cloud mode is not enabled"), "cloud mode is not enabled")
|
||||
@@ -276,65 +246,5 @@ class GatedSettleTests(unittest.TestCase):
|
||||
self.assertTrue(any("controller=gated" in ln for ln in lines))
|
||||
|
||||
|
||||
class FirstRunSeedTests(unittest.TestCase):
|
||||
"""The record the first-run tests install: a first run behind the
|
||||
checks and the burns."""
|
||||
|
||||
STATUS = {"wizards": [{"id": "advisories", "version": 1, "class": "form"},
|
||||
{"id": "account", "version": 1, "class": "form"},
|
||||
{"id": "cloud", "version": 1, "class": "form"},
|
||||
{"id": "switches", "version": 1, "class": "dark"},
|
||||
{"id": "motion", "version": 2, "class": "dark"},
|
||||
{"id": "laser.focus", "version": 1, "class": "live"}]}
|
||||
|
||||
def test_no_consent_no_account_not_complete_and_every_check_done(self):
|
||||
base = {"created": "2026-09-01T00:00:00Z", "completed": "2026-09-02T00:00:00Z",
|
||||
"advisories": {"safety-and-risk": {"hash": "x"}}, "acceptance": {"pressed_at": "t"},
|
||||
"account": {"name": "scott", "uid": 1000}, "flags": {"flow_thin": True},
|
||||
"wizards": {"advisories": {"version": 1}, "switches": {"version": 1, "result": {"lid": True}}}}
|
||||
rec = setup.first_run_record(self.STATUS, base)
|
||||
self.assertNotIn("completed", rec)
|
||||
self.assertNotIn("acceptance", rec)
|
||||
self.assertNotIn("account", rec)
|
||||
self.assertEqual(rec["advisories"], {})
|
||||
self.assertEqual(rec["created"], "2026-09-01T00:00:00Z")
|
||||
self.assertEqual(rec["flags"], {"flow_thin": True})
|
||||
self.assertEqual(sorted(rec["wizards"]), ["laser.focus", "motion", "switches"])
|
||||
self.assertEqual(rec["wizards"]["switches"]["result"], {"lid": True}) # kept from the base
|
||||
self.assertEqual(rec["wizards"]["motion"]["version"], 2) # written at the catalog version
|
||||
|
||||
def test_without_a_base_record(self):
|
||||
rec = setup.first_run_record(self.STATUS, None)
|
||||
self.assertEqual(sorted(rec["wizards"]), ["laser.focus", "motion", "switches"])
|
||||
self.assertEqual(rec["wizards"]["laser.focus"]["version"], 1)
|
||||
|
||||
|
||||
class SshdPolicyTests(unittest.TestCase):
|
||||
def test_the_three_keys_out_of_sshd_t(self):
|
||||
from forgetest import hw
|
||||
calls = []
|
||||
|
||||
def fake_run(cmd, timeout=60):
|
||||
calls.append(cmd)
|
||||
return 0, "port 22\npermitrootlogin no\npasswordauthentication yes\npermitemptypasswords no\nx11forwarding no\n"
|
||||
real = hw.run
|
||||
hw.run = fake_run
|
||||
try:
|
||||
self.assertEqual(setup.sshd_policy(), {"permitrootlogin": "no", "passwordauthentication": "yes",
|
||||
"permitemptypasswords": "no"})
|
||||
finally:
|
||||
hw.run = real
|
||||
self.assertEqual(calls, [["/usr/sbin/sshd", "-T"]])
|
||||
|
||||
def test_a_failing_sshd_reports_the_error(self):
|
||||
from forgetest import hw
|
||||
real = hw.run
|
||||
hw.run = lambda cmd, timeout=60: (1, "sshd: no hostkeys available")
|
||||
try:
|
||||
self.assertEqual(setup.sshd_policy(), {"error": "sshd: no hostkeys available"})
|
||||
finally:
|
||||
hw.run = real
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user