use super::*;
use crate::parser::ast::{Event, Section, SectionType};
use crate::ScriptVersion;
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec};
#[test]
fn atomic_batch_update_success() {
use crate::parser::ast::{EventType, Span};
let content = "[Script Info]\nTitle: Test\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize\nStyle: Default,Arial,20";
let mut script = Script::parse(content).unwrap();
let updates = if let Some(Section::Styles(styles)) = script.find_section(SectionType::Styles) {
vec![UpdateOperation {
offset: styles[0].span.start,
new_line: "Style: Default,Helvetica,24",
line_number: 10,
}]
} else {
vec![]
};
let events = vec![Event {
event_type: EventType::Dialogue,
layer: "0",
start: "0:00:00.00",
end: "0:00:05.00",
style: "Default",
name: "",
margin_l: "0",
margin_r: "0",
margin_v: "0",
margin_t: None,
margin_b: None,
effect: "",
text: "New Event",
span: Span::new(0, 0, 0, 0),
}];
let event_batch = EventBatch { events };
let result = script.atomic_batch_update(updates, None, Some(event_batch));
assert!(result.is_ok());
if let Some(Section::Styles(styles)) = script.find_section(SectionType::Styles) {
assert_eq!(styles[0].fontname, "Helvetica");
assert_eq!(styles[0].fontsize, "24");
}
if let Some(Section::Events(events)) = script.find_section(SectionType::Events) {
assert_eq!(events.len(), 1);
assert_eq!(events[0].text, "New Event");
}
}
#[test]
fn atomic_batch_update_rollback() {
let content = "[Script Info]\nTitle: Test\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize\nStyle: Default,Arial,20";
let mut script = Script::parse(content).unwrap();
let original_script = script.clone();
let updates = vec![UpdateOperation {
offset: 999_999, new_line: "Style: Invalid,Arial,20",
line_number: 10,
}];
let result = script.atomic_batch_update(updates, None, None);
assert!(result.is_err());
assert_eq!(script, original_script);
}
#[test]
fn parse_malformed_comprehensive() {
let malformed_inputs = vec![
"[Script Info]\nTitleWithoutColon",
"[Script Info]\nTitle: Test\n\nInvalid line outside section",
];
for input in malformed_inputs {
let result = Script::parse(input);
assert!(result.is_ok() || result.is_err());
if let Ok(script) = result {
assert_eq!(script.source(), input);
let _ = script.sections();
let _ = script.issues();
}
}
}
#[test]
fn parse_edge_case_inputs() {
let edge_cases = vec![
"", "\n\n\n", " ", "\t\t\t", "[Script Info]", "[Script Info]\n", "[]", "[ ]", "[Script Info]\nTitle:", "[Script Info]\n:Value", ];
for input in edge_cases {
let result = Script::parse(input);
assert!(result.is_ok(), "Failed to parse edge case: {input:?}");
let script = result.unwrap();
assert_eq!(script.source(), input);
let _ = script.sections();
}
}
#[test]
fn script_version_handling() {
let v4_script = Script::parse("[Script Info]\nScriptType: v4.00").unwrap();
assert_eq!(v4_script.version(), ScriptVersion::SsaV4);
let v4_plus_script = Script::parse("[Script Info]\nScriptType: v4.00+").unwrap();
assert_eq!(v4_plus_script.version(), ScriptVersion::AssV4);
let no_version_script = Script::parse("[Script Info]\nTitle: Test").unwrap();
assert_eq!(no_version_script.version(), ScriptVersion::AssV4);
}
#[test]
fn parse_large_script_comprehensive() {
#[cfg(not(feature = "std"))]
use alloc::fmt::Write;
#[cfg(feature = "std")]
use std::fmt::Write;
let mut content = String::from("[Script Info]\nTitle: Large Test\n");
content.push_str("[V4+ Styles]\nFormat: Name, Fontname, Fontsize\n");
for i in 0..100 {
writeln!(content, "Style: Style{},Arial,{}", i, 16 + i % 10).unwrap();
}
content.push_str("\n[Events]\nFormat: Layer, Start, End, Style, Text\n");
for i in 0..100 {
let start_time = i * 5;
let end_time = start_time + 4;
writeln!(
content,
"Dialogue: 0,0:00:{:02}.00,0:00:{:02}.00,Style{},Text {}",
start_time / 60,
end_time / 60,
i % 10,
i
)
.unwrap();
}
let script = Script::parse(&content).unwrap();
assert_eq!(script.sections().len(), 3);
assert_eq!(script.source(), content);
}