use std::path::{Path, PathBuf};
use std::sync::RwLock;
pub const ORT_DYLIB_ENV: &str = "ORT_DYLIB_PATH";
const LEINDEX_HOME_ENV: &str = "LEINDEX_HOME";
#[cfg(feature = "onnx")]
const LEINDEX_PYTHON_ENV: &str = "LEINDEX_PYTHON";
static LAST_OUTCOME: RwLock<Option<DiscoveryOutcome>> = RwLock::new(None);
fn ort_lib_names() -> &'static [&'static str] {
#[cfg(target_os = "linux")]
{
&["libonnxruntime.so"]
}
#[cfg(target_os = "macos")]
{
&["libonnxruntime.dylib"]
}
#[cfg(target_os = "windows")]
{
&["onnxruntime.dll"]
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
&["libonnxruntime.so"]
}
}
#[cfg(any(feature = "onnx", test))]
fn is_ort_runtime_lib_name(name: &str) -> bool {
#[cfg(target_os = "linux")]
{
name == "libonnxruntime.so" || name.starts_with("libonnxruntime.so.")
}
#[cfg(target_os = "macos")]
{
name == "libonnxruntime.dylib"
|| (name.starts_with("libonnxruntime.") && name.ends_with(".dylib"))
}
#[cfg(target_os = "windows")]
{
name.eq_ignore_ascii_case("onnxruntime.dll")
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
ort_lib_names().iter().any(|candidate| candidate == &name)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DiscoverySource {
EnvVar,
Config,
UserLib,
Sibling,
Pip,
System,
}
impl DiscoverySource {
pub fn as_str(self) -> &'static str {
match self {
DiscoverySource::EnvVar => "env",
DiscoverySource::Config => "config",
DiscoverySource::UserLib => "user_lib",
DiscoverySource::Sibling => "sibling",
DiscoverySource::Pip => "pip",
DiscoverySource::System => "system",
}
}
}
impl std::fmt::Display for DiscoverySource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiscoveryOutcome {
pub source: DiscoverySource,
pub path: PathBuf,
}
#[derive(Debug)]
pub enum InitResult {
Initialized(DiscoveryOutcome),
NotFound {
searched: Vec<(DiscoverySource, String)>,
last_error: Option<String>,
},
}
impl InitResult {
pub fn is_initialized(&self) -> bool {
matches!(self, InitResult::Initialized(_))
}
}
pub fn last_outcome() -> Option<DiscoveryOutcome> {
LAST_OUTCOME.read().ok().and_then(|outcome| outcome.clone())
}
#[cfg_attr(not(feature = "onnx"), allow(dead_code))]
fn record_last_outcome(outcome: Option<DiscoveryOutcome>) {
if let Ok(mut cached) = LAST_OUTCOME.write() {
*cached = outcome;
}
}
fn leindex_home() -> Option<PathBuf> {
if let Ok(custom) = std::env::var(LEINDEX_HOME_ENV) {
let p = PathBuf::from(custom);
if p.is_absolute() {
return Some(p);
}
}
dirs::home_dir().map(|h| h.join(".leindex"))
}
fn read_config_ort_path() -> Option<PathBuf> {
crate::config::LeIndexConfig::load()
.ok()
.and_then(|cfg| cfg.neural.ort_dylib_path)
.filter(|path| !path.trim().is_empty())
.map(PathBuf::from)
.and_then(|path| resolve_config_ort_path(&path))
}
fn resolve_config_ort_path(config_path: &Path) -> Option<PathBuf> {
if config_path.exists() {
return Some(config_path.to_path_buf());
}
let parent = config_path.parent()?;
let prefix = "libonnxruntime.so";
let mut versioned: Vec<PathBuf> = Vec::new();
let entries = std::fs::read_dir(parent).ok()?;
for entry in entries.filter_map(|e| e.ok()) {
let name = entry.file_name();
let Some(name_str) = name.to_str() else {
continue;
};
if name_str == prefix {
return Some(entry.path());
}
if name_str.starts_with(prefix) && !name_str.ends_with(".debug") {
versioned.push(entry.path());
}
}
pick_best_ort_lib(&versioned)
}
#[cfg(any(feature = "onnx", test))]
fn find_lib_in_dir(dir: &Path) -> Option<PathBuf> {
for name in ort_lib_names() {
let candidate = dir.join(name);
if candidate.is_file() {
return Some(candidate);
}
}
let matches: Vec<PathBuf> = std::fs::read_dir(dir)
.ok()?
.filter_map(Result::ok)
.map(|entry| entry.path())
.filter(|path| {
path.file_name()
.and_then(|name| name.to_str())
.map(is_ort_runtime_lib_name)
.unwrap_or(false)
})
.collect();
pick_best_ort_lib(&matches)
}
const MIN_ORT_VERSION: (u64, u64, u64) = (1, 24, 0);
fn parse_ort_version_tuple(name: &str) -> Option<(u64, u64, u64)> {
let digits: Vec<u64> = name
.split(|c: char| !c.is_ascii_digit())
.filter(|part| !part.is_empty())
.filter_map(|part| part.parse::<u64>().ok())
.collect();
match digits.as_slice() {
[major, minor, patch, ..] => Some((*major, *minor, *patch)),
_ => None,
}
}
fn pick_best_ort_lib(paths: &[PathBuf]) -> Option<PathBuf> {
let mut keyed: Vec<(bool, (u64, u64, u64), PathBuf)> = paths
.iter()
.map(|path| {
let name = path
.file_name()
.and_then(|name| name.to_str())
.unwrap_or_default();
let version = parse_ort_version_tuple(name).unwrap_or((0, 0, 0));
(version >= MIN_ORT_VERSION, version, path.clone())
})
.collect();
keyed.sort_by(|a, b| b.0.cmp(&a.0).then_with(|| b.1.cmp(&a.1)));
keyed.into_iter().next().map(|(_, _, path)| path)
}
fn binary_dir() -> Option<PathBuf> {
std::env::current_exe()
.ok()
.and_then(|p| p.parent().map(Path::to_path_buf))
}
#[cfg(any(feature = "onnx", test))]
fn leindex_cache_dir() -> Option<PathBuf> {
leindex_home().map(|h| h.join("cache"))
}
#[cfg(any(feature = "onnx", test))]
fn ort_pip_cache_path() -> Option<PathBuf> {
leindex_cache_dir().map(|d| d.join("ort_pip_path"))
}
#[cfg(any(feature = "onnx", test))]
fn write_ort_pip_cache(path: &Path) {
let Some(cache_path) = ort_pip_cache_path() else {
return;
};
if let Some(parent) = cache_path.parent() {
if std::fs::create_dir_all(parent).is_err() {
return;
}
}
let _ = std::fs::write(&cache_path, path.display().to_string());
}
#[cfg(any(feature = "onnx", test))]
fn read_ort_pip_cache() -> Option<PathBuf> {
let cache_path = ort_pip_cache_path()?;
let cached = std::fs::read_to_string(&cache_path).ok()?;
let trimmed = cached.trim();
if trimmed.is_empty() {
return None;
}
let path = PathBuf::from(trimmed);
if path.is_file() { Some(path) } else { None }
}
#[cfg(any(feature = "onnx", test))]
fn user_site_packages_dirs() -> Vec<PathBuf> {
let mut dirs = Vec::new();
if let Some(home) = dirs::home_dir() {
let local_lib = home.join(".local").join("lib");
if let Ok(entries) = std::fs::read_dir(&local_lib) {
for entry in entries.flatten() {
let path = entry.path();
let capi = path.join("site-packages").join("onnxruntime").join("capi");
if capi.is_dir() {
dirs.push(capi);
}
}
}
}
dirs
}
#[cfg(any(feature = "onnx", test))]
fn system_site_packages_dirs() -> Vec<PathBuf> {
let mut dirs = Vec::new();
for prefix in ["/usr/local/lib", "/usr/lib"] {
let lib = PathBuf::from(prefix);
if let Ok(entries) = std::fs::read_dir(&lib) {
for entry in entries.flatten() {
let path = entry.path();
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
if name.starts_with("python") {
let capi = path.join("site-packages").join("onnxruntime").join("capi");
if capi.is_dir() {
dirs.push(capi);
}
let dist_capi = path.join("dist-packages").join("onnxruntime").join("capi");
if dist_capi.is_dir() {
dirs.push(dist_capi);
}
}
}
}
}
dirs
}
#[cfg(any(feature = "onnx", test))]
pub fn discover_pip_lib_filesystem() -> Option<PathBuf> {
if let Some(cached) = read_ort_pip_cache() {
tracing::debug!("ORT pip path loaded from cache: {}", cached.display());
return find_lib_in_dir_with(&cached).or(Some(cached));
}
for dir in user_site_packages_dirs() {
if let Some(path) = find_lib_in_dir(&dir) {
write_ort_pip_cache(&path);
tracing::debug!(
"ORT pip path found via user site-packages scan: {}",
path.display()
);
return Some(path);
}
}
for dir in system_site_packages_dirs() {
if let Some(path) = find_lib_in_dir(&dir) {
write_ort_pip_cache(&path);
tracing::debug!(
"ORT pip path found via system site-packages scan: {}",
path.display()
);
return Some(path);
}
}
None
}
#[cfg(any(feature = "onnx", test))]
fn find_lib_in_dir_with(dir: &Path) -> Option<PathBuf> {
find_lib_in_dir(dir)
}
#[cfg(feature = "onnx")]
fn python_one_line(program: &str) -> Option<String> {
let mut candidates: Vec<std::process::Command> = Vec::new();
if let Ok(exe) = std::env::var(LEINDEX_PYTHON_ENV) {
candidates.push(std::process::Command::new(exe));
}
candidates.push(std::process::Command::new("python3"));
candidates.push(std::process::Command::new("python"));
for mut cmd in candidates {
cmd.arg("-c").arg(program);
cmd.stdin(std::process::Stdio::null());
cmd.stdout(std::process::Stdio::piped());
cmd.stderr(std::process::Stdio::null());
match cmd.output() {
Ok(out) if out.status.success() => {
let s = String::from_utf8_lossy(&out.stdout).trim().to_string();
if !s.is_empty() {
return Some(s);
}
}
_ => continue,
}
}
None
}
#[cfg(feature = "onnx")]
fn discover_pip_lib() -> Option<PathBuf> {
if let Some(path) = discover_pip_lib_filesystem() {
return Some(path);
}
let program = "import os,onnxruntime.capi as c; print(os.path.dirname(c.__file__))";
let capi_dir = python_one_line(program)?;
let dir = PathBuf::from(capi_dir);
if !dir.is_dir() {
return None;
}
let path = find_lib_in_dir(&dir)?;
write_ort_pip_cache(&path);
tracing::debug!(
"ORT pip path found via Python subprocess (cached for future runs): {}",
path.display()
);
Some(path)
}
fn system_lib_dirs() -> Vec<PathBuf> {
#[cfg(unix)]
{
vec![
PathBuf::from("/usr/local/lib"),
PathBuf::from("/usr/lib"),
PathBuf::from("/lib"),
]
}
#[cfg(not(unix))]
{
Vec::new()
}
}
pub fn discover_candidates() -> Vec<(DiscoverySource, PathBuf)> {
let mut out: Vec<(DiscoverySource, PathBuf)> = Vec::new();
if let Ok(path) = std::env::var(ORT_DYLIB_ENV) {
if !path.is_empty() {
out.push((DiscoverySource::EnvVar, PathBuf::from(path)));
}
}
if let Some(path) = read_config_ort_path() {
out.push((DiscoverySource::Config, path));
}
if let Some(home) = leindex_home() {
let lib_dir = home.join("lib");
for name in ort_lib_names() {
out.push((DiscoverySource::UserLib, lib_dir.join(name)));
}
}
if let Some(bin_dir) = binary_dir() {
for name in ort_lib_names() {
out.push((DiscoverySource::Sibling, bin_dir.join(name)));
}
if let Some(bundle_root) = bin_dir.parent() {
let bundle_lib = bundle_root.join("lib");
for name in ort_lib_names() {
out.push((DiscoverySource::Sibling, bundle_lib.join(name)));
}
}
}
out
}
fn system_candidates() -> Vec<(DiscoverySource, PathBuf)> {
let mut out: Vec<(DiscoverySource, PathBuf)> = Vec::new();
for dir in system_lib_dirs() {
for name in ort_lib_names() {
out.push((DiscoverySource::System, dir.join(name)));
}
}
out
}
#[cfg(feature = "onnx")]
pub fn discover_and_init() -> InitResult {
let mut searched: Vec<(DiscoverySource, String)> = Vec::new();
let mut last_error: Option<String> = None;
let mut try_path = |source: DiscoverySource,
path: PathBuf,
require_exists: bool|
-> Option<DiscoveryOutcome> {
if require_exists && !path.exists() {
searched.push((source, path.display().to_string()));
return None;
}
match ort::init_from(&path) {
Ok(builder) => {
let _ = builder.commit();
let outcome = DiscoveryOutcome { source, path };
record_last_outcome(Some(outcome.clone()));
tracing::info!(
"loaded ONNX Runtime dylib from {} [{}]",
outcome.path.display(),
outcome.source
);
Some(outcome)
}
Err(e) => {
let msg = format!("init_from({}) failed: {}", path.display(), e);
tracing::warn!("{}", msg);
last_error = Some(msg);
searched.push((source, path.display().to_string()));
None
}
}
};
for (source, path) in discover_candidates() {
if let Some(outcome) = try_path(source, path, true) {
return InitResult::Initialized(outcome);
}
}
if let Some(path) = discover_pip_lib() {
if let Some(outcome) = try_path(DiscoverySource::Pip, path, true) {
return InitResult::Initialized(outcome);
}
}
for (source, path) in system_candidates() {
if let Some(outcome) = try_path(source, path, true) {
return InitResult::Initialized(outcome);
}
}
if let Some(outcome) = try_path(
DiscoverySource::System,
PathBuf::from(ort_lib_names()[0]),
false,
) {
return InitResult::Initialized(outcome);
}
record_last_outcome(None);
InitResult::NotFound {
searched,
last_error,
}
}
#[cfg(not(feature = "onnx"))]
pub fn discover_and_init() -> InitResult {
InitResult::NotFound {
searched: Vec::new(),
last_error: None,
}
}
pub fn discover_path_only() -> Option<DiscoveryOutcome> {
for (source, path) in discover_candidates() {
if path.exists() {
return Some(DiscoveryOutcome { source, path });
}
}
#[cfg(feature = "onnx")]
if let Some(path) = discover_pip_lib() {
if path.exists() {
return Some(DiscoveryOutcome {
source: DiscoverySource::Pip,
path,
});
}
}
for (source, path) in system_candidates() {
if path.exists() {
return Some(DiscoveryOutcome { source, path });
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use crate::embed::test_util::ENV_TEST_LOCK;
fn make_fake_lib(dir: &Path) -> PathBuf {
let name = ort_lib_names()[0];
let p = dir.join(name);
std::fs::write(&p, b"not a real ort lib").unwrap();
p
}
#[test]
fn test_discover_candidates_includes_env_var() {
let _g = ENV_TEST_LOCK.lock().unwrap();
let tmp = tempfile::tempdir().unwrap();
unsafe { std::env::set_var(ORT_DYLIB_ENV, tmp.path().join("env.so")) };
let candidates = discover_candidates();
assert!(
candidates
.iter()
.any(|(s, p)| *s == DiscoverySource::EnvVar && p == &tmp.path().join("env.so"))
);
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
}
#[test]
fn test_discover_candidates_excludes_empty_env() {
let _g = ENV_TEST_LOCK.lock().unwrap();
unsafe { std::env::set_var(ORT_DYLIB_ENV, "") };
let candidates = discover_candidates();
assert!(
!candidates
.iter()
.any(|(s, _)| *s == DiscoverySource::EnvVar)
);
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
}
#[test]
fn test_discover_candidates_includes_user_lib() {
let _g = ENV_TEST_LOCK.lock().unwrap();
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
let tmp = tempfile::tempdir().unwrap();
unsafe { std::env::set_var(LEINDEX_HOME_ENV, tmp.path()) };
let candidates = discover_candidates();
let expected = tmp.path().join("lib").join(ort_lib_names()[0]);
assert!(
candidates
.iter()
.any(|(s, p)| *s == DiscoverySource::UserLib && p == &expected)
);
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
}
#[test]
fn test_discover_candidates_includes_bundle_lib_next_to_bin() {
let _g = ENV_TEST_LOCK.lock().unwrap();
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
let candidates = discover_candidates();
if let Some(bin_dir) = binary_dir() {
if let Some(bundle_root) = bin_dir.parent() {
let expected = bundle_root.join("lib").join(ort_lib_names()[0]);
assert!(
candidates
.iter()
.any(|(s, p)| *s == DiscoverySource::Sibling && p == &expected)
);
}
}
}
#[test]
fn test_discover_candidates_includes_system_paths() {
let _g = ENV_TEST_LOCK.lock().unwrap();
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
let candidates = system_candidates();
#[cfg(unix)]
{
assert!(
candidates
.iter()
.any(|(s, p)| *s == DiscoverySource::System && p.starts_with("/usr/local/lib"))
);
}
}
#[test]
fn test_read_config_ort_path_returns_value() {
let _g = ENV_TEST_LOCK.lock().unwrap();
let tmp = tempfile::tempdir().unwrap();
unsafe { std::env::set_var(LEINDEX_HOME_ENV, tmp.path()) };
let lib_dir = tmp.path().join("ort");
std::fs::create_dir_all(&lib_dir).unwrap();
let lib_path = lib_dir.join("libonnxruntime.so");
std::fs::write(&lib_path, b"fake").unwrap();
let cfg_dir = tmp.path().join("config");
std::fs::create_dir_all(&cfg_dir).unwrap();
let cfg_path = cfg_dir.join("leindex.toml");
std::fs::write(
&cfg_path,
format!(
"[neural]\nenabled = true\nort_dylib_path = \"{}\"\nmodel_dir = \"~/.leindex/models\"\n",
lib_path.display()
),
)
.unwrap();
let parsed = read_config_ort_path();
assert_eq!(parsed, Some(lib_path));
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
}
#[test]
fn test_read_config_ort_path_returns_none_when_missing() {
let _g = ENV_TEST_LOCK.lock().unwrap();
let tmp = tempfile::tempdir().unwrap();
unsafe { std::env::set_var(LEINDEX_HOME_ENV, tmp.path()) };
assert_eq!(read_config_ort_path(), None);
let cfg_dir = tmp.path().join("config");
std::fs::create_dir_all(&cfg_dir).unwrap();
std::fs::write(
cfg_dir.join("leindex.toml"),
"[search]\nmode = \"hybrid\"\n",
)
.unwrap();
assert_eq!(read_config_ort_path(), None);
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
}
#[test]
fn test_read_config_ort_path_handles_single_quotes() {
let _g = ENV_TEST_LOCK.lock().unwrap();
let tmp = tempfile::tempdir().unwrap();
unsafe { std::env::set_var(LEINDEX_HOME_ENV, tmp.path()) };
let lib_dir = tmp.path().join("quote");
std::fs::create_dir_all(&lib_dir).unwrap();
let lib_path = lib_dir.join("libonnxruntime.so");
std::fs::write(&lib_path, b"fake").unwrap();
let cfg_dir = tmp.path().join("config");
std::fs::create_dir_all(&cfg_dir).unwrap();
std::fs::write(
cfg_dir.join("leindex.toml"),
format!("[neural]\nort_dylib_path = '{}'\n", lib_path.display()),
)
.unwrap();
assert_eq!(read_config_ort_path(), Some(lib_path));
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
}
#[cfg(target_os = "linux")]
#[test]
fn test_resolve_config_ort_path_finds_versioned_fallback() {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path().join("capi");
std::fs::create_dir_all(&dir).unwrap();
let actual = dir.join("libonnxruntime.so.1.23.2");
std::fs::write(&actual, b"fake").unwrap();
let stale = dir.join("libonnxruntime.so.1.27.1");
let resolved = resolve_config_ort_path(&stale);
assert_eq!(resolved, Some(actual));
}
#[test]
fn test_resolve_config_ort_path_prefers_exact_so() {
let tmp = tempfile::tempdir().unwrap();
let dir = tmp.path().join("lib");
std::fs::create_dir_all(&dir).unwrap();
let exact = dir.join("libonnxruntime.so");
std::fs::write(&exact, b"fake").unwrap();
let versioned = dir.join("libonnxruntime.so.1.25.0");
std::fs::write(&versioned, b"fake").unwrap();
let stale = dir.join("libonnxruntime.so.1.27.1");
let resolved = resolve_config_ort_path(&stale);
assert_eq!(resolved, Some(exact));
}
#[test]
fn test_resolve_config_ort_path_returns_existing() {
let tmp = tempfile::tempdir().unwrap();
let existing = tmp.path().join("libonnxruntime.so");
std::fs::write(&existing, b"fake").unwrap();
let resolved = resolve_config_ort_path(&existing);
assert_eq!(resolved, Some(existing));
}
#[test]
fn test_find_lib_in_dir_finds_matching_name() {
let tmp = tempfile::tempdir().unwrap();
let p = make_fake_lib(tmp.path());
assert_eq!(find_lib_in_dir(tmp.path()), Some(p));
}
#[test]
fn test_find_lib_in_dir_returns_none_when_empty() {
let tmp = tempfile::tempdir().unwrap();
assert_eq!(find_lib_in_dir(tmp.path()), None);
}
#[cfg(target_os = "linux")]
#[test]
fn test_find_lib_in_dir_accepts_linux_versioned_pip_soname() {
let temp = tempfile::tempdir().unwrap();
let versioned = temp.path().join("libonnxruntime.so.1.25.0");
std::fs::write(&versioned, b"fake").unwrap();
let found =
find_lib_in_dir(temp.path()).expect("versioned pip ORT library should be found");
assert_eq!(found, versioned);
}
#[cfg(target_os = "linux")]
#[test]
fn test_find_lib_in_dir_uses_numeric_version_order() {
let temp = tempfile::tempdir().unwrap();
let older = temp.path().join("libonnxruntime.so.1.9.0");
let newer = temp.path().join("libonnxruntime.so.1.10.0");
std::fs::write(&older, b"fake-older").unwrap();
std::fs::write(&newer, b"fake-newer").unwrap();
let found = find_lib_in_dir(temp.path()).expect("ORT library should be found");
assert_eq!(found, newer);
}
#[cfg(target_os = "linux")]
#[test]
fn test_find_lib_in_dir_prefers_unversioned_link_when_present() {
let temp = tempfile::tempdir().unwrap();
let unversioned = temp.path().join("libonnxruntime.so");
let versioned = temp.path().join("libonnxruntime.so.1.25.0");
std::fs::write(&versioned, b"fake-versioned").unwrap();
std::fs::write(&unversioned, b"fake-unversioned").unwrap();
let found = find_lib_in_dir(temp.path()).expect("ORT library should be found");
assert_eq!(found, unversioned);
}
#[test]
fn test_discover_path_only_checks_pip_before_system() {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/src/embed/ort_discovery.rs");
let src = std::fs::read_to_string(path).unwrap();
let helper = src
.split("pub fn discover_path_only()")
.nth(1)
.and_then(|s| s.split("\n}\n\n").next())
.expect("discover_path_only must exist");
let pip = helper
.find("discover_pip_lib")
.expect("path-only discovery must check pip");
let system = helper
.find("system_candidates")
.expect("path-only discovery must check system");
assert!(
pip < system,
"path-only discovery must prefer pip over system"
);
}
#[test]
fn test_bare_loader_fallback_does_not_require_path_exists() {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/src/embed/ort_discovery.rs");
let src = std::fs::read_to_string(path).unwrap();
let helper = src
.split("pub fn discover_and_init()")
.nth(1)
.and_then(|s| s.split("\n}\n\n#[cfg(not(feature = \"onnx\"))]").next())
.expect("discover_and_init must exist");
let bare_probe = "PathBuf::from(ort_lib_names()[0])";
let bare_probe_pos = helper
.find(bare_probe)
.expect("discover_and_init must try the bare ORT library name");
let after_bare_probe = &helper[bare_probe_pos..];
assert!(
after_bare_probe.contains("false"),
"bare dynamic-loader fallback must call try_path with require_exists=false"
);
}
#[test]
fn test_source_as_str_covers_all_variants() {
assert_eq!(DiscoverySource::EnvVar.as_str(), "env");
assert_eq!(DiscoverySource::Config.as_str(), "config");
assert_eq!(DiscoverySource::UserLib.as_str(), "user_lib");
assert_eq!(DiscoverySource::Sibling.as_str(), "sibling");
assert_eq!(DiscoverySource::Pip.as_str(), "pip");
assert_eq!(DiscoverySource::System.as_str(), "system");
}
#[test]
fn test_init_result_is_initialized() {
let r1 = InitResult::Initialized(DiscoveryOutcome {
source: DiscoverySource::Pip,
path: PathBuf::from("/x/y/libonnxruntime.so"),
});
assert!(r1.is_initialized());
let r2 = InitResult::NotFound {
searched: Vec::new(),
last_error: None,
};
assert!(!r2.is_initialized());
}
#[test]
fn test_discover_path_only_returns_first_existing_no_init() {
let _g = ENV_TEST_LOCK.lock().unwrap();
let tmp = tempfile::tempdir().unwrap();
let fake_lib = make_fake_lib(tmp.path());
unsafe { std::env::set_var(ORT_DYLIB_ENV, &fake_lib) };
let before = last_outcome();
let outcome = discover_path_only();
let after = last_outcome();
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
let outcome = outcome.expect("discover_path_only should find the env candidate");
assert_eq!(outcome.source, DiscoverySource::EnvVar);
assert_eq!(outcome.path, fake_lib);
assert_eq!(
before, after,
"discover_path_only must not cache LAST_OUTCOME (no init_from() side effect)"
);
}
#[test]
fn test_discover_path_only_returns_none_when_absent() {
let _g = ENV_TEST_LOCK.lock().unwrap();
unsafe { std::env::remove_var(ORT_DYLIB_ENV) };
let tmp = tempfile::tempdir().unwrap();
unsafe { std::env::set_var(LEINDEX_HOME_ENV, tmp.path()) };
let _ = discover_path_only();
unsafe { std::env::remove_var(LEINDEX_HOME_ENV) };
}
#[test]
fn test_discover_pip_lib_filesystem_returns_none_when_no_site_packages() {
let _ = discover_pip_lib_filesystem();
}
#[test]
fn test_user_site_packages_dirs_is_callable() {
let dirs = user_site_packages_dirs();
let _ = dirs;
}
#[test]
fn test_system_site_packages_dirs_is_callable() {
let dirs = system_site_packages_dirs();
let _ = dirs;
}
}