#!/usr/bin/env perl require 5.008; use warnings; use strict; unshift(@INC, '.'); require qpdf_test_helpers; chdir("qpdf") or die "chdir testdir failed: $!\n"; require TestDriver; cleanup(); my $td = new TestDriver('merge-and-split'); my $n_tests = 28; # Select pages from the same file multiple times including selecting # twice from an encrypted file and specifying the password only the # first time. The file 20-pages.pdf is specified with two different # paths to duplicate a page. my $pages_options = "--pages page-labels-and-outlines.pdf 1,3,5-7,z" . " 20-pages.pdf --password=user z-15" . " page-labels-and-outlines.pdf 12" . " 20-pages.pdf 10" . " ./20-pages.pdf --password=owner 10" . " minimal.pdf 1 --"; $td->runtest("merge three files", {$td->COMMAND => "qpdf page-labels-and-outlines.pdf a.pdf" . " $pages_options --static-id --verbose --progress", $td->FILTER => "perl filter-progress.pl"}, {$td->FILE => "verbose-merge.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); # Manually verified about this file: make sure that outline entries # that pointed to pages that were preserved still work in the copy, # and verify that all pages are as expected. page-labels-and-outlines # as well as 20-pages have text on page n (from 1) that shows its page # position from 0, so page 1 says it's page 0. $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf merge-three-files-1.pdf"}, {$td->FILE => "merge-three-files-1.pdf", $td->EXIT_STATUS => 0}); # Select the same pages but add them to an empty file $td->runtest("merge three files", {$td->COMMAND => "qpdf --empty a.pdf" . " $pages_options --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); # Manually verified about this file: it has the same pages but does # not contain outlines or other things from the original file. $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf merge-three-files-2.pdf"}, {$td->FILE => "merge-three-files-2.pdf", $td->EXIT_STATUS => 0}); $td->runtest("avoid respecification of password", {$td->COMMAND => "qpdf --empty a.pdf --copy-encryption=20-pages.pdf" . " --allow-weak-crypto" . " --encryption-file-password=user" . " --pages 20-pages.pdf 1,z -- --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "pages-copy-encryption.pdf"}); $td->runtest("merge with implicit ranges", {$td->COMMAND => "qpdf --empty a.pdf" . " --pages minimal.pdf 20-pages.pdf --password=user" . " page-labels-and-outlines.pdf --" . " --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf merge-implicit-ranges.pdf"}, {$td->FILE => "merge-implicit-ranges.pdf", $td->EXIT_STATUS => 0}); $td->runtest("merge with . and implicit ranges", {$td->COMMAND => "qpdf minimal.pdf a.pdf --pages minimal.pdf . 1 --" . " --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf merge-dot-implicit-ranges.pdf"}, {$td->FILE => "merge-dot-implicit-ranges.pdf", $td->EXIT_STATUS => 0}); $td->runtest("merge with multiple labels", {$td->COMMAND => "qpdf --empty a.pdf" . " --pages 11-pages-with-labels.pdf 8-11" . " minimal.pdf " . " page-labels-and-outlines.pdf 17-19 --" . " --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf merge-multiple-labels.pdf"}, {$td->FILE => "merge-multiple-labels.pdf", $td->EXIT_STATUS => 0}); $td->runtest("remove labels", {$td->COMMAND => "qpdf --empty a.pdf" . " --remove-page-labels" . " --pages 11-pages-with-labels.pdf 8-11" . " minimal.pdf " . " page-labels-and-outlines.pdf 17-19 --" . " --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf remove-labels.pdf"}, {$td->FILE => "remove-labels.pdf", $td->EXIT_STATUS => 0}); $td->runtest("split with shared resources", {$td->COMMAND => "qpdf --qdf --static-id" . " --remove-unreferenced-resources=yes" . " shared-images.pdf --pages . 1,3" . " ./shared-images.pdf 1,2 -- a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "shared-images-pages-out.pdf"}); $td->runtest("split with really shared resources", {$td->COMMAND => "qpdf --qdf --static-id" . " --remove-unreferenced-resources=yes" . " shared-images.pdf --pages . 1,3" . " . 1,2 -- a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "really-shared-images-pages-out.pdf"}); $td->runtest("shared resources relevant errors", {$td->COMMAND => "qpdf --qdf --static-id" . " shared-images-errors.pdf --pages . 2 -- a.pdf"}, {$td->FILE => "shared-images-errors-2.out", $td->EXIT_STATUS => 3}, $td->NORMALIZE_NEWLINES); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "shared-images-errors-2-out.pdf"}); # This test used to generate warnings about images on pages we didn't # care about, but qpdf was modified not to process those pages, so the # "irrelevant" errors went away. $td->runtest("shared resources irrelevant errors", {$td->COMMAND => "qpdf --qdf --static-id" . " shared-images-errors.pdf --pages . 1 -- a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "shared-images-errors-1-out.pdf"}); $td->runtest("don't remove shared resources", {$td->COMMAND => "qpdf --qdf --static-id --preserve-unreferenced-resources" . " shared-images.pdf --pages . 1,3 -- a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "shared-images-errors-1-3-out.pdf"}); $td->runtest("duplicate pages", {$td->COMMAND => "qpdf --qdf --static-id 11-pages-with-labels.pdf" . " --pages . 6,5,6 . 5 minimal.pdf 1,1 minimal.pdf 1 --" . " a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "duplicate-pages.pdf"}); # See https://github.com/qpdf/qpdf/issues/399 -- we don't want to # break this, especially if we ever implement deduplication of # identical streams. $td->runtest("force full page duplication", {$td->COMMAND => "qpdf --static-id minimal.pdf" . " --pages . ./minimal.pdf -- a.pdf"}, {$td->STRING => "", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("check output", {$td->COMMAND => "qpdf-test-compare a.pdf deep-duplicate-pages.pdf"}, {$td->FILE => "deep-duplicate-pages.pdf", $td->EXIT_STATUS => 0}); cleanup(); $td->report($n_tests);