#![allow(unused_imports)]
use pathlint::catalog::{
builtin, builtin_relations, check_acyclic, embedded_version, merge_with_user,
merge_with_user_relations, version_check,
};
use pathlint::config::{Config, Expectation, Kind, Relation, Severity, SourceDef};
use pathlint::doctor::{
AnalyzeDeps, Diagnostic, Filter, Kind as DoctorKind, Severity as DoctorSeverity,
all_kind_names, analyze, analyze_real, env_lookup_real, fs_exists_real, fs_list_dir_real,
has_error, is_writable_dir_real, kind_name, user_diagnostic_names, validate_filter_names,
};
use pathlint::expand::{
expand_and_normalize, expand_and_normalize_with, expand_env, expand_env_with, normalize,
};
use pathlint::lint::{
CheckOutcomeView, Diagnosis, EvaluateDeps, Outcome, Status, check_shape_filesystem, diagnose,
evaluate, evaluate_real, exit_code, has_config_error, is_failure,
};
use pathlint::os_detect::{Os, os_filter_applies};
use pathlint::path_entry::PathEntry;
use pathlint::sort::{EntryMove, SortDeps, SortNote, SortPlan, sort_path, sort_path_real};
use pathlint::source_match::{
Match, SourceWarning, SourceWarningReason, find, find_with, names_only, names_only_with,
validate_sources, validate_sources_with,
};
use pathlint::trace::{
Found, LocateDeps, Provenance, TraceOutcome, UninstallHint, locate, locate_real,
};
use pathlint::{Attribution, CommonDeps};
#[test]
fn public_api_compiles() {
}
#[test]
fn evaluate_callable_with_evaluate_deps() {
use std::collections::BTreeMap;
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let deps = EvaluateDeps {
common: CommonDeps {
env_lookup: Box::new(|_var: &str| -> Option<String> { None }),
},
resolver: Box::new(|_cmd: &str| -> Option<std::path::PathBuf> { None }),
shape_check: Box::new(
|_path: &std::path::Path, _kind: Kind| -> Result<(), String> { Ok(()) },
),
};
let outcomes = evaluate(&[], &sources, Os::Linux, deps);
assert!(outcomes.is_empty());
}
#[test]
fn locate_callable_with_locate_deps() {
use std::collections::BTreeMap;
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let relations: Vec<Relation> = Vec::new();
let deps = LocateDeps {
common: CommonDeps {
env_lookup: Box::new(|_var: &str| -> Option<String> { None }),
},
resolver: Box::new(|_cmd: &str| -> Option<std::path::PathBuf> { None }),
};
let outcome = locate(
"definitely_no_such_command",
&sources,
&relations,
Os::Linux,
deps,
);
assert!(matches!(outcome, TraceOutcome::NotFound));
}
#[test]
fn analyze_callable_with_analyze_deps() {
use std::collections::BTreeMap;
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let relations: Vec<Relation> = Vec::new();
let entries: Vec<Attribution> = Vec::new();
let deps = AnalyzeDeps {
common: CommonDeps {
env_lookup: Box::new(|_var: &str| -> Option<String> { None }),
},
fs_exists: Box::new(|_path: &str| -> bool { false }),
fs_list_dir: Box::new(|_path: &str| -> Vec<String> { Vec::new() }),
is_writable_dir: Box::new(|_path: &str| -> bool { false }),
};
let diags = analyze(&entries, &sources, &relations, Os::Linux, deps);
assert!(diags.is_empty());
let _real: Vec<String> = fs_list_dir_real("/this/path/does/not/exist");
let _w: bool = is_writable_dir_real("/this/path/does/not/exist");
}
#[test]
fn path_entry_from_raw_takes_env_lookup_closure() {
let entry = PathEntry::from_raw("$FOO/bin", |k| {
(k == "FOO").then(|| "/expanded".to_string())
});
assert_eq!(entry.raw, "$FOO/bin");
assert_eq!(entry.expanded, "/expanded/bin");
}
#[test]
fn analyze_signature_pinned_with_attribution_slice() {
use std::collections::BTreeMap;
let entries: Vec<Attribution> = vec![Attribution::new(PathEntry::from_raw(
"/usr/bin",
|_| -> Option<String> { None },
))];
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let relations: Vec<Relation> = Vec::new();
let deps = AnalyzeDeps {
common: CommonDeps {
env_lookup: Box::new(|_var: &str| -> Option<String> { None }),
},
fs_exists: Box::new(|_path: &str| -> bool { true }),
fs_list_dir: Box::new(|_path: &str| -> Vec<String> { Vec::new() }),
is_writable_dir: Box::new(|_path: &str| -> bool { false }),
};
let diags = analyze(&entries, &sources, &relations, Os::Linux, deps);
assert!(diags.is_empty(), "got: {diags:?}");
}
#[test]
fn expand_env_with_pinned_on_public_surface() {
let out = expand_env_with("$X", |k| (k == "X").then(|| "ok".to_string()));
assert_eq!(out, "ok");
}
#[test]
fn path_entry_is_pure_observation() {
let pe = PathEntry::from_raw("/usr/bin", |_| -> Option<String> { None });
assert_eq!(pe.raw, "/usr/bin");
assert_eq!(pe.expanded, "/usr/bin");
}
#[test]
fn attribution_pinned_on_public_surface() {
let pe = PathEntry::from_raw("/usr/bin", |_| -> Option<String> { None });
let attrib = Attribution::new(pe.clone());
assert_eq!(attrib.observed.raw, "/usr/bin");
assert_eq!(attrib.observed.expanded, "/usr/bin");
assert!(attrib.provenance_raw.is_none());
assert_eq!(attrib.effective_raw_for_user_intent(), "/usr/bin");
let with_prov = attrib.with_provenance("%CUSTOM%/bin".to_string());
assert_eq!(with_prov.provenance_raw.as_deref(), Some("%CUSTOM%/bin"));
assert_eq!(with_prov.effective_raw_for_user_intent(), "%CUSTOM%/bin");
assert_eq!(with_prov.observed.raw, "/usr/bin");
}
#[test]
fn expand_and_normalize_with_pinned_on_public_surface() {
let out =
expand_and_normalize_with(r"$ROOT\BIN", |k| (k == "ROOT").then(|| "/Var".to_string()));
assert_eq!(out, "/var/bin");
}
#[test]
fn source_match_with_variants_pinned_on_public_surface() {
use pathlint::config::SourceDef;
use std::collections::BTreeMap;
let mut sources: BTreeMap<String, SourceDef> = BTreeMap::new();
sources.insert(
"stub".into(),
SourceDef {
unix: Some(r"$STUB_HOME/.cargo/bin".into()),
..Default::default()
},
);
let env_lookup =
|k: &str| -> Option<String> { (k == "STUB_HOME").then(|| "/home/stub".to_string()) };
let hits = find_with(
"/home/stub/.cargo/bin/runex",
&sources,
Os::Linux,
env_lookup,
);
assert_eq!(hits.len(), 1);
assert_eq!(hits[0].name, "stub");
let names = names_only_with(
"/home/stub/.cargo/bin/runex",
&sources,
Os::Linux,
env_lookup,
);
assert_eq!(names, vec!["stub".to_string()]);
let warnings = validate_sources_with(&sources, Os::Linux, env_lookup);
assert!(warnings.is_empty(), "got: {warnings:?}");
}
#[test]
fn common_deps_production_pinned_on_public_surface() {
let _common: CommonDeps = CommonDeps::production();
}
#[test]
fn analyze_deps_production_pinned_on_public_surface() {
let _deps: AnalyzeDeps = AnalyzeDeps::production();
}
#[test]
fn evaluate_real_pinned_on_public_surface() {
use std::collections::BTreeMap;
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let entries: Vec<Attribution> = Vec::new();
let outcomes = evaluate_real(&[], &sources, Os::Linux, &entries);
assert!(outcomes.is_empty());
}
#[test]
fn locate_real_pinned_on_public_surface() {
use std::collections::BTreeMap;
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let relations: Vec<Relation> = Vec::new();
let entries: Vec<Attribution> = Vec::new();
let outcome = locate_real(
"definitely_no_such_command",
&sources,
&relations,
Os::Linux,
&entries,
);
assert!(matches!(outcome, TraceOutcome::NotFound));
}
#[test]
fn sort_path_real_pinned_on_public_surface() {
use std::collections::BTreeMap;
let entries: Vec<Attribution> = Vec::new();
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let relations: Vec<Relation> = Vec::new();
let plan = sort_path_real(&entries, &[], &sources, &relations, Os::Linux);
let _ = plan;
}
#[test]
fn sort_path_callable_with_sort_deps() {
use std::collections::BTreeMap;
let entries: Vec<Attribution> = Vec::new();
let sources: BTreeMap<String, SourceDef> = BTreeMap::new();
let relations: Vec<Relation> = Vec::new();
let deps = SortDeps {
common: CommonDeps {
env_lookup: Box::new(|_var: &str| -> Option<String> { None }),
},
};
let _plan = sort_path(&entries, &[], &sources, &relations, Os::Linux, deps);
}