nigig-org/crates/apps/pdf/pdf-document/tests/xmp_roundtrip.rs

75 lines
3 KiB
Rust

//! 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"));
}