use super::*;
use std::io::{Read as _, Write as _};
use std::net::TcpListener;
use std::time::{Duration, Instant};
fn listening_server(
status: &'static str,
body: &'static str,
) -> (
String,
std::sync::Arc<std::sync::Mutex<String>>,
std::thread::JoinHandle<()>,
) {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind");
let addr = listener.local_addr().expect("addr");
let seen = std::sync::Arc::new(std::sync::Mutex::new(String::new()));
let recorder = std::sync::Arc::clone(&seen);
let handle = std::thread::spawn(move || {
if let Ok((mut socket, _)) = listener.accept() {
let mut scratch = [0_u8; 2048];
let read = socket.read(&mut scratch).unwrap_or(0);
let request = String::from_utf8_lossy(&scratch[..read]).to_string();
if let Ok(mut slot) = recorder.lock() {
*slot = request.lines().next().unwrap_or_default().to_owned();
}
let _ = socket.write_all(
format!(
"HTTP/1.1 {status}\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{body}",
body.len()
)
.as_bytes(),
);
}
});
(format!("http://{addr}"), seen, handle)
}
fn closed_port() -> String {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind");
let addr = listener.local_addr().expect("addr");
drop(listener);
format!("http://{addr}")
}
fn probe_at(url: &str, model: &str) -> Reachability {
probe_openai(url, model, None, Duration::from_secs(2))
}
const MODELS_JSON: &str = r#"{"data":[{"id":"ornith-35b"},{"id":"bge-m3"}]}"#;
#[test]
fn a_reachable_backend_listing_the_model_is_reachable() {
let (url, _seen, handle) = listening_server("200 OK", MODELS_JSON);
assert!(matches!(
probe_at(&url, "ornith-35b"),
Reachability::Reachable
));
drop(handle);
}
#[test]
fn a_reachable_backend_produces_no_warning_at_all() {
let (url, _seen, handle) = listening_server("200 OK", MODELS_JSON);
let outcome = probe_at(&url, "ornith-35b");
assert_eq!(
warning_line("extraction", &url, "ornith-35b", &outcome),
None
);
drop(handle);
}
#[test]
fn a_closed_port_is_unreachable_and_says_so() {
let url = closed_port();
let outcome = probe_at(&url, "ornith-35b");
assert!(
matches!(outcome, Reachability::Unreachable { .. }),
"a closed port must be Unreachable, got {outcome:?}"
);
let line = warning_line("extraction", &url, "ornith-35b", &outcome).expect("a warning");
assert!(line.contains("unreachable"), "{line}");
}
#[test]
fn a_listing_without_the_model_is_a_different_diagnosis() {
let (url, _seen, handle) = listening_server("200 OK", MODELS_JSON);
let outcome = probe_at(&url, "a-model-nobody-pulled");
assert!(
matches!(outcome, Reachability::ModelNotAdvertised { .. }),
"a served listing without the model must be ModelNotAdvertised, got {outcome:?}"
);
let line =
warning_line("extraction", &url, "a-model-nobody-pulled", &outcome).expect("warning");
assert!(line.contains("a-model-nobody-pulled"), "{line}");
drop(handle);
}
#[test]
fn ollamas_latest_suffix_is_not_a_missing_model() {
let (url, _seen, handle) = listening_server(
"200 OK",
r#"{"data":[{"id":"bge-m3:latest"},{"id":"qwen3:8b"}]}"#,
);
assert!(
matches!(probe_at(&url, "bge-m3"), Reachability::Reachable),
"`bge-m3` must match Ollama's `bge-m3:latest`"
);
drop(handle);
}
#[test]
fn a_tag_that_differs_is_still_a_missing_model() {
let (url, _seen, handle) = listening_server("200 OK", r#"{"data":[{"id":"bge-m3:v2"}]}"#);
assert!(
matches!(
probe_at(&url, "bge-m3:v3"),
Reachability::ModelNotAdvertised { .. }
),
"a different explicit tag must stay a miss"
);
drop(handle);
}
#[test]
fn a_401_is_a_credential_diagnosis() {
let (url, _seen, handle) = listening_server("401 Unauthorized", r#"{"error":"nope"}"#);
let outcome = probe_at(&url, "ornith-35b");
assert!(
matches!(outcome, Reachability::Unauthorized),
"a 401 must be Unauthorized, got {outcome:?}"
);
drop(handle);
}
#[test]
fn no_warning_ever_echoes_the_credential() {
let credential = "tok-do-not-log-me";
let outcomes = [
Reachability::Unreachable {
detail: "connection refused".to_owned(),
},
Reachability::Unauthorized,
Reachability::ModelNotAdvertised { listed: 3 },
Reachability::ListingUnsupported,
];
for outcome in &outcomes {
let line = warning_line("extraction", "http://127.0.0.1:8019", "ornith-35b", outcome)
.expect("a warning");
assert!(
!line.contains(credential),
"the credential leaked into: {line}"
);
assert!(!line.to_lowercase().contains("authorization"), "{line}");
}
}
#[test]
fn the_warning_names_the_role_the_url_and_the_model() {
let outcome = Reachability::Unreachable {
detail: "connection refused".to_owned(),
};
let line = warning_line(
"extraction",
"http://127.0.0.1:8019",
"ornith-35b",
&outcome,
)
.expect("warning");
assert!(line.contains("extraction"), "{line}");
assert!(line.contains("http://127.0.0.1:8019"), "{line}");
assert!(line.contains("ornith-35b"), "{line}");
}
#[test]
fn the_warning_carries_an_action_not_only_a_complaint() {
let outcome = Reachability::Unreachable {
detail: "connection refused".to_owned(),
};
let line = warning_line(
"extraction",
"http://127.0.0.1:8019",
"ornith-35b",
&outcome,
)
.expect("warning");
assert!(
line.contains("VELESDB_MEMORY_EXTRACTOR") || line.contains("autograph"),
"the operator is told what is wrong and not what to do: {line}"
);
}
#[test]
fn the_probe_reads_a_listing_and_never_asks_for_a_generation() {
let (url, seen, handle) = listening_server("200 OK", MODELS_JSON);
let _ = probe_at(&url, "ornith-35b");
let request = seen.lock().expect("lock").clone();
assert!(
request.starts_with("GET "),
"the probe was not a GET: {request}"
);
assert!(request.contains("/v1/models"), "{request}");
assert!(
!request.contains("completions") && !request.contains("embeddings"),
"the probe touched a generation endpoint: {request}"
);
drop(handle);
}
#[test]
fn the_probe_is_bounded_by_its_own_timeout() {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind");
let addr = listener.local_addr().expect("addr");
let handle = std::thread::spawn(move || {
if let Ok((mut socket, _)) = listener.accept() {
let mut scratch = [0_u8; 1024];
let _ = socket.read(&mut scratch);
std::thread::sleep(Duration::from_secs(20));
}
});
let started = Instant::now();
let outcome = probe_openai(
&format!("http://{addr}"),
"ornith-35b",
None,
Duration::from_secs(1),
);
let elapsed = started.elapsed();
assert!(
matches!(outcome, Reachability::Unreachable { .. }),
"a silent server must read as Unreachable, got {outcome:?}"
);
assert!(
elapsed < Duration::from_secs(10),
"the probe must be bounded by its own timeout, took {elapsed:?}"
);
drop(handle);
}
#[test]
fn a_server_that_does_not_serve_a_listing_is_not_called_unreachable() {
let (url, _seen, handle) = listening_server("404 Not Found", r#"{"error":"no such route"}"#);
let outcome = probe_at(&url, "ornith-35b");
assert!(
matches!(outcome, Reachability::ListingUnsupported),
"a 404 on the listing must be its own verdict, got {outcome:?}"
);
drop(handle);
}
fn asserts_degradation(line: &str) -> bool {
line.contains("will degrade silently")
}
#[test]
fn an_unadvertised_alias_is_not_reported_as_a_proven_absence() {
let outcome = Reachability::ModelNotAdvertised { listed: 7 };
let line = warning_line(
"extraction",
"http://127.0.0.1:8080",
"ornith-35b",
&outcome,
)
.expect("an unadvertised alias is still worth one line");
assert!(
!asserts_degradation(&line),
"the line must not assert that enrichment degrades — a listing that \
omits an alias proves nothing about routability:\n{line}"
);
assert!(
line.contains("may still be routable"),
"the line must say the alias may still be routable, or the operator \
reads an omission as a breakage:\n{line}"
);
}
#[test]
fn a_verdict_that_does_prove_breakage_still_says_so() {
for outcome in [
Reachability::Unreachable {
detail: "connection refused".to_owned(),
},
Reachability::Unauthorized,
] {
let line = warning_line("extraction", "http://127.0.0.1:8080", "m", &outcome)
.expect("a proven breakage must produce a line");
assert!(
asserts_degradation(&line),
"a verdict that DOES establish the backend is unusable must keep \
saying enrichment degrades, got:\n{line}"
);
}
}