Skip to content

forms: 46 unasserted mutants in include/morph/forms, mostly boundary comparisons tested away from their boundaries #432

Description

@Yaraslaut

Sibling of morph#431, for the forms half of the same measurement.

The framework's first mutation run (morph#405) left 321 unasserted
survivors
— code morph_tests executes, changes to which no test notices.
46 of them are in include/morph/forms:

survivors file
25 include/morph/forms/forms.hpp
11 include/morph/forms/flows.hpp
6 include/morph/forms/instance_constraints.hpp
4 include/morph/forms/views.hpp

Against a subsystem measuring 94.37% lines. Full triage in
scripts/mutation_survivors.json.

Why this is not a coverage-percentage ticket

morph#410 asked for include/morph/forms at 99% lines. That target is being
replaced by this one, for a reason the same measurement demonstrates: line
coverage says these lines run, and the mutation run says nothing checks what they
do. Chasing the percentage produces more of the tests that created the gap.

The shape that dominates here

Boundary comparisons exercised only away from their boundaries.
cxx_gt_to_ge and family survive at instance_constraints.hpp:156
(kMaxDecimalPlaces), forms.hpp:2356, and others. The pattern to look for is a
test whose name claims a boundary and whose body tests the middle — that is
exactly what morph#405 found next door in wire.hpp, where a case named "decode
accepts an envelope at the size limit boundary" asserted a 1 KiB envelope against
an 8 MiB cap.

Check each forms boundary the same way before writing anything: read the existing
test that covers it, and see whether it actually sits on the edge.

Interaction with the rest of this lane

flows.hpp's 11 survivors sit in the file morph#417 is already correcting for
dangling citations, and forms.hpp is what morph#388 and morph#387 have just
changed. Read the current files rather than any line number quoted in an older
issue.

Note that FlowSession's absence of in-flight coalescing was measured during
morph#417 — five back-to-back ready set<> calls produced five executes. That
behaviour is now documented but is a candidate for exactly this ticket: is there
a test that would fail if coalescing were reintroduced?

The constraint

Do not chase the number. A mutant killed by an assertion written to kill that
mutant, on a path nobody cares about, is a test with no reason to exist. Each new
test must be justifiable from the behaviour, with the survivor as evidence that
the assertion was missing.

Some survivors will be genuinely equivalent — the run already found 11 such in
core, each recorded with a reason. Moving a forms survivor into that class with a
stated reason is a valid outcome and is not a failure.

Verification status: measured

Mull 0.34.0 / mull-runner-22 / LLVM 22.1.2 / clang 22.1.8, cxx_all, over
include/morph/core and include/morph/forms together. Reproduce with
bash scripts/mutation.sh (morph#405).

Not verified: whether the forms survivors are reachable through the QML
renderer as well as through the C++ suite. morph_forms_qml_tests was not part
of the campaign, so a mutant surviving morph_tests may still be caught there —
worth checking before writing a C++ test for a path the QML suite already pins.

What would close this

  1. bash scripts/mutation.sh over include/morph/forms reports zero surviving
    mutants at the named boundary sites.
  2. Every remaining forms survivor is killed, or classified equivalent /
    side-channel with a reason, in scripts/mutation_survivors.json. None
    left unclassified.
  3. The re-run forms score is recorded next to this baseline.
  4. Each new test asserts behaviour rather than merely reaching it — removing its
    assertion would make it pass on mutated code.

Supersedes the percentage target in morph#410, which should be closed or
re-pointed at this once the split is agreed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: formsSubsystem: formsbugSomething isn't workingtriage: validWell-framed; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions