use crate::tokenizer::{AssTokenizer, TokenType};
#[cfg(not(feature = "std"))]
use hashbrown::HashSet;
#[cfg(feature = "std")]
use std::collections::HashSet;
#[test]
fn tokenizer_boundary_character_handling() {
let content = "\n\r\n\r\r\n";
let mut tokenizer = AssTokenizer::new(content);
let tokens = tokenizer.tokenize_all().unwrap();
let newline_count = tokens
.iter()
.filter(|t| t.token_type == TokenType::Newline)
.count();
assert!(newline_count > 0);
}
#[test]
fn tokenizer_comment_edge_cases() {
let content = ";comment\n!comment\n!:comment\n!notcomment\n;;double\n";
let mut tokenizer = AssTokenizer::new(content);
let tokens = tokenizer.tokenize_all().unwrap();
assert!(tokens.iter().any(|t| t.token_type == TokenType::Comment));
}
#[test]
fn tokenizer_empty_section_and_override() {
let content = "[]{}text[empty]{}";
let mut tokenizer = AssTokenizer::new(content);
let tokens = tokenizer.tokenize_all().unwrap();
let section_headers = tokens
.iter()
.filter(|t| t.token_type == TokenType::SectionHeader)
.count();
let section_closes = tokens
.iter()
.filter(|t| t.token_type == TokenType::SectionClose)
.count();
assert_eq!(section_headers, section_closes);
}
#[test]
fn tokenizer_position_consistency() {
let content = "line1\nline2\r\nline3\rline4";
let mut tokenizer = AssTokenizer::new(content);
let mut prev_line = 1;
let mut prev_column = 1;
while let Some(token) = tokenizer.next_token().unwrap() {
assert!(token.line >= prev_line);
if token.line == prev_line {
assert!(token.column >= prev_column);
}
prev_line = token.line;
prev_column = token.column;
}
}
#[test]
fn tokenizer_scanner_methods_coverage() {
let content = "[V4+ Styles]\n{\\alpha&H80}Text{\\b1}Bold";
let mut tokenizer = AssTokenizer::new(content);
let tokens = tokenizer.tokenize_all().unwrap();
let token_types: HashSet<_> = tokens.iter().map(|t| &t.token_type).collect();
assert!(token_types.len() > 3);
}
#[test]
fn tokenizer_issue_collection_edge_cases() {
let mut tokenizer = AssTokenizer::new("valid content");
assert!(tokenizer.issues().is_empty());
let _tokens = tokenizer.tokenize_all().unwrap();
assert!(tokenizer.issues().is_empty());
}
#[test]
fn tokenizer_context_reset_scenarios() {
let content = "{override\nnewline resets}\n[section\nnewline resets]";
let mut tokenizer = AssTokenizer::new(content);
let tokens = tokenizer.tokenize_all().unwrap();
let newlines = tokens
.iter()
.filter(|t| t.token_type == TokenType::Newline)
.count();
assert!(newlines > 0);
}
#[test]
fn tokenizer_whitespace_skipping_behavior() {
let content = " { override } [ section ] : value ";
let mut tokenizer = AssTokenizer::new(content);
let tokens = tokenizer.tokenize_all().unwrap();
assert!(!tokens.is_empty());
let has_override = tokens
.iter()
.any(|t| t.token_type == TokenType::OverrideOpen);
let has_section = tokens
.iter()
.any(|t| t.token_type == TokenType::SectionHeader);
let has_colon = tokens.iter().any(|t| t.token_type == TokenType::Colon);
assert!(has_override || has_section);
assert!(has_colon);
}
#[test]
fn tokenizer_iteration_limit_exceeded() {
let mut tokenizer = AssTokenizer::new("a");
let result = tokenizer.tokenize_all();
assert!(result.is_ok());
let long_input = "a".repeat(100);
let mut long_tokenizer = AssTokenizer::new(&long_input);
let result = long_tokenizer.tokenize_all();
assert!(result.is_ok());
}
#[test]
fn tokenizer_position_advancement_protection() {
let mut tokenizer = AssTokenizer::new("test");
let token = tokenizer.next_token();
assert!(token.is_ok());
assert!(token.unwrap().is_some());
}