use adk_core::SchemaAdapter;
use serde_json::Value;
pub fn normalize_for_provider(adapter: &dyn SchemaAdapter, schema: Value) -> Value {
adapter.normalize_schema(schema)
}
pub fn representative_mcp_schema() -> Value {
serde_json::json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query"
},
"filters": {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["web", "news", "images"]
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"additionalProperties": false
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["query"],
"additionalProperties": false
})
}
#[cfg(test)]
mod tests {
use super::*;
use adk_core::GenericSchemaAdapter;
use serde_json::json;
#[test]
fn test_generic_adapter_strips_schema_keyword() {
let adapter = GenericSchemaAdapter;
let schema = representative_mcp_schema();
let normalized = normalize_for_provider(&adapter, schema);
assert!(
normalized.get("$schema").is_none(),
"GenericSchemaAdapter should strip $schema keyword"
);
assert_eq!(normalized["type"], "object");
assert!(normalized.get("properties").is_some());
assert_eq!(normalized["properties"]["query"]["type"], "string");
}
#[test]
fn test_normalization_preserves_functional_structure() {
let adapter = GenericSchemaAdapter;
let schema = representative_mcp_schema();
let normalized = normalize_for_provider(&adapter, schema);
let props = normalized.get("properties").unwrap();
assert!(props.get("query").is_some());
assert!(props.get("filters").is_some());
assert!(props.get("tags").is_some());
let required = normalized.get("required").unwrap().as_array().unwrap();
assert_eq!(required.len(), 1);
assert_eq!(required[0], "query");
assert_eq!(props["filters"]["type"], "object");
assert_eq!(props["tags"]["type"], "array");
assert_eq!(props["tags"]["items"]["type"], "string");
}
#[test]
fn test_same_schema_callable_by_all_providers() {
let generic_adapter = GenericSchemaAdapter;
let schema = representative_mcp_schema();
let normalized = normalize_for_provider(&generic_adapter, schema);
assert!(normalized.is_object());
assert!(normalized.get("$schema").is_none());
assert_eq!(normalized["type"], "object");
assert!(normalized["properties"]["query"].is_object());
}
#[test]
fn test_minimal_schema_normalization() {
let adapter = GenericSchemaAdapter;
let schema = json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"input": {
"type": "string"
}
}
});
let normalized = normalize_for_provider(&adapter, schema);
assert!(normalized.get("$schema").is_none());
assert_eq!(normalized["type"], "object");
assert_eq!(normalized["properties"]["input"]["type"], "string");
}
#[test]
fn test_empty_schema_normalization() {
let adapter = GenericSchemaAdapter;
let schema = json!({});
let normalized = normalize_for_provider(&adapter, schema);
assert!(normalized.is_object());
}
#[test]
fn test_schema_without_dollar_schema_passes_through() {
let adapter = GenericSchemaAdapter;
let schema = json!({
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
});
let normalized = normalize_for_provider(&adapter, schema.clone());
assert_eq!(normalized["type"], schema["type"]);
assert_eq!(normalized["properties"]["name"]["type"], schema["properties"]["name"]["type"]);
assert_eq!(normalized["required"], schema["required"]);
}
#[test]
fn test_deeply_nested_schema_normalization() {
let adapter = GenericSchemaAdapter;
let schema = json!({
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"config": {
"type": "object",
"properties": {
"database": {
"type": "object",
"properties": {
"host": { "type": "string" },
"port": { "type": "integer" }
},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"additionalProperties": false
});
let normalized = normalize_for_provider(&adapter, schema);
assert!(normalized.get("$schema").is_none());
assert_eq!(normalized["type"], "object");
assert_eq!(
normalized["properties"]["config"]["properties"]["database"]["properties"]["host"]["type"],
"string"
);
}
#[test]
fn test_representative_schema_is_well_formed() {
let schema = representative_mcp_schema();
assert!(schema.is_object());
assert_eq!(schema["type"], "object");
assert!(schema.get("$schema").is_some()); assert!(schema.get("properties").is_some());
assert!(schema.get("required").is_some());
}
}