1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#![allow(dead_code)]
use crate::config::Config;
use crate::errors::RunError;
use crate::process_handling::RunningProcessHandle;
use crate::source_analysis::LineAnalysis;
use crate::statemachine::*;
use crate::TestHandle;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::path::PathBuf;
use tracing::info;
pub fn create_state_machine<'a>(
test: impl Into<TestHandle>,
traces: &'a mut TraceMap,
analysis: &'a HashMap<PathBuf, LineAnalysis>,
config: &'a Config,
event_log: &'a Option<EventLog>,
) -> (TestState, LlvmInstrumentedData<'a>) {
let handle = test.into();
if let TestHandle::Process(process) = handle {
let llvm = LlvmInstrumentedData {
process: Some(process),
event_log,
config,
traces,
analysis,
};
(TestState::start_state(), llvm)
} else {
error!("The llvm cov statemachine requires a process::Child");
let invalid = LlvmInstrumentedData {
process: None,
config,
event_log,
traces,
analysis,
};
(TestState::End(1), invalid)
}
}
pub struct LlvmInstrumentedData<'a> {
process: Option<RunningProcessHandle>,
config: &'a Config,
event_log: &'a Option<EventLog>,
traces: &'a mut TraceMap,
analysis: &'a HashMap<PathBuf, LineAnalysis>,
}
impl<'a> StateData for LlvmInstrumentedData<'a> {
fn start(&mut self) -> Result<Option<TestState>, RunError> {
Ok(Some(TestState::wait_state()))
}
fn init(&mut self) -> Result<TestState, RunError> {
unreachable!();
}
fn last_wait_attempt(&mut self) -> Result<Option<TestState>, RunError> {
unreachable!();
}
fn wait(&mut self) -> Result<Option<TestState>, RunError> {
if let Some(parent) = self.process.as_mut() {
match parent.child.wait() {
Ok(exit) => {
let profraws = fs::read_dir(self.config.root())?
.into_iter()
.filter_map(Result::ok)
.filter(|x| {
x.path().is_file()
&& x.path().extension() == Some(OsStr::new("profraw"))
&& !parent.existing_profraws.contains(&x.path())
})
.map(|x| x.path())
.collect::<Vec<_>>();
info!(
"For binary: {}",
self.config.strip_base_dir(&parent.path).display()
);
for prof in &profraws {
info!("Generated: {}", self.config.strip_base_dir(prof).display());
}
self.process = None;
let code = exit.code().unwrap_or(1);
Ok(Some(TestState::End(code)))
}
Err(e) => Err(e.into()),
}
} else {
Err(RunError::TestCoverage("Test was not launched".to_string()))
}
}
fn stop(&mut self) -> Result<TestState, RunError> {
unreachable!();
}
}