use ass_core::{parser::IssueSeverity, Script};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_styles_without_format_line() {
let script_no_format = r"
[V4+ Styles]
Style: Default,Arial,20,&Hffffff,&H0,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1
Style: Large,Arial,40,&Hff0000,&H0,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(script_no_format).expect("Script parsing should work");
assert!(!script.sections().is_empty());
let _has_format_warnings = script.issues().iter().any(|issue| {
issue.message.to_lowercase().contains("format")
|| issue.message.to_lowercase().contains("field")
});
}
#[test]
fn test_v4_styles_section() {
let script_v4 = r"
[V4 Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding, RelativeToVideo
Style: Default,Arial,20,16777215,255,0,0,0,0,1,2,0,2,10,10,10,0,1,0
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(script_v4).expect("Script parsing should work");
assert!(!script.sections().is_empty());
}
#[test]
fn test_style_field_count_mismatch() {
let script_too_few = r"
[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,&Hffffff
Style: Complete,Arial,20,&Hffffff,&H0,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(script_too_few).expect("Script parsing should work");
let _has_mismatch_warnings = script.issues().iter().any(|issue| {
matches!(issue.severity, IssueSeverity::Warning)
&& (issue.message.contains("field") || issue.message.contains("count"))
});
let script_too_many = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize
Style: Default,Arial,20,&Hffffff,&H0,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1,extra,fields
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script_many = Script::parse(script_too_many).expect("Script parsing should work");
assert!(!script_many.sections().is_empty());
}
#[test]
fn test_missing_format_fields() {
let script_missing_fields = r"
[V4+ Styles]
Format: Name, Fontname
Style: Default,Arial,20,&Hffffff,&H0,&H0,&H0,0,0,0,0,100,100,0,0,1,2,0,2,10,10,10,1
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(script_missing_fields).expect("Script parsing should work");
assert!(!script.sections().is_empty());
let _has_missing_field_issues = script
.issues()
.iter()
.any(|issue| issue.message.contains("field") || issue.message.contains("missing"));
}
#[test]
fn test_abrupt_ending_in_styles() {
let truncated_style = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style: Default,Arial,20";
let script = Script::parse(truncated_style).expect("Script parsing should work");
assert!(!script.sections().is_empty() || !script.issues().is_empty());
let truncated_comment = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize
; This is a comment that gets cut off in the mid";
let script_comment = Script::parse(truncated_comment).expect("Script parsing should work");
let _has_sections_or_issues =
!script_comment.sections().is_empty() || !script_comment.issues().is_empty();
let ending_whitespace = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize
Style: Default,Arial,20
";
let script_ws = Script::parse(ending_whitespace).expect("Script parsing should work");
assert!(!script_ws.sections().is_empty());
}
#[test]
fn test_malformed_format_lines() {
let empty_format = r"
[V4+ Styles]
Format:
Style: Default,Arial,20
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(empty_format).expect("Script parsing should work");
assert!(!script.sections().is_empty());
let spaces_format = r"
[V4+ Styles]
Format:
Style: Default,Arial,20
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script_spaces = Script::parse(spaces_format).expect("Script parsing should work");
assert!(!script_spaces.sections().is_empty());
}
#[test]
fn test_styles_special_characters() {
let special_chars = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style: Default,Arial,20,&Hffffff
Style: Special!@#$%,Arial,20,&H00ff00
Style: Unicode测试,Arial,20,&Hff0000
Style: Empty,,20,&H0000ff
Style: Comma\,Name,Arial,20,&Hffff00
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(special_chars).expect("Script parsing should work");
assert!(!script.sections().is_empty());
let _has_critical_errors = script
.issues()
.iter()
.any(|issue| matches!(issue.severity, IssueSeverity::Error));
}
#[test]
fn test_multiple_format_lines() {
let multiple_formats = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize
Format: Name, Fontname, Fontsize, PrimaryColour
Style: Default,Arial,20,&Hffffff
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(multiple_formats).expect("Script parsing should work");
assert!(!script.sections().is_empty());
}
#[test]
fn test_empty_styles_section() {
let empty_section = r"
[V4+ Styles]
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(empty_section).expect("Script parsing should work");
assert!(!script.sections().is_empty());
}
#[test]
fn test_styles_only_comments() {
let only_comments = r"
[V4+ Styles]
; This is a comment
; Another comment
!: This is also a comment
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(only_comments).expect("Script parsing should work");
assert!(!script.sections().is_empty());
}
#[test]
fn test_style_spacing_variations() {
let spacing_variations = r"
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour
Style:Default,Arial,20,&Hffffff
Style: Spaced , Arial , 20 , &H00ff00
Style: Tabbed , Arial , 20 , &Hff0000
Style: Mixed , Arial, 20,&H0000ff
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(spacing_variations).expect("Script parsing should work");
assert!(!script.sections().is_empty());
}
#[test]
fn test_field_parsing_boundaries() {
let boundary_cases = r"
[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: Minimum,,,,,,,,,,,,,,,,,,,,,
Style: Maximum,Arial,999,&HFFFFFFFF,&HFFFFFFFF,&HFFFFFFFF,&HFFFFFFFF,1,1,1,1,1000,1000,100,360,4,100,100,11,9999,9999,9999,255
Style: Negative,Arial,-1,&H0,&H0,&H0,&H0,-1,-1,-1,-1,-100,-100,-100,-360,-1,-100,-100,-1,-1,-1,-1,-1
[Events\]
Format: Start, End, Style, Text
Dialogue: 0:00:00.00,0:00:05.00,Default,Test
";
let script = Script::parse(boundary_cases).expect("Script parsing should work");
assert!(!script.sections().is_empty());
let _has_sections = !script.sections().is_empty();
}
}