From 647b9831dc5cb2f2bfe775a8802416cdd51ed59d Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Wed, 20 Dec 2023 07:17:06 -0500 Subject: Have qpdf-test-compare handle certain /ID differences Rationale is in comments in the code. Deterministic ID tests explicitly do not use this tool. --- compare-for-test/qpdf-test-compare.cc | 31 +++++++++++++++++++++--- compare-for-test/qtest/compare.test | 9 +++++++ compare-for-test/qtest/compare/diff-id.pdf | Bin 0 -> 844 bytes compare-for-test/qtest/compare/zlib-new-id.pdf | Bin 0 -> 844 bytes compare-for-test/qtest/compare/zlib-new-id1.pdf | Bin 0 -> 844 bytes compare-for-test/qtest/compare/zlib-new-id2.pdf | Bin 0 -> 844 bytes 6 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 compare-for-test/qtest/compare/diff-id.pdf create mode 100644 compare-for-test/qtest/compare/zlib-new-id.pdf create mode 100644 compare-for-test/qtest/compare/zlib-new-id1.pdf create mode 100644 compare-for-test/qtest/compare/zlib-new-id2.pdf (limited to 'compare-for-test') diff --git a/compare-for-test/qpdf-test-compare.cc b/compare-for-test/qpdf-test-compare.cc index 7873f4a2..3952381b 100644 --- a/compare-for-test/qpdf-test-compare.cc +++ b/compare-for-test/qpdf-test-compare.cc @@ -24,7 +24,7 @@ usage() << std::endl << "If the files match, the output is the expected file. Otherwise, it is" << std::endl - << "the actual file. Read comments in the test suite for rationale." << std::endl; + << "the actual file. Read comments in the code for rationale." << std::endl; exit(2); } @@ -50,6 +50,8 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle return label + ": different types"; } if (act.isStream()) { + // Disregard stream lengths. The length of stream data is compared later, and we don't care + // about the length of compressed data as long as the uncompressed data matches. auto act_dict = act.getDict(); auto exp_dict = exp.getDict(); act_dict.removeKey("/Length"); @@ -59,6 +61,8 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle return label + ": stream dictionaries differ"; } if (act_dict.getKey("/Type").isNameAndEquals("/XRef")) { + // Cross-reference streams will generally not match, but we have numerous tests that + // meaningfully ensure that xref streams are correct. QTC::TC("compare", "ignore data for xref stream"); return ""; } @@ -103,6 +107,27 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle return ""; } +void +cleanTrailer(QPDFObjectHandle& trailer) +{ + // If the trailer is an object stream, it will have /Length. + trailer.removeKey("/Length"); + // Disregard the second half of /ID. This doesn't have anything directly to do with zlib, but + // lots of tests use --deterministic-id, and that is affected. The deterministic ID tests + // meaningfully exercise that deterministic IDs behave as expected, so for the rest of the + // tests, it's okay to ignore /ID[1]. If the two halves of /ID are the same, ignore both since + // this means qpdf completely generated the /ID rather than preserving the first half. + auto id = trailer.getKey("/ID"); + if (id.isArray() && id.getArrayNItems() == 2) { + auto id0 = id.getArrayItem(0).unparse(); + auto id1 = id.getArrayItem(1).unparse(); + id.setArrayItem(1, "()"_qpdf); + if (id0 == id1) { + id.setArrayItem(0, "()"_qpdf); + } + } +} + std::string compare(char const* actual_filename, char const* expected_filename) { @@ -118,8 +143,8 @@ compare(char const* actual_filename, char const* expected_filename) auto act_trailer = actual.getTrailer(); auto exp_trailer = expected.getTrailer(); - act_trailer.removeKey("/Length"); - exp_trailer.removeKey("/Length"); + cleanTrailer(act_trailer); + cleanTrailer(exp_trailer); auto trailer_diff = compareObjects("trailer", act_trailer, exp_trailer); if (!trailer_diff.empty()) { QTC::TC("compare", "different trailer"); diff --git a/compare-for-test/qtest/compare.test b/compare-for-test/qtest/compare.test index 48625cf3..bcf6b788 100644 --- a/compare-for-test/qtest/compare.test +++ b/compare-for-test/qtest/compare.test @@ -52,6 +52,7 @@ my @diff = ( ["diff-data-unc.pdf", "5,0: stream data differs"], ["diff-stream-dict.pdf", "4,0: stream dictionaries differ"], ["diff-object-type.pdf", "6,0: different types"], + ["diff-id.pdf", "trailer: object contents differ"], ); $n_tests += 2 * scalar(@diff); @@ -90,4 +91,12 @@ $td->runtest("compare object stream files (same)", {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare ostream1.pdf ostream2.pdf"}, {$td->FILE => "ostream2.pdf", $td->EXIT_STATUS => 0}); +$n_tests += 2; +$td->runtest("files identical except /ID[1]", + {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare zlib.pdf zlib-new-id.pdf"}, + {$td->FILE => "zlib-new-id.pdf", $td->EXIT_STATUS => 0}); +$td->runtest("/ID[0] = /ID[1]", + {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare zlib-new-id1.pdf zlib-new-id2.pdf"}, + {$td->FILE => "zlib-new-id2.pdf", $td->EXIT_STATUS => 0}); + $td->report($n_tests); diff --git a/compare-for-test/qtest/compare/diff-id.pdf b/compare-for-test/qtest/compare/diff-id.pdf new file mode 100644 index 00000000..58df0db7 Binary files /dev/null and b/compare-for-test/qtest/compare/diff-id.pdf differ diff --git a/compare-for-test/qtest/compare/zlib-new-id.pdf b/compare-for-test/qtest/compare/zlib-new-id.pdf new file mode 100644 index 00000000..8618f369 Binary files /dev/null and b/compare-for-test/qtest/compare/zlib-new-id.pdf differ diff --git a/compare-for-test/qtest/compare/zlib-new-id1.pdf b/compare-for-test/qtest/compare/zlib-new-id1.pdf new file mode 100644 index 00000000..5dd7a823 Binary files /dev/null and b/compare-for-test/qtest/compare/zlib-new-id1.pdf differ diff --git a/compare-for-test/qtest/compare/zlib-new-id2.pdf b/compare-for-test/qtest/compare/zlib-new-id2.pdf new file mode 100644 index 00000000..1dd13b89 Binary files /dev/null and b/compare-for-test/qtest/compare/zlib-new-id2.pdf differ -- cgit v1.2.3-54-g00ecf