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.
This commit is contained in:
ScottW514
2026-10-13 20:29:25 -04:00
parent 8536ae7076
commit 520d62ac05
16 changed files with 78 additions and 2848 deletions
+3 -37
View File
@@ -9,10 +9,9 @@ The installer runs once per machine, on factory firmware, over whatever
network the owner has. These tests run its own functions under sh with a
scripted curl in front of them: a transfer that fails resumes and is
tried again, the failures that waiting cannot fix end the tries at once,
and every step leaves a line in the install log in the log tree's own
format."""
the reason an install stopped is in the install log, and a log that cannot
be written never fails the install."""
import os
import re
import shutil
import stat
import subprocess
@@ -25,10 +24,6 @@ REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)
SCRIPT = os.path.join(REPO, "scripts", "install-forgefirm.sh")
MARK = "# The install log, before anything can fail."
# The log tree's line format (forgetest/suite/logs.py keeps the same one).
LINE_RE = re.compile(r"^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?[+-]\d\d:\d\d install\[\d+\] "
r"(EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG) .+$")
# A curl that plays a script: each call takes the next "rc http bytes"
# line of $CURL_PLAN, appends that many bytes to the --output file the way
# a resumed transfer does, prints the HTTP code as -w '%{http_code}'
@@ -149,24 +144,11 @@ class InstallerTests(unittest.TestCase):
self.assertEqual(len(calls), 3)
self.assertEqual(os.path.getsize(self.fw), 5000) # not 9000: the stale part went
def test_a_tls_failure_names_the_clock(self):
out, _, _ = self.download(["60 000 0"] * 5)
self.assertRegex(out, r"TLS handshake failed \(a wrong clock does this: \d{4}-\d\d-\d\d")
def test_every_log_line_is_in_the_tree_format(self):
self.download(["7 000 0", "0 200 10"])
self.run_sh('log NOTICE "operator declined to continue; no changes made"')
lines = self.log_lines()
self.assertGreater(len(lines), 5)
for line in lines:
self.assertRegex(line, LINE_RE)
def test_die_leaves_the_reason_in_the_log(self):
r = self.run_sh('die "archiving slot 1 failed"; echo not-reached')
self.assertEqual(r.returncode, 1)
self.assertNotIn("not-reached", r.stdout)
self.assertTrue(any(" ERR install failed: archiving slot 1 failed" in line
for line in self.log_lines()))
self.assertTrue(any("archiving slot 1 failed" in line for line in self.log_lines()))
def test_no_writable_log_never_fails_the_install(self):
r = self.run_sh('LOG_OK=""; log INFO "x"; LOG_OK=yes; LOG_FILE=/nonexistent/dir/x.log; '
@@ -174,21 +156,5 @@ class InstallerTests(unittest.TestCase):
self.assertIn("still-running rc=0", r.stdout)
class InstallerShapeTests(unittest.TestCase):
"""What holds on any host, with no shell to run."""
def test_the_log_lives_in_the_tree_the_export_carries(self):
head = functions()
self.assertIn('LOG_DIR="/data/log/forgefirm/install"', head)
self.assertIn('LOG_FILE="$LOG_DIR/install.log"', head)
def test_the_download_is_the_retrying_one(self):
with open(SCRIPT, encoding="utf-8") as f:
text = f.read()
body = text.partition(MARK)[2]
self.assertIn("download_fw", body)
self.assertNotRegex(body, r"(?m)^\s*curl ") # no bare curl past the functions
if __name__ == "__main__":
unittest.main()