1.6. Rust coverage analysis with gnatcov coverage

Source coverage analysis for the Rust language is an unstable feature of gnatcov. It relies on the internal coverage instrumentation of the rustc compiler, which is itself leaning on the code coverage framework of the LLVM project.

Note

This feature is made to be compatible with the GNATPro For Rust tool suite, compatibility with other rust toolchains is not guaranteed.

1.6.1. Rust coverage workflow

The workflow consists in 3 steps. First, build the program while instrumenting it for coverage analysis. The instrumentation is delegated to rustc. Then, run the program, which produces trace files. Finally, use gnatcov coverage to generate a coverage report.

An example project demonstrating Rust instrumentation can be found at share/examples/gnatcoverage/doc/rust_cov.

1.6.1.1. Instrument and build the project

Unlike source coverage analysis for Ada, C and C++ which rely on gnatcov to instrument the source code before compiling it, the Rust workflow delegates instrumentation to the rustc compiler.

To instrument the code, pass the -Cinstrument-coverage argument to the compiler. If instrumenting for the stmt+decision or stmt+mcdc coverage levels, pass the -Ccoverage-options=mcdc additionally.

Decision coverage as defined by gnatcov does not exist in the rust compiler, thus gnatcov will infer the decision coverage from MC/DC coverage.

The example showcases using the Cargo build system to instrument a project for stmt+mcdc analysis analysis.

RUSTFLAGS="-Cinstrument-coverage -Ccoverage-options=mcdc" cargo build

1.6.1.2. Run the executed binary

Once again, the example showcases running the compiled program through Cargo. At the end of execution, a trace file ending with .profraw is created.

The name of the file can be customized with the LLVM_PROFILE_FILE environment variable. See LLVM_PROFILE_FILE format.

LLVM_PROFILE_FILE="trace-%p.profraw" cargo run -- ARGS...

The program may be run several times with different inputs to improve final coverage.

1.6.1.3. Produce a coverage report

To produce the coverage analysis from the obtained .profraw files, proceed as follow:

gnatcov coverage --level=stmt+mcdc -a xcov --exec EXEC_BIN PROFRAW_FILES...

The important part is that the program binary needs to be passed with the --exec argument. In a Cargo project, the binary usually lives under target/debug or target/release.

Note that aside of producing a report, the rust coverage report can be saved as a checkpoint and reused for consolidation.

1.6.2. Rust coverage limitations

This feature being relatively new, there are known limitations that we shall mention hereafter.

1.6.2.2. Approximative source location ranges

Currently, you may witness that some SCOs have a source location range that can overlap or merge with its neighbours. This is due to bugs in the compiler’s instrumentation logic and will be fixed in coming releases.

1.6.2.3. Unsupported constructs

Some constructs are not yet supported:

  • MC/DC instrumentation of pattern matching. Pattern matching can be viewed as a decision with multiple conditions. However, it can lead to more than just 2 outcomes.

  • Rust macros by example and procedural macros are not yet instrumented.