mithril_common/digesters/
dummy_immutable_db_builder.rsuse crate::test_utils::TempDir;
use crate::{digesters::ImmutableFile, entities::ImmutableFileNumber};
use std::{
fs::File,
io::prelude::Write,
path::{Path, PathBuf},
};
const IMMUTABLE_DIR: &str = "immutable";
const LEDGER_DIR: &str = "ledger";
const VOLATILE_DIR: &str = "volatile";
pub struct DummyImmutablesDbBuilder {
dir: PathBuf,
immutables_to_write: Vec<ImmutableFileNumber>,
non_immutables_to_write: Vec<String>,
append_uncompleted_trio: bool,
immutable_file_size: Option<u64>,
ledger_files_to_write: Vec<String>,
ledger_file_size: Option<u64>,
volatile_files_to_write: Vec<String>,
volatile_file_size: Option<u64>,
}
pub struct DummyImmutableDb {
pub dir: PathBuf,
pub immutables_files: Vec<ImmutableFile>,
pub non_immutables_files: Vec<PathBuf>,
}
impl DummyImmutableDb {
pub fn add_immutable_file(&mut self) -> ImmutableFileNumber {
let new_file_number = self.last_immutable_number().unwrap_or(0) + 1;
let mut new_files = write_immutable_trio(None, &self.dir, new_file_number);
self.immutables_files.append(&mut new_files);
new_file_number
}
pub fn last_immutable_number(&self) -> Option<ImmutableFileNumber> {
self.immutables_files.last().map(|f| f.number)
}
}
impl DummyImmutablesDbBuilder {
pub fn new(dir_name: &str) -> Self {
Self {
dir: get_test_dir(dir_name),
immutables_to_write: vec![],
non_immutables_to_write: vec![],
append_uncompleted_trio: false,
immutable_file_size: None,
ledger_files_to_write: vec![],
ledger_file_size: None,
volatile_files_to_write: vec![],
volatile_file_size: None,
}
}
pub fn with_immutables(&mut self, immutables: &[ImmutableFileNumber]) -> &mut Self {
self.immutables_to_write = immutables.to_vec();
self
}
pub fn with_non_immutables(&mut self, non_immutables: &[&str]) -> &mut Self {
self.non_immutables_to_write = non_immutables.iter().map(|f| f.to_string()).collect();
self
}
pub fn with_ledger_files(&mut self, files: &[&str]) -> &mut Self {
self.ledger_files_to_write = files.iter().map(|name| name.to_string()).collect();
self
}
pub fn set_ledger_file_size(&mut self, file_size: u64) -> &mut Self {
self.ledger_file_size = Some(file_size);
self
}
pub fn with_volatile_files(&mut self, files: &[&str]) -> &mut Self {
self.volatile_files_to_write = files.iter().map(|f| f.to_string()).collect();
self
}
pub fn set_volatile_file_size(&mut self, file_size: u64) -> &mut Self {
self.volatile_file_size = Some(file_size);
self
}
pub fn append_immutable_trio(&mut self) -> &mut Self {
self.append_uncompleted_trio = true;
self
}
pub fn set_immutable_trio_file_size(&mut self, trio_file_size: u64) -> &mut Self {
assert!(
trio_file_size % 3 == 0,
"'trio_file_size' must be a multiple of 3"
);
self.immutable_file_size = Some(trio_file_size / 3);
self
}
pub fn build(&self) -> DummyImmutableDb {
let mut non_immutables_files = vec![];
let mut immutable_numbers = self.immutables_to_write.clone();
immutable_numbers.sort();
if self.append_uncompleted_trio {
write_immutable_trio(
self.immutable_file_size,
&self.dir.join(IMMUTABLE_DIR),
match immutable_numbers.last() {
None => 0,
Some(last) => last + 1,
},
);
}
for non_immutable in &self.non_immutables_to_write {
non_immutables_files.push(write_dummy_file(
self.immutable_file_size,
&self.dir.join(IMMUTABLE_DIR),
non_immutable,
));
}
for filename in &self.ledger_files_to_write {
write_dummy_file(self.ledger_file_size, &self.dir.join(LEDGER_DIR), filename);
}
for filename in &self.volatile_files_to_write {
write_dummy_file(
self.volatile_file_size,
&self.dir.join(VOLATILE_DIR),
filename,
);
}
DummyImmutableDb {
dir: self.dir.join(IMMUTABLE_DIR),
immutables_files: immutable_numbers
.into_iter()
.flat_map(|ifn| {
write_immutable_trio(
self.immutable_file_size,
&self.dir.join(IMMUTABLE_DIR),
ifn,
)
})
.collect::<Vec<_>>(),
non_immutables_files,
}
}
}
fn write_immutable_trio(
optional_size: Option<u64>,
dir: &Path,
immutable: ImmutableFileNumber,
) -> Vec<ImmutableFile> {
let mut result = vec![];
for filename in [
format!("{immutable:05}.chunk"),
format!("{immutable:05}.primary"),
format!("{immutable:05}.secondary"),
] {
let file = write_dummy_file(optional_size, dir, &filename);
result.push(ImmutableFile {
number: immutable.to_owned(),
path: file,
filename: filename.to_string(),
});
}
result
}
fn write_dummy_file(optional_size: Option<u64>, dir: &Path, filename: &str) -> PathBuf {
let file = dir.join(Path::new(filename));
let mut source_file = File::create(&file).unwrap();
write!(source_file, "This is a test file named '{filename}'").unwrap();
if let Some(file_size) = optional_size {
writeln!(source_file).unwrap();
source_file.set_len(file_size).unwrap();
}
file
}
fn get_test_dir(subdir_name: &str) -> PathBuf {
let db_dir = TempDir::create("test_cardano_db", subdir_name);
for subdir_name in [LEDGER_DIR, IMMUTABLE_DIR, VOLATILE_DIR] {
std::fs::create_dir(db_dir.join(subdir_name)).unwrap();
}
db_dir
}