Skip to content

Conversation

simon-something
Copy link

@simon-something simon-something commented Mar 28, 2025

As discussed in #478 , this is an implementation of mutation tests for foundry unit tests (I'd suggest closing the other PR which uses Gambit)

Motivation

While coverage explains which lines are executed when running a test suite, mutation tests add another level of security by assessing which lines are tested. To do so, mutations (ie random or constrained changes to the codebase) are introduced, the codebase is then recompiled (only keeping the successful compilation outcome) and the test run against this "mutated codebase". Ideally, the tests should fail against any mutant (ie not a single part of the code can be changed without getting caught by at least one test).

Solution

This implementation started from the existing Certora's Gambit, but diverged (but kept some of the mutation naming). It leverages Solar to create an ast, find mutation and conduct them, in an efficient manner.

The flow is as follow:

  • triggered by --mutate flag of forge test
  • if a list of contracts is passed after mutate, these are the targets mutated
  • if no contract is provided, list all contracts in src/
  • for now, mutate isn't excluding test filters (still not sure if it shouldn't be the case tho)
  • run all tests, using cache (see below) - if one test fails, interrupt here
  • do the following for each contract to mutate:
    • check if there is a previous mutation test for this contract and its build id - if unchanged, reuse this result and go on the next contract to mutate
    • lex and parse it as an ast (using Solar)
    • visit this ast, for each expression, generate each possible mutation (eg x = 4 will be mutated as x = 0 and x = -4)
    • for each mutant:
      • emit the solidity code of the mutant in src
      • (try to) compile it, using dynamic linking (this uses foundry-compiler, to be "compiler-agnostic" if/when Solar is used, even tho it should then be refactored to avoid writing solidity on the disk/starts from the mutated ast instead)
      • if successfully compiling, run the tests and get the outcome
      • save the outcome in the out folder, along the current build id
  • collect and display all outcomes, in terms of invalid, dead, surviving mutant

The mutations are stored in a mutator module, to allow easily adding/modifying them (even if it is kept as temporary design, this will help designing them imo).

Beside the (many) todo's in the code, some things to work on are:
tests+++, doc, squash, implement non-duplicate detection (trivial cases at least:compare bytecode hash?) - see the original issue, review other mutation strategies (vertigo and univeralmutator?) or poke the one not implemented by Gambit (https://github.com/Certora/gambit/blob/bf7ab3c91c47a10dcf272380b6406f0404f3b5d1/src/mutation.rs#L323 for instance)

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

@simon-something
Copy link
Author

This is getting quite huge of a PR - there are lots of optimization to hunt for imo (and maybe some mutators aren't applied correctly), but would appreciate at least a quick first/overall design review, before digging further!
image

@grandizzy
Copy link
Collaborator

This is getting quite huge of a PR - there are lots of optimization to hunt for imo (and maybe some mutators aren't applied correctly), but would appreciate at least a quick first/overall design review, before digging further!

@simon-something sorry for late reply, this is on list of prio and will walk through it asap. thank you!

@jenpaff jenpaff linked an issue Jun 12, 2025 that may be closed by this pull request
1 task
@grandizzy grandizzy moved this from Ready For Review to Todo in Foundry Jul 8, 2025
@jenpaff jenpaff added this to the v1.4.0 milestone Aug 18, 2025
@jenpaff jenpaff moved this from Todo to Backlog in Foundry Aug 18, 2025
@zerosnacks zerosnacks moved this from Backlog to In Progress in Foundry Aug 26, 2025
@grandizzy grandizzy modified the milestones: v1.4.0, v1.5.0 Sep 8, 2025
@github-project-automation github-project-automation bot moved this from In Progress to Done in Foundry Oct 13, 2025
@simon-something
Copy link
Author

Closed for #11996

@jenpaff jenpaff moved this from Done to Completed in Foundry Oct 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Completed

Development

Successfully merging this pull request may close these issues.

tracking: add mutation testing support

6 participants