Pokrytí testy Rust executable se měří jednou a kladou se mu dvě otázky. Měřením je scripts/rust-coverage: jeden export cargo llvm-cov, testovací kód vyloučený z obou stran každého zlomku, jedno pravidlo počítání řádků, funkcí a regionů (autoritou, jak se který počítá, je hlavička samotného skriptu). Každý konzument — kontrola cratu, kontrola domény, diferenciální kontrola a jakýkoli report — čte tentýž jeden soud. Neexistuje druhý práh, druhý parser ani procento počítané jinde jinak.
Dvě hranice a rozdílové měření
Podlaha crate (scripts/rust-coverage-threshold) je dolní mez pokrytí řádků celého spustitelného souboru, přičemž testovací kód je mimo jmenovatele. Je to ratchet proti hnití crate, nikoli příslib úplnosti.
Doména relace/kontinuity (scripts/session-coverage-threshold, nad soubory v scripts/session-coverage-domain) drží jeden subsystém na jeho vlastní spodní hranici, stejně na řádcích, funkcích i regionech. Spodní hranice pro celý crate neříká nic o tom, zda je subsystém, na kterém závisí kontinuita repozitáře, vůbec testován; tady se to hlídá.
Obě hranice jsou západky. Každá je pokrytí, které její předmět skutečně naměřil, když byla stanovena, a smí růst, nikdy klesat; když se pokrytí zlepší, zvyšte soubor i jeho mez společně. Pevná hranice nad tím, čeho kdy kterýkoli běh dosáhl, nekontroluje nic — jen učí lidi očekávat, že úloha bude červená — takže žádná z nich takovou hranicí není. Mez hranice crate drží pravidlo: project.rust-command-tested-in-file odmítne hranici pod FLOOR_BOUND, kterou deklaruje její kontrola scripts/ci/rust-command-check, a test/cases/77_rust_evidence.sh čte tutéž mez. Mez hranice domény drží samotné test/cases/77_rust_evidence.sh. Nový nepokrytý kód je odmítnut bez ohledu na kterýkoli agregát diferenciální kontrolou níže.
Diferenční kontrola (scripts/ci/coverage-differential, pravidlo project.new-code-is-covered) je invariant změněného kódu z úkolu #214. Drží v pokrytí každý spustitelný řádek, funkci a region, který změna přidává nebo se jich dotýká — měřeno proti merge-base větve s trunkem, včetně pracovního stromu, takže necommitnutá úprava se drží přesně jako commitnutá.
Proč diferenciální a co nedělá
Pokrytí celého repozitáře je pod 100 % a starý dluh je skutečný. Jediná podlaha pro celý crate nemůže zakázat nový dluh: změna může přidat nepokrytý kód, zatímco souhrn se sotva pohne. Diferenční kontrola vede hranici tam, kde ji lze udržet bez přepisování historie — u kódu, kterého se změna dotýká:
| Co změna dělá | Co kontrola vyžaduje |
|---|---|
| přidá soubor | každý spustitelný řádek, funkce a region v něm pokrytý |
| přidává funkci | pokryto |
| mění spustitelný řádek | pokryto |
| mění větev nebo oblast | pokryto |
| ponechává starý kód nedotčený | nic: není to věc této kontroly |
Invariant je new_debt == 0 a legacy_debt_after <= legacy_debt_before. Kontrola se nikdy nedívá na řádek, kterého se změna nedotkla, takže nemůže chtít, aby se splácel starý dluh; selže na prvním změněném řádku, který se spouští a žádný test ho nezkouší. Změněný řádek, který se nemapuje na nic spustitelného — komentář, prázdný řádek, use, deklarace typu nebo testovací kód — není nález: není tam co spouštět, takže diff jen s dokumentací nebo jen s testy projde bez nálezů.
Pět výsledků, nikdy nesměšovaných
Kontrola hlásí a končí v jednom slovníku — stejném, který používá scripts/rust-coverage:
| výsledek | význam | ukončení |
|---|---|---|
| PASS | každá změněná spustitelná položka je pokryta | 0 |
| PASS | změna se nedotkla žádného zdrojového řádku crate | 0 |
| SELHÁNÍ | změněný spustitelný řádek, funkce nebo oblast je nepokrytá | 10 |
| NEZNÁMÉ | git nedokáže vyřešit základ, proti kterému se má diffovat (mělký klon, žádný vzdálený server) | 13 |
| BLOCKED | cargo-llvm-cov chybí, nebo instrumentovanému běhu nešlo věřit | 12 |
Neznámé není průchod. Blokované není průchod. Spadlé měření není nikdy zelené — kontrola, která z „nástroj pokrytí selhal“ udělá průchod, je přesně ten způsob selhání, který celé úsilí existuje, aby odmítlo.
Test, který selže pod instrumentací, je také BLOCKED: cargo-llvm-cov nezapíše žádný export pro sadu, která selhala. Kontrola pak vypíše, co hlásil testovací harness, sekci failures: každé selhávající binárky s názvem a panikou každého selhávajícího testu, takže log úlohy jmenuje test, ne jen jeho binárku. Binárka ukončená signálem takovou sekci nezapíše a ani řádek test result:, takže se vypíše i její nedokončený blok running N tests: jeho hlavička, kolik testů dokončilo a jeho poslední řádky. Nemůže jmenovat test, který běžel, protože paralelní harness zapisuje řádek testu až po jeho dokončení; stderr cargo jmenuje binárku a signál. Zelený běh nevypíše nic z výstupu harnessu. test/cases/536_the_coverage_gate_names_the_failing_test.sh toto chování drží.
Spuštění
scripts/ci/coverage-differential # against origin/master's merge-base
scripts/ci/coverage-differential <base> # against an explicit base
MJ_COVERAGE_EXPORT=<file> scripts/ci/coverage-differential # reuse an existing export
scripts/rust-coverage --changed <base> # the measurement directly
scripts/rust-coverage # both floors
scripts/rust-coverage --report # measure, hold nothing
scripts/rust-coverage --domain # the session/continuity domain only
CI spouští kontrolu v jobu coverage při každé změně pod apps/majordomus-cli/; lokální check a cesta pre-commit dospějí ke stejnému posouzení. Behaviorální důkaz je test/cases/132_coverage_differential.sh: spouští kontrolu proti pevnému exportu a syntetickým diffům a ověřuje, že záměrně nepokrytý změněný řádek selže, tentýž řádek pokrytý projde, změna jen v dokumentaci se nemá k ničemu držet a nerozlišitelná báze je UNKNOWN, ne tichý průchod.
Záznam, který čte předběžná kontrola
Měření celého cratu, které scripts/rust-coverage spouští samo (kontrola nebo --report), zanechá záznam v .ai/local/state/coverage/rust.json: součty cratu a domén, výsledek (pass, fail nebo report), návratový kód cargo pro instrumentovanou sadu a commit a strom, které změřilo. Strom se čte před během sady a znovu po něm a záznam říká clean jen tehdy, když jsou obě čtení čistá a jmenují stejný HEAD. --from, --changed a --domain nezaznamenávají nic: první měří strom, který skript nikdy neviděl, ostatní dva měří část cratu.
Kontrola verification.coverage preflightu (docs/PREFLIGHT.md) posuzuje pokrytí podle tohoto záznamu samotného. Záznam jiného commitu nebo stromu, který se pohnul, je stale a selhávající sada je failed i tam, kde prahy platí. Bez záznamu je kontrola unavailable. Záznam je lokální stav, takže odpověď pokrývá jen tento checkout. Měření z CI se k němu nikdy nedostane. test/cases/552_coverage_is_recorded_for_the_preflight.sh spouští skutečný skript proti náhradnímu cargo a nechá skutečný spustitelný soubor posoudit každý záznam, který zapíše.
Čím toto zatím není
Diferenciální kontrola drží pokrytí řádků, funkcí a regionů — dimenze, které cargo-llvm-cov pro tento crate měří. Neprovádí mutační testování ani injekci chyb; tam, kde záleží na smyslu predikátu (kontrola autorizace, rozhodnutí o důvěře, přechod stavu), číslo pokrytí dokazuje, že řádek běžel, ne že by test selhal, kdyby řádek byl špatně. Tyto subsystémy nesou vlastní adverzární testy (například sady důvěry a protokolu meshe) a kontrola pokrytí je pro ně nutná, nikoli postačující. Zastarání důkazů pokrytí je vázáno na export, proti němuž kontrola běží a který CI regeneruje při každém běhu; trvalý model důkazů a zastarání nad zaznamenanými běhy (území ADR 0041) není součástí této kontroly.