# Testing — `mgf-hrb`

> One-page strategy. Links into [`docs/testing/`](docs/testing/) for the
> deep dives. Reusable as a template for sibling federation projects;
> the project-specific bits are isolated to two files (`EXECUTION.md` +
> `COVERAGE_MAP.md`).

## Why test infrastructure is a first-class artifact

`mgf-hrb` is a hardware-resource broker. Failure modes range from
"return the wrong dict shape" to "leak a lease that survives client
death." The cost of an undetected bug compounds across consumers (any
GUI / CLI / future kernel-port). The testing infrastructure is the
mechanism that converts "we intend to be reliable" into "we verify we
are" — peer to the production code, not below it.

Two reasons it lives in `mgf-hrb` rather than getting copied around:

1. **One source of truth for the test taxonomy** the federation
   reuses — see [`docs/testing/TAXONOMY.md`](docs/testing/TAXONOMY.md).
   The vocabulary (smoke / unit / functional / integration / e2e /
   use-case / property / fuzz / stress / perf / conformance /
   regression / contract) is the same one `mgf-common` standards
   reference via `TS-01..TS-06`.
2. **The infrastructure patterns** (fixture builders, marker hygiene,
   broker-spawning harness, dual-language gating) are reusable across
   any project that mixes Zig + Python — see
   [`docs/testing/INFRASTRUCTURE.md`](docs/testing/INFRASTRUCTURE.md).

## The four gates (DAILY contract)

Every PR runs four gates, each one a different test layer. No PR
merges with any gate red:

| Gate | Command | Layer | What it catches |
|---|---|---|---|
| **Lint** | `ruff check src tests` | Style, dead imports, banned patterns | Mechanical drift |
| **Types** | `mypy --strict src` | Static contracts | Type-level lies |
| **Tests (Py)** | `pytest -q --cov --cov-fail-under=80` | Unit + functional (Python) | Behavioural regressions |
| **Tests (Zig)** | `cd hrb-code && zig build test --summary all` | Unit + concurrency (Zig) | Lease / cap / wire correctness |

Two canonical runners:

* **`./scripts/gates`** — runs all four gates with unified
  pass/fail output. `--fast` skips Zig; `--keep-going` runs every
  gate regardless of failures. Used by main-branch CI; reflects
  the spec verbatim.
* **`uv run mgf-test-supervisor`** — federation test supervisor
  (consumed as a dev dep — see `pyproject.toml`). Runs pytest from
  OUTSIDE so it can detect hangs, crashes, freezes that pytest
  itself can't. Tier-aware (`--tier 0-2`), budget-aware
  (`--budget 30s`), resumable (`--resume`), with a quarantine
  layer for flaky tests. Writes structured per-test records +
  per-failure detail bundles to `.gates/last-run/`. Used by the
  pre-push hook and the PR + nightly CI jobs.

The Woodpecker workflow ([`.woodpecker.yml`](.woodpecker.yml))
runs both: `mgf-test-supervisor` for tiered tests, `scripts/gates`
for the four-contract gates on push to main.

mgf-hrb is sibling-#8 in the federation supervisor rollout
(originator of the pre-extraction code; the only repo with a real
daemon — `mgf-hrb-server`). The supervisor's
`MGF_TEST_SUPERVISOR_DAEMON_PROCESS_NAME=mgf-hrb-server` env-var
override (added in v0.1.1) keeps `daemon_state()` in failure
bundles. See `hooks/pre-push` + `tests/smoke/test_mtest_self_check.py`
for the canonical env-wiring shape.

E2E + stress + perf + use_case + conformance gates fire **on opt-in**
(markers / explicit invocations). They are run before each release
and on a nightly cycle — see [`docs/testing/EXECUTION.md`](docs/testing/EXECUTION.md)
for the full matrix.

**When a test hangs or crashes:** [`docs/testing/DIAGNOSING_HANGS.md`](docs/testing/DIAGNOSING_HANGS.md)
is the on-call playbook. Each recipe is symptom → diagnosis → fix;
no root required. With mtest, failures land as one-file bundles
at `.gates/last-run/failures/<id>.txt` — open that first.

