Mull mutates C and C++ at the LLVM IR level
Practical mutation testing and fault injection for C and C++
At a glance
- What is it?
- Mull is a mutation testing and fault injection tool for C and C++, built on the LLVM JIT so that mutants are compiled and run against your existing test suite. It suits teams that already have good coverage and want to know whether those tests would notice a broken implementation.
- Who is it for?
- Adopt Mull when your C or C++ project already has a test suite and you need to know which of your assertions would actually catch a regression, since the tool compiles mutated programs and runs them through your tests rather than asking you to reason about coverage by hand. Do not adopt it as a first step in a project that still lacks a working test suite, because a mutation score against weak tests mostly measures the weakness.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A tool for the question coverage cannot answer
Mull is described in one line as a practical mutation testing and fault injection tool for C and C++. The problem it addresses is the one every team hits after its coverage numbers look good. Coverage says a line was executed. It does not say that any assertion noticed what the line produced, so a suite can execute every branch of a parser and still pass when the parser returns the wrong number. Mutation testing changes the question: you deliberately break the implementation, then check whether your tests fail. The fault injection side of the tool is the same idea used at runtime rather than as a pre-compiled mutant, and the project treats both as parts of one tool. The audience is therefore not someone learning about testing, but someone with an existing suite in C or C++ who wants a measure of the suite's sensitivity rather than its coverage.
The mutants live in LLVM IR
The mechanism is visible in the project's own citation, which points at the paper Mull it over: mutation testing based on LLVM, published in the 2018 IEEE International Conference on Software Testing, Verification and Validation Workshops. The keywords of that paper list just-in-time, program compilers, LLVM IR, mutated programs, the LLVM framework, the LLVM JIT, the tested program, the runtime and program crashes, which is a compact description of how the tool works. Mutations are introduced at the intermediate representation level rather than in your source, and the mutated program is then executed. The consequence is that Mull inherits the LLVM toolchain, and the repository makes that dependency explicit with files that track the available and supported LLVM versions alongside the build definitions.
Just-in-time execution is what makes the loop usable
Why the JIT matters is the difference between a usable tool and an unusable one, and the project says so by listing just-in-time among its keywords. A source level mutation tool that rewrites your code and recompiles the whole project for every mutant is slow enough that people run it once a quarter. If the mutant can be produced and executed at the IR level, the cost of each mutant is dominated by running the tests rather than by rebuilding everything. That is the engineering reason a tool in this space exists at all, and it is the reason the LLVM version list in the repository is a practical constraint rather than an implementation detail, since a compiler upgrade can change the IR and therefore the behaviour of the mutants. The tool also supports fault injection, where the fault is introduced while the program runs, which is the mode you want when the failure you care about is a crash rather than a wrong value.
A Bazel build with pinned LLVM versions
The repository layout is that of a serious infrastructure project. There is a `.bazelrc` and a `.bazelversion`, a `MODULE.bazel` and a `BUILD` file, and a `bazel/` directory, so Bazel is the build system. The LLVM versions are handled in dedicated Starlark files: `mull_available_llvm_versions.bzl`, `mull_supported_llvm_versions.bzl`, alongside `mull_build.bzl`, `mull_deps.bzl`, `mull_package.bzl`, `mull_package_info.bzl` and `mull_publish.bzl`. The code itself sits under `include/` and `lib/`, with `tests/`, `tools/`, `docs/`, `infrastructure/`, `third_party/` and a `rust/` directory alongside it. On top of that sit the Python tooling files, `cloudsmith_runner.py` and a set of requirement files that separate the base list from the Linux and macOS lock files, plus a `.pre-commit-config.yaml`, a `.clang-format` and a `.devcontainer/` for a reproducible development environment.
Precompiled packages through Cloudsmith
Not everyone wants to build a LLVM based tool from source, so the project publishes precompiled packages. The README states that hosting for precompiled packages is graciously provided by Cloudsmith, and the badge links to that service. The Python side of that pipeline is visible in the repository rather than hidden: `cloudsmith_runner.py` sits at the root, `cloudsmith-cli` appears in the requirements file, and the `mull_package.bzl` and `mull_publish.bzl` files suggest the packaging and publication steps are driven from the Bazel side. The requirements file itself is short and pinned, with lit, psutil, cloudsmith-cli, pystache and pre-commit, each with an exact version, which is the kind of pinning you want in a build that publishes binaries. The pinned set is short:
lit==23.1.3
psutil==7.2.2
cloudsmith-cli==1.29.0
pystache==0.6.8
pre-commit==4.7.0The README points you elsewhere for everything practical
This is a real limitation of the repository as a starting point, and it is worth stating plainly. The README contains no installation command, no configuration file format, no list of the available mutation operators and no invocation syntax. It says only that for installation and usage you should refer to the latest documentation at mull-project.com. The documentation is therefore part of the product rather than an appendix, and the repository reinforces that with a `docs/` directory and a `.readthedocs.yaml` file, which is the configuration Read the Docs uses. The community channel is a Discord server with an invitation link in the README, and the contribution path starts from `CONTRIBUTING.md`. If you are evaluating the tool, budget time to read the external documentation, because the repository alone will not tell you what the tool can mutate or how to configure a run.
Apache-2.0, a named paper, and a steady 0.34 line
The licence is Apache-2.0, which in short terms means you can use, modify and redistribute the tool, including commercially, with the notice preserved and with the patent and contribution terms the licence adds. The copyright line reads Copyright 2016 to 2026 Alex Denisov and Stanislav Pankevich, with details in the LICENSE file. The project's research footing is the 2018 ICSTW paper, and the README keeps the BibTeX entry so the work can be cited. The release history is regular. Version 0.34.2 was published on 2026-10-17, after 0.34.1 on 2026-09-13 and 0.34.0 on 2026-05-12, and the repository is not archived with the last push on 2026-10-20. A `CHANGELOG.md` is present, and `mull-ci.yml` at the root suggests the continuous integration configuration for the project itself.
Editorial conclusion
Adopt Mull when your C or C++ project already has a test suite and you need to know which of your assertions would actually catch a regression, since the tool compiles mutated programs and runs them through your tests rather than asking you to reason about coverage by hand. Do not adopt it as a first step in a project that still lacks a working test suite, because a mutation score against weak tests mostly measures the weakness. Verify first which LLVM versions the build supports, since the repository tracks them in dedicated .bzl files, and read the documentation site rather than the README, which contains no installation or usage instructions at all.
Frequently asked questions
What does Mull do for C and C++ projects?
It is a mutation testing and fault injection tool. It builds mutated versions of the program and checks whether your existing tests fail, so you can see whether your assertions would catch a broken implementation rather than only which lines ran.
How does Mull relate to LLVM?
Mull is built on LLVM: its paper is titled Mull it over: mutation testing based on LLVM, and the repository tracks available and supported LLVM versions in dedicated .bzl files next to the Bazel build definitions.
Where can I get precompiled Mull packages?
Precompiled packages are hosted on Cloudsmith, which the README credits for providing the hosting, with publication driven from the repository through cloudsmith_runner.py and the Bazel package files.
How do I install Mull?
The README contains no installation commands and points to the latest documentation at mull-project.com for installation and usage. The repository itself documents the build with Bazel.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mull-project-mull)Was this useful?