[functional-tests] port some of the cache_check tests to Rust
This commit is contained in:
1
src/cache/mod.rs
vendored
Normal file
1
src/cache/mod.rs
vendored
Normal file
@ -0,0 +1 @@
|
||||
pub mod xml;
|
175
src/cache/xml.rs
vendored
Normal file
175
src/cache/xml.rs
vendored
Normal file
@ -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<u8>,
|
||||
}
|
||||
|
||||
#[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<Visit>;
|
||||
fn superblock_e(&mut self) -> Result<Visit>;
|
||||
|
||||
fn mappings_b(&mut self) -> Result<Visit>;
|
||||
fn mappings_e(&mut self) -> Result<Visit>;
|
||||
fn mapping(&mut self, m: &Map) -> Result<Visit>;
|
||||
|
||||
fn hints_b(&mut self) -> Result<Visit>;
|
||||
fn hints_e(&mut self) -> Result<Visit>;
|
||||
fn hint(&mut self, h: &Hint) -> Result<Visit>;
|
||||
|
||||
fn discards_b(&mut self) -> Result<Visit>;
|
||||
fn discards_e(&mut self) -> Result<Visit>;
|
||||
fn discard(&mut self, d: &Discard) -> Result<Visit>;
|
||||
|
||||
fn eof(&mut self) -> Result<Visit>;
|
||||
}
|
||||
|
||||
pub struct XmlWriter<W: Write> {
|
||||
w: Writer<W>,
|
||||
}
|
||||
|
||||
impl<W: Write> XmlWriter<W> {
|
||||
pub fn new(w: W) -> XmlWriter<W> {
|
||||
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<T: Display>(key: &[u8], value: T) -> Attribute {
|
||||
Attribute {
|
||||
key,
|
||||
value: mk_attr_(value),
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> MetadataVisitor for XmlWriter<W> {
|
||||
fn superblock_b(&mut self, sb: &Superblock) -> Result<Visit> {
|
||||
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<Visit> {
|
||||
self.w.write_event(Event::End(BytesEnd::borrowed(b"superblock")))?;
|
||||
Ok(Visit::Continue)
|
||||
}
|
||||
|
||||
fn mappings_b(&mut self) -> Result<Visit> {
|
||||
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<Visit> {
|
||||
self.w.write_event(Event::End(BytesEnd::borrowed(b"mappings")))?;
|
||||
Ok(Visit::Continue)
|
||||
}
|
||||
|
||||
fn mapping(&mut self, m: &Map) -> Result<Visit> {
|
||||
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<Visit> {
|
||||
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<Visit> {
|
||||
self.w.write_event(Event::End(BytesEnd::borrowed(b"hints")))?;
|
||||
Ok(Visit::Continue)
|
||||
}
|
||||
|
||||
fn hint(&mut self, h: &Hint) -> Result<Visit> {
|
||||
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<Visit> {
|
||||
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<Visit> {
|
||||
self.w.write_event(Event::End(BytesEnd::borrowed(b"discards")))?;
|
||||
Ok(Visit::Continue)
|
||||
}
|
||||
|
||||
fn discard(&mut self, d: &Discard) -> Result<Visit> {
|
||||
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<Visit> {
|
||||
Ok(Visit::Continue)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user