use std::{cmp::Ordering, path::Path}; use cuddle_clusters::{process::ProcessOpts, ConcreteComponent, IntoComponent}; use walkdir::DirEntry; pub(crate) async fn run_test_with_components( name: &str, components: Vec, ) -> anyhow::Result<()> { let _ = tracing_subscriber::fmt::try_init(); println!("running for: {name}"); let current_dir = std::env::current_dir()?; let test_folder = current_dir.join("tests").join(name); let actual = test_folder.join("actual"); tokio::fs::create_dir_all(&actual).await?; let expected = test_folder.join("expected"); tokio::fs::create_dir_all(&expected).await?; let components: Vec<_> = components.into_iter().map(|p| p.into_component()).collect(); cuddle_clusters::process_opts( components.clone(), ProcessOpts { path: test_folder.clone(), output: actual.clone(), }, ) .await?; if std::env::var("TEST_OVERRIDE") == Ok("true".to_string()) { cuddle_clusters::process_opts( components, ProcessOpts { path: test_folder, output: expected.clone(), }, ) .await?; } compare(&expected, &actual).await?; Ok(()) } pub(crate) async fn run_test(name: &str) -> anyhow::Result<()> { run_test_with_components(name, Vec::::new()).await } async fn compare(expected: &Path, actual: &Path) -> anyhow::Result<()> { let mut exp = walk_dir(expected)?; let mut act = walk_dir(actual)?; for (exp, act) in (&mut exp).zip(&mut act) { let exp = exp?; let act = act?; if exp.depth() != act.depth() { return Err(anyhow::anyhow!( "path(different depth): expected {} is different from actual: {}", exp.path().display(), act.path().display() )); } if exp.file_type() != act.file_type() { return Err(anyhow::anyhow!( "path(different filetype): expected {} is different from actual: {}", exp.path().display(), act.path().display() )); } if exp.file_name() != act.file_name() { return Err(anyhow::anyhow!( "path(different filename): expected {} is different from actual: {}", exp.path().display(), act.path().display() )); } if exp.metadata()?.is_file() { let exp_file = tokio::fs::read_to_string(exp.path()).await?; let act_file = tokio::fs::read_to_string(act.path()).await?; similar_asserts::assert_eq!(exp_file, act_file); } } if exp.next().is_some() || act.next().is_some() { return Err(anyhow::anyhow!( "path(uneven amount of items): expected: {}, actual: {}", exp.next() .map(|o| match o { Ok(o) => o.path().display().to_string(), Err(_) => "expected: not-found".to_string(), }) .unwrap_or("expected: not-found".into()), act.next() .map(|o| match o { Ok(o) => o.path().display().to_string(), Err(_) => "actual: not-found".to_string(), }) .unwrap_or("actual: not-found".into()), )); } Ok(()) } fn walk_dir(path: &Path) -> anyhow::Result { let mut walkdir = walkdir::WalkDir::new(path) .sort_by(compare_by_file_name) .into_iter(); if let Some(Err(e)) = walkdir.next() { Err(e.into()) } else { Ok(walkdir) } } fn compare_by_file_name(a: &DirEntry, b: &DirEntry) -> Ordering { a.file_name().cmp(b.file_name()) }