75 lines
3 KiB
Rust
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"));
|
|
}
|