#[cfg(feature = "pdf_comparison_tests")] mod tests { use rckive_genpdf::{elements, fonts, style, Element as _}; const FONT_DIRS: &[&str] = &["./tests/files/liberation"]; const DEFAULT_FONT_NAME: &str = "LiberationSans"; const LOREM_IPSUM: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut \ labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco \ laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in \ voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat \ non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; /// Creates a new document with the default font, minimal conformance and constant creation and /// modification dates. fn get_document() -> rckive_genpdf::Document { let font_dir = FONT_DIRS .iter() .find(|path| std::path::Path::new(path).exists()) .expect("Could not find font directory"); let default_font = fonts::from_files(font_dir, DEFAULT_FONT_NAME, Some(fonts::Builtin::Helvetica)) .expect("Failed to load the default font family"); let mut doc = rckive_genpdf::Document::new(default_font); doc.set_minimal_conformance(); doc.set_creation_date(printpdf::OffsetDateTime::unix_epoch()); doc.set_modification_date(printpdf::OffsetDateTime::unix_epoch()); doc } /// Compares the PDF file generated by the given document with the stored PDF file at /// `tests/files/.pdf`. fn check(name: &str, doc: rckive_genpdf::Document) { let expected_dir = std::path::Path::new("tests/files"); if !expected_dir.exists() { std::fs::create_dir(expected_dir).expect("Failed to create expected directory"); } let mut actual_doc: Vec = Vec::new(); doc.render(&mut actual_doc) .expect("Failed to render document"); // Prune ID because it is randomly generated by printpdf. let mut actual_pdf_doc = lopdf::Document::load_mem(&actual_doc).expect("Failed to load actual document"); actual_pdf_doc.trailer.remove(b"ID"); let mut actual_doc: Vec = Vec::new(); actual_pdf_doc .save_to(&mut actual_doc) .expect("Failed to save pruned actual document"); let expected_path = expected_dir.join(name).with_extension("pdf"); if expected_path.exists() { let expected_doc = std::fs::read(&expected_path).expect("Failed to read expected document"); if actual_doc != expected_doc { let actual_path = expected_path.with_extension("new.pdf"); std::fs::write(&actual_path, actual_doc).expect("Failed to write actual document"); panic!( "Actual document does not match expected document. Please check {} \ for more information", actual_path.display(), ); } } else { std::fs::write(expected_path, actual_doc).expect("Failed to write expected document"); } } macro_rules! test_with_document { ($( $(#[$outer:meta])* fn $name:ident($arg:ident: $arg_ty:ty) -> $ret_ty:ty $body:block )*) => { $( $(#[$outer])* fn $name() { let $arg: $arg_ty = get_document(); let doc: $ret_ty = $body; check(stringify!($name), doc); } )* }; } test_with_document! { #[test] fn minimal(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { doc } #[test] fn text(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { // TODO: Why 14pt and not 12? let mut doc = doc; doc.set_paper_size((12, rckive_genpdf::Mm::from(printpdf::Pt(14.0)))); doc.push(elements::Text::new("foobar")); doc } #[test] // Ignore as this currently returns an error #[ignore] fn paragraph_long(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { let mut doc = doc; doc.set_paper_size((50, 100)); doc.push(elements::Paragraph::new("Donaudampfschifffahrtskapitänsmützenhersteller")); doc } #[test] fn kerning(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { let mut doc = doc; doc.set_paper_size((7, 10)); doc.push(elements::Paragraph::new("AV")); doc.push(elements::Paragraph::new("A").string("V")); doc } #[test] #[ignore] fn sizes(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { // TODO: Top/bottom spacing let mut doc = doc; doc.set_paper_size((25, 50)); for size in &[5, 10, 20, 40, 5, 20, 10] { doc.push( elements::Text::new("zyp") .styled(style::Style::new().with_font_size(*size)) ); } doc } #[test] fn frame_single(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { let mut doc = doc; doc.set_paper_size((100, 30)); let mut decorator = rckive_genpdf::SimplePageDecorator::new(); decorator.set_margins(5); doc.set_page_decorator(decorator); doc.push( elements::Paragraph::new("Lorem ipsum") .framed(style::LineStyle::new()) ); doc } #[test] fn frame_multi(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { let mut doc = doc; doc.set_paper_size((100, 30)); let mut decorator = rckive_genpdf::SimplePageDecorator::new(); decorator.set_margins(5); doc.set_page_decorator(decorator); doc.push( elements::Paragraph::new(LOREM_IPSUM) .framed(style::LineStyle::new()) ); doc } #[test] fn frame_single_thick(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { let mut doc = doc; doc.set_paper_size((100, 30)); let mut decorator = rckive_genpdf::SimplePageDecorator::new(); decorator.set_margins(5); doc.set_page_decorator(decorator); doc.push( elements::Paragraph::new("Lorem ipsum") .framed(style::LineStyle::new().with_thickness(5)) ); doc } #[test] fn frame_multi_thick(doc: rckive_genpdf::Document) -> rckive_genpdf::Document { let mut doc = doc; doc.set_paper_size((100, 30)); let mut decorator = rckive_genpdf::SimplePageDecorator::new(); decorator.set_margins(5); doc.set_page_decorator(decorator); doc.push( elements::Paragraph::new(LOREM_IPSUM) .framed(style::LineStyle::new().with_thickness(5)) ); doc } } }