use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; use std::process::{Child, Command, Stdio}; #[derive(Clone, Debug)] pub struct SicTestCommandBuilder { commands: Vec, features: Vec<&'static str>, } impl SicTestCommandBuilder { #[allow(clippy::new_without_default)] pub fn new() -> Self { SicTestCommandBuilder { commands: Vec::with_capacity(128), features: Vec::new(), } } pub fn with_feature(mut self, feature: &'static str) -> Self { self.features.push(feature); self } pub fn input>(mut self, path: S) -> Self { self.commands.push("--input".into()); self.commands.push(path.into()); self } pub fn input_from_resources>(mut self, path: S) -> Self { let path = Self::with_resources_path(path.as_ref()); self.commands.push("--input".into()); self.commands.push(path); self } pub fn glob_input>(mut self, pattern: S) -> Self { self.commands.push("--glob-input".into()); self.commands.push(pattern.into()); self } pub fn glob_input_from_resources>(mut self, path: S) -> Self { let path = Self::with_resources_path(path.as_ref()); self.commands.push("--glob-input".into()); self.commands.push(path); self } pub fn output>(mut self, path: S) -> Self { self.commands.push("--output".into()); self.commands.push(path.into()); self } pub fn output_in_target>(mut self, path: S) -> Self { let path = Self::with_target_path(path.as_ref()); self.commands.push("--output".into()); self.commands.push(path); self } pub fn glob_output>(mut self, path: S) -> Self { self.commands.push("--glob-output".into()); self.commands.push(path.into()); self } pub fn glob_output_in_target>(mut self, path: S) -> Self { let path = Self::with_target_path(path.as_ref()); self.commands.push("--glob-output".into()); self.commands.push(path); self } pub fn with_args(mut self, args: I) -> Self where I: IntoIterator, S: Into, { self.commands.extend(args.into_iter().map(|s| s.into())); self } pub fn spawn_child(self) -> Child { let mut command = Command::new("cargo"); command.arg("run"); if !self.features.is_empty() { command.arg("--features"); command.args(&self.features); } command.arg("--"); command.args(self.commands); command .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() .map_err(|err| { eprintln!( "Spawn child error for SicTestCommandBuilder:\nCommand: {:?}", command ); err }) .expect("Unable to spawn child process for SicTestCommandBuilder instance") } fn with_resources_path(path: &OsStr) -> OsString { Path::new(env!("CARGO_MANIFEST_DIR")) .join("resources") .join(path) .into_os_string() } fn with_target_path(path: &OsStr) -> OsString { Path::new(env!("CARGO_MANIFEST_DIR")) .join("target") .join(path) .into_os_string() } } pub fn setup_input_path(test_image_path: &str) -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")) .join("resources") .join(test_image_path) } pub fn setup_output_path(test_output_path: &str) -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")) .join("target") .join(test_output_path) } pub const DEFAULT_IN: &str = "rainbow_8x6.bmp"; #[allow(unused)] macro_rules! assert_not { ($e:expr) => { assert!(!$e) }; }