use super::*;
#[test]
fn request_body_carries_model_and_prompt() {
let body = build_request_body("all-minilm", "hello world");
let json: serde_json::Value = serde_json::from_str(&body).expect("valid json");
assert_eq!(json["model"], "all-minilm");
assert_eq!(json["prompt"], "hello world");
}
#[test]
fn request_body_pins_the_model_in_memory() {
let body = build_request_body("all-minilm", "hello world");
let json: serde_json::Value = serde_json::from_str(&body).expect("valid json");
assert_eq!(
json["keep_alive"], DEFAULT_KEEP_ALIVE,
"request must pin the model for the daemon's lifetime"
);
assert!(
json["keep_alive"].is_number(),
"Ollama ignores a STRING \"-1\" and unloads after 5 minutes anyway"
);
}
#[test]
fn parses_a_well_formed_embedding() {
let vector = parse_embedding_response(r#"{"embedding":[0.1,0.2,0.3]}"#).expect("parse");
assert_eq!(vector.len(), 3);
assert!((vector[0] - 0.1_f32).abs() < f32::EPSILON);
}
#[test]
fn rejects_an_empty_embedding() {
let parsed = parse_embedding_response(r#"{"embedding":[]}"#);
assert!(matches!(parsed, Err(EmbedError::Empty)));
}
#[test]
fn rejects_a_malformed_response() {
let parsed = parse_embedding_response(r#"{"oops":true}"#);
assert!(matches!(parsed, Err(EmbedError::Backend(_))));
}
#[test]
fn a_silent_ollama_is_bounded_instead_of_hanging_forever() {
use std::io::Read as _;
use std::net::TcpListener;
use std::time::{Duration, Instant};
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(30));
}
});
let agent = embed_agent(Duration::from_secs(1));
let started = Instant::now();
let outcome = request_embedding(&agent, &format!("http://{addr}"), "all-minilm", "hello");
let elapsed = started.elapsed();
assert!(
matches!(outcome, Err(EmbedError::Backend(_))),
"a silent backend must surface as a Backend error, got {outcome:?}"
);
assert!(
elapsed < Duration::from_secs(10),
"the request must be bounded by the agent timeout, took {elapsed:?}"
);
drop(handle);
}
const EXPECTED_ATTEMPTS: usize = 3;
fn resetting_listener() -> (
std::net::SocketAddr,
std::sync::Arc<std::sync::atomic::AtomicUsize>,
std::thread::JoinHandle<()>,
) {
use std::net::TcpListener;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
let listener = TcpListener::bind("127.0.0.1:0").expect("bind");
let addr = listener.local_addr().expect("addr");
let attempts = Arc::new(AtomicUsize::new(0));
let seen = Arc::clone(&attempts);
let handle = std::thread::spawn(move || {
for _ in 0..EXPECTED_ATTEMPTS {
let Ok((socket, _)) = listener.accept() else {
break;
};
seen.fetch_add(1, Ordering::SeqCst);
std::thread::sleep(Duration::from_millis(50));
drop(socket);
}
});
(addr, attempts, handle)
}
#[test]
fn an_ollama_that_resets_the_connection_is_retried_then_reported_actionably() {
use std::sync::atomic::Ordering;
use std::time::{Duration, Instant};
let (addr, attempts, handle) = resetting_listener();
let agent = embed_agent(Duration::from_secs(2));
let url = format!("http://{addr}");
let started = Instant::now();
let outcome = request_embedding(&agent, &url, "all-minilm", "hello");
let elapsed = started.elapsed();
assert_eq!(
attempts.load(Ordering::SeqCst),
EXPECTED_ATTEMPTS,
"a reset connection must be replayed on a fresh connection, not \
reported after a single doomed attempt"
);
let Err(EmbedError::Backend(message)) = outcome else {
panic!("a reset backend must surface as a Backend error, got {outcome:?}");
};
for needle in [
url.as_str(),
"all-minilm",
"3 attempts",
"VELESDB_MEMORY_OLLAMA_URL",
"VELESDB_MEMORY_OLLAMA_MODEL",
"VELESDB_MEMORY_EMBEDDER=hash",
] {
assert!(
message.contains(needle),
"the failure must name {needle:?} to be actionable, got: {message}"
);
}
assert!(
elapsed < Duration::from_secs(15),
"retrying must not turn a fast failure into a long wait, took {elapsed:?}"
);
drop(handle);
}
#[test]
fn the_shipped_timeout_stays_bounded_and_usable() {
assert!((5..=120).contains(&EMBED_TIMEOUT_SECS));
}
#[test]
#[ignore = "requires a local Ollama with an embedding model (ollama pull all-minilm)"]
fn embeds_through_a_running_ollama() {
let embedder =
OllamaEmbedder::new(DEFAULT_OLLAMA_URL, DEFAULT_OLLAMA_MODEL).expect("connect to ollama");
let vector = embedder
.embed("parking_lot avoids lock poisoning")
.expect("embed");
assert_eq!(vector.len(), embedder.dimension());
assert!(vector
.iter()
.any(|&component| component.abs() > f32::EPSILON));
}