#coverage #gcov #lcov

cov

gcov format (*.gcda/*.gcno) parser and analyzer in pure Rust

4 releases

Uses old Rust 2015

0.0.5 Aug 29, 2018
0.0.4 Jun 18, 2018
0.0.2 Nov 15, 2017
0.0.1 Jun 13, 2017
0.0.0 Jun 8, 2017

#5 in #gcov


Used in cargo-cov

MIT license

125KB
2.5K SLoC

cov is a GCNO/GCDA parser. GCNO/GCDA are source code coverage file formats produced by GCC and LLVM-based compilers, including rustc.

GCNO (gcov notes) files are created by rustc when given the -Z profile flag. The GCNO files encode the structure of every function in the program, known as the control-flow graph (CFG). The GCNO also contains the filename and line number of each node in the CFG.

GCDA (gcov data) files are created when running the code program produced with -Z profile flag. For every edge in the CFG, the GCDA stores how many times this edge has been taken.

Combining the statistics in GCDA and source information in GCNO, coverage tools can generate a branch coverage report.

Examples

GCNO and GCDA have a similar format, and are parsed using the same Reader class. The result is the Gcov structure. Complex projects will typically produce multiple GCNO and GCDA files. The statistics can be all merged into a single Graph class for analysis. Finally, an export-friendly Report structure can be derived from the Graph, to make it easy for creating a human-readable HTML report or generate data for third-party coverage collection services.

The typical usage is like:

extern crate cov;
extern crate serde_json;
use cov::{Gcov, Graph, Interner, SerializeWithInterner};

let mut interner = Interner::default();
let mut graph = Graph::default();

// merge the coverage statistics.
// note: merge all gcno before gcda.
graph.merge(Gcov::open("test-data/trivial.clang/x.gcno", &mut interner)?)?;
graph.merge(Gcov::open("test-data/trivial.rustc/x.gcno", &mut interner)?)?;

graph.merge(Gcov::open("test-data/trivial.clang/x.gcda", &mut interner)?)?;
graph.merge(Gcov::open("test-data/trivial.rustc/x.gcda", &mut interner)?)?;

// analyze the graph (if you skip this step, the report will be empty)
graph.analyze();

// produce the report.
let report = graph.report();

// serialize the report into json.
println!("{}", serde_json::to_string_pretty(&report.with_interner(&interner))?);

Dependencies

~2.3–3.5MB
~60K SLoC