Skip to content

mutate_scenario.py never flips != back to ==, so every '!=' assertion in the corpus goes operator-unmutated #383

Description

@Yaraslaut

Summary

scripts/scenario/mutate_scenario.py flips three operator pairs and no more:

for original, flipped in ((" == ", " != "), (" !~ ", " ~ "), (" ~ ", " !~ ")):

!= is a destination but never a source. So an assertion written
expect ok field X != Y is never mutated at the operator, and its only mutant
is the okerr kind flip — which is caught by the reply's kind, not by
anything the comparison itself measures. The comparison is, for mutation
purposes, unverified: an != that would pass against literally any value
(because the named field is never equal to the constant, for a reason
unrelated to what the file claims) survives the whole mutation run silently.

The mutator's own docstring names the pairs it flips as
"==!=, ~!~" — the ↔ says bidirectional, and only one
direction is implemented.

Scope in the shipped corpus

13 assertions across four files, on this branch:

scripts/scenario/scenarios/bookmarks/the-live-model-cap-is-reached.scenario:52:expect ok field @modelId != 0
scripts/scenario/scenarios/bookmarks/the-live-model-cap-is-reached.scenario:816:expect ok field @modelId != 0
scripts/scenario/scenarios/bookmarks/the-live-model-cap-is-reached.scenario:863:expect ok field @modelId != 0
scripts/scenario/scenarios/ledger/bootstrap-a-book-over-the-wire.scenario:82:expect ok field id != $book
scripts/scenario/scenarios/ledger/open-account-transact-report-close.scenario:116:expect ok field status != 2
scripts/scenario/scenarios/ledger/submit-a-report-and-poll-it.scenario:69:expect ok field status != 2
scripts/scenario/scenarios/ledger/submit-a-report-and-poll-it.scenario:73:expect ok field status != 2
scripts/scenario/scenarios/ledger/submit-a-report-and-poll-it.scenario:80:expect ok field status != 2
scripts/scenario/scenarios/ledger/submit-a-report-and-poll-it.scenario:84:expect ok field status != 2
scripts/scenario/scenarios/ledger/submit-a-report-and-poll-it.scenario:99:expect ok field status != 2
scripts/scenario/scenarios/pastebin/wire-kinds-and-typeid-refusals.scenario:39:expect ok field @modelId != 0
scripts/scenario/scenarios/pastebin/wire-kinds-and-typeid-refusals.scenario:56:expect ok field @body != "[]"

Five of the ledger ones are status != 2 (ReportStatus::Failed), which
submit-a-report-and-poll-it.scenario's own header explains was chosen
because status == 0 raced the report runner's timer. Those are the
assertions carrying that file's central claim, and the operator in them is
exactly what nothing checks.

Verification status

Reproduced. Running the mutator over
scenarios/ledger/bootstrap-a-book-over-the-wire.scenario (which has one !=
line, at 82) produces 31 mutants; line 82 contributes exactly one, the kind
flip, and no operator flip:

  line   81  kind ok->err       caught
  line   82  kind ok->err       caught
  line   85  kind ok->err       caught
  line   85  op !~->~           caught

Every neighbouring ==/~/!~ line contributes both a kind flip and an
operator flip; line 82 contributes only the kind flip.

Not verified: whether adding the (" != ", " == ") pair leaves the shipped
corpus green. It very likely does not, and that is the point — field status != 2 mutated to field status == 2 would be a survivor if and only if the
job really has reached Failed, which it should never do, so that one should
be caught. @modelId != 0 mutated to @modelId == 0 should also be caught.
I did not run it.

Not verified: whether the same one-directional gap exists for any other
operator the runner supports. morph_scenario.py's compare handles
==, !=, ~, !~ and nothing else, so the set is closed, but I only
checked the mutator's source rather than exhausting the runner's.

What would close this

Add (" != ", " == ") to the pair list, run
python3 scripts/scenario/run_scenarios.py --mutate over every rung, and
either fix or explicitly document any assertion that then survives. A
survivor found this way is the finding, not the failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: ciSubsystem: cibugSomething 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