aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-01-31 21:56:05 +0100
committerJay Berkenbilt <ejb@ql.org>2022-01-31 21:57:45 +0100
commit47f33cec2582101485ed93d041d069118a62b5cf (patch)
treea853eb0319a79d1eefef78c38d33c602bcf49ee3
parente3506253f17137d6d4831b4615d74689446da72c (diff)
downloadqpdf-47f33cec2582101485ed93d041d069118a62b5cf.tar.zst
QPDFJob: add test cases
-rw-r--r--libqpdf/QPDFJob_json.cc8
-rw-r--r--qpdf/qpdf.testcov7
-rw-r--r--qpdf/qtest/qpdf.test87
-rw-r--r--qpdf/qtest/qpdf/bad-bare-option-false-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-choice-mismatch-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-encrypt-duplicate-key-length-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-encrypt-missing-password-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-encrypt-no-key-length-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-json-bare-option-false.json7
-rw-r--r--qpdf/qtest/qpdf/bad-json-choice-mismatch.json7
-rw-r--r--qpdf/qtest/qpdf/bad-json-encrypt-duplicate-key-length.json14
-rw-r--r--qpdf/qtest/qpdf/bad-json-encrypt-missing-password.json11
-rw-r--r--qpdf/qtest/qpdf/bad-json-encrypt-no-key-length.json10
-rw-r--r--qpdf/qtest/qpdf/bad-json-error-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-json-json-error.json10
-rw-r--r--qpdf/qtest/qpdf/bad-json-pages-no-file.json9
-rw-r--r--qpdf/qtest/qpdf/bad-json-schema-error.json12
-rw-r--r--qpdf/qtest/qpdf/bad-pages-no-file-json.out10
-rw-r--r--qpdf/qtest/qpdf/bad-schema-error-json.out11
-rw-r--r--qpdf/qtest/qpdf/job-api.out8
-rw-r--r--qpdf/qtest/qpdf/job-json-add-attachments.json27
-rw-r--r--qpdf/qtest/qpdf/job-json-add-attachments.pdfbin0 -> 1715 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-choice-match.json12
-rw-r--r--qpdf/qtest/qpdf/job-json-choice-match.pdfbin0 -> 743 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-copy-attachments.json26
-rw-r--r--qpdf/qtest/qpdf/job-json-copy-attachments.pdfbin0 -> 2527 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-empty-input.json23
-rw-r--r--qpdf/qtest/qpdf/job-json-empty-input.pdfbin0 -> 2546 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-encrypt-128.json19
-rw-r--r--qpdf/qtest/qpdf/job-json-encrypt-128.pdfbin0 -> 7439 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.json20
-rw-r--r--qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.out16
-rw-r--r--qpdf/qtest/qpdf/job-json-encrypt-40.json19
-rw-r--r--qpdf/qtest/qpdf/job-json-encrypt-40.pdf39
-rw-r--r--qpdf/qtest/qpdf/job-json-input-file-password.json14
-rw-r--r--qpdf/qtest/qpdf/job-json-input-file-password.pdfbin0 -> 7343 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-misc-options.json13
-rw-r--r--qpdf/qtest/qpdf/job-json-misc-options.pdfbin0 -> 1285 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-output.json16
-rw-r--r--qpdf/qtest/qpdf/job-json-output.out.json28
-rw-r--r--qpdf/qtest/qpdf/job-json-replace-input.json12
-rw-r--r--qpdf/qtest/qpdf/job-json-replace-input.pdfbin0 -> 743 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-underlay-overlay-password.json23
-rw-r--r--qpdf/qtest/qpdf/job-json-underlay-overlay-password.pdfbin0 -> 2098 bytes
-rw-r--r--qpdf/qtest/qpdf/job-json-underlay-overlay.json23
-rw-r--r--qpdf/qtest/qpdf/job-json-underlay-overlay.pdfbin0 -> 17541 bytes
-rw-r--r--qpdf/qtest/qpdf/job-partial-json.out3
-rw-r--r--qpdf/qtest/qpdf/job-partial.json12
-rw-r--r--qpdf/qtest/qpdf/job-show-encryption.json5
-rw-r--r--qpdf/qtest/qpdf/test84.pdf101
-rw-r--r--qpdf/test_driver.cc82
51 files changed, 802 insertions, 2 deletions
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 <qpdf/JSONHandler.hh>
#include <qpdf/QPDFUsage.hh>
#include <qpdf/QUtil.hh>
+#include <qpdf/QTC.hh>
#include <memory>
#include <stdexcept>
@@ -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
@@ -372,6 +372,93 @@ foreach my $f (@dangling)
}
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 ---");
my @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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-add-attachments.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-choice-match.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-copy-attachments.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-empty-input.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-encrypt-128.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-input-file-password.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-misc-options.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-replace-input.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-underlay-overlay-password.pdf
Binary files 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
--- /dev/null
+++ b/qpdf/qtest/qpdf/job-json-underlay-overlay.pdf
Binary files 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 [<cd76a1aff58b062d8141f81511edbe38><cd76a1aff58b062d8141f81511edbe38>]
+>>
+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 <qpdf/QPDFWriter.hh>
#include <qpdf/QPDFSystemError.hh>
#include <qpdf/QIntC.hh>
+#include <qpdf/QPDFJob.hh>
+#include <qpdf/QPDFUsage.hh>
#include <iostream>
#include <sstream>
#include <algorithm>
@@ -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<char> 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);