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
110
use super::reroot_path;
use clap::*;
use move_compiler::compiled_unit::{CompiledUnit, NamedCompiledModule};
use move_coverage::{
coverage_map::CoverageMap, format_csv_summary, format_human_summary,
source_coverage::SourceCoverageBuilder, summary::summarize_inst_cov,
};
use move_disassembler::disassembler::Disassembler;
use move_package::BuildConfig;
use std::path::PathBuf;
#[derive(Parser)]
pub enum CoverageSummaryOptions {
#[clap(name = "summary")]
Summary {
#[clap(long = "summarize-functions")]
functions: bool,
#[clap(long = "csv")]
output_csv: bool,
},
#[clap(name = "source")]
Source {
#[clap(long = "module")]
module_name: String,
},
#[clap(name = "bytecode")]
Bytecode {
#[clap(long = "module")]
module_name: String,
},
}
#[derive(Parser)]
#[clap(name = "coverage")]
pub struct Coverage {
#[clap(subcommand)]
pub options: CoverageSummaryOptions,
}
impl Coverage {
pub fn execute(self, path: Option<PathBuf>, config: BuildConfig) -> anyhow::Result<()> {
let path = reroot_path(path)?;
let coverage_map = CoverageMap::from_binary_file(path.join(".coverage_map.mvcov"))?;
let package = config.compile_package(&path, &mut Vec::new())?;
let modules: Vec<_> = package
.root_modules()
.filter_map(|unit| match &unit.unit {
CompiledUnit::Module(NamedCompiledModule { module, .. }) => Some(module.clone()),
_ => None,
})
.collect();
match self.options {
CoverageSummaryOptions::Source { module_name } => {
let unit = package.get_module_by_name_from_root(&module_name)?;
let source_path = &unit.source_path;
let (module, source_map) = match &unit.unit {
CompiledUnit::Module(NamedCompiledModule {
module, source_map, ..
}) => (module, source_map),
_ => panic!("Should all be modules"),
};
let source_coverage = SourceCoverageBuilder::new(module, &coverage_map, source_map);
source_coverage
.compute_source_coverage(source_path)
.output_source_coverage(&mut std::io::stdout())
.unwrap();
}
CoverageSummaryOptions::Summary {
functions,
output_csv,
..
} => {
let coverage_map = coverage_map.to_unified_exec_map();
if output_csv {
format_csv_summary(
modules.as_slice(),
&coverage_map,
summarize_inst_cov,
&mut std::io::stdout(),
)
} else {
format_human_summary(
modules.as_slice(),
&coverage_map,
summarize_inst_cov,
&mut std::io::stdout(),
functions,
)
}
}
CoverageSummaryOptions::Bytecode { module_name } => {
let unit = package.get_module_by_name_from_root(&module_name)?;
let mut disassembler = Disassembler::from_unit(&unit.unit);
disassembler.add_coverage_map(coverage_map.to_unified_exec_map());
println!("{}", disassembler.disassemble()?);
}
}
Ok(())
}
}