#![cfg(test)]
use std::path::PathBuf;
fn repo_root() -> PathBuf {
let dir = env!("CARGO_MANIFEST_DIR");
PathBuf::from(dir)
}
fn install_sh() -> String {
read_repo_file("install.sh")
}
fn read_repo_file(rel: &str) -> String {
let path = repo_root().join(rel);
std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("failed to read {}: {e}", path.display()))
}
mod ort_env_invariants {
use super::*;
#[test]
fn no_ort_lib_path_references() {
let sh = install_sh();
assert!(
!sh.contains("ORT_LIB_PATH"),
"install.sh must not contain ORT_LIB_PATH (obsolete under load-dynamic)"
);
}
#[test]
fn no_ort_prefer_dynamic_link_references() {
let sh = install_sh();
assert!(
!sh.contains("ORT_PREFER_DYNAMIC_LINK"),
"install.sh must not contain ORT_PREFER_DYNAMIC_LINK (obsolete under load-dynamic)"
);
}
}
mod build_line_invariants {
use super::*;
#[test]
fn build_line_uses_onnx_not_onnx_migraphx() {
let sh = install_sh();
let has_cargo_build = sh
.lines()
.any(|line| line.contains("cargo build") && line.contains("--features"));
assert!(
has_cargo_build,
"install.sh must contain a cargo build command with --features"
);
let build_lines: Vec<&str> = sh
.lines()
.filter(|line| {
let trimmed = line.trim_start();
!trimmed.starts_with('#')
})
.filter(|line| line.contains("cargo build") && line.contains("--features"))
.collect();
assert!(
!build_lines.is_empty(),
"install.sh must have at least one non-comment cargo build line with --features"
);
for line in &build_lines {
assert!(
line.contains("onnx"),
"cargo build line must reference the 'onnx' feature (load-dynamic): {line}"
);
assert!(
!line.contains("onnx-migraphx"),
"cargo build line must NOT contain onnx-migraphx (runtime-only under load-dynamic): {line}"
);
}
}
#[test]
fn build_line_does_not_use_download_binaries_or_copy_dylibs() {
let sh = install_sh();
let build_lines: Vec<&str> = sh
.lines()
.filter(|line| {
let trimmed = line.trim_start();
!trimmed.starts_with('#')
})
.filter(|line| line.contains("cargo build") && line.contains("--features"))
.collect();
for line in &build_lines {
assert!(
!line.contains("download-binaries"),
"cargo build line must not enable download-binaries: {line}"
);
assert!(
!line.contains("copy-dylibs"),
"cargo build line must not enable copy-dylibs: {line}"
);
}
}
}
mod bundle_consumption {
use super::*;
#[test]
fn copies_bundled_ort_libs_to_leindex_lib() {
let sh = install_sh();
assert!(
sh.contains("install_ort_libraries"),
"install.sh must define an install_ort_libraries function"
);
assert!(
sh.contains("LEINDEX_HOME") && sh.contains("/lib"),
"install.sh must reference LEINDEX_HOME and a lib/ subdirectory for ORT install"
);
assert!(
sh.contains("libonnxruntime"),
"install.sh must look for libonnxruntime shared library files"
);
}
#[test]
fn copies_bundled_models_to_leindex_models() {
let sh = install_sh();
assert!(
sh.contains("install_model_assets"),
"install.sh must define an install_model_assets function"
);
assert!(
sh.contains("models"),
"install.sh must install model assets to a models/ directory"
);
assert!(
sh.contains("qwen3-embed-0.6b.onnx"),
"install.sh must reference the qwen3-embed-0.6b.onnx model file"
);
}
#[test]
fn prefers_release_bundle_download() {
let sh = install_sh();
assert!(
sh.contains("try_install_from_release_bundle")
|| sh.contains("release bundle")
|| sh.contains("download_bundle"),
"install.sh should attempt to download the pre-built release bundle"
);
}
#[test]
fn release_bundle_path_runs_before_rust_gate() {
let sh = install_sh();
let bundle_idx = sh
.find("try_install_from_release_bundle")
.expect("install.sh must try release bundle install");
let rust_idx = sh
.find("Rust is not installed or is too old")
.expect("install.sh must still validate Rust before source build fallback");
assert!(
bundle_idx < rust_idx,
"pre-built bundle install must be attempted before prompting for Rust"
);
}
}
mod setup_check {
use super::*;
#[test]
fn runs_setup_check_after_install() {
let sh = install_sh();
assert!(
sh.contains("setup --check") || sh.contains("setup\", \"--check"),
"install.sh must run 'leindex setup --check' after install"
);
}
#[test]
fn suggests_leindex_setup_when_unset() {
let sh = install_sh();
assert!(
sh.contains("leindex setup"),
"install.sh should mention 'leindex setup' for enabling neural search"
);
}
}
mod version_parity {
use super::*;
#[test]
fn script_version_matches_cargo_toml() {
let cargo_toml_path = repo_root().join("Cargo.toml");
let cargo_toml = std::fs::read_to_string(&cargo_toml_path)
.unwrap_or_else(|e| panic!("failed to read {}: {e}", cargo_toml_path.display()));
let cargo_version = cargo_toml
.lines()
.find_map(|line| {
let trimmed = line.trim();
trimmed
.strip_prefix("version = ")
.map(|v| v.trim_matches('"'))
})
.expect("Cargo.toml must have a top-level version = \"...\" line");
let sh = install_sh();
let script_version = sh
.lines()
.find_map(|line| {
let trimmed = line.trim();
trimmed
.strip_prefix("readonly SCRIPT_VERSION=")
.or_else(|| trimmed.strip_prefix("SCRIPT_VERSION="))
.map(|v| v.trim_matches('"'))
})
.expect("install.sh must define SCRIPT_VERSION=\"...\"");
assert_eq!(
cargo_version, script_version,
"install.sh SCRIPT_VERSION ({script_version}) must match Cargo.toml version ({cargo_version})"
);
let ps1 = read_repo_file("install.ps1");
assert!(
ps1.contains(&format!(r#"$ScriptVersion = "{cargo_version}""#))
&& ps1.contains(&format!(r#"$ExpectedVersion = "{cargo_version}""#)),
"install.ps1 ScriptVersion and ExpectedVersion must match Cargo.toml version ({cargo_version})"
);
let macos = read_repo_file("install_macos.sh");
assert!(
macos.contains(&format!(r#"readonly SCRIPT_VERSION="{cargo_version}""#)),
"install_macos.sh SCRIPT_VERSION must match Cargo.toml version ({cargo_version})"
);
}
#[test]
fn install_sh_accepts_all_published_macos_bundles() {
let sh = install_sh();
assert!(
!sh.contains("aarch64 only"),
"install.sh must not reject macOS x86_64 when release.yml publishes macos-x86_64"
);
assert!(
sh.contains(r#"asset_name="${os_name}-${arch}""#),
"install.sh should derive the bundle asset name from normalized OS and architecture"
);
}
}
mod exit_handling {
use super::*;
#[test]
fn setup_check_preserves_exit_status_without_or_true() {
let script = install_sh();
assert!(
!script.contains(r#"setup_output=$("$binary" setup --check 2>&1) || true"#),
"run_setup_check must not use `|| true` before capturing setup_exit"
);
assert!(
script.contains("set +e") && script.contains("set -e"),
"run_setup_check should temporarily disable errexit, capture status, then restore errexit"
);
assert!(
script.contains("setup_exit=$?"),
"run_setup_check must capture setup --check exit status"
);
}
#[test]
fn verify_installation_does_not_require_repo_cargo_toml() {
let script = install_sh();
assert!(
script.contains(r#"if [[ -f "Cargo.toml" ]]"#)
&& script.contains(r#"expected_version="$SCRIPT_VERSION""#),
"verify_installation must fall back to SCRIPT_VERSION when install.sh runs outside a repo checkout"
);
}
#[test]
fn model_asset_install_failure_is_checked_by_callers() {
let script = install_sh();
assert!(
script.contains(r#"if ! install_model_assets "$repo_dir"; then"#),
"source install path must check install_model_assets failure"
);
assert!(
script.contains(r#"if ! install_model_assets "$bundle_dir"; then"#),
"bundle install path must check install_model_assets failure"
);
}
}