use super::liveness::StreamDeadlinePolicy;
use super::sse::{consume_sse_lines, consume_sse_lines_with_policy};
use crate::llm::api::DialectContract;
use crate::llm::api::LlmResult;
use crate::llm::capabilities::WireDialect;
use crate::llm::usage::ProviderUsageReceipt;
use crate::value::VmValue;
use std::time::Duration;
const OBSERVED_BUILD: &str = "b9994-14d3ba45f";
const OTHER_BUILD: &str = "b10360-48d22e295";
fn content_chunk(fingerprint: Option<&str>) -> serde_json::Value {
let mut frame = serde_json::json!({
"choices": [{"finish_reason": null, "index": 0, "delta": {"content": "hi"}}],
"id": "chatcmpl-stream",
"model": "served-model",
"object": "chat.completion.chunk"
});
if let Some(fingerprint) = fingerprint {
frame["system_fingerprint"] = serde_json::json!(fingerprint);
}
frame
}
fn usage_chunk(fingerprint: Option<&str>) -> serde_json::Value {
let mut frame = serde_json::json!({
"choices": [],
"id": "chatcmpl-stream",
"object": "chat.completion.chunk",
"usage": {"completion_tokens": 6, "prompt_tokens": 14, "total_tokens": 20}
});
if let Some(fingerprint) = fingerprint {
frame["system_fingerprint"] = serde_json::json!(fingerprint);
}
frame
}
fn llamacpp_usage_chunk() -> serde_json::Value {
serde_json::json!({
"choices": [],
"id": "chatcmpl-stream",
"model": "served-model",
"object": "chat.completion.chunk",
"system_fingerprint": "b10603-c060ca974",
"usage": {
"completion_tokens": 6,
"prompt_tokens": 6036,
"total_tokens": 6042
},
"timings": {
"prompt_n": 4,
"cache_n": 6032,
"prompt_ms": 12.4,
"predicted_n": 6,
"predicted_ms": 30.6
}
})
}
fn sse_body(frames: &[serde_json::Value]) -> String {
let mut body = String::new();
for frame in frames {
body.push_str("data: ");
body.push_str(&frame.to_string());
body.push('\n');
}
body.push_str("data: [DONE]\n");
body
}
async fn drive_openai(body: &str) -> LlmResult {
let (delta_tx, _delta_rx) = tokio::sync::mpsc::unbounded_channel::<String>();
consume_sse_lines(
tokio::io::BufReader::new(body.as_bytes()),
"llamacpp",
"test-model",
DialectContract::new(WireDialect::OpenAiCompat, None),
delta_tx,
None,
None,
false,
)
.await
.expect("sse parse should succeed")
}
#[tokio::test(flavor = "current_thread")]
async fn streamed_system_fingerprint_reaches_telemetry() {
let body = sse_body(&[
content_chunk(Some(OBSERVED_BUILD)),
usage_chunk(Some(OBSERVED_BUILD)),
]);
let result = drive_openai(&body).await;
assert_eq!(
result.telemetry.serving_fingerprint.as_deref(),
Some(OBSERVED_BUILD)
);
}
#[tokio::test(flavor = "current_thread")]
async fn empty_openai_stream_keeps_provider_usage_receipt() {
let body = sse_body(&[usage_chunk(None)]);
let (delta_tx, _delta_rx) = tokio::sync::mpsc::unbounded_channel::<String>();
let error = consume_sse_lines(
tokio::io::BufReader::new(body.as_bytes()),
"openai",
"gpt-5.4-preview",
DialectContract::new(WireDialect::OpenAiCompat, None),
delta_tx,
None,
None,
false,
)
.await
.expect_err("token-bearing empty stream must be rejected");
let receipt = ProviderUsageReceipt::from_error(&error)
.expect("stream parser error must retain provider usage");
let VmValue::Dict(fields) = receipt.to_vm_value() else {
panic!("provider usage receipt must be a dictionary");
};
assert_eq!(
fields.get("input_tokens").and_then(VmValue::as_int),
Some(14)
);
assert_eq!(
fields.get("output_tokens").and_then(VmValue::as_int),
Some(6)
);
}
#[tokio::test(flavor = "current_thread")]
async fn streamed_llamacpp_root_timings_reach_telemetry() {
let body = sse_body(&[content_chunk(None), llamacpp_usage_chunk()]);
let result = drive_openai(&body).await;
assert_eq!(
result.telemetry.source,
crate::llm::api::telemetry_source::LLAMACPP_TIMINGS
);
assert_eq!(result.telemetry.server_prompt_eval_ms, Some(12));
assert_eq!(result.telemetry.server_generation_ms, Some(31));
assert_eq!(result.telemetry.server_total_ms, Some(43));
assert_eq!(result.telemetry.server_prompt_tokens, Some(6036));
assert_eq!(result.telemetry.server_uncached_prompt_tokens, Some(4));
assert_eq!(result.telemetry.server_cached_prompt_tokens, Some(6032));
}
#[tokio::test(flavor = "current_thread")]
async fn fingerprint_announced_only_on_the_opening_chunk_survives_the_usage_frame() {
let body = sse_body(&[content_chunk(Some(OBSERVED_BUILD)), usage_chunk(None)]);
let result = drive_openai(&body).await;
assert_eq!(
result.telemetry.serving_fingerprint.as_deref(),
Some(OBSERVED_BUILD),
"the opening chunk's build id must survive the usage frame's envelope reset"
);
assert_eq!(result.telemetry.server_prompt_tokens, Some(14));
}
#[tokio::test(flavor = "current_thread")]
async fn a_stream_reporting_no_fingerprint_leaves_it_absent() {
let body = sse_body(&[content_chunk(None), usage_chunk(None)]);
let result = drive_openai(&body).await;
assert_eq!(result.telemetry.serving_fingerprint, None);
}
#[tokio::test(flavor = "current_thread")]
async fn a_later_frames_fingerprint_wins_over_an_earlier_one() {
let body = sse_body(&[
content_chunk(Some(OBSERVED_BUILD)),
usage_chunk(Some(OTHER_BUILD)),
]);
let result = drive_openai(&body).await;
assert_eq!(
result.telemetry.serving_fingerprint.as_deref(),
Some(OTHER_BUILD)
);
}
fn terminal_content_chunk() -> serde_json::Value {
serde_json::json!({
"choices": [{"finish_reason": "stop", "index": 0, "delta": {"content": "hi"}}],
"id": "chatcmpl-stream",
"model": "served-model",
"object": "chat.completion.chunk"
})
}
#[tokio::test(flavor = "current_thread")]
async fn first_frame_latency_survives_the_usage_frame_rebuild() {
let body = sse_body(&[content_chunk(None), usage_chunk(None)]);
let result = drive_openai(&body).await;
assert!(
result.telemetry.client_first_frame_ms.is_some(),
"a streamed call records its first-frame latency"
);
assert_eq!(
result.telemetry.server_prompt_tokens,
Some(14),
"the usage frame still lands, so the rebuild really happened"
);
}
#[tokio::test(flavor = "current_thread")]
async fn a_stream_with_no_parseable_frame_reports_no_first_frame() {
let body = ": keepalive\n\ndata: [DONE]\n".to_string();
let result = drive_openai(&body).await;
assert_eq!(
result.telemetry.client_first_frame_ms, None,
"a keepalive is not a provider frame"
);
let encoded = serde_json::to_value(&result.telemetry).expect("telemetry serializes");
assert!(
encoded.get("client_first_frame_ms").is_none(),
"an unmeasured first frame is omitted from the artifact, not written as 0"
);
}
#[tokio::test(start_paused = true)]
async fn first_frame_latency_measures_the_wait_before_the_first_frame() {
use tokio::io::AsyncWriteExt;
let (reader, mut writer) = tokio::io::duplex(4096);
let (delta_tx, _delta_rx) = tokio::sync::mpsc::unbounded_channel::<String>();
let request_origin = tokio::time::Instant::now();
let first = format!("data: {}\n", content_chunk(None));
let rest = format!(
"data: {}\ndata: {}\ndata: [DONE]\n",
terminal_content_chunk(),
usage_chunk(None)
);
let (result, ()) = tokio::join!(
consume_sse_lines_with_policy(
tokio::io::BufReader::new(reader),
"llamacpp",
"test-model",
DialectContract::new(WireDialect::OpenAiCompat, None),
delta_tx,
None,
None,
false,
StreamDeadlinePolicy::for_test(
Duration::from_hours(1),
Duration::from_hours(1),
Duration::from_hours(1),
),
None,
request_origin,
),
async move {
tokio::time::sleep(Duration::from_millis(1_500)).await;
writer
.write_all(first.as_bytes())
.await
.expect("first frame");
tokio::time::sleep(Duration::from_millis(500)).await;
writer
.write_all(rest.as_bytes())
.await
.expect("usage frame");
drop(writer);
}
);
let telemetry = result.expect("sse parse should succeed").telemetry;
let first_frame = telemetry
.client_first_frame_ms
.expect("a streamed call records its first-frame latency");
assert!(
(1_500..2_000).contains(&first_frame),
"first-frame latency measures the prefill wait, not the whole stream: {first_frame}"
);
}