#![cfg(test)]
use serde_json::Value;
pub fn legacy_props(tool_name: &str) -> serde_json::Map<String, Value> {
let defs = crate::mcp::registry::tool_definitions();
let tools = defs
.get("tools")
.and_then(Value::as_array)
.expect("tool_definitions emits `tools` array");
let entry = tools
.iter()
.find(|t| t.get("name").and_then(Value::as_str) == Some(tool_name))
.unwrap_or_else(|| panic!("{tool_name} must be in legacy catalog"));
entry
.pointer("/inputSchema/properties")
.and_then(Value::as_object)
.unwrap_or_else(|| panic!("{tool_name}.inputSchema.properties must be object"))
.clone()
}
pub fn derived_props_for<T: schemars::JsonSchema>() -> serde_json::Map<String, Value> {
let schema = schemars::schema_for!(T);
let v = serde_json::to_value(schema).expect("schema → value");
if let Some(props) = v.get("properties").and_then(Value::as_object) {
return props.clone();
}
let short = std::any::type_name::<T>().rsplit("::").next().unwrap_or("");
v.pointer(&format!("/definitions/{short}/properties"))
.and_then(Value::as_object)
.cloned()
.expect("schemars schema must have properties at a known path")
}
pub fn assert_property_set_parity(tool_name: &str, derived: &serde_json::Map<String, Value>) {
let legacy = legacy_props(tool_name);
let legacy_keys: std::collections::BTreeSet<&str> = legacy.keys().map(String::as_str).collect();
let derived_keys: std::collections::BTreeSet<&str> =
derived.keys().map(String::as_str).collect();
assert_eq!(
legacy_keys,
derived_keys,
"{tool_name}: property set drift; diff = {:?}",
legacy_keys
.symmetric_difference(&derived_keys)
.collect::<Vec<_>>()
);
}
pub fn assert_descriptions_match(tool_name: &str, derived: &serde_json::Map<String, Value>) {
let legacy = legacy_props(tool_name);
for (name, legacy_prop) in &legacy {
if let Some(want) = legacy_prop.get("description").and_then(Value::as_str) {
let got = derived
.get(name)
.and_then(|p| p.get("description"))
.and_then(Value::as_str);
assert_eq!(
got,
Some(want),
"{tool_name}.{name}: description must match legacy byte-for-byte"
);
}
}
}
#[cfg(test)]
mod self_tests {
use super::{
assert_descriptions_match, assert_property_set_parity, derived_props_for, legacy_props,
};
#[test]
fn helpers_round_trip_on_memory_get() {
let legacy = legacy_props("memory_get");
assert!(
!legacy.is_empty(),
"memory_get must carry legacy properties"
);
let derived = derived_props_for::<crate::mcp::get::GetRequest>();
assert_property_set_parity("memory_get", &derived);
assert_descriptions_match("memory_get", &derived);
}
}