test(runner): isolate API validation regression module

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-19 14:20:43 -05:00
1 parent 045714189c
commit c8ee531371
2 files changed
+89 -85

No files matched your search

@@ -4998,91 +4998,6 @@ mod tests {
invalid_tool_call_result("schema-call".to_owned(), operation_id.to_owned(), &error)
}
#[test]
fn api_window_rejection_explains_limits_and_allows_corrected_call() {
let contracts: Value = serde_json::from_str(include_str!(
"../../../../generated/capability/semantic-tool-contracts.json"
))
.unwrap();
let contract = contracts
.as_array()
.unwrap()
.iter()
.find(|contract| contract["name"] == "call_api")
.unwrap();
let operation = crate::provider_bridge::AuthorizedTool {
operation_id: "call_api".to_owned(),
version: 1,
description: contract["description"].as_str().unwrap().to_owned(),
input_schema: contract["inputSchema"].clone(),
response_schema: contract["outputSchema"].clone(),
};
let mut bridge = ProviderToolBridge::default();
bridge
.prepare(AuthorizedToolSet {
schema: TOOL_SET_SCHEMA.to_owned(),
schema_version: 1,
catalog_digest: authorized_tool_catalog_digest(std::slice::from_ref(&operation))
.unwrap(),
operations: vec![operation],
})
.unwrap();
let mut input = json!({
"operationId": "GET /api/assets/{assetId}/content",
"pathParams": {"assetId": "PRIVATE_ASSET"},
"responseText": {"limitBytes": 60000}
});
let error = bridge
.begin_call(
"api-window".to_owned(),
"call_api".to_owned(),
input.clone(),
)
.unwrap_err();
let result =
invalid_tool_call_result("api-window".to_owned(), "call_api".to_owned(), &error);
let message = result.result["error"]["message"].as_str().unwrap();
assert!(message.contains("responseText.limitBytes"));
assert!(message.contains("4") && message.contains("24576"));
assert!(message.contains("/properties/responseText/properties/limitBytes/maximum"));
assert!(!message.contains("PRIVATE_ASSET"));
assert!(message.len() <= 512);
assert!(!message.chars().any(char::is_control));
assert_eq!(result.result["error"]["code"], "invalid_tool_call");
input["responseText"]["limitBytes"] = json!(16000);
let mut unknown_field = input.clone();
unknown_field["responseText"]["PRIVATE_FIELD"] = json!("PRIVATE_VALUE");
let unknown_error = bridge
.begin_call(
"unknown-api-window".to_owned(),
"call_api".to_owned(),
unknown_field,
)
.unwrap_err();
let unknown_result = invalid_tool_call_result(
"unknown-api-window".to_owned(),
"call_api".to_owned(),
&unknown_error,
);
let unknown_message = unknown_result.result["error"]["message"].as_str().unwrap();
assert!(unknown_message.contains("/additionalProperties"));
for private in ["PRIVATE_FIELD", "PRIVATE_VALUE", "PRIVATE_ASSET"] {
assert!(!unknown_result.result.to_string().contains(private));
}
assert!(unknown_message.len() <= 512);
let denied = ProviderToolBridge::default()
.begin_call("denied-api".to_owned(), "call_api".to_owned(), json!({}))
.unwrap_err();
assert_eq!(
invalid_tool_call_result("denied-api".to_owned(), "call_api".to_owned(), &denied)
.result["error"]["message"],
GENERIC_INVALID_TOOL_CALL_MESSAGE
);
assert!(bridge
.begin_call("api-window".to_owned(), "call_api".to_owned(), input)
.is_ok());
}
#[test]
fn invalid_tool_results_expose_only_reserved_schema_guidance() {
let finish_result = schema_rejection(
@@ -6624,3 +6539,7 @@ mod tests {
fs::remove_dir_all(directory).unwrap();
}
}
#[cfg(test)]
#[path = "tests/provider_api_validation.rs"]
mod api_validation_tests;
@@ -0,0 +1,85 @@
use super::*;
#[test]
fn api_window_rejection_explains_limits_and_allows_corrected_call() {
let contracts: Value = serde_json::from_str(include_str!(
"../../../../../generated/capability/semantic-tool-contracts.json"
))
.unwrap();
let contract = contracts
.as_array()
.unwrap()
.iter()
.find(|contract| contract["name"] == "call_api")
.unwrap();
let operation = crate::provider_bridge::AuthorizedTool {
operation_id: "call_api".to_owned(),
version: 1,
description: contract["description"].as_str().unwrap().to_owned(),
input_schema: contract["inputSchema"].clone(),
response_schema: contract["outputSchema"].clone(),
};
let mut bridge = ProviderToolBridge::default();
bridge
.prepare(AuthorizedToolSet {
schema: TOOL_SET_SCHEMA.to_owned(),
schema_version: 1,
catalog_digest: authorized_tool_catalog_digest(std::slice::from_ref(&operation))
.unwrap(),
operations: vec![operation],
})
.unwrap();
let mut input = json!({
"operationId": "GET /api/assets/{assetId}/content",
"pathParams": {"assetId": "PRIVATE_ASSET"},
"responseText": {"limitBytes": 60000}
});
let error = bridge
.begin_call(
"api-window".to_owned(),
"call_api".to_owned(),
input.clone(),
)
.unwrap_err();
let result = invalid_tool_call_result("api-window".to_owned(), "call_api".to_owned(), &error);
let message = result.result["error"]["message"].as_str().unwrap();
assert!(message.contains("responseText.limitBytes"));
assert!(message.contains("4") && message.contains("24576"));
assert!(message.contains("/properties/responseText/properties/limitBytes/maximum"));
assert!(!message.contains("PRIVATE_ASSET"));
assert!(message.len() <= 512);
assert!(!message.chars().any(char::is_control));
assert_eq!(result.result["error"]["code"], "invalid_tool_call");
input["responseText"]["limitBytes"] = json!(16000);
let mut unknown_field = input.clone();
unknown_field["responseText"]["PRIVATE_FIELD"] = json!("PRIVATE_VALUE");
let unknown_error = bridge
.begin_call(
"unknown-api-window".to_owned(),
"call_api".to_owned(),
unknown_field,
)
.unwrap_err();
let unknown_result = invalid_tool_call_result(
"unknown-api-window".to_owned(),
"call_api".to_owned(),
&unknown_error,
);
let unknown_message = unknown_result.result["error"]["message"].as_str().unwrap();
assert!(unknown_message.contains("/additionalProperties"));
for private in ["PRIVATE_FIELD", "PRIVATE_VALUE", "PRIVATE_ASSET"] {
assert!(!unknown_result.result.to_string().contains(private));
}
assert!(unknown_message.len() <= 512);
let denied = ProviderToolBridge::default()
.begin_call("denied-api".to_owned(), "call_api".to_owned(), json!({}))
.unwrap_err();
assert_eq!(
invalid_tool_call_result("denied-api".to_owned(), "call_api".to_owned(), &denied).result
["error"]["message"],
GENERIC_INVALID_TOOL_CALL_MESSAGE
);
assert!(bridge
.begin_call("api-window".to_owned(), "call_api".to_owned(), input)
.is_ok());
}