1use std::collections::BTreeSet; 2use std::process::{Command, Stdio}; 3 4pub type Feature = &'static str; 5 6pub struct TestArgs { 7 pub features: BTreeSet<Feature>, 8 pub default_features: bool, 9 pub lib_only: bool, 10} 11 12impl Default for TestArgs { 13 fn default() -> Self { 14 TestArgs { 15 features: BTreeSet::new(), 16 default_features: true, 17 lib_only: false, 18 } 19 } 20} 21 22impl TestArgs { 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 41pub 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