use super::*;
#[test]
fn fingerprint_matches_shapes() {
use FingerprintMarker::*;
let props = serde_json::json!({"default_generation_settings": {}, "total_slots": 4});
assert!(fingerprint_matches(
&HasAnyKey(&["default_generation_settings", "model_path"]),
&props
));
let old_props = serde_json::json!({"model_path": "/models/x.gguf"});
assert!(fingerprint_matches(
&HasAnyKey(&["default_generation_settings", "model_path"]),
&old_props
));
let version = serde_json::json!({"version": "0.6.3"});
assert!(fingerprint_matches(&HasKey("version"), &version));
assert!(!fingerprint_matches(&HasKey("version"), &props));
let models = serde_json::json!({"data": [
{"id": "a", "state": "loaded"},
{"id": "b", "status": "unloaded"}
]});
assert!(fingerprint_matches(&ModelsArrayWithState, &models));
let openai = serde_json::json!({"data": [{"id": "a"}, {"id": "b"}]});
assert!(!fingerprint_matches(&ModelsArrayWithState, &openai));
assert!(!fingerprint_matches(
&ModelsArrayWithState,
&serde_json::json!({"data": []})
));
}
#[tokio::test]
async fn detect_engine_identifies_llamacpp_via_props() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/props"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"default_generation_settings": {}, "total_slots": 1
})))
.mount(&server)
.await;
let engine = detect_engine(
&reqwest::Client::new(),
&server.uri(),
BackendKind::Openai,
None,
)
.await;
assert_eq!(engine, Some(Engine::LlamaCpp));
}
#[tokio::test]
async fn detect_engine_identifies_vllm_via_version() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/props"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/version"))
.respond_with(
ResponseTemplate::new(200).set_body_json(serde_json::json!({"version": "0.8.5.post1"})),
)
.mount(&server)
.await;
let engine = detect_engine(
&reqwest::Client::new(),
&server.uri(),
BackendKind::Openai,
None,
)
.await;
assert_eq!(engine, Some(Engine::Vllm));
}
#[tokio::test]
async fn detect_engine_old_llamacpp_falls_back_to_models_route() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/props"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/version"))
.respond_with(ResponseTemplate::new(404))
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "qwen3-32b", "state": "loaded"}]
})))
.mount(&server)
.await;
let engine = detect_engine(
&reqwest::Client::new(),
&server.uri(),
BackendKind::Openai,
None,
)
.await;
assert_eq!(engine, Some(Engine::LlamaCpp));
}
#[tokio::test]
async fn detect_engine_unknown_for_generic_gateway() {
let server = MockServer::start().await;
let engine = detect_engine(
&reqwest::Client::new(),
&server.uri(),
BackendKind::Openai,
None,
)
.await;
assert_eq!(engine, None);
}
#[tokio::test]
async fn detect_engine_short_circuits_for_ollama_kind() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.respond_with(ResponseTemplate::new(500))
.expect(0)
.mount(&server)
.await;
let engine = detect_engine(
&reqwest::Client::new(),
&server.uri(),
BackendKind::Ollama,
None,
)
.await;
assert_eq!(engine, Some(Engine::Ollama));
server.verify().await;
}
#[test]
fn reads_n_ctx_from_a_llamacpp_props_body() {
let props = serde_json::json!({
"default_generation_settings": {"n_ctx": 65536, "n_predict": -1},
"model_path": "/home/u/models/gguf/Ornith-1.5-35B-Q8_0.gguf",
"build_info": "b623-511f9c1",
});
assert_eq!(served_context_window(&props), Some(65536));
let flat = serde_json::json!({"model_path": "/m.gguf", "n_ctx": 32768});
assert_eq!(served_context_window(&flat), Some(32768));
}
#[test]
fn an_unloaded_router_reports_nothing_not_zero() {
let unloaded = serde_json::json!({
"default_generation_settings": {"n_ctx": 0},
"model_path": "none",
});
assert_eq!(
served_context_window(&unloaded),
None,
"n_ctx 0 means 'ask again with ?model=<id>', never a real window"
);
}
#[test]
fn a_body_without_a_window_yields_none() {
assert_eq!(
served_context_window(&serde_json::json!({"version": "0.6.3"})),
None
);
assert_eq!(served_context_window(&serde_json::json!({})), None);
assert_eq!(
served_context_window(&serde_json::json!({"n_ctx": "65536"})),
None
);
}
#[tokio::test]
async fn openai_context_window_reads_a_llamacpp_served_window_per_model() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "Ornith-1.5-35B-Q8_0"}, {"id": "qwen3-coder"}]
})))
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/props"))
.and(query_param("model", "Ornith-1.5-35B-Q8_0"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"default_generation_settings": {"n_ctx": 65536},
"model_path": "/models/Ornith-1.5-35B-Q8_0.gguf",
})))
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/props"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"default_generation_settings": {"n_ctx": 0}, "model_path": "none"
})))
.mount(&server)
.await;
let client = reqwest::Client::new();
assert_eq!(
api_for(BackendKind::Openai)
.context_window(&client, &server.uri(), "Ornith-1.5-35B-Q8_0", None)
.await,
Some(65_536),
"the served window must reach the method adopt and the cache probe call"
);
assert_eq!(
api_for(BackendKind::Openai)
.context_window(&client, &server.uri(), "qwen3-coder", None)
.await,
None,
"one endpoint serves many models; a window is never endpoint-wide"
);
}
#[tokio::test]
async fn a_declared_max_model_len_still_wins_without_a_props_fetch() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "m", "max_model_len": 262_144}]
})))
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/props"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"default_generation_settings": {"n_ctx": 4096}
})))
.expect(0)
.mount(&server)
.await;
assert_eq!(
api_for(BackendKind::Openai)
.context_window(&reqwest::Client::new(), &server.uri(), "m", None)
.await,
Some(262_144)
);
}
#[tokio::test]
async fn no_props_route_yields_no_window_not_an_error() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id": "m"}]
})))
.mount(&server)
.await;
assert_eq!(
api_for(BackendKind::Openai)
.context_window(&reqwest::Client::new(), &server.uri(), "m", None)
.await,
None
);
}
#[test]
fn router_launch_window_stays_provisional_until_props() {
for args in [
serde_json::json!(["llama-server", "-c", "262144", "-np", "2"]),
serde_json::json!(["llama-server", "--ctx-size=262144", "--parallel=2"]),
] {
let body = serde_json::json!({"data": [
{"id":"other", "max_model_len":4096},
{"id":"selected", "status":{"value":"loaded", "args":args}}
]});
assert_eq!(parse_openai_models_window(&body, "selected"), None);
}
}
#[test]
fn router_automatic_or_ambiguous_launch_window_stays_unknown() {
for args in [
serde_json::json!(["llama-server", "-c", "0", "-np", "1"]),
serde_json::json!(["llama-server", "-c", "131072"]),
serde_json::json!(["llama-server", "-c", "131072", "-np", "0"]),
serde_json::json!(["llama-server", "-c", "131072", "-np", "2", "-kvu"]),
serde_json::json!(["llama-server", "-c", "131072", "-np", "2", "--kv-unified"]),
] {
let body = serde_json::json!({"data": [{"id":"selected", "status":{"value":"loaded", "args":args}}]});
assert_eq!(parse_openai_models_window(&body, "selected"), None);
}
}
#[tokio::test]
async fn router_launch_window_stays_unknown_when_props_is_unavailable() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"data": [{"id":"selected", "status":{"value":"loaded",
"args":["llama-server", "-c", "262144", "-np", "2"]}}]
})))
.expect(1)
.mount(&server)
.await;
Mock::given(method("GET"))
.and(path("/props"))
.respond_with(ResponseTemplate::new(503))
.expect(1)
.mount(&server)
.await;
assert_eq!(
api_for(BackendKind::Openai)
.context_window(&reqwest::Client::new(), &server.uri(), "selected", None)
.await,
None
);
}