use super::*;
fn generation(root: &Path, name: &str) -> PathBuf {
let path = root.join(name);
std::fs::create_dir_all(path.join("cargo-target")).expect("toolchain cache generation");
std::fs::write(path.join(USE_STAMP), []).expect("use stamp");
std::thread::sleep(Duration::from_millis(10));
path
}
#[test]
fn only_the_live_key_and_the_newest_retained_generation_survive_a_sweep() {
let directory = tempfile::tempdir().expect("temp directory");
let root = toolchain_cache_root(directory.path());
let oldest = generation(&root, "oldest");
let middle = generation(&root, "middle");
let newest = generation(&root, "newest");
let live_key = "live".to_string();
let live = generation(&root, &live_key);
let stray = root.join("stray-file");
std::fs::write(&stray, b"leftover").expect("stray file");
purge_toolchain_cache_root(directory.path(), &BTreeSet::from([live_key]), SystemTime::now(), 1)
.expect("sweeping the toolchain cache root");
assert!(
live.is_dir(),
"the key this run is about to use must never be reclaimed"
);
assert!(
newest.is_dir(),
"the most recently used stale generation must be retained at generations = 1"
);
assert!(
!middle.exists(),
"a stale generation beyond the retention cap must be reclaimed"
);
assert!(
!oldest.exists(),
"a stale generation beyond the retention cap must be reclaimed"
);
assert!(!stray.exists(), "a stray file in the cache root must be removed");
}
#[test]
fn a_cache_a_concurrent_run_is_still_writing_into_is_never_reclaimed() {
let directory = tempfile::tempdir().expect("temp directory");
let root = toolchain_cache_root(directory.path());
let concurrent = generation(&root, "another-processes-key");
purge_toolchain_cache_root(directory.path(), &BTreeSet::new(), SystemTime::UNIX_EPOCH, 0)
.expect("sweeping the toolchain cache root");
assert!(
concurrent.is_dir(),
"a cache modified inside the grace window must survive a sweep that retains no generations"
);
}
#[test]
fn the_reclaim_cutoff_trails_the_present_by_the_run_timeout_plus_the_abandoned_grace() {
let timeout_secs = 120;
let cutoff = reclaim_cutoff(timeout_secs).expect("a cutoff for an ordinary timeout");
let age = SystemTime::now()
.duration_since(cutoff)
.expect("the cutoff is in the past");
let grace = Duration::from_secs(timeout_secs + ABANDONED_GRACE_SECS);
assert!(
age >= grace,
"the cutoff must be at least {grace:?} in the past, was {age:?}"
);
assert!(
age < grace + Duration::from_secs(5),
"the cutoff must trail the present by the grace window and nothing more, was {age:?}"
);
}
#[test]
fn stamping_a_cache_refreshes_its_recency_without_any_toolchain_write() {
let directory = tempfile::tempdir().expect("temp directory");
let caches = ToolchainCaches {
root: directory.path().join("key"),
go_build: directory.path().join("key/go-build"),
zig_global: directory.path().join("key/zig-global"),
cargo_target: directory.path().join("key/cargo-target"),
};
std::fs::create_dir_all(&caches.cargo_target).expect("toolchain cache directories");
let before = last_used(&caches.root);
std::thread::sleep(Duration::from_millis(10));
caches.mark_used();
assert!(
last_used(&caches.root) > before,
"stamping a cache must make it more recently used than it was"
);
}