use super::{json, parse_bare_calls_in_body, sample_tool_registry};
#[test]
fn surrogate_pair_escape_decodes_and_keeps_call() {
let tools = sample_tool_registry();
let src = "run({ command: \"hi \\uD83D\\uDE00 there\" })";
let result = parse_bare_calls_in_body(src, Some(&tools));
assert!(
result.errors.is_empty(),
"surrogate pair should not error: {:?}",
result.errors
);
assert_eq!(result.calls.len(), 1, "call must not be dropped");
assert_eq!(
result.calls[0]["arguments"]["command"],
json!("hi \u{1F600} there")
);
}
#[test]
fn brace_form_nonbmp_escape_decodes() {
let tools = sample_tool_registry();
let src = r#"run({ command: "hi \u{1F600} there" })"#;
let result = parse_bare_calls_in_body(src, Some(&tools));
assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
assert_eq!(
result.calls[0]["arguments"]["command"],
json!("hi \u{1F600} there")
);
}
#[test]
fn lone_high_surrogate_still_rejected() {
let tools = sample_tool_registry();
let src = "run({ command: \"x \\uD83D y\" })";
let result = parse_bare_calls_in_body(src, Some(&tools));
assert!(
!result.errors.is_empty() || result.calls.is_empty(),
"a lone surrogate must not silently produce a value: {:?}",
result.calls
);
}
#[test]
fn unknown_escape_in_quoted_string_keeps_backslash() {
let tools = sample_tool_registry();
let result = parse_bare_calls_in_body(
r#"edit({ action: "create", path: "re.py", content: "p = '\d+\w*'" })"#,
Some(&tools),
);
assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
assert_eq!(
result.calls[0]["arguments"]["content"],
json!("p = '\\d+\\w*'")
);
}
#[test]
fn regex_content_identical_across_channels() {
let tools = sample_tool_registry();
let expected = json!("p = '\\d+\\w*'");
let quoted = parse_bare_calls_in_body(
r#"edit({ action: "create", path: "re.py", content: "p = '\d+\w*'" })"#,
Some(&tools),
);
let template = parse_bare_calls_in_body(
"edit({ action: \"create\", path: \"re.py\", content: `p = '\\d+\\w*'` })",
Some(&tools),
);
let heredoc = parse_bare_calls_in_body(
"edit({ action: \"create\", path: \"re.py\", content: <<EOF\np = '\\d+\\w*'\nEOF\n })",
Some(&tools),
);
assert_eq!(quoted.calls[0]["arguments"]["content"], expected, "quoted");
assert_eq!(
template.calls[0]["arguments"]["content"], expected,
"template"
);
assert_eq!(
heredoc.calls[0]["arguments"]["content"], expected,
"heredoc"
);
}
#[test]
fn known_escapes_in_quoted_string_unchanged() {
let tools = sample_tool_registry();
let result = parse_bare_calls_in_body(r#"run({ command: "a\nb\tc\\d\"e" })"#, Some(&tools));
assert!(result.errors.is_empty(), "errors: {:?}", result.errors);
assert_eq!(
result.calls[0]["arguments"]["command"],
json!("a\nb\tc\\d\"e")
);
}
fn run_command(src: &str) -> Result<String, String> {
let tools = sample_tool_registry();
let result = parse_bare_calls_in_body(src, Some(&tools));
if !result.errors.is_empty() {
return Err(format!("{:?}", result.errors));
}
let call = result.calls.first().ok_or("call was dropped")?;
call["arguments"]["command"]
.as_str()
.map(str::to_string)
.ok_or_else(|| "command not a string".to_string())
}
#[test]
fn malformed_known_escapes_keep_literal_not_dropped() {
let cases = [
(r#""m/\x{1F600}/""#, r"m/\x{1F600}/"), (r#""C:\xtra\data""#, r"C:\xtra\data"), (r#""ends with \x""#, r"ends with \x"), (r#""bad \uAB stop""#, r"bad \uAB stop"), (r#""bad \uABCG end""#, r"bad \uABCG end"), (r#""path C:\users\me""#, r"path C:\users\me"), ];
for (src_value, expected) in cases {
let src = format!("run({{ command: {src_value} }})");
let got =
run_command(&src).unwrap_or_else(|err| panic!("call dropped for {src_value}: {err}"));
assert_eq!(got, expected, "for source {src_value}");
}
}
#[test]
fn malformed_escape_identical_across_channels() {
let tools = sample_tool_registry();
let expected = json!(r"m/\x{1F600}/");
let quoted = parse_bare_calls_in_body(r#"run({ command: "m/\x{1F600}/" })"#, Some(&tools));
let template = parse_bare_calls_in_body("run({ command: `m/\\x{1F600}/` })", Some(&tools));
let heredoc = parse_bare_calls_in_body(
"run({ command: <<EOF\nm/\\x{1F600}/\nEOF\n })",
Some(&tools),
);
assert_eq!(quoted.calls[0]["arguments"]["command"], expected, "quoted");
assert_eq!(
template.calls[0]["arguments"]["command"], expected,
"template"
);
assert_eq!(
heredoc.calls[0]["arguments"]["command"], expected,
"heredoc"
);
}
#[test]
fn well_formed_hex_and_unicode_escapes_still_decode() {
assert_eq!(
run_command(r#"run({ command: "\x41\x42" })"#).unwrap(),
"AB"
);
assert_eq!(
run_command(r#"run({ command: "snow ☃ done" })"#).unwrap(),
"snow \u{2603} done"
);
assert_eq!(
run_command(r#"run({ command: "emoji \u{1F600} done" })"#).unwrap(),
"emoji \u{1F600} done"
);
}