test(browser): keep the slow-reset summary on a coarse clock

On Windows the report timer can fire a few milliseconds short of the
threshold, and the summary was then dropped. A reset that was reported
now always gets its summary. The server test uses the plain reset, which
the Windows jobs can seed, and puts the server stderr in its failure
messages.
This commit is contained in:
Vito Sansevero
2026-10-23 01:20:10 -07:00
parent 0e3cdeeea8
commit 954369add9
2 changed files with 12 additions and 5 deletions
+5 -1
View File
@@ -61,6 +61,7 @@ class ResetWatch:
self._start = time.monotonic()
self._calls: list[str] = []
self._calls_lock = threading.Lock()
self._stalled = threading.Event()
self._timer = threading.Timer(threshold, self._report_stall)
self._timer.daemon = True
self._timer.name = "pm-slow-reset-watch"
@@ -81,13 +82,16 @@ class ResetWatch:
def finish(self, outcome: str) -> None:
self._timer.cancel()
elapsed = self.elapsed()
if elapsed < self.threshold:
# A coarse clock (Windows) can fire the timer just short of the
# threshold; a reset that was reported always gets its summary.
if elapsed < self.threshold and not self._stalled.is_set():
return
with self._calls_lock:
calls = list(self._calls)
self._write([f"{self.label} {outcome} after {elapsed:.3f}s", *calls])
def _report_stall(self) -> None:
self._stalled.set()
lines = [f"{self.label} still running after {self.elapsed():.3f}s"]
try:
lines.extend(self._describe())
+7 -4
View File
@@ -153,7 +153,7 @@ class TestSlowResetOnTheServer(unittest.TestCase):
def reset(self) -> tuple[int, float]:
request = urllib.request.Request(
self.base + "/__test__/reset",
data=b'{"chronological_history": true}',
data=b"{}",
headers={"Content-Type": "application/json"},
method="POST",
)
@@ -168,7 +168,7 @@ class TestSlowResetOnTheServer(unittest.TestCase):
return self.stderr.read().decode("utf-8", "replace")
def test_a_reset_held_behind_a_write_lock_names_the_wait_and_ends_with_it(self):
self.assertEqual(self.reset()[0], 200)
self.assertEqual(self.reset()[0], 200, self.server_stderr())
self.assertNotIn(REPORT_PREFIX, self.server_stderr())
held = threading.Event()
@@ -201,6 +201,7 @@ class TestSlowResetOnTheServer(unittest.TestCase):
time.sleep(PROBE_INTERVAL_SECONDS)
resetting.join()
lock.join()
self.assertEqual(len(outcome), 1, self.server_stderr())
[(status, elapsed)] = outcome
self.assertLess(slowest, RESPONSIVE_SECONDS)
@@ -220,10 +221,12 @@ class TestSlowResetOnTheServer(unittest.TestCase):
self.assertRegex(
text, r"kernel: asyncio_\d+ \(0x[0-9a-f]{16}\) state \w, waiting in "
)
self.assertIn("in seed_workspace_visual", text)
# The plain reset's seed() waits on its first DELETE.
self.assertRegex(text, r"line \d+ in seed\n")
self.assertIn("POST /__test__/reset answered 200 after", text)
self.assertRegex(
text, r"executor call .*reset.*: queued \d+\.\d+s, ran \d+\.\d+s"
text,
r"executor call create_app.<locals>.seed: queued \d+\.\d+s, ran \d+\.\d+s",
)