ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
selftest_assert.py
Go to the documentation of this file.
1# SPDX-License-Identifier: MIT
2# Copyright (c) 2026 Brighton Sikarskie
3"""Shared both-direction selftest scaffolding for the ``check_*.py`` gates.
4
5Every gate in this tree is required to prove itself in both directions -- it
6must FIRE on a broken input and stay QUIET on a good one -- because a checker
7that has quietly stopped matching is this repository's dominant defect class
8and reports success forever.
9
10Four gates had grown a byte-identical copy of that scaffolding:
11``check_asm``, ``check_devcontainer``, ``check_gitignore_scope`` and
12``check_lint_coverage`` each carried the same ``_expect`` and the same
13report-and-exit tail, down to the docstring. Four copies of an assertion
14helper is four places for the reporting convention to drift, and drift in a
15selftest is invisible by construction. They share this module instead.
16
17This is deliberately not a unittest/pytest layer. The gates run as standalone
18scripts from ``scripts/git/pre-commit`` and from ``scripts/ci.sh`` with no test
19runner on PATH, and their selftest output is read by humans in a CI log.
20"""
21
22from __future__ import annotations
23
24import sys
25
26
27def expect(cond: bool, label: str, failures: list[str]) -> None:
28 """Record one selftest assertion and print its pass/fail line.
29
30 Accumulates into ``failures`` instead of raising, so one failing
31 assertion does not hide the ones after it -- the value of a
32 both-direction selftest is the whole picture, not the first breakage.
33 """
34 print(f" [{'ok' if cond else 'FAIL'}] {label}")
35 if not cond:
36 failures.append(label)
37
38
39def report(failures: list[str]) -> int:
40 """Print the closing verdict for a selftest run and return its exit code.
41
42 Returns 1 when anything failed (listing each failed assertion on stderr),
43 0 when every assertion held in both directions.
44 """
45 if failures:
46 print(f"\nSELFTEST FAILED: {len(failures)} assertion(s)", file=sys.stderr)
47 for item in failures:
48 print(f" {item}", file=sys.stderr)
49 return 1
50 print("selftest: all assertions held (both directions).")
51 return 0