use super::super::*;
#[test]
fn compiler_hash_cache_reuses_hash_for_unchanged_compiler() {
let tmp = tempfile::tempdir().unwrap();
let compiler = tmp.path().join("rustc.exe");
std::fs::write(&compiler, b"fake rustc").unwrap();
let cache = CompilerHashCache::new();
let hash_calls = AtomicUsize::new(0);
let first = cache.get_or_hash_with(&compiler, |_| {
hash_calls.fetch_add(1, Ordering::Relaxed);
Some(ContentHash::from_bytes([7; 32]))
});
let second = cache.get_or_hash_with(&compiler, |_| {
hash_calls.fetch_add(1, Ordering::Relaxed);
Some(ContentHash::from_bytes([9; 32]))
});
assert_eq!(first, Some(ContentHash::from_bytes([7; 32])));
assert_eq!(second, first);
assert_eq!(hash_calls.load(Ordering::Relaxed), 1);
}
#[test]
fn compiler_hash_cache_rehashes_when_compiler_metadata_changes() {
let tmp = tempfile::tempdir().unwrap();
let compiler = tmp.path().join("rustc.exe");
std::fs::write(&compiler, b"fake rustc").unwrap();
filetime::set_file_mtime(
&compiler,
filetime::FileTime::from_unix_time(1_000_000_000, 0),
)
.unwrap();
let cache = CompilerHashCache::new();
let hash_calls = AtomicUsize::new(0);
let first = cache.get_or_hash_with(&compiler, |_| {
hash_calls.fetch_add(1, Ordering::Relaxed);
Some(ContentHash::from_bytes([1; 32]))
});
std::fs::write(&compiler, b"fake rustc changed").unwrap();
filetime::set_file_mtime(
&compiler,
filetime::FileTime::from_unix_time(1_000_000_010, 0),
)
.unwrap();
let second = cache.get_or_hash_with(&compiler, |_| {
hash_calls.fetch_add(1, Ordering::Relaxed);
Some(ContentHash::from_bytes([2; 32]))
});
assert_eq!(first, Some(ContentHash::from_bytes([1; 32])));
assert_eq!(second, Some(ContentHash::from_bytes([2; 32])));
assert_eq!(hash_calls.load(Ordering::Relaxed), 2);
}
#[test]
fn rustc_context_build_reuses_compiler_hash_cache() {
let tmp = tempfile::tempdir().unwrap();
let compiler = tmp.path().join("rustc.exe");
let source = tmp.path().join("lib.rs");
let output = tmp.path().join("libunit.rmeta");
std::fs::write(&compiler, b"fake rustc").unwrap();
std::fs::write(&source, b"pub fn unit() {}").unwrap();
let args: Vec<String> = vec![
"--crate-name".into(),
"unit".into(),
"--edition".into(),
"2021".into(),
"--emit=dep-info,metadata".into(),
source.to_string_lossy().into_owned(),
"-o".into(),
output.to_string_lossy().into_owned(),
];
let compilation = crate::compiler::CacheableCompilation {
compiler: compiler.clone().into(),
family: crate::compiler::CompilerFamily::Rustc,
source_file: source.clone().into(),
output_file: output.into(),
original_args: std::sync::Arc::from(args),
unknown_flags: Vec::new(),
};
let cache = CompilerHashCache::new();
let expected_hash = crate::hash::hash_file(&compiler).ok();
let first = build_rustc_compile_context(&compilation, tmp.path(), &[], &cache);
let second = build_rustc_compile_context(&compilation, tmp.path(), &[], &cache);
let first_hash = match first {
BuildContextResult::Rustc { rustc_ctx, .. } => rustc_ctx.compiler_hash,
BuildContextResult::Cc { .. } => panic!("expected rustc context"),
};
let second_hash = match second {
BuildContextResult::Rustc { rustc_ctx, .. } => rustc_ctx.compiler_hash,
BuildContextResult::Cc { .. } => panic!("expected rustc context"),
};
assert_eq!(first_hash, expected_hash);
assert_eq!(second_hash, expected_hash);
assert_eq!(cache.len(), 1);
}