//! Phase 9 exit criterion: XMP metadata round-trip through a real document. //! //! The unit tests in `xmp.rs` parse hand-built packets. These go through the //! whole write→parse pipeline: a document is built with an XMP packet in its //! catalogue `/Metadata` stream, written, re-parsed, and the metadata is read //! back off the catalogue — proving the `read_xmp` path navigates the real //! trailer→catalog→stream→decode chain, not just the parser. //! //! See `REVIEWS/adr/0039-pdf-xmp-and-conformance-decisions.md`. use nigig_pdf_cos::writer::PdfDocBuilder; use nigig_pdf_document::xmp::XmpMetadata; use nigig_pdf_document::PdfDocument; fn sample() -> XmpMetadata { XmpMetadata { title: Some("XMP Round Trip".into()), creators: vec!["Grace Hopper".into(), "Ada Lovelace".into()], description: Some("A document with metadata in XMP.".into()), keywords: vec!["compiler".into(), "navy".into()], creator_tool: Some("Nigig Test".into()), producer: Some("nigig-pdf".into()), creation_date: Some("2026-09-05T09:30:00Z".into()), mod_date: Some("2026-09-05T10:00:00Z".into()), } } #[test] fn xmp_metadata_round_trips_through_a_built_document() { let mut builder = PdfDocBuilder::new(); builder.add_page(100.0, 100.0, b""); builder.set_xmp_metadata(sample().to_packet()); let pdf = builder.finish(); let mut doc = PdfDocument::parse(&pdf).expect("parses"); let read = doc.xmp_metadata().expect("reads metadata"); let xmp = read.expect("catalogue has /Metadata"); assert_eq!(xmp.title.as_deref(), Some("XMP Round Trip")); assert_eq!(xmp.creators, vec!["Grace Hopper", "Ada Lovelace"]); assert_eq!(xmp.description.as_deref(), Some("A document with metadata in XMP.")); assert_eq!(xmp.keywords, vec!["compiler", "navy"]); assert_eq!(xmp.creator_tool.as_deref(), Some("Nigig Test")); assert_eq!(xmp.producer.as_deref(), Some("nigig-pdf")); assert_eq!(xmp.creation_date.as_deref(), Some("2026-09-05T09:30:00Z")); assert_eq!(xmp.mod_date.as_deref(), Some("2026-09-05T10:00:00Z")); } #[test] fn a_document_without_metadata_returns_none_not_error() { let mut builder = PdfDocBuilder::new(); builder.add_page(100.0, 100.0, b""); let pdf = builder.finish(); let mut doc = PdfDocument::parse(&pdf).expect("parses"); let read = doc.xmp_metadata().expect("reads metadata"); assert!(read.is_none(), "no /Metadata means Ok(None), not an error"); } #[test] fn the_packet_bridges_onto_document_info() { let info = sample().to_document_info(); assert_eq!(info.title.as_deref(), Some("XMP Round Trip")); assert_eq!(info.author.as_deref(), Some("Grace Hopper")); assert_eq!(info.subject.as_deref(), Some("A document with metadata in XMP.")); assert_eq!(info.keywords.as_deref(), Some("compiler, navy")); assert_eq!(info.producer.as_deref(), Some("nigig-pdf")); assert_eq!(info.creator.as_deref(), Some("Nigig Test")); }