use crate::{RocmHost, RocmVersion};
use std::path::{Path, PathBuf};
const DEFAULT_ROOT: &str = "/opt/rocm";
const VERSION_FILE: &str = ".info/version";
fn parse_version(content: &str) -> Option<RocmVersion> {
let (major, minor, patch) = crate::parse_dotted_version(content)?;
Some(RocmVersion {
major,
minor,
patch,
})
}
fn version_at(root: &Path) -> Option<RocmVersion> {
std::fs::read_to_string(root.join(VERSION_FILE))
.ok()
.and_then(|content| parse_version(&content))
}
fn roots() -> Vec<PathBuf> {
let mut roots = Vec::new();
if let Some(path) = std::env::var_os("ROCM_PATH") {
roots.push(PathBuf::from(path));
}
roots.push(PathBuf::from(DEFAULT_ROOT));
roots
}
pub(crate) fn host() -> Option<RocmHost> {
let version = roots().iter().find_map(|root| version_at(root))?;
Some(RocmHost { version })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_release_with_build_suffix() {
assert_eq!(
parse_version("6.2.4-123\n"),
Some(RocmVersion::new(6, 2, 4))
);
assert_eq!(parse_version("5.7.1-63"), Some(RocmVersion::new(5, 7, 1)));
assert_eq!(
parse_version(" 6.0.0-91 "),
Some(RocmVersion::new(6, 0, 0))
);
}
#[test]
fn parses_release_without_suffix_or_patch() {
assert_eq!(parse_version("6.2.4"), Some(RocmVersion::new(6, 2, 4)));
assert_eq!(parse_version("6.2"), Some(RocmVersion::new(6, 2, 0)));
assert_eq!(parse_version("6.2+build"), Some(RocmVersion::new(6, 2, 0)));
}
#[test]
fn rejects_malformed_versions() {
assert_eq!(parse_version(""), None);
assert_eq!(parse_version("6"), None, "a bare major is not a version");
assert_eq!(parse_version("six.two.four"), None);
assert_eq!(parse_version("6.2.x"), None);
assert_eq!(parse_version("-6.2.4"), None);
}
#[test]
fn versions_order_major_first() {
assert!(RocmVersion::new(6, 2, 4) > RocmVersion::new(6, 2, 0));
assert!(RocmVersion::new(6, 0, 0) > RocmVersion::new(5, 7, 1));
assert!(RocmVersion::new(6, 10, 0) > RocmVersion::new(6, 9, 9));
}
#[test]
fn missing_install_root_reports_nothing() {
assert_eq!(version_at(Path::new("/nonexistent-rocm-root")), None);
}
#[test]
fn rocm_path_is_searched_before_the_default() {
let roots = roots();
assert_eq!(
roots.last().map(PathBuf::as_path),
Some(Path::new(DEFAULT_ROOT)),
"the conventional prefix is always the fallback",
);
if std::env::var_os("ROCM_PATH").is_some() {
assert_eq!(roots.len(), 2, "an explicit ROCM_PATH is tried first");
}
}
#[test]
fn host_lookup_never_panics() {
if let Some(rocm) = host() {
assert!(rocm.version.major > 0);
}
}
}