blob: 1e7e4a8430ee05a2e9d63e71f9a1ca33b613edb9 [file] [log] [blame]
#ifndef _WIN32
#include <unistd.h>
#else
#include <windows.h>
#define sleep Sleep
#endif
#include <time.h>
#include <poppler-qt5.h>
#include <poppler-form.h>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QMutex>
#include <QtCore/QThread>
#include <QtGui/QImage>
class SillyThread : public QThread
{
Q_OBJECT
public:
SillyThread(Poppler::Document* document, QObject* parent = nullptr);
void run() override;
private:
Poppler::Document* m_document;
QVector< Poppler::Page* > m_pages;
};
class CrazyThread : public QThread
{
Q_OBJECT
public:
CrazyThread(uint seed, Poppler::Document* document, QMutex* annotationMutex, QObject* parent = nullptr);
void run() override;
private:
uint m_seed;
Poppler::Document* m_document;
QMutex* m_annotationMutex;
};
static Poppler::Page* loadPage(Poppler::Document* document, int index)
{
Poppler::Page* page = document->page(index);
if(page == nullptr)
{
qDebug() << "!Document::page";
exit(EXIT_FAILURE);
}
return page;
}
static Poppler::Page* loadRandomPage(Poppler::Document* document)
{
return loadPage(document, qrand() % document->numPages());
}
SillyThread::SillyThread(Poppler::Document* document, QObject* parent) : QThread(parent),
m_document(document),
m_pages()
{
m_pages.reserve(m_document->numPages());
for(int index = 0; index < m_document->numPages(); ++index)
{
m_pages.append(loadPage(m_document, index));
}
}
void SillyThread::run()
{
forever
{
foreach(Poppler::Page* page, m_pages)
{
QImage image = page->renderToImage();
if(image.isNull())
{
qDebug() << "!Page::renderToImage";
::exit(EXIT_FAILURE);
}
}
}
}
CrazyThread::CrazyThread(uint seed, Poppler::Document* document, QMutex* annotationMutex, QObject* parent) : QThread(parent),
m_seed(seed),
m_document(document),
m_annotationMutex(annotationMutex)
{
}
void CrazyThread::run()
{
typedef QScopedPointer< Poppler::Page > PagePointer;
qsrand(m_seed);
forever
{
if(qrand() % 2 == 0)
{
qDebug() << "search...";
PagePointer page(loadRandomPage(m_document));
page->search(QStringLiteral("c"), Poppler::Page::IgnoreCase);
page->search(QStringLiteral("r"));
page->search(QStringLiteral("a"), Poppler::Page::IgnoreCase);
page->search(QStringLiteral("z"));
page->search(QStringLiteral("y"), Poppler::Page::IgnoreCase);
}
if(qrand() % 2 == 0)
{
qDebug() << "links...";
PagePointer page(loadRandomPage(m_document));
QList< Poppler::Link* > links = page->links();
qDeleteAll(links);
}
if(qrand() % 2 == 0)
{
qDebug() << "form fields...";
PagePointer page(loadRandomPage(m_document));
QList< Poppler::FormField* > formFields = page->formFields();
qDeleteAll(formFields);
}
if(qrand() % 2 == 0)
{
qDebug() << "thumbnail...";
PagePointer page(loadRandomPage(m_document));
page->thumbnail();
}
if(qrand() % 2 == 0)
{
qDebug() << "text...";
PagePointer page(loadRandomPage(m_document));
page->text(QRectF(QPointF(), page->pageSizeF()));
}
if(qrand() % 2 == 0)
{
QMutexLocker mutexLocker(m_annotationMutex);
qDebug() << "add annotation...";
PagePointer page(loadRandomPage(m_document));
Poppler::Annotation* annotation = nullptr;
switch(qrand() % 3)
{
default:
case 0:
annotation = new Poppler::TextAnnotation(qrand() % 2 == 0 ? Poppler::TextAnnotation::Linked : Poppler::TextAnnotation::InPlace);
break;
case 1:
annotation = new Poppler::HighlightAnnotation();
break;
case 2:
annotation = new Poppler::InkAnnotation();
break;
}
annotation->setBoundary(QRectF(0.0, 0.0, 0.5, 0.5));
annotation->setContents(QStringLiteral("crazy"));
page->addAnnotation(annotation);
delete annotation;
}
if(qrand() % 2 == 0)
{
QMutexLocker mutexLocker(m_annotationMutex);
for(int index = 0; index < m_document->numPages(); ++index)
{
PagePointer page(loadPage(m_document, index));
QList< Poppler::Annotation* > annotations = page->annotations();
if(!annotations.isEmpty())
{
qDebug() << "modify annotation...";
annotations.at(qrand() % annotations.size())->setBoundary(QRectF(0.5, 0.5, 0.25, 0.25));
annotations.at(qrand() % annotations.size())->setAuthor(QStringLiteral("foo"));
annotations.at(qrand() % annotations.size())->setContents(QStringLiteral("bar"));
annotations.at(qrand() % annotations.size())->setCreationDate(QDateTime::currentDateTime());
annotations.at(qrand() % annotations.size())->setModificationDate(QDateTime::currentDateTime());
}
qDeleteAll(annotations);
if(!annotations.isEmpty())
{
break;
}
}
}
if(qrand() % 2 == 0)
{
QMutexLocker mutexLocker(m_annotationMutex);
for(int index = 0; index < m_document->numPages(); ++index)
{
PagePointer page(loadPage(m_document, index));
QList< Poppler::Annotation* > annotations = page->annotations();
if(!annotations.isEmpty())
{
qDebug() << "remove annotation...";
page->removeAnnotation(annotations.takeAt(qrand() % annotations.size()));
}
qDeleteAll(annotations);
if(!annotations.isEmpty())
{
break;
}
}
}
if(qrand() % 2 == 0)
{
qDebug() << "fonts...";
m_document->fonts();
}
}
}
int main(int argc, char** argv)
{
if(argc < 5)
{
qDebug() << "usage: stress-threads-qt duration sillyCount crazyCount file(s)";
return EXIT_FAILURE;
}
const int duration = atoi(argv[1]);
const int sillyCount = atoi(argv[2]);
const int crazyCount = atoi(argv[3]);
qsrand(time(nullptr));
for(int argi = 4; argi < argc; ++argi)
{
const QString file = QFile::decodeName(argv[argi]);
Poppler::Document* document = Poppler::Document::load(file);
if(document == nullptr)
{
qDebug() << "Could not load" << file;
continue;
}
if(document->isLocked())
{
qDebug() << file << "is locked";
continue;
}
for(int i = 0; i < sillyCount; ++i)
{
(new SillyThread(document))->start();
}
QMutex* annotationMutex = new QMutex();
for(int i = 0; i < crazyCount; ++i)
{
(new CrazyThread(qrand(), document, annotationMutex))->start();
}
}
sleep(duration);
return EXIT_SUCCESS;
}
#include "stress-threads-qt5.moc"