use hippmem_model::api::openai::OpenAiEmbedder;
use hippmem_model::traits::Embedder;
use std::io::{Read, Write};
use std::net::TcpListener;
use std::thread;
fn mock_server(response_body: &'static str, status_line: &'static str) -> u16 {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.local_addr().unwrap().port();
thread::spawn(move || {
if let Some(stream) = listener.incoming().flatten().next() {
let mut stream = stream;
let mut buf = [0u8; 4096];
let _ = stream.read(&mut buf);
let resp = format!(
"{}\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
status_line,
response_body.len(),
response_body
);
let _ = stream.write_all(resp.as_bytes());
}
});
port
}
struct EnvVarGuard {
key: &'static str,
prev: Option<String>,
}
impl EnvVarGuard {
fn remove(key: &'static str) -> Self {
let prev = std::env::var(key).ok();
std::env::remove_var(key);
Self { key, prev }
}
}
impl Drop for EnvVarGuard {
fn drop(&mut self) {
match &self.prev {
Some(v) => std::env::set_var(self.key, v),
None => std::env::remove_var(self.key),
}
}
}
#[test]
fn openai_mock_embedding_parses_correctly() {
let body = r#"{
"data": [
{"embedding": [0.1, 0.2, 0.3], "index": 0},
{"embedding": [0.4, 0.5, 0.6], "index": 1}
],
"model": "text-embedding-3-small",
"usage": {"total_tokens": 5}
}"#;
let port = mock_server(body, "HTTP/1.1 200 OK");
let embedder = OpenAiEmbedder::new_with_base_url(
"sk-test-key".into(),
&format!("http://127.0.0.1:{port}/v1"),
"text-embedding-3-small",
1536,
)
.expect("explicit key, no env lookup");
let vectors = embedder
.embed_sync(&["hello".into(), "world".into()])
.expect("mock response should parse");
assert_eq!(vectors, vec![vec![0.1, 0.2, 0.3], vec![0.4, 0.5, 0.6]]);
}
#[test]
fn openai_embedder_type_exists() {
let e = OpenAiEmbedder::new("sk-test-key".into());
assert_eq!(e.dim(), 1536);
assert_eq!(e.backend_id(), "text-embedding-3-small");
}
#[test]
fn empty_api_key_does_not_panic() {
let _guard = EnvVarGuard::remove("OPENAI_API_KEY");
let result = OpenAiEmbedder::new_with_base_url(
String::new(),
"https://api.openai.com/v1",
"text-embedding-3-small",
1536,
);
assert!(result.is_err(), "an empty key should return Err, not Ok");
}