From 66b49e6f3dd407e2f5a810c59281ffc68ae2fb63 Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Tue, 20 Jul 2021 15:07:12 +0800 Subject: [PATCH 1/3] [tests] Change the path type to OsString for compatibility --- tests/cache_check.rs | 4 +-- tests/cache_dump.rs | 4 +-- tests/common/input_arg.rs | 3 ++- tests/common/mod.rs | 48 ++++++++++++++++++++++++++++------- tests/thin_check.rs | 4 +-- tests/thin_delta.rs | 4 +-- tests/thin_dump.rs | 4 +-- tests/thin_metadata_pack.rs | 4 +-- tests/thin_metadata_unpack.rs | 4 +-- tests/thin_repair.rs | 4 +-- tests/thin_restore.rs | 4 +-- tests/thin_rmap.rs | 4 +-- 12 files changed, 61 insertions(+), 30 deletions(-) diff --git a/tests/cache_check.rs b/tests/cache_check.rs index f89c182..6b6b668 100644 --- a/tests/cache_check.rs +++ b/tests/cache_check.rs @@ -29,8 +29,8 @@ impl<'a> Program<'a> for CacheCheck { "cache_check" } - fn path() -> &'a str { - CACHE_CHECK + fn path() -> &'a std::ffi::OsStr { + CACHE_CHECK.as_ref() } fn usage() -> &'a str { diff --git a/tests/cache_dump.rs b/tests/cache_dump.rs index a8f3754..365d69b 100644 --- a/tests/cache_dump.rs +++ b/tests/cache_dump.rs @@ -25,8 +25,8 @@ impl<'a> Program<'a> for CacheDump { "cache_dump" } - fn path() -> &'a str { - CACHE_DUMP + fn path() -> &'a std::ffi::OsStr { + CACHE_DUMP.as_ref() } fn usage() -> &'a str { diff --git a/tests/common/input_arg.rs b/tests/common/input_arg.rs index 4e096db..20feac4 100644 --- a/tests/common/input_arg.rs +++ b/tests/common/input_arg.rs @@ -53,7 +53,8 @@ pub fn test_missing_input_arg<'a, P>() -> Result<()> where P: InputProgram<'a>, { - let stderr = run_fail(P::path(), &[])?; + let args: [&str; 0] = []; + let stderr = run_fail(P::path(), &args)?; assert!(stderr.contains(P::missing_input_arg())); Ok(()) } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index a4801aa..e9dffd8 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,9 +1,11 @@ #![allow(dead_code)] use anyhow::Result; +use std::ffi::{OsStr, OsString}; use std::fs::OpenOptions; use std::io::{Read, Write}; use std::path::PathBuf; + use thinp::file_utils; use thinp::io_engine::*; @@ -104,7 +106,7 @@ pub enum ArgType { pub trait Program<'a> { fn name() -> &'a str; - fn path() -> &'a str; + fn path() -> &'a OsStr; fn usage() -> &'a str; fn arg_type() -> ArgType; @@ -134,8 +136,15 @@ pub trait BinaryOutputProgram<'a>: OutputProgram<'a> {} //------------------------------------------ // Returns stdout. The command must return zero. -pub fn run_ok(program: &str, args: &[&str]) -> Result { - let command = duct::cmd(program, args).stdout_capture().stderr_capture(); +pub fn run_ok(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); let output = command.run()?; assert!(output.status.success()); let stdout = std::str::from_utf8(&output.stdout[..]) @@ -146,16 +155,30 @@ pub fn run_ok(program: &str, args: &[&str]) -> Result { } // Returns the entire output. The command must return zero. -pub fn run_ok_raw(program: &str, args: &[&str]) -> Result { - let command = duct::cmd(program, args).stdout_capture().stderr_capture(); +pub fn run_ok_raw(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); let output = command.run()?; assert!(output.status.success()); Ok(output) } // Returns stderr, a non zero status must be returned -pub fn run_fail(program: &str, args: &[&str]) -> Result { - let command = duct::cmd(program, args).stdout_capture().stderr_capture(); +pub fn run_fail(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); let output = command.unchecked().run()?; assert!(!output.status.success()); let stderr = std::str::from_utf8(&output.stderr[..]).unwrap().to_string(); @@ -163,8 +186,15 @@ pub fn run_fail(program: &str, args: &[&str]) -> Result { } // Returns the entire output, a non zero status must be returned -pub fn run_fail_raw(program: &str, args: &[&str]) -> Result { - let command = duct::cmd(program, args).stdout_capture().stderr_capture(); +pub fn run_fail_raw(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); let output = command.unchecked().run()?; assert!(!output.status.success()); Ok(output) diff --git a/tests/thin_check.rs b/tests/thin_check.rs index 577a34d..bfe1161 100644 --- a/tests/thin_check.rs +++ b/tests/thin_check.rs @@ -31,8 +31,8 @@ impl<'a> Program<'a> for ThinCheck { "thin_check" } - fn path() -> &'a str { - THIN_CHECK + fn path() -> &'a std::ffi::OsStr { + THIN_CHECK.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_delta.rs b/tests/thin_delta.rs index c9256a8..7455f10 100644 --- a/tests/thin_delta.rs +++ b/tests/thin_delta.rs @@ -26,8 +26,8 @@ impl<'a> Program<'a> for ThinDelta { "thin_delta" } - fn path() -> &'a str { - THIN_DELTA + fn path() -> &'a std::ffi::OsStr { + THIN_DELTA.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_dump.rs b/tests/thin_dump.rs index 6d6eb11..2f1fae6 100644 --- a/tests/thin_dump.rs +++ b/tests/thin_dump.rs @@ -32,8 +32,8 @@ impl<'a> Program<'a> for ThinDump { "thin_dump" } - fn path() -> &'a str { - THIN_DUMP + fn path() -> &'a std::ffi::OsStr { + THIN_DUMP.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_metadata_pack.rs b/tests/thin_metadata_pack.rs index 616bc83..bbcb8c0 100644 --- a/tests/thin_metadata_pack.rs +++ b/tests/thin_metadata_pack.rs @@ -36,8 +36,8 @@ impl<'a> Program<'a> for ThinMetadataPack { "thin_metadata_pack" } - fn path() -> &'a str { - THIN_METADATA_PACK + fn path() -> &'a std::ffi::OsStr { + THIN_METADATA_PACK.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_metadata_unpack.rs b/tests/thin_metadata_unpack.rs index 9a66d58..3702e73 100644 --- a/tests/thin_metadata_unpack.rs +++ b/tests/thin_metadata_unpack.rs @@ -36,8 +36,8 @@ impl<'a> Program<'a> for ThinMetadataUnpack { "thin_metadata_pack" } - fn path() -> &'a str { - THIN_METADATA_UNPACK + fn path() -> &'a std::ffi::OsStr { + THIN_METADATA_UNPACK.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_repair.rs b/tests/thin_repair.rs index aa2deba..e9b3b92 100644 --- a/tests/thin_repair.rs +++ b/tests/thin_repair.rs @@ -29,8 +29,8 @@ impl<'a> Program<'a> for ThinRepair { "thin_repair" } - fn path() -> &'a str { - THIN_REPAIR + fn path() -> &'a std::ffi::OsStr { + THIN_REPAIR.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_restore.rs b/tests/thin_restore.rs index 5208d71..7408be0 100644 --- a/tests/thin_restore.rs +++ b/tests/thin_restore.rs @@ -30,8 +30,8 @@ impl<'a> Program<'a> for ThinRestore { "thin_restore" } - fn path() -> &'a str { - THIN_RESTORE + fn path() -> &'a std::ffi::OsStr { + THIN_RESTORE.as_ref() } fn usage() -> &'a str { diff --git a/tests/thin_rmap.rs b/tests/thin_rmap.rs index 1acae99..bdee4cd 100644 --- a/tests/thin_rmap.rs +++ b/tests/thin_rmap.rs @@ -26,8 +26,8 @@ impl<'a> Program<'a> for ThinRmap { "thin_rmap" } - fn path() -> &'a str { - THIN_RMAP + fn path() -> &'a std::ffi::OsStr { + THIN_RMAP.as_ref() } fn usage() -> &'a str { From 16190f0f9aa7c2098ce131c6e0f1f206bece716d Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Tue, 20 Jul 2021 17:37:55 +0800 Subject: [PATCH 2/3] [tests] Pull out common submodules New modules: fixture, process, program, target, and thin --- tests/cache_check.rs | 7 +- tests/cache_dump.rs | 6 +- tests/common/common_args.rs | 6 +- tests/common/fixture.rs | 69 +++++++ tests/common/input_arg.rs | 10 +- tests/common/mod.rs | 379 +--------------------------------- tests/common/output_option.rs | 8 +- tests/common/process.rs | 71 +++++++ tests/common/program.rs | 43 ++++ tests/common/target.rs | 79 +++++++ tests/common/thin.rs | 135 ++++++++++++ tests/thin_check.rs | 6 +- tests/thin_delta.rs | 5 +- tests/thin_dump.rs | 6 +- tests/thin_metadata_pack.rs | 4 +- tests/thin_metadata_unpack.rs | 6 +- tests/thin_repair.rs | 6 +- tests/thin_restore.rs | 6 +- tests/thin_rmap.rs | 5 +- 19 files changed, 469 insertions(+), 388 deletions(-) create mode 100644 tests/common/fixture.rs create mode 100644 tests/common/process.rs create mode 100644 tests/common/program.rs create mode 100644 tests/common/target.rs create mode 100644 tests/common/thin.rs diff --git a/tests/cache_check.rs b/tests/cache_check.rs index 6b6b668..f73c7ae 100644 --- a/tests/cache_check.rs +++ b/tests/cache_check.rs @@ -3,9 +3,12 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::fixture::*; use common::input_arg::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; //------------------------------------------ @@ -48,7 +51,7 @@ impl<'a> Program<'a> for CacheCheck { impl<'a> InputProgram<'a> for CacheCheck { fn mk_valid_input(td: &mut TestDir) -> Result { - mk_valid_md(td) + common::thin::mk_valid_md(td) // FIXME: create cache metadata } fn file_not_found() -> &'a str { diff --git a/tests/cache_dump.rs b/tests/cache_dump.rs index 365d69b..f1b0f25 100644 --- a/tests/cache_dump.rs +++ b/tests/cache_dump.rs @@ -4,8 +4,10 @@ mod common; use common::common_args::*; use common::input_arg::*; + +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; //------------------------------------------ @@ -44,7 +46,7 @@ impl<'a> Program<'a> for CacheDump { impl<'a> InputProgram<'a> for CacheDump { fn mk_valid_input(td: &mut TestDir) -> Result { - mk_valid_md(td) + common::thin::mk_valid_md(td) // FIXME: generate cache metadata } fn file_not_found() -> &'a str { diff --git a/tests/common/common_args.rs b/tests/common/common_args.rs index 41387df..095e74b 100644 --- a/tests/common/common_args.rs +++ b/tests/common/common_args.rs @@ -1,6 +1,10 @@ -use crate::common::*; +use anyhow::Result; + use thinp::version::tools_version; +use crate::common::process::*; +use crate::common::program::*; + //------------------------------------------ // help diff --git a/tests/common/fixture.rs b/tests/common/fixture.rs new file mode 100644 index 0000000..2ddc82d --- /dev/null +++ b/tests/common/fixture.rs @@ -0,0 +1,69 @@ +use anyhow::Result; +use std::fs::OpenOptions; +use std::io::{Read, Write}; +use std::path::PathBuf; + +use thinp::file_utils; + +use crate::common::test_dir::TestDir; + +//------------------------------------------ + +pub fn mk_zeroed_md(td: &mut TestDir) -> Result { + let md = td.mk_path("meta.bin"); + eprintln!("path = {:?}", md); + let _file = file_utils::create_sized_file(&md, 1024 * 1024 * 16); + Ok(md) +} + +pub fn damage_superblock(path: &PathBuf) -> Result<()> { + let mut output = OpenOptions::new().read(false).write(true).open(path)?; + let buf = [0u8; 512]; + output.write_all(&buf)?; + Ok(()) +} + +//------------------------------------------ + +pub fn md5(md: &PathBuf) -> Result { + let output = duct::cmd!("md5sum", "-b", &md).stdout_capture().run()?; + let csum = std::str::from_utf8(&output.stdout[0..])?.to_string(); + let csum = csum.split_ascii_whitespace().next().unwrap().to_string(); + Ok(csum) +} + +// This checksums the file before and after the thunk is run to +// ensure it is unchanged. +pub fn ensure_untouched(p: &PathBuf, thunk: F) -> Result<()> +where + F: Fn() -> Result<()>, +{ + let csum = md5(p)?; + thunk()?; + assert_eq!(csum, md5(p)?); + Ok(()) +} + +pub fn superblock_all_zeroes(path: &PathBuf) -> Result { + let mut input = OpenOptions::new().read(true).write(false).open(path)?; + let mut buf = vec![0; 4096]; + input.read_exact(&mut buf[0..])?; + for b in buf { + if b != 0 { + return Ok(false); + } + } + + Ok(true) +} + +pub fn ensure_superblock_zeroed(p: &PathBuf, thunk: F) -> Result<()> +where + F: Fn() -> Result<()>, +{ + thunk()?; + assert!(superblock_all_zeroes(p)?); + Ok(()) +} + +//------------------------------------------ diff --git a/tests/common/input_arg.rs b/tests/common/input_arg.rs index 20feac4..6b3e00f 100644 --- a/tests/common/input_arg.rs +++ b/tests/common/input_arg.rs @@ -1,5 +1,11 @@ +use anyhow::Result; +use thinp::file_utils; + +use crate::common::fixture::*; +use crate::common::process::*; +use crate::common::program::*; +use crate::common::test_dir::*; use crate::common::thin_xml_generator::{write_xml, FragmentedS}; -use crate::common::*; //------------------------------------------ // wrappers @@ -148,7 +154,7 @@ where let mut td = TestDir::new()?; // input an unreadable file - let input = mk_valid_md(&mut td)?; + let input = P::mk_valid_input(&mut td)?; duct::cmd!("chmod", "-r", &input).run()?; let wrapper = build_args_fn(P::arg_type())?; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index e9dffd8..a8e1717 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,380 +1,15 @@ +// suppress all the false alarms by cargo test +// https://github.com/rust-lang/rust/issues/46379 #![allow(dead_code)] -use anyhow::Result; -use std::ffi::{OsStr, OsString}; -use std::fs::OpenOptions; -use std::io::{Read, Write}; -use std::path::PathBuf; - -use thinp::file_utils; -use thinp::io_engine::*; - pub mod cache_xml_generator; pub mod common_args; +pub mod fixture; pub mod input_arg; pub mod output_option; +pub mod process; +pub mod program; +pub mod target; pub mod test_dir; +pub mod thin; pub mod thin_xml_generator; - -use crate::common::thin_xml_generator::{write_xml, SingleThinS}; -use test_dir::TestDir; - -//------------------------------------------ - -pub mod cpp_msg { - pub const FILE_NOT_FOUND: &str = "No such file or directory"; - pub const MISSING_INPUT_ARG: &str = "No input file provided"; - pub const MISSING_OUTPUT_ARG: &str = "No output file provided"; - pub const BAD_SUPERBLOCK: &str = "bad checksum in superblock"; - - pub fn bad_option_hint(option: &str) -> String { - format!("unrecognized option '{}'", option) - } -} - -pub mod rust_msg { - pub const FILE_NOT_FOUND: &str = "Couldn't find input file"; - pub const MISSING_INPUT_ARG: &str = "The following required arguments were not provided"; // TODO: be specific - pub const MISSING_OUTPUT_ARG: &str = "The following required arguments were not provided"; // TODO: be specific - pub const BAD_SUPERBLOCK: &str = "bad checksum in superblock"; - - pub fn bad_option_hint(option: &str) -> String { - format!("Found argument '{}' which wasn't expected", option) - } -} - -#[cfg(not(feature = "rust_tests"))] -pub use cpp_msg as msg; -#[cfg(feature = "rust_tests")] -pub use rust_msg as msg; - -//------------------------------------------ - -#[macro_export] -macro_rules! path_to_cpp { - ($name: literal) => { - concat!("bin/", $name) - }; -} - -#[macro_export] -macro_rules! path_to_rust { - ($name: literal) => { - env!(concat!("CARGO_BIN_EXE_", $name)) - }; -} - -#[cfg(not(feature = "rust_tests"))] -#[macro_export] -macro_rules! path_to { - ($name: literal) => { - path_to_cpp!($name) - }; -} - -#[cfg(feature = "rust_tests")] -#[macro_export] -macro_rules! path_to { - ($name: literal) => { - path_to_rust!($name) - }; -} - -//------------------------------------------ - -pub const CACHE_CHECK: &str = path_to!("cache_check"); -pub const CACHE_DUMP: &str = path_to!("cache_dump"); - -pub const THIN_CHECK: &str = path_to!("thin_check"); -pub const THIN_DELTA: &str = path_to_cpp!("thin_delta"); // TODO: rust version -pub const THIN_DUMP: &str = path_to!("thin_dump"); -pub const THIN_METADATA_PACK: &str = path_to_rust!("thin_metadata_pack"); // rust-only -pub const THIN_METADATA_UNPACK: &str = path_to_rust!("thin_metadata_unpack"); // rust-only -pub const THIN_REPAIR: &str = path_to_cpp!("thin_repair"); // TODO: rust version -pub const THIN_RESTORE: &str = path_to!("thin_restore"); -pub const THIN_RMAP: &str = path_to_cpp!("thin_rmap"); // TODO: rust version -pub const THIN_GENERATE_METADATA: &str = path_to_cpp!("thin_generate_metadata"); // cpp-only -pub const THIN_GENERATE_MAPPINGS: &str = path_to_cpp!("thin_generate_mappings"); // cpp-only -pub const THIN_GENERATE_DAMAGE: &str = path_to_cpp!("thin_generate_damage"); // cpp-only - -//------------------------------------------ - -pub enum ArgType { - InputArg, - IoOptions, -} - -pub trait Program<'a> { - fn name() -> &'a str; - fn path() -> &'a OsStr; - fn usage() -> &'a str; - fn arg_type() -> ArgType; - - // error messages - fn bad_option_hint(option: &str) -> String; -} - -pub trait InputProgram<'a>: Program<'a> { - fn mk_valid_input(td: &mut TestDir) -> Result; - - // error messages - fn missing_input_arg() -> &'a str; - fn file_not_found() -> &'a str; - fn corrupted_input() -> &'a str; -} - -pub trait BinaryInputProgram<'a>: InputProgram<'a> {} - -pub trait OutputProgram<'a>: InputProgram<'a> { - // error messages - fn missing_output_arg() -> &'a str; - fn file_not_found() -> &'a str; -} - -pub trait BinaryOutputProgram<'a>: OutputProgram<'a> {} - -//------------------------------------------ - -// Returns stdout. The command must return zero. -pub fn run_ok(program: S, args: I) -> Result -where - S: AsRef, - I: IntoIterator, - I::Item: Into, -{ - let command = duct::cmd(program.as_ref(), args) - .stdout_capture() - .stderr_capture(); - let output = command.run()?; - assert!(output.status.success()); - let stdout = std::str::from_utf8(&output.stdout[..]) - .unwrap() - .trim_end_matches(|c| c == '\n' || c == '\r') - .to_string(); - Ok(stdout) -} - -// Returns the entire output. The command must return zero. -pub fn run_ok_raw(program: S, args: I) -> Result -where - S: AsRef, - I: IntoIterator, - I::Item: Into, -{ - let command = duct::cmd(program.as_ref(), args) - .stdout_capture() - .stderr_capture(); - let output = command.run()?; - assert!(output.status.success()); - Ok(output) -} - -// Returns stderr, a non zero status must be returned -pub fn run_fail(program: S, args: I) -> Result -where - S: AsRef, - I: IntoIterator, - I::Item: Into, -{ - let command = duct::cmd(program.as_ref(), args) - .stdout_capture() - .stderr_capture(); - let output = command.unchecked().run()?; - assert!(!output.status.success()); - let stderr = std::str::from_utf8(&output.stderr[..]).unwrap().to_string(); - Ok(stderr) -} - -// Returns the entire output, a non zero status must be returned -pub fn run_fail_raw(program: S, args: I) -> Result -where - S: AsRef, - I: IntoIterator, - I::Item: Into, -{ - let command = duct::cmd(program.as_ref(), args) - .stdout_capture() - .stderr_capture(); - let output = command.unchecked().run()?; - assert!(!output.status.success()); - Ok(output) -} - -//------------------------------------------ - -pub fn mk_valid_xml(td: &mut TestDir) -> Result { - let xml = td.mk_path("meta.xml"); - let mut gen = SingleThinS::new(0, 1024, 2048, 2048); - write_xml(&xml, &mut gen)?; - Ok(xml) -} - -pub fn mk_valid_md(td: &mut TestDir) -> Result { - let xml = td.mk_path("meta.xml"); - let md = td.mk_path("meta.bin"); - - let mut gen = SingleThinS::new(0, 1024, 20480, 20480); - write_xml(&xml, &mut gen)?; - - let _file = file_utils::create_sized_file(&md, 4096 * 4096); - let args = ["-i", xml.to_str().unwrap(), "-o", md.to_str().unwrap()]; - run_ok(THIN_RESTORE, &args)?; - - Ok(md) -} - -pub fn mk_zeroed_md(td: &mut TestDir) -> Result { - let md = td.mk_path("meta.bin"); - eprintln!("path = {:?}", md); - let _file = file_utils::create_sized_file(&md, 1024 * 1024 * 16); - Ok(md) -} - -pub fn superblock_all_zeroes(path: &PathBuf) -> Result { - let mut input = OpenOptions::new().read(true).write(false).open(path)?; - let mut buf = vec![0; 4096]; - input.read_exact(&mut buf[0..])?; - for b in buf { - if b != 0 { - return Ok(false); - } - } - - Ok(true) -} - -pub fn damage_superblock(path: &PathBuf) -> Result<()> { - let mut output = OpenOptions::new().read(false).write(true).open(path)?; - let buf = [0u8; 512]; - output.write_all(&buf)?; - Ok(()) -} - -//----------------------------------------------- - -// FIXME: replace mk_valid_md with this? -pub fn prep_metadata(td: &mut TestDir) -> Result { - let md = mk_zeroed_md(td)?; - let args = [ - "-o", - md.to_str().unwrap(), - "--format", - "--nr-data-blocks", - "102400", - ]; - run_ok(THIN_GENERATE_METADATA, &args)?; - - // Create a 2GB device - let args = ["-o", md.to_str().unwrap(), "--create-thin", "1"]; - run_ok(THIN_GENERATE_METADATA, &args)?; - let args = [ - "-o", - md.to_str().unwrap(), - "--dev-id", - "1", - "--size", - "2097152", - "--rw=randwrite", - "--seq-nr=16", - ]; - run_ok(THIN_GENERATE_MAPPINGS, &args)?; - - // Take a few snapshots. - let mut snap_id = 2; - for _i in 0..10 { - // take a snapshot - let args = [ - "-o", - md.to_str().unwrap(), - "--create-snap", - &snap_id.to_string(), - "--origin", - "1", - ]; - run_ok(THIN_GENERATE_METADATA, &args)?; - - // partially overwrite the origin (64MB) - let args = [ - "-o", - md.to_str().unwrap(), - "--dev-id", - "1", - "--size", - "2097152", - "--io-size", - "131072", - "--rw=randwrite", - "--seq-nr=16", - ]; - run_ok(THIN_GENERATE_MAPPINGS, &args)?; - snap_id += 1; - } - - Ok(md) -} - -pub fn set_needs_check(md: &PathBuf) -> Result<()> { - let args = ["-o", md.to_str().unwrap(), "--set-needs-check"]; - run_ok(THIN_GENERATE_METADATA, &args)?; - Ok(()) -} - -pub fn generate_metadata_leaks( - md: &PathBuf, - nr_blocks: u64, - expected: u32, - actual: u32, -) -> Result<()> { - let args = [ - "-o", - md.to_str().unwrap(), - "--create-metadata-leaks", - "--nr-blocks", - &nr_blocks.to_string(), - "--expected", - &expected.to_string(), - "--actual", - &actual.to_string(), - ]; - run_ok(THIN_GENERATE_DAMAGE, &args)?; - - Ok(()) -} - -pub fn get_needs_check(md: &PathBuf) -> Result { - use thinp::thin::superblock::*; - - let engine = SyncIoEngine::new(&md, 1, false)?; - let sb = read_superblock(&engine, SUPERBLOCK_LOCATION)?; - Ok(sb.flags.needs_check) -} - -pub fn md5(md: &PathBuf) -> Result { - let output = duct::cmd!("md5sum", "-b", &md).stdout_capture().run()?; - let csum = std::str::from_utf8(&output.stdout[0..])?.to_string(); - let csum = csum.split_ascii_whitespace().next().unwrap().to_string(); - Ok(csum) -} - -// This checksums the file before and after the thunk is run to -// ensure it is unchanged. -pub fn ensure_untouched(p: &PathBuf, thunk: F) -> Result<()> -where - F: Fn() -> Result<()>, -{ - let csum = md5(p)?; - thunk()?; - assert_eq!(csum, md5(p)?); - Ok(()) -} - -pub fn ensure_superblock_zeroed(p: &PathBuf, thunk: F) -> Result<()> -where - F: Fn() -> Result<()>, -{ - thunk()?; - assert!(superblock_all_zeroes(p)?); - Ok(()) -} - -//------------------------------------------ diff --git a/tests/common/output_option.rs b/tests/common/output_option.rs index a5e5e7b..8cd2da1 100644 --- a/tests/common/output_option.rs +++ b/tests/common/output_option.rs @@ -1,4 +1,10 @@ -use crate::common::*; +use anyhow::Result; + +use thinp::file_utils; + +use crate::common::process::*; +use crate::common::program::*; +use crate::common::test_dir::*; //----------------------------------------- // test invalid arguments diff --git a/tests/common/process.rs b/tests/common/process.rs new file mode 100644 index 0000000..c87e2bc --- /dev/null +++ b/tests/common/process.rs @@ -0,0 +1,71 @@ +use anyhow::Result; +use std::ffi::{OsStr, OsString}; + +//------------------------------------------ + +// Returns stdout. The command must return zero. +pub fn run_ok(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); + let output = command.run()?; + assert!(output.status.success()); + let stdout = std::str::from_utf8(&output.stdout[..]) + .unwrap() + .trim_end_matches(|c| c == '\n' || c == '\r') + .to_string(); + Ok(stdout) +} + +// Returns the entire output. The command must return zero. +pub fn run_ok_raw(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); + let output = command.run()?; + assert!(output.status.success()); + Ok(output) +} + +// Returns stderr, a non zero status must be returned +pub fn run_fail(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); + let output = command.unchecked().run()?; + assert!(!output.status.success()); + let stderr = std::str::from_utf8(&output.stderr[..]).unwrap().to_string(); + Ok(stderr) +} + +// Returns the entire output, a non zero status must be returned +pub fn run_fail_raw(program: S, args: I) -> Result +where + S: AsRef, + I: IntoIterator, + I::Item: Into, +{ + let command = duct::cmd(program.as_ref(), args) + .stdout_capture() + .stderr_capture(); + let output = command.unchecked().run()?; + assert!(!output.status.success()); + Ok(output) +} + +//------------------------------------------ diff --git a/tests/common/program.rs b/tests/common/program.rs new file mode 100644 index 0000000..51b63e9 --- /dev/null +++ b/tests/common/program.rs @@ -0,0 +1,43 @@ +use anyhow::Result; +use std::ffi::OsStr; +use std::path::PathBuf; + +use crate::common::test_dir::TestDir; + +//------------------------------------------ + +pub enum ArgType { + InputArg, + IoOptions, +} + +pub trait Program<'a> { + fn name() -> &'a str; + fn path() -> &'a OsStr; + fn usage() -> &'a str; + fn arg_type() -> ArgType; + + // error messages + fn bad_option_hint(option: &str) -> String; +} + +pub trait InputProgram<'a>: Program<'a> { + fn mk_valid_input(td: &mut TestDir) -> Result; + + // error messages + fn missing_input_arg() -> &'a str; + fn file_not_found() -> &'a str; + fn corrupted_input() -> &'a str; +} + +pub trait BinaryInputProgram<'a>: InputProgram<'a> {} + +pub trait OutputProgram<'a>: InputProgram<'a> { + // error messages + fn missing_output_arg() -> &'a str; + fn file_not_found() -> &'a str; +} + +pub trait BinaryOutputProgram<'a>: OutputProgram<'a> {} + +//------------------------------------------ diff --git a/tests/common/target.rs b/tests/common/target.rs new file mode 100644 index 0000000..65885bc --- /dev/null +++ b/tests/common/target.rs @@ -0,0 +1,79 @@ +//------------------------------------------ + +#[macro_export] +macro_rules! path_to_cpp { + ($name: literal) => { + concat!("bin/", $name) + }; +} + +#[macro_export] +macro_rules! path_to_rust { + ($name: literal) => { + env!(concat!("CARGO_BIN_EXE_", $name)) + }; +} + +#[cfg(not(feature = "rust_tests"))] +#[macro_export] +macro_rules! path_to { + ($name: literal) => { + path_to_cpp!($name) + }; +} + +#[cfg(feature = "rust_tests")] +#[macro_export] +macro_rules! path_to { + ($name: literal) => { + path_to_rust!($name) + }; +} + +//------------------------------------------ + +pub const CACHE_CHECK: &str = path_to!("cache_check"); +pub const CACHE_DUMP: &str = path_to!("cache_dump"); + +pub const THIN_CHECK: &str = path_to!("thin_check"); +pub const THIN_DELTA: &str = path_to_cpp!("thin_delta"); // TODO: rust version +pub const THIN_DUMP: &str = path_to!("thin_dump"); +pub const THIN_METADATA_PACK: &str = path_to_rust!("thin_metadata_pack"); // rust-only +pub const THIN_METADATA_UNPACK: &str = path_to_rust!("thin_metadata_unpack"); // rust-only +pub const THIN_REPAIR: &str = path_to_cpp!("thin_repair"); // TODO: rust version +pub const THIN_RESTORE: &str = path_to!("thin_restore"); +pub const THIN_RMAP: &str = path_to_cpp!("thin_rmap"); // TODO: rust version +pub const THIN_GENERATE_METADATA: &str = path_to_cpp!("thin_generate_metadata"); // cpp-only +pub const THIN_GENERATE_MAPPINGS: &str = path_to_cpp!("thin_generate_mappings"); // cpp-only +pub const THIN_GENERATE_DAMAGE: &str = path_to_cpp!("thin_generate_damage"); // cpp-only + +//------------------------------------------ + +pub mod cpp_msg { + pub const FILE_NOT_FOUND: &str = "No such file or directory"; + pub const MISSING_INPUT_ARG: &str = "No input file provided"; + pub const MISSING_OUTPUT_ARG: &str = "No output file provided"; + pub const BAD_SUPERBLOCK: &str = "bad checksum in superblock"; + + pub fn bad_option_hint(option: &str) -> String { + format!("unrecognized option '{}'", option) + } +} + +pub mod rust_msg { + pub const FILE_NOT_FOUND: &str = "Couldn't find input file"; + pub const MISSING_INPUT_ARG: &str = "The following required arguments were not provided"; // TODO: be specific + pub const MISSING_OUTPUT_ARG: &str = "The following required arguments were not provided"; // TODO: be specific + pub const BAD_SUPERBLOCK: &str = "bad checksum in superblock"; + + pub fn bad_option_hint(option: &str) -> String { + format!("Found argument '{}' which wasn't expected", option) + } +} + +#[cfg(not(feature = "rust_tests"))] +pub use cpp_msg as msg; +#[cfg(feature = "rust_tests")] +pub use rust_msg as msg; + +//------------------------------------------ diff --git a/tests/common/thin.rs b/tests/common/thin.rs new file mode 100644 index 0000000..0004f2d --- /dev/null +++ b/tests/common/thin.rs @@ -0,0 +1,135 @@ +use anyhow::Result; +use std::path::PathBuf; + +use thinp::file_utils; +use thinp::io_engine::*; + +use crate::common::fixture::*; +use crate::common::process::*; +use crate::common::target::*; +use crate::common::test_dir::TestDir; +use crate::common::thin_xml_generator::{write_xml, SingleThinS}; + +//----------------------------------------------- + +pub fn mk_valid_xml(td: &mut TestDir) -> Result { + let xml = td.mk_path("meta.xml"); + let mut gen = SingleThinS::new(0, 1024, 2048, 2048); + write_xml(&xml, &mut gen)?; + Ok(xml) +} + +pub fn mk_valid_md(td: &mut TestDir) -> Result { + let xml = td.mk_path("meta.xml"); + let md = td.mk_path("meta.bin"); + + let mut gen = SingleThinS::new(0, 1024, 20480, 20480); + write_xml(&xml, &mut gen)?; + + let _file = file_utils::create_sized_file(&md, 4096 * 4096); + let args = ["-i", xml.to_str().unwrap(), "-o", md.to_str().unwrap()]; + run_ok(THIN_RESTORE, &args)?; + + Ok(md) +} + +//----------------------------------------------- + +// FIXME: replace mk_valid_md with this? +pub fn prep_metadata(td: &mut TestDir) -> Result { + let md = mk_zeroed_md(td)?; + let args = [ + "-o", + md.to_str().unwrap(), + "--format", + "--nr-data-blocks", + "102400", + ]; + run_ok(THIN_GENERATE_METADATA, &args)?; + + // Create a 2GB device + let args = ["-o", md.to_str().unwrap(), "--create-thin", "1"]; + run_ok(THIN_GENERATE_METADATA, &args)?; + let args = [ + "-o", + md.to_str().unwrap(), + "--dev-id", + "1", + "--size", + "2097152", + "--rw=randwrite", + "--seq-nr=16", + ]; + run_ok(THIN_GENERATE_MAPPINGS, &args)?; + + // Take a few snapshots. + let mut snap_id = 2; + for _i in 0..10 { + // take a snapshot + let args = [ + "-o", + md.to_str().unwrap(), + "--create-snap", + &snap_id.to_string(), + "--origin", + "1", + ]; + run_ok(THIN_GENERATE_METADATA, &args)?; + + // partially overwrite the origin (64MB) + let args = [ + "-o", + md.to_str().unwrap(), + "--dev-id", + "1", + "--size", + "2097152", + "--io-size", + "131072", + "--rw=randwrite", + "--seq-nr=16", + ]; + run_ok(THIN_GENERATE_MAPPINGS, &args)?; + snap_id += 1; + } + + Ok(md) +} + +pub fn set_needs_check(md: &PathBuf) -> Result<()> { + let args = ["-o", md.to_str().unwrap(), "--set-needs-check"]; + run_ok(THIN_GENERATE_METADATA, &args)?; + Ok(()) +} + +pub fn generate_metadata_leaks( + md: &PathBuf, + nr_blocks: u64, + expected: u32, + actual: u32, +) -> Result<()> { + let args = [ + "-o", + md.to_str().unwrap(), + "--create-metadata-leaks", + "--nr-blocks", + &nr_blocks.to_string(), + "--expected", + &expected.to_string(), + "--actual", + &actual.to_string(), + ]; + run_ok(THIN_GENERATE_DAMAGE, &args)?; + + Ok(()) +} + +pub fn get_needs_check(md: &PathBuf) -> Result { + use thinp::thin::superblock::*; + + let engine = SyncIoEngine::new(&md, 1, false)?; + let sb = read_superblock(&engine, SUPERBLOCK_LOCATION)?; + Ok(sb.flags.needs_check) +} + +//----------------------------------------------- diff --git a/tests/thin_check.rs b/tests/thin_check.rs index bfe1161..7b166a7 100644 --- a/tests/thin_check.rs +++ b/tests/thin_check.rs @@ -3,9 +3,13 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::fixture::*; use common::input_arg::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_delta.rs b/tests/thin_delta.rs index 7455f10..63e0ce8 100644 --- a/tests/thin_delta.rs +++ b/tests/thin_delta.rs @@ -3,8 +3,11 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_dump.rs b/tests/thin_dump.rs index 2f1fae6..ae11219 100644 --- a/tests/thin_dump.rs +++ b/tests/thin_dump.rs @@ -6,9 +6,13 @@ use std::str::from_utf8; mod common; use common::common_args::*; +use common::fixture::*; use common::input_arg::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_metadata_pack.rs b/tests/thin_metadata_pack.rs index bbcb8c0..dea1eff 100644 --- a/tests/thin_metadata_pack.rs +++ b/tests/thin_metadata_pack.rs @@ -5,8 +5,10 @@ mod common; use common::common_args::*; use common::input_arg::*; use common::output_option::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_metadata_unpack.rs b/tests/thin_metadata_unpack.rs index 3702e73..5cd8966 100644 --- a/tests/thin_metadata_unpack.rs +++ b/tests/thin_metadata_unpack.rs @@ -3,10 +3,14 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::fixture::*; use common::input_arg::*; use common::output_option::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_repair.rs b/tests/thin_repair.rs index e9b3b92..e7a3ef3 100644 --- a/tests/thin_repair.rs +++ b/tests/thin_repair.rs @@ -3,10 +3,14 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::fixture::*; use common::input_arg::*; use common::output_option::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_restore.rs b/tests/thin_restore.rs index 7408be0..7da5cbf 100644 --- a/tests/thin_restore.rs +++ b/tests/thin_restore.rs @@ -3,10 +3,14 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::fixture::*; use common::input_arg::*; use common::output_option::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ diff --git a/tests/thin_rmap.rs b/tests/thin_rmap.rs index bdee4cd..1fa2a66 100644 --- a/tests/thin_rmap.rs +++ b/tests/thin_rmap.rs @@ -3,8 +3,11 @@ use anyhow::Result; mod common; use common::common_args::*; +use common::process::*; +use common::program::*; +use common::target::*; use common::test_dir::*; -use common::*; +use common::thin::*; //------------------------------------------ From 222b4f09024f82390c0535c0915ce38f4488ee7a Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Wed, 21 Jul 2021 02:11:46 +0800 Subject: [PATCH 3/3] [tests] Do not perform Path to str conversion for compatibility --- tests/cache_check.rs | 4 +- tests/common/common_args.rs | 11 +++--- tests/common/input_arg.rs | 37 +++++++++--------- tests/common/output_option.rs | 30 +++------------ tests/common/process.rs | 11 ++++++ tests/common/thin.rs | 50 +++++++++++-------------- tests/thin_check.rs | 70 +++++++++++++---------------------- tests/thin_delta.rs | 6 +-- tests/thin_dump.rs | 35 ++++++++---------- tests/thin_metadata_unpack.rs | 11 ++---- tests/thin_repair.rs | 37 +++++------------- tests/thin_restore.rs | 10 ++--- tests/thin_rmap.rs | 15 ++------ 13 files changed, 131 insertions(+), 196 deletions(-) diff --git a/tests/cache_check.rs b/tests/cache_check.rs index f73c7ae..d729542 100644 --- a/tests/cache_check.rs +++ b/tests/cache_check.rs @@ -90,7 +90,7 @@ test_corrupted_input_data!(CacheCheck); fn failing_q() -> Result<()> { let mut td = TestDir::new()?; let md = mk_zeroed_md(&mut td)?; - let output = run_fail_raw(CACHE_CHECK, &["-q", md.to_str().unwrap()])?; + let output = run_fail_raw(CACHE_CHECK, args!["-q", &md])?; assert_eq!(output.stdout.len(), 0); assert_eq!(output.stderr.len(), 0); Ok(()) @@ -100,7 +100,7 @@ fn failing_q() -> Result<()> { fn failing_quiet() -> Result<()> { let mut td = TestDir::new()?; let md = mk_zeroed_md(&mut td)?; - let output = run_fail_raw(CACHE_CHECK, &["--quiet", md.to_str().unwrap()])?; + let output = run_fail_raw(CACHE_CHECK, args!["--quiet", &md])?; assert_eq!(output.stdout.len(), 0); assert_eq!(output.stderr.len(), 0); Ok(()) diff --git a/tests/common/common_args.rs b/tests/common/common_args.rs index 095e74b..a0cba34 100644 --- a/tests/common/common_args.rs +++ b/tests/common/common_args.rs @@ -2,6 +2,7 @@ use anyhow::Result; use thinp::version::tools_version; +use crate::args; use crate::common::process::*; use crate::common::program::*; @@ -12,7 +13,7 @@ pub fn test_help_short<'a, P>() -> Result<()> where P: Program<'a>, { - let stdout = run_ok(P::path(), &["-h"])?; + let stdout = run_ok(P::path(), args!["-h"])?; assert_eq!(stdout, P::usage()); Ok(()) } @@ -21,7 +22,7 @@ pub fn test_help_long<'a, P>() -> Result<()> where P: Program<'a>, { - let stdout = run_ok(P::path(), &["--help"])?; + let stdout = run_ok(P::path(), args!["--help"])?; assert_eq!(stdout, P::usage()); Ok(()) } @@ -48,7 +49,7 @@ pub fn test_version_short<'a, P>() -> Result<()> where P: Program<'a>, { - let stdout = run_ok(P::path(), &["-V"])?; + let stdout = run_ok(P::path(), args!["-V"])?; assert!(stdout.contains(tools_version())); Ok(()) } @@ -57,7 +58,7 @@ pub fn test_version_long<'a, P>() -> Result<()> where P: Program<'a>, { - let stdout = run_ok(P::path(), &["--version"])?; + let stdout = run_ok(P::path(), args!["--version"])?; assert!(stdout.contains(tools_version())); Ok(()) } @@ -84,7 +85,7 @@ where P: Program<'a>, { let option = "--hedgehogs-only"; - let stderr = run_fail(P::path(), &[option])?; + let stderr = run_fail(P::path(), args![option])?; assert!(stderr.contains(&P::bad_option_hint(option))); Ok(()) } diff --git a/tests/common/input_arg.rs b/tests/common/input_arg.rs index 6b3e00f..1dc377a 100644 --- a/tests/common/input_arg.rs +++ b/tests/common/input_arg.rs @@ -1,6 +1,9 @@ use anyhow::Result; +use std::ffi::OsStr; + use thinp::file_utils; +use crate::args; use crate::common::fixture::*; use crate::common::process::*; use crate::common::program::*; @@ -10,38 +13,38 @@ use crate::common::thin_xml_generator::{write_xml, FragmentedS}; //------------------------------------------ // wrappers -type ArgsBuilder = fn(&mut TestDir, &str, &dyn Fn(&[&str]) -> Result<()>) -> Result<()>; +type ArgsBuilder = fn(&mut TestDir, &OsStr, &dyn Fn(&[&OsStr]) -> Result<()>) -> Result<()>; fn with_output_md_untouched( td: &mut TestDir, - input: &str, - thunk: &dyn Fn(&[&str]) -> Result<()>, + input: &OsStr, + thunk: &dyn Fn(&[&OsStr]) -> Result<()>, ) -> Result<()> { let output = mk_zeroed_md(td)?; ensure_untouched(&output, || { - let args = ["-i", input, "-o", output.to_str().unwrap()]; + let args = args!["-i", input, "-o", &output]; thunk(&args) }) } fn with_output_superblock_zeroed( td: &mut TestDir, - input: &str, - thunk: &dyn Fn(&[&str]) -> Result<()>, + input: &OsStr, + thunk: &dyn Fn(&[&OsStr]) -> Result<()>, ) -> Result<()> { let output = mk_zeroed_md(td)?; ensure_superblock_zeroed(&output, || { - let args = ["-i", input, "-o", output.to_str().unwrap()]; + let args = args!["-i", input, "-o", &output]; thunk(&args) }) } fn input_arg_only( _td: &mut TestDir, - input: &str, - thunk: &dyn Fn(&[&str]) -> Result<()>, + input: &OsStr, + thunk: &dyn Fn(&[&OsStr]) -> Result<()>, ) -> Result<()> { - let args = [input]; + let args = args![input]; thunk(&args) } @@ -82,7 +85,7 @@ where let mut td = TestDir::new()?; let output = mk_zeroed_md(&mut td)?; ensure_untouched(&output, || { - let args = ["-o", output.to_str().unwrap()]; + let args = args!["-o", &output]; let stderr = run_fail(P::path(), &args)?; assert!(stderr.contains(P::missing_input_arg())); Ok(()) @@ -106,7 +109,7 @@ where let mut td = TestDir::new()?; let wrapper = build_args_fn(P::arg_type())?; - wrapper(&mut td, "no-such-file", &|args: &[&str]| { + wrapper(&mut td, "no-such-file".as_ref(), &|args: &[&OsStr]| { let stderr = run_fail(P::path(), args)?; assert!(stderr.contains(P::file_not_found())); Ok(()) @@ -130,7 +133,7 @@ where let mut td = TestDir::new()?; let wrapper = build_args_fn(P::arg_type())?; - wrapper(&mut td, "/tmp", &|args: &[&str]| { + wrapper(&mut td, "/tmp".as_ref(), &|args: &[&OsStr]| { let stderr = run_fail(P::path(), args)?; assert!(stderr.contains("Not a block device or regular file")); Ok(()) @@ -158,7 +161,7 @@ where duct::cmd!("chmod", "-r", &input).run()?; let wrapper = build_args_fn(P::arg_type())?; - wrapper(&mut td, input.to_str().unwrap(), &|args: &[&str]| { + wrapper(&mut td, input.as_ref(), &|args: &[&OsStr]| { let stderr = run_fail(P::path(), args)?; assert!(stderr.contains("Permission denied")); Ok(()) @@ -188,7 +191,7 @@ where file_utils::create_sized_file(&input, 1024)?; let wrapper = build_args_fn(P::arg_type())?; - wrapper(&mut td, input.to_str().unwrap(), &|args: &[&str]| { + wrapper(&mut td, input.as_ref(), &|args: &[&OsStr]| { let stderr = run_fail(P::path(), args)?; assert!(stderr.contains("Metadata device/file too small. Is this binary metadata?")); Ok(()) @@ -217,7 +220,7 @@ where write_xml(&input, &mut gen)?; let wrapper = build_args_fn(P::arg_type())?; - wrapper(&mut td, input.to_str().unwrap(), &|args: &[&str]| { + wrapper(&mut td, input.as_ref(), &|args: &[&OsStr]| { let stderr = run_fail(P::path(), args)?; eprintln!("{}", stderr); let msg = format!( @@ -250,7 +253,7 @@ where ArgType::InputArg => input_arg_only, ArgType::IoOptions => with_output_superblock_zeroed, }; - wrapper(&mut td, input.to_str().unwrap(), &|args: &[&str]| { + wrapper(&mut td, input.as_ref(), &|args: &[&OsStr]| { let stderr = run_fail(P::path(), args)?; assert!(stderr.contains(P::corrupted_input())); Ok(()) diff --git a/tests/common/output_option.rs b/tests/common/output_option.rs index 8cd2da1..e4e7695 100644 --- a/tests/common/output_option.rs +++ b/tests/common/output_option.rs @@ -2,6 +2,7 @@ use anyhow::Result; use thinp::file_utils; +use crate::args; use crate::common::process::*; use crate::common::program::*; use crate::common::test_dir::*; @@ -15,7 +16,7 @@ where { let mut td = TestDir::new()?; let input = P::mk_valid_input(&mut td)?; - let stderr = run_fail(P::path(), &["-i", input.to_str().unwrap()])?; + let stderr = run_fail(P::path(), args!["-i", &input])?; assert!(stderr.contains(P::missing_output_arg())); Ok(()) } @@ -36,10 +37,7 @@ where { let mut td = TestDir::new()?; let input = P::mk_valid_input(&mut td)?; - let stderr = run_fail( - P::path(), - &["-i", input.to_str().unwrap(), "-o", "no-such-file"], - )?; + let stderr = run_fail(P::path(), args!["-i", &input, "-o", "no-such-file"])?; assert!(stderr.contains(

::file_not_found())); Ok(()) } @@ -60,7 +58,7 @@ where { let mut td = TestDir::new()?; let input = P::mk_valid_input(&mut td)?; - let stderr = run_fail(P::path(), &["-i", input.to_str().unwrap(), "-o", "/tmp"])?; + let stderr = run_fail(P::path(), args!["-i", &input, "-o", "/tmp"])?; assert!(stderr.contains("Not a block device or regular file")); Ok(()) } @@ -86,15 +84,7 @@ where let _file = file_utils::create_sized_file(&output, 4096); duct::cmd!("chmod", "-w", &output).run()?; - let stderr = run_fail( - P::path(), - &[ - "-i", - input.to_str().unwrap(), - "-o", - output.to_str().unwrap(), - ], - )?; + let stderr = run_fail(P::path(), args!["-i", &input, "-o", &output])?; assert!(stderr.contains("Permission denied")); Ok(()) } @@ -123,15 +113,7 @@ where let output = td.mk_path("meta.bin"); let _file = file_utils::create_sized_file(&output, 4096); - let stderr = run_fail( - P::path(), - &[ - "-i", - input.to_str().unwrap(), - "-o", - output.to_str().unwrap(), - ], - )?; + let stderr = run_fail(P::path(), args!["-i", &input, "-o", &output])?; assert!(stderr.contains("Output file too small")); Ok(()) } diff --git a/tests/common/process.rs b/tests/common/process.rs index c87e2bc..a5da6d2 100644 --- a/tests/common/process.rs +++ b/tests/common/process.rs @@ -3,6 +3,17 @@ use std::ffi::{OsStr, OsString}; //------------------------------------------ +#[macro_export] +macro_rules! args { + ( $( $arg: expr ),* ) => { + { + use std::ffi::OsStr; + let args = [$( OsStr::new($arg) ),*]; + args + } + }; +} + // Returns stdout. The command must return zero. pub fn run_ok(program: S, args: I) -> Result where diff --git a/tests/common/thin.rs b/tests/common/thin.rs index 0004f2d..685e59f 100644 --- a/tests/common/thin.rs +++ b/tests/common/thin.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use thinp::file_utils; use thinp::io_engine::*; +use crate::args; use crate::common::fixture::*; use crate::common::process::*; use crate::common::target::*; @@ -27,7 +28,7 @@ pub fn mk_valid_md(td: &mut TestDir) -> Result { write_xml(&xml, &mut gen)?; let _file = file_utils::create_sized_file(&md, 4096 * 4096); - let args = ["-i", xml.to_str().unwrap(), "-o", md.to_str().unwrap()]; + let args = args!["-i", &xml, "-o", &md]; run_ok(THIN_RESTORE, &args)?; Ok(md) @@ -38,27 +39,21 @@ pub fn mk_valid_md(td: &mut TestDir) -> Result { // FIXME: replace mk_valid_md with this? pub fn prep_metadata(td: &mut TestDir) -> Result { let md = mk_zeroed_md(td)?; - let args = [ - "-o", - md.to_str().unwrap(), - "--format", - "--nr-data-blocks", - "102400", - ]; + let args = args!["-o", &md, "--format", "--nr-data-blocks", "102400"]; run_ok(THIN_GENERATE_METADATA, &args)?; // Create a 2GB device - let args = ["-o", md.to_str().unwrap(), "--create-thin", "1"]; + let args = args!["-o", &md, "--create-thin", "1"]; run_ok(THIN_GENERATE_METADATA, &args)?; - let args = [ + let args = args![ "-o", - md.to_str().unwrap(), + &md, "--dev-id", "1", "--size", "2097152", "--rw=randwrite", - "--seq-nr=16", + "--seq-nr=16" ]; run_ok(THIN_GENERATE_MAPPINGS, &args)?; @@ -66,20 +61,14 @@ pub fn prep_metadata(td: &mut TestDir) -> Result { let mut snap_id = 2; for _i in 0..10 { // take a snapshot - let args = [ - "-o", - md.to_str().unwrap(), - "--create-snap", - &snap_id.to_string(), - "--origin", - "1", - ]; + let snap_id_str = snap_id.to_string(); + let args = args!["-o", &md, "--create-snap", &snap_id_str, "--origin", "1"]; run_ok(THIN_GENERATE_METADATA, &args)?; // partially overwrite the origin (64MB) - let args = [ + let args = args![ "-o", - md.to_str().unwrap(), + &md, "--dev-id", "1", "--size", @@ -87,7 +76,7 @@ pub fn prep_metadata(td: &mut TestDir) -> Result { "--io-size", "131072", "--rw=randwrite", - "--seq-nr=16", + "--seq-nr=16" ]; run_ok(THIN_GENERATE_MAPPINGS, &args)?; snap_id += 1; @@ -97,7 +86,7 @@ pub fn prep_metadata(td: &mut TestDir) -> Result { } pub fn set_needs_check(md: &PathBuf) -> Result<()> { - let args = ["-o", md.to_str().unwrap(), "--set-needs-check"]; + let args = args!["-o", &md, "--set-needs-check"]; run_ok(THIN_GENERATE_METADATA, &args)?; Ok(()) } @@ -108,16 +97,19 @@ pub fn generate_metadata_leaks( expected: u32, actual: u32, ) -> Result<()> { - let args = [ + let nr_blocks_str = nr_blocks.to_string(); + let expected_str = expected.to_string(); + let actual_str = actual.to_string(); + let args = args![ "-o", - md.to_str().unwrap(), + &md, "--create-metadata-leaks", "--nr-blocks", - &nr_blocks.to_string(), + &nr_blocks_str, "--expected", - &expected.to_string(), + &expected_str, "--actual", - &actual.to_string(), + &actual_str ]; run_ok(THIN_GENERATE_DAMAGE, &args)?; diff --git a/tests/thin_check.rs b/tests/thin_check.rs index 7b166a7..1f1db46 100644 --- a/tests/thin_check.rs +++ b/tests/thin_check.rs @@ -93,8 +93,7 @@ test_corrupted_input_data!(ThinCheck); fn accepts_flag(flag: &str) -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - run_ok(THIN_CHECK, &[flag, md_path])?; + run_ok(THIN_CHECK, args![flag, &md])?; Ok(()) } @@ -130,9 +129,8 @@ fn accepts_auto_repair() -> Result<()> { fn accepts_quiet() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - let output = run_ok_raw(THIN_CHECK, &["--quiet", md_path])?; + let output = run_ok_raw(THIN_CHECK, args!["--quiet", &md])?; assert_eq!(output.stdout.len(), 0); assert_eq!(output.stderr.len(), 0); Ok(()) @@ -145,8 +143,7 @@ fn accepts_quiet() -> Result<()> { fn detects_corrupt_superblock_with_superblock_only() -> Result<()> { let mut td = TestDir::new()?; let md = mk_zeroed_md(&mut td)?; - let md_path = md.to_str().unwrap(); - let _stderr = run_fail(THIN_CHECK, &["--super-block-only", md_path])?; + let _stderr = run_fail(THIN_CHECK, args!["--super-block-only", &md])?; Ok(()) } @@ -157,8 +154,7 @@ fn detects_corrupt_superblock_with_superblock_only() -> Result<()> { fn prints_info_fields() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - let stdout = run_ok(THIN_CHECK, &[md_path])?; + let stdout = run_ok(THIN_CHECK, args![&md])?; assert!(stdout.contains("TRANSACTION_ID=")); assert!(stdout.contains("METADATA_FREE_BLOCKS=")); Ok(()) @@ -171,20 +167,19 @@ fn prints_info_fields() -> Result<()> { fn auto_repair_incompatible_opts() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - run_fail(THIN_CHECK, &["--auto-repair", "-m", md_path])?; + run_fail(THIN_CHECK, args!["--auto-repair", "-m", &md])?; run_fail( THIN_CHECK, - &["--auto-repair", "--override-mapping-root", "123", md_path], + args!["--auto-repair", "--override-mapping-root", "123", &md], )?; run_fail( THIN_CHECK, - &["--auto-repair", "--super-block-only", md_path], + args!["--auto-repair", "--super-block-only", &md], )?; - run_fail(THIN_CHECK, &["--auto-repair", "--skip-mappings", md_path])?; + run_fail(THIN_CHECK, args!["--auto-repair", "--skip-mappings", &md])?; run_fail( THIN_CHECK, - &["--auto-repair", "--ignore-non-fatal-errors", md_path], + args!["--auto-repair", "--ignore-non-fatal-errors", &md], )?; Ok(()) } @@ -193,28 +188,23 @@ fn auto_repair_incompatible_opts() -> Result<()> { fn clear_needs_check_incompatible_opts() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - run_fail(THIN_CHECK, &["--clear-needs-check-flag", "-m", md_path])?; + run_fail(THIN_CHECK, args!["--clear-needs-check-flag", "-m", &md])?; run_fail( THIN_CHECK, - &[ + args![ "--clear-needs-check-flag", "--override-mapping-root", "123", - md_path, + &md ], )?; run_fail( THIN_CHECK, - &["--clear-needs-check-flag", "--super-block-only", md_path], + args!["--clear-needs-check-flag", "--super-block-only", &md], )?; run_fail( THIN_CHECK, - &[ - "--clear-needs-check-flag", - "--ignore-non-fatal-errors", - md_path, - ], + args!["--clear-needs-check-flag", "--ignore-non-fatal-errors", &md], )?; Ok(()) } @@ -226,12 +216,11 @@ fn clear_needs_check_incompatible_opts() -> Result<()> { fn clear_needs_check() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); set_needs_check(&md)?; assert!(get_needs_check(&md)?); - run_ok(THIN_CHECK, &["--clear-needs-check-flag", md_path])?; + run_ok(THIN_CHECK, args!["--clear-needs-check-flag", &md])?; assert!(!get_needs_check(&md)?); Ok(()) } @@ -240,11 +229,10 @@ fn clear_needs_check() -> Result<()> { fn no_clear_needs_check_if_error() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); set_needs_check(&md)?; generate_metadata_leaks(&md, 1, 0, 1)?; - run_fail(THIN_CHECK, &["--clear-needs-check-flag", md_path])?; + run_fail(THIN_CHECK, args!["--clear-needs-check-flag", &md])?; assert!(get_needs_check(&md)?); Ok(()) } @@ -253,7 +241,6 @@ fn no_clear_needs_check_if_error() -> Result<()> { fn clear_needs_check_if_skip_mappings() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); set_needs_check(&md)?; generate_metadata_leaks(&md, 1, 0, 1)?; @@ -261,7 +248,7 @@ fn clear_needs_check_if_skip_mappings() -> Result<()> { assert!(get_needs_check(&md)?); run_ok( THIN_CHECK, - &["--clear-needs-check-flag", "--skip-mappings", md_path], + args!["--clear-needs-check-flag", "--skip-mappings", &md], )?; assert!(!get_needs_check(&md)?); Ok(()) @@ -274,10 +261,9 @@ fn clear_needs_check_if_skip_mappings() -> Result<()> { fn metadata_leaks_are_non_fatal() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); generate_metadata_leaks(&md, 1, 0, 1)?; - run_fail(THIN_CHECK, &[md_path])?; - run_ok(THIN_CHECK, &["--ignore-non-fatal-errors", md_path])?; + run_fail(THIN_CHECK, args![&md])?; + run_ok(THIN_CHECK, args!["--ignore-non-fatal-errors", &md])?; Ok(()) } @@ -285,11 +271,10 @@ fn metadata_leaks_are_non_fatal() -> Result<()> { fn fatal_errors_cant_be_ignored() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); generate_metadata_leaks(&md, 1, 1, 0)?; ensure_untouched(&md, || { - run_fail(THIN_CHECK, &["--ignore-non-fatal-errors", md_path])?; + run_fail(THIN_CHECK, args!["--ignore-non-fatal-errors", &md])?; Ok(()) }) } @@ -301,18 +286,17 @@ fn fatal_errors_cant_be_ignored() -> Result<()> { fn auto_repair() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); // auto-repair should have no effect on good metadata. ensure_untouched(&md, || { - run_ok(THIN_CHECK, &["--auto-repair", md_path])?; + run_ok(THIN_CHECK, args!["--auto-repair", &md])?; Ok(()) })?; generate_metadata_leaks(&md, 16, 0, 1)?; - run_fail(THIN_CHECK, &[md_path])?; - run_ok(THIN_CHECK, &["--auto-repair", md_path])?; - run_ok(THIN_CHECK, &[md_path])?; + run_fail(THIN_CHECK, args![&md])?; + run_ok(THIN_CHECK, args!["--auto-repair", &md])?; + run_ok(THIN_CHECK, args![&md])?; Ok(()) } @@ -320,11 +304,10 @@ fn auto_repair() -> Result<()> { fn auto_repair_has_limits() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); generate_metadata_leaks(&md, 16, 1, 0)?; ensure_untouched(&md, || { - run_fail(THIN_CHECK, &["--auto-repair", md_path])?; + run_fail(THIN_CHECK, args!["--auto-repair", &md])?; Ok(()) })?; Ok(()) @@ -334,10 +317,9 @@ fn auto_repair_has_limits() -> Result<()> { fn auto_repair_clears_needs_check() -> Result<()> { let mut td = TestDir::new()?; let md = prep_metadata(&mut td)?; - let md_path = md.to_str().unwrap(); set_needs_check(&md)?; - run_ok(THIN_CHECK, &["--auto-repair", md_path])?; + run_ok(THIN_CHECK, args!["--auto-repair", &md])?; assert!(!get_needs_check(&md)?); Ok(()) } diff --git a/tests/thin_delta.rs b/tests/thin_delta.rs index 63e0ce8..a47eacb 100644 --- a/tests/thin_delta.rs +++ b/tests/thin_delta.rs @@ -58,7 +58,7 @@ test_rejects_bad_option!(ThinDelta); fn snap1_unspecified() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let stderr = run_fail(THIN_DELTA, &["--snap2", "45", md.to_str().unwrap()])?; + let stderr = run_fail(THIN_DELTA, args!["--snap2", "45", &md])?; assert!(stderr.contains("--snap1 or --root1 not specified")); Ok(()) } @@ -67,14 +67,14 @@ fn snap1_unspecified() -> Result<()> { fn snap2_unspecified() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let stderr = run_fail(THIN_DELTA, &["--snap1", "45", md.to_str().unwrap()])?; + let stderr = run_fail(THIN_DELTA, args!["--snap1", "45", &md])?; assert!(stderr.contains("--snap2 or --root2 not specified")); Ok(()) } #[test] fn dev_unspecified() -> Result<()> { - let stderr = run_fail(THIN_DELTA, &["--snap1", "45", "--snap2", "46"])?; + let stderr = run_fail(THIN_DELTA, args!["--snap1", "45", "--snap2", "46"])?; // TODO: replace with msg::MISSING_INPUT_ARG once the rust version is ready assert!(stderr.contains("No input file provided")); Ok(()) diff --git a/tests/thin_dump.rs b/tests/thin_dump.rs index ae11219..8e17e19 100644 --- a/tests/thin_dump.rs +++ b/tests/thin_dump.rs @@ -90,8 +90,7 @@ fn dump_restore_cycle() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - let output = run_ok_raw(THIN_DUMP, &[md_path])?; + let output = run_ok_raw(THIN_DUMP, args![&md])?; let xml = td.mk_path("meta.xml"); let mut file = OpenOptions::new() @@ -103,11 +102,9 @@ fn dump_restore_cycle() -> Result<()> { drop(file); let md2 = mk_zeroed_md(&mut td)?; - let md2_path = md2.to_str().unwrap(); - let xml_path = xml.to_str().unwrap(); - run_ok(THIN_RESTORE, &["-i", xml_path, "-o", md2_path])?; + run_ok(THIN_RESTORE, args!["-i", &xml, "-o", &md2])?; - let output2 = run_ok_raw(THIN_DUMP, &[md2_path])?; + let output2 = run_ok_raw(THIN_DUMP, args![&md2])?; assert_eq!(output.stdout, output2.stdout); Ok(()) @@ -121,8 +118,7 @@ fn no_stderr() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - let output = run_ok_raw(THIN_DUMP, &[md_path])?; + let output = run_ok_raw(THIN_DUMP, args![&md])?; assert_eq!(output.stderr.len(), 0); Ok(()) @@ -135,8 +131,7 @@ fn no_stderr() -> Result<()> { fn override_something(flag: &str, value: &str, pattern: &str) -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - let output = run_ok_raw(THIN_DUMP, &[md_path, flag, value])?; + let output = run_ok_raw(THIN_DUMP, args![&md, flag, value])?; assert_eq!(output.stderr.len(), 0); assert!(from_utf8(&output.stdout[0..])?.contains(pattern)); @@ -165,23 +160,23 @@ fn repair_superblock() -> Result<()> { let md = mk_valid_md(&mut td)?; let before = run_ok_raw( THIN_DUMP, - &[ + args![ "--transaction-id=5", "--data-block-size=128", "--nr-data-blocks=4096000", - md.to_str().unwrap(), + &md ], )?; damage_superblock(&md)?; let after = run_ok_raw( THIN_DUMP, - &[ + args![ "--repair", "--transaction-id=5", "--data-block-size=128", "--nr-data-blocks=4096000", - md.to_str().unwrap(), + &md ], )?; assert_eq!(after.stderr.len(), 0); @@ -201,11 +196,11 @@ fn missing_transaction_id() -> Result<()> { damage_superblock(&md)?; let stderr = run_fail( THIN_DUMP, - &[ + args![ "--repair", "--data-block-size=128", "--nr-data-blocks=4096000", - md.to_str().unwrap(), + &md ], )?; assert!(stderr.contains("transaction id")); @@ -219,11 +214,11 @@ fn missing_data_block_size() -> Result<()> { damage_superblock(&md)?; let stderr = run_fail( THIN_DUMP, - &[ + args![ "--repair", "--transaction-id=5", "--nr-data-blocks=4096000", - md.to_str().unwrap(), + &md ], )?; assert!(stderr.contains("data block size")); @@ -237,11 +232,11 @@ fn missing_nr_data_blocks() -> Result<()> { damage_superblock(&md)?; let stderr = run_fail( THIN_DUMP, - &[ + args![ "--repair", "--transaction-id=5", "--data-block-size=128", - md.to_str().unwrap(), + &md ], )?; assert!(stderr.contains("nr data blocks")); diff --git a/tests/thin_metadata_unpack.rs b/tests/thin_metadata_unpack.rs index 5cd8966..1292965 100644 --- a/tests/thin_metadata_unpack.rs +++ b/tests/thin_metadata_unpack.rs @@ -106,17 +106,14 @@ fn end_to_end() -> Result<()> { let mut td = TestDir::new()?; let md_in = mk_valid_md(&mut td)?; let md_out = mk_zeroed_md(&mut td)?; - run_ok( - THIN_METADATA_PACK, - &["-i", md_in.to_str().unwrap(), "-o", "meta.pack"], - )?; + run_ok(THIN_METADATA_PACK, args!["-i", &md_in, "-o", "meta.pack"])?; run_ok( THIN_METADATA_UNPACK, - &["-i", "meta.pack", "-o", md_out.to_str().unwrap()], + args!["-i", "meta.pack", "-o", &md_out], )?; - let dump1 = run_ok(THIN_DUMP, &[md_in.to_str().unwrap()])?; - let dump2 = run_ok(THIN_DUMP, &[md_out.to_str().unwrap()])?; + let dump1 = run_ok(THIN_DUMP, args![&md_in])?; + let dump2 = run_ok(THIN_DUMP, args![&md_out])?; assert_eq!(dump1, dump2); Ok(()) } diff --git a/tests/thin_repair.rs b/tests/thin_repair.rs index e7a3ef3..19e4865 100644 --- a/tests/thin_repair.rs +++ b/tests/thin_repair.rs @@ -100,9 +100,7 @@ fn dont_repair_xml() -> Result<()> { let mut td = TestDir::new()?; let md = mk_zeroed_md(&mut td)?; let xml = mk_valid_xml(&mut td)?; - let xml_path = xml.to_str().unwrap(); - let md_path = md.to_str().unwrap(); - run_fail(THIN_REPAIR, &["-i", xml_path, "-o", md_path])?; + run_fail(THIN_REPAIR, args!["-i", &xml, "-o", &md])?; Ok(()) } @@ -114,12 +112,9 @@ fn override_thing(flag: &str, val: &str, pattern: &str) -> Result<()> { let mut td = TestDir::new()?; let md1 = mk_valid_md(&mut td)?; let md2 = mk_zeroed_md(&mut td)?; - let md1_path = md1.to_str().unwrap(); - let md2_path = md2.to_str().unwrap(); - let output = run_ok_raw(THIN_REPAIR, &[flag, val, "-i", md1_path, "-o", md2_path])?; + let output = run_ok_raw(THIN_REPAIR, args![flag, val, "-i", &md1, "-o", &md2])?; assert_eq!(output.stderr.len(), 0); - let md2_path = md2.to_str().unwrap(); - let output = run_ok(THIN_DUMP, &[md2_path])?; + let output = run_ok(THIN_DUMP, args![&md2])?; assert!(output.contains(pattern)); Ok(()) } @@ -144,33 +139,31 @@ fn override_nr_data_blocks() -> Result<()> { fn superblock_succeeds() -> Result<()> { let mut td = TestDir::new()?; let md1 = mk_valid_md(&mut td)?; - let md1_path = md1.to_str().unwrap(); let original = run_ok_raw( THIN_DUMP, - &[ + args![ "--transaction-id=5", "--data-block-size=128", "--nr-data-blocks=4096000", - md1_path, + &md1 ], )?; assert_eq!(original.stderr.len(), 0); damage_superblock(&md1)?; let md2 = mk_zeroed_md(&mut td)?; - let md2_path = md2.to_str().unwrap(); run_ok( THIN_REPAIR, - &[ + args![ "--transaction-id=5", "--data-block-size=128", "--nr-data-blocks=4096000", "-i", - md1_path, + &md1, "-o", - md2_path, + &md2 ], )?; - let repaired = run_ok_raw(THIN_DUMP, &[md2_path])?; + let repaired = run_ok_raw(THIN_DUMP, args![&md2])?; assert_eq!(repaired.stderr.len(), 0); assert_eq!(original.stdout, repaired.stdout); Ok(()) @@ -185,17 +178,7 @@ fn missing_thing(flag1: &str, flag2: &str, pattern: &str) -> Result<()> { let md1 = mk_valid_md(&mut td)?; damage_superblock(&md1)?; let md2 = mk_zeroed_md(&mut td)?; - let stderr = run_fail( - THIN_REPAIR, - &[ - flag1, - flag2, - "-i", - md1.to_str().unwrap(), - "-o", - md2.to_str().unwrap(), - ], - )?; + let stderr = run_fail(THIN_REPAIR, args![flag1, flag2, "-i", &md1, "-o", &md2])?; assert!(stderr.contains(pattern)); Ok(()) } diff --git a/tests/thin_restore.rs b/tests/thin_restore.rs index 7da5cbf..65ef87a 100644 --- a/tests/thin_restore.rs +++ b/tests/thin_restore.rs @@ -102,9 +102,7 @@ fn quiet_flag(flag: &str) -> Result<()> { let xml = mk_valid_xml(&mut td)?; let md = mk_zeroed_md(&mut td)?; - let xml_path = xml.to_str().unwrap(); - let md_path = md.to_str().unwrap(); - let output = run_ok_raw(THIN_RESTORE, &["-i", xml_path, "-o", md_path, flag])?; + let output = run_ok_raw(THIN_RESTORE, args!["-i", &xml, "-o", &md, flag])?; assert_eq!(output.stdout.len(), 0); assert_eq!(output.stderr.len(), 0); @@ -130,11 +128,9 @@ fn override_something(flag: &str, value: &str, pattern: &str) -> Result<()> { let xml = mk_valid_xml(&mut td)?; let md = mk_zeroed_md(&mut td)?; - let xml_path = xml.to_str().unwrap(); - let md_path = md.to_str().unwrap(); - run_ok(THIN_RESTORE, &["-i", xml_path, "-o", md_path, flag, value])?; + run_ok(THIN_RESTORE, args!["-i", &xml, "-o", &md, flag, value])?; - let output = run_ok(THIN_DUMP, &[md_path])?; + let output = run_ok(THIN_DUMP, args![&md])?; assert!(output.contains(pattern)); Ok(()) } diff --git a/tests/thin_rmap.rs b/tests/thin_rmap.rs index 1fa2a66..8b58e28 100644 --- a/tests/thin_rmap.rs +++ b/tests/thin_rmap.rs @@ -58,8 +58,7 @@ test_rejects_bad_option!(ThinRmap); fn valid_region_format_should_pass() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let md_path = md.to_str().unwrap(); - run_ok(THIN_RMAP, &["--region", "23..7890", md_path])?; + run_ok(THIN_RMAP, args!["--region", "23..7890", &md])?; Ok(()) } @@ -78,7 +77,7 @@ fn invalid_regions_should_fail() -> Result<()> { for r in &invalid_regions { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - run_fail(THIN_RMAP, &[&r.to_string(), md.to_str().unwrap()])?; + run_fail(THIN_RMAP, args![r, &md])?; } Ok(()) } @@ -89,13 +88,7 @@ fn multiple_regions_should_pass() -> Result<()> { let md = mk_valid_md(&mut td)?; run_ok( THIN_RMAP, - &[ - "--region", - "1..23", - "--region", - "45..78", - md.to_str().unwrap(), - ], + args!["--region", "1..23", "--region", "45..78", &md], )?; Ok(()) } @@ -104,7 +97,7 @@ fn multiple_regions_should_pass() -> Result<()> { fn junk_input() -> Result<()> { let mut td = TestDir::new()?; let xml = mk_valid_xml(&mut td)?; - run_fail(THIN_RMAP, &["--region", "0..-1", xml.to_str().unwrap()])?; + run_fail(THIN_RMAP, args!["--region", "0..-1", &xml])?; Ok(()) }