diff --git a/Cargo.lock b/Cargo.lock index 9ec72e0..a2678fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "bitflags" version = "1.2.1" @@ -638,6 +644,7 @@ name = "thinp" version = "0.1.0" dependencies = [ "anyhow", + "base64", "byteorder", "clap", "crc32c", diff --git a/Cargo.toml b/Cargo.toml index dbb8470..63de8df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL3" [dependencies] anyhow = "1.0" +base64 = "0.12" byteorder = "1.3" clap = "2.33" crc32c = "0.4" diff --git a/functional-tests/cache-functional-tests.scm b/functional-tests/cache-functional-tests.scm index 9b3a203..13dcaee 100644 --- a/functional-tests/cache-functional-tests.scm +++ b/functional-tests/cache-functional-tests.scm @@ -49,105 +49,6 @@ ;; to run. (define (register-cache-tests) #t) - ;;;----------------------------------------------------------- - ;;; cache_check scenarios - ;;;----------------------------------------------------------- - - (define-scenario (cache-check v) - "cache_check -V" - (run-ok-rcv (stdout _) (cache-check "-V") - (assert-equal tools-version stdout))) - - (define-scenario (cache-check version) - "cache_check --version" - (run-ok-rcv (stdout _) (cache-check "--version") - (assert-equal tools-version stdout))) - - (define-scenario (cache-check h) - "cache_check -h" - (run-ok-rcv (stdout _) (cache-check "-h") - (assert-equal cache-check-help stdout))) - - (define-scenario (cache-check help) - "cache_check --help" - (run-ok-rcv (stdout _) (cache-check "--help") - (assert-equal cache-check-help stdout))) - - (define-scenario (cache-check must-specify-metadata) - "Metadata file must be specified" - (run-fail-rcv (_ stderr) (cache-check) - (assert-equal - (string-append "No input file provided.\n" - cache-check-help) - stderr))) - - (define-scenario (cache-check no-such-metadata) - "Metadata file doesn't exist." - (let ((bad-path "/arbitrary/filename")) - (run-fail-rcv (_ stderr) (cache-check bad-path) - (assert-starts-with - (string-append bad-path ": No such file or directory") - stderr)))) - - (define-scenario (cache-check metadata-file-cannot-be-a-directory) - "Metadata file must not be a directory" - (let ((bad-path "/tmp")) - (run-fail-rcv (_ stderr) (cache-check bad-path) - (assert-starts-with - (string-append bad-path ": Not a block device or regular file") - stderr)))) - - (define-scenario (cache-check unreadable-metadata) - "Metadata file exists, but is unreadable." - (with-valid-metadata (md) - (run-ok "chmod" "-r" md) - (run-fail-rcv (_ stderr) (cache-check md) - (assert-starts-with "syscall 'open' failed: Permission denied" stderr)))) - - (define-scenario (cache-check fails-with-corrupt-metadata) - "Fail with corrupt superblock" - (with-corrupt-metadata (md) - (run-fail (cache-check md)))) - - (define-scenario (cache-check failing-q) - "Fail quietly with -q" - (with-corrupt-metadata (md) - (run-fail-rcv (stdout stderr) (cache-check "-q" md) - (assert-eof stdout) - (assert-eof stderr)))) - - (define-scenario (cache-check failing-quiet) - "Fail quietly with --quiet" - (with-corrupt-metadata (md) - (run-fail-rcv (stdout stderr) (cache-check "--quiet" md) - (assert-eof stdout) - (assert-eof stderr)))) - - (define-scenario (cache-check valid-metadata-passes) - "A valid metadata area passes" - (with-valid-metadata (md) - (run-ok (cache-check md)))) - - (define-scenario (cache-check bad-metadata-version) - "Invalid metadata version fails" - (with-cache-xml (xml) - (with-empty-metadata (md) - (cache-restore "-i" xml "-o" md "--debug-override-metadata-version" "12345") - (run-fail (cache-check md))))) - - (define-scenario (cache-check tiny-metadata) - "Prints helpful message in case tiny metadata given" - (with-temp-file-sized ((md "cache.bin" 1024)) - (run-fail-rcv (_ stderr) (cache-check md) - (assert-starts-with "Metadata device/file too small. Is this binary metadata?" stderr)))) - - (define-scenario (cache-check spot-accidental-xml-data) - "Prints helpful message if XML metadata given" - (with-cache-xml (xml) - (system (fmt #f "man bash >> " xml)) - (run-fail-rcv (_ stderr) (cache-check xml) - (assert-matches ".*This looks like XML. cache_check only checks the binary metadata format." stderr)))) - ;;;----------------------------------------------------------- ;;; cache_restore scenarios ;;;----------------------------------------------------------- diff --git a/src/cache/mod.rs b/src/cache/mod.rs new file mode 100644 index 0000000..2910ec6 --- /dev/null +++ b/src/cache/mod.rs @@ -0,0 +1 @@ +pub mod xml; diff --git a/src/cache/xml.rs b/src/cache/xml.rs new file mode 100644 index 0000000..d39b057 --- /dev/null +++ b/src/cache/xml.rs @@ -0,0 +1,175 @@ +use anyhow::Result; +use base64::encode; +use std::{borrow::Cow, fmt::Display, io::Write}; + +use quick_xml::events::attributes::Attribute; +use quick_xml::events::{BytesEnd, BytesStart, Event}; +use quick_xml::Writer; + +//--------------------------------------- + +#[derive(Clone)] +pub struct Superblock { + pub uuid: String, + pub block_size: u64, + pub nr_cache_blocks: u64, + pub policy: String, + pub hint_width: u32, +} + +#[derive(Clone)] +pub struct Map { + pub cblock: u64, + pub oblock: u64, + pub dirty: bool, +} + +#[derive(Clone)] +pub struct Hint { + pub cblock: u64, + pub data: Vec, +} + +#[derive(Clone)] +pub struct Discard { + pub begin: u64, + pub end: u64, +} + +#[derive(Clone)] +pub enum Visit { + Continue, + Stop, +} + +pub trait MetadataVisitor { + fn superblock_b(&mut self, sb: &Superblock) -> Result; + fn superblock_e(&mut self) -> Result; + + fn mappings_b(&mut self) -> Result; + fn mappings_e(&mut self) -> Result; + fn mapping(&mut self, m: &Map) -> Result; + + fn hints_b(&mut self) -> Result; + fn hints_e(&mut self) -> Result; + fn hint(&mut self, h: &Hint) -> Result; + + fn discards_b(&mut self) -> Result; + fn discards_e(&mut self) -> Result; + fn discard(&mut self, d: &Discard) -> Result; + + fn eof(&mut self) -> Result; +} + +pub struct XmlWriter { + w: Writer, +} + +impl XmlWriter { + pub fn new(w: W) -> XmlWriter { + XmlWriter { + w: Writer::new_with_indent(w, 0x20, 2), + } + } +} + +fn mk_attr_<'a, T: Display>(n: T) -> Cow<'a, [u8]> { + let str = format!("{}", n); + Cow::Owned(str.into_bytes()) +} + +fn mk_attr(key: &[u8], value: T) -> Attribute { + Attribute { + key, + value: mk_attr_(value), + } +} + +impl MetadataVisitor for XmlWriter { + fn superblock_b(&mut self, sb: &Superblock) -> Result { + let tag = b"superblock"; + let mut elem = BytesStart::owned(tag.to_vec(), tag.len()); + elem.push_attribute(mk_attr(b"uuid", sb.uuid.clone())); + elem.push_attribute(mk_attr(b"block_size", sb.block_size)); + elem.push_attribute(mk_attr(b"nr_cache_blocks", sb.nr_cache_blocks)); + elem.push_attribute(mk_attr(b"policy", sb.policy.clone())); + elem.push_attribute(mk_attr(b"hint_width", sb.hint_width)); + + self.w.write_event(Event::Start(elem))?; + Ok(Visit::Continue) + } + + fn superblock_e(&mut self) -> Result { + self.w.write_event(Event::End(BytesEnd::borrowed(b"superblock")))?; + Ok(Visit::Continue) + } + + fn mappings_b(&mut self) -> Result { + let tag = b"mappings"; + let elem = BytesStart::owned(tag.to_vec(), tag.len()); + self.w.write_event(Event::Start(elem))?; + Ok(Visit::Continue) + } + + fn mappings_e(&mut self) -> Result { + self.w.write_event(Event::End(BytesEnd::borrowed(b"mappings")))?; + Ok(Visit::Continue) + } + + fn mapping(&mut self, m: &Map) -> Result { + let tag = b"map"; + let mut elem = BytesStart::owned(tag.to_vec(), tag.len()); + elem.push_attribute(mk_attr(b"cache_block", m.cblock)); + elem.push_attribute(mk_attr(b"origin_block", m.oblock)); + elem.push_attribute(mk_attr(b"dirty", m.dirty)); + self.w.write_event(Event::Empty(elem))?; + Ok(Visit::Continue) + } + + fn hints_b(&mut self) -> Result { + let tag = b"hints"; + let elem = BytesStart::owned(tag.to_vec(), tag.len()); + self.w.write_event(Event::Start(elem))?; + Ok(Visit::Continue) + } + + fn hints_e(&mut self) -> Result { + self.w.write_event(Event::End(BytesEnd::borrowed(b"hints")))?; + Ok(Visit::Continue) + } + + fn hint(&mut self, h: &Hint) -> Result { + let tag = b"hint"; + let mut elem = BytesStart::owned(tag.to_vec(), tag.len()); + elem.push_attribute(mk_attr(b"cache_block", h.cblock)); + elem.push_attribute(mk_attr(b"data", encode(&h.data[0..]))); + self.w.write_event(Event::Empty(elem))?; + Ok(Visit::Continue) + } + + fn discards_b(&mut self) -> Result { + let tag = b"discards"; + let elem = BytesStart::owned(tag.to_vec(), tag.len()); + self.w.write_event(Event::Start(elem))?; + Ok(Visit::Continue) + } + + fn discards_e(&mut self) -> Result { + self.w.write_event(Event::End(BytesEnd::borrowed(b"discards")))?; + Ok(Visit::Continue) + } + + fn discard(&mut self, d: &Discard) -> Result { + let tag = b"discard"; + let mut elem = BytesStart::owned(tag.to_vec(), tag.len()); + elem.push_attribute(mk_attr(b"dbegin", d.begin)); + elem.push_attribute(mk_attr(b"dend", d.end)); + self.w.write_event(Event::Empty(elem))?; + Ok(Visit::Continue) + } + + fn eof(&mut self) -> Result { + Ok(Visit::Continue) + } +} + diff --git a/src/lib.rs b/src/lib.rs index 6d52650..ac0780e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ extern crate quickcheck; extern crate quickcheck_macros; pub mod block_manager; +pub mod cache; pub mod checksum; pub mod file_utils; pub mod pack; diff --git a/src/thin/check.rs b/src/thin/check.rs index 6461ad8..a0a92a6 100644 --- a/src/thin/check.rs +++ b/src/thin/check.rs @@ -212,7 +212,6 @@ pub fn check(dev: &Path) -> Result<()> { println!("found {} devices", visitor.devs.len()); } -/* // mapping top level let mut roots = HashMap::new(); { @@ -242,7 +241,6 @@ pub fn check(dev: &Path) -> Result<()> { pool.join(); } - */ // data space map { @@ -276,7 +274,7 @@ pub fn check(dev: &Path) -> Result<()> { return Err(anyhow!("Index entry points to block ({}) that isn't a bitmap", b.loc)); } - let bitmap = unpack::(b.get_data())?; + let _bitmap = unpack::(b.get_data())?; } } diff --git a/tests/cache_check.rs b/tests/cache_check.rs new file mode 100644 index 0000000..fc79bc5 --- /dev/null +++ b/tests/cache_check.rs @@ -0,0 +1,129 @@ +use anyhow::Result; +use thinp::file_utils; +use thinp::version::TOOLS_VERSION; +use duct::cmd; + +mod common; + +use common::*; +use common::test_dir::*; +use common::cache_xml_generator::{write_xml, XmlGen}; + +//------------------------------------------ + +#[test] +fn accepts_v() -> Result<()> { + let stdout = cache_check!("-V").read()?; + assert_eq!(stdout, TOOLS_VERSION); + Ok(()) +} + +#[test] +fn accepts_version() -> Result<()> { + let stdout = cache_check!("--version").read()?; + assert_eq!(stdout, TOOLS_VERSION); + Ok(()) +} + +const USAGE: &str = "Usage: cache_check [options] {device|file}\nOptions:\n {-q|--quiet}\n {-h|--help}\n {-V|--version}\n {--clear-needs-check-flag}\n {--super-block-only}\n {--skip-mappings}\n {--skip-hints}\n {--skip-discards}"; + +#[test] +fn accepts_h() -> Result<()> { + let stdout = cache_check!("-h").read()?; + assert_eq!(stdout, USAGE); + Ok(()) +} + +#[test] +fn accepts_help() -> Result<()> { + let stdout = cache_check!("--help").read()?; + assert_eq!(stdout, USAGE); + Ok(()) +} + +#[test] +fn missing_metadata() -> Result<()> { + let stderr = run_fail(cache_check!())?; + assert!(stderr.contains("No input file provided")); + Ok(()) +} + +#[test] +fn no_such_metadata() -> Result<()> { + let stderr = run_fail(cache_check!("/arbitrary/filename"))?; + assert!(stderr.contains("No such file or directory")); + Ok(()) +} + +#[test] +fn metadata_cannot_be_a_directory() -> Result<()> { + let stderr = run_fail(cache_check!("/tmp"))?; + assert!(stderr.contains("Not a block device or regular file")); + Ok(()) +} + +#[test] +fn unreadable_metadata() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_valid_md(&mut td)?; + cmd!("chmod", "-r", &md).run()?; + let stderr = run_fail(cache_check!(&md))?; + assert!(stderr.contains("syscall 'open' failed: Permission denied")); + Ok(()) +} + +#[test] +fn corrupt_metadata() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_zeroed_md(&mut td)?; + run_fail(cache_check!(&md))?; + Ok(()) +} + +#[test] +fn failing_q() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_zeroed_md(&mut td)?; + let output = cache_check!("-q", &md).unchecked().run()?; + assert!(!output.status.success()); + assert_eq!(output.stdout.len(), 0); + assert_eq!(output.stderr.len(), 0); + Ok(()) +} + +#[test] +fn failing_quiet() -> Result<()> { + let mut td = TestDir::new()?; + let md = mk_zeroed_md(&mut td)?; + let output = cache_check!("--quiet", &md).unchecked().run()?; + assert!(!output.status.success()); + assert_eq!(output.stdout.len(), 0); + assert_eq!(output.stderr.len(), 0); + Ok(()) +} + +// (define-scenario (cache-check valid-metadata-passes) +// "A valid metadata area passes" +// (with-valid-metadata (md) +// (run-ok (cache-check md)))) +// +// (define-scenario (cache-check bad-metadata-version) +// "Invalid metadata version fails" +// (with-cache-xml (xml) +// (with-empty-metadata (md) +// (cache-restore "-i" xml "-o" md "--debug-override-metadata-version" "12345") +// (run-fail (cache-check md))))) +// +// (define-scenario (cache-check tiny-metadata) +// "Prints helpful message in case tiny metadata given" +// (with-temp-file-sized ((md "cache.bin" 1024)) +// (run-fail-rcv (_ stderr) (cache-check md) +// (assert-starts-with "Metadata device/file too small. Is this binary metadata?" stderr)))) +// +// (define-scenario (cache-check spot-accidental-xml-data) +// "Prints helpful message if XML metadata given" +// (with-cache-xml (xml) +// (system (fmt #f "man bash >> " xml)) +// (run-fail-rcv (_ stderr) (cache-check xml) +// (assert-matches ".*This looks like XML. cache_check only checks the binary metadata format." stderr)))) +// diff --git a/tests/common/cache_xml_generator.rs b/tests/common/cache_xml_generator.rs new file mode 100644 index 0000000..d9e558e --- /dev/null +++ b/tests/common/cache_xml_generator.rs @@ -0,0 +1,94 @@ +use anyhow::{Result}; +use rand::prelude::*; +use std::collections::HashSet; +use std::fs::OpenOptions; +use std::path::Path; +use thinp::cache::xml; + +//------------------------------------------ + +pub trait XmlGen { + fn generate_xml(&mut self, v: &mut dyn xml::MetadataVisitor) -> Result<()>; +} + +pub fn write_xml(path: &Path, g: &mut dyn XmlGen) -> Result<()> { + let xml_out = OpenOptions::new() + .read(false) + .write(true) + .create(true) + .truncate(true) + .open(path)?; + let mut w = xml::XmlWriter::new(xml_out); + + g.generate_xml(&mut w) +} + +pub struct CacheGen { + block_size: u64, + nr_cache_blocks: u64, + nr_origin_blocks: u64, + percent_resident: u8, + percent_dirty: u8, +} + +impl CacheGen { + pub fn new( + block_size: u64, + nr_cache_blocks: u64, + nr_origin_blocks: u64, + percent_resident: u8, + percent_dirty: u8, + ) -> Self { + CacheGen { + block_size, + nr_cache_blocks, + nr_origin_blocks, + percent_resident, + percent_dirty, + } + } +} + +impl XmlGen for CacheGen { + fn generate_xml(&mut self, v: &mut dyn xml::MetadataVisitor) -> Result<()> { + v.superblock_b(&xml::Superblock { + uuid: "".to_string(), + block_size: self.block_size, + nr_cache_blocks: self.nr_cache_blocks, + policy: "smq".to_string(), + hint_width: 4, + })?; + + let mut cblocks = Vec::new(); + for n in 0..self.nr_cache_blocks { + cblocks.push(n); + } + cblocks.shuffle(&mut rand::thread_rng()); + + v.mappings_b()?; + { + let nr_resident = (self.nr_cache_blocks * 100 as u64) / (self.percent_resident as u64); + let mut used = HashSet::new(); + for n in 0..nr_resident { + let mut oblock = 0u64; + while used.contains(&oblock) { + oblock = rand::thread_rng().gen(); + } + + used.insert(oblock); + // FIXME: dirty should vary + v.mapping(&xml::Map { + cblock: cblocks[n as usize], + oblock, + dirty: false, + })?; + } + } + v.mappings_e()?; + + v.superblock_e()?; + Ok(()) + } +} + +//------------------------------------------ diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 21c5526..6580f79 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -6,11 +6,14 @@ use std::fs::OpenOptions; use std::io::{Read, Write}; use std::path::{PathBuf}; use std::str::from_utf8; -use tempfile::{tempdir, TempDir}; use thinp::file_utils; -pub mod xml_generator; -use crate::common::xml_generator::{write_xml, SingleThinS}; +pub mod thin_xml_generator; +pub mod cache_xml_generator; +pub mod test_dir; + +use crate::common::thin_xml_generator::{write_xml, SingleThinS}; +use test_dir::TestDir; //------------------------------------------ @@ -103,28 +106,19 @@ macro_rules! thin_metadata_unpack { }; } +#[macro_export] +macro_rules! cache_check { + ( $( $arg: expr ),* ) => { + { + use std::ffi::OsString; + let args: &[OsString] = &[$( Into::::into($arg) ),*]; + duct::cmd("bin/cache_check", args).stdout_capture().stderr_capture() + } + }; +} + //------------------------------------------ -pub struct TestDir { - dir: TempDir, - file_count: usize, -} - -impl TestDir { - pub fn new() -> Result { - let dir = tempdir()?; - Ok(TestDir { dir, file_count: 0 }) - } - - pub fn mk_path(&mut self, file: &str) -> PathBuf { - let mut p = PathBuf::new(); - p.push(&self.dir); - p.push(PathBuf::from(format!("{:02}_{}", self.file_count, file))); - self.file_count += 1; - p - } -} - // Returns stderr, a non zero status must be returned pub fn run_fail(command: Expression) -> Result { let output = command.stderr_capture().unchecked().run()?; diff --git a/tests/common/test_dir.rs b/tests/common/test_dir.rs new file mode 100644 index 0000000..91a4b62 --- /dev/null +++ b/tests/common/test_dir.rs @@ -0,0 +1,27 @@ +use anyhow::Result; +use std::path::{PathBuf}; +use tempfile::{tempdir, TempDir}; + +//--------------------------------------- + +pub struct TestDir { + dir: TempDir, + file_count: usize, +} + +impl TestDir { + pub fn new() -> Result { + let dir = tempdir()?; + Ok(TestDir { dir, file_count: 0 }) + } + + pub fn mk_path(&mut self, file: &str) -> PathBuf { + let mut p = PathBuf::new(); + p.push(&self.dir); + p.push(PathBuf::from(format!("{:02}_{}", self.file_count, file))); + self.file_count += 1; + p + } +} + +//--------------------------------------- diff --git a/tests/common/xml_generator.rs b/tests/common/thin_xml_generator.rs similarity index 100% rename from tests/common/xml_generator.rs rename to tests/common/thin_xml_generator.rs diff --git a/tests/thin_check.rs b/tests/thin_check.rs index a3aa22e..5a7c801 100644 --- a/tests/thin_check.rs +++ b/tests/thin_check.rs @@ -5,7 +5,8 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; -use common::xml_generator::{write_xml, FragmentedS}; +use common::test_dir::*; +use common::thin_xml_generator::{write_xml, FragmentedS}; //------------------------------------------ diff --git a/tests/thin_delta.rs b/tests/thin_delta.rs index 7c1442b..49d92cb 100644 --- a/tests/thin_delta.rs +++ b/tests/thin_delta.rs @@ -3,6 +3,7 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_dump.rs b/tests/thin_dump.rs index c754eff..d2e58a9 100644 --- a/tests/thin_dump.rs +++ b/tests/thin_dump.rs @@ -6,6 +6,7 @@ use std::str::from_utf8; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_metadata_pack.rs b/tests/thin_metadata_pack.rs index ee9926b..2e12228 100644 --- a/tests/thin_metadata_pack.rs +++ b/tests/thin_metadata_pack.rs @@ -3,6 +3,7 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_metadata_unpack.rs b/tests/thin_metadata_unpack.rs index 057e147..b0a540b 100644 --- a/tests/thin_metadata_unpack.rs +++ b/tests/thin_metadata_unpack.rs @@ -3,6 +3,7 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_repair.rs b/tests/thin_repair.rs index 9bf9a33..98ded1f 100644 --- a/tests/thin_repair.rs +++ b/tests/thin_repair.rs @@ -4,6 +4,7 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_restore.rs b/tests/thin_restore.rs index 819b292..9a90273 100644 --- a/tests/thin_restore.rs +++ b/tests/thin_restore.rs @@ -5,6 +5,7 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_rmap.rs b/tests/thin_rmap.rs index e741c7f..1a932a2 100644 --- a/tests/thin_rmap.rs +++ b/tests/thin_rmap.rs @@ -3,6 +3,7 @@ use thinp::version::TOOLS_VERSION; mod common; use common::*; +use common::test_dir::*; //------------------------------------------ diff --git a/tests/thin_shrink.rs b/tests/thin_shrink.rs index 3397d20..0856859 100644 --- a/tests/thin_shrink.rs +++ b/tests/thin_shrink.rs @@ -9,8 +9,8 @@ use thinp::file_utils; use thinp::thin::xml::{self, Visit}; mod common; -use common::*; -use common::xml_generator::{ +use common::test_dir::*; +use common::thin_xml_generator::{ write_xml, EmptyPoolS, FragmentedS, SingleThinS, SnapS, XmlGen };