forgetest: a check run_check stops following at its timeout is aborted before the test fails

run_check judged its timeout with ctx.check, which raises, ahead of the
abort meant for that case, so the abort never ran: a check still
running at the end of its follow was left running behind the FAIL. For
setup.focus that is a live burn wizard. Its put-back waits 120 s for
the burn to end and then skips the controller restart, and forgectrl's
own bound on a live run (1500 s) outlasts the test's 900 s follow. The
same driver serves the setup.check-* tests,
setup.cloud-header-capture and motion.release.

The abort now goes out before the timeout is judged, and the
unreachable return after it is gone. The change only ends a check the
test started itself: it adds no energy and no motion.

Proof: tests/test_setup_dark.py, the Unit tests step of forgetest-ci.yml
(python -B -m unittest discover -s tests), 21 tests OK on Windows with
python 3.14 and on Ubuntu 24.04 with python 3.12:
test_a_check_that_does_not_end_in_time_is_aborted_before_the_test_fails
(a lens.travel check that never ends, followed for 0.2 s: Failed, and
/wiz/lens.travel/abort posted). test_setup_burns.py (24) and
test_setup_suite.py (15) pass. Negative control on a scratch copy: the
timeout judged before the abort, as it was, fails the case (only
/wiz/lens.travel/start posted). setup.focus run whole against
test_setup_burns.py's scripted daemon with a burn that never ends (the
follow cut to 0.5 s, the press prompt held open): before, Failed with no
abort, the wizard still running and the restart skipped ("the burn is
still ending"); after, Failed with laser.focus aborted, the wizard
stopped, and the controller stopped and started (200, 200). pyflakes
reports no undefined name.

Acceptance: the shared text of setup_dark.py moves the fingerprints of
its five tests (setup.check-switches, setup.check-airflow,
setup.check-motion, setup.check-lens, setup.cloud-header-capture), of
setup.focus (setup_burns.py imports it at its top level) and of
motion.release (its own function imports run_check); the other 36 do
not move (source_sha compared before and after). Against the campaign
this series already needs, that adds no run: 850498f moved all 43
once.
This commit is contained in:
ScottW514
2026-10-16 23:00:54 -04:00
parent 7b0f065a3f
commit ce73dbb052
2 changed files with 23 additions and 2 deletions
+3 -2
View File
@@ -132,10 +132,11 @@ def run_check(ctx, wid, on_prompt, timeout_s, on_poll=None):
raise
ev["elapsed_s"] = round(time.time() - t0, 1)
ev["phases"] = phases[-12:]
ctx.check(last is not None, "the %s check did not end within %d s", wid, timeout_s)
if last is None:
# A check this test stops following is aborted before the test
# fails: no check runs on behind the FAIL.
fc.post("/wiz/%s/abort" % wid)
return {}
ctx.check(last is not None, "the %s check did not end within %d s", wid, timeout_s)
ev["log"] = last.get("log", [])[-12:]
ev["error"] = last.get("error")
ev["result"] = last.get("result")
+20
View File
@@ -408,6 +408,26 @@ class LensCheckTests(ScriptedCheck):
self.assertIn(("/wiz/lens.travel/abort", {}), self.fake.posts)
self.assert_put_back()
def test_a_check_that_does_not_end_in_time_is_aborted_before_the_test_fails(self):
# The run never ends: the test stops following it at its timeout,
# aborts it, and fails, so no check runs on behind the FAIL.
from forgetest.runner import Failed
from forgetest.suite import setup_dark
real = self.fake.on_get
def on_get(path, q):
if path == "/wiz/dark":
return 200, dict(self.dark) # running until aborted
return real(path, q)
self.fake.on_get = on_get
t = catalog.load_suite()["setup.check-lens"]
ctx = Context(Run("test", t.id, t.title), None, t)
with self.assertRaises(Failed) as cm:
setup_dark.run_check(ctx, self.WID, lambda p: None, 0.2)
self.assertIn("did not end within", str(cm.exception))
self.assertIn(("/wiz/lens.travel/abort", {}), self.fake.posts)
self.assertFalse(self.dark["running"])
def test_a_controller_that_does_not_restart_fails_the_hand_back(self):
# The start refused: the controller stays stopped on the stale
# window's heels, and the run says so rather than pass.