use oxidize_pdf::parser::{ParseError, ParseOptions, PdfReader};
use std::io::Cursor;
#[test]
fn test_empty_pdf_detection() {
let empty_data = b"";
let cursor = Cursor::new(empty_data);
let result = PdfReader::new(cursor);
assert!(result.is_err());
match result {
Err(ParseError::EmptyFile) => {
}
_ => panic!("Expected EmptyFile error"),
}
}
#[test]
fn test_minimal_invalid_pdf() {
let invalid_data = b"Not a PDF file";
let cursor = Cursor::new(invalid_data);
let result = PdfReader::new(cursor);
assert!(result.is_err());
}
#[test]
fn test_truncated_pdf_header() {
let truncated_header = b"%PD";
let cursor = Cursor::new(truncated_header);
let result = PdfReader::new(cursor);
assert!(result.is_err());
}
#[test]
fn test_reader_options_getter() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
let options = ParseOptions::lenient();
let reader = PdfReader::new_with_options(cursor, options.clone());
if let Ok(reader) = reader {
let reader_options = reader.options();
assert_eq!(reader_options.strict_mode, options.strict_mode);
}
}
#[test]
fn test_reader_with_strict_options() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
let strict_options = ParseOptions::strict();
let result = PdfReader::new_with_options(cursor, strict_options);
let _ = result;
}
#[test]
fn test_reader_with_lenient_options() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
let lenient_options = ParseOptions::lenient();
let result = PdfReader::new_with_options(cursor, lenient_options);
let _ = result;
}
#[test]
fn test_is_encrypted_on_unencrypted_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(reader) = PdfReader::new(cursor) {
assert!(!reader.is_encrypted());
}
}
#[test]
fn test_is_unlocked_on_unencrypted_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(reader) = PdfReader::new(cursor) {
assert!(reader.is_unlocked());
}
}
#[test]
fn test_encryption_handler_on_unencrypted_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(reader) = PdfReader::new(cursor) {
assert!(reader.encryption_handler().is_none());
}
}
#[test]
fn test_unlock_with_password_on_unencrypted_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let result = reader.unlock_with_password("any_password");
assert!(result.is_ok());
assert_eq!(result.unwrap(), true);
}
}
#[test]
fn test_try_empty_password_on_unencrypted_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let result = reader.try_empty_password();
assert!(result.is_ok());
assert_eq!(result.unwrap(), true);
}
}
#[test]
fn test_encryption_handler_mut_on_unencrypted_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
assert!(reader.encryption_handler_mut().is_none());
}
}
#[test]
fn test_pdf_version_getter() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(reader) = PdfReader::new(cursor) {
let version = reader.version();
assert_eq!(version.major, 1);
assert_eq!(version.minor, 4);
}
}
#[test]
fn test_pdf_with_only_header() {
let header_only = b"%PDF-1.4\n";
let cursor = Cursor::new(header_only);
let result = PdfReader::new(cursor);
assert!(result.is_err());
}
#[test]
fn test_pdf_with_invalid_version() {
let invalid_version = b"%PDF-X.Y\n%%EOF\n";
let cursor = Cursor::new(invalid_version);
let result = PdfReader::new(cursor);
assert!(result.is_err());
}
#[test]
fn test_new_reader_with_default_options() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
let result = PdfReader::new(cursor);
if let Ok(reader) = result {
assert_eq!(
reader.options().strict_mode,
ParseOptions::default().strict_mode
);
}
}
#[test]
fn test_catalog_access_attempt() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let _ = reader.catalog();
}
}
#[test]
fn test_info_access_attempt() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let _ = reader.info();
}
}
#[test]
fn test_page_count_attempt() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let _ = reader.page_count();
}
}
#[test]
fn test_metadata_attempt() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let _ = reader.metadata();
}
}
#[test]
fn test_resolve_null_object() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
use oxidize_pdf::parser::objects::PdfObject;
let null_obj = PdfObject::Null;
let resolved = reader.resolve(&null_obj);
if let Ok(obj) = resolved {
assert!(matches!(obj, PdfObject::Null));
}
}
}
#[test]
fn test_resolve_boolean_object() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
use oxidize_pdf::parser::objects::PdfObject;
let bool_obj = PdfObject::Boolean(true);
let resolved = reader.resolve(&bool_obj);
if let Ok(obj) = resolved {
assert!(matches!(obj, PdfObject::Boolean(true)));
}
}
}
#[test]
fn test_resolve_integer_object() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
use oxidize_pdf::parser::objects::PdfObject;
let int_obj = PdfObject::Integer(42);
let resolved = reader.resolve(&int_obj);
if let Ok(obj) = resolved {
assert!(matches!(obj, PdfObject::Integer(42)));
}
}
}
#[test]
fn test_resolve_stream_length_on_non_stream() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
use oxidize_pdf::parser::objects::PdfObject;
let int_obj = PdfObject::Integer(42);
let result = reader.resolve_stream_length(&int_obj);
if let Ok(None) = result {
} else if result.is_err() {
} else {
panic!("Expected None or error, got {:?}", result);
}
}
}
#[test]
fn test_clear_parse_context() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
reader.clear_parse_context();
let _context = reader.parse_context_mut();
}
}
#[test]
fn test_parse_context_mut_access() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let context = reader.parse_context_mut();
let _ = context.depth;
}
}
#[test]
fn test_into_document_conversion() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(reader) = PdfReader::new(cursor) {
let _document = reader.into_document();
}
}
fn create_minimal_valid_pdf() -> Vec<u8> {
let pdf = b"%PDF-1.4
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/Count 0
/Kids []
>>
endobj
xref
0 3
0000000000 65535 f
0000000009 00000 n
0000000068 00000 n
trailer
<<
/Size 3
/Root 1 0 R
>>
startxref
135
%%EOF
";
pdf.to_vec()
}
#[test]
fn test_open_and_parse_simple_pdf() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/jpeg_extraction_test.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let result = PdfReader::open(pdf_path);
assert!(result.is_ok(), "Failed to open simple PDF");
if let Ok(mut reader) = result {
let version = reader.version();
assert!(version.major >= 1);
assert!(!reader.is_encrypted());
assert!(reader.is_unlocked());
let catalog_result = reader.catalog();
assert!(catalog_result.is_ok(), "Failed to get catalog");
let page_count_result = reader.page_count();
if let Ok(count) = page_count_result {
assert!(count >= 1, "PDF should have at least 1 page");
}
let _ = reader.info();
let _ = reader.pages();
let _ = reader.metadata();
}
}
#[test]
fn test_open_and_parse_unicode_pdf() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/unicode_glyph_mapping_test.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let result = PdfReader::open(pdf_path);
assert!(result.is_ok(), "Failed to open Unicode PDF");
if let Ok(mut reader) = result {
let pages_result = reader.get_all_pages();
if let Ok(pages) = pages_result {
assert!(pages.len() >= 1, "Should have at least 1 page");
}
let _ = reader.get_object(1, 0);
}
}
#[test]
fn test_open_with_strict_options_real_pdf() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/page_tree_inheritance.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let result = PdfReader::open_strict(pdf_path);
let _ = result;
}
#[test]
fn test_open_with_custom_options_real_pdf() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/png_transparency.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let mut options = ParseOptions::lenient();
options.recover_from_stream_errors = true;
options.ignore_corrupt_streams = false;
let result = PdfReader::open_with_options(pdf_path, options);
assert!(result.is_ok(), "Failed to open PDF with custom options");
}
#[test]
fn test_open_document_convenience_method() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/jpeg_extraction_test.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let result = PdfReader::open_document(pdf_path);
assert!(result.is_ok(), "Failed to open PDF as document");
}
#[test]
fn test_parse_complex_pdf_with_many_objects() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/Cold_Email_Hacks.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let result = PdfReader::open(pdf_path);
assert!(result.is_ok(), "Failed to open complex PDF");
if let Ok(mut reader) = result {
let page_count_result = reader.page_count();
if let Ok(count) = page_count_result {
assert!(count > 0, "Complex PDF should have pages");
}
let pages_result = reader.get_all_pages();
if let Ok(pages) = pages_result {
assert!(pages.len() > 0, "Should return page array");
if pages.len() > 0 {
let page_result = reader.get_page(0);
let _ = page_result; }
}
let info_result = reader.info();
if let Ok(Some(_info_dict)) = info_result {
}
let metadata_result = reader.metadata();
let _ = metadata_result; }
}
#[test]
fn test_parse_issue_93_romanian_pdf() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/issue-93-romanian.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
let result = PdfReader::open(pdf_path);
assert!(
result.is_ok(),
"Issue #93 PDF should open without panicking"
);
if let Ok(mut reader) = result {
let catalog_result = reader.catalog();
assert!(
catalog_result.is_ok(),
"Should retrieve catalog from Issue #93 PDF"
);
let page_count_result = reader.page_count();
let _ = page_count_result;
let pages_result = reader.get_all_pages();
let _ = pages_result;
}
}
#[test]
fn test_object_cache_behavior() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/jpeg_extraction_test.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
if let Ok(mut reader) = PdfReader::open(pdf_path) {
let obj1_is_ok = reader.get_object(1, 0).is_ok();
let obj2_is_ok = reader.get_object(1, 0).is_ok();
assert_eq!(obj1_is_ok, obj2_is_ok);
}
}
#[test]
fn test_resolve_reference_chain() {
use oxidize_pdf::parser::objects::PdfObject;
use std::path::Path;
let pdf_path = Path::new("test-pdfs/page_tree_inheritance.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
if let Ok(mut reader) = PdfReader::open(pdf_path) {
let ref_obj = PdfObject::Reference(1, 0);
let resolved_result = reader.resolve(&ref_obj);
let _ = resolved_result;
}
}
#[test]
fn test_clear_context_and_reparse() {
use std::path::Path;
let pdf_path = Path::new("test-pdfs/jpeg_extraction_test.pdf");
if !pdf_path.exists() {
eprintln!("Skipping test - PDF not found: {:?}", pdf_path);
return;
}
if let Ok(mut reader) = PdfReader::open(pdf_path) {
let count1 = reader.page_count();
reader.clear_parse_context();
let count2 = reader.page_count();
assert_eq!(count1.is_ok(), count2.is_ok());
}
}
#[test]
fn test_malformed_xref_handling() {
let malformed_xref = b"%PDF-1.4
1 0 obj
<< /Type /Catalog >>
endobj
xref
MALFORMED
trailer
<< /Size 2 /Root 1 0 R >>
startxref
50
%%EOF
";
let cursor = Cursor::new(malformed_xref);
let result = PdfReader::new(cursor);
assert!(result.is_err());
}
#[test]
fn test_missing_trailer() {
let no_trailer = b"%PDF-1.4
1 0 obj
<< /Type /Catalog >>
endobj
xref
0 2
0000000000 65535 f
0000000009 00000 n
";
let cursor = Cursor::new(no_trailer);
let result = PdfReader::new(cursor);
assert!(result.is_err());
}
#[test]
fn test_get_object_with_invalid_reference() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let result = reader.get_object(9999, 0);
if result.is_err() {
} else if let Ok(obj) = result {
use oxidize_pdf::parser::objects::PdfObject;
assert!(matches!(obj, PdfObject::Null));
}
}
}
#[test]
fn test_pages_access_on_minimal_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let result = reader.pages();
let _ = result;
}
}
#[test]
fn test_get_all_pages_on_empty_pdf() {
let pdf_data = create_minimal_valid_pdf();
let cursor = Cursor::new(pdf_data);
if let Ok(mut reader) = PdfReader::new(cursor) {
let result = reader.get_all_pages();
if let Ok(pages) = result {
assert_eq!(pages.len(), 0);
}
}
}