mirror of https://github.com/qpdf/qpdf.git
test_driver: split runtest into separate functions
Too bad about git annotate but it was pretty crazy to have all those test cases together like that.
This commit is contained in:
parent
c1e2b64a3f
commit
cf7b2b5700
2
TODO
2
TODO
|
@ -3,8 +3,6 @@ Next
|
|||
|
||||
* High-level API/doc overhaul: #593
|
||||
|
||||
* Refactor test_driver.cc so that runtest is not one huge function.
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
no forms
|
||||
test 43 done
|
||||
|
|
|
@ -193,99 +193,7 @@ static void compare_numbers(
|
|||
}
|
||||
}
|
||||
|
||||
void runtest(int n, char const* filename1, char const* arg2)
|
||||
{
|
||||
// Most tests here are crafted to work on specific files. Look at
|
||||
// the test suite to see how the test is invoked to find the file
|
||||
// that the test is supposed to operate on.
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
// Throw in some random test cases that don't fit anywhere
|
||||
// else. This is in addition to whatever else is going on in
|
||||
// test 0.
|
||||
|
||||
// The code to trim user passwords looks for 0x28 (which is
|
||||
// "(") since it marks the beginning of the padding. Exercise
|
||||
// the code to make sure it skips over 0x28 characters that
|
||||
// aren't part of padding.
|
||||
std::string password(
|
||||
"1234567890123456789012(45678\x28\xbf\x4e\x5e");
|
||||
assert(password.length() == 32);
|
||||
QPDF::trim_user_password(password);
|
||||
assert(password == "1234567890123456789012(45678");
|
||||
|
||||
QPDFObjectHandle uninitialized;
|
||||
assert(uninitialized.getTypeCode() == QPDFObject::ot_uninitialized);
|
||||
assert(strcmp(uninitialized.getTypeName(), "uninitialized") == 0);
|
||||
}
|
||||
|
||||
QPDF pdf;
|
||||
PointerHolder<char> file_buf;
|
||||
FILE* filep = 0;
|
||||
if (n == 0)
|
||||
{
|
||||
pdf.setAttemptRecovery(false);
|
||||
}
|
||||
if (((n == 35) || (n == 36)) && (arg2 != 0))
|
||||
{
|
||||
// arg2 is password
|
||||
pdf.processFile(filename1, arg2);
|
||||
}
|
||||
else if (n == 45)
|
||||
{
|
||||
// Decode obfuscated files. To obfuscated, run the input file
|
||||
// through this perl script, and save the result to
|
||||
// filename.obfuscated. This pretends that the input was
|
||||
// called filename.pdf and that that file contained the
|
||||
// deobfuscated version.
|
||||
|
||||
// undef $/;
|
||||
// my @str = split('', <STDIN>);
|
||||
// for (my $i = 0; $i < scalar(@str); ++$i)
|
||||
// {
|
||||
// $str[$i] = chr(ord($str[$i]) ^ 0xcc);
|
||||
// }
|
||||
// print(join('', @str));
|
||||
|
||||
std::string filename(std::string(filename1) + ".obfuscated");
|
||||
size_t size = 0;
|
||||
QUtil::read_file_into_memory(filename.c_str(), file_buf, size);
|
||||
char* p = file_buf.getPointer();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
p[i] = static_cast<char>(p[i] ^ 0xcc);
|
||||
}
|
||||
pdf.processMemoryFile((std::string(filename1) + ".pdf").c_str(),
|
||||
p, size);
|
||||
}
|
||||
else if ((n == 61) || (n == 81))
|
||||
{
|
||||
// Ignore filename argument entirely
|
||||
}
|
||||
else if (n % 2 == 0)
|
||||
{
|
||||
if (n % 4 == 0)
|
||||
{
|
||||
QTC::TC("qpdf", "exercise processFile(name)");
|
||||
pdf.processFile(filename1);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "exercise processFile(FILE*)");
|
||||
filep = QUtil::safe_fopen(filename1, "rb");
|
||||
pdf.processFile(filename1, filep, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "exercise processMemoryFile");
|
||||
size_t size = 0;
|
||||
QUtil::read_file_into_memory(filename1, file_buf, size);
|
||||
pdf.processMemoryFile(filename1, file_buf.getPointer(), size);
|
||||
}
|
||||
|
||||
if ((n == 0) || (n == 1))
|
||||
static void test_0_1(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
QPDFObjectHandle qtest = trailer.getKey("/QTest");
|
||||
|
@ -411,7 +319,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
<< "unparseResolved: " << qtest.unparseResolved()
|
||||
<< std::endl;
|
||||
}
|
||||
else if (n == 2)
|
||||
|
||||
static void test_2(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Encrypted file. This test case is designed for a specific
|
||||
// PDF file.
|
||||
|
@ -435,7 +344,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
PointerHolder<Pl_StdioFile> out = new Pl_StdioFile("filtered", stdout);
|
||||
contents.pipeStreamData(out.getPointer(), 0, qpdf_dl_generalized);
|
||||
}
|
||||
else if (n == 3)
|
||||
|
||||
static void test_3(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle streams = pdf.getTrailer().getKey("/QStreams");
|
||||
for (int i = 0; i < streams.getArrayNItems(); ++i)
|
||||
|
@ -450,7 +360,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
qpdf_ef_normalize, qpdf_dl_generalized);
|
||||
}
|
||||
}
|
||||
else if (n == 4)
|
||||
|
||||
static void test_4(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Mutability testing: Make /QTest direct recursively, then
|
||||
// copy to /Info. Also make some other mutations so we can
|
||||
|
@ -503,7 +414,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
// Prevent "done" message from getting appended
|
||||
exit(0);
|
||||
}
|
||||
else if (n == 5)
|
||||
|
||||
static void test_5(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
|
||||
|
@ -566,7 +478,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (n == 6)
|
||||
|
||||
static void test_6(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle metadata = root.getKey("/Metadata");
|
||||
|
@ -592,7 +505,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
<< (cleartext ? 1 : 0)
|
||||
<< std::endl;
|
||||
}
|
||||
else if (n == 7)
|
||||
|
||||
static void test_7(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle qstream = root.getKey("/QStream");
|
||||
|
@ -608,7 +522,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 8)
|
||||
|
||||
static void test_8(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle qstream = root.getKey("/QStream");
|
||||
|
@ -650,7 +565,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 9)
|
||||
|
||||
static void test_9(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
// Explicitly exercise the Buffer version of newStream
|
||||
|
@ -679,7 +595,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 10)
|
||||
|
||||
static void test_10(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
|
@ -696,7 +613,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 11)
|
||||
|
||||
static void test_11(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle qstream = root.getKey("/QStream");
|
||||
|
@ -713,12 +631,14 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "raw stream data okay" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 12)
|
||||
|
||||
static void test_12(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
pdf.setOutputStreams(0, 0);
|
||||
pdf.showLinearizationData();
|
||||
}
|
||||
else if (n == 13)
|
||||
|
||||
static void test_13(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
std::ostringstream out;
|
||||
std::ostringstream err;
|
||||
|
@ -729,15 +649,15 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
<< "---error---" << std::endl
|
||||
<< err.str();
|
||||
}
|
||||
else if (n == 14)
|
||||
|
||||
static void test_14(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Exercise swap and replace. This test case is designed for
|
||||
// a specific file.
|
||||
std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
|
||||
if (pages.size() != 4)
|
||||
{
|
||||
throw std::logic_error("test " + QUtil::int_to_string(n) +
|
||||
" not called 4-page file");
|
||||
throw std::logic_error("test 14 not called 4-page file");
|
||||
}
|
||||
// Swap pages 2 and 3
|
||||
auto orig_page2 = pages.at(1);
|
||||
|
@ -812,7 +732,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
delete b;
|
||||
}
|
||||
}
|
||||
else if (n == 15)
|
||||
|
||||
static void test_15(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
// Reference to original page numbers for this test case are
|
||||
|
@ -895,7 +816,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 16)
|
||||
|
||||
static void test_16(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Insert a page manually and then update the cache.
|
||||
std::vector<QPDFObjectHandle> const& all_pages = pdf.getAllPages();
|
||||
|
@ -926,7 +848,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 17)
|
||||
|
||||
static void test_17(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// The input file to this test case has a duplicated page.
|
||||
QPDFObjectHandle page_kids =
|
||||
|
@ -947,7 +870,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
b->getSize());
|
||||
assert(contents.find("page 0") != std::string::npos);
|
||||
}
|
||||
else if (n == 18)
|
||||
|
||||
static void test_18(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Remove a page and re-insert it in the same file.
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
|
@ -967,7 +891,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 19)
|
||||
|
||||
static void test_19(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Remove a page and re-insert it in the same file.
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
|
@ -983,7 +908,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
assert(last.getKey("/Contents").getObjGen() ==
|
||||
newpage.getKey("/Contents").getObjGen());
|
||||
}
|
||||
else if (n == 20)
|
||||
|
||||
static void test_20(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Shallow copy an array
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
|
@ -998,7 +924,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 21)
|
||||
|
||||
static void test_21(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Try to shallow copy a stream
|
||||
std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
|
||||
|
@ -1007,7 +934,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
contents.shallowCopy();
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
}
|
||||
else if (n == 22)
|
||||
|
||||
static void test_22(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Try to remove a page we don't have
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
|
@ -1017,13 +945,15 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
dh.removePage(page);
|
||||
std::cout << "you can't see this" << std::endl;
|
||||
}
|
||||
else if (n == 23)
|
||||
|
||||
static void test_23(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFPageDocumentHelper dh(pdf);
|
||||
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
|
||||
dh.removePage(pages.back());
|
||||
}
|
||||
else if (n == 24)
|
||||
|
||||
static void test_24(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test behavior of reserved objects
|
||||
QPDFObjectHandle res1 = QPDFObjectHandle::newReserved(&pdf);
|
||||
|
@ -1099,7 +1029,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 25)
|
||||
|
||||
static void test_25(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// The copy object tests are designed to work with a specific
|
||||
// file. Look at the test suite for the file, and look at the
|
||||
|
@ -1123,7 +1054,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 26)
|
||||
|
||||
static void test_26(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Copy the O3 page using addPage. Copy qtest without
|
||||
// crossing page boundaries. In addition to previous results,
|
||||
|
@ -1148,7 +1080,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 27)
|
||||
|
||||
static void test_27(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Copy O3 and the page O3 refers to before copying qtest.
|
||||
// Should get qtest plus only the O3 page and the page that O3
|
||||
|
@ -1232,7 +1165,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setDecodeLevel(qpdf_dl_generalized);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 28)
|
||||
|
||||
static void test_28(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Copy foreign object errors
|
||||
try
|
||||
|
@ -1254,7 +1188,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "logic error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 29)
|
||||
|
||||
static void test_29(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Detect mixed objects in QPDFWriter
|
||||
assert(arg2 != 0);
|
||||
|
@ -1287,7 +1222,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "logic error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 30)
|
||||
|
||||
static void test_30(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
assert(arg2 != 0);
|
||||
QPDF encrypted;
|
||||
|
@ -1312,7 +1248,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 31)
|
||||
|
||||
static void test_31(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test object parsing from a string. The input file is not used.
|
||||
|
||||
|
@ -1347,7 +1284,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
&pdf, "[1 0 R]", "indirect test").unparse() ==
|
||||
"[ 1 0 R ]");
|
||||
}
|
||||
else if (n == 32)
|
||||
|
||||
static void test_32(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Extra header text
|
||||
char const* filenames[] = {"a.pdf", "b.pdf", "c.pdf", "d.pdf"};
|
||||
|
@ -1368,7 +1306,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.write();
|
||||
}
|
||||
}
|
||||
else if (n == 33)
|
||||
|
||||
static void test_33(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test writing to a custom pipeline
|
||||
Pl_Buffer p("buffer");
|
||||
|
@ -1381,14 +1320,16 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
fwrite(b->getBuffer(), b->getSize(), 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
else if (n == 34)
|
||||
|
||||
static void test_34(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Look at Extensions dictionary
|
||||
std::cout << "version: " << pdf.getPDFVersion() << std::endl
|
||||
<< "extension level: " << pdf.getExtensionLevel() << std::endl
|
||||
<< pdf.getRoot().getKey("/Extensions").unparse() << std::endl;
|
||||
}
|
||||
else if (n == 35)
|
||||
|
||||
static void test_35(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Extract attachments
|
||||
|
||||
|
@ -1449,7 +1390,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << filename << ":\n" << data << "--END--\n";
|
||||
}
|
||||
}
|
||||
else if (n == 36)
|
||||
|
||||
static void test_36(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Extract raw unfilterable attachment
|
||||
|
||||
|
@ -1481,7 +1423,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (n == 37)
|
||||
|
||||
static void test_37(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Parse content streams of all pages
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
|
@ -1494,7 +1437,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
page.parseContents(&cb);
|
||||
}
|
||||
}
|
||||
else if (n == 38)
|
||||
|
||||
static void test_38(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Designed for override-compressed-object.pdf
|
||||
QPDFObjectHandle qtest = pdf.getRoot().getKey("/QTest");
|
||||
|
@ -1503,7 +1447,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << qtest.getArrayItem(i).unparseResolved() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 39)
|
||||
|
||||
static void test_39(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Display image filter and color set for each image on each page
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
|
@ -1528,7 +1473,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (n == 40)
|
||||
|
||||
static void test_40(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Write PCLm. This requires specially crafted PDF files. This
|
||||
// feature was implemented by Sahil Arora
|
||||
|
@ -1540,7 +1486,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 41)
|
||||
|
||||
static void test_41(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Apply a token filter. This test case is crafted to work
|
||||
// with coalesce.pdf.
|
||||
|
@ -1557,7 +1504,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 42)
|
||||
|
||||
static void test_42(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Access objects as wrong type. This test case is crafted to
|
||||
// work with object-types.pdf.
|
||||
|
@ -1663,7 +1611,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
assert(! uninitialized.isInteger());
|
||||
assert(! uninitialized.isDictionary());
|
||||
}
|
||||
else if (n == 43)
|
||||
|
||||
static void test_43(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Forms
|
||||
QPDFAcroFormDocumentHelper afdh(pdf);
|
||||
|
@ -1765,7 +1714,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (n == 44)
|
||||
|
||||
static void test_44(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Set form fields.
|
||||
QPDFAcroFormDocumentHelper afdh(pdf);
|
||||
|
@ -1793,7 +1743,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setSuppressOriginalObjectIDs(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 45)
|
||||
|
||||
static void test_45(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Decode obfuscated files. This is here to help test with
|
||||
// files that trigger anti-virus warnings. See comments in
|
||||
|
@ -1806,7 +1757,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
exit(3);
|
||||
}
|
||||
}
|
||||
else if (n == 46)
|
||||
|
||||
static void test_46(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test number tree. This test is crafted to work with
|
||||
// number-tree.pdf
|
||||
|
@ -1980,7 +1932,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
pdf.getTrailer().getKey("/Bad5"), pdf);
|
||||
assert(bad5.find(10) == bad5.end());
|
||||
}
|
||||
else if (n == 47)
|
||||
|
||||
static void test_47(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test page labels.
|
||||
QPDFPageLabelDocumentHelper pldh(pdf);
|
||||
|
@ -1995,7 +1948,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
<< labels.at(i+1).unparse() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 48)
|
||||
|
||||
static void test_48(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test name tree. This test is crafted to work with
|
||||
// name-tree.pdf
|
||||
|
@ -2160,7 +2114,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
pdf.getTrailer().getKey("/Bad6"), pdf);
|
||||
assert(bad6.insert("H", QPDFObjectHandle::newNull())->first == "H");
|
||||
}
|
||||
else if (n == 49)
|
||||
|
||||
static void test_49(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Outlines
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
|
@ -2183,7 +2138,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (n == 50)
|
||||
|
||||
static void test_50(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test dictionary merge. This test is crafted to work with
|
||||
// merge-dict.pdf
|
||||
|
@ -2200,7 +2156,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << *iter << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 51)
|
||||
|
||||
static void test_51(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test radio button and checkbox field setting. The input
|
||||
// files must have radios button called r1 and r2 and
|
||||
|
@ -2249,7 +2206,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 52)
|
||||
|
||||
static void test_52(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// This test just sets a field value for appearance stream
|
||||
// generating testing.
|
||||
|
@ -2275,7 +2233,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
QPDFWriter w(pdf, "a.pdf");
|
||||
w.write();
|
||||
}
|
||||
else if (n == 53)
|
||||
|
||||
static void test_53(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test get all objects and dangling ref handling
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
|
@ -2294,7 +2253,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 54)
|
||||
|
||||
static void test_54(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test getFinalVersion. This must be invoked with a file
|
||||
// whose final version is not 1.5.
|
||||
|
@ -2306,7 +2266,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "oops: " << w.getFinalVersion() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 55)
|
||||
|
||||
static void test_55(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Form XObjects
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
|
@ -2325,21 +2286,22 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if ((n >= 56) && (n <= 59))
|
||||
{
|
||||
// Placing form XObjects
|
||||
assert(arg2);
|
||||
QPDF pdf2;
|
||||
pdf2.processFile(arg2);
|
||||
|
||||
static void test_56_59(QPDF& pdf, char const* arg2,
|
||||
bool handle_from_transformation,
|
||||
bool invert_to_transformation)
|
||||
{
|
||||
// red pages are from pdf, blue pages are from pdf2
|
||||
// red pages always have stated rotation absolutely
|
||||
// 56: blue pages are overlaid exactly on top of red pages
|
||||
// 57: blue pages have stated rotation relative to red pages
|
||||
// 58: blue pages have no rotation (absolutely upright)
|
||||
// 59: blue pages have stated rotation absolutely
|
||||
bool handle_from_transformation = ((n == 57) || (n == 59));
|
||||
bool invert_to_transformation = ((n == 58) || (n == 59));
|
||||
|
||||
// Placing form XObjects
|
||||
assert(arg2);
|
||||
QPDF pdf2;
|
||||
pdf2.processFile(arg2);
|
||||
|
||||
std::vector<QPDFPageObjectHelper> pages1 =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
|
@ -2378,7 +2340,28 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 60)
|
||||
|
||||
static void test_56(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_56_59(pdf, arg2, false, false);
|
||||
}
|
||||
|
||||
static void test_57(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_56_59(pdf, arg2, true, false);
|
||||
}
|
||||
|
||||
static void test_58(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_56_59(pdf, arg2, false, true);
|
||||
}
|
||||
|
||||
static void test_59(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_56_59(pdf, arg2, true, true);
|
||||
}
|
||||
|
||||
static void test_60(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Boundary condition testing for getUniqueResourceName;
|
||||
// additional testing of mergeResources with conflict
|
||||
|
@ -2458,7 +2441,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 61)
|
||||
|
||||
static void test_61(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test to make sure exceptions can be caught properly across
|
||||
// shared library boundaries.
|
||||
|
@ -2497,7 +2481,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "Caught runtime_error as expected" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 62)
|
||||
|
||||
static void test_62(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test int size checks. This test will fail if int and long
|
||||
// long are the same size.
|
||||
|
@ -2522,7 +2507,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
assert_compare_numbers(INT_MAX, t.getKey("/Q3").getIntValueAsInt());
|
||||
assert_compare_numbers(UINT_MAX, t.getKey("/Q3").getUIntValueAsUInt());
|
||||
}
|
||||
else if (n == 63)
|
||||
|
||||
static void test_63(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFWriter w(pdf);
|
||||
// Exercise setting encryption parameters before setting the
|
||||
|
@ -2535,20 +2521,21 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setOutputFilename("a.pdf");
|
||||
w.write();
|
||||
}
|
||||
else if ((n >= 64) && (n <= 67))
|
||||
{
|
||||
// Placing form XObjects: expand, shrink
|
||||
assert(arg2);
|
||||
QPDF pdf2;
|
||||
pdf2.processFile(arg2);
|
||||
|
||||
static void test_64_67(QPDF& pdf, char const* arg2,
|
||||
bool allow_shrink, bool allow_expand)
|
||||
{
|
||||
// Overlay file2 on file1.
|
||||
// 64: allow neither shrink nor shrink
|
||||
// 65: allow shrink but not expand
|
||||
// 66: allow expand but not shrink
|
||||
// 67: allow both shrink and expand
|
||||
bool allow_shrink = ((n == 65) || (n == 67));
|
||||
bool allow_expand = ((n == 66) || (n == 67));
|
||||
|
||||
// Placing form XObjects: expand, shrink
|
||||
assert(arg2);
|
||||
QPDF pdf2;
|
||||
pdf2.processFile(arg2);
|
||||
|
||||
std::vector<QPDFPageObjectHelper> pages1 =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
std::vector<QPDFPageObjectHelper> pages2 =
|
||||
|
@ -2586,7 +2573,28 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setStaticID(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 68)
|
||||
|
||||
static void test_64(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_64_67(pdf, arg2, false, false);
|
||||
}
|
||||
|
||||
static void test_65(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_64_67(pdf, arg2, true, false);
|
||||
}
|
||||
|
||||
static void test_66(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_64_67(pdf, arg2, false, true);
|
||||
}
|
||||
|
||||
static void test_67(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
test_64_67(pdf, arg2, true, true);
|
||||
}
|
||||
|
||||
static void test_68(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle qstream = root.getKey("/QStream");
|
||||
|
@ -2615,7 +2623,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << "raw stream data okay" << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 69)
|
||||
|
||||
static void test_69(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
pdf.setImmediateCopyFrom(true);
|
||||
auto pages = pdf.getAllPages();
|
||||
|
@ -2631,7 +2640,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.write();
|
||||
}
|
||||
}
|
||||
else if (n == 70)
|
||||
|
||||
static void test_70(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
auto trailer = pdf.getTrailer();
|
||||
trailer.getKey("/S1").setFilterOnWrite(false);
|
||||
|
@ -2641,7 +2651,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setDecodeLevel(qpdf_dl_specialized);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 71)
|
||||
|
||||
static void test_71(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
auto show = [](QPDFObjectHandle& obj,
|
||||
QPDFObjectHandle& xobj_dict,
|
||||
|
@ -2692,7 +2703,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
std::cout << i.first << " -> " << i.second.unparse() << std::endl;
|
||||
}
|
||||
}
|
||||
else if (n == 72)
|
||||
|
||||
static void test_72(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Call some QPDFPageObjectHelper methods on form XObjects.
|
||||
auto page = QPDFPageDocumentHelper(pdf).getAllPages().at(0);
|
||||
|
@ -2726,7 +2738,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
assert(s.find("/bye") != std::string::npos);
|
||||
}
|
||||
}
|
||||
else if (n == 73)
|
||||
|
||||
static void test_73(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -2741,7 +2754,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
pdf.closeInputSource();
|
||||
pdf.getRoot().getKey("/Pages").unparseResolved();
|
||||
}
|
||||
else if (n == 74)
|
||||
|
||||
static void test_74(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// This test is crafted to work with split-nntree.pdf
|
||||
std::cout << "/Split1" << std::endl;
|
||||
|
@ -2792,7 +2806,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setQDFMode(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 75)
|
||||
|
||||
static void test_75(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// This test is crafted to work with erase-nntree.pdf
|
||||
auto erase1 = QPDFNameTreeObjectHelper(
|
||||
|
@ -2851,7 +2866,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setQDFMode(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 76)
|
||||
|
||||
static void test_76(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Embedded files. arg2 is a file to attach. Hard-code the
|
||||
// mime type and file name for test purposes.
|
||||
|
@ -2901,7 +2917,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setQDFMode(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 77)
|
||||
|
||||
static void test_77(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||
assert(efdh.removeEmbeddedFile("att2"));
|
||||
|
@ -2912,7 +2929,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setQDFMode(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 78)
|
||||
|
||||
static void test_78(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Test functional versions of replaceStreamData()
|
||||
|
||||
|
@ -2954,7 +2972,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setQDFMode(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 79)
|
||||
|
||||
static void test_79(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Exercise stream copier
|
||||
|
||||
|
@ -3015,7 +3034,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w.setQDFMode(true);
|
||||
w.write();
|
||||
}
|
||||
else if (n == 80)
|
||||
|
||||
static void test_80(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Exercise transform/copy annotations without passing in
|
||||
// QPDFAcroFormDocumentHelper pointers. The case of passing
|
||||
|
@ -3062,7 +3082,8 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
w2.setQDFMode(true);
|
||||
w2.write();
|
||||
}
|
||||
else if (n == 81)
|
||||
|
||||
static void test_81(QPDF& pdf, char const* arg2)
|
||||
{
|
||||
// Exercise that type errors get their own special type
|
||||
try
|
||||
|
@ -3075,11 +3096,130 @@ void runtest(int n, char const* filename1, char const* arg2)
|
|||
assert(e.getErrorCode() == qpdf_e_object);
|
||||
}
|
||||
}
|
||||
|
||||
void runtest(int n, char const* filename1, char const* arg2)
|
||||
{
|
||||
// Most tests here are crafted to work on specific files. Look at
|
||||
// the test suite to see how the test is invoked to find the file
|
||||
// that the test is supposed to operate on.
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
// Throw in some random test cases that don't fit anywhere
|
||||
// else. This is in addition to whatever else is going on in
|
||||
// test 0.
|
||||
|
||||
// The code to trim user passwords looks for 0x28 (which is
|
||||
// "(") since it marks the beginning of the padding. Exercise
|
||||
// the code to make sure it skips over 0x28 characters that
|
||||
// aren't part of padding.
|
||||
std::string password(
|
||||
"1234567890123456789012(45678\x28\xbf\x4e\x5e");
|
||||
assert(password.length() == 32);
|
||||
QPDF::trim_user_password(password);
|
||||
assert(password == "1234567890123456789012(45678");
|
||||
|
||||
QPDFObjectHandle uninitialized;
|
||||
assert(uninitialized.getTypeCode() == QPDFObject::ot_uninitialized);
|
||||
assert(strcmp(uninitialized.getTypeName(), "uninitialized") == 0);
|
||||
}
|
||||
|
||||
QPDF pdf;
|
||||
PointerHolder<char> file_buf;
|
||||
FILE* filep = 0;
|
||||
if (n == 0)
|
||||
{
|
||||
pdf.setAttemptRecovery(false);
|
||||
}
|
||||
if (((n == 35) || (n == 36)) && (arg2 != 0))
|
||||
{
|
||||
// arg2 is password
|
||||
pdf.processFile(filename1, arg2);
|
||||
}
|
||||
else if (n == 45)
|
||||
{
|
||||
// Decode obfuscated files. To obfuscated, run the input file
|
||||
// through this perl script, and save the result to
|
||||
// filename.obfuscated. This pretends that the input was
|
||||
// called filename.pdf and that that file contained the
|
||||
// deobfuscated version.
|
||||
|
||||
// undef $/;
|
||||
// my @str = split('', <STDIN>);
|
||||
// for (my $i = 0; $i < scalar(@str); ++$i)
|
||||
// {
|
||||
// $str[$i] = chr(ord($str[$i]) ^ 0xcc);
|
||||
// }
|
||||
// print(join('', @str));
|
||||
|
||||
std::string filename(std::string(filename1) + ".obfuscated");
|
||||
size_t size = 0;
|
||||
QUtil::read_file_into_memory(filename.c_str(), file_buf, size);
|
||||
char* p = file_buf.getPointer();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
p[i] = static_cast<char>(p[i] ^ 0xcc);
|
||||
}
|
||||
pdf.processMemoryFile((std::string(filename1) + ".pdf").c_str(),
|
||||
p, size);
|
||||
}
|
||||
else if ((n == 61) || (n == 81))
|
||||
{
|
||||
// Ignore filename argument entirely
|
||||
}
|
||||
else if (n % 2 == 0)
|
||||
{
|
||||
if (n % 4 == 0)
|
||||
{
|
||||
QTC::TC("qpdf", "exercise processFile(name)");
|
||||
pdf.processFile(filename1);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "exercise processFile(FILE*)");
|
||||
filep = QUtil::safe_fopen(filename1, "rb");
|
||||
pdf.processFile(filename1, filep, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "exercise processMemoryFile");
|
||||
size_t size = 0;
|
||||
QUtil::read_file_into_memory(filename1, file_buf, size);
|
||||
pdf.processMemoryFile(filename1, file_buf.getPointer(), size);
|
||||
}
|
||||
|
||||
std::map<int, void (*)(QPDF&, char const*)> test_functions = {
|
||||
{0, test_0_1}, {1, test_0_1}, {2, test_2}, {3, test_3},
|
||||
{4, test_4}, {5, test_5}, {6, test_6}, {7, test_7},
|
||||
{8, test_8}, {9, test_9}, {10, test_10}, {11, test_11},
|
||||
{12, test_12}, {13, test_13}, {14, test_14}, {15, test_15},
|
||||
{16, test_16}, {17, test_17}, {18, test_18}, {19, test_19},
|
||||
{20, test_20}, {21, test_21}, {22, test_22}, {23, test_23},
|
||||
{24, test_24}, {25, test_25}, {26, test_26}, {27, test_27},
|
||||
{28, test_28}, {29, test_29}, {30, test_30}, {31, test_31},
|
||||
{32, test_32}, {33, test_33}, {34, test_34}, {35, test_35},
|
||||
{36, test_36}, {37, test_37}, {38, test_38}, {39, test_39},
|
||||
{40, test_40}, {41, test_41}, {42, test_42}, {43, test_43},
|
||||
{44, test_44}, {45, test_45}, {46, test_46}, {47, test_47},
|
||||
{48, test_48}, {49, test_49}, {50, test_50}, {51, test_51},
|
||||
{52, test_52}, {53, test_53}, {54, test_54}, {55, test_55},
|
||||
{56, test_56}, {57, test_57}, {58, test_58}, {59, test_59},
|
||||
{60, test_60}, {61, test_61}, {62, test_62}, {63, test_63},
|
||||
{64, test_64}, {65, test_65}, {66, test_66}, {67, test_67},
|
||||
{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},
|
||||
};
|
||||
|
||||
auto fn = test_functions.find(n);
|
||||
if (fn == test_functions.end())
|
||||
{
|
||||
throw std::runtime_error(std::string("invalid test ") +
|
||||
QUtil::int_to_string(n));
|
||||
}
|
||||
(fn->second)(pdf, arg2);
|
||||
|
||||
if (filep)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue