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
use anyhow::{bail, ensure, Context, Result};
use assert_cmd::Command;
use cargo_metadata::{Artifact, ArtifactProfile, Message, MetadataCommand};
use if_chain::if_chain;
use log::debug;
use std::io::BufReader;
use subprocess::{Exec, Redirection};
pub fn test(krate: &str, test: &str) -> Result<Command> {
let metadata = MetadataCommand::new().exec()?;
let args = [
"test",
"--package",
"test-fuzz-examples",
"--no-default-features",
"--features",
&("test-fuzz/".to_owned() + crate::serde_format().as_feature()),
"--no-run",
"--message-format=json",
];
let exec = Exec::cmd("cargo")
.cwd(metadata.workspace_root)
.args(&args)
.stdout(Redirection::Pipe);
debug!("{:?}", exec);
let mut popen = exec.clone().popen()?;
let messages = popen
.stdout
.take()
.map_or(Ok(vec![]), |stream| -> Result<_> {
let reader = BufReader::new(stream);
let messages: Vec<Message> = Message::parse_stream(reader)
.collect::<std::result::Result<_, std::io::Error>>()
.with_context(|| format!("`parse_stream` failed for `{:?}`", exec))?;
Ok(messages)
})?;
let status = popen
.wait()
.with_context(|| format!("`wait` failed for `{:?}`", popen))?;
ensure!(status.success(), "Command failed: {:?}", exec);
let messages = messages
.into_iter()
.filter_map(|message| {
if_chain! {
if let Message::CompilerArtifact(Artifact {
profile: ArtifactProfile { test: true, .. },
executable: Some(executable),
..
}) = message;
if let Some(file_name) = executable.file_name();
if file_name.starts_with(&(krate.to_owned() + "-"));
then {
Some(executable)
} else {
None
}
}
})
.collect::<Vec<_>>();
ensure!(
messages.len() <= 1,
"Found multiple executables starting with `{}`",
krate
);
if let Some(message) = messages.into_iter().next() {
let mut cmd = Command::new(message);
cmd.args(&["--exact", test]);
Ok(cmd)
} else {
bail!("Found no executables starting with `{}`", krate)
}
}
pub fn test_fuzz(target: &str) -> Result<Command> {
let mut cmd = Command::cargo_bin("cargo-test-fuzz")?;
cmd.args(&[
"test-fuzz",
"--package",
"test-fuzz-examples",
"--no-default-features",
"--features",
&("test-fuzz/".to_owned() + crate::serde_format().as_feature()),
"--exact",
"--target",
target,
]);
Ok(cmd)
}