-
-
Notifications
You must be signed in to change notification settings - Fork 181
Developers
- Overview
- Building other projects
- Source Analysis
- Instrumenting code
- Process tracing
- Generating Reports
This section aims to layout some of the structure of Tarpaulin and provide a technical reference for the technologies underpinning it.
When Tarpaulin runs, the basic sequence of events is as follows (assuming the user is collecting coverage):
- Build the tests for the project to cover with any user supplied options
- Take the list of test binaries and for each one:
- Run source analysis on the project identifying lines that can't be covered or will be absent from debug info but can be covered
- Load the object file and parse to find lines that can be instrumented
- Return a list of these lines and their addresses to populate with coverage stats
- Fork the process, have the child run the test and the parent instrument it
- The parent now steps through the code like a debugger logging coverage stats
- Merge all the coverage statistics to get unified stats for the project
- Generate any reports and save or send them
We can split tarpaulin into a few function areas as a result
- Interactions with the Rust build system (compiler, linker, Cargo)
- Source code analysis: what lines are uncoverable (
#[derive(..)]
, what lines will be missed (unused templates) - Finding lines to instrument - understanding what's in the DWARF tables or x86_64 assembly
- Tracing the process - ptrace in Linux, other tools for other operating systems
- Coverage reports - codecov.io, coveralls.io, Cobertura.xml, HTML, other useful formats
- General usability/code quality
As well as these areas involving the implementation of Tarpaulin, work also has to be done in testing and documentation to ensure correctness and make Tarpaulin easy to use.
## Building Other ProjectsTarpaulin uses Cargo as a library to manage the build systems of other projects and allow uses to configure what packages or features are included when they run coverage.
Most coverage tools are designed to work with C which lacks a lot of abstractions that higher level languages have. This can cause language constructs which aren't actually executable code to be mistakenly included as misses and result in other code being omitted from results. Also multiple addresses may map to the same expression, and with some code where the expression is split over multiple lines you don't want that expression appearing more than once in the statistics. Below are some examples which Tarpaulin filters out, for more comprehensive examples look to the tests in the source_analysis module.
Derive macros, the generated code is mapped to the derive statement partially although the executable lines exist outside the project source causing it to be flagged as a missed line.
#[derive(Debug}]
struct SomeStruct;
Unused meta-programming code doesn't generate any assembly so isn't included in the debug tables. This means unused traits and templated functions need to be included in the statistics via source analysis. Also, unused inline functions don't generate assembly or debug information.
fn foo<T>(t: T) {
// Some code
}
To in
TODO
TODO