cranpose_core/
test_scratch.rs1use std::{
8 path::{Path, PathBuf},
9 sync::atomic::{AtomicU32, Ordering},
10};
11
12pub fn test_scratch_dir(manifest_dir: &str, tag: &str) -> PathBuf {
26 static COUNTER: AtomicU32 = AtomicU32::new(0);
27 let unique = COUNTER.fetch_add(1, Ordering::Relaxed);
28 let manifest = PathBuf::from(manifest_dir);
29 let owner = manifest
30 .file_name()
31 .map(|name| name.to_string_lossy().into_owned())
32 .unwrap_or_else(|| "workspace".to_string());
33 let path = workspace_root(&manifest)
34 .join("target/test-output")
35 .join(owner)
36 .join(format!("{tag}-{}-{unique}", std::process::id()));
37 let _ = std::fs::remove_dir_all(&path);
38 std::fs::create_dir_all(&path).expect("a scratch directory under target/test-output");
39 path
40}
41
42fn workspace_root(manifest: &Path) -> PathBuf {
43 manifest
44 .ancestors()
45 .find(|directory| directory.join("Cargo.lock").is_file())
46 .unwrap_or(manifest)
47 .to_path_buf()
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn a_scratch_directory_is_empty_under_the_workspace_target() {
56 let path = test_scratch_dir(env!("CARGO_MANIFEST_DIR"), "scratch");
57 assert!(path.is_dir());
58 assert_eq!(std::fs::read_dir(&path).expect("read").count(), 0);
59 assert!(
60 path.components().any(|part| part.as_os_str() == "target"),
61 "the scratch directory belongs under the workspace target: {}",
62 path.display()
63 );
64 let _ = std::fs::remove_dir_all(&path);
65 }
66
67 #[test]
68 fn two_calls_do_not_share_a_directory() {
69 let first = test_scratch_dir(env!("CARGO_MANIFEST_DIR"), "scratch");
70 let second = test_scratch_dir(env!("CARGO_MANIFEST_DIR"), "scratch");
71 assert_ne!(first, second);
72 let _ = std::fs::remove_dir_all(&first);
73 let _ = std::fs::remove_dir_all(&second);
74 }
75}