use std::path::Path;
use rucc_sysroot::{BUNDLED_GLIBC, Kernel, Sysroot, bundled_glibc_minor, layout::can_be_bundled};
use rucc_tuple::{TARGETS, TargetEntry, TargetTuple};
fn target(tuple: &str) -> TargetTuple {
tuple.parse().expect("a target this understands")
}
#[test]
fn the_cache_key_is_the_whole_tuple() {
let cache = Path::new("/cache");
let mut keys: Vec<String> = TARGETS
.iter()
.map(|entry| {
let row = TargetEntry::parse(entry).expect("the table parses");
Sysroot::in_cache(cache, row).cache_key()
})
.collect();
let total = keys.len();
keys.sort();
keys.dedup();
assert_eq!(keys.len(), total, "two rows of the table share a sysroot directory");
}
#[test]
fn a_pinned_libc_version_is_a_different_sysroot() {
let cache = Path::new("/cache");
let plain = Sysroot::in_cache(cache, target("x86_64-linux-gnu"));
let pinned = Sysroot::in_cache(cache, target("x86_64-linux-gnu.2.28"));
assert_ne!(plain.cache_key(), pinned.cache_key());
assert_ne!(plain.root(), pinned.root());
}
#[test]
fn the_baseline_within_an_architecture_does_not_change_the_header_directory() {
let cache = Path::new("/cache");
let hard = Sysroot::in_cache(cache, target("armv7a-linux-musleabihf"));
let soft = Sysroot::in_cache(cache, target("armv5te-linux-musleabi"));
assert_eq!(hard.header_arch(), "arm");
assert_eq!(soft.header_arch(), "arm");
assert_ne!(hard.cache_key(), soft.cache_key());
}
#[test]
fn the_two_libcs_split_x32_in_two_different_places() {
let cache = Path::new("/cache");
let x32 = Sysroot::in_cache(cache, target("x86_64-linux-gnux32"));
let lp64 = Sysroot::in_cache(cache, target("x86_64-linux-gnu"));
assert_eq!(x32.header_arch(), "x86");
assert_eq!(lp64.header_arch(), "x86");
assert_ne!(x32.cache_key(), lp64.cache_key());
let musl_x32 = Sysroot::in_cache(cache, target("x86_64-linux-muslx32"));
let musl_lp64 = Sysroot::in_cache(cache, target("x86_64-linux-musl"));
assert_eq!(musl_x32.header_arch(), "x32");
assert_eq!(musl_lp64.header_arch(), "x86_64");
}
#[test]
fn glibc_names_its_header_directory_after_the_family_and_musl_after_the_architecture() {
let cache = Path::new("/cache");
for (tuple, family, own) in [
("i686-linux-gnu", "x86", "i386"),
("riscv64-linux-gnu", "riscv", "riscv64"),
("powerpc64le-linux-gnu", "powerpcle", "powerpc64"),
("loongarch64-linux-gnu", "loongarch", "loongarch64"),
] {
let gnu = Sysroot::in_cache(cache, target(tuple));
assert_eq!(gnu.header_arch(), family, "{tuple} reads the wrong glibc directory");
let musl = Sysroot::in_cache(cache, target(&tuple.replace("-gnu", "-musl")));
assert_eq!(musl.header_arch(), own, "{tuple} reads the wrong musl directory");
}
}
#[test]
fn the_byte_order_is_in_the_glibc_directory_name_for_powerpc_and_for_no_other_family() {
let cache = Path::new("/cache");
let le = Sysroot::in_cache(cache, target("powerpc64le-linux-gnu"));
let be = Sysroot::in_cache(cache, target("powerpc64-linux-gnu"));
assert_eq!(le.header_arch(), "powerpcle");
assert_eq!(be.header_arch(), "powerpc");
assert_ne!(le.arch_include(), be.arch_include());
for (little, big) in [
("aarch64-linux-gnu", "aarch64_be-linux-gnu"),
("armv7-linux-gnueabihf", "armv7eb-linux-gnueabihf"),
] {
let one = Sysroot::in_cache(cache, target(little));
let other = Sysroot::in_cache(cache, target(big));
assert_eq!(
one.header_arch(),
other.header_arch(),
"{little} and {big} read the same text and should read the same directory"
);
assert_ne!(one.cache_key(), other.cache_key());
}
let musl_le = Sysroot::in_cache(cache, target("powerpc64le-linux-musl"));
let musl_be = Sysroot::in_cache(cache, target("powerpc64-linux-musl"));
assert_eq!(musl_le.header_arch(), "powerpc64");
assert_eq!(musl_be.header_arch(), "powerpc64");
}
#[test]
fn the_architecture_specific_headers_are_searched_before_the_generic_ones() {
let sysroot = Sysroot::in_cache(Path::new("/cache"), target("aarch64-linux-musl"));
let includes = sysroot.includes();
assert_eq!(includes[0], sysroot.arch_include());
assert_eq!(includes[1], sysroot.generic_include());
assert!(includes[0].ends_with("include/aarch64"));
assert!(includes[1].ends_with("include/generic"));
}
#[test]
fn everything_is_under_the_root_and_nothing_is_absolute_from_somewhere_else() {
let sysroot = Sysroot::in_cache(Path::new("/cache"), target("aarch64-linux-musl"));
for path in
[sysroot.arch_include(), sysroot.generic_include(), sysroot.lib(), sysroot.manifest_path()]
{
assert!(path.starts_with(sysroot.root()), "{} escaped the root", path.display());
}
}
#[test]
fn the_two_licence_walls_are_the_only_targets_we_cannot_bundle() {
for entry in TARGETS {
let row = TargetEntry::parse(entry).expect("the table parses");
let expected = !matches!(
(row.os(), row.env()),
(rucc_tuple::Os::MacOs | rucc_tuple::Os::IOs, _) | (_, rucc_tuple::Env::Msvc)
);
assert_eq!(can_be_bundled(row), expected, "{}", entry.tuple);
}
assert!(can_be_bundled(target("aarch64-linux-musl")));
assert!(can_be_bundled(target("x86_64-pc-windows-gnu")));
assert!(!can_be_bundled(target("x86_64-pc-windows-msvc")));
assert!(!can_be_bundled(target("aarch64-macos")));
assert!(can_be_bundled(target("armv7m-none-eabi")));
}
#[test]
fn the_kernel_headers_are_shared_rather_than_copied_per_target() {
let cache = Path::new("/cache");
let gnu = Kernel::for_target(cache, target("x86_64-linux-gnu")).expect("x86-64 has a kernel");
let musl = Kernel::for_target(cache, target("x86_64-linux-musl")).expect("so does musl");
let arm = Kernel::for_target(cache, target("aarch64-linux-gnu")).expect("so does aarch64");
assert_eq!(gnu, musl, "the libc does not change the kernel's headers");
assert_eq!(gnu.generic_include(), arm.generic_include());
assert_ne!(gnu.arch_include(), arm.arch_include());
assert!(!gnu.arch_include().starts_with("/cache/sysroots"));
}
#[test]
fn the_kernel_has_its_own_name_for_the_machine() {
let cache = Path::new("/cache");
for (tuple, arch) in [
("aarch64-linux-gnu", "arm64"),
("s390x-linux-gnu", "s390"),
("x86_64-linux-gnu", "x86"),
("i686-linux-gnu", "x86"),
("riscv64-linux-gnu", "riscv"),
("powerpc64le-linux-gnu", "powerpc"),
("loongarch64-linux-gnu", "loongarch"),
("armv7a-linux-gnueabihf", "arm"),
] {
let kernel = Kernel::for_target(cache, target(tuple)).expect("a Linux target has a kernel");
assert_eq!(kernel.arch(), arch, "{tuple} reads the wrong asm directory");
assert!(kernel.arch_include().ends_with(arch));
}
}
#[test]
fn only_linux_with_a_libc_we_produce_has_kernel_headers() {
let cache = Path::new("/cache");
for tuple in ["x86_64-pc-windows-gnu", "aarch64-macos", "armv7m-none-eabi", "wasm32-wasi"] {
assert!(Kernel::for_target(cache, target(tuple)).is_none(), "{tuple} has no kernel tree");
}
assert!(Kernel::for_target(cache, target("aarch64-linux-android")).is_none());
assert!(Kernel::for_target(cache, target("x86_64-linux-gnu")).is_some());
}
#[test]
fn the_kernels_asm_is_searched_before_its_shared_tree() {
let cache = Path::new("/cache");
let kernel = Kernel::for_target(cache, target("aarch64-linux-musl")).expect("a kernel");
let includes = kernel.includes();
assert_eq!(includes[0], kernel.arch_include());
assert_eq!(includes[1], kernel.generic_include());
assert!(includes[0].ends_with("kernel-headers/arm64"));
assert!(includes[1].ends_with("kernel-headers/generic"));
}
#[test]
fn the_version_macro_is_the_one_the_target_asked_for_and_the_trees_own_otherwise() {
let asked = target("x86_64-linux-gnu.2.28");
assert_eq!(bundled_glibc_minor(asked), Ok(Some(28)));
let plain = target("x86_64-linux-gnu");
assert_eq!(bundled_glibc_minor(plain), Ok(Some(BUNDLED_GLIBC.minor_part().unwrap())));
assert_eq!(bundled_glibc_minor(target("x86_64-linux-gnu.2")), bundled_glibc_minor(plain));
}
#[test]
fn nothing_but_glibc_gets_a_glibc_version_macro() {
for tuple in ["x86_64-linux-musl", "x86_64-pc-windows-gnu", "aarch64-macos", "armv7m-none-eabi"]
{
assert_eq!(bundled_glibc_minor(target(tuple)), Ok(None), "{tuple}");
}
}
#[test]
fn a_release_newer_than_the_tree_is_refused_rather_than_approximated() {
let skew =
bundled_glibc_minor(target("x86_64-linux-gnu.2.99")).expect_err("newer than the tree");
assert_eq!(skew.tree, BUNDLED_GLIBC);
assert_eq!(skew.asked.to_string(), "2.99");
assert!(skew.to_string().contains("2.99") && skew.to_string().contains("2.44"));
assert!(bundled_glibc_minor(target("x86_64-linux-gnu.3.0")).is_err());
assert!(bundled_glibc_minor(target("x86_64-linux-gnu.1.9")).is_err());
}