use crate::llm::client::Extracted;
use crate::llm::error::LlmError;
use crate::test_support::{
cfg_for, fast_retry_client, request_count, server_finishing_with, server_returning,
};
const FRAGMENTS: &[&str] = &[
"Here is wh",
"at I fou",
"nd.\n\n``",
"`json\n{\"find",
"ings\": [{\"line\": 1",
"2, \"severity\": \"warn",
"ing\", \"message\": \"unwrap on a Res",
"ult\"}]}\n``",
"`\n",
];
const TRUNCATED: &[&str] = &[
"{\"find",
"ings\": [{\"line\": 1",
"2, \"severity\": \"warn",
"ing\", \"message\": \"unwrap on a Res",
"ult\"",
];
#[tokio::test]
async fn fragmented_text_extracts_what_one_delta_extracts() {
let single_delta = FRAGMENTS.concat();
let one = server_returning(&[single_delta.as_str()]).await;
let many = server_returning(FRAGMENTS).await;
let from_one = fast_retry_client(&cfg_for(&one, "m", 1))
.complete_json("sys", "user")
.await
.expect("a fenced object parses");
let from_many = fast_retry_client(&cfg_for(&many, "m", 1))
.complete_json("sys", "user")
.await
.expect("the same bytes parse however they were streamed");
assert!(
matches!(from_one, Extracted::Complete(_)),
"the fixture must be a complete object, got {from_one:?}"
);
assert_eq!(
from_many, from_one,
"a response split across deltas must assemble to the same JSON"
);
assert_eq!(request_count(&many).await, 1);
}
#[tokio::test]
async fn a_truncated_answer_survives_fragmentation() {
let single_delta = TRUNCATED.concat();
let one = server_returning(&[single_delta.as_str()]).await;
let many = server_returning(TRUNCATED).await;
let from_one = fast_retry_client(&cfg_for(&one, "m", 1))
.complete_json("sys", "user")
.await
.expect("an unterminated object is recovered by brace balancing");
let from_many = fast_retry_client(&cfg_for(&many, "m", 1))
.complete_json("sys", "user")
.await
.expect("and is recovered identically when it arrives in pieces");
assert!(
matches!(from_one, Extracted::Truncated(_)),
"the fixture must be the truncated case, got {from_one:?}"
);
assert_eq!(from_many, from_one);
assert_eq!(request_count(&many).await, 1);
}
#[tokio::test]
async fn a_capped_fragmented_response_is_not_retried() {
let server = server_finishing_with(&["I ran ou", "t of room befo"], "length").await;
let err = fast_retry_client(&cfg_for(&server, "m", 1))
.complete_json("sys", "user")
.await
.expect_err("prose that hit the cap produced no JSON");
assert!(
matches!(&err, LlmError::ModelStopped { finish, .. } if finish == "length"),
"got {err:?}"
);
assert_eq!(
request_count(&server).await,
1,
"the same request hits the same cap, so it must not be asked again"
);
}