use axum::Json;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use serde::Serialize;
use serde_json::Value;
use tokio::sync::watch;
use crate::model::qwen35_config::GenerateConfig;
pub const REQUEST_BODY_LIMIT_BYTES: usize = 1_048_576;
pub const OVERFLOW_PARITY_CONTEXT_WINDOW: usize = 1024;
pub const OVERFLOW_PARITY_MAX_TOKENS: usize = OVERFLOW_PARITY_CONTEXT_WINDOW;
pub const OVERFLOW_PARITY_MAX_TOKENS_CAP: usize = 4096;
pub const OVERFLOW_PARITY_REQUEST_BODY: &str = r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"max_tokens":1024,"stream":true}"#;
#[derive(Debug)]
pub enum ApiError {
BadRequest { message: String, code: &'static str },
PayloadTooLarge { message: String },
Internal { message: String },
}
impl ApiError {
pub fn message(&self) -> &str {
match self {
ApiError::BadRequest { message, .. } => message,
ApiError::PayloadTooLarge { message } => message,
ApiError::Internal { message } => message,
}
}
}
#[derive(Serialize)]
struct ErrorBody {
error: ErrorDetail,
}
#[derive(Serialize)]
struct ErrorDetail {
message: String,
r#type: &'static str,
code: String,
param: Option<String>,
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
match self {
ApiError::BadRequest { message, code } => {
let body = Json(ErrorBody {
error: ErrorDetail {
message,
r#type: "invalid_request_error",
code: code.to_string(),
param: None,
},
});
(StatusCode::BAD_REQUEST, body).into_response()
}
ApiError::PayloadTooLarge { message } => {
let body = Json(ErrorBody {
error: ErrorDetail {
message,
r#type: "invalid_request_error",
code: "request_body_too_large".to_string(),
param: None,
},
});
(StatusCode::PAYLOAD_TOO_LARGE, body).into_response()
}
ApiError::Internal { message } => {
let body = Json(ErrorBody {
error: ErrorDetail {
message,
r#type: "server_error",
code: "internal_error".to_string(),
param: None,
},
});
(StatusCode::INTERNAL_SERVER_ERROR, body).into_response()
}
}
}
}
pub fn finish_reason(stopped: bool) -> &'static str {
if stopped { "stop" } else { "length" }
}
pub fn reject_zero_max_tokens(effective: usize) -> Result<(), ApiError> {
if effective == 0 {
return Err(ApiError::BadRequest {
message: "max_tokens must be at least 1".to_string(),
code: "invalid_max_tokens",
});
}
Ok(())
}
pub fn root_body() -> Value {
serde_json::json!({
"name": "lattice",
"object": "engine",
"endpoints": ["/v1/chat/completions", "/v1/models", "/health"],
})
}
pub fn models_list_body(model_id: &str, created: u64) -> Value {
serde_json::json!({
"object": "list",
"data": [{
"id": model_id,
"object": "model",
"created": created,
"owned_by": "lattice",
}],
})
}
pub struct CancelOnDrop(pub watch::Sender<bool>);
impl Drop for CancelOnDrop {
fn drop(&mut self) {
let _ = self.0.send(true);
}
}
pub fn cancel_pair() -> (CancelOnDrop, watch::Receiver<bool>) {
let (tx, rx) = watch::channel(false);
(CancelOnDrop(tx), rx)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Binary {
Lattice,
LatticeServe,
}
pub enum CaseBody {
Fixed(&'static str),
Oversized,
}
impl CaseBody {
pub fn build(&self) -> Vec<u8> {
match self {
CaseBody::Fixed(s) => s.as_bytes().to_vec(),
CaseBody::Oversized => {
let filler = "x".repeat(REQUEST_BODY_LIMIT_BYTES + 1);
format!(
r#"{{"model":"test-model","messages":[{{"role":"user","content":"{filler}"}}]}}"#
)
.into_bytes()
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Scalar {
Str(&'static str),
U64(u64),
Bool(bool),
}
impl Scalar {
fn matches(&self, value: &Value) -> bool {
match self {
Scalar::Str(s) => value.as_str() == Some(*s),
Scalar::U64(n) => value.as_u64() == Some(*n),
Scalar::Bool(b) => value.as_bool() == Some(*b),
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum FieldExpectation {
Eq {
json_pointer: &'static str,
scalar: Scalar,
},
Absent { json_pointer: &'static str },
ArrayLen {
json_pointer: &'static str,
len: usize,
},
StringPrefix {
json_pointer: &'static str,
prefix: &'static str,
},
UnsignedInt { json_pointer: &'static str },
}
impl FieldExpectation {
pub fn check(&self, body: &Value) -> Result<(), String> {
match self {
FieldExpectation::Eq {
json_pointer,
scalar,
} => match body.pointer(json_pointer) {
Some(value) if scalar.matches(value) => Ok(()),
Some(value) => Err(format!(
"field '{json_pointer}': expected {scalar:?}, got {value} (body: {body})"
)),
None => Err(format!(
"field '{json_pointer}': expected {scalar:?}, field is absent (body: {body})"
)),
},
FieldExpectation::Absent { json_pointer } => match body.pointer(json_pointer) {
None => Ok(()),
Some(value) => Err(format!(
"field '{json_pointer}': expected absent, got {value} (body: {body})"
)),
},
FieldExpectation::ArrayLen { json_pointer, len } => match body.pointer(json_pointer) {
Some(Value::Array(arr)) if arr.len() == *len => Ok(()),
Some(Value::Array(arr)) => Err(format!(
"field '{json_pointer}': expected array of length {len}, got length {} \
(body: {body})",
arr.len()
)),
Some(other) => Err(format!(
"field '{json_pointer}': expected an array of length {len}, got {other} \
(body: {body})"
)),
None => Err(format!(
"field '{json_pointer}': expected an array of length {len}, field is \
absent (body: {body})"
)),
},
FieldExpectation::StringPrefix {
json_pointer,
prefix,
} => match body.pointer(json_pointer).and_then(Value::as_str) {
Some(s) if s.starts_with(prefix) => Ok(()),
Some(s) => Err(format!(
"field '{json_pointer}': expected a string starting with '{prefix}', got \
'{s}' (body: {body})"
)),
None => Err(format!(
"field '{json_pointer}': expected a string starting with '{prefix}', field \
is absent or not a string (body: {body})"
)),
},
FieldExpectation::UnsignedInt { json_pointer } => {
match body.pointer(json_pointer).and_then(Value::as_u64) {
Some(_) => Ok(()),
None => Err(format!(
"field '{json_pointer}': expected an unsigned integer, field is \
absent or not representable as u64 (body: {body})"
)),
}
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum EventExpectation {
RoleOpener,
ContentDelta,
Finish { finish_reason: &'static str },
Done,
}
enum SseFrame {
Chunk(Value),
Done,
}
fn parse_sse_frames(body: &str) -> Vec<SseFrame> {
body.lines()
.filter_map(|line| {
line.strip_prefix("data: ")
.or_else(|| line.strip_prefix("data:"))
})
.map(|payload| {
let payload = payload.trim();
if payload == "[DONE]" {
SseFrame::Done
} else {
SseFrame::Chunk(
serde_json::from_str(payload).unwrap_or_else(|e| {
panic!("SSE data payload must be JSON: {e} ({payload})")
}),
)
}
})
.collect()
}
enum ChunkKind {
RoleOpener,
ContentDelta,
Finish {
finish_reason: String,
},
Other,
}
fn classify_chunk(chunk: &Value) -> ChunkKind {
let Some(choice) = chunk.pointer("/choices/0") else {
return ChunkKind::Other;
};
let finish_reason = choice.pointer("/finish_reason");
let role = choice.pointer("/delta/role");
let content = choice.pointer("/delta/content");
if finish_reason.is_none_or(Value::is_null) {
if role.and_then(Value::as_str) == Some("assistant") && content.is_none() {
return ChunkKind::RoleOpener;
}
if content.and_then(Value::as_str).is_some() && role.is_none() {
return ChunkKind::ContentDelta;
}
ChunkKind::Other
} else {
match finish_reason.and_then(Value::as_str) {
Some(reason) if role.is_none() && content.is_none() => ChunkKind::Finish {
finish_reason: reason.to_string(),
},
_ => ChunkKind::Other,
}
}
}
pub fn check_sse_events(body: &str, expected: &[EventExpectation]) -> Result<(), String> {
let frames = parse_sse_frames(body);
let mut idx = 0usize;
for (phase_idx, exp) in expected.iter().enumerate() {
match exp {
EventExpectation::ContentDelta => {
let start = idx;
while idx < frames.len()
&& matches!(
&frames[idx],
SseFrame::Chunk(c) if matches!(classify_chunk(c), ChunkKind::ContentDelta)
)
{
idx += 1;
}
if idx == start {
return Err(format!(
"expected phase {phase_idx} (ContentDelta) to match at least one \
content-delta chunk at frame index {start}, but none matched"
));
}
}
EventExpectation::Done => match frames.get(idx) {
Some(SseFrame::Done) => idx += 1,
Some(SseFrame::Chunk(c)) => {
return Err(format!(
"expected phase {phase_idx} (Done) at frame index {idx}, got a \
chunk instead: {c}"
));
}
None => {
return Err(format!(
"expected phase {phase_idx} (Done) at frame index {idx}, but the \
stream ended"
));
}
},
EventExpectation::RoleOpener => {
let frame = frames.get(idx).ok_or_else(|| {
format!(
"expected phase {phase_idx} (RoleOpener) at frame index {idx}, but \
the stream ended"
)
})?;
match frame {
SseFrame::Chunk(c) if matches!(classify_chunk(c), ChunkKind::RoleOpener) => {
FieldExpectation::StringPrefix {
json_pointer: "/id",
prefix: "chatcmpl-",
}
.check(c)
.map_err(|e| {
format!("phase {phase_idx} (RoleOpener) chunk field check failed: {e}")
})?;
FieldExpectation::UnsignedInt {
json_pointer: "/created",
}
.check(c)
.map_err(|e| {
format!("phase {phase_idx} (RoleOpener) chunk field check failed: {e}")
})?;
idx += 1;
}
other => {
return Err(sse_phase_mismatch(phase_idx, "RoleOpener", idx, other));
}
}
}
EventExpectation::Finish { finish_reason } => {
let frame = frames.get(idx).ok_or_else(|| {
format!(
"expected phase {phase_idx} (Finish) at frame index {idx}, but the \
stream ended"
)
})?;
match frame {
SseFrame::Chunk(c) => match classify_chunk(c) {
ChunkKind::Finish {
finish_reason: actual,
} if actual == *finish_reason => {
idx += 1;
}
_ => {
return Err(format!(
"expected phase {phase_idx} (Finish {{ finish_reason: \
\"{finish_reason}\" }}) at frame index {idx}, got: {c}"
));
}
},
SseFrame::Done => {
return Err(sse_phase_mismatch(phase_idx, "Finish", idx, frame));
}
}
}
}
}
if idx != frames.len() {
return Err(format!(
"expected exactly {idx} SSE frames but the stream carried {} \
(trailing frames beyond every listed phase)",
frames.len()
));
}
Ok(())
}
fn sse_phase_mismatch(phase_idx: usize, phase: &str, idx: usize, frame: &SseFrame) -> String {
match frame {
SseFrame::Chunk(c) => {
format!("expected phase {phase_idx} ({phase}) at frame index {idx}, got chunk: {c}")
}
SseFrame::Done => format!(
"expected phase {phase_idx} ({phase}) at frame index {idx}, got the [DONE] sentinel"
),
}
}
#[derive(Debug, Clone, Copy)]
pub enum ExpectedResponse {
Error { status: u16, code: &'static str },
Json {
status: u16,
fields: &'static [FieldExpectation],
},
Sse {
status: u16,
events: &'static [EventExpectation],
},
}
impl ExpectedResponse {
pub fn status(&self) -> u16 {
match self {
ExpectedResponse::Error { status, .. } => *status,
ExpectedResponse::Json { status, .. } => *status,
ExpectedResponse::Sse { status, .. } => *status,
}
}
}
pub struct ParityCase {
pub name: &'static str,
pub method: &'static str,
pub path: &'static str,
pub body: CaseBody,
lattice: ExpectedResponse,
lattice_serve: ExpectedResponse,
pub divergence_reason: Option<&'static str>,
}
impl ParityCase {
pub fn expected(&self, binary: Binary) -> ExpectedResponse {
match binary {
Binary::Lattice => self.lattice,
Binary::LatticeServe => self.lattice_serve,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct GenerateConfigSnapshot {
pub max_new_tokens: usize,
pub temperature: f32,
pub top_k: usize,
pub top_p: f32,
pub repetition_penalty: f32,
pub seed: Option<u64>,
pub stop_token_ids: Vec<u32>,
pub enable_thinking: bool,
pub enable_mtp: Option<bool>,
pub has_grammar: bool,
pub stop_strings: Vec<String>,
pub reasoning_budget: Option<usize>,
pub logprobs: Option<usize>,
}
impl From<&GenerateConfig> for GenerateConfigSnapshot {
fn from(cfg: &GenerateConfig) -> Self {
GenerateConfigSnapshot {
max_new_tokens: cfg.max_new_tokens,
temperature: cfg.temperature,
top_k: cfg.top_k,
top_p: cfg.top_p,
repetition_penalty: cfg.repetition_penalty,
seed: cfg.seed,
stop_token_ids: cfg.stop_token_ids.clone(),
enable_thinking: cfg.enable_thinking,
enable_mtp: cfg.enable_mtp,
has_grammar: cfg.grammar.is_some(),
stop_strings: cfg.stop_strings.clone(),
reasoning_budget: cfg.reasoning_budget,
logprobs: cfg.logprobs,
}
}
}
#[derive(Debug, Clone)]
pub struct ProductionAdapterObservation {
pub rendered_prompt: Option<String>,
pub messages: Option<Vec<(String, String)>>,
pub gen_cfg: GenerateConfigSnapshot,
pub prompt_tokens: usize,
pub stopped: bool,
}
pub const OBSERVATION_GOLDEN_USER_HI_THERE_CHATML: &str =
"<|im_start|>user\nhi there<|im_end|>\n<|im_start|>assistant\n";
pub struct ExpectedObservation<'a> {
pub gen_cfg: GenerateConfigSnapshot,
pub rendered_prompt: Option<&'a str>,
pub messages: Option<&'a [(&'a str, &'a str)]>,
pub prompt_tokens: usize,
pub stopped: bool,
}
pub fn assert_observation_matches(
obs: &ProductionAdapterObservation,
expected: &ExpectedObservation<'_>,
) {
assert_eq!(
obs.gen_cfg, expected.gen_cfg,
"GenerateConfigSnapshot mismatch: observed {:?}, expected {:?}",
obs.gen_cfg, expected.gen_cfg
);
assert_eq!(
obs.rendered_prompt.as_deref(),
expected.rendered_prompt,
"rendered_prompt mismatch: observed {:?}, expected {:?}",
obs.rendered_prompt,
expected.rendered_prompt
);
let expected_messages: Option<Vec<(String, String)>> = expected.messages.map(|m| {
m.iter()
.map(|(r, c)| (r.to_string(), c.to_string()))
.collect()
});
assert_eq!(
obs.messages, expected_messages,
"messages mismatch: observed {:?}, expected {:?}",
obs.messages, expected_messages
);
assert_eq!(
obs.prompt_tokens, expected.prompt_tokens,
"prompt_tokens mismatch: observed {}, expected {}",
obs.prompt_tokens, expected.prompt_tokens
);
assert_eq!(
obs.stopped, expected.stopped,
"stopped (terminal outcome) mismatch: observed {}, expected {}",
obs.stopped, expected.stopped
);
}
pub const CHAT_COMPLETIONS_PARITY_CASES: &[ParityCase] = &[
ParityCase {
name: "unknown_role_not_openai",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"moderator","content":"hi"},{"role":"user","content":"hi"}]}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_role",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "invalid_role",
},
divergence_reason: None,
},
ParityCase {
name: "developer_role_unsupported_feature",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"developer","content":"hi"},{"role":"user","content":"hi"}]}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "unsupported_feature",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "unsupported_feature",
},
divergence_reason: None,
},
ParityCase {
name: "empty_messages",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(r#"{"model":"test-model","messages":[]}"#),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_messages",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "invalid_messages",
},
divergence_reason: None,
},
ParityCase {
name: "max_tokens_zero",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"max_tokens":0}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_max_tokens",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "invalid_max_tokens",
},
divergence_reason: None,
},
ParityCase {
name: "max_tokens_and_max_completion_tokens_conflict",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"max_tokens":10,"max_completion_tokens":20}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_request",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "invalid_request",
},
divergence_reason: None,
},
ParityCase {
name: "tools_unsupported",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"tools":[{"type":"function","function":{"name":"f"}}]}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "unsupported_feature",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "unsupported_feature",
},
divergence_reason: None,
},
ParityCase {
name: "malformed_json_body",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(r#"{"model":"test-model","messages":"#),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_request_body",
},
lattice_serve: ExpectedResponse::Error {
status: 400,
code: "invalid_request_body",
},
divergence_reason: None,
},
ParityCase {
name: "max_tokens_over_cap_reject_vs_clamp",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"max_tokens":999999}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "max_tokens_exceeds_limit",
},
lattice_serve: ExpectedResponse::Error {
status: 500,
code: "internal_error",
},
divergence_reason: Some(
"lattice.rs rejects max_tokens above its server cap at validation time; \
lattice_serve.rs clamps the resolved value to the model's context \
window and proceeds past validation instead of rejecting -- an \
intentional per-binary policy difference, not drift (see \
reject_zero_max_tokens's doc comment). The lattice_serve 500 here is \
this router-level fixture's no-live-worker harness artifact once past \
validation, not the divergence itself.",
),
},
ParityCase {
name: "get_root_route_exposed",
method: "GET",
path: "/",
body: CaseBody::Fixed(""),
lattice: ExpectedResponse::Json {
status: 200,
fields: &[],
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: &[],
},
divergence_reason: None,
},
ParityCase {
name: "oversized_body_over_limit",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Oversized,
lattice: ExpectedResponse::Error {
status: 413,
code: "request_body_too_large",
},
lattice_serve: ExpectedResponse::Error {
status: 413,
code: "request_body_too_large",
},
divergence_reason: None,
},
ParityCase {
name: "baseline_non_streaming_200",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}]}"#,
),
lattice: ExpectedResponse::Json {
status: 200,
fields: &[
FieldExpectation::StringPrefix {
json_pointer: "/id",
prefix: "chatcmpl-",
},
FieldExpectation::UnsignedInt {
json_pointer: "/created",
},
FieldExpectation::Eq {
json_pointer: "/object",
scalar: Scalar::Str("chat.completion"),
},
FieldExpectation::Eq {
json_pointer: "/model",
scalar: Scalar::Str("test-model"),
},
FieldExpectation::Eq {
json_pointer: "/choices/0/message/role",
scalar: Scalar::Str("assistant"),
},
FieldExpectation::Eq {
json_pointer: "/choices/0/message/content",
scalar: Scalar::Str(BASELINE_CANNED_TEXT),
},
FieldExpectation::Eq {
json_pointer: "/choices/0/finish_reason",
scalar: Scalar::Str("stop"),
},
FieldExpectation::Eq {
json_pointer: "/usage/prompt_tokens",
scalar: Scalar::U64(BASELINE_CANNED_PROMPT_TOKENS),
},
FieldExpectation::Eq {
json_pointer: "/usage/completion_tokens",
scalar: Scalar::U64(BASELINE_CANNED_COMPLETION_TOKENS),
},
FieldExpectation::Eq {
json_pointer: "/usage/total_tokens",
scalar: Scalar::U64(
BASELINE_CANNED_PROMPT_TOKENS + BASELINE_CANNED_COMPLETION_TOKENS,
),
},
],
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: &[
FieldExpectation::StringPrefix {
json_pointer: "/id",
prefix: "chatcmpl-",
},
FieldExpectation::UnsignedInt {
json_pointer: "/created",
},
FieldExpectation::Eq {
json_pointer: "/object",
scalar: Scalar::Str("chat.completion"),
},
FieldExpectation::Eq {
json_pointer: "/model",
scalar: Scalar::Str("test-model"),
},
FieldExpectation::Eq {
json_pointer: "/choices/0/message/role",
scalar: Scalar::Str("assistant"),
},
FieldExpectation::Eq {
json_pointer: "/choices/0/message/content",
scalar: Scalar::Str(BASELINE_CANNED_TEXT),
},
FieldExpectation::Eq {
json_pointer: "/choices/0/finish_reason",
scalar: Scalar::Str("stop"),
},
FieldExpectation::Eq {
json_pointer: "/usage/prompt_tokens",
scalar: Scalar::U64(BASELINE_CANNED_PROMPT_TOKENS),
},
FieldExpectation::Eq {
json_pointer: "/usage/completion_tokens",
scalar: Scalar::U64(BASELINE_CANNED_COMPLETION_TOKENS),
},
FieldExpectation::Eq {
json_pointer: "/usage/total_tokens",
scalar: Scalar::U64(
BASELINE_CANNED_PROMPT_TOKENS + BASELINE_CANNED_COMPLETION_TOKENS,
),
},
],
},
divergence_reason: None,
},
ParityCase {
name: "baseline_streaming_200",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"stream":true}"#,
),
lattice: ExpectedResponse::Sse {
status: 200,
events: BASELINE_SSE_EVENTS,
},
lattice_serve: ExpectedResponse::Sse {
status: 200,
events: BASELINE_SSE_EVENTS,
},
divergence_reason: None,
},
ParityCase {
name: "temperature_boundary_zero_accepted",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"temperature":0.0}"#,
),
lattice: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
divergence_reason: None,
},
ParityCase {
name: "temperature_boundary_two_accepted",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"temperature":2.0}"#,
),
lattice: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
divergence_reason: None,
},
ParityCase {
name: "temperature_out_of_range_rejected",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"temperature":2.5}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_temperature",
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
divergence_reason: Some(
"lattice.rs's validate_temperature rejects outside [0.0, 2.0]; \
lattice_serve.rs's build_cfg has no temperature range check at \
all and passes any client-supplied value straight into \
GenerateConfig -- a pre-existing gap, not introduced by #828.",
),
},
ParityCase {
name: "top_p_boundary_one_accepted",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"top_p":1.0}"#,
),
lattice: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
divergence_reason: None,
},
ParityCase {
name: "top_p_zero_rejected",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"top_p":0.0}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_top_p",
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
divergence_reason: Some(
"lattice.rs's validate_top_p rejects a top_p of 0.0 ((0.0, 1.0] \
is half-open at zero); lattice_serve.rs's build_cfg has no \
top_p range check at all -- a pre-existing gap, not introduced \
by #828.",
),
},
ParityCase {
name: "top_p_above_one_rejected",
method: "POST",
path: "/v1/chat/completions",
body: CaseBody::Fixed(
r#"{"model":"test-model","messages":[{"role":"user","content":"hi"}],"top_p":1.5}"#,
),
lattice: ExpectedResponse::Error {
status: 400,
code: "invalid_top_p",
},
lattice_serve: ExpectedResponse::Json {
status: 200,
fields: ACCEPTED_MINIMAL_FIELDS,
},
divergence_reason: Some(
"lattice.rs's validate_top_p rejects anything above 1.0; \
lattice_serve.rs's build_cfg has no top_p range check at all \
-- a pre-existing gap, not introduced by #828.",
),
},
];
pub const BASELINE_CANNED_TEXT: &str = "hello world";
pub const BASELINE_CANNED_PROMPT_TOKENS: u64 = 7;
pub const BASELINE_CANNED_COMPLETION_TOKENS: u64 = 2;
pub const BASELINE_SSE_EVENTS: &[EventExpectation] = &[
EventExpectation::RoleOpener,
EventExpectation::ContentDelta,
EventExpectation::Finish {
finish_reason: "stop",
},
EventExpectation::Done,
];
const ACCEPTED_MINIMAL_FIELDS: &[FieldExpectation] = &[FieldExpectation::Eq {
json_pointer: "/object",
scalar: Scalar::Str("chat.completion"),
}];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn finish_reason_stopped_true_is_stop() {
assert_eq!(finish_reason(true), "stop");
}
#[test]
fn finish_reason_stopped_false_is_length() {
assert_eq!(finish_reason(false), "length");
}
#[test]
fn reject_zero_max_tokens_rejects_zero() {
let err = reject_zero_max_tokens(0).unwrap_err();
assert!(matches!(
err,
ApiError::BadRequest {
code: "invalid_max_tokens",
..
}
));
}
#[test]
fn reject_zero_max_tokens_accepts_positive() {
assert!(reject_zero_max_tokens(1).is_ok());
assert!(reject_zero_max_tokens(4096).is_ok());
}
#[test]
fn root_body_shape() {
let body = root_body();
assert_eq!(body["name"], "lattice");
assert_eq!(body["object"], "engine");
assert_eq!(
body["endpoints"],
serde_json::json!(["/v1/chat/completions", "/v1/models", "/health"])
);
}
#[test]
fn models_list_body_shape() {
let body = models_list_body("my-model", 1_700_000_000);
assert_eq!(body["object"], "list");
assert_eq!(body["data"][0]["id"], "my-model");
assert_eq!(body["data"][0]["object"], "model");
assert_eq!(body["data"][0]["created"], 1_700_000_000);
assert_eq!(body["data"][0]["owned_by"], "lattice");
}
#[test]
fn api_error_bad_request_envelope_shape() {
let err = ApiError::BadRequest {
message: "bad".to_string(),
code: "some_code",
};
assert_eq!(err.message(), "bad");
}
#[test]
fn api_error_internal_message() {
let err = ApiError::Internal {
message: "oops".to_string(),
};
assert_eq!(err.message(), "oops");
}
#[test]
fn api_error_payload_too_large_message() {
let err = ApiError::PayloadTooLarge {
message: "too big".to_string(),
};
assert_eq!(err.message(), "too big");
}
#[test]
fn cancel_pair_receiver_starts_false() {
let (_guard, rx) = cancel_pair();
assert!(!*rx.borrow());
}
#[test]
fn cancel_on_drop_flips_receiver_true_on_drop() {
let (guard, rx) = cancel_pair();
assert!(!*rx.borrow());
drop(guard);
assert!(*rx.borrow());
}
#[test]
fn cancel_on_drop_leaves_receiver_false_while_alive() {
let (guard, rx) = cancel_pair();
assert!(!*rx.borrow());
assert!(!*rx.borrow());
drop(guard);
}
#[test]
fn field_expectation_eq_matches_and_reports_mismatch() {
let body = serde_json::json!({"object": "chat.completion", "usage": {"total_tokens": 9}});
assert!(
FieldExpectation::Eq {
json_pointer: "/object",
scalar: Scalar::Str("chat.completion"),
}
.check(&body)
.is_ok()
);
assert!(
FieldExpectation::Eq {
json_pointer: "/usage/total_tokens",
scalar: Scalar::U64(9),
}
.check(&body)
.is_ok()
);
let err = FieldExpectation::Eq {
json_pointer: "/object",
scalar: Scalar::Str("chat.completion.chunk"),
}
.check(&body)
.unwrap_err();
assert!(err.contains("/object"), "error must name the field: {err}");
}
#[test]
fn field_expectation_eq_missing_field_is_an_error() {
let body = serde_json::json!({});
let err = FieldExpectation::Eq {
json_pointer: "/model",
scalar: Scalar::Str("x"),
}
.check(&body)
.unwrap_err();
assert!(err.contains("absent"));
}
#[test]
fn field_expectation_absent_passes_when_missing_fails_when_present() {
let body = serde_json::json!({"logprobs": null});
assert!(
FieldExpectation::Absent {
json_pointer: "/choices"
}
.check(&body)
.is_ok()
);
let err = FieldExpectation::Absent {
json_pointer: "/logprobs",
}
.check(&body)
.unwrap_err();
assert!(err.contains("expected absent"));
}
#[test]
fn field_expectation_array_len_checks_exact_length() {
let body = serde_json::json!({"choices": [{"index": 0}]});
assert!(
FieldExpectation::ArrayLen {
json_pointer: "/choices",
len: 1,
}
.check(&body)
.is_ok()
);
assert!(
FieldExpectation::ArrayLen {
json_pointer: "/choices",
len: 2,
}
.check(&body)
.is_err()
);
}
fn sse_body(lines: &[&str]) -> String {
lines.iter().map(|l| format!("data: {l}\n\n")).collect()
}
#[test]
fn check_sse_events_accepts_well_formed_baseline_stream() {
let body = sse_body(&[
r#"{"id":"chatcmpl-1","created":1,"choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{"content":"hel"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{"content":"lo"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}"#,
"[DONE]",
]);
check_sse_events(&body, BASELINE_SSE_EVENTS).expect("well-formed stream must pass");
}
#[test]
fn check_sse_events_requires_at_least_one_content_delta() {
let body = sse_body(&[
r#"{"id":"chatcmpl-1","created":1,"choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}"#,
"[DONE]",
]);
let err = check_sse_events(&body, BASELINE_SSE_EVENTS).unwrap_err();
assert!(err.contains("ContentDelta"), "error: {err}");
}
#[test]
fn check_sse_events_rejects_wrong_finish_reason() {
let body = sse_body(&[
r#"{"id":"chatcmpl-1","created":1,"choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{"content":"hi"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{},"finish_reason":"length"}]}"#,
"[DONE]",
]);
assert!(check_sse_events(&body, BASELINE_SSE_EVENTS).is_err());
}
#[test]
fn check_sse_events_rejects_missing_done_sentinel() {
let body = sse_body(&[
r#"{"id":"chatcmpl-1","created":1,"choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{"content":"hi"},"finish_reason":null}]}"#,
r#"{"choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}"#,
]);
let err = check_sse_events(&body, BASELINE_SSE_EVENTS).unwrap_err();
assert!(
err.contains("Done") || err.contains("stream ended"),
"error: {err}"
);
}
#[test]
fn check_sse_events_rejects_role_opener_missing_id_or_created() {
let missing_id = sse_body(&[
r#"{"created":1,"choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}"#,
]);
let err = check_sse_events(&missing_id, &[EventExpectation::RoleOpener]).unwrap_err();
assert!(err.contains("/id"), "error: {err}");
let missing_created = sse_body(&[
r#"{"id":"chatcmpl-1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}"#,
]);
let err = check_sse_events(&missing_created, &[EventExpectation::RoleOpener]).unwrap_err();
assert!(err.contains("/created"), "error: {err}");
}
#[test]
fn generate_config_snapshot_captures_every_field() {
let cfg = GenerateConfig {
max_new_tokens: 42,
temperature: 1.3,
top_k: 7,
top_p: 0.55,
repetition_penalty: 1.05,
seed: Some(9),
stop_token_ids: vec![100],
enable_thinking: false,
enable_mtp: Some(true),
grammar: None,
stop_strings: vec!["STOP".to_string()],
reasoning_budget: Some(3),
logprobs: Some(2),
};
let snapshot = GenerateConfigSnapshot::from(&cfg);
assert_eq!(snapshot.max_new_tokens, 42);
assert_eq!(snapshot.temperature, 1.3);
assert_eq!(snapshot.top_k, 7);
assert_eq!(snapshot.top_p, 0.55);
assert_eq!(snapshot.repetition_penalty, 1.05);
assert_eq!(snapshot.seed, Some(9));
assert_eq!(snapshot.stop_token_ids, vec![100]);
assert!(!snapshot.enable_thinking);
assert_eq!(snapshot.enable_mtp, Some(true));
assert!(!snapshot.has_grammar);
assert_eq!(snapshot.stop_strings, vec!["STOP".to_string()]);
assert_eq!(snapshot.reasoning_budget, Some(3));
assert_eq!(snapshot.logprobs, Some(2));
}
#[test]
fn chat_completions_parity_cases_expected_status_matches_variant() {
for case in CHAT_COMPLETIONS_PARITY_CASES {
for binary in [Binary::Lattice, Binary::LatticeServe] {
let expected = case.expected(binary);
match expected {
ExpectedResponse::Error { status, .. } => assert!(
!(200..300).contains(&status),
"case '{}': Error variant must not carry a 2xx status",
case.name
),
ExpectedResponse::Json { status, .. }
| ExpectedResponse::Sse { status, .. } => {
assert_eq!(
expected.status(),
status,
"case '{}': status() must match the variant's own status",
case.name
);
}
}
}
}
}
}