Commit 647b9831dc5cb2f2bfe775a8802416cdd51ed59d
1 parent
a238b4b0
Have qpdf-test-compare handle certain /ID differences
Rationale is in comments in the code. Deterministic ID tests explicitly do not use this tool.
Showing
6 changed files
with
37 additions
and
3 deletions
compare-for-test/qpdf-test-compare.cc
| @@ -24,7 +24,7 @@ usage() | @@ -24,7 +24,7 @@ usage() | ||
| 24 | << std::endl | 24 | << std::endl |
| 25 | << "If the files match, the output is the expected file. Otherwise, it is" | 25 | << "If the files match, the output is the expected file. Otherwise, it is" |
| 26 | << std::endl | 26 | << std::endl |
| 27 | - << "the actual file. Read comments in the test suite for rationale." << std::endl; | 27 | + << "the actual file. Read comments in the code for rationale." << std::endl; |
| 28 | exit(2); | 28 | exit(2); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| @@ -50,6 +50,8 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle | @@ -50,6 +50,8 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle | ||
| 50 | return label + ": different types"; | 50 | return label + ": different types"; |
| 51 | } | 51 | } |
| 52 | if (act.isStream()) { | 52 | if (act.isStream()) { |
| 53 | + // Disregard stream lengths. The length of stream data is compared later, and we don't care | ||
| 54 | + // about the length of compressed data as long as the uncompressed data matches. | ||
| 53 | auto act_dict = act.getDict(); | 55 | auto act_dict = act.getDict(); |
| 54 | auto exp_dict = exp.getDict(); | 56 | auto exp_dict = exp.getDict(); |
| 55 | act_dict.removeKey("/Length"); | 57 | act_dict.removeKey("/Length"); |
| @@ -59,6 +61,8 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle | @@ -59,6 +61,8 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle | ||
| 59 | return label + ": stream dictionaries differ"; | 61 | return label + ": stream dictionaries differ"; |
| 60 | } | 62 | } |
| 61 | if (act_dict.getKey("/Type").isNameAndEquals("/XRef")) { | 63 | if (act_dict.getKey("/Type").isNameAndEquals("/XRef")) { |
| 64 | + // Cross-reference streams will generally not match, but we have numerous tests that | ||
| 65 | + // meaningfully ensure that xref streams are correct. | ||
| 62 | QTC::TC("compare", "ignore data for xref stream"); | 66 | QTC::TC("compare", "ignore data for xref stream"); |
| 63 | return ""; | 67 | return ""; |
| 64 | } | 68 | } |
| @@ -103,6 +107,27 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle | @@ -103,6 +107,27 @@ compareObjects(std::string const& label, QPDFObjectHandle act, QPDFObjectHandle | ||
| 103 | return ""; | 107 | return ""; |
| 104 | } | 108 | } |
| 105 | 109 | ||
| 110 | +void | ||
| 111 | +cleanTrailer(QPDFObjectHandle& trailer) | ||
| 112 | +{ | ||
| 113 | + // If the trailer is an object stream, it will have /Length. | ||
| 114 | + trailer.removeKey("/Length"); | ||
| 115 | + // Disregard the second half of /ID. This doesn't have anything directly to do with zlib, but | ||
| 116 | + // lots of tests use --deterministic-id, and that is affected. The deterministic ID tests | ||
| 117 | + // meaningfully exercise that deterministic IDs behave as expected, so for the rest of the | ||
| 118 | + // tests, it's okay to ignore /ID[1]. If the two halves of /ID are the same, ignore both since | ||
| 119 | + // this means qpdf completely generated the /ID rather than preserving the first half. | ||
| 120 | + auto id = trailer.getKey("/ID"); | ||
| 121 | + if (id.isArray() && id.getArrayNItems() == 2) { | ||
| 122 | + auto id0 = id.getArrayItem(0).unparse(); | ||
| 123 | + auto id1 = id.getArrayItem(1).unparse(); | ||
| 124 | + id.setArrayItem(1, "()"_qpdf); | ||
| 125 | + if (id0 == id1) { | ||
| 126 | + id.setArrayItem(0, "()"_qpdf); | ||
| 127 | + } | ||
| 128 | + } | ||
| 129 | +} | ||
| 130 | + | ||
| 106 | std::string | 131 | std::string |
| 107 | compare(char const* actual_filename, char const* expected_filename) | 132 | compare(char const* actual_filename, char const* expected_filename) |
| 108 | { | 133 | { |
| @@ -118,8 +143,8 @@ compare(char const* actual_filename, char const* expected_filename) | @@ -118,8 +143,8 @@ compare(char const* actual_filename, char const* expected_filename) | ||
| 118 | 143 | ||
| 119 | auto act_trailer = actual.getTrailer(); | 144 | auto act_trailer = actual.getTrailer(); |
| 120 | auto exp_trailer = expected.getTrailer(); | 145 | auto exp_trailer = expected.getTrailer(); |
| 121 | - act_trailer.removeKey("/Length"); | ||
| 122 | - exp_trailer.removeKey("/Length"); | 146 | + cleanTrailer(act_trailer); |
| 147 | + cleanTrailer(exp_trailer); | ||
| 123 | auto trailer_diff = compareObjects("trailer", act_trailer, exp_trailer); | 148 | auto trailer_diff = compareObjects("trailer", act_trailer, exp_trailer); |
| 124 | if (!trailer_diff.empty()) { | 149 | if (!trailer_diff.empty()) { |
| 125 | QTC::TC("compare", "different trailer"); | 150 | QTC::TC("compare", "different trailer"); |
compare-for-test/qtest/compare.test
| @@ -52,6 +52,7 @@ my @diff = ( | @@ -52,6 +52,7 @@ my @diff = ( | ||
| 52 | ["diff-data-unc.pdf", "5,0: stream data differs"], | 52 | ["diff-data-unc.pdf", "5,0: stream data differs"], |
| 53 | ["diff-stream-dict.pdf", "4,0: stream dictionaries differ"], | 53 | ["diff-stream-dict.pdf", "4,0: stream dictionaries differ"], |
| 54 | ["diff-object-type.pdf", "6,0: different types"], | 54 | ["diff-object-type.pdf", "6,0: different types"], |
| 55 | + ["diff-id.pdf", "trailer: object contents differ"], | ||
| 55 | ); | 56 | ); |
| 56 | $n_tests += 2 * scalar(@diff); | 57 | $n_tests += 2 * scalar(@diff); |
| 57 | 58 | ||
| @@ -90,4 +91,12 @@ $td->runtest("compare object stream files (same)", | @@ -90,4 +91,12 @@ $td->runtest("compare object stream files (same)", | ||
| 90 | {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare ostream1.pdf ostream2.pdf"}, | 91 | {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare ostream1.pdf ostream2.pdf"}, |
| 91 | {$td->FILE => "ostream2.pdf", $td->EXIT_STATUS => 0}); | 92 | {$td->FILE => "ostream2.pdf", $td->EXIT_STATUS => 0}); |
| 92 | 93 | ||
| 94 | +$n_tests += 2; | ||
| 95 | +$td->runtest("files identical except /ID[1]", | ||
| 96 | + {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare zlib.pdf zlib-new-id.pdf"}, | ||
| 97 | + {$td->FILE => "zlib-new-id.pdf", $td->EXIT_STATUS => 0}); | ||
| 98 | +$td->runtest("/ID[0] = /ID[1]", | ||
| 99 | + {$td->COMMAND => "env QPDF_COMPARE_WHY=1 qpdf-test-compare zlib-new-id1.pdf zlib-new-id2.pdf"}, | ||
| 100 | + {$td->FILE => "zlib-new-id2.pdf", $td->EXIT_STATUS => 0}); | ||
| 101 | + | ||
| 93 | $td->report($n_tests); | 102 | $td->report($n_tests); |
compare-for-test/qtest/compare/diff-id.pdf
0 → 100644
No preview for this file type
compare-for-test/qtest/compare/zlib-new-id.pdf
0 → 100644
No preview for this file type
compare-for-test/qtest/compare/zlib-new-id1.pdf
0 → 100644
No preview for this file type
compare-for-test/qtest/compare/zlib-new-id2.pdf
0 → 100644
No preview for this file type