From 3c749e13df0c2ebd4e63c38549442397dbbf6a40 Mon Sep 17 00:00:00 2001 From: mtlcl410 Date: Thu, 5 Nov 2026 11:05:35 +0800 Subject: [PATCH] M11: tests: split the predefined XMP value type test by kind of value (6.6.2.3.1) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Pq7HyDBXygTf7jcqdsjcfn --- crates/preflight/src/tests.rs | 60 ++++++++++++++++++++++++----------- parity/acrobat-features.toml | 2 +- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/crates/preflight/src/tests.rs b/crates/preflight/src/tests.rs index c187280667..ab1686be55 100644 --- a/crates/preflight/src/tests.rs +++ b/crates/preflight/src/tests.rs @@ -489,25 +489,32 @@ fn an_output_intent_profile_header_is_read_within_a_size_cap() { } } -/// PDF/A-2 6.6.2.3.1: the properties of the predefined XMP schemas have the value types XMP gives -/// them (ISO 16684-1 8.2 and XMP Part 2), in every RDF/XML form a value can take. -#[test] -fn xmp_properties_of_predefined_schemas_have_their_value_types() { - const NS: &str = concat!( - r#"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" "#, - r#"xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" "#, - r#"xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" "#, - r#"xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/" xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" "#, - r#"xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" xmlns:pdf="http://ns.adobe.com/pdf/1.3/""# +const XMP_NS: &str = concat!( + r#"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" "#, + r#"xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" "#, + r#"xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" "#, + r#"xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/" xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" "#, + r#"xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" xmlns:pdf="http://ns.adobe.com/pdf/1.3/""# +); + +/// The mistyped predefined properties of a packet whose one description holds `body` (its +/// attributes, then `>` and its elements). +fn mistyped(body: &str) -> Vec { + let xmp = format!( + r#""# ); - let mistyped = |body: &str| -> Vec { - let xmp = format!( - r#""# - ); - let parsed = xmp::parse(&xmp).expect("parses"); - xmp_types::mistyped(&parsed).into_iter().collect() - }; - let element = |p: &str, v: &str| mistyped(&format!("><{p}>{v}")); + let parsed = xmp::parse(&xmp).expect("parses"); + xmp_types::mistyped(&parsed).into_iter().collect() +} + +/// [`mistyped`] for the property `p` written as an element holding `v`. +fn element(p: &str, v: &str) -> Vec { + mistyped(&format!("><{p}>{v}")) +} + +/// PDF/A-2 6.6.2.3.1, simple values: their lexical forms (ISO 16684-1 8.2.1), as elements and attributes. +#[test] +fn xmp_simple_values_have_their_lexical_forms() { // Simple types, as elements and as attributes. assert!(element("crs:Contrast", "-25").is_empty()); assert_eq!(element("crs:Contrast", "25.0"), ["crs:Contrast"]); @@ -529,6 +536,11 @@ fn xmp_properties_of_predefined_schemas_have_their_value_types() { } assert!(element("xmpDM:videoPixelAspectRatio", "1001/30000").is_empty()); assert_eq!(element("xmpDM:videoPixelAspectRatio", "1.5"), ["xmpDM:videoPixelAspectRatio"]); +} + +/// PDF/A-2 6.6.2.3.1, arrays: the kind, every item, and the languages of a language alternative. +#[test] +fn xmp_arrays_have_their_kind_and_item_types() { // Text can't be an array or a structure; a simple value can be given as rdf:resource. assert_eq!(element("crs:RawFileName", "a"), ["crs:RawFileName"]); assert_eq!(mistyped(r#">1"#), ["crs:RawFileName"]); @@ -542,6 +554,11 @@ fn xmp_properties_of_predefined_schemas_have_their_value_types() { assert!(element("dc:title", r#"T"#).is_empty()); assert_eq!(element("dc:title", "T"), ["dc:title"]); assert_eq!(element("dc:title", "T"), ["dc:title"]); +} + +/// PDF/A-2 6.6.2.3.1, structures in their three RDF/XML forms, nested, and qualified values. +#[test] +fn xmp_structures_have_their_field_types() { // Structures in their three forms, with each known field checked. assert!(mistyped(r#">d2016"#).is_empty()); assert!(mistyped(r#">"#).is_empty()); @@ -566,9 +583,14 @@ fn xmp_properties_of_predefined_schemas_have_their_value_types() { // A qualified value is checked by its rdf:value. assert!(mistyped(r#">5q"#).is_empty()); assert_eq!(mistyped(r#">five"#), ["crs:Contrast"]); +} + +/// PDF/A-2 6.6.2.3.1 through verify: one issue per mistyped property, not fixable. +#[test] +fn xmp_value_types_are_reported_by_verify() { // Through verify: reported under 6.6.2.3.1, not fixable. let xmp = - format!(r#""#); + format!(r#""#); let stream = format!("<< /Type /Metadata /Subtype /XML /Length {} >>\nstream\n{xmp}\nendstream", xmp.len()); let doc = build(&["<< /Type /Catalog /Pages 2 0 R /Metadata 3 0 R >>", "<< /Type /Pages /Kids [] /Count 0 >>", &stream], ""); let issues: Vec = verify(&doc, Level::A2b).into_iter().filter(|i| i.clause == "6.6.2.3.1").collect(); diff --git a/parity/acrobat-features.toml b/parity/acrobat-features.toml index 33be107925..309782be84 100644 --- a/parity/acrobat-features.toml +++ b/parity/acrobat-features.toml @@ -7943,7 +7943,7 @@ milestone = "M11" status = "partial" commands = ["standards.pdfa"] tools = ["pdfa_verify"] -evidence = ["crates/preflight/src/tests.rs::verify_reports_what_breaks_pdfa", "crates/preflight/src/tests.rs::standards_identification_uses_namespace_not_prefix", "crates/preflight/src/tests.rs::convert_fixes_all_but_fonts", "crates/preflight/src/tests.rs::verify_reports_an_output_intent_that_does_not_match_device_colour", "crates/preflight/src/tests.rs::xmp_properties_of_predefined_schemas_have_their_value_types", "crates/automation/tests/it/automation.rs::pdfa_through_tools", "crates/ui-egui/tests/it/compare.rs::pdfa_dialog_verifies_and_converts"] +evidence = ["crates/preflight/src/tests.rs::verify_reports_what_breaks_pdfa", "crates/preflight/src/tests.rs::standards_identification_uses_namespace_not_prefix", "crates/preflight/src/tests.rs::convert_fixes_all_but_fonts", "crates/preflight/src/tests.rs::verify_reports_an_output_intent_that_does_not_match_device_colour", "crates/preflight/src/tests.rs::xmp_simple_values_have_their_lexical_forms", "crates/preflight/src/tests.rs::xmp_arrays_have_their_kind_and_item_types", "crates/preflight/src/tests.rs::xmp_structures_have_their_field_types", "crates/preflight/src/tests.rs::xmp_value_types_are_reported_by_verify", "crates/automation/tests/it/automation.rs::pdfa_through_tools", "crates/ui-egui/tests/it/compare.rs::pdfa_dialog_verifies_and_converts"] notes = "PDF/A-2b/3b structural rules: identification, the value types of the predefined XMP schemas (6.6.2.3.1: dc, xmp, xmpRights, xmpMM, xmpBJ, xmpTPg, xmpDM, pdf, photoshop, crs and their structures; the tiff, exif and aux namespaces, whose tables XMP Part 2 defers to CIPA DC-010, are not yet checked), encryption, output intent (present, and RGB/CMYK to match DeviceRGB/DeviceCMYK use), fonts embedded, annotations, actions, images, embedded files. Not yet: content-stream operator checks, transparency details, PDF/A-1 and -4, a veraPDF comparison." [[feature]]