#![cfg(feature = "serde")]
use serde_json::json;
use tokitai::tool;
use tokitai_core::ToolErrorKind;
#[derive(Default)]
struct ErrorTestTools;
#[tool]
impl ErrorTestTools {
pub fn add(&self, a: i32, b: i32) -> i32 {
a + b
}
pub fn process_text(&self, text: String) -> String {
text.to_uppercase()
}
pub fn with_option(&self, required: String, optional: Option<i32>) -> String {
format!("{}: {:?}", required, optional)
}
pub fn get_data(&self) -> Vec<String> {
vec!["a".to_string(), "b".to_string()]
}
}
#[test]
fn test_missing_required_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"b": 10}));
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind, ToolErrorKind::ValidationError);
}
#[test]
fn test_missing_all_params() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({}));
assert!(result.is_err());
}
#[test]
fn test_wrong_type_string_for_integer() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": "not_a_number", "b": 10}));
assert!(result.is_err());
}
#[test]
fn test_wrong_type_integer_for_string() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": 12345}));
assert!(result.is_err());
}
#[test]
fn test_wrong_type_array_for_string() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": ["not", "a", "string"]}));
assert!(result.is_err());
}
#[test]
fn test_wrong_type_object_for_integer() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": {"value": 10}, "b": 20}));
assert!(result.is_err());
}
#[test]
fn test_null_for_required_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": null, "b": 10}));
assert!(result.is_err());
}
#[test]
fn test_null_for_optional_param() {
let tools = ErrorTestTools;
let result = tools.call_tool(
"with_option",
&json!({"required": "test", "optional": null}),
);
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!("test: None"));
}
#[test]
fn test_null_for_string_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": null}));
assert!(result.is_err());
}
#[test]
fn test_extremely_large_number() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": i64::MAX, "b": 10}));
assert!(result.is_err());
}
#[test]
fn test_extremely_long_string() {
let tools = ErrorTestTools;
let long_string = "a".repeat(1_000_000);
let result = tools.call_tool("process_text", &json!({"text": long_string}));
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.as_str().unwrap().starts_with("AAA"));
}
#[test]
fn test_deeply_nested_json() {
let tools = ErrorTestTools;
let mut nested = json!(0);
for _ in 0..100 {
nested = json!({"nested": nested});
}
let result = tools.call_tool("add", &nested);
assert!(result.is_err());
}
#[test]
fn test_unknown_tool() {
let tools = ErrorTestTools;
let result = tools.call_tool("nonexistent_tool", &json!({}));
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind, ToolErrorKind::NotFound);
}
#[test]
fn test_empty_tool_name() {
let tools = ErrorTestTools;
let result = tools.call_tool("", &json!({}));
assert!(result.is_err());
}
#[test]
fn test_unicode_in_tool_name() {
let tools = ErrorTestTools;
let result = tools.call_tool("添加", &json!({}));
assert!(result.is_err()); }
#[test]
fn test_unicode_in_string_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": "你好,世界!🦀"}));
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.as_str().unwrap().contains("🦀"));
}
#[test]
fn test_emoji_in_tool_name() {
let tools = ErrorTestTools;
let result = tools.call_tool("add_🔥", &json!({}));
assert!(result.is_err());
}
#[test]
fn test_array_instead_of_object() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!([{"a": 1, "b": 2}]));
assert!(result.is_err());
}
#[test]
fn test_string_instead_of_object() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!("not an object"));
assert!(result.is_err());
}
#[test]
fn test_integer_instead_of_object() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!(42));
assert!(result.is_err());
}
#[test]
fn test_i32_max_value() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": i32::MAX, "b": 0}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(i32::MAX));
}
#[test]
fn test_i32_min_value() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": i32::MIN, "b": 0}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(i32::MIN));
}
#[test]
#[should_panic(expected = "attempt to add with overflow")]
fn test_integer_overflow() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": i32::MAX, "b": 1}));
let _ = result;
}
#[test]
fn test_zero_values() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": 0, "b": 0}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(0));
}
#[test]
fn test_negative_values() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": -100, "b": -50}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(-150));
}
#[test]
fn test_extra_unknown_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": 10, "b": 20, "unknown": "ignored"}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(30));
}
#[test]
fn test_all_extra_params() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"x": 1, "y": 2, "z": 3}));
assert!(result.is_err()); }
#[test]
fn test_empty_array_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("get_data", &json!({}));
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_array());
assert_eq!(response.as_array().unwrap().len(), 2);
}
#[test]
fn test_empty_string_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": ""}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(""));
}
#[test]
fn test_whitespace_string() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": " "}));
assert!(result.is_ok());
assert_eq!(result.unwrap(), json!(" "));
}
#[test]
fn test_float_for_integer_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": 10.5, "b": 20}));
assert!(result.is_err());
}
#[test]
fn test_integer_for_float_param() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": 10, "b": 20.0}));
let _ = result;
}
#[test]
fn test_boolean_for_integer() {
let tools = ErrorTestTools;
let result = tools.call_tool("add", &json!({"a": true, "b": false}));
assert!(result.is_err());
}
#[test]
fn test_boolean_for_string() {
let tools = ErrorTestTools;
let result = tools.call_tool("process_text", &json!({"text": true}));
assert!(result.is_err());
}