use std::path::Path;
use std::process::Command;
fn setup_in(dir: &Path) -> toml::Value {
let status = Command::new(env!("CARGO_BIN_EXE_stow-cli"))
.arg("setup")
.current_dir(dir)
.status()
.expect("run stow-cli setup");
assert!(status.success(), "stow-cli setup failed");
let config = std::fs::read_to_string(dir.join(".cargo").join("config.toml"))
.expect("read generated .cargo/config.toml");
toml::from_str(&config).expect("parse generated .cargo/config.toml")
}
fn env_value<'a>(config: &'a toml::Value, key: &str) -> &'a str {
config
.get("env")
.and_then(|env| env.get(key))
.and_then(|entry| entry.get("value"))
.and_then(toml::Value::as_str)
.unwrap_or_else(|| panic!("generated config has no [env] entry for {key}"))
}
#[test]
fn cc_is_invoked_with_compiler_arguments_only() {
if let Err(error) = Command::new("cc").arg("--version").output() {
if error.kind() == std::io::ErrorKind::NotFound {
return;
}
panic!("spawn cc --version: {error}");
}
let dir = tempfile::tempdir().expect("temp dir");
let config = setup_in(dir.path());
std::fs::write(dir.path().join("probe.c"), "int main(void) { return 0; }\n")
.expect("write probe source");
let object = dir.path().join("probe.o");
let status = Command::new(env_value(&config, "CC"))
.arg("-c")
.arg("-o")
.arg(&object)
.arg("probe.c")
.current_dir(dir.path())
.env("STOW_REAL_CC", env_value(&config, "STOW_REAL_CC"))
.status()
.expect("run the CC shim");
assert!(status.success(), "the CC shim failed to compile a probe");
assert!(object.exists(), "the CC shim produced no object file");
}
#[test]
fn the_launcher_and_the_compilers_are_three_different_shims() {
let dir = tempfile::tempdir().expect("temp dir");
let config = setup_in(dir.path());
let cc = env_value(&config, "CC");
let cxx = env_value(&config, "CXX");
let launcher = env_value(&config, "CMAKE_C_COMPILER_LAUNCHER");
assert_ne!(cc, launcher, "CC must not be the launcher-shaped shim");
assert_ne!(cxx, launcher, "CXX must not be the launcher-shaped shim");
assert_ne!(cc, cxx, "CC and CXX must exec different real compilers");
assert_eq!(
launcher,
env_value(&config, "CMAKE_CXX_COMPILER_LAUNCHER"),
"both CMake launcher variables take the same launcher shim"
);
}
#[test]
fn an_explicit_toolchain_survives_setup() {
let dir = tempfile::tempdir().expect("temp dir");
let status = Command::new(env!("CARGO_BIN_EXE_stow-cli"))
.arg("setup")
.current_dir(dir.path())
.env("CC", "/usr/bin/clang")
.env("CXX", "/usr/bin/clang++")
.env_remove("STOW_REAL_CC")
.env_remove("STOW_REAL_CXX")
.status()
.expect("run stow-cli setup");
assert!(status.success(), "stow-cli setup failed");
let config: toml::Value = toml::from_str(
&std::fs::read_to_string(dir.path().join(".cargo").join("config.toml"))
.expect("read generated .cargo/config.toml"),
)
.expect("parse generated .cargo/config.toml");
assert_eq!(env_value(&config, "STOW_REAL_CC"), "/usr/bin/clang");
assert_eq!(env_value(&config, "STOW_REAL_CXX"), "/usr/bin/clang++");
}