#[cfg(feature = "benches")]
mod benchmark_tests {
use ass_core::parser::{
ast::{Section, SectionType},
Script,
};
#[test]
fn test_synthetic_script_generation() {
let simple_script = r"[Script Info]
Title: Test Script
ScriptType: v4.00+
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Simple test dialogue
";
let result = Script::parse(simple_script);
assert!(result.is_ok(), "Failed to parse simple synthetic script");
let script = result.unwrap();
assert!(script.find_section(SectionType::Events).is_some());
assert!(script.find_section(SectionType::Styles).is_some());
}
#[test]
fn test_complex_synthetic_content() {
let complex_script = r"[Script Info]
Title: Complex Test Script
ScriptType: v4.00+
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
Style: Complex,Arial,24,&H0000FFFF,&H000000FF,&H00000000,&H00000000,1,1,0,0,110,110,2,15,1,2,1,2,10,10,10,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\b1}Bold text{\b0} with {\i1}italic{\i0}
Dialogue: 0,0:00:05.00,0:00:10.00,Complex,,0,0,0,,{\c&H0000FF&}Red text{\c} with {\pos(100,200)}positioning
Dialogue: 0,0:00:10.00,0:00:15.00,Default,,0,0,0,,{\k50}Ka{\k30}ra{\k40}o{\k35}ke {\k45}text
Dialogue: 0,0:00:15.00,0:00:20.00,Default,,0,0,0,,{\fad(500,500)}Fade in and out
";
let result = Script::parse(complex_script);
assert!(result.is_ok(), "Failed to parse complex synthetic script");
let script = result.unwrap();
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
assert_eq!(events.len(), 4);
} else {
panic!("Expected Events section");
}
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
let first_event = &events[0];
assert!(first_event.text.contains(r"{\b1}"));
assert!(first_event.text.contains(r"{\i1}"));
let karaoke_event = &events[2];
assert!(karaoke_event.text.contains(r"{\k"));
}
}
#[test]
fn test_stress_test_content_generation() {
use std::fmt::Write;
let mut large_content = String::from(
r"[Script Info]
Title: Stress Test Script
ScriptType: v4.00+
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
",
);
for i in 0..100 {
let start_time = format!("0:00:{:02}.00", i % 60);
let end_time = format!("0:00:{:02}.00", (i + 5) % 60);
writeln!(
large_content,
"Dialogue: 0,{start_time},{end_time},Default,,0,0,0,,Event {i} with some text content"
).unwrap();
}
let result = Script::parse(&large_content);
assert!(result.is_ok(), "Failed to parse large synthetic script");
let script = result.unwrap();
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
assert_eq!(events.len(), 100);
} else {
panic!("Expected Events section");
}
}
#[test]
fn test_unicode_content_generation() {
let unicode_script = r"[Script Info]
Title: Unicode Test Script
ScriptType: v4.00+
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Hello, 世界! 🌍
Dialogue: 0,0:00:05.00,0:00:10.00,Default,,0,0,0,,Здравствуй, мир! 🚀
Dialogue: 0,0:00:10.00,0:00:15.00,Default,,0,0,0,,مرحبا بالعالم! 🎉
Dialogue: 0,0:00:15.00,0:00:20.00,Default,,0,0,0,,こんにちは、世界! 🦀
";
let result = Script::parse(unicode_script);
assert!(result.is_ok(), "Failed to parse Unicode synthetic script");
let script = result.unwrap();
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
assert_eq!(events.len(), 4);
assert!(events[0].text.contains("世界"));
assert!(events[1].text.contains("мир"));
assert!(events[2].text.contains("بالعالم"));
assert!(events[3].text.contains("こんにちは"));
} else {
panic!("Expected Events section");
}
}
#[test]
fn test_malformed_content_generation() {
let malformed_script = r"[Script Info]
Title: Malformed Test Script
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style: Default,Arial,20,&H00FFFFFF
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Normal dialogue
Dialogue: 0,0:99:99.99,0:00:05.00,Default,,0,0,0,,Invalid start time (after end)
Dialogue: 0,0:00:00.00,0:00:05.00,NonexistentStyle,,0,0,0,,Reference to non-existent style
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\invalid_tag}Text with invalid tag
";
let result = Script::parse(malformed_script);
assert!(
result.is_ok(),
"Parser should handle malformed content gracefully"
);
let script = result.unwrap();
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
assert_eq!(events.len(), 4);
} else {
panic!("Expected Events section");
}
}
#[test]
fn test_time_format_generation() {
let time_formats = vec![
"0:00:00.00",
"0:00:59.99",
"0:59:59.99",
"1:00:00.00",
"23:59:59.99",
];
for time_str in time_formats {
let script_content = format!(
r"[Script Info]
Title: Time Format Test
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,{time_str},{time_str},Default,,0,0,0,,Test dialogue
"
);
let result = Script::parse(&script_content);
assert!(
result.is_ok(),
"Failed to parse script with time format: {time_str}"
);
}
}
#[test]
fn test_style_generation_variations() {
let complex_styles = r"[Script Info]
Title: Style Variations Test
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
Style: Bold,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,1,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
Style: Italic,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,1,0,0,100,100,0,0,1,0,0,2,0,0,0,1
Style: Large,Arial,48,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
Style: Colored,Arial,20,&H000000FF,&H00FFFFFF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
Style: Rotated,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,45,1,0,0,2,0,0,0,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,Default style
Dialogue: 0,0:00:05.00,0:00:10.00,Bold,,0,0,0,,Bold style
Dialogue: 0,0:00:10.00,0:00:15.00,Italic,,0,0,0,,Italic style
Dialogue: 0,0:00:15.00,0:00:20.00,Large,,0,0,0,,Large style
Dialogue: 0,0:00:20.00,0:00:25.00,Colored,,0,0,0,,Colored style
Dialogue: 0,0:00:25.00,0:00:30.00,Rotated,,0,0,0,,Rotated style
";
let result = Script::parse(complex_styles);
assert!(result.is_ok(), "Failed to parse complex styles script");
let script = result.unwrap();
let styles_section = script.find_section(SectionType::Styles).unwrap();
if let Section::Styles(styles) = styles_section {
assert_eq!(styles.len(), 6);
} else {
panic!("Expected Styles section");
}
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
assert_eq!(events.len(), 6);
} else {
panic!("Expected Events section");
}
}
#[test]
fn test_memory_efficiency_content() {
use std::fmt::Write;
let mut efficient_content = String::from(
r"[Script Info]
Title: Memory Efficiency Test
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0,0,2,0,0,0,1
[Events\]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
",
);
let repeated_text = "This is repeated dialogue content that appears multiple times.";
for i in 0..50 {
writeln!(
efficient_content,
"Dialogue: 0,0:00:{:02}.00,0:00:{:02}.00,Default,,0,0,0,,{repeated_text}",
i % 60,
(i + 3) % 60
)
.unwrap();
}
let result = Script::parse(&efficient_content);
assert!(
result.is_ok(),
"Failed to parse memory efficiency test script"
);
let script = result.unwrap();
let events_section = script.find_section(SectionType::Events).unwrap();
if let Section::Events(events) = events_section {
assert_eq!(events.len(), 50);
for event in events {
assert_eq!(event.text, repeated_text);
}
} else {
panic!("Expected Events section");
}
}
const fn create_benchmark_test_event(
start: &'static str,
end: &'static str,
text: &'static str,
) -> ass_core::parser::ast::Event<'static> {
use ass_core::parser::ast::{Event, EventType, Span};
Event {
event_type: EventType::Dialogue,
layer: "0",
start,
end,
style: "Default",
name: "",
margin_l: "0",
margin_r: "0",
margin_v: "0",
margin_t: None,
margin_b: None,
effect: "",
text,
span: Span::new(0, 0, 0, 0),
}
}
#[test]
fn test_create_test_event_basic() {
use ass_core::parser::ast::EventType;
let simple_event = create_benchmark_test_event("0:00:00.00", "0:00:05.00", "Simple text");
assert_eq!(simple_event.event_type, EventType::Dialogue);
assert_eq!(simple_event.start, "0:00:00.00");
assert_eq!(simple_event.end, "0:00:05.00");
assert_eq!(simple_event.text, "Simple text");
assert_eq!(simple_event.style, "Default");
assert_eq!(simple_event.layer, "0");
assert_eq!(simple_event.name, "");
assert_eq!(simple_event.margin_l, "0");
assert_eq!(simple_event.margin_r, "0");
assert_eq!(simple_event.margin_v, "0");
assert_eq!(simple_event.effect, "");
}
#[test]
fn test_create_test_event_formatting() {
let complex_event = create_benchmark_test_event(
"0:00:05.00",
"0:00:10.00",
r"Text with {\b1}formatting{\b0} and {\c&H0000FF&}colors{\c}",
);
assert_eq!(complex_event.start, "0:00:05.00");
assert_eq!(complex_event.end, "0:00:10.00");
assert!(complex_event.text.contains(r"{\b1}"));
assert!(complex_event.text.contains(r"{\c&H0000FF&}"));
}
#[test]
fn test_create_test_event_unicode() {
let unicode_event = create_benchmark_test_event(
"0:00:10.00",
"0:00:15.00",
"Hello, 世界! 🌍 Здравствуй мир! 🚀",
);
assert_eq!(unicode_event.text, "Hello, 世界! 🌍 Здравствуй мир! 🚀");
}
#[test]
fn test_create_test_event_defaults() {
use ass_core::parser::ast::EventType;
let events = vec![
create_benchmark_test_event("0:00:00.00", "0:00:05.00", "Event 1"),
create_benchmark_test_event("0:00:05.00", "0:00:10.00", "Event 2"),
create_benchmark_test_event("0:00:10.00", "0:00:15.00", "Event 3"),
];
for event in &events {
assert_eq!(event.event_type, EventType::Dialogue);
assert_eq!(event.layer, "0");
assert_eq!(event.style, "Default");
assert_eq!(event.name, "");
assert_eq!(event.margin_l, "0");
assert_eq!(event.margin_r, "0");
assert_eq!(event.margin_v, "0");
assert_eq!(event.effect, "");
}
assert_eq!(events[0].text, "Event 1");
assert_eq!(events[1].text, "Event 2");
assert_eq!(events[2].text, "Event 3");
}
#[test]
fn test_benchmark_event_creation_edge_cases() {
let karaoke_event = create_benchmark_test_event(
"0:00:00.00",
"0:00:10.00",
r"{\k50}Ka{\k30}ra{\k40}o{\k35}ke {\k45}text",
);
assert!(karaoke_event.text.contains(r"{\k"));
let animation_event = create_benchmark_test_event(
"0:00:00.00",
"0:00:05.00",
r"{\move(0,0,100,100)\t(0,1000,\fscx120)}Animated text",
);
assert!(animation_event.text.contains(r"{\move"));
assert!(animation_event.text.contains(r"\t("));
let empty_event = create_benchmark_test_event("0:00:00.00", "0:00:01.00", "");
assert_eq!(empty_event.text, "");
let special_event =
create_benchmark_test_event("0:00:00.00", "0:00:05.00", "Special: \n\r\t{}[]():,;");
assert!(special_event.text.contains("{}"));
assert!(special_event.text.contains("[]"));
}
}
#[cfg(not(feature = "benches"))]
mod fallback_tests {
#[test]
fn test_benchmark_feature_not_enabled() {
}
}