use super::*;
use crate::error::AxCode;
use crate::event::Payload;
use crate::locator::{B3Hash, Locator};
use serde_json::Map;
fn one_image() -> ImageRef {
ImageRef {
locator: Locator::parse(&format!("cas:b3-{}", "ab".repeat(32))).unwrap(),
media_type: ImageType::Png,
width: 640,
height: 480,
}
}
#[test]
fn a_picture_crosses_the_ledger_as_a_locator_and_four_integers() {
let blocks = vec![
ContentBlock::Image(one_image()),
ContentBlock::ToolResult {
tool_use_id: "tu_1".to_owned(),
content: "the screenshot".to_owned(),
is_error: false,
attachments: vec![one_image()],
},
];
let payload = message_payload(&blocks).unwrap();
assert_eq!(content_from_message(&payload).unwrap(), blocks);
let json = serde_json::to_value(&blocks[0]).unwrap();
assert_eq!(json["kind"], "image");
assert_eq!(json["media_type"], "png");
assert_eq!(json["width"], 640);
assert_eq!(json["height"], 480);
assert_eq!(ImageType::Jpeg.mime(), "image/jpeg");
}
#[test]
fn a_tool_result_written_before_attachments_existed_still_replays() {
let old = serde_json::json!({
"kind": "tool_result",
"tool_use_id": "tu_1",
"content": "ok",
"is_error": false,
});
let block: ContentBlock = serde_json::from_value(old).unwrap();
assert_eq!(
block,
ContentBlock::ToolResult {
tool_use_id: "tu_1".to_owned(),
content: "ok".to_owned(),
is_error: false,
attachments: Vec::new(),
}
);
}
#[test]
fn policy_default_is_not_confidential() {
assert!(!BuildingPolicy::default().confidential);
assert!(BuildingPolicy::new(true).confidential);
}
#[test]
fn model_return_roundtrips_with_sorted_payload_keys() {
let ret = ModelReturn::bare(Payload::empty(), vec![]);
let json = serde_json::to_string(&ret).unwrap();
let back: ModelReturn = serde_json::from_str(&json).unwrap();
assert_eq!(back, ret);
}
#[test]
fn thinking_survives_the_payload_round_trip_verbatim() {
let signature = format!("{}{}", "WaUjzkyp", "Q2mUEVM36O2Txu");
let issued = vec![
ContentBlock::Thinking {
thinking: "The question has two parts.".to_owned(),
signature,
},
ContentBlock::RedactedThinking {
data: "EroBCkYIARgCKkBmx".to_owned(),
},
ContentBlock::Text {
text: "Based on my analysis...".to_owned(),
},
];
let payload = message_payload(&issued).unwrap();
assert_eq!(content_from_message(&payload).unwrap(), issued);
}
#[test]
fn a_content_array_that_cannot_be_read_is_an_error_not_an_empty_window() {
let mut map = Map::new();
map.insert(
"content".to_owned(),
serde_json::json!([{ "kind": "from_a_later_build" }]),
);
let payload = Payload::new(map).unwrap();
let err = content_from_message(&payload).unwrap_err();
assert_eq!(*err.code(), AxCode::WireMismatch);
assert!(content_from_message(&Payload::empty()).unwrap().is_empty());
}
#[test]
fn effort_is_ordered_from_none_to_max() {
let ladder = [
Effort::None,
Effort::Low,
Effort::Medium,
Effort::High,
Effort::XHigh,
Effort::Max,
];
assert!(ladder.windows(2).all(|pair| pair[0] < pair[1]));
assert_eq!(
serde_json::to_string(&Effort::XHigh).unwrap(),
"\"xhigh\"",
"the city spells an effort level the way the provider spells it"
);
}
#[test]
fn request_carries_four_segment_hashes() {
let req = ModelRequest {
policy: BuildingPolicy::default(),
segments: [B3Hash::digest(b"a"); 4],
chat: ChatRequest::empty("m", Ceiling::new(64).unwrap()),
};
let json = serde_json::to_value(&req).unwrap();
assert_eq!(json["segments"].as_array().unwrap().len(), 4);
}
#[test]
fn an_unversioned_usage_row_reads_in_the_one_meaning() {
let read = |row: serde_json::Value| {
serde_json::from_value::<ModelUsage>(row)
.unwrap()
.input_tokens
.get()
};
let anthropic_row = serde_json::json!({
"input_tokens": 10, "output_tokens": 1,
"cache_read_tokens": 90, "cache_write_tokens": 5,
});
let uncached_row = serde_json::json!({
"input_tokens": 10, "output_tokens": 1,
"cache_read_tokens": 0, "cache_write_tokens": 0,
});
let versioned_row = serde_json::json!({
"input_tokens": 10, "output_tokens": 1,
"cache_read_tokens": 90, "cache_write_tokens": 5, "v": 1,
});
assert_eq!(
[read(anthropic_row), read(uncached_row), read(versioned_row)],
[105, 10, 10]
);
}