[tests] Pull out common submodules

New modules: fixture, process, program, target, and thin
This commit is contained in:
Ming-Hung Tsai 2021-07-20 17:37:55 +08:00
parent 66b49e6f3d
commit 16190f0f9a
19 changed files with 469 additions and 388 deletions

View File

@ -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<std::path::PathBuf> {
mk_valid_md(td)
common::thin::mk_valid_md(td) // FIXME: create cache metadata
}
fn file_not_found() -> &'a str {

View File

@ -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<std::path::PathBuf> {
mk_valid_md(td)
common::thin::mk_valid_md(td) // FIXME: generate cache metadata
}
fn file_not_found() -> &'a str {

View File

@ -1,6 +1,10 @@
use crate::common::*;
use anyhow::Result;
use thinp::version::tools_version;
use crate::common::process::*;
use crate::common::program::*;
//------------------------------------------
// help

69
tests/common/fixture.rs Normal file
View File

@ -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<PathBuf> {
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<String> {
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<F>(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<bool> {
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<F>(p: &PathBuf, thunk: F) -> Result<()>
where
F: Fn() -> Result<()>,
{
thunk()?;
assert!(superblock_all_zeroes(p)?);
Ok(())
}
//------------------------------------------

View File

@ -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())?;

View File

@ -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<PathBuf>;
// 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<S, I>(program: S, args: I) -> Result<String>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<S, I>(program: S, args: I) -> Result<std::process::Output>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<S, I>(program: S, args: I) -> Result<String>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<S, I>(program: S, args: I) -> Result<std::process::Output>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<PathBuf> {
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<PathBuf> {
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<PathBuf> {
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<bool> {
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<PathBuf> {
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<bool> {
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<String> {
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<F>(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<F>(p: &PathBuf, thunk: F) -> Result<()>
where
F: Fn() -> Result<()>,
{
thunk()?;
assert!(superblock_all_zeroes(p)?);
Ok(())
}
//------------------------------------------

View File

@ -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

71
tests/common/process.rs Normal file
View File

@ -0,0 +1,71 @@
use anyhow::Result;
use std::ffi::{OsStr, OsString};
//------------------------------------------
// Returns stdout. The command must return zero.
pub fn run_ok<S, I>(program: S, args: I) -> Result<String>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<S, I>(program: S, args: I) -> Result<std::process::Output>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<S, I>(program: S, args: I) -> Result<String>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
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<S, I>(program: S, args: I) -> Result<std::process::Output>
where
S: AsRef<OsStr>,
I: IntoIterator,
I::Item: Into<OsString>,
{
let command = duct::cmd(program.as_ref(), args)
.stdout_capture()
.stderr_capture();
let output = command.unchecked().run()?;
assert!(!output.status.success());
Ok(output)
}
//------------------------------------------

43
tests/common/program.rs Normal file
View File

@ -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<PathBuf>;
// 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> {}
//------------------------------------------

79
tests/common/target.rs Normal file
View File

@ -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;
//------------------------------------------

135
tests/common/thin.rs Normal file
View File

@ -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<PathBuf> {
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<PathBuf> {
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<PathBuf> {
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<bool> {
use thinp::thin::superblock::*;
let engine = SyncIoEngine::new(&md, 1, false)?;
let sb = read_superblock(&engine, SUPERBLOCK_LOCATION)?;
Ok(sb.flags.needs_check)
}
//-----------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------

View File

@ -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::*;
//------------------------------------------