Skip to content

feat: add ASIL-aware MC/DC coverage gate to cfusa coverage - #112

Merged
SoundMatt merged 1 commit into
mainfrom
feat/coverage-asil-mcdc-gate
Aug 13, 2026
Merged

feat: add ASIL-aware MC/DC coverage gate to cfusa coverage#112
SoundMatt merged 1 commit into
mainfrom
feat/coverage-asil-mcdc-gate

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

Fixes #106. Part of the ASIL-scaling initiative tracked in #103. Builds on #104 (merged).

Summary

cfusa coverage's MC/DC/threshold gate previously keyed only to DO-178C --dal; an ISO 26262 project got no automatic MC/DC gate unless it pretended to be DO-178C via --dal DAL-A.

Adds --asil QM|ASIL-A|ASIL-B|ASIL-C|ASIL-D, mapping onto ISO 26262-6 Table 12's structural-coverage recommendation levels using the same four-tier shape --dal already has:

ASIL Line Branch MC/DC (same tier as)
ASIL-D 100% 100% required DAL-A
ASIL-C 100% 100% DAL-B
ASIL-A/B 100% DAL-C
QM DAL-D

Table 12 rates these as "+"/"++" recommendations rather than DO-178C's binary "required" framing; this treats the "++" MC/DC rating at ASIL-D as a hard gate, mirroring how the command already treats DO-178C's own recommendation levels as hard gates via --dal.

apply_asil() uses the shared cfusa_asil_rank() from #104 instead of its own string table. When both --dal and --asil are given, the stricter of the two applies to each of line/branch/MC/DC independently (max-combine) rather than one silently overriding the other — a project declaring both standards must satisfy whichever is more demanding. Verified with a regression test that --dal DAL-D (which alone disables every threshold) does not suppress an --asil ASIL-D requirement given alongside it.

--asil composes with the existing --mcdc-file precision path exactly like --dal already does: without --mcdc-file, ASIL-D falls back to the 100%-branch-coverage proxy; with it, the precise LLVM MC/DC result overrides the proxy.

Testing

  • 9 new regression tests in tests/test_coverage_asil.c: --asil validation, each tier's threshold behavior (ASIL-A line-only, ASIL-C line+branch, ASIL-D branch-proxy and precise-MC/DC-file paths), the --dal+--asil combination, and the JSON asil field.
  • ctest: 42/42 passing.
  • cfusa check --dir .: 0 errors.
  • cfusa trace --dir .: new REQ-COV020 traced + tested, no dangling references.

🤖 Generated with Claude Code

cfusa coverage's MC/DC/threshold gate previously keyed only to
DO-178C --dal; an ISO 26262 project got no automatic MC/DC gate
unless it pretended to be DO-178C via --dal DAL-A.

Adds --asil QM|ASIL-A|ASIL-B|ASIL-C|ASIL-D, mapping onto ISO 26262-6
Table 12's structural-coverage recommendation levels using the same
four-tier shape --dal already has: ASIL-D requires MC/DC (same tier
as DAL-A), ASIL-C requires full branch coverage but not MC/DC (same
tier as DAL-B), ASIL-A/B require full line coverage only (same tier
as DAL-C), QM has no requirement (same tier as DAL-D). Table 12 rates
these as "+"/"++" recommendations rather than DO-178C's binary
"required" framing; this treats the "++" MC/DC rating at ASIL-D as
a hard gate, mirroring how the command already treats DO-178C's own
recommendation levels as hard gates via --dal.

apply_asil() uses the shared cfusa_asil_rank() from #104 instead of
its own string table. When both --dal and --asil are given, the
stricter of the two applies to each of line/branch/MC/DC
independently (max-combine) rather than one silently overriding the
other -- verified with a regression test that --dal DAL-D (which
alone disables every threshold) does not suppress an --asil ASIL-D
requirement given alongside it.

--asil composes with the existing --mcdc-file precision path exactly
like --dal already does: without --mcdc-file, ASIL-D falls back to
the 100%-branch-coverage proxy; with it, the precise LLVM MC/DC
result overrides the proxy.

9 new regression tests in tests/test_coverage_asil.c covering
validation, each ASIL tier's threshold, the --dal/--asil combination,
and the JSON asil field.

Part of #103.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
"BRF:%ld\nBRH:%ld\n"
"end_of_record\n",
lines_found, lines_hit, branches_found, branches_hit);
fclose(f);
FILE *f = cfusa_fopen_write(path);
if (!f) return;
fputs(content, f);
fclose(f);
char buf[4096] = "";
size_t n = fread(buf, 1, sizeof(buf) - 1, f);
buf[n] = '\0';
fclose(f);
char lcov[256];
snprintf(lcov, sizeof(lcov), "%s/full.info", COVA_DIR);
write_lcov("full.info", 10, 10, 4, 4);
char *argv[] = {"cfusa", "--lcov", lcov, "--asil", "ASIL-Z", NULL};
char lcov[256];
snprintf(lcov, sizeof(lcov), "%s/partial_line.info", COVA_DIR);
write_lcov("partial_line.info", 100, 60, 10, 5); /* 60% line */
char *argv[] = {"cfusa", "--lcov", lcov, "--asil", "ASIL-A", NULL};
char lcov[256];
snprintf(lcov, sizeof(lcov), "%s/full_both.info", COVA_DIR);
write_lcov("full_both.info", 100, 100, 10, 10); /* 100% line + branch */
char *argv[] = {"cfusa", "--lcov", lcov, "--asil", "ASIL-C", NULL};
char lcov[256];
snprintf(lcov, sizeof(lcov), "%s/full_both2.info", COVA_DIR);
write_lcov("full_both2.info", 100, 100, 10, 10);
char *argv[] = {"cfusa", "--lcov", lcov, "--asil", "ASIL-D", NULL};
"{\"covered_true_count\":3,\"covered_false_count\":2},"
"{\"covered_true_count\":0,\"covered_false_count\":1}"
"]}]}]}]}");
char *argv[] = {"cfusa", "--lcov", lcov, "--asil", "ASIL-D",
char lcov[256];
snprintf(lcov, sizeof(lcov), "%s/partial3.info", COVA_DIR);
write_lcov("partial3.info", 100, 60, 10, 6); /* 60% line, 60% branch */
char *argv[] = {"cfusa", "--lcov", lcov,
snprintf(lcov, sizeof(lcov), "%s/full_both4.info", COVA_DIR);
snprintf(out, sizeof(out), "%s/asil_out.json", COVA_DIR);
write_lcov("full_both4.info", 10, 10, 4, 4);
char *argv[] = {"cfusa", "--lcov", lcov, "--asil", "ASIL-B",
@SoundMatt
SoundMatt merged commit 461412f into main Aug 13, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cfusa coverage: add an ASIL-aware MC/DC gate (currently DO-178C --dal only)

2 participants