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
mod codecov;
use codecov::Tracker;
use instruction_hooking::{InstructionHook, INSTRUCTION_HOOKS};
use std::any::{Any, TypeId};
use auxtools::*;
fn with_tracker_option<F>(f: F, create: bool)
where
F: FnOnce(&mut Tracker) {
INSTRUCTION_HOOKS.with(|hooks|{
let mut hooks_ref: std::cell::RefMut<Vec<Box<dyn InstructionHook>>> = hooks.borrow_mut();
let tracker_tid = TypeId::of::<Tracker>();
let tracker_option = hooks_ref
.iter_mut()
.find(|hook|(*hook).as_ref().type_id() == tracker_tid);
match tracker_option {
Some(existing_hook) => {
let mut_hook = existing_hook.as_mut();
let any_hook = mut_hook.as_any();
let existing_tracker = any_hook.downcast_mut::<Tracker>().unwrap();
f(existing_tracker);
},
None => {
if create {
let mut created_tracker = Tracker::new();
f(&mut created_tracker);
hooks_ref.push(Box::new(created_tracker));
}
}
}
});
}
#[hook("/proc/start_code_coverage")]
fn start_code_coverage(coverage_file: Value) {
let coverage_file_string_result = coverage_file.as_string();
if let Err(runtime) = coverage_file_string_result {
return Err(runtime);
}
let coverage_file_string = coverage_file_string_result.unwrap();
let mut init_result = false;
with_tracker_option(|tracker|{
init_result = tracker.init_context(coverage_file_string.clone());
}, true);
if !init_result {
return Err(runtime!(
"A code coverage context for {} already exists!",
coverage_file_string
));
}
Ok(Value::null())
}
#[hook("/proc/stop_code_coverage")]
fn stop_code_coverage(coverage_file: Value) {
let coverage_file_string_result = coverage_file.as_string();
if let Err(runtime) = coverage_file_string_result {
return Err(runtime);
}
let coverage_file_string = coverage_file_string_result.unwrap();
let mut result = Ok(Value::null());
with_tracker_option(|tracker|{
let inner_result = tracker.finalize_context(&coverage_file_string);
result = match inner_result {
Ok(had_entry) => {
if !had_entry {
Err(runtime!(
"A code coverage context for {} does not exist!",
coverage_file_string
))
} else {
Ok(Value::null())
}
},
Err(error) => Err(runtime!(
"A error occurred while trying to save the coverage file: {}",
error
))
}
}, false);
result
}