use ass_core::parser::{IssueCategory, IssueSeverity, Script};
#[cfg(test)]
mod parser_main_coverage_tests {
use super::*;
#[test]
fn test_input_size_limit_exceeded() {
let large_content = "A".repeat(51 * 1024 * 1024); let script = Script::parse(&large_content);
assert!(script.is_ok());
let script = script.unwrap();
let issues = script.issues();
assert!(issues.iter().any(|issue| {
issue.severity == IssueSeverity::Error
&& issue.category == IssueCategory::Security
&& issue.message.contains("Input size limit exceeded")
}));
}
#[test]
fn test_bom_validation_warning() {
let mut content_with_invalid_bom = vec![0xFF, 0xFE]; content_with_invalid_bom.extend_from_slice(b"[Script Info]\nTitle: Test\n");
let content_str = String::from_utf8_lossy(&content_with_invalid_bom);
let script = Script::parse(&content_str);
assert!(script.is_ok());
let script = script.unwrap();
let issues = script.issues();
println!("Issues found: {issues:?}");
}
#[test]
fn test_bom_handling_with_utf8_bom() {
let content_with_utf8_bom = "\u{FEFF}[Script Info]\nTitle: Test\n";
let script = Script::parse(content_with_utf8_bom);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
}
#[test]
fn test_parser_with_empty_input() {
let script = Script::parse("");
assert!(script.is_ok());
let script = script.unwrap();
assert!(script.sections().is_empty());
}
#[test]
fn test_parser_with_whitespace_only() {
let script = Script::parse(" \n\t\r\n ");
assert!(script.is_ok());
let script = script.unwrap();
assert!(script.sections().is_empty() || script.sections().len() <= 1);
}
#[test]
fn test_parser_with_malformed_sections() {
let malformed_inputs = vec![
"[Invalid Section\n", "[]Section]\n", "[Script Info\nNo closing bracket",
"[Events]\nFormat: Invalid\nDialogue: malformed",
"[V4+ Styles]\nFormat: Invalid\nStyle: malformed",
];
for input in malformed_inputs {
let script = Script::parse(input);
assert!(
script.is_ok(),
"Parser should not fail on malformed input: {input}"
);
let script = script.unwrap();
println!(
"Malformed input '{}' produced {} issues",
input.chars().take(20).collect::<String>(),
script.issues().len()
);
}
}
#[test]
fn test_parser_with_extremely_long_lines() {
let long_line = "A".repeat(100_000);
let content = format!("[Script Info]\nTitle: {long_line}\n");
let script = Script::parse(&content);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
}
#[test]
fn test_parser_with_unicode_edge_cases() {
let unicode_content = "[Script Info]\n\
Title: Test with 🎵 emojis and ñáéíóú accents\n\
ScriptType: v4.00+\n\
\n\
[V4+ Styles]\n\
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n\
Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,30,30,30,1\n\
\n\
[Events]\n\
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Unicode text: 日本語 العربية Русский\n";
let script = Script::parse(unicode_content);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
}
#[test]
fn test_parser_error_recovery() {
let content_with_errors = "[Script Info]\n\
Title: Test\n\
Invalid: Line\n\
\n\
[Invalid Section Name]\n\
Some content\n\
\n\
[V4+ Styles]\n\
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n\
Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,30,30,30,1\n\
Invalid: Style line\n\
\n\
[Events]\n\
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Valid event\n\
Invalid: Event line\n";
let script = Script::parse(content_with_errors);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
assert!(!script.issues().is_empty());
assert!(!script.sections().is_empty());
}
#[test]
fn test_parser_with_mixed_line_endings() {
let content = "[Script Info]\rTitle: Test\r\nScriptType: v4.00+\n\n[Events]\r\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\nDialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Mixed line endings\r";
let script = Script::parse(content);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
}
#[test]
fn test_parser_memory_efficiency() {
let mut reasonable_content = String::from("[Script Info]\n");
reasonable_content.push_str(&"Title: Test\n".repeat(1000));
reasonable_content.push_str("\n[Events]\n");
reasonable_content.push_str(
"Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n",
);
reasonable_content.push_str(
&"Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Event text\n".repeat(1000),
);
let script = Script::parse(&reasonable_content);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
}
#[test]
fn test_parser_version_detection() {
let version_tests = vec![
"[Script Info]\nScriptType: v4.00+\n",
"[Script Info]\nScriptType: v4.00\n",
"[Script Info]\nScriptType: ASS\n",
"[Script Info]\n!: This is v4.00+ style\n",
"[Script Info]\nTitle: Test\n", ];
for content in version_tests {
let script = Script::parse(content);
assert!(script.is_ok(), "Failed to parse version test: {content}");
let script = script.unwrap();
println!(
"Version detected for '{}': {:?}",
content.lines().nth(1).unwrap_or(""),
script.version()
);
}
}
#[test]
fn test_parser_with_binary_data() {
let mut binary_content = b"[Script Info]\nTitle: Test\n".to_vec();
binary_content.extend_from_slice(&[0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD]);
binary_content.extend_from_slice(b"\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n");
let content_str = String::from_utf8_lossy(&binary_content);
let script = Script::parse(&content_str);
assert!(script.is_ok());
let script = script.unwrap();
assert!(!script.sections().is_empty());
}
}