in src/compiler/compiler.rs [2792:2877]
fn test_compiler_get_cached_or_compile_preprocessor_error(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());
// Pretend to be GCC. Also inject a fake object file that the subsequent
// preprocessor failure should remove.
let obj = f.tempdir.path().join("foo.o");
// Write a dummy input file so the preprocessor cache mode can work
std::fs::write(f.tempdir.path().join("foo.c"), "whatever").unwrap();
let o = obj.clone();
next_command_calls(&creator, move |_| {
let mut f = File::create(&o)?;
f.write_all(b"file contents")?;
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;
// We should now have a fake object file.
assert!(fs::metadata(&obj).is_ok());
// The preprocessor invocation.
const PREPROCESSOR_STDERR: &[u8] = b"something went wrong";
next_command(
&creator,
Ok(MockChild::new(
exit_status(1),
b"preprocessor output",
PREPROCESSOR_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 (cached, res) = runtime
.block_on(async {
hasher
.get_cached_or_compile(
&service,
None,
creator,
storage,
arguments,
cwd.to_path_buf(),
vec![],
CacheControl::Default,
pool,
)
.await
})
.unwrap();
assert_eq!(cached, CompileResult::Error);
assert_eq!(exit_status(1), res.status);
// Shouldn't get anything on stdout, since that would just be preprocessor spew!
assert_eq!(b"", res.stdout.as_slice());
assert_eq!(PREPROCESSOR_STDERR, res.stderr.as_slice());
// Errors in preprocessing should remove the object file.
assert!(fs::metadata(&obj).is_err());
}