diff --git a/TODO b/TODO index fbf10c05..eeef3413 100644 --- a/TODO +++ b/TODO @@ -97,10 +97,6 @@ General things to remember: * Add json to the large file tests. -* Object representation tests - * "b:cf80", "b:CF80", "u:Ï€", "u:\u03c0" - * "b:d83edd54", "u:🥔", "u:\ud83e\udd54" - JSON to PDF: Have --json-input and --update-from-json. With --json-input, the json diff --git a/qpdf/qtest/qpdf-json.test b/qpdf/qtest/qpdf-json.test index e6a6a18f..80c73d60 100644 --- a/qpdf/qtest/qpdf-json.test +++ b/qpdf/qtest/qpdf-json.test @@ -67,30 +67,30 @@ foreach my $i (@goodfiles) if (ref($i) eq 'ARRAY') { ($f, $xargs) = @$i; } - $td->runtest("good: $f -> json", + $td->runtest("good: $f -> JSON", {$td->COMMAND => "qpdf $xargs --decode-level=none" . " --json-output=latest $f a.json"}, {$td->STRING => "", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); - $td->runtest("good: $f json -> json", + $td->runtest("good: $f JSON -> JSON", {$td->COMMAND => "qpdf --decode-level=none" . " --json-input --json-output=latest a.json b.json"}, {$td->STRING => "", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); - $td->runtest("good: $f json -> qdf", + $td->runtest("good: $f JSON -> QDF", {$td->COMMAND => "qpdf --qdf --json-input --stream-data=preserve" . " --static-id a.json a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); - $td->runtest("good: $f compare json", + $td->runtest("good: $f compare JSON", {$td->FILE => "a.json"}, {$td->FILE => "b.json"}); my $exp = "json-changed-$f"; if (! -f $exp) { - $td->runtest("good: $f -> qdf", + $td->runtest("good: $f -> aqdf", {$td->COMMAND => "qpdf $xargs --object-streams=disable --qdf" . " --stream-data=preserve --static-id $f b.pdf"}, @@ -115,7 +115,34 @@ foreach my $i (@goodfiles) {$td->FILE => $exp}); # from original PDF } +$n_tests += 6; +$td->runtest("manual JSON to PDF", + {$td->COMMAND => "qpdf --json-input --static-id --qdf" . + " manual-qpdf-json.json a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check manual JSON to PDF", + {$td->FILE => "a.pdf"}, + {$td->FILE => "manual-qpdf-json.pdf"}); +$td->runtest("check manual JSON to PDF to JSON", + {$td->COMMAND => "qpdf --json-output=2 a.pdf -"}, + {$td->FILE => "manual-qpdf-json-pdf.json", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("manual JSON to JSON", + {$td->COMMAND => "qpdf --json-input --json-output=2" . + " manual-qpdf-json.json a.json"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check manual JSON to JSON", + {$td->FILE => "a.json"}, + {$td->FILE => "manual-qpdf-json-out.json"}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check manual JSON to JSON to JSON", + {$td->COMMAND => "qpdf --json-output=2 --json-input a.json -"}, + {$td->FILE => "a.json", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +# QXXXQ file cleanup(); $td->report($n_tests); diff --git a/qpdf/qtest/qpdf/manual-qpdf-json-out.json b/qpdf/qtest/qpdf/manual-qpdf-json-out.json new file mode 100644 index 00000000..a04c98ae --- /dev/null +++ b/qpdf/qtest/qpdf/manual-qpdf-json-out.json @@ -0,0 +1,133 @@ +{ + "qpdf-v2": { + "pdfversion": "2.0", + "maxobjectid": 8, + "objects": { + "obj:1 0 R": { + "value": { + "/Pages": "2 0 R", + "/Type": "/Catalog" + } + }, + "obj:2 0 R": { + "value": { + "/Count": 1, + "/Kids": [ + "3 0 R" + ], + "/Type": "/Pages" + } + }, + "obj:3 0 R": { + "value": { + "/Contents": "4 0 R", + "/MediaBox": [ + 0, + 0, + 612, + 792 + ], + "/Parent": "2 0 R", + "/Resources": { + "/Font": { + "/F1": "6 0 R" + }, + "/ProcSet": "5 0 R" + }, + "/Type": "/Page" + } + }, + "obj:4 0 R": { + "stream": { + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", + "dict": {} + } + }, + "obj:5 0 R": { + "value": [ + "/PDF", + "/Text" + ] + }, + "obj:6 0 R": { + "value": { + "/BaseFont": "/Helvetica", + "/Encoding": "/WinAnsiEncoding", + "/Name": "/F1", + "/Subtype": "/Type1", + "/Type": "/Font" + } + }, + "obj:7 0 R": { + "value": { + "/hex strings": [ + "u:Potato", + "b:01020300040560", + "u:AB" + ], + "/indirect": "8 0 R", + "/names": [ + "/nesting", + "/hex strings", + "/text/plain" + ], + "/nesting": { + "/a": [ + 1, + 2, + { + "/x": "u:y" + }, + [ + "u:z" + ] + ], + "/b": { + "/": "u:legal", + "/a": [ + 1, + 2 + ] + } + }, + "/strings": [ + "u:one", + "b:24a2", + "u:", + "u:()", + "u:(", + "u:)", + "u:a\f\b\t\r\nb", + "u:\"", + "u:\"\"", + "u:\"(\")\"", + "b:410042", + "u:a\nb", + "u:a b", + [ + "u:Ï€", + "u:Ï€", + "u:Ï€", + "u:Ï€" + ], + [ + "u:🥔", + "u:🥔", + "u:🥔" + ] + ] + } + }, + "obj:8 0 R": { + "value": "u:hello" + }, + "trailer": { + "value": { + "/QTest": "7 0 R", + "/Root": "1 0 R", + "/Size": 9 + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json b/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json new file mode 100644 index 00000000..a27f551f --- /dev/null +++ b/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json @@ -0,0 +1,140 @@ +{ + "qpdf-v2": { + "pdfversion": "2.0", + "maxobjectid": 9, + "objects": { + "obj:1 0 R": { + "value": { + "/Pages": "3 0 R", + "/Type": "/Catalog" + } + }, + "obj:2 0 R": { + "value": { + "/hex strings": [ + "u:Potato", + "b:01020300040560", + "u:AB" + ], + "/indirect": "4 0 R", + "/names": [ + "/nesting", + "/hex strings", + "/text/plain" + ], + "/nesting": { + "/a": [ + 1, + 2, + { + "/x": "u:y" + }, + [ + "u:z" + ] + ], + "/b": { + "/": "u:legal", + "/a": [ + 1, + 2 + ] + } + }, + "/strings": [ + "u:one", + "b:24a2", + "u:", + "u:()", + "u:(", + "u:)", + "u:a\f\b\t\r\nb", + "u:\"", + "u:\"\"", + "u:\"(\")\"", + "b:410042", + "u:a\nb", + "u:a b", + [ + "u:Ï€", + "u:Ï€", + "u:Ï€", + "u:Ï€" + ], + [ + "u:🥔", + "u:🥔", + "u:🥔" + ] + ] + } + }, + "obj:3 0 R": { + "value": { + "/Count": 1, + "/Kids": [ + "5 0 R" + ], + "/Type": "/Pages" + } + }, + "obj:4 0 R": { + "value": "u:hello" + }, + "obj:5 0 R": { + "value": { + "/Contents": "6 0 R", + "/MediaBox": [ + 0, + 0, + 612, + 792 + ], + "/Parent": "3 0 R", + "/Resources": { + "/Font": { + "/F1": "8 0 R" + }, + "/ProcSet": "9 0 R" + }, + "/Type": "/Page" + } + }, + "obj:6 0 R": { + "stream": { + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", + "dict": {} + } + }, + "obj:7 0 R": { + "value": 44 + }, + "obj:8 0 R": { + "value": { + "/BaseFont": "/Helvetica", + "/Encoding": "/WinAnsiEncoding", + "/Name": "/F1", + "/Subtype": "/Type1", + "/Type": "/Font" + } + }, + "obj:9 0 R": { + "value": [ + "/PDF", + "/Text" + ] + }, + "trailer": { + "value": { + "/ID": [ + "b:31415926535897932384626433832795", + "b:31415926535897932384626433832795" + ], + "/QTest": "2 0 R", + "/Root": "1 0 R", + "/Size": 10 + } + } + } + } +} diff --git a/qpdf/qtest/qpdf/manual-qpdf-json.json b/qpdf/qtest/qpdf/manual-qpdf-json.json index 0f7d5b61..c67be939 100644 --- a/qpdf/qtest/qpdf/manual-qpdf-json.json +++ b/qpdf/qtest/qpdf/manual-qpdf-json.json @@ -104,11 +104,14 @@ "u:(", "u:)", "u:a\f\b\t\r\nb", + "u:\"", + "u:\"\"", + "u:\"(\")\"", "b:410042", "u:a\nb", "u:a b", - "u:Ï€", - "u:🥔" + ["u:Ï€", "u:\u03c0", "b:EFBBBFCF80", "b:feff03c0"], + ["u:🥔", "u:\ud83e\udd54", "b:feffd83eDD54"] ] } }, diff --git a/qpdf/qtest/qpdf/manual-qpdf-json.pdf b/qpdf/qtest/qpdf/manual-qpdf-json.pdf new file mode 100644 index 00000000..d8a40eed --- /dev/null +++ b/qpdf/qtest/qpdf/manual-qpdf-json.pdf @@ -0,0 +1,171 @@ +%PDF-2.0 +%¿÷¢þ +%QDF-1.0 + +%% Original object ID: 1 0 +1 0 obj +<< + /Pages 3 0 R + /Type /Catalog +>> +endobj + +%% Original object ID: 7 0 +2 0 obj +<< + /hex#20strings [ + (Potato) + <01020300040560> + (AB) + ] + /indirect 4 0 R + /names [ + /nesting + /hex#20strings + /text#2fplain + ] + /nesting << + /a [ + 1 + 2 + << + /x (y) + >> + [ + (z) + ] + ] + /b << + / (legal) + /a [ + 1 + 2 + ] + >> + >> + /strings [ + (one) + <24a2> + () + (\(\)) + (\() + (\)) + (a\f\b\t\r\nb) + (") + ("") + ("\("\)") + <410042> + (a\nb) + (a b) + [ + + + + + ] + [ + + + + ] + ] +>> +endobj + +%% Original object ID: 2 0 +3 0 obj +<< + /Count 1 + /Kids [ + 5 0 R + ] + /Type /Pages +>> +endobj + +%% Original object ID: 8 0 +4 0 obj +(hello) +endobj + +%% Page 1 +%% Original object ID: 3 0 +5 0 obj +<< + /Contents 6 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 8 0 R + >> + /ProcSet 9 0 R + >> + /Type /Page +>> +endobj + +%% Contents for page 1 +%% Original object ID: 4 0 +6 0 obj +<< + /Length 7 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato) Tj +ET +endstream +endobj + +7 0 obj +44 +endobj + +%% Original object ID: 6 0 +8 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Original object ID: 5 0 +9 0 obj +[ + /PDF + /Text +] +endobj + +xref +0 10 +0000000000 65535 f +0000000052 00000 n +0000000133 00000 n +0000000829 00000 n +0000000928 00000 n +0000000989 00000 n +0000001231 00000 n +0000001330 00000 n +0000001376 00000 n +0000001521 00000 n +trailer << + /QTest 2 0 R + /Root 1 0 R + /Size 10 + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] +>> +startxref +1556 +%%EOF