", "HTML tags")]
#[case("a & b", "a & b", "ampersand")]
#[case(""quoted"", "\"quoted\"", "quotes")]
fn test_html_unescape(#[case] input: &str, #[case] expected: &str, #[case] _description: &str) {
assert_eq!(html_unescape(input), expected);
}
#[test]
fn test_parse_simple_tool_call() {
let input = r#"
pwd && ls
"#;
let (calls, normal) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "execute_bash");
assert_eq!(normal, Some("".to_string()));
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
assert_eq!(args["command"], "pwd && ls");
}
#[test]
fn test_parse_multiple_parameters() {
let input = r#"
San Francisco
CA
fahrenheit
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "get_weather");
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
assert_eq!(args["city"], "San Francisco");
assert_eq!(args["state"], "CA");
assert_eq!(args["unit"], "fahrenheit");
}
#[test]
fn test_parse_with_normal_text() {
let input = r#"I'll help you with that.
Dallas
Let me check that for you."#;
let (calls, normal) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "get_weather");
assert_eq!(
normal,
Some("I'll help you with that. Let me check that for you.".to_string())
);
}
#[test]
fn test_parse_multiple_tool_calls() {
let input = r#"
Dallas
Orlando
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 2);
assert_eq!(calls[0].function.name, "get_weather");
assert_eq!(calls[1].function.name, "get_weather");
let args0: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
let args1: serde_json::Value = serde_json::from_str(&calls[1].function.arguments).unwrap();
assert_eq!(args0["city"], "Dallas");
assert_eq!(args1["city"], "Orlando");
}
#[test]
fn test_parse_json_parameter_value() {
let input = r#"
{"setting": "value", "count": 42}
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
assert!(args["config"].is_object());
assert_eq!(args["config"]["setting"], "value");
assert_eq!(args["config"]["count"], 42);
}
#[test]
fn test_parse_no_tool_calls() {
let input = "This is just normal text without any tool calls.";
let (calls, normal) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 0);
assert_eq!(normal, Some(input.to_string()));
}
#[test]
fn test_parse_malformed_tool_call() {
let input = r#"
value
"#;
// Should handle gracefully - might parse or return empty
let result = try_tool_call_parse_xml(input, &XmlParserConfig::default());
assert!(result.is_ok());
}
#[test]
fn test_parse_missing_parameter_closing_tag() {
let input = r#"
ls -la
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "execute_bash");
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
assert_eq!(args["command"], "ls -la");
}
#[test]
fn test_parse_missing_function_closing_tag() {
let input = r#"
Boston
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "get_weather");
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
assert_eq!(args["city"], "Boston");
}
#[test]
fn test_parse_missing_both_closing_tags() {
let input = r#"
SELECT * FROM users
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "run_query");
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
// This matches the original SGLang python implementation.
assert_eq!(args["sql"], "SELECT * FROM users\n");
}
#[test]
fn test_parse_multiple_parameters_missing_closing_tags() {
let input = r#"
rust programming
10
"#;
let (calls, _) = try_tool_call_parse_xml(input, &XmlParserConfig::default()).unwrap();
assert_eq!(calls.len(), 1);
assert_eq!(calls[0].function.name, "search");
let args: serde_json::Value = serde_json::from_str(&calls[0].function.arguments).unwrap();
// This matches the original SGLang python implementation.
assert_eq!(args["query"], "rust programming\n
\n10");
}
}