Files
forgefirm/forgetest/tests/test_cooling_suite.py
T
ScottW514 520d62ac05 forgetest tests: the confirmed trims of the tool's own unit tests
The cases that tested a mock, a timer, a wording or a table, or that
replayed a judgment a host test already holds, leave forgetest/tests.
What catches a false PASS, keeps the bench safe, or guards the gate
stays.

- test_baseline: the fake sysfs tree is a mixin with no test_ methods,
  so ExtensionFreeTests and BaselineModeTests no longer re-run
  BaselineTests' 25 cases (133 runs, now 45). CoolPublishTests, the
  lamp-fade cases and TransientNotLeftoverTests go; PositionDeadbandTests
  keeps a reading past the band and an unreadable reading, both never
  excused. Both latch-relock cases stay.
- test_fixture: MdnsTests, the three timing cases, the probe's log
  wording, and nine prompt-routing variants go. A live test never runs
  unattended, the arm-press opt-in, the short-press edge, the presence
  press handing over the arm press, and the arm notice dropping at the
  press stay (35 cases, now 21).
- test_cloud_suite: three false-PASS guards stay: the latch open at a
  dark print's button, a lid stop that is not edge-driven, the kernel
  refusing the resume. The guards for the latch unlocking in the hold
  and a paused print resuming left with their catalog tests in 6a434bb.
  The rest go, with the harness pieces and the hunt-lid fixture only
  they read (41 cases, now 3).
- test_cooling_suite: GateOffTests, CriticalTierTests, FanGateTests and
  FansQuietTests go with their harness; the flow verdict's log reads
  stay: only the text after the offset, never an older verdict before it
  (the flow-under-load false-PASS guard), a rotated log read whole.
- test_queue: RunClockTests and three ordering cases go, and refusals
  are judged by a reason given, not its words; both live
  acknowledgment cases stay.
- test_takeover_position: the six cases that judge the head and move
  nothing stay.
- test_camera_home_return: the five cases where the head must not move
  stay, and so do the three that check the hand-back jog's direction and
  distance (homed, unhomed with the counters not counted twice, after
  cloud mode): a wrong sign or a double count drives the head into the
  gantry stops (15 cases, now 8).
- test_server: the keep-alive and ETag cases, the takeover and scope
  half of the bench case, and the page's self-contained asserts
  (test_page.py's) go.
- test_operator: the wording cases, the fixture case (test_fixture.py's)
  and JournalTests go.
- test_mode: the supervisor timeout table goes.
- test_takeover_client: the listener, the offline service back, the
  online client without the hunt, and GRBL under no marker stay.
- test_responsiveness: PageTests and ImplementationCostTests go; the
  log cache keeps appends, a partial line, a replaced file and a fresh
  list, and the fingerprint cache a changed manifest and one with no
  content hash.
- test_bench_registry: GfbenchTests and two description and argument
  pins go.
- test_installer: the log-format and TLS-wording cases and
  InstallerShapeTests go; the die case checks the reason is in the log,
  not its format.
- test_image: KernelIdentTests and the registration pin go.

Each file's __main__ guard now ends the file, and the docstrings say what
each still proves.

Proof: each of the fifteen files passes under Linux as forgetest-ci
discovers it, and pyflakes reports nothing new in them.

Acceptance: none; test-only.
2026-10-13 20:29:25 -04:00

65 lines
2.7 KiB
Python

# Copyright 2026 514 LLC d/b/a OpenGlow
# Written by Scott Wiederhold
# https://community.openglow.org
# SPDX-License-Identifier: MIT
"""cooling.flow-under-load reads the engine's flow verdict from what the
forgectrl log gained since the job began: only the text after the offset,
never an older verdict before it, and the whole of a log rotated under
the test."""
import os
import shutil
import tempfile
import unittest
from forgetest.suite import cooling
class FlowVerdictLogTests(unittest.TestCase):
"""cooling.flow-under-load finds the engine's verdict in what the log
gained since the job began, not in a count over a tail of fixed length:
there a new verdict line comes in at the bottom as an old one leaves at
the top, the count does not move, and a check that verified reads as
one that never judged."""
VERDICT = ("2026-09-19T21:37:46.869674+00:00 forgectrl[2796] INFO cool: coolant flow verified "
"(heater rise 11.5 C, dT 9.5 C; laser 1.6 off 13.1)\n")
OLD = ("2026-09-19T21:17:27.200840+00:00 forgectrl[965] INFO cool: coolant flow verified "
"(heater rise 9.5 C, dT 8.7 C)\n")
def setUp(self):
self.dir = tempfile.mkdtemp(prefix="flowlog.")
self.addCleanup(shutil.rmtree, self.dir, ignore_errors=True)
self.path = os.path.join(self.dir, "forgectrl.log")
def write(self, text, mode="w"):
with open(self.path, mode, newline="\n") as f:
f.write(text)
def test_only_the_text_after_the_offset_comes_back(self):
self.write(self.OLD + "filler\n" * 400)
off = os.path.getsize(self.path)
self.assertEqual(cooling._log_since(self.path, off), "")
self.write(self.VERDICT, mode="a")
text = cooling._log_since(self.path, off)
self.assertEqual(text, self.VERDICT)
m = cooling._load_verdict_rx().search(text)
self.assertEqual(m.group(1), "coolant flow verified")
self.assertEqual((m.group(2), m.group(5)), ("11.5", "1.6"))
def test_an_old_verdict_before_the_offset_is_not_the_new_one(self):
self.write(self.OLD)
off = os.path.getsize(self.path)
self.write("2026-09-19T21:36:40+00:00 forgectrl[2796] INFO cool: crash watch armed\n", mode="a")
self.assertIsNone(cooling._load_verdict_rx().search(cooling._log_since(self.path, off)))
def test_a_log_rotated_under_the_test_is_read_whole(self):
self.write(self.OLD + "filler\n" * 400)
off = os.path.getsize(self.path)
self.write(self.VERDICT) # the rotation: a new, shorter file
self.assertEqual(cooling._log_since(self.path, off), self.VERDICT)
if __name__ == "__main__":
unittest.main()