#![cfg(test)]
use std::path::PathBuf;
fn repo_root() -> PathBuf {
let dir = env!("CARGO_MANIFEST_DIR");
PathBuf::from(dir)
}
fn read_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 no_ort_fallback_notice {
use super::*;
#[test]
fn worker_runtime_emits_actionable_notice_when_ort_missing() {
let src = read_file("crates/leindex-embed/src/runtime.rs");
let not_found_branch = src
.split("InitResult::NotFound")
.nth(1)
.and_then(|s| s.split("return (None, None, Duration::ZERO)").next())
.expect("runtime.rs must handle InitResult::NotFound and fall back");
assert!(
not_found_branch.contains("leindex setup"),
"the no-ORT notice MUST mention `leindex setup`; got: {}",
not_found_branch
);
assert!(
not_found_branch.contains("ORT_DYLIB_PATH")
|| not_found_branch.contains("ort_dylib_path"),
"the no-ORT notice MUST mention ORT_DYLIB_PATH as a remediation; got: {}",
not_found_branch
);
assert!(
not_found_branch.contains("neural embeddings disabled")
|| not_found_branch.contains("TF-IDF"),
"the no-ORT notice MUST indicate TF-IDF fallback / neural disabled; got: {}",
not_found_branch
);
}
#[test]
fn npm_wrapper_does_not_override_fallback_notice() {
let wrapper = read_file("packages/npm-leindex-mcp/bin/mcp-wrapper.js");
assert!(
!wrapper.contains("neural embeddings disabled"),
"npm wrapper must NOT emit its own neural-disabled notice; the Rust worker is authoritative"
);
assert!(
!wrapper.contains("neural is disabled"),
"npm wrapper must NOT emit its own neural-disabled notice; the Rust worker is authoritative"
);
}
#[test]
fn pypi_wrapper_does_not_override_fallback_notice() {
let wrapper = read_file("packages/pypi-leindex/src/leindex/bootstrap.py");
assert!(
!wrapper.contains("neural embeddings disabled"),
"PyPI wrapper must NOT emit its own neural-disabled notice"
);
assert!(
!wrapper.contains("neural is disabled"),
"PyPI wrapper must NOT emit its own neural-disabled notice"
);
}
#[test]
fn worker_inherits_stderr_so_notice_reaches_user() {
let src = read_file("src/search/onnx/client.rs");
assert!(
src.contains("Stdio::inherit()"),
"the EmbeddingClient must inherit worker stderr so the no-ORT notice reaches the user"
);
}
}
mod ort_discovery_priority {
use super::*;
#[test]
fn env_var_is_highest_priority_in_rust_discovery() {
let src = read_file("crates/leindex-embed/src/ort_discovery.rs");
let candidates_fn = src
.split("pub fn discover_candidates()")
.nth(1)
.and_then(|s| s.split("}\n\n///").next())
.expect("discover_candidates() must exist");
let env_position = candidates_fn.find("ORT_DYLIB_ENV");
let config_position = candidates_fn.find("read_config_ort_path");
let user_lib_position = candidates_fn
.find("home.join(\"lib\")")
.or_else(|| candidates_fn.find("DiscoverySource::UserLib"));
let sibling_position = candidates_fn.find("binary_dir()");
assert!(
env_position.is_some(),
"discovery must consult ORT_DYLIB_PATH"
);
assert!(
config_position.is_some(),
"discovery must consult config ort_dylib_path"
);
assert!(
user_lib_position.is_some(),
"discovery must consult ~/.leindex/lib/"
);
assert!(
sibling_position.is_some(),
"discovery must consult the sibling dir of the binary"
);
let env = env_position.unwrap();
let cfg = config_position.unwrap();
let ul = user_lib_position.unwrap();
let sib = sibling_position.unwrap();
assert!(
env < cfg && cfg < ul && ul < sib,
"discovery chain MUST be ordered: ORT_DYLIB_PATH -> config -> user_lib -> sibling (got env={}, cfg={}, user_lib={}, sib={})",
env, cfg, ul, sib
);
}
#[test]
fn pip_discovery_precedes_system_discovery() {
let src = read_file("crates/leindex-embed/src/ort_discovery.rs");
let discover_fn = src
.split("pub fn discover_and_init()")
.nth(1)
.and_then(|s| s.split("\n}\n\n///").next())
.expect("discover_and_init() must exist");
let pip_pos = discover_fn
.find("discover_pip_lib")
.expect("discover_and_init must consult pip ORT");
let system_pos = discover_fn
.find("system_candidates")
.or_else(|| discover_fn.find("DiscoverySource::System"))
.expect("discover_and_init must consult system ORT");
assert!(
pip_pos < system_pos,
"pip ORT must be tried before system ORT so setup-installed ORT wins over stale system libraries"
);
}
#[test]
fn npm_wrapper_respects_user_ort_dylib_path_override() {
let wrapper = read_file("packages/npm-leindex-mcp/bin/mcp-wrapper.js");
assert!(
wrapper.contains("!env.ORT_DYLIB_PATH")
|| wrapper.contains("!process.env.ORT_DYLIB_PATH"),
"npm wrapper must NOT override a user-supplied ORT_DYLIB_PATH"
);
}
#[test]
fn bundle_ort_discoverable_via_sibling_and_user_lib() {
let src = read_file("crates/leindex-embed/src/ort_discovery.rs");
assert!(
src.contains("binary_dir()"),
"discovery must search the sibling dir of the running binary (bundle zero-setup)"
);
assert!(
src.contains("home.join(\"lib\")"),
"discovery must search ~/.leindex/lib/ (install.sh placement)"
);
}
#[test]
fn install_sh_copies_bundled_libs_to_leindex_lib() {
let sh = read_file("install.sh");
assert!(
sh.contains("install_ort_libraries"),
"install.sh must define install_ort_libraries()"
);
assert!(
sh.contains("LEINDEX_HOME") && sh.contains("/lib"),
"install.sh must place bundled libs under $LEINDEX_HOME/lib"
);
assert!(
sh.contains("libonnxruntime"),
"install.sh must look for libonnxruntime shared libraries"
);
}
}
mod setup_idempotency_and_preservation {
use super::*;
#[test]
fn config_save_overwrites_in_place_without_duplicating() {
let src = read_file("src/cli/neural_config.rs");
let save_fn = src
.split("pub fn save(&self) -> Result<PathBuf, ConfigError>")
.nth(1)
.and_then(|s| s.split("\n }\n\n /// Read config").next())
.expect("LeIndexConfig::save() must exist");
assert!(
save_fn.contains("create_dir_all"),
"save() must create the config dir if missing (idempotent re-run after upgrade)"
);
assert!(
save_fn.contains("std::fs::write"),
"save() must atomically overwrite the file (no append path that duplicates keys)"
);
assert!(
!save_fn.contains("append"),
"save() must NOT use append mode (would duplicate keys across runs)"
);
}
#[test]
fn setup_loads_existing_config_before_writing() {
let setup = read_file("src/cli/leindex/setup.rs");
assert!(
setup.contains("load_or_recover"),
"setup must load the existing config before re-writing (preserves user choices on upgrade)"
);
}
#[test]
fn install_sh_preserves_leindex_home_by_default() {
let sh = read_file("install.sh");
assert!(
sh.contains("has_existing") || sh.contains("existing"),
"install.sh must detect the existing LeIndex home and let the user opt in to wipe"
);
assert!(
sh.contains("Preserving all existing data")
|| sh.contains("Keep all flag set - preserving all existing data"),
"install.sh must preserve existing data by default"
);
}
#[test]
fn installer_offers_selective_preserve_menu() {
let sh = read_file("install.sh");
assert!(
sh.contains("PRESERVE_BINARY")
&& sh.contains("PRESERVE_CONFIG")
&& sh.contains("PRESERVE_DATA"),
"install.sh must expose PRESERVE_BINARY / PRESERVE_CONFIG / PRESERVE_DATA flags for selective preserve"
);
assert!(
sh.contains("Select what to preserve:"),
"install.sh must present a selective-preserve menu so users can keep config/data"
);
let uninstall_path = repo_root().join("uninstall.sh");
if uninstall_path.exists() {
let un = std::fs::read_to_string(&uninstall_path).unwrap_or_default();
assert!(
un.contains("preserved") || un.contains("Preserve") || un.contains("backup"),
"uninstall.sh must offer a preserve/backup affordance so the user can keep config/data"
);
}
}
#[test]
fn setup_skips_model_download_when_checksum_matches() {
let setup = read_file("src/cli/leindex/setup.rs");
assert!(
setup.contains("already present, checksum verified"),
"setup must skip re-download when the on-disk model checksum matches"
);
}
}
mod version_parity {
use super::*;
fn extract_version(toml: &str) -> Option<String> {
for line in toml.lines() {
let trimmed = line.trim();
if let Some(rest) = trimmed.strip_prefix("version = ") {
let v = rest.trim().trim_matches('"');
if !v.is_empty() {
return Some(v.to_string());
}
}
}
None
}
#[test]
fn all_surfaces_share_same_version() {
let cargo = read_file("Cargo.toml");
let npm_pkg = read_file("packages/npm-leindex-mcp/package.json");
let pypi_proj = read_file("packages/pypi-leindex/pyproject.toml");
let install_sh = read_file("install.sh");
let cargo_v = extract_version(&cargo).expect("Cargo.toml version");
let npm_v = npm_pkg
.lines()
.find_map(|line| {
let trimmed = line.trim();
trimmed
.strip_prefix("\"version\":")
.map(|v| v.trim().trim_matches(',').trim_matches('"'))
})
.expect("npm package.json version");
let pypi_v = extract_version(&pypi_proj).expect("pyproject.toml version");
let install_v = install_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 SCRIPT_VERSION");
assert_eq!(
cargo_v, npm_v,
"npm version drift: cargo={} npm={}",
cargo_v, npm_v
);
assert_eq!(
cargo_v, pypi_v,
"PyPI version drift: cargo={} pypi={}",
cargo_v, pypi_v
);
assert_eq!(
cargo_v, install_v,
"install.sh version drift: cargo={} install.sh={}",
cargo_v, install_v
);
}
#[test]
fn leindex_embed_matches_root_version() {
let cargo = read_file("Cargo.toml");
let embed = read_file("crates/leindex-embed/Cargo.toml");
let cargo_v = extract_version(&cargo).expect("Cargo.toml version");
let embed_v = extract_version(&embed).expect("leindex-embed Cargo.toml version");
assert_eq!(cargo_v, embed_v, "embed subcrate version drift");
}
}
mod diagnostics_ort_info {
use super::*;
#[test]
fn diagnostics_command_reports_ort_info() {
let cli = read_file("src/cli/cli.rs");
for key in ["ort_path", "ort_version", "execution_provider"] {
let needle = format!("\"{}\":", key);
assert!(
cli.contains(&needle),
"diagnostics JSON must include `{}` (got needle: {})",
key,
needle
);
}
assert!(
cli.contains("fn collect_ort_diagnostics()"),
"diagnostics command must define collect_ort_diagnostics()"
);
assert!(
cli.contains("discover_path_only"),
"collect_ort_diagnostics must use discover_path_only so the reported path matches the worker's discovery chain"
);
assert!(
cli.contains("LeIndexConfig::load"),
"collect_ort_diagnostics must read the user config (ort_version, execution_provider)"
);
}
#[test]
fn diagnostics_does_not_load_ort_into_main_process() {
let cli = read_file("src/cli/cli.rs");
let helper = cli
.split("fn collect_ort_diagnostics()")
.nth(1)
.and_then(|s| s.split("\n}\n\nasync fn").next())
.expect("collect_ort_diagnostics helper must exist");
assert!(
!helper.contains("init_from("),
"diagnostics helper must NOT call init_from() (it would load ORT into the main process)"
);
assert!(
!helper.contains("discover_and_init("),
"diagnostics helper must NOT call discover_and_init() (it would load ORT into the main process)"
);
}
#[test]
fn mcp_diagnostics_handler_inserts_ort_info_fields() {
let handler = read_file("src/cli/mcp/diagnostics_handler.rs");
assert!(
handler.contains("collect_ort_diagnostics"),
"MCP diagnostics must call the shared ORT diagnostics helper"
);
for key in ["ort_path", "ort_version", "execution_provider"] {
let needle = format!("\"{}\"", key);
assert!(
handler.contains(&needle),
"MCP diagnostics output must insert `{}`",
key
);
}
}
#[test]
fn ort_discovery_exposes_last_outcome_for_diagnostics() {
let src = read_file("crates/leindex-embed/src/ort_discovery.rs");
assert!(
src.contains("pub fn last_outcome()"),
"ort_discovery must expose last_outcome() so the worker reports the resolved ORT path"
);
}
#[test]
fn setup_check_reports_same_ort_info_shape() {
let setup = read_file("src/cli/leindex/setup.rs");
for header in ["ORT dylib path:", "ORT version:", "Execution provider:"] {
assert!(
setup.contains(header),
"setup --check must report `{}` so its ORT info matches diagnostics",
header
);
}
}
#[test]
fn setup_ort_path_uses_worker_discovery_chain() {
let setup = read_file("src/cli/leindex/setup.rs");
let helper = setup
.split("pub(crate) fn discover_ort_path()")
.nth(1)
.and_then(|s| s.split("\n}\n\n").next())
.expect("setup discover_ort_path helper must exist");
assert!(
helper.contains("leindex_embed::ort_discovery::discover_path_only"),
"setup --check must use worker discover_path_only so ORT priority remains env/config/user_lib/sibling/pip/system"
);
assert!(
!helper.contains("for py in"),
"setup --check must not maintain a pip-first discovery chain"
);
}
#[test]
fn smoke_summary_distinguishes_active_from_configured_provider() {
let setup = read_file("src/cli/leindex/setup.rs");
assert!(
setup.contains("configured_provider_label"),
"SmokeTestResult must store configured provider separately from active provider"
);
assert!(
setup.contains("Configured EP:"),
"summary should label configured provider as configured, not active"
);
assert!(
setup.contains("Active EP:"),
"summary may still print Active EP when the worker actually reports it"
);
}
}
mod per_surface_journeys {
use super::*;
#[test]
fn cargo_install_lays_out_both_binaries_cooperatively() {
let cargo = read_file("Cargo.toml");
let has_embed_target = cargo
.lines()
.any(|line| line.trim().contains("name = \"leindex-embed\""));
assert!(
has_embed_target,
"VAL-CROSS-001 / VAL-CARGO-002: root Cargo.toml must declare the leindex-embed bin target"
);
}
#[test]
fn npm_wrapper_sets_ort_dylib_path_from_bundled_lib() {
let wrapper = read_file("packages/npm-leindex-mcp/bin/mcp-wrapper.js");
assert!(
wrapper.contains("findBundledOrt"),
"VAL-NPM-003: npm wrapper must compute the bundled ORT path via findBundledOrt()"
);
assert!(
wrapper.contains("env.ORT_DYLIB_PATH"),
"VAL-NPM-003: npm wrapper must set env.ORT_DYLIB_PATH before spawning"
);
assert!(
wrapper.contains("MODELS_DIR"),
"VAL-NPM-001: npm wrapper must reference the bundled MODELS_DIR"
);
let pkg = read_file("packages/npm-leindex-mcp/package.json");
assert!(
pkg.contains("\"setup\":"),
"VAL-NPM-005: npm package.json must expose a `setup` script"
);
}
#[test]
fn pypi_exposes_leindex_setup_console_script() {
let toml = read_file("packages/pypi-leindex/pyproject.toml");
assert!(
toml.contains("leindex-setup = \"leindex.bootstrap:setup_main\""),
"VAL-PYPI-005: pyproject.toml must declare the leindex-setup console script"
);
let bootstrap = read_file("packages/pypi-leindex/src/leindex/bootstrap.py");
assert!(
bootstrap.contains("install_embed_worker"),
"VAL-PYPI-008: bootstrap must also install the leindex-embed worker binary"
);
assert!(
bootstrap.contains("\"onnx\"") || bootstrap.contains("INSTALL_FEATURES = \"onnx\""),
"VAL-PYPI-002: bootstrap must install with the onnx feature (setup is feature-gated)"
);
}
#[test]
fn onnx_migraphx_feature_propagates_to_embed_subcrate() {
let cargo = read_file("Cargo.toml");
let migraphx_line = cargo
.lines()
.find(|l| l.trim_start().starts_with("onnx-migraphx = ["))
.expect("Cargo.toml must define onnx-migraphx feature");
assert!(
migraphx_line.contains("leindex-embed/onnx-migraphx"),
"VAL-CROSS-005: onnx-migraphx feature must propagate to leindex-embed/onnx-migraphx"
);
}
#[test]
fn cpu_provider_maps_to_plain_onnxruntime_pip_package() {
let setup = read_file("src/cli/leindex/setup.rs");
let cpu_block = setup
.split("ExecutionProvider::Cpu => \"onnxruntime\"")
.count();
assert!(
cpu_block >= 1,
"VAL-CROSS-006: CPU provider must map to the plain `onnxruntime` pip package"
);
let migraphx_block = setup
.split("ExecutionProvider::Migraphx => \"onnxruntime-migraphx\"")
.count();
assert!(
migraphx_block >= 1,
"VAL-CROSS-005: MIGraphX provider must map to onnxruntime-migraphx"
);
let cuda_block = setup
.split("ExecutionProvider::Cuda => \"onnxruntime-gpu\"")
.count();
assert!(
cuda_block >= 1,
"VAL-CROSS-005: CUDA provider must map to onnxruntime-gpu"
);
}
}
mod cross_surface_fallback_consistency {
use super::*;
#[test]
fn search_query_neural_embedding_returns_none_on_failure() {
let src = read_file("src/cli/leindex/query.rs");
assert!(
src.contains("Ok(None) => None, // TF-IDF only mode, no neural available"),
"VAL-CROSS-007: query embedding must fall back to None so TF-IDF keeps working"
);
assert!(
src.contains("using TF-IDF fallback"),
"VAL-CROSS-007: query embedding must log a TF-IDF fallback message on failures"
);
}
#[test]
fn tfidf_only_embedder_variant_exists_for_zero_setup_path() {
let src = read_file("src/cli/index_builder.rs");
assert!(
src.contains("HybridEmbedder::TfIdfOnly("),
"VAL-CROSS-008 / VAL-CROSS-017: TfIdfOnly embedder variant must exist so TF-IDF works without ORT"
);
}
#[test]
fn bundle_lib_layout_matches_discovery_chain_search_path() {
let sh = read_file("install.sh");
let cmd = read_file("crates/leindex-embed/src/ort_discovery.rs");
assert!(
sh.contains("${LEINDEX_HOME}/lib") || sh.contains("$LEINDEX_HOME/lib"),
"install.sh must copy bundled libs to $LEINDEX_HOME/lib"
);
assert!(
cmd.contains("home.join(\"lib\")"),
"discovery chain must search ~/.leindex/lib to find the installed bundle ORT"
);
}
}
mod npm_tfidf_fallback {
use super::*;
#[test]
fn npm_wrapper_does_not_exit_when_bundled_ort_missing() {
let wrapper = read_file("packages/npm-leindex-mcp/bin/mcp-wrapper.js");
let exit_calls: Vec<&str> = wrapper
.lines()
.filter(|line| line.contains("process.exit(1)"))
.collect();
assert!(
!exit_calls.is_empty(),
"npm wrapper must exit 1 when the binary is missing"
);
for line in &exit_calls {
assert!(
!line.to_lowercase().contains("ort") && !line.to_lowercase().contains("onnx"),
"npm wrapper must NOT exit on missing bundled ORT (TF-IDF fallback); got: {}",
line
);
}
}
}