use super::super::*;
#[test]
fn test_unicode_path_params_emoji() {
assert_eq!(url_decode("%F0%9F%98%80").unwrap(), "😀");
}
#[test]
fn test_unicode_path_params_cjk() {
let encoded_chinese = "%E4%B8%AD%E6%96%87"; let encoded_japanese = "%E6%97%A5%E6%9C%AC%E8%AA%9E"; let encoded_korean = "%ED%95%9C%EA%B5%AD%EC%96%B4";
assert_eq!(url_decode(encoded_chinese).unwrap(), "中文");
assert_eq!(url_decode(encoded_japanese).unwrap(), "日本語");
assert_eq!(url_decode(encoded_korean).unwrap(), "한국어");
}
#[test]
fn test_unicode_path_params_arabic_hebrew() {
let encoded_arabic = "%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9"; let encoded_hebrew = "%D7%A2%D7%91%D7%A8%D7%99%D7%AA";
assert_eq!(url_decode(encoded_arabic).unwrap(), "العربية");
assert_eq!(url_decode(encoded_hebrew).unwrap(), "עברית");
}
#[test]
fn test_unicode_mixed_encodings() {
assert_eq!(
url_decode("john_%F0%9F%91%A8%E2%80%8D%F0%9F%92%BB").unwrap(),
"john_👨💻"
);
}
#[test]
fn test_unicode_zero_width_chars() {
let encoded = "%E2%80%8B%E2%80%8C%E2%80%8D"; let decoded = url_decode(encoded).unwrap();
assert_eq!(decoded.len(), 9); }
#[test]
fn test_unicode_normalization_forms() {
let precomposed = "%C3%A9"; let decomposed = "e%CC%81";
let decoded_precomposed = url_decode(precomposed).unwrap();
let decoded_decomposed = url_decode(decomposed).unwrap();
assert_eq!(decoded_precomposed, "é"); assert_eq!(decoded_decomposed, "e\u{0301}"); assert_eq!(decoded_decomposed.chars().count(), 2);
assert_ne!(decoded_precomposed, decoded_decomposed);
}
#[test]
fn test_unicode_boundary_chars() {
assert_eq!(url_decode("%7F").unwrap(), "\u{007F}");
assert_eq!(url_decode("%C2%80").unwrap(), "\u{0080}");
assert_eq!(url_decode("%E0%A0%80").unwrap(), "\u{0800}");
assert_eq!(url_decode("%F0%90%80%80").unwrap(), "\u{10000}");
}
#[test]
fn test_path_traversal_encoded() {
let test_cases = [
("%2e%2e%2f", "../"), ("%2e%2e/", "../"), ("..%2f", "../"), ("%2e%2e%5c", "..\\"), ("%252e%252e%252f", "%2e%2e%2f"), ];
for (encoded, expected_decoded) in test_cases {
let decoded = url_decode(encoded).unwrap();
assert_eq!(decoded, expected_decoded, "Failed for {encoded}");
}
}
#[test]
fn test_path_traversal_null_byte() {
assert_eq!(url_decode("file%00.txt").unwrap(), "file\0.txt");
}
#[test]
fn test_path_traversal_unicode() {
let test_cases = [
("%c0%af", "\u{FFFD}\u{FFFD}"), ("%ef%bc%8f", "/"), ("%e2%81%84", "⁄"), ];
for (encoded, _expected) in test_cases {
let _decoded = url_decode(encoded).unwrap();
}
}
#[test]
fn test_url_decode_security_edge_cases() {
let _overlong = url_decode("%c0%ae").unwrap();
assert_eq!(url_decode("%25").unwrap(), "%");
assert_eq!(url_decode("%2525").unwrap(), "%25");
assert_eq!(url_decode("a%20b%ZZc").unwrap(), "a b%ZZc");
assert_eq!(url_decode("%2").unwrap(), "%2");
assert_eq!(url_decode("%").unwrap(), "%");
assert_eq!(url_decode("%%").unwrap(), "%%");
}
#[test]
fn test_malformed_empty_request() {
let req = Request::new(
Method::Get,
String::new(),
vec![],
None,
std::collections::HashMap::new(),
);
assert_eq!(req.path(), "");
assert_eq!(req.path_without_query(), "");
assert_eq!(req.query("any"), None);
}