#include "QueueTests.h" #include #include #include #include #include #include "AppendCharacterJob.h" #include #include #include #include #include #include #include #include #include #include // always. ahm. no. never. never show your private parts in public. #ifdef THREADWEAVER_PRIVATE_API #error "PARTS OF THREADWEAVER'S PRIVATE API ARE INCLUDED IN PUBLIC HEADERS!" #endif QMutex s_GlobalMutex; LowPriorityAppendCharacterJob::LowPriorityAppendCharacterJob (QChar c, QString* stringref, QObject* parent) : AppendCharacterJob (c, stringref, parent) {} int LowPriorityAppendCharacterJob ::priority() const { return -1; } HighPriorityAppendCharacterJob::HighPriorityAppendCharacterJob (QChar c, QString* stringref, QObject* parent) : AppendCharacterJob (c, stringref, parent) {} int HighPriorityAppendCharacterJob::priority() const { return 1; } SecondThreadThatQueues::SecondThreadThatQueues() : QThread() { } void SecondThreadThatQueues::run () { QString sequence; AppendCharacterJob a( 'a', &sequence ); ThreadWeaver::Weaver::instance()->enqueue ( &a ); ThreadWeaver::Weaver::instance()->finish(); QCOMPARE( sequence, QString("a" ) ); } QueueTests::QueueTests( QObject* parent ) : QObject( parent ) , autoDeleteJob ( 0 ) { } void QueueTests::SimpleQueuePrioritiesTest() { ThreadWeaver::Weaver weaver; weaver.setMaximumNumberOfThreads ( 1 ); // just one thread QString sequence; LowPriorityAppendCharacterJob jobA ( QChar( 'a' ), &sequence ); AppendCharacterJob jobB ( QChar( 'b' ), &sequence ); HighPriorityAppendCharacterJob jobC ( QChar( 'c' ), &sequence ); // queue low priority, then normal priority, then high priority // if priorities are processed correctly, the jobs will be executed in reverse order weaver.suspend(); weaver.enqueue ( & jobA ); weaver.enqueue ( & jobB ); weaver.enqueue ( & jobC ); weaver.resume(); weaver.finish(); QCOMPARE ( sequence, QString ("cba" ) ); } void QueueTests::WeaverInitializationTest() { // this one mostly tests the sanity of the startup behaviour ThreadWeaver::Weaver weaver; QCOMPARE (weaver.currentNumberOfThreads(), 0); QVERIFY (weaver.isEmpty()); QVERIFY(weaver.isIdle()); QVERIFY(weaver.queueLength() == 0); weaver.finish(); } void QueueTests::QueueFromSecondThreadTest() { SecondThreadThatQueues thread; thread.start(); thread.wait(); QVERIFY ( ThreadWeaver::Weaver::instance()->isIdle() ); } void QueueTests::deleteJob( ThreadWeaver::Job* job) { // test that signals are properly emitted (asynchronously, that is): QVERIFY( thread() == QThread::currentThread() ); QVERIFY( job == autoDeleteJob ); delete job; autoDeleteJob = 0; } void QueueTests::DeleteDoneJobsFromSequenceTest() { QString sequence; autoDeleteJob = new AppendCharacterJob( QChar( 'a' ), &sequence ); AppendCharacterJob b( QChar( 'b' ), &sequence ); AppendCharacterJob c( QChar( 'c' ), &sequence ); ThreadWeaver::JobCollection jobCollection( this ); jobCollection.addJob ( autoDeleteJob ); jobCollection.addJob ( &b ); jobCollection.addJob ( &c); QVERIFY( autoDeleteJob != 0 ); connect( autoDeleteJob, SIGNAL(done(ThreadWeaver::Job*)), SLOT(deleteJob(ThreadWeaver::Job*)) ); ThreadWeaver::Weaver::instance()->enqueue ( &jobCollection ); QTest::qWait(100); // return to event queue to make sure signals are delivered ThreadWeaver::Weaver::instance()->finish(); QTest::qWait(100); // return to event queue to make sure signals are delivered // no need to delete a, that should be done in deleteJob QVERIFY( autoDeleteJob == 0 ); } void QueueTests::deleteCollection( Job* collection ) { QVERIFY( thread() == QThread::currentThread() ); QVERIFY( collection == autoDeleteCollection ); delete autoDeleteCollection; autoDeleteCollection = 0; } void QueueTests::DeleteCollectionOnDoneTest() { QString sequence; autoDeleteCollection = new ThreadWeaver::JobCollection( this ); connect ( autoDeleteCollection, SIGNAL(done(ThreadWeaver::Job*)), SLOT(deleteCollection(ThreadWeaver::Job*)) ); AppendCharacterJob a( QChar( 'a' ), &sequence ); AppendCharacterJob b( QChar( 'b' ), &sequence ); autoDeleteCollection->addJob( &a ); autoDeleteCollection->addJob( &b ); ThreadWeaver::Weaver::instance()->enqueue( autoDeleteCollection ); // return to event queue to make sure signals are delivered // (otherwise, no slot calls would happen before the end of this function) // I assume the amount of time that we wait does not matter QTest::qWait(10); ThreadWeaver::Weaver::instance()->finish(); // return to event queue to make sure signals are delivered QTest::qWait(10); // no need to delete a, that should be done in deleteJob QVERIFY( sequence.length() == 2 ); QVERIFY( autoDeleteCollection == 0 ); } QTEST_MAIN ( QueueTests ) #include "moc_QueueTests.cpp"