1 use std::collections::BTreeSet;
2 use std::process::{Command, Stdio};
3
4 pub type Feature = &'static str;
5
6 pub struct TestArgs {
7 pub features: BTreeSet<Feature>,
8 pub default_features: bool,
9 pub lib_only: bool,
10 }
11
12 impl Default for TestArgs {
default() -> Self13 fn default() -> Self {
14 TestArgs {
15 features: BTreeSet::new(),
16 default_features: true,
17 lib_only: false,
18 }
19 }
20 }
21
22 impl TestArgs {
features_string(&self) -> Option<String>23 fn features_string(&self) -> Option<String> {
24 if self.features.is_empty() {
25 return None;
26 }
27
28 let s = self.features.iter().fold(String::new(), |mut s, f| {
29 if !s.is_empty() {
30 s.push(' ');
31 }
32 s.push_str(f);
33
34 s
35 });
36
37 Some(s)
38 }
39 }
40
test(args: TestArgs) -> bool41 pub fn test(args: TestArgs) -> bool {
42 let features = args.features_string();
43
44 let mut command = Command::new("cargo");
45
46 command
47 .stdout(Stdio::inherit())
48 .stderr(Stdio::inherit())
49 .arg("test")
50 .arg("--verbose");
51
52 if !args.default_features {
53 command.arg("--no-default-features");
54 }
55
56 if args.lib_only {
57 command.arg("--lib");
58 }
59
60 if let Some(features) = &features {
61 command.args(&["--features", features]);
62 }
63
64 println!("running {:?}", command);
65
66 let status = command.status().expect("Failed to execute command");
67
68 if !status.success() {
69 eprintln!(
70 "test execution failed for features: {}",
71 features.as_ref().map(AsRef::as_ref).unwrap_or("")
72 );
73 false
74 } else {
75 true
76 }
77 }
78