Skip to content

Commit 72f969b

Browse files
authored
Initial implementation (#42)
* Initial implementation * fmt things * Make pathbuf to be a bit easier * Move to a predicate * Add bench for subreport generation * Update changelog
1 parent da7fd26 commit 72f969b

File tree

5 files changed

+103
-3
lines changed

5 files changed

+103
-3
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Added
9+
- Added the ability to filter out certain sections from the generated coverage reports
10+
811
### Changed
912
- Now use some hashmap based caching to speedup record lookup during profile merge.
1013

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,8 @@ path = "benches/profdata_parsing.rs"
6262
name = "report_merging"
6363
harness = false
6464
path = "benches/report_merging.rs"
65+
66+
[[bench]]
67+
name = "coverage_mapping"
68+
harness = false
69+
path = "benches/coverage_mapping.rs"

benches/coverage_mapping.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use llvm_profparser::*;
3+
use std::fs;
4+
5+
// This benchmark is a bit faffy as first you need to generate the binaries and profraws and pop
6+
// them in the appropriate folder structure. After that it will work as expected
7+
8+
pub fn coverage_mapping(c: &mut Criterion) {
9+
let files = fs::read_dir("./benches/data/mapping/profraws")
10+
.unwrap()
11+
.map(|x| x.unwrap().path())
12+
.collect::<Vec<_>>();
13+
14+
let profile = merge_profiles(&files).unwrap();
15+
16+
let binaries = fs::read_dir("./benches/data/mapping/binaries")
17+
.unwrap()
18+
.map(|x| x.unwrap().path())
19+
.collect::<Vec<_>>();
20+
21+
c.bench_function("coverage mapping", |b| {
22+
b.iter(|| {
23+
let _a = CoverageMapping::new(black_box(&binaries), black_box(&profile), true).unwrap();
24+
})
25+
});
26+
}
27+
28+
pub fn report_generation(c: &mut Criterion) {
29+
let files = fs::read_dir("./benches/data/mapping/profraws")
30+
.unwrap()
31+
.map(|x| x.unwrap().path())
32+
.collect::<Vec<_>>();
33+
34+
let profile = merge_profiles(&files).unwrap();
35+
36+
let binaries = fs::read_dir("./benches/data/mapping/binaries")
37+
.unwrap()
38+
.map(|x| x.unwrap().path())
39+
.collect::<Vec<_>>();
40+
41+
let mapping = CoverageMapping::new(&binaries, &profile, true).unwrap();
42+
43+
c.bench_function("report generation", |b| {
44+
b.iter(|| {
45+
let _a = mapping.generate_report();
46+
})
47+
});
48+
}
49+
50+
pub fn subreport_generation(c: &mut Criterion) {
51+
let files = fs::read_dir("./benches/data/mapping/profraws")
52+
.unwrap()
53+
.map(|x| x.unwrap().path())
54+
.collect::<Vec<_>>();
55+
56+
let profile = merge_profiles(&files).unwrap();
57+
58+
let binaries = fs::read_dir("./benches/data/mapping/binaries")
59+
.unwrap()
60+
.map(|x| x.unwrap().path())
61+
.collect::<Vec<_>>();
62+
63+
let mapping = CoverageMapping::new(&binaries, &profile, true).unwrap();
64+
65+
c.bench_function("subreport generation", |b| {
66+
b.iter(|| {
67+
let _a = mapping.generate_subreport(|paths| {
68+
paths
69+
.iter()
70+
.any(|path| path.starts_with("/home/daniel/personal/tarpaulin/src"))
71+
});
72+
})
73+
});
74+
}
75+
76+
criterion_group!(
77+
benches,
78+
coverage_mapping,
79+
report_generation,
80+
subreport_generation
81+
);
82+
83+
criterion_main!(benches);

benches/data/mapping/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/binaries
2+
/profraws

src/coverage/coverage_mapping.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::convert::TryInto;
99
use std::error::Error;
1010
use std::fmt;
1111
use std::fs;
12-
use std::path::Path;
12+
use std::path::{Path, PathBuf};
1313
use tracing::{debug, error, trace, warn};
1414

1515
/// Stores the instrumentation profile and information from the coverage mapping sections in the
@@ -149,14 +149,17 @@ impl<'a> CoverageMapping<'a> {
149149
result
150150
}
151151

152-
pub fn generate_report(&self) -> CoverageReport {
152+
pub fn generate_subreport<P>(&self, mut predicate: P) -> CoverageReport
153+
where
154+
P: FnMut(&[PathBuf]) -> bool,
155+
{
153156
let mut report = CoverageReport::default();
154157
//let base_region_ids = info.get_simple_counters(self.profile);
155158
for info in &self.mapping_info {
156159
for func in &info.cov_fun {
157160
let base_region_ids = self.get_simple_counters(func);
158161
let paths = info.get_files_from_id(func.header.filenames_ref);
159-
if paths.is_empty() {
162+
if paths.is_empty() || !predicate(&paths) {
160163
continue;
161164
}
162165

@@ -265,6 +268,10 @@ impl<'a> CoverageMapping<'a> {
265268
}
266269
report
267270
}
271+
272+
pub fn generate_report(&self) -> CoverageReport {
273+
self.generate_subreport(|_| true)
274+
}
268275
}
269276

270277
fn parse_coverage_mapping(

0 commit comments

Comments
 (0)