**Federation standard:** authoritative spec lives in
[`mgf-standard/docs/standards/TESTING.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/TESTING.md)
(TS-22..TS-27, the 13-marker taxonomy at §13.11, supervisor
implementation guide at §19). CI workflow shape:
[`mgf-standard/docs/standards/WORKFLOWS.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/WORKFLOWS.md)
(WF-01..WF-12). Reference implementation:
[`mgf-test-supervisor`](https://codeberg.org/magogi-admin/mgf-test-supervisor).
The mgf-hrb-specific patterns that survived extraction
(`tests/_broker.py`, `tests/conftest.py`, the Zig-source
freshness check) carry the same shape; copy verbatim into any
future federation worker that ships a daemon binary.

## The thirteen test layers

Detail in [`TAXONOMY.md`](docs/testing/TAXONOMY.md); one-line summary
of each:

| Layer | Lives in | Marker | Default? | Purpose |
|---|---|---|---|---|
| **Unit** | `tests/unit/`, `*_test.zig` | (none) | ✅ | One function, isolated, in-memory |
| **Functional** | `tests/unit/` | (none) | ✅ | One feature end-to-end at the in-process layer |
| **Integration** | `tests/unit/` (cross-module) | (none) | ✅ | Two-plus components in one process |
| **Contract** | `tests/contract/` | `contract` | ✅ | Wire format + SDK surface pins |
| **Property** | `tests/unit/` (Python) + `*_test.zig` (Zig fuzz) | `property` | ✅ | Invariants under random / generated inputs |
| **Smoke** | `tests/smoke/` | `smoke` | ✅ | Broker boots + handshake works |
| **Concurrency** | `core_test.zig` + `test_client.py` | (none) | ✅ | Thread / process race correctness |
| **End-to-end** | `tests/e2e/` | `e2e` | opt-in | Real broker subprocess ↔ real Python SDK |
| **Use case** | `tests/use_cases/` | `use_case` | opt-in | Consumer-scenario walkthroughs (hrb-app patterns) |
| **Fuzz** | `request_test.zig` + `tests/fuzz/` | `fuzz` | opt-in | Garbage bytes / hostile inputs |
| **Stress** | `stub_usb_test.zig` + `tests/stress/` | `stress` | nightly | High load, sustained churn |
| **Performance** | `ring_test.zig` (bench) + `tests/perf/` | `perf` | nightly | Latency / throughput budgets |
| **Conformance** | `conformance.zig` + `tests/conformance/` | `conformance` | release | S1–S5 survivability + G1–G4 guarantees |

The four "release-gated" layers (e2e / stress / perf / conformance) are
NOT redundant — each catches a different failure class:

* **e2e** catches wire-format drift.
* **stress** catches resource-exhaustion regressions.
* **perf** catches O(n²) sneaking in.
* **conformance** catches design-promise violations.

## Where to start as a contributor

Read in this order:

1. [`TAXONOMY.md`](docs/testing/TAXONOMY.md) — what each test type IS,
   five minutes per category.
2. [`RECIPES.md`](docs/testing/RECIPES.md) — code-level patterns to
   copy-paste when writing a new test.
3. [`INFRASTRUCTURE.md`](docs/testing/INFRASTRUCTURE.md) — the fixtures,
   helpers, and conventions you compose with.
4. [`EXECUTION.md`](docs/testing/EXECUTION.md) — every command to run
   tests locally, in CI, before release.
5. [`COVERAGE_MAP.md`](docs/testing/COVERAGE_MAP.md) — the current
   state of the union + gap roadmap. Pick from the "open" rows when
   looking for a contribution.

## Reuse across the federation

Sibling projects can adopt this infrastructure in three steps:

1. Copy `docs/testing/TAXONOMY.md` + `RECIPES.md` verbatim — they are
   federation-generic.
2. Copy `INFRASTRUCTURE.md` and replace the `mgf-hrb`-specific patterns
   (broker subprocess harness, the SCM_RIGHTS fd helpers) with
   project-specific equivalents — the section headers are stable.
3. Author `EXECUTION.md` + `COVERAGE_MAP.md` from scratch for the
   sibling — these are the project-specific runbook + state-of-union.

The federation standards `TS-01..TS-06` (in `mgf-common`) name the
contract every project's testing posture must meet; this repo's
infrastructure implements that contract concretely.
