From 4ac428128aaf6f880ed684e7dd4454edf0eeea56 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 4 Aug 2020 11:30:46 +0100 Subject: [PATCH] [functional-tests (rust)] port thin_repair tests to rust. cargo test --- functional-tests/thin-functional-tests.scm | 91 ------------ tests/common/mod.rs | 11 ++ tests/thin_repair.rs | 158 +++++++++++++++++++++ tests/thin_rmap.rs | 5 +- 4 files changed, 170 insertions(+), 95 deletions(-) create mode 100644 tests/thin_repair.rs diff --git a/functional-tests/thin-functional-tests.scm b/functional-tests/thin-functional-tests.scm index ee3372f..c921b87 100644 --- a/functional-tests/thin-functional-tests.scm +++ b/functional-tests/thin-functional-tests.scm @@ -111,97 +111,6 @@ (run-fail-rcv (_ stderr) (thin-delta "--snap1 45 --snap2 46") (assert-starts-with "No input device provided." stderr))) - ;;;----------------------------------------------------------- - ;;; thin_repair scenarios - ;;;----------------------------------------------------------- - (define-scenario (thin-repair dont-repair-xml) - "Fails gracefully if run on XML rather than metadata" - (with-thin-xml (xml) - (with-empty-metadata (md) - (run-fail-rcv (_ stderr) (thin-repair "-i" xml "-o" md) - #t)))) - - (define-scenario (thin-repair missing-input-file) - "the input file can't be found" - (with-empty-metadata (md) - (run-fail-rcv (_ stderr) (thin-repair "-i no-such-file -o" md) - (assert-superblock-all-zeroes md) - (assert-starts-with "Couldn't stat file" stderr)))) - - (define-scenario (thin-repair garbage-input-file) - "the input file is just zeroes" - (with-empty-metadata (md1) - (with-corrupt-metadata (md2) - (run-fail-rcv (_ stderr) (thin-repair "-i " md1 "-o" md2) - (assert-superblock-all-zeroes md2))))) - - (define-scenario (thin-repair missing-output-file) - "the output file can't be found" - (with-thin-xml (xml) - (run-fail-rcv (_ stderr) (thin-repair "-i " xml) - (assert-starts-with "No output file provided." stderr)))) - - (define-scenario (thin-repair override transaction-id) - "thin_repair obeys the --transaction-id override" - (with-valid-metadata (md1) - (with-empty-metadata (md2) - (run-ok-rcv (stdout stderr) (thin-repair "--transaction-id 2345" "-i" md1 "-o" md2) - (assert-eof stderr)) - (run-ok-rcv (stdout stderr) (thin-dump md2) - (assert-matches ".*transaction=\"2345\"" stdout))))) - - (define-scenario (thin-repair override data-block-size) - "thin_repair obeys the --data-block-size override" - (with-valid-metadata (md1) - (with-empty-metadata (md2) - (run-ok-rcv (stdout stderr) (thin-repair "--data-block-size 8192" "-i" md1 "-o" md2) - (assert-eof stderr)) - (run-ok-rcv (stdout stderr) (thin-dump md2) - (assert-matches ".*data_block_size=\"8192\"" stdout))))) - - (define-scenario (thin-repair override nr-data-blocks) - "thin_repair obeys the --nr-data-blocks override" - (with-valid-metadata (md1) - (with-empty-metadata (md2) - (run-ok-rcv (stdout stderr) (thin-repair "--nr-data-blocks 234500" "-i" md1 "-o" md2) - (assert-eof stderr)) - (run-ok-rcv (stdout stderr) (thin-dump md2) - (assert-matches ".*nr_data_blocks=\"234500\"" stdout))))) - - (define-scenario (thin-repair superblock succeeds) - "thin_repair can restore a missing superblock" - (with-valid-metadata (md1) - (run-ok-rcv (expected-xml stderr) (thin-dump "--transaction-id=5" "--data-block-size=128" "--nr-data-blocks=4096000" md1) - (damage-superblock md1) - (with-empty-metadata (md2) - (run-ok-rcv (_ stderr) (thin-repair "--transaction-id=5" "--data-block-size=128" "--nr-data-blocks=4096000" "-i" md1 "-o" md2) - (assert-eof stderr)) - (run-ok-rcv (repaired-xml stderr) (thin-dump md2) - (assert-eof stderr) - (assert-equal expected-xml repaired-xml)))))) - - (define-scenario (thin-repair superblock missing-transaction-id) - "--transaction-id is mandatory if the superblock is damaged" - (with-damaged-superblock (md1) - (with-empty-metadata (md2) - (run-fail-rcv (_ stderr) (thin-repair "--data-block-size=128" "--nr-data-blocks=4096000" "-i" md1 "-o" md2) - (assert-matches ".*transaction id.*" stderr))))) - - (define-scenario (thin-repair superblock missing-data-block-size) - "--data-block-size is mandatory if the superblock is damaged" - (with-damaged-superblock (md1) - (with-empty-metadata (md2) - (run-fail-rcv (_ stderr) (thin-repair "--transaction-id=5" "--nr-data-blocks=4096000" "-i" md1 "-o" md2) - (assert-matches ".*data block size.*" stderr))))) - - (define-scenario (thin-repair superblock missing-nr-data-blocks) - "--nr-data-blocks is mandatory if the superblock is damaged" - (with-damaged-superblock (md1) - (with-empty-metadata (md2) - (run-fail-rcv (_ stderr) (thin-repair "--transaction-id=5" "--data-block-size=128" "-i" md1 "-o" md2) - (assert-matches ".*nr data blocks.*" stderr))))) - - ;;;----------------------------------------------------------- ;;; thin_metadata_pack scenarios ;;;----------------------------------------------------------- diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 23fa38d..bf24132 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -59,6 +59,17 @@ macro_rules! thin_rmap { }; } +#[macro_export] +macro_rules! thin_repair { + ( $( $arg: expr ),* ) => { + { + use std::ffi::OsString; + let args: &[OsString] = &[$( Into::::into($arg) ),*]; + duct::cmd("bin/thin_repair", args).stdout_capture().stderr_capture() + } + }; +} + //------------------------------------------ pub struct TestDir { diff --git a/tests/thin_repair.rs b/tests/thin_repair.rs new file mode 100644 index 0000000..9bf9a33 --- /dev/null +++ b/tests/thin_repair.rs @@ -0,0 +1,158 @@ +use anyhow::Result; +use std::str::from_utf8; +use thinp::version::TOOLS_VERSION; + +mod common; +use common::*; + +//------------------------------------------ + +#[test] +fn accepts_v() -> Result<()> { + let stdout = thin_repair!("-V").read()?; + assert_eq!(stdout, TOOLS_VERSION); + Ok(()) +} + +#[test] +fn accepts_version() -> Result<()> { + let stdout = thin_repair!("--version").read()?; + assert_eq!(stdout, TOOLS_VERSION); + Ok(()) +} + +const USAGE: &str = "Usage: thin_repair [options] {device|file}\nOptions:\n {-h|--help}\n {-i|--input} \n {-o|--output} \n {--transaction-id} \n {--data-block-size} \n {--nr-data-blocks} \n {-V|--version}"; + +#[test] +fn accepts_h() -> Result<()> { + let stdout = thin_repair!("-h").read()?; + assert_eq!(stdout, USAGE); + Ok(()) +} + +#[test] +fn accepts_help() -> Result<()> { + let stdout = thin_repair!("--help").read()?; + assert_eq!(stdout, USAGE); + Ok(()) +} + +#[test] +fn dont_repair_xml() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_zeroed_md(&mut td)?; + let xml = mk_valid_xml(&mut td)?; + run_fail(thin_repair!("-i", &xml, "-o", &md))?; + Ok(()) +} + +#[test] +fn missing_input_file() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_zeroed_md(&mut td)?; + let stderr = run_fail(thin_repair!("-i", "no-such-file", "-o", &md))?; + assert!(superblock_all_zeroes(&md)?); + assert!(stderr.contains("Couldn't stat file")); + Ok(()) +} + +#[test] +fn garbage_input_file() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_zeroed_md(&mut td)?; + let md2 = mk_zeroed_md(&mut td)?; + run_fail(thin_repair!("-i", &md, "-o", &md2))?; + assert!(superblock_all_zeroes(&md2)?); + Ok(()) +} + +#[test] +fn missing_output_file() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_valid_md(&mut td)?; + let stderr = run_fail(thin_repair!("-i", &md))?; + assert!(stderr.contains("No output file provided.")); + Ok(()) +} + +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 output = thin_repair!(flag, val, "-i", &md1, "-o", &md2).run()?; + assert_eq!(output.stderr.len(), 0); + let output = thin_dump!(&md2).run()?; + assert!(from_utf8(&output.stdout[0..])?.contains(pattern)); + Ok(()) +} + +#[test] +fn override_transaction_id() -> Result<()> { + override_thing("--transaction-id", "2345", "transaction=\"2345\"") +} + +#[test] +fn override_data_block_size() -> Result<()> { + override_thing("--data-block-size", "8192", "data_block_size=\"8192\"") +} + +#[test] +fn override_nr_data_blocks() -> Result<()> { + override_thing("--nr-data-blocks", "234500", "nr_data_blocks=\"234500\"") +} + +#[test] +fn superblock_succeeds() -> Result<()> { + let mut td = TestDir::new()?; + let md1 = mk_valid_md(&mut td)?; + let original = thin_dump!( + "--transaction-id=5", + "--data-block-size=128", + "--nr-data-blocks=4096000", + &md1 + ) + .run()?; + assert_eq!(original.stderr.len(), 0); + damage_superblock(&md1)?; + let md2 = mk_zeroed_md(&mut td)?; + thin_repair!( + "--transaction-id=5", + "--data-block-size=128", + "--nr-data-blocks=4096000", + "-i", + &md1, + "-o", + &md2 + ) + .run()?; + let repaired = thin_dump!(&md2).run()?; + assert_eq!(repaired.stderr.len(), 0); + assert_eq!(original.stdout, repaired.stdout); + Ok(()) +} + +fn missing_thing(flag1: &str, flag2: &str, pattern: &str) -> Result<()> +{ + let mut td = TestDir::new()?; + 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, "-o", &md2))?; + assert!(stderr.contains(pattern)); + Ok(()) +} + +#[test] +fn missing_transaction_id() -> Result<()> { + missing_thing("--data-block-size=128", "--nr-data-blocks=4096000", "transaction id") +} + +#[test] +fn missing_data_block_size() -> Result<()> { + missing_thing("--transaction-id=5", "--nr-data-blocks=4096000", "data block size") +} + +#[test] +fn missing_nr_data_blocks() -> Result<()> { + missing_thing("--transaction-id=5", "--data-block-size=128", "nr data blocks") +} diff --git a/tests/thin_rmap.rs b/tests/thin_rmap.rs index e6255e6..e741c7f 100644 --- a/tests/thin_rmap.rs +++ b/tests/thin_rmap.rs @@ -47,10 +47,7 @@ fn rejects_bad_option() -> Result<()> { fn valid_region_format_should_pass() -> Result<()> { let mut td = TestDir::new()?; let md = mk_valid_md(&mut td)?; - let output = thin_rmap!("--region", "23..7890", &md).unchecked().run()?; - eprintln!("stdout: {:?}", output.stdout); - eprintln!("stderr: {:?}", output.stderr); - assert!(output.status.success()); + thin_rmap!("--region", "23..7890", &md).run()?; Ok(()) }