14.18 round 1: a starved PDF throws, an early zoom centres, inches round to even, tests tightened
This commit is contained in:
13 files changed
+210
-15
No files matched your search
@@ -0,0 +1,73 @@
|
||||
#include "AddressSpaceLimit.h"
|
||||
#include "IO/ImageExporter.h"
|
||||
#include <QThreadPool>
|
||||
#include <QtEndian>
|
||||
#include <QtTest>
|
||||
#include <malloc.h>
|
||||
|
||||
// A starved PDF throws; it never comes back broken.
|
||||
class ExportPDFFailureTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void aStarvedPDFThrowsOrIsWhole();
|
||||
};
|
||||
|
||||
namespace {
|
||||
// Each Flate stream's bytes, inflated.
|
||||
QList<QByteArray> inflated(const QByteArray &pdf)
|
||||
{
|
||||
QList<QByteArray> streams;
|
||||
for (qsizetype at = pdf.indexOf("/FlateDecode"); at >= 0; at = pdf.indexOf("/FlateDecode", at + 1)) {
|
||||
const qsizetype begin = pdf.indexOf(">>\nstream\n", at) + 10, end = pdf.indexOf("\nendstream", begin);
|
||||
QByteArray sized(4, 0);
|
||||
qToBigEndian(quint32(64 << 20), sized.data());
|
||||
streams << qUncompress(sized + pdf.mid(begin, end - begin));
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
}
|
||||
|
||||
void ExportPDFFailureTests::aStarvedPDFThrowsOrIsWhole()
|
||||
{
|
||||
// Noise, so the compressed streams stay near their size.
|
||||
QImage noise(1000, 1000, QImage::Format_RGBA8888_Premultiplied);
|
||||
quint32 seed = 7;
|
||||
for (int y = 0; y < noise.height(); ++y) {
|
||||
auto *row = reinterpret_cast<quint32 *>(noise.scanLine(y));
|
||||
for (int x = 0; x < noise.width(); ++x)
|
||||
row[x] = (seed = seed * 1664525u + 1013904223u) | 0xff000000u;
|
||||
}
|
||||
const ExportRaster raster{noise, 72};
|
||||
// Qt converts on pool threads: start them before any limit.
|
||||
QThreadPool::globalInstance()->setExpiryTimeout(-1);
|
||||
ImageExporter::pdfData(raster);
|
||||
int refused = 0, whole = 0;
|
||||
for (qint64 megabytes = 2; megabytes <= 48; ++megabytes) {
|
||||
QByteArray pdf;
|
||||
try {
|
||||
const AddressSpaceLimit limit(megabytes << 20);
|
||||
pdf = ImageExporter::pdfData(raster);
|
||||
} catch (const ExportError &error) {
|
||||
QCOMPARE(error.kind, ExportError::Kind::render);
|
||||
++refused;
|
||||
continue;
|
||||
}
|
||||
const QList<QByteArray> streams = inflated(pdf);
|
||||
QCOMPARE(streams.size(), qsizetype(2));
|
||||
QVERIFY2(streams[0].size() == 1000 * 1000 * 3 && streams[1].size() == 1000 * 1000, qPrintable(QString::number(megabytes)));
|
||||
++whole;
|
||||
}
|
||||
// The sweep reaches both sides of the limit.
|
||||
QVERIFY(refused > 0 && whole > 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Large asks map memory the limit counts.
|
||||
mallopt(M_MMAP_THRESHOLD, 64 * 1024);
|
||||
QCoreApplication app(argc, argv);
|
||||
ExportPDFFailureTests tests;
|
||||
return QTest::qExec(&tests, argc, argv);
|
||||
}
|
||||
|
||||
#include "ExportPDFFailureTests.moc"
|
||||
Reference in new issue
Block a user