From a596767a9aa16cf4b584452fc0e29d05e62c780a Mon Sep 17 00:00:00 2001 From: ScottW514 Date: Thu, 15 Oct 2026 18:06:36 -0400 Subject: [PATCH] forgetest: a press the fixture could not make leaves a notice that comes down at the press press_now and arm_press hand the arm press to the operator when the bench actuator refuses it (the box is off) or when the button never lights for it within the arm wait, and put the notice up for a person. Those three fallbacks raised the notice without the watch that takes it down at the press, so the notice stood until the test's next step: the second-press hazard the watch exists for, because a press during the job pauses it. Each fallback now calls _clear_when_taken() after its notice, so the notice comes down the moment the controller takes the press, as the operator's own path does. No press, judge, or energy path changes. Proof: forgetest-ci "Unit tests" (`python -B -m unittest discover -s tests -v` in forgetest), on Ubuntu 24.04 with python 3.12: test_fixture.py's test_the_arm_notice_comes_down_when_the_press_is_taken gains the leg where the fixture cannot press: press_now's notice for a refused press, arm_press's notice for a refused press, and arm_press's notice for a button that never lit each come down within 2 s of the press. Three runs OK, the file's 21 tests OK. Negative control on a scratch copy: the leg against the runner without the three calls fails at the first press, the notice still standing. pyflakes reports no undefined name. Acceptance: every catalog test's fingerprint moves: runner.py is a shared judge, in every implementation hash (43 of 43 move). Against the campaign this series already needs, that adds no run: 850498f moved all 43 once. tests/ are in none. --- forgetest/forgetest/runner.py | 3 +++ forgetest/tests/test_fixture.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/forgetest/forgetest/runner.py b/forgetest/forgetest/runner.py index 7a76787..27cd4fe 100644 --- a/forgetest/forgetest/runner.py +++ b/forgetest/forgetest/runner.py @@ -485,6 +485,7 @@ class Context: rec["fixture_error"] = str(e) self.log("ARM press: fixture failed (%s) - asking the operator", e) self.notice(text) + self._clear_when_taken() return False rec["by"] = "fixture" self.log("ARM press by the fixture, at the machine's own press prompt") @@ -566,6 +567,7 @@ class Context: if lit is None: self.log("ARM: the button never lit within %d s - asking the operator", lit_timeout) self.notice(text) + self._clear_when_taken() return try: fixture.act("button", "press") @@ -573,6 +575,7 @@ class Context: self.log("ARM press: fixture failed (%s) - asking the operator", e) rec["fixture_error"] = str(e) self.notice(text) + self._clear_when_taken() return rec["by"] = "fixture" rec["took_s"] = round(lit, 2) diff --git a/forgetest/tests/test_fixture.py b/forgetest/tests/test_fixture.py index 0e114fb..1346057 100644 --- a/forgetest/tests/test_fixture.py +++ b/forgetest/tests/test_fixture.py @@ -594,6 +594,38 @@ class RoutingTests(unittest.TestCase): time.sleep(0.02) self.assertFalse(watching()) self.assertIsNotNone(run.notice) # the finished run's notice is left as it was + # A press the fixture could not make is asked of the operator, and + # that notice comes down at the press like any other: press_now and + # arm_press with the box refusing, and arm_press with the button + # never lit for the box. + self.stub.arm_press = True + self.stub.fail = True + run = Run("test", "r.live", "r.live") + ctx = Context(run, self.runner, self.reg["r.live"]) + + def settles(up): + deadline = time.time() + 2 + while (run.notice is not None) != up and time.time() < deadline: + time.sleep(0.02) + return (run.notice is not None) == up + lit["v"] = True # the machine waits for the press + self.assertFalse(ctx.press_now()) # the box is off: the operator is asked + self.assertIsNotNone(run.notice) + time.sleep(0.2) # lit: the arm waits for the press + lit["v"] = False # the operator's press is taken + self.assertTrue(settles(False)) + lit["v"] = True + self.assertTrue(ctx.arm_press()) # the fixture is asked, and refuses + self.assertTrue(settles(True)) + time.sleep(0.2) + lit["v"] = False + self.assertTrue(settles(False)) + self.assertTrue(ctx.arm_press(lit_timeout=0)) # the button never lit for the fixture + self.assertTrue(settles(True)) + lit["v"] = True + time.sleep(0.2) + lit["v"] = False + self.assertTrue(settles(False)) finally: runner_mod.hw.button_lit = saved