use std::path::PathBuf;
use std::{fs, sync::OnceLock};
use miette::{Context, IntoDiagnostic, Result};
use rand::Rng;
static PLACEHOLDER_DATA: OnceLock<String> = OnceLock::new();
fn get_placeholder_data() -> &'static str {
PLACEHOLDER_DATA.get_or_init(|| "PLACEHOLDER\n".repeat(500))
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GeneratedFileNesting {
Flat,
RandomToMax(usize),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TestSubfolderConfiguration {
pub(crate) nesting: GeneratedFileNesting,
pub(crate) file_count: usize,
pub(crate) name: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct GenerateTestFilesArgs {
pub(crate) path: Option<PathBuf>,
pub(crate) subfolder_configs: Vec<TestSubfolderConfiguration>,
}
pub fn generate_test_files(args: GenerateTestFilesArgs) -> Result<Vec<PathBuf>> {
let tmpdir = if let Some(p) = args.path {
p
} else {
tempfile::tempdir()
.into_diagnostic()
.wrap_err("failed to build tempdir")?
.keep()
};
let mut paths = vec![tmpdir.clone()];
for subfolder_config in &args.subfolder_configs {
let subfolder_path = tmpdir.join(&subfolder_config.name);
fs::create_dir(&subfolder_path)
.into_diagnostic()
.wrap_err(format!(
"failed to create path for dir [{}]",
subfolder_path.display()
))?;
paths.push(subfolder_path.clone());
match subfolder_config.nesting {
GeneratedFileNesting::Flat => {
for idx in 0..subfolder_config.file_count {
fs::write(
subfolder_path.join(format!("stub-file-{idx}")),
get_placeholder_data(),
)
.into_diagnostic()
.wrap_err(format!(
"failed to write temporary file in subfolder {} @ idx {idx}",
subfolder_path.display()
))?;
}
}
GeneratedFileNesting::RandomToMax(max_depth) => {
let mut generator = rand::rng();
for idx in 0..subfolder_config.file_count {
let mut generated_path = subfolder_path.clone();
let depth = generator.random_range(0..max_depth);
for _ in 0..depth {
generated_path.push("stub-dir");
}
fs::create_dir_all(&generated_path)
.into_diagnostic()
.wrap_err(format!(
"failed to create randomly generated path [{}]",
generated_path.display()
))?;
fs::write(
generated_path.join(format!("stub-file-{idx}")),
get_placeholder_data(),
)
.into_diagnostic()
.wrap_err(format!(
"failed to write temporary file in subfolder {} @ idx {idx}",
subfolder_path.display()
))?;
}
}
}
}
Ok(paths)
}