From 4cfe93570cdb3950cf1a2351210f6da4a60ffaf4 Mon Sep 17 00:00:00 2001 From: Ming-Hung Tsai Date: Fri, 1 Oct 2021 15:49:23 +0800 Subject: [PATCH] [tests] Add era test fixtures --- tests/common/era.rs | 34 +++++++ tests/common/era_xml_generator.rs | 157 ++++++++++++++++++++++++++++++ tests/common/mod.rs | 2 + 3 files changed, 193 insertions(+) create mode 100644 tests/common/era.rs create mode 100644 tests/common/era_xml_generator.rs diff --git a/tests/common/era.rs b/tests/common/era.rs new file mode 100644 index 0000000..c7b66a0 --- /dev/null +++ b/tests/common/era.rs @@ -0,0 +1,34 @@ +use anyhow::Result; +use std::path::PathBuf; + +use thinp::file_utils; + +use crate::args; +use crate::common::era_xml_generator::{write_xml, CleanShutdownMeta}; +use crate::common::process::*; +use crate::common::target::*; +use crate::common::test_dir::TestDir; + +//----------------------------------------------- + +pub fn mk_valid_xml(td: &mut TestDir) -> Result { + let xml = td.mk_path("meta.xml"); + let mut gen = CleanShutdownMeta::new(128, 256, 32, 4); // bs, nr_blocks, era, nr_wsets + 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 = CleanShutdownMeta::new(128, 256, 32, 4); + write_xml(&xml, &mut gen)?; + + let _file = file_utils::create_sized_file(&md, 4096 * 4096); + run_ok(ERA_RESTORE, args!["-i", &xml, "-o", &md])?; + + Ok(md) +} + +//----------------------------------------------- diff --git a/tests/common/era_xml_generator.rs b/tests/common/era_xml_generator.rs new file mode 100644 index 0000000..8c7fad4 --- /dev/null +++ b/tests/common/era_xml_generator.rs @@ -0,0 +1,157 @@ +use anyhow::Result; +use rand::prelude::*; +use std::fs::OpenOptions; +use std::path::Path; +use thinp::era::ir::{self, MetadataVisitor}; +use thinp::era::xml; + +//------------------------------------------ + +pub trait XmlGen { + fn generate_xml(&mut self, v: &mut dyn 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, false); + + g.generate_xml(&mut w) +} + +//------------------------------------------ + +// Ordered sequence generator where each element has an independent probability +// of being present. +struct IndependentSequence { + begin: u32, + end: u32, + prob: u32, + rng: ThreadRng, +} + +impl IndependentSequence { + fn new(begin: u32, end: u32, prob: u32) -> IndependentSequence { + IndependentSequence { + begin, + end, + prob, + rng: rand::thread_rng(), + } + } +} + +impl Iterator for IndependentSequence { + type Item = std::ops::Range; + + // FIXME: reduce complexity + fn next(&mut self) -> Option> { + if self.begin >= self.end { + return None; + } + + let mut b = self.begin; + while b < self.end && self.rng.gen_range(0..100) >= self.prob { + b += 1; + } + + if b == self.end { + return None; + } + + let mut e = b + 1; + while e < self.end && self.rng.gen_range(0..100) < self.prob { + e += 1; + } + self.begin = e + 1; + + Some(std::ops::Range { start: b, end: e }) + } +} + +//------------------------------------------ + +fn create_superblock(block_size: u32, nr_blocks: u32, current_era: u32) -> ir::Superblock { + ir::Superblock { + uuid: "".to_string(), + block_size, + nr_blocks, + current_era, + } +} + +pub struct CleanShutdownMeta { + block_size: u32, + nr_blocks: u32, + current_era: u32, + nr_writesets: u32, +} + +impl CleanShutdownMeta { + pub fn new(block_size: u32, nr_blocks: u32, current_era: u32, nr_writesets: u32) -> Self { + CleanShutdownMeta { + block_size, + nr_blocks, + current_era, + nr_writesets, + } + } + + fn generate_writeset(v: &mut dyn MetadataVisitor, ws: &ir::Writeset) -> Result<()> { + v.writeset_b(ws)?; + let gen = IndependentSequence::new(0, ws.nr_bits, 10); + for seq in gen { + v.writeset_blocks(&ir::MarkedBlocks { + begin: seq.start, + len: seq.end - seq.start, + })?; + } + v.writeset_e()?; + + Ok(()) + } + + fn generate_era_array(v: &mut dyn MetadataVisitor, nr_blocks: u32, max_era: u32) -> Result<()> { + let mut rng = rand::thread_rng(); + v.era_b()?; + for b in 0..nr_blocks { + let era = rng.gen_range(0..max_era); + v.era(&ir::Era { block: b, era })?; + } + v.era_e()?; + + Ok(()) + } +} + +impl XmlGen for CleanShutdownMeta { + fn generate_xml(&mut self, v: &mut dyn MetadataVisitor) -> Result<()> { + v.superblock_b(&create_superblock( + self.block_size, + self.nr_blocks, + self.current_era, + ))?; + + let era_low = self.current_era - self.nr_writesets + 1; + for era in era_low..self.current_era + 1 { + Self::generate_writeset( + v, + &ir::Writeset { + era, + nr_bits: self.nr_blocks, + }, + )?; + } + + Self::generate_era_array(v, self.nr_blocks, era_low)?; + + v.superblock_e()?; + Ok(()) + } +} + +//------------------------------------------ diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 93f6db4..e434e72 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -5,6 +5,8 @@ pub mod cache; pub mod cache_xml_generator; pub mod common_args; +pub mod era; +pub mod era_xml_generator; pub mod fixture; pub mod input_arg; pub mod output_option;