in src/compiler/compiler.rs [2662:2788]
fn test_compiler_get_cached_or_compile_force_recache(preprocessor_cache_mode: bool) {
drop(env_logger::try_init());
let creator = new_creator();
let f = TestFixture::new();
let gcc = f.mk_bin("gcc").unwrap();
let runtime = single_threaded_runtime();
let pool = runtime.handle().clone();
let storage = DiskCache::new(
f.tempdir.path().join("cache"),
u64::MAX,
&pool,
PreprocessorCacheModeConfig {
use_preprocessor_cache_mode: preprocessor_cache_mode,
..Default::default()
},
CacheMode::ReadWrite,
);
let storage = Arc::new(storage);
let service = server::SccacheService::mock_with_storage(storage.clone(), pool.clone());
// Write a dummy input file so the preprocessor cache mode can work
std::fs::write(f.tempdir.path().join("foo.c"), "whatever").unwrap();
// Pretend to be GCC.
next_command(
&creator,
Ok(MockChild::new(exit_status(0), "compiler_id=gcc", "")),
);
let c = get_compiler_info(
creator.clone(),
&gcc,
f.tempdir.path(),
&[],
&[],
&pool,
None,
)
.wait()
.unwrap()
.0;
const COMPILER_STDOUT: &[u8] = b"compiler stdout";
const COMPILER_STDERR: &[u8] = b"compiler stderr";
// The compiler should be invoked twice, since we're forcing
// recaching.
let obj = f.tempdir.path().join("foo.o");
for _ in 0..2 {
// The preprocessor invocation.
next_command(
&creator,
Ok(MockChild::new(exit_status(0), "preprocessor output", "")),
);
// The compiler invocation.
let o = obj.clone();
next_command_calls(&creator, move |_| {
// Pretend to compile something.
let mut f = File::create(&o)?;
f.write_all(b"file contents")?;
Ok(MockChild::new(
exit_status(0),
COMPILER_STDOUT,
COMPILER_STDERR,
))
});
}
let cwd = f.tempdir.path();
let arguments = ovec!["-c", "foo.c", "-o", "foo.o"];
let hasher = match c.parse_arguments(&arguments, ".".as_ref(), &[]) {
CompilerArguments::Ok(h) => h,
o => panic!("Bad result from parse_arguments: {:?}", o),
};
let hasher2 = hasher.clone();
let (cached, res) = runtime
.block_on(async {
hasher
.get_cached_or_compile(
&service,
None,
creator.clone(),
storage.clone(),
arguments.clone(),
cwd.to_path_buf(),
vec![],
CacheControl::Default,
pool.clone(),
)
.await
})
.unwrap();
// Ensure that the object file was created.
assert!(fs::metadata(&obj).map(|m| m.len() > 0).unwrap());
match cached {
CompileResult::CacheMiss(MissType::Normal, DistType::NoDist, _, f) => {
// wait on cache write future so we don't race with it!
f.wait().unwrap();
}
_ => panic!("Unexpected compile result: {:?}", cached),
}
assert_eq!(exit_status(0), res.status);
assert_eq!(COMPILER_STDOUT, res.stdout.as_slice());
assert_eq!(COMPILER_STDERR, res.stderr.as_slice());
// Now compile again, but force recaching.
fs::remove_file(&obj).unwrap();
let (cached, res) = hasher2
.get_cached_or_compile(
&service,
None,
creator,
storage,
arguments,
cwd.to_path_buf(),
vec![],
CacheControl::ForceRecache,
pool,
)
.wait()
.unwrap();
// Ensure that the object file was created.
assert!(fs::metadata(&obj).map(|m| m.len() > 0).unwrap());
match cached {
CompileResult::CacheMiss(MissType::ForcedRecache, DistType::NoDist, _, f) => {
// wait on cache write future so we don't race with it!
f.wait().unwrap();
}
_ => panic!("Unexpected compile result: {:?}", cached),
}
assert_eq!(exit_status(0), res.status);
assert_eq!(COMPILER_STDOUT, res.stdout.as_slice());
assert_eq!(COMPILER_STDERR, res.stderr.as_slice());
}