use oatf::{parse, validate};
#[test]
fn stress_oversized_input_rejected() {
let big = "a".repeat(10 * 1024 * 1024 + 1);
let err = parse(&big).unwrap_err();
assert!(
err.message.contains("exceeds maximum"),
"expected size-limit error, got: {}",
err.message
);
}
#[test]
fn stress_deeply_nested_state() {
let mut nested = "null".to_string();
for i in (0..64).rev() {
nested = format!("{{\"level{}\": {}}}", i, nested);
}
let yaml = format!(
r#"oatf: "0.1"
attack:
execution:
mode: mcp_server
phases:
- name: exploit
state: {}
trigger:
event: tools/call
- name: terminal
indicators:
- surface: tools/list
target: "tools[*].description"
pattern:
contains: test
"#,
nested
);
let doc = parse(&yaml).expect("should parse deeply nested doc");
let result = validate(&doc);
let _ = result;
}
#[test]
fn stress_many_indicators() {
let mut indicators = String::new();
for i in 0..500 {
indicators.push_str(&format!(
" - surface: tools/list\n target: \"tools[*].description\"\n pattern:\n contains: \"test-{}\"\n",
i
));
}
let yaml = format!(
r#"oatf: "0.1"
attack:
execution:
mode: mcp_server
phases:
- name: exploit
state:
tools:
- name: t
description: test
inputSchema:
type: object
trigger:
event: tools/call
- name: terminal
indicators:
{}
"#,
indicators
);
let doc = parse(&yaml).expect("should parse many indicators");
let result = validate(&doc);
assert!(
result.errors.is_empty(),
"unexpected errors: {:?}",
result.errors
);
}
#[test]
fn stress_many_phases() {
let mut phases = String::new();
for i in 0..100 {
if i < 99 {
phases.push_str(&format!(
" - name: phase-{}\n state:\n tools:\n - name: tool-{}\n description: t\n inputSchema:\n type: object\n trigger:\n event: tools/call\n",
i, i
));
} else {
phases.push_str(&format!(" - name: phase-{}\n", i));
}
}
let yaml = format!(
r#"oatf: "0.1"
attack:
execution:
mode: mcp_server
phases:
{} indicators:
- surface: tools/list
target: "tools[*].description"
pattern:
contains: t
"#,
phases
);
let doc = parse(&yaml).expect("should parse many phases");
let result = validate(&doc);
assert!(
result.errors.is_empty(),
"unexpected errors: {:?}",
result.errors
);
}
#[test]
fn stress_large_state_object() {
let mut tools = String::new();
for i in 0..200 {
tools.push_str(&format!(
" - name: tool-{}\n description: \"Tool number {}\"\n inputSchema:\n type: object\n",
i, i
));
}
let yaml = format!(
r#"oatf: "0.1"
attack:
execution:
mode: mcp_server
phases:
- name: exploit
state:
tools:
{} trigger:
event: tools/call
- name: terminal
indicators:
- surface: tools/list
target: "tools[*].description"
pattern:
contains: Tool
"#,
tools
);
let doc = parse(&yaml).expect("should parse large state");
let result = validate(&doc);
assert!(
result.errors.is_empty(),
"unexpected errors: {:?}",
result.errors
);
}
#[test]
fn stress_regex_size_limit() {
let huge_pattern = format!("[a-z]{{1,10000}}{}", r"(\d+[a-z]+){1,1000}".repeat(50));
let yaml = format!(
"oatf: '0.1'\n\
attack:\n\
\x20 execution:\n\
\x20 mode: mcp_server\n\
\x20 phases:\n\
\x20 - name: exploit\n\
\x20 state:\n\
\x20 tools:\n\
\x20 - name: t\n\
\x20 description: test\n\
\x20 inputSchema:\n\
\x20 type: object\n\
\x20 trigger:\n\
\x20 event: tools/call\n\
\x20 - name: terminal\n\
\x20 indicators:\n\
\x20 - surface: tools/list\n\
\x20 target: 'tools[*].description'\n\
\x20 pattern:\n\
\x20 regex: '{}'\n",
huge_pattern
);
let doc = parse(&yaml).expect("should parse doc with huge regex");
let result = validate(&doc);
assert!(
result.errors.iter().any(|e| e.rule == "V-013"),
"expected V-013 error for oversized regex, got: {:?}",
result.errors
);
}