use std::sync::OnceLock;
use serde_json::{Map, Value};
use super::*;
use crate::test_support::{assert_same_json_text, vectors};
use crate::wire;
const FUNCTION_CASES: [&str; 3] = [
"mint_back_session_line",
"get_more_tools_descriptor",
"get_more_tools_result",
];
const CONSTANTS: [(&str, &str); 26] = [
(
"DEFAULT_CONTEXT_PARAMETER_DESCRIPTION",
DEFAULT_CONTEXT_PARAMETER_DESCRIPTION,
),
("AGENTCAT_CUSTOM_EVENT_TYPE", AGENTCAT_CUSTOM_EVENT_TYPE),
("SESSION_ID_PARAM_DESCRIPTION", SESSION_ID_PARAM_DESCRIPTION),
("SESSION_ID_PARAM_PATTERN", SESSION_ID_PARAM_PATTERN),
("SESSION_START_SENTINEL", SESSION_START_SENTINEL),
("AGENT_ID_PARAM_DESCRIPTION", AGENT_ID_PARAM_DESCRIPTION),
("MINT_BACK_HEADER_ISSUED", MINT_BACK_HEADER_ISSUED),
("MINT_BACK_ISSUED_BODY", MINT_BACK_ISSUED_BODY),
(
"MINT_BACK_HEADER_UNRECOGNIZED",
MINT_BACK_HEADER_UNRECOGNIZED,
),
("MINT_BACK_UNRECOGNIZED_BODY", MINT_BACK_UNRECOGNIZED_BODY),
("MCP_SESSION_KEY", MCP_SESSION_KEY),
(
"MCP_SESSION_FIELD_DESCRIPTION",
MCP_SESSION_FIELD_DESCRIPTION,
),
(
"MCP_SESSION_FIELD_DESCRIPTION_HOOK_MODE",
MCP_SESSION_FIELD_DESCRIPTION_HOOK_MODE,
),
(
"MCP_SESSION_SESSION_ID_DESCRIPTION",
MCP_SESSION_SESSION_ID_DESCRIPTION,
),
(
"MCP_SESSION_AGENT_ID_DESCRIPTION",
MCP_SESSION_AGENT_ID_DESCRIPTION,
),
(
"MCP_SESSION_STATUS_DESCRIPTION",
MCP_SESSION_STATUS_DESCRIPTION,
),
("META_CLIENT_INFO_KEY", META_CLIENT_INFO_KEY),
("META_PROTOCOL_VERSION_KEY", META_PROTOCOL_VERSION_KEY),
("AGENTCAT_TAG_AGENT_ID", AGENTCAT_TAG_AGENT_ID),
("AGENTCAT_TAG_SESSION_SOURCE", AGENTCAT_TAG_SESSION_SOURCE),
("AGENTCAT_TAG_AGENT_SOURCE", AGENTCAT_TAG_AGENT_SOURCE),
(
"AGENTCAT_TAG_PROTOCOL_VERSION",
AGENTCAT_TAG_PROTOCOL_VERSION,
),
("AGENTCAT_TAG_MRTR", AGENTCAT_TAG_MRTR),
("GET_MORE_TOOLS_NAME", GET_MORE_TOOLS_NAME),
("SESSION_ID_PARAM", SESSION_ID_PARAM),
("AGENT_ID_PARAM", AGENT_ID_PARAM),
];
fn cases() -> &'static [Map<String, Value>] {
static CASES: OnceLock<Vec<Map<String, Value>>> = OnceLock::new();
CASES.get_or_init(|| vectors::cases("constants"))
}
fn case(name: &str) -> Map<String, Value> {
cases()
.iter()
.find(|c| vectors::name(c) == name)
.cloned()
.unwrap_or_else(|| panic!("no vector case {name:?}"))
}
fn expected(name: &str) -> Value {
case(name)
.remove("value")
.unwrap_or_else(|| panic!("case {name:?} has no value"))
}
#[test]
fn every_constant_equals_its_fixture_value() {
for (name, actual) in CONSTANTS {
assert_same_json_text(&Value::from(actual), &expected(name), name);
}
}
#[test]
fn every_fixture_constant_is_a_crate_constant() {
let plain: Vec<String> = cases()
.iter()
.map(|c| vectors::name(c).to_owned())
.filter(|n| !FUNCTION_CASES.contains(&n.as_str()))
.collect();
for name in &plain {
assert!(
CONSTANTS.iter().any(|(c, _)| c == name),
"{name}: the fixture holds a constant that the crate lacks"
);
}
for (name, _) in CONSTANTS {
assert!(
plain.iter().any(|p| p == name),
"{name}: no fixture constant of that name"
);
}
}
#[test]
fn mint_back_session_line_is_pinned() {
let case = case("mint_back_session_line");
let input = case["input"].as_str().unwrap_or_else(|| {
panic!(
"mint_back_session_line: input is not a string: {:?}",
case["input"]
)
});
assert_same_json_text(
&Value::from(mint_back_session_line(input)),
&case["value"],
"mint_back_session_line",
);
}
#[test]
fn get_more_tools_descriptor_is_pinned() {
assert_same_json_text(
&get_more_tools_descriptor(),
&expected("get_more_tools_descriptor"),
"get_more_tools_descriptor",
);
}
#[test]
fn get_more_tools_result_is_pinned() {
assert_same_json_text(
&get_more_tools_result(),
&expected("get_more_tools_result"),
"get_more_tools_result",
);
}
#[test]
fn get_more_tools_result_text_is_pinned() {
let value = expected("get_more_tools_result");
assert_same_json_text(
&Value::from(GET_MORE_TOOLS_RESULT_TEXT),
&value["content"][0]["text"],
"get_more_tools_result text",
);
}
#[test]
fn report_missing_log_line_is_pinned() {
let case = case("get_more_tools_result");
let context = case["input"]["context"].as_str().unwrap_or_else(|| {
panic!(
"get_more_tools_result: input.context is not a string: {:?}",
case["input"]
)
});
let logs = case["logs"].as_array().unwrap_or_else(|| {
panic!(
"get_more_tools_result: logs is not an array: {:?}",
case.get("logs")
)
});
assert_eq!(
logs.len(),
1,
"get_more_tools_result logs one line: {logs:?}"
);
assert_same_json_text(
&Value::from(report_missing_log_line(wire::utf16_len(context))),
&logs[0],
"get_more_tools_result log",
);
}