jugar_probar/coverage/
executor.rs1use super::{CoverageReport, Superblock, SuperblockId};
8
9#[derive(Debug, Clone)]
11pub struct SuperblockResult {
12 pub id: SuperblockId,
14 pub success: bool,
16 pub error: Option<String>,
18}
19
20#[derive(Debug)]
22pub struct CoverageExecutor {
23 superblocks: Vec<Superblock>,
25 worker_count: usize,
27 work_stealing: bool,
29}
30
31impl CoverageExecutor {
32 #[must_use]
34 pub fn new(superblocks: Vec<Superblock>) -> Self {
35 Self {
36 superblocks,
37 worker_count: num_cpus(),
38 work_stealing: true,
39 }
40 }
41
42 #[must_use]
44 pub fn with_workers(mut self, count: usize) -> Self {
45 self.worker_count = count;
46 self
47 }
48
49 #[must_use]
51 pub fn with_work_stealing(mut self, enabled: bool) -> Self {
52 self.work_stealing = enabled;
53 self
54 }
55
56 pub fn execute<F>(&self, test_fn: F) -> CoverageReport
61 where
62 F: Fn(&Superblock) -> SuperblockResult + Send + Sync,
63 {
64 let total_blocks = self.superblocks.iter().map(|sb| sb.block_count()).sum();
66
67 let mut report = CoverageReport::new(total_blocks);
68
69 for superblock in &self.superblocks {
72 let result = test_fn(superblock);
73 if result.success {
74 for block in superblock.iter() {
76 report.record_hit(*block);
77 }
78 }
79 }
80
81 report
82 }
83
84 #[must_use]
86 pub fn superblock_count(&self) -> usize {
87 self.superblocks.len()
88 }
89
90 #[must_use]
92 pub fn total_block_count(&self) -> usize {
93 self.superblocks.iter().map(|sb| sb.block_count()).sum()
94 }
95
96 #[must_use]
98 pub fn worker_count(&self) -> usize {
99 self.worker_count
100 }
101}
102
103fn num_cpus() -> usize {
105 4
107}