use super::*;
#[test]
fn the_probe_describes_this_host() {
let Ok(identity) = identity_without_agent() else {
return;
};
assert!(Path::new(&identity.driver).is_absolute());
assert!(!identity.driver_version.is_empty());
assert!(!identity.linker_version.is_empty());
assert!(
identity.crt_objects.values().all(|d| !d.key().is_empty()),
"{identity:?}"
);
assert!(!identity.driver_version.contains('\n') || identity.driver_version.lines().count() > 1);
for (required, what) in [
(file_probes().startup, "what the link starts with"),
(file_probes().libc, "the libc"),
] {
assert!(
required.is_empty()
|| required
.iter()
.any(|name| identity.crt_objects.contains_key(*name)),
"a resolved identity must pin {what}: {identity:?}"
);
}
if cfg!(target_os = "macos") {
assert!(
identity.sdk.is_some(),
"a macOS host should identify its SDK: {identity:?}"
);
}
}
#[test]
fn the_identity_round_trips_through_its_recorded_form() {
let identity = LinkerIdentity {
driver: "/usr/bin/cc".into(),
driver_version: "cc version 14".into(),
linker_version: "GNU ld 2.42".into(),
crt_objects: BTreeMap::from([("crt1.o".into(), CacheDigest::blake3(b"crt"))]),
sdk: None,
deployment_target: Some("11.0".into()),
};
let recorded = canonical_json(&identity).unwrap();
assert_eq!(
serde_json::from_slice::<LinkerIdentity>(&recorded).unwrap(),
identity
);
}
fn identity_without_agent() -> Result<LinkerIdentity> {
let driver = which::which("cc")?;
probe(&driver, None)
}
#[test]
fn a_fuse_ld_selection_resolves_or_is_refused() {
let Ok(driver) = which::which("cc") else {
return;
};
let bogus = resolve_fuse_ld(&driver, "definitely-not-a-real-linker");
assert!(
bogus.is_err(),
"a nonexistent linker must not resolve: {bogus:?}"
);
let direct = Path::new(if cfg!(windows) { "C:/ld" } else { "/opt/ld" });
assert_eq!(
resolve_fuse_ld(&driver, direct.to_str().unwrap()).unwrap(),
direct
);
for name in ["mold", "lld", "bfd", "gold"] {
if let Ok(program) = resolve_fuse_ld(&driver, name) {
assert!(
program.is_absolute() && program.exists(),
"{name} resolved to {program:?}"
);
}
}
}
#[test]
fn a_link_is_only_identified_once_its_essentials_resolve() {
let directory = tempfile::tempdir().unwrap();
let placed = |name: &str| {
let path = directory.path().join(name);
std::fs::write(&path, name).unwrap();
path
};
let probes = FileProbes {
startup: &["Scrt1.o", "crt1.o"],
libc: &["libc.so.6", "libc.a"],
rest: &["crti.o"],
};
let resolved = probe_files(&probes, |name| {
matches!(name, "crt1.o" | "libc.a").then(|| placed(name))
})
.unwrap();
assert_eq!(
resolved.keys().collect::<Vec<_>>(),
["crt1.o", "libc.a"],
"only what resolved belongs in the key"
);
assert!(
probe_files(&probes, |name| (name == "crt1.o").then(|| placed(name))).is_err(),
"no libc should refuse"
);
assert!(
probe_files(&probes, |name| (name == "libc.a").then(|| placed(name))).is_err(),
"no startup object should refuse"
);
assert!(
probe_files(&probes, |_| None).is_err(),
"nothing should refuse"
);
let glibc = probe_files(&probes, |name| {
matches!(name, "crt1.o" | "libc.so.6").then(|| placed(name))
})
.unwrap();
assert_ne!(glibc, resolved);
}
#[test]
fn a_platform_that_places_nothing_is_still_identified() {
let probes = FileProbes {
startup: &[],
libc: &[],
rest: &[],
};
assert!(probe_files(&probes, |_| None).unwrap().is_empty());
}
#[test]
fn a_windows_identity_requires_toolset_sdk_and_both_crts() {
let version = windows_sdk_identity_for(|name| match name {
"VCToolsVersion" => Some("14.40".into()),
"WindowsSDKVersion" => Some("10.0.26100.0".into()),
_ => None,
})
.unwrap();
assert!(version.contains("VCToolsVersion=14.40"));
assert!(windows_sdk_identity_for(|_| None).is_err());
let directory = tempfile::tempdir().unwrap();
std::fs::write(directory.path().join("vcruntime.lib"), b"vc runtime").unwrap();
std::fs::write(directory.path().join("ucrt.lib"), b"universal crt").unwrap();
let identity = windows_crt_objects_in(&[directory.path().to_path_buf()]).unwrap();
assert_eq!(identity.len(), 2);
std::fs::remove_file(directory.path().join("ucrt.lib")).unwrap();
assert!(windows_crt_objects_in(&[directory.path().to_path_buf()]).is_err());
}
#[cfg(target_os = "macos")]
#[test]
fn the_sdk_identity_follows_sdkroot() {
let Ok(Some(_)) = sdk_identity_for(None) else {
return;
};
let overridden = sdk_identity_for(Some("/nonexistent.sdk".into()));
assert!(
overridden.is_err(),
"an unusable SDKROOT must not report the default SDK: {overridden:?}"
);
}
#[test]
fn the_platform_gate_does_not_depend_on_who_set_the_variable() {
assert_eq!(
crate::session::cache_links_supported(),
cfg!(any(target_os = "linux", target_os = "macos", windows))
);
if !crate::session::cache_links_supported() {
assert!(!crate::session::cache_links_requested());
}
}