in src/compiler/compiler.rs [2882:2994]
fn test_compiler_get_cached_or_compile_dist_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 = Runtime::new().unwrap();
let pool = runtime.handle().clone();
let dist_clients = vec![
test_dist::ErrorPutToolchainClient::new(),
test_dist::ErrorAllocJobClient::new(),
test_dist::ErrorSubmitToolchainClient::new(),
test_dist::ErrorRunJobClient::new(),
];
// Write a dummy input file so the preprocessor cache mode can work
std::fs::write(f.tempdir.path().join("foo.c"), "whatever").unwrap();
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);
// 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 dist_clients.iter() {
// 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),
};
// All these dist clients will fail, but should still result in successful compiles
for dist_client in dist_clients {
let service = server::SccacheService::mock_with_dist_client(
dist_client.clone(),
storage.clone(),
pool.clone(),
);
if obj.is_file() {
fs::remove_file(&obj).unwrap();
}
let hasher = hasher.clone();
let (cached, res) = hasher
.get_cached_or_compile(
&service,
Some(dist_client.clone()),
creator.clone(),
storage.clone(),
arguments.clone(),
cwd.to_path_buf(),
vec![],
CacheControl::ForceRecache,
pool.clone(),
)
.wait()
.expect("Does not error if storage put fails. qed");
// Ensure that the object file was created.
assert!(fs::metadata(&obj).map(|m| m.len() > 0).unwrap());
match cached {
CompileResult::CacheMiss(MissType::ForcedRecache, DistType::Error, _, 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());
}
}