use alloc::string::String;
use std::format;
use std::fs::File;
use std::io::copy;
use std::process::Command;
use std::sync::atomic::{AtomicU32, Ordering};
use spin::Lazy;
use crate::error::Error;
pub const LOREM: &str = include_str!("../tests/lorem.txt");
pub const LOREM_LENGTH: usize = LOREM.len();
static DEVICE_ID: Lazy<AtomicU32> = Lazy::new(AtomicU32::default);
pub fn new_device_id() -> u32 {
DEVICE_ID.fetch_add(1, Ordering::Relaxed)
}
static FILE_ID: Lazy<AtomicU32> = Lazy::new(AtomicU32::default);
pub fn new_file_id() -> u32 {
FILE_ID.fetch_add(1, Ordering::Relaxed)
}
pub fn copy_file(path: &str) -> Result<String, Error<!>> {
let mut real_file = File::open(path)?;
let temp_file_name = format!("{path}_{}", new_file_id());
let mut temp_file = File::create(&temp_file_name)?;
copy(&mut real_file, &mut temp_file)?;
Ok(temp_file_name)
}
#[derive(Debug, PartialEq, Eq)]
pub enum PostCheck {
Ext,
None,
}
impl PostCheck {
pub fn run(self, file_path: &str) -> Result<(), Error<!>> {
match self {
Self::Ext => {
let output = Command::new("e2fsck").arg("-f").arg("-v").arg("-n").arg(file_path).output()?;
if output.status.success() {
Ok(())
} else {
Err(Error::IO(deku::no_std_io::Error::new(
deku::no_std_io::ErrorKind::Other,
String::from_utf8(output.stdout)
.unwrap_or_else(|_| unreachable!("e2fsck's output is valid UTF-8")),
)))
}
},
Self::None => Ok(()),
}
}
}
macro_rules! generate_fs_test {
($func_name:ident, $input_file:tt) => {
generate_fs_test!($func_name, $input_file, crate::tests::PostCheck::None, true);
};
($func_name:ident, $input_file:tt, $post_check:expr) => {
generate_fs_test!($func_name, $input_file, $post_check, true);
};
($func_name:ident, $input_file:tt, $post_check:expr, $clear:expr) => {
#[test]
fn $func_name() {
let file_name = crate::tests::copy_file($input_file).unwrap();
let file = std::fs::OpenOptions::new().read(true).write(true).open(&file_name).unwrap();
super::$func_name(file);
match $post_check.run(&file_name) {
Ok(()) => {
if $clear {
std::fs::remove_file(&file_name).unwrap();
}
},
Err(err) => {
if $clear {
std::fs::remove_file(&file_name).unwrap();
}
panic!("Post Check Error: {err}");
},
}
}
};
}
pub(crate) use generate_fs_test;