#[test]
fn detect_is_safe_and_repeatable() {
let first = gpu_probe::detect();
let second = gpu_probe::detect();
assert_eq!(
first.len(),
second.len(),
"the set of detected GPUs should be stable",
);
for (a, b) in first.iter().zip(&second) {
assert_eq!(a.name, b.name, "GPU name should be stable");
assert_eq!(a.vendor, b.vendor, "GPU vendor should be stable");
assert_eq!(
a.total_bytes, b.total_bytes,
"total memory should be stable",
);
}
}
#[test]
fn detected_gpus_satisfy_invariants() {
for gpu in gpu_probe::detect() {
assert!(!gpu.name.is_empty(), "every GPU must have a name");
assert!(
gpu.total_bytes > 0,
"a detected GPU must report some memory"
);
if let Some(free) = gpu.free_bytes {
assert!(free <= gpu.total_bytes, "free cannot exceed total");
}
if let Some(used) = gpu.used_bytes {
assert!(used <= gpu.total_bytes, "used cannot exceed total");
}
assert!(!gpu.to_string().is_empty());
}
}
#[test]
fn gfx_target_is_publicly_usable() {
let target = gpu_probe::GfxTarget::new(10, 1, 3);
assert_eq!(target.to_string(), "gfx1013");
assert!(target >= gpu_probe::GfxTarget::new(10, 1, 0));
for gpu in gpu_probe::detect() {
if let Some(gfx) = gpu.arch_target.and_then(gpu_probe::ArchTarget::gfx) {
assert!(gfx.to_string().starts_with("gfx"));
assert!(gfx.major > 0, "gfx target 0 marks a CPU node, not a GPU");
}
}
}
#[test]
fn arch_target_matches_its_vendor() {
for gpu in gpu_probe::detect() {
match gpu.arch_target {
Some(target) if target.gfx().is_some() => {
assert_eq!(gpu.vendor, gpu_probe::Vendor::Amd, "gfx is AMD-only");
}
Some(target) if target.sm().is_some() => {
assert_eq!(
gpu.vendor,
gpu_probe::Vendor::Nvidia,
"compute capability is NVIDIA-only",
);
}
Some(target) if target.xe().is_some() => {
assert_eq!(gpu.vendor, gpu_probe::Vendor::Intel, "xe is Intel-only");
}
Some(target) if target.apple().is_some() => {
assert_eq!(
gpu.vendor,
gpu_probe::Vendor::Apple,
"a Metal family is Apple-only",
);
}
Some(_) | None => {}
}
if let Some(target) = gpu.arch_target {
assert!(!target.to_string().is_empty());
}
}
}
#[test]
fn rocm_host_is_publicly_usable() {
let version = gpu_probe::RocmVersion::new(6, 2, 4);
assert_eq!(version.to_string(), "6.2.4");
assert!(version >= gpu_probe::RocmVersion::new(6, 0, 0));
if let Some(rocm) = gpu_probe::rocm_host() {
assert!(rocm.version.major > 0, "a real install has a major version");
}
}
#[test]
fn oneapi_host_is_publicly_usable() {
let version = gpu_probe::OneApiVersion::new(2024, 2, 1);
assert_eq!(version.to_string(), "2024.2.1");
assert!(version >= gpu_probe::OneApiVersion::new(2024, 0, 0));
if let Some(oneapi) = gpu_probe::oneapi_host() {
assert!(
oneapi.version.major > 0,
"a real install has a release year"
);
}
}
#[test]
fn vulkan_host_is_publicly_usable() {
let version = gpu_probe::VulkanVersion::new(1, 3, 280);
assert_eq!(version.to_string(), "1.3.280");
assert!(version >= gpu_probe::VulkanVersion::new(1, 2, 0));
if let Some(vulkan) = gpu_probe::vulkan_host() {
assert!(
vulkan.api_version.major > 0,
"a real loader reports a nonzero API version"
);
assert!(
vulkan.api_version >= gpu_probe::VulkanVersion::new(1, 0, 0),
"every ICD advertises at least Vulkan 1.0",
);
assert!(!vulkan.api_version.to_string().is_empty());
assert_eq!(
gpu_probe::vulkan_host(),
Some(vulkan),
"a filesystem probe must not vary between calls",
);
}
}
#[test]
fn vulkan_support_is_independent_of_the_detected_gpus() {
let before = gpu_probe::vulkan_host();
let gpus = gpu_probe::detect();
let after = gpu_probe::vulkan_host();
assert_eq!(
before, after,
"GPU detection must not change the Vulkan answer",
);
assert_eq!(
gpu_probe::detect().len(),
gpus.len(),
"probing Vulkan must not disturb GPU detection",
);
}
#[test]
fn vendor_is_publicly_usable() {
let v = gpu_probe::Vendor::Apple;
let copied = v;
assert_eq!(copied.to_string(), "Apple");
}