From 47f33cec2582101485ed93d041d069118a62b5cf Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 31 Jan 2022 15:56:05 -0500 Subject: QPDFJob: add test cases --- libqpdf/QPDFJob_json.cc | 8 ++ qpdf/qpdf.testcov | 7 ++ qpdf/qtest/qpdf.test | 87 ++++++++++++++++++ qpdf/qtest/qpdf/bad-bare-option-false-json.out | 10 ++ qpdf/qtest/qpdf/bad-choice-mismatch-json.out | 10 ++ .../qpdf/bad-encrypt-duplicate-key-length-json.out | 10 ++ .../qpdf/bad-encrypt-missing-password-json.out | 10 ++ qpdf/qtest/qpdf/bad-encrypt-no-key-length-json.out | 10 ++ qpdf/qtest/qpdf/bad-json-bare-option-false.json | 7 ++ qpdf/qtest/qpdf/bad-json-choice-mismatch.json | 7 ++ .../bad-json-encrypt-duplicate-key-length.json | 14 +++ .../qpdf/bad-json-encrypt-missing-password.json | 11 +++ .../qtest/qpdf/bad-json-encrypt-no-key-length.json | 10 ++ qpdf/qtest/qpdf/bad-json-error-json.out | 10 ++ qpdf/qtest/qpdf/bad-json-json-error.json | 10 ++ qpdf/qtest/qpdf/bad-json-pages-no-file.json | 9 ++ qpdf/qtest/qpdf/bad-json-schema-error.json | 12 +++ qpdf/qtest/qpdf/bad-pages-no-file-json.out | 10 ++ qpdf/qtest/qpdf/bad-schema-error-json.out | 11 +++ qpdf/qtest/qpdf/job-api.out | 8 ++ qpdf/qtest/qpdf/job-json-add-attachments.json | 27 ++++++ qpdf/qtest/qpdf/job-json-add-attachments.pdf | Bin 0 -> 1715 bytes qpdf/qtest/qpdf/job-json-choice-match.json | 12 +++ qpdf/qtest/qpdf/job-json-choice-match.pdf | Bin 0 -> 743 bytes qpdf/qtest/qpdf/job-json-copy-attachments.json | 26 ++++++ qpdf/qtest/qpdf/job-json-copy-attachments.pdf | Bin 0 -> 2527 bytes qpdf/qtest/qpdf/job-json-empty-input.json | 23 +++++ qpdf/qtest/qpdf/job-json-empty-input.pdf | Bin 0 -> 2546 bytes qpdf/qtest/qpdf/job-json-encrypt-128.json | 19 ++++ qpdf/qtest/qpdf/job-json-encrypt-128.pdf | Bin 0 -> 7439 bytes .../job-json-encrypt-256-with-restrictions.json | 20 ++++ .../job-json-encrypt-256-with-restrictions.out | 16 ++++ qpdf/qtest/qpdf/job-json-encrypt-40.json | 19 ++++ qpdf/qtest/qpdf/job-json-encrypt-40.pdf | 39 ++++++++ qpdf/qtest/qpdf/job-json-input-file-password.json | 14 +++ qpdf/qtest/qpdf/job-json-input-file-password.pdf | Bin 0 -> 7343 bytes qpdf/qtest/qpdf/job-json-misc-options.json | 13 +++ qpdf/qtest/qpdf/job-json-misc-options.pdf | Bin 0 -> 1285 bytes qpdf/qtest/qpdf/job-json-output.json | 16 ++++ qpdf/qtest/qpdf/job-json-output.out.json | 28 ++++++ qpdf/qtest/qpdf/job-json-replace-input.json | 12 +++ qpdf/qtest/qpdf/job-json-replace-input.pdf | Bin 0 -> 743 bytes .../qpdf/job-json-underlay-overlay-password.json | 23 +++++ .../qpdf/job-json-underlay-overlay-password.pdf | Bin 0 -> 2098 bytes qpdf/qtest/qpdf/job-json-underlay-overlay.json | 23 +++++ qpdf/qtest/qpdf/job-json-underlay-overlay.pdf | Bin 0 -> 17541 bytes qpdf/qtest/qpdf/job-partial-json.out | 3 + qpdf/qtest/qpdf/job-partial.json | 12 +++ qpdf/qtest/qpdf/job-show-encryption.json | 5 + qpdf/qtest/qpdf/test84.pdf | 101 +++++++++++++++++++++ qpdf/test_driver.cc | 82 ++++++++++++++++- 51 files changed, 802 insertions(+), 2 deletions(-) create mode 100644 qpdf/qtest/qpdf/bad-bare-option-false-json.out create mode 100644 qpdf/qtest/qpdf/bad-choice-mismatch-json.out create mode 100644 qpdf/qtest/qpdf/bad-encrypt-duplicate-key-length-json.out create mode 100644 qpdf/qtest/qpdf/bad-encrypt-missing-password-json.out create mode 100644 qpdf/qtest/qpdf/bad-encrypt-no-key-length-json.out create mode 100644 qpdf/qtest/qpdf/bad-json-bare-option-false.json create mode 100644 qpdf/qtest/qpdf/bad-json-choice-mismatch.json create mode 100644 qpdf/qtest/qpdf/bad-json-encrypt-duplicate-key-length.json create mode 100644 qpdf/qtest/qpdf/bad-json-encrypt-missing-password.json create mode 100644 qpdf/qtest/qpdf/bad-json-encrypt-no-key-length.json create mode 100644 qpdf/qtest/qpdf/bad-json-error-json.out create mode 100644 qpdf/qtest/qpdf/bad-json-json-error.json create mode 100644 qpdf/qtest/qpdf/bad-json-pages-no-file.json create mode 100644 qpdf/qtest/qpdf/bad-json-schema-error.json create mode 100644 qpdf/qtest/qpdf/bad-pages-no-file-json.out create mode 100644 qpdf/qtest/qpdf/bad-schema-error-json.out create mode 100644 qpdf/qtest/qpdf/job-api.out create mode 100644 qpdf/qtest/qpdf/job-json-add-attachments.json create mode 100644 qpdf/qtest/qpdf/job-json-add-attachments.pdf create mode 100644 qpdf/qtest/qpdf/job-json-choice-match.json create mode 100644 qpdf/qtest/qpdf/job-json-choice-match.pdf create mode 100644 qpdf/qtest/qpdf/job-json-copy-attachments.json create mode 100644 qpdf/qtest/qpdf/job-json-copy-attachments.pdf create mode 100644 qpdf/qtest/qpdf/job-json-empty-input.json create mode 100644 qpdf/qtest/qpdf/job-json-empty-input.pdf create mode 100644 qpdf/qtest/qpdf/job-json-encrypt-128.json create mode 100644 qpdf/qtest/qpdf/job-json-encrypt-128.pdf create mode 100644 qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.json create mode 100644 qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.out create mode 100644 qpdf/qtest/qpdf/job-json-encrypt-40.json create mode 100644 qpdf/qtest/qpdf/job-json-encrypt-40.pdf create mode 100644 qpdf/qtest/qpdf/job-json-input-file-password.json create mode 100644 qpdf/qtest/qpdf/job-json-input-file-password.pdf create mode 100644 qpdf/qtest/qpdf/job-json-misc-options.json create mode 100644 qpdf/qtest/qpdf/job-json-misc-options.pdf create mode 100644 qpdf/qtest/qpdf/job-json-output.json create mode 100644 qpdf/qtest/qpdf/job-json-output.out.json create mode 100644 qpdf/qtest/qpdf/job-json-replace-input.json create mode 100644 qpdf/qtest/qpdf/job-json-replace-input.pdf create mode 100644 qpdf/qtest/qpdf/job-json-underlay-overlay-password.json create mode 100644 qpdf/qtest/qpdf/job-json-underlay-overlay-password.pdf create mode 100644 qpdf/qtest/qpdf/job-json-underlay-overlay.json create mode 100644 qpdf/qtest/qpdf/job-json-underlay-overlay.pdf create mode 100644 qpdf/qtest/qpdf/job-partial-json.out create mode 100644 qpdf/qtest/qpdf/job-partial.json create mode 100644 qpdf/qtest/qpdf/job-show-encryption.json create mode 100644 qpdf/qtest/qpdf/test84.pdf diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc index da1e19e2..2da427c3 100644 --- a/libqpdf/QPDFJob_json.cc +++ b/libqpdf/QPDFJob_json.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -108,6 +109,7 @@ Handlers::addBare(bare_handler_t fn) jh->addBoolHandler([this, fn](std::string const& path, bool v){ if (! v) { + QTC::TC("qpdf", "QPDFJob json bare not true"); usage(path + ": value must be true"); } else @@ -140,12 +142,14 @@ Handlers::addChoices(char const** choices, { if (strcmp(*i, p) == 0) { + QTC::TC("qpdf", "QPDFJob json choice match"); matches = true; break; } } if (! matches) { + QTC::TC("qpdf", "QPDFJob json choice mismatch"); std::ostringstream msg; msg << path + ": unexpected value; expected one of "; bool first = true; @@ -307,6 +311,7 @@ Handlers::beginOutputOptionsEncrypt(JSON j) { if (key_len != 0) { + QTC::TC("qpdf", "QPDFJob json encrypt duplicate key length"); usage("exactly one of 40bit, 128bit, or 256bit must be given"); } key_len = QUtil::string_to_int(key.c_str()); @@ -322,12 +327,14 @@ Handlers::beginOutputOptionsEncrypt(JSON j) }); if (key_len == 0) { + QTC::TC("qpdf", "QPDFJob json encrypt no key length"); usage("exactly one of 40bit, 128bit, or 256bit must be given;" " an empty dictionary may be supplied for one of them" " to set the key length without imposing any restrictions"); } if (! (user_password_seen && owner_password_seen)) { + QTC::TC("qpdf", "QPDFJob json encrypt missing password"); usage("the user and owner password are both required; use the empty" " string for the user password if you don't want a password"); } @@ -550,6 +557,7 @@ Handlers::beginOptionsPages(JSON j) }); if (! file_seen) { + QTC::TC("qpdf", "QPDFJob json pages no file"); usage("file is required in page specification"); } this->c_pages->pageSpec( diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index f3936bd4..6648815a 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -630,3 +630,10 @@ qpdf check password password correct 0 qpdf check password not encrypted 0 QPDFJob_config password file 0 QPDFJob_config password stdin 0 +QPDFJob json bare not true 0 +QPDFJob json choice mismatch 0 +QPDFJob json choice match 0 +QPDFJob json encrypt no key length 0 +QPDFJob json encrypt duplicate key length 0 +QPDFJob json encrypt missing password 0 +QPDFJob json pages no file 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index f847cee8..040567cf 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -370,6 +370,93 @@ foreach my $f (@dangling) {$td->FILE => "a.pdf"}, {$td->FILE => "$f-dangling-out.pdf"}); } +show_ntests(); +# ---------- +$td->notify("--- QPDFJob Tests ---"); + +open(F, ">auto-txt") or die; +print F "from file"; +close(F); + +my @bad_json = ( + "bare-option-false", + "choice-mismatch", + "encrypt-duplicate-key-length", + "encrypt-missing-password", + "encrypt-no-key-length", + "pages-no-file", + "schema-error", + "json-error" + ); +my @good_json = ( + "choice-match", + "input-file-password", + "empty-input", + "replace-input", + "encrypt-40", + "encrypt-128", + "encrypt-256-with-restrictions", + "add-attachments", + "copy-attachments", + "underlay-overlay", + "underlay-overlay-password", + "misc-options", + ); +$n_tests += 4 + scalar(@bad_json) + (2 * scalar(@good_json)); + + +foreach my $i (@bad_json) +{ + $td->runtest("QPDFJob bad json: $i", + {$td->COMMAND => "qpdf --job-json-file=bad-json-$i.json"}, + {$td->FILE => "bad-$i-json.out", $td->EXIT_STATUS => 2}, + $td->NORMALIZE_NEWLINES); +} + +foreach my $i (@good_json) +{ + if ($i eq 'replace-input') + { + copy("minimal.pdf", 'a.pdf'); + } + $td->runtest("QPDFJob good json: $i", + {$td->COMMAND => "qpdf --job-json-file=job-json-$i.json"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + if ($i =~ m/encrypt-256/) + { + $td->runtest("check encryption $i", + {$td->COMMAND => + "qpdf a.pdf --password=u" . + " --job-json-file=job-show-encryption.json"}, + {$td->FILE => "job-json-$i.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + } + else + { + $td->runtest("check good json $i output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "job-json-$i.pdf"}); + } +} + + +$td->runtest("QPDFJob json partial", + {$td->COMMAND => "test_driver 83 - job-partial.json"}, + {$td->FILE => "job-partial-json.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("QPDFJob API", + {$td->COMMAND => "test_driver 84 -"}, + {$td->FILE => "job-api.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "test84.pdf"}); +$td->runtest("json output from job", + {$td->COMMAND => "qpdf --job-json-file=job-json-output.json"}, + {$td->FILE => "job-json-output.out.json", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + show_ntests(); # ---------- $td->notify("--- Form Tests ---"); diff --git a/qpdf/qtest/qpdf/bad-bare-option-false-json.out b/qpdf/qtest/qpdf/bad-bare-option-false-json.out new file mode 100644 index 00000000..6fa389f7 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-bare-option-false-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-bare-option-false.json: .output.options.qdf: value must be true +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-choice-mismatch-json.out b/qpdf/qtest/qpdf/bad-choice-mismatch-json.out new file mode 100644 index 00000000..16f7aac9 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-choice-mismatch-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-choice-mismatch.json: .output.options.objectStreams: unexpected value; expected one of disable, preserve, generate +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-encrypt-duplicate-key-length-json.out b/qpdf/qtest/qpdf/bad-encrypt-duplicate-key-length-json.out new file mode 100644 index 00000000..20490205 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-encrypt-duplicate-key-length-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-encrypt-duplicate-key-length.json: exactly one of 40bit, 128bit, or 256bit must be given +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-encrypt-missing-password-json.out b/qpdf/qtest/qpdf/bad-encrypt-missing-password-json.out new file mode 100644 index 00000000..41e09114 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-encrypt-missing-password-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-encrypt-missing-password.json: the user and owner password are both required; use the empty string for the user password if you don't want a password +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-encrypt-no-key-length-json.out b/qpdf/qtest/qpdf/bad-encrypt-no-key-length-json.out new file mode 100644 index 00000000..475937c6 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-encrypt-no-key-length-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-encrypt-no-key-length.json: exactly one of 40bit, 128bit, or 256bit must be given; an empty dictionary may be supplied for one of them to set the key length without imposing any restrictions +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-json-bare-option-false.json b/qpdf/qtest/qpdf/bad-json-bare-option-false.json new file mode 100644 index 00000000..c42380a9 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-bare-option-false.json @@ -0,0 +1,7 @@ +{ + "output": { + "options": { + "qdf": false + } + } +} diff --git a/qpdf/qtest/qpdf/bad-json-choice-mismatch.json b/qpdf/qtest/qpdf/bad-json-choice-mismatch.json new file mode 100644 index 00000000..45143a14 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-choice-mismatch.json @@ -0,0 +1,7 @@ +{ + "output": { + "options": { + "objectStreams": "potato" + } + } +} diff --git a/qpdf/qtest/qpdf/bad-json-encrypt-duplicate-key-length.json b/qpdf/qtest/qpdf/bad-json-encrypt-duplicate-key-length.json new file mode 100644 index 00000000..4afa96fd --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-encrypt-duplicate-key-length.json @@ -0,0 +1,14 @@ +{ + "output": { + "options": { + "encrypt": { + "userPassword": "", + "ownerPassword": "someOwnerThing", + "256bit": { + }, + "128bit": { + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/bad-json-encrypt-missing-password.json b/qpdf/qtest/qpdf/bad-json-encrypt-missing-password.json new file mode 100644 index 00000000..8c9a14a5 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-encrypt-missing-password.json @@ -0,0 +1,11 @@ +{ + "output": { + "options": { + "encrypt": { + "userPassword": "", + "256bit": { + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/bad-json-encrypt-no-key-length.json b/qpdf/qtest/qpdf/bad-json-encrypt-no-key-length.json new file mode 100644 index 00000000..997dfe79 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-encrypt-no-key-length.json @@ -0,0 +1,10 @@ +{ + "output": { + "options": { + "encrypt": { + "userPassword": "", + "ownerPassword": "someOwnerThing" + } + } + } +} diff --git a/qpdf/qtest/qpdf/bad-json-error-json.out b/qpdf/qtest/qpdf/bad-json-error-json.out new file mode 100644 index 00000000..e8933d72 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-error-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-json-error.json: JSON: offset 130: unexpected dictionary end delimiter +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-json-json-error.json b/qpdf/qtest/qpdf/bad-json-json-error.json new file mode 100644 index 00000000..439434a8 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-json-error.json @@ -0,0 +1,10 @@ +{ + "output": { + "options": { + "encrypt": { + "userPassword": "", + "ownerPassword": "someOwnerThing", + } + } + } +} diff --git a/qpdf/qtest/qpdf/bad-json-pages-no-file.json b/qpdf/qtest/qpdf/bad-json-pages-no-file.json new file mode 100644 index 00000000..5d855a32 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-pages-no-file.json @@ -0,0 +1,9 @@ +{ + "options": { + "pages": [ + { + "range": "1-z" + } + ] + } +} diff --git a/qpdf/qtest/qpdf/bad-json-schema-error.json b/qpdf/qtest/qpdf/bad-json-schema-error.json new file mode 100644 index 00000000..d4d289ac --- /dev/null +++ b/qpdf/qtest/qpdf/bad-json-schema-error.json @@ -0,0 +1,12 @@ +{ + "output": { + "potato": { + "encrypt": { + "userPassword": "", + "ownerPassword": "someOwnerThing", + "256bit": { + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/bad-pages-no-file-json.out b/qpdf/qtest/qpdf/bad-pages-no-file-json.out new file mode 100644 index 00000000..35b0f9c0 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-pages-no-file-json.out @@ -0,0 +1,10 @@ + +qpdf: error with job-json file bad-json-pages-no-file.json: file is required in page specification +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/bad-schema-error-json.out b/qpdf/qtest/qpdf/bad-schema-error-json.out new file mode 100644 index 00000000..700a4099 --- /dev/null +++ b/qpdf/qtest/qpdf/bad-schema-error-json.out @@ -0,0 +1,11 @@ + +qpdf: error with job-json file bad-json-schema-error.json: qpdf: job json has errors: + json key ".output": key "potato" is not present in schema but appears in object +Run qpdf--job-json-help for information on the file format. + +For help: + qpdf--help=usage usage information + qpdf--help=topic help on a topic + qpdf--help=--option help on an option + qpdf--help general help and a topic list + diff --git a/qpdf/qtest/qpdf/job-api.out b/qpdf/qtest/qpdf/job-api.out new file mode 100644 index 00000000..47b00ecf --- /dev/null +++ b/qpdf/qtest/qpdf/job-api.out @@ -0,0 +1,8 @@ +normal +error caught by check +finished config +usage: an input file name is required +error caught by run +finished config +usage: an input file name is required +test 84 done diff --git a/qpdf/qtest/qpdf/job-json-add-attachments.json b/qpdf/qtest/qpdf/job-json-add-attachments.json new file mode 100644 index 00000000..9eb03ca4 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-add-attachments.json @@ -0,0 +1,27 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true + } + }, + "options": { + "addAttachment": [ + { + "file": "auto-txt", + "moddate": "D:20220131134246-05'00'", + "creationdate": "D:20220131134246-05'00'" + }, + { + "file": "auto-txt", + "moddate": "D:20220131134246-05'00'", + "creationdate": "D:20220131134246-05'00'", + "filename": "auto2", + "key": "auto2-key" + } + ] + } +} diff --git a/qpdf/qtest/qpdf/job-json-add-attachments.pdf b/qpdf/qtest/qpdf/job-json-add-attachments.pdf new file mode 100644 index 00000000..f4db626b Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-add-attachments.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-choice-match.json b/qpdf/qtest/qpdf/job-json-choice-match.json new file mode 100644 index 00000000..555e0f5b --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-choice-match.json @@ -0,0 +1,12 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "deterministicId": true, + "objectStreams": "generate" + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-choice-match.pdf b/qpdf/qtest/qpdf/job-json-choice-match.pdf new file mode 100644 index 00000000..b0a7e2e9 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-choice-match.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-copy-attachments.json b/qpdf/qtest/qpdf/job-json-copy-attachments.json new file mode 100644 index 00000000..7aa531b6 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-copy-attachments.json @@ -0,0 +1,26 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true + } + }, + "options": { + "copyAttachmentsFrom": [ + { + "file": "job-json-add-attachments.pdf" + }, + { + "file": "20-pages.pdf", + "password": "user" + }, + { + "file": "job-json-add-attachments.pdf", + "prefix": "p-" + } + ] + } +} diff --git a/qpdf/qtest/qpdf/job-json-copy-attachments.pdf b/qpdf/qtest/qpdf/job-json-copy-attachments.pdf new file mode 100644 index 00000000..ab49f624 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-copy-attachments.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-empty-input.json b/qpdf/qtest/qpdf/job-json-empty-input.json new file mode 100644 index 00000000..c124169c --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-empty-input.json @@ -0,0 +1,23 @@ +{ + "input": { + "empty": true + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true + } + }, + "options": { + "pages": [ + { + "file": "minimal.pdf" + }, + { + "file": "20-pages.pdf", + "password": "user", + "range": "1-5" + } + ] + } +} diff --git a/qpdf/qtest/qpdf/job-json-empty-input.pdf b/qpdf/qtest/qpdf/job-json-empty-input.pdf new file mode 100644 index 00000000..b93a9113 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-empty-input.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-encrypt-128.json b/qpdf/qtest/qpdf/job-json-encrypt-128.json new file mode 100644 index 00000000..318dfd6f --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-encrypt-128.json @@ -0,0 +1,19 @@ +{ + "input": { + "file": "fxo-blue.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true, + "staticAesIv": true, + "encrypt": { + "userPassword": "u", + "ownerPassword": "o", + "128bit": { + "useAes": "y" + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-encrypt-128.pdf b/qpdf/qtest/qpdf/job-json-encrypt-128.pdf new file mode 100644 index 00000000..99d6a45d Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-encrypt-128.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.json b/qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.json new file mode 100644 index 00000000..d9b8d282 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.json @@ -0,0 +1,20 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true, + "staticAesIv": true, + "encrypt": { + "userPassword": "u", + "ownerPassword": "o", + "256bit": { + "print": "low", + "modify": "form" + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.out b/qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.out new file mode 100644 index 00000000..8773ab58 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.out @@ -0,0 +1,16 @@ +R = 6 +P = -2092 +User password = u +Supplied password is user password +extract for accessibility: allowed +extract for any purpose: allowed +print low resolution: allowed +print high resolution: not allowed +modify document assembly: allowed +modify forms: allowed +modify annotations: not allowed +modify other: not allowed +modify anything: not allowed +stream encryption method: AESv3 +string encryption method: AESv3 +file encryption method: AESv3 diff --git a/qpdf/qtest/qpdf/job-json-encrypt-40.json b/qpdf/qtest/qpdf/job-json-encrypt-40.json new file mode 100644 index 00000000..785bbe5d --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-encrypt-40.json @@ -0,0 +1,19 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true, + "encrypt": { + "userPassword": "u", + "ownerPassword": "o", + "40bit": {} + } + } + }, + "options": { + "allowWeakCrypto": true + } +} diff --git a/qpdf/qtest/qpdf/job-json-encrypt-40.pdf b/qpdf/qtest/qpdf/job-json-encrypt-40.pdf new file mode 100644 index 00000000..3e64a2a2 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-encrypt-40.pdf @@ -0,0 +1,39 @@ +%PDF-1.3 +%¿÷¢þ +1 0 obj +<< /Pages 2 0 R /Type /Catalog >> +endobj +2 0 obj +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +3 0 obj +<< /Contents 4 0 R /MediaBox [ 0 0 612 792 ] /Parent 2 0 R /Resources << /Font << /F1 5 0 R >> /ProcSet 6 0 R >> /Type /Page >> +endobj +4 0 obj +<< /Length 48 /Filter /FlateDecode >> +stream +´æ@!Ò©¯ e›îºŠ\ †Në‘ §ŽK3Ù3­GAG5â‚|'j4oeendstream +endobj +5 0 obj +<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> +endobj +6 0 obj +[ /PDF /Text ] +endobj +7 0 obj +<< /Filter /Standard /Length 40 /O <853fee3f6550fc3bc212797eaed99cc9be53347583a738e25fdfb1242bf93366> /P -4 /R 2 /U <5c78313a3f3f17efd751ded6e1f69b40e384ea413e49df3af00c031a9f4185c0> /V 1 >> +endobj +xref +0 8 +0000000000 65535 f +0000000015 00000 n +0000000064 00000 n +0000000123 00000 n +0000000266 00000 n +0000000384 00000 n +0000000491 00000 n +0000000521 00000 n +trailer << /Root 1 0 R /Size 8 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] /Encrypt 7 0 R >> +startxref +727 +%%EOF diff --git a/qpdf/qtest/qpdf/job-json-input-file-password.json b/qpdf/qtest/qpdf/job-json-input-file-password.json new file mode 100644 index 00000000..8f22aad0 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-input-file-password.json @@ -0,0 +1,14 @@ +{ + "input": { + "file": "20-pages.pdf", + "password": "user" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true, + "staticAesIv": true, + "compressStreams": "n" + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-input-file-password.pdf b/qpdf/qtest/qpdf/job-json-input-file-password.pdf new file mode 100644 index 00000000..dc56bf36 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-input-file-password.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-misc-options.json b/qpdf/qtest/qpdf/job-json-misc-options.json new file mode 100644 index 00000000..3056f2fe --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-misc-options.json @@ -0,0 +1,13 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true, + "linearize": true, + "compressStreams": "n" + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-misc-options.pdf b/qpdf/qtest/qpdf/job-json-misc-options.pdf new file mode 100644 index 00000000..be88f1e1 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-misc-options.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-output.json b/qpdf/qtest/qpdf/job-json-output.json new file mode 100644 index 00000000..7110c725 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-output.json @@ -0,0 +1,16 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "inspect": { + "json": "1", + "jsonKey": [ + "pages", + "objects" + ], + "jsonObject": [ + "trailer", + "5" + ] + } +} diff --git a/qpdf/qtest/qpdf/job-json-output.out.json b/qpdf/qtest/qpdf/job-json-output.out.json new file mode 100644 index 00000000..e06c1a74 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-output.out.json @@ -0,0 +1,28 @@ +{ + "objects": { + "5 0 R": [ + "/PDF", + "/Text" + ], + "trailer": { + "/Root": "1 0 R", + "/Size": 7 + } + }, + "pages": [ + { + "contents": [ + "4 0 R" + ], + "images": [], + "label": null, + "object": "3 0 R", + "outlines": [], + "pageposfrom1": 1 + } + ], + "parameters": { + "decodelevel": "generalized" + }, + "version": 1 +} diff --git a/qpdf/qtest/qpdf/job-json-replace-input.json b/qpdf/qtest/qpdf/job-json-replace-input.json new file mode 100644 index 00000000..1e45acfe --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-replace-input.json @@ -0,0 +1,12 @@ +{ + "input": { + "file": "a.pdf" + }, + "output": { + "replaceInput": true, + "options": { + "staticId": true, + "objectStreams": "generate" + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-replace-input.pdf b/qpdf/qtest/qpdf/job-json-replace-input.pdf new file mode 100644 index 00000000..a121ef24 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-replace-input.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-underlay-overlay-password.json b/qpdf/qtest/qpdf/job-json-underlay-overlay-password.json new file mode 100644 index 00000000..304c1654 --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-underlay-overlay-password.json @@ -0,0 +1,23 @@ +{ + "input": { + "file": "minimal.pdf" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true + } + }, + "options": { + "underlay": { + "file": "20-pages.pdf", + "password": "user", + "from": "5" + }, + "overlay": { + "file": "job-json-encrypt-128.pdf", + "password": "o", + "from": "7" + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-underlay-overlay-password.pdf b/qpdf/qtest/qpdf/job-json-underlay-overlay-password.pdf new file mode 100644 index 00000000..31c0e1f8 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-underlay-overlay-password.pdf differ diff --git a/qpdf/qtest/qpdf/job-json-underlay-overlay.json b/qpdf/qtest/qpdf/job-json-underlay-overlay.json new file mode 100644 index 00000000..ebf4c1ed --- /dev/null +++ b/qpdf/qtest/qpdf/job-json-underlay-overlay.json @@ -0,0 +1,23 @@ +{ + "input": { + "file": "20-pages.pdf", + "password": "owner" + }, + "output": { + "file": "a.pdf", + "options": { + "staticId": true, + "decrypt": true + } + }, + "options": { + "underlay": { + "file": "fxo-green.pdf" + }, + "overlay": { + "file": "fxo-red.pdf", + "from": "1,2", + "repeat": "3" + } + } +} diff --git a/qpdf/qtest/qpdf/job-json-underlay-overlay.pdf b/qpdf/qtest/qpdf/job-json-underlay-overlay.pdf new file mode 100644 index 00000000..d0327ab4 Binary files /dev/null and b/qpdf/qtest/qpdf/job-json-underlay-overlay.pdf differ diff --git a/qpdf/qtest/qpdf/job-partial-json.out b/qpdf/qtest/qpdf/job-partial-json.out new file mode 100644 index 00000000..bc86596f --- /dev/null +++ b/qpdf/qtest/qpdf/job-partial-json.out @@ -0,0 +1,3 @@ +calling initializeFromJson +usage: an input file name is required +test 83 done diff --git a/qpdf/qtest/qpdf/job-partial.json b/qpdf/qtest/qpdf/job-partial.json new file mode 100644 index 00000000..ff2587c1 --- /dev/null +++ b/qpdf/qtest/qpdf/job-partial.json @@ -0,0 +1,12 @@ +{ + "output": { + "options": { + "encrypt": { + "userPassword": "", + "ownerPassword": "", + "256bit": { + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/job-show-encryption.json b/qpdf/qtest/qpdf/job-show-encryption.json new file mode 100644 index 00000000..0a785ec6 --- /dev/null +++ b/qpdf/qtest/qpdf/job-show-encryption.json @@ -0,0 +1,5 @@ +{ + "inspect": { + "showEncryption": true + } +} diff --git a/qpdf/qtest/qpdf/test84.pdf b/qpdf/qtest/qpdf/test84.pdf new file mode 100644 index 00000000..0d065c16 --- /dev/null +++ b/qpdf/qtest/qpdf/test84.pdf @@ -0,0 +1,101 @@ +%PDF-1.3 +%¿÷¢þ +%QDF-1.0 + +%% Original object ID: 1 0 +1 0 obj +<< + /Pages 2 0 R + /Type /Catalog +>> +endobj + +%% Original object ID: 2 0 +2 0 obj +<< + /Count 1 + /Kids [ + 3 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +%% Original object ID: 3 0 +3 0 obj +<< + /Contents 4 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 6 0 R + >> + /ProcSet 7 0 R + >> + /Type /Page +>> +endobj + +%% Contents for page 1 +%% Original object ID: 4 0 +4 0 obj +<< + /Length 5 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato) Tj +ET +endstream +endobj + +5 0 obj +44 +endobj + +%% Original object ID: 6 0 +6 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Original object ID: 5 0 +7 0 obj +[ + /PDF + /Text +] +endobj + +xref +0 8 +0000000000 65535 f +0000000052 00000 n +0000000133 00000 n +0000000242 00000 n +0000000484 00000 n +0000000583 00000 n +0000000629 00000 n +0000000774 00000 n +trailer << + /Root 1 0 R + /Size 8 + /ID [] +>> +startxref +809 +%%EOF diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 65b2038c..4158b030 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -3140,6 +3142,81 @@ static void test_82(QPDF& pdf, char const* arg2) assert(! str.isOrHasName("/Marvin")); } +static void test_83(QPDF& pdf, char const* arg2) +{ + // Test QPDFJob json with partial = false. For testing with + // partial = true, we just use qpdf --job-json-file. + + QPDFJob j; + PointerHolder file_buf; + size_t size; + QUtil::read_file_into_memory(arg2, file_buf, size); + try + { + std::cout << "calling initializeFromJson" << std::endl; + j.initializeFromJson(std::string(file_buf.getPointer(), size)); + std::cout << "called initializeFromJson" << std::endl; + } + catch (QPDFUsage& e) + { + std::cerr << "usage: " << e.what() << std::endl; + } + catch (std::exception& e) + { + std::cerr << "exception: " << e.what() << std::endl; + } +} + +static void test_84(QPDF& pdf, char const* arg2) +{ + // Test QPDFJob API + + std::cout << "normal" << std::endl; + { + QPDFJob j; + j.config() + ->inputFile("minimal.pdf") + ->outputFile("a.pdf") + ->qdf() + ->deterministicId() + ->objectStreams("preserve") + ->checkConfiguration(); + j.run(); + } + + std::cout << "error caught by check" << std::endl; + try + { + QPDFJob j; + j.config() + ->outputFile("a.pdf") + ->qdf(); + std::cout << "finished config" << std::endl; + j.checkConfiguration(); + assert(false); + } + catch (QPDFUsage& e) + { + std::cout << "usage: " << e.what() << std::endl; + } + + std::cout << "error caught by run" << std::endl; + try + { + QPDFJob j; + j.config() + ->outputFile("a.pdf") + ->qdf(); + std::cout << "finished config" << std::endl; + j.run(); + assert(false); + } + catch (QPDFUsage& e) + { + std::cout << "usage: " << e.what() << std::endl; + } +} + void runtest(int n, char const* filename1, char const* arg2) { // Most tests here are crafted to work on specific files. Look at @@ -3206,7 +3283,7 @@ void runtest(int n, char const* filename1, char const* arg2) pdf.processMemoryFile((std::string(filename1) + ".pdf").c_str(), p, size); } - else if ((n == 61) || (n == 81)) + else if ((n == 61) || (n == 81) || (n == 83) || (n == 84)) { // Ignore filename argument entirely } @@ -3253,7 +3330,8 @@ void runtest(int n, char const* filename1, char const* arg2) {68, test_68}, {69, test_69}, {70, test_70}, {71, test_71}, {72, test_72}, {73, test_73}, {74, test_74}, {75, test_75}, {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, - {80, test_80}, {81, test_81}, {82, test_82}, + {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, + {84, test_84}, }; auto fn = test_functions.find(n); -- cgit v1.2.3-54-g00ecf