use openrouter_batch::{
BatchObject, BatchTransport, Message, StructuredParams, SubmitBatch, TransportError,
submit_structured,
};
use parking_lot::Mutex;
use serde_json::json;
use std::sync::Arc;
struct CapturingTransport {
submitted: Arc<Mutex<Option<SubmitBatch>>>,
}
#[async_trait::async_trait]
impl BatchTransport for CapturingTransport {
async fn submit(
&self,
batch: &SubmitBatch,
_idempotency_key: &str,
) -> Result<BatchObject, TransportError> {
*self.submitted.lock() = Some(batch.clone());
Ok(serde_json::from_value(json!({
"id": "batch_1", "status": "validating", "created_at": 1_000
}))
.unwrap())
}
async fn get(&self, _batch_id: &str) -> Result<BatchObject, TransportError> {
panic!("no poll expected in this test");
}
}
fn params(disable_reasoning: bool) -> StructuredParams {
StructuredParams {
schema: json!({"type": "object"}),
schema_name: "reply".to_string(),
max_tokens: 100,
disable_reasoning,
require_parameters: false,
reasoning_max_tokens: None,
}
}
fn messages() -> Vec<Message> {
vec![Message::user("Say OK")]
}
#[tokio::test]
async fn overlong_custom_id_fails_without_submitting() {
let submitted = Arc::new(Mutex::new(None));
let transport = CapturingTransport {
submitted: submitted.clone(),
};
let long_key = "a".repeat(65);
let error = submit_structured(
&transport,
"z-ai/glm-5.3-flash:batch",
"idempotency-1",
¶ms(false),
vec![(long_key, messages())],
)
.await
.unwrap_err();
assert!(error.to_string().contains("64-character cap"), "{error}");
assert!(!error.retryable(), "a key-scheme fix is the only remedy");
assert!(
submitted.lock().is_none(),
"no batch may reach the transport"
);
}
#[tokio::test]
async fn sixty_four_character_custom_id_submits() {
let submitted = Arc::new(Mutex::new(None));
let transport = CapturingTransport {
submitted: submitted.clone(),
};
submit_structured(
&transport,
"z-ai/glm-5.3-flash:batch",
"idempotency-1",
¶ms(false),
vec![("a".repeat(64), messages())],
)
.await
.unwrap();
assert!(submitted.lock().is_some());
}
#[tokio::test]
async fn reasoning_field_is_omitted_unless_requested() {
let submitted = Arc::new(Mutex::new(None));
let transport = CapturingTransport {
submitted: submitted.clone(),
};
submit_structured(
&transport,
"z-ai/glm-5.3-flash:batch",
"idempotency-1",
¶ms(false),
vec![("req-1".to_string(), messages())],
)
.await
.unwrap();
let batch = submitted.lock().clone().unwrap();
let body = &batch.requests()[0].body;
assert!(body.get("reasoning").is_none(), "{body}");
submit_structured(
&transport,
"z-ai/glm-5.3-flash:batch",
"idempotency-2",
¶ms(true),
vec![("req-1".to_string(), messages())],
)
.await
.unwrap();
let batch = submitted.lock().clone().unwrap();
let body = &batch.requests()[0].body;
assert_eq!(body["reasoning"], json!({"enabled": false}), "{body}");
}