diff options
author | Holger Ihrig <holger.ihrig@nokia.com> | 2011-08-26 12:56:14 +0200 |
---|---|---|
committer | Holger Ihrig <holger.ihrig@nokia.com> | 2011-09-01 12:54:58 +0200 |
commit | 82e715b2770258fa2c536aeae1f46c7fccdcdecf (patch) | |
tree | a4b9135effe2109b164f622314a6ffac6198a8f8 /tests/auto/qthread | |
parent | c9a5ccb268b5e2b2ce0743989c44f808b538ba9b (diff) |
Moving relevant tests to corelib/thread
Task-number: QTBUG-21066
Change-Id: Ia16fa8961f1a73f4da6709197b5dd9929c16583f
Reviewed-on: http://codereview.qt.nokia.com/3663
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com>
Reviewed-by: Jason McDonald <jason.mcdonald@nokia.com>
Diffstat (limited to 'tests/auto/qthread')
-rw-r--r-- | tests/auto/qthread/.gitignore | 1 | ||||
-rw-r--r-- | tests/auto/qthread/qthread.pro | 5 | ||||
-rw-r--r-- | tests/auto/qthread/tst_qthread.cpp | 1249 |
3 files changed, 0 insertions, 1255 deletions
diff --git a/tests/auto/qthread/.gitignore b/tests/auto/qthread/.gitignore deleted file mode 100644 index 4413a75588..0000000000 --- a/tests/auto/qthread/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qthread diff --git a/tests/auto/qthread/qthread.pro b/tests/auto/qthread/qthread.pro deleted file mode 100644 index d3b1028034..0000000000 --- a/tests/auto/qthread/qthread.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qthread.cpp -QT = core -symbian:LIBS += -llibpthread -CONFIG += parallel_test diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp deleted file mode 100644 index 3c46212c16..0000000000 --- a/tests/auto/qthread/tst_qthread.cpp +++ /dev/null @@ -1,1249 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> - -#include <qcoreapplication.h> -#include <qdatetime.h> -#include <qmutex.h> -#include <qthread.h> -#include <qtimer.h> -#include <qwaitcondition.h> -#include <qdebug.h> -#include <qmetaobject.h> - -#ifdef Q_OS_UNIX -#include <pthread.h> -#endif -#if defined(Q_OS_WINCE) -#include <windows.h> -#elif defined(Q_OS_WIN) -#include <process.h> -#include <windows.h> -#endif - -//TESTED_CLASS= -//TESTED_FILES= - -class tst_QThread : public QObject -{ - Q_OBJECT - -public: - tst_QThread(); - virtual ~tst_QThread(); - -private slots: - void currentThreadId(); - void currentThread(); - void idealThreadCount(); - void isFinished(); - void isRunning(); - void setPriority(); - void priority(); - void setStackSize(); - void stackSize(); - void exit(); - void start(); - void terminate(); - void quit(); - void wait(); - void started(); - void finished(); - void terminated(); - void run(); - void exec(); - void setTerminationEnabled(); - void sleep(); - void msleep(); - void usleep(); - - void nativeThreadAdoption(); - void adoptedThreadAffinity(); - void adoptedThreadSetPriority(); - void adoptedThreadExit(); - void adoptedThreadExec(); - void adoptedThreadFinished(); - void adoptedThreadExecFinished(); - void adoptMultipleThreads(); - void adoptMultipleThreadsOverlap(); - - void QTBUG13810_exitAndStart(); - void QTBUG15378_exitAndExec(); - - void connectThreadFinishedSignalToObjectDeleteLaterSlot(); - void wait2(); - void wait3_slowDestructor(); - void destroyFinishRace(); - void startFinishRace(); - void startAndQuitCustomEventLoop(); - - void stressTest(); -}; - -enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute }; - -class SignalRecorder : public QObject -{ - Q_OBJECT -public: - QAtomicInt activationCount; - - inline SignalRecorder() - { activationCount = 0; } - - bool wasActivated() - { return activationCount > 0; } - -public slots: - void slot(); -}; - -void SignalRecorder::slot() -{ activationCount.ref(); } - -class Current_Thread : public QThread -{ -public: - Qt::HANDLE id; - QThread *thread; - - void run() - { - id = QThread::currentThreadId(); - thread = QThread::currentThread(); - } -}; - -class Simple_Thread : public QThread -{ -public: - QMutex mutex; - QWaitCondition cond; - - void run() - { - QMutexLocker locker(&mutex); - cond.wakeOne(); - } -}; - -class Exit_Object : public QObject -{ - Q_OBJECT -public: - QThread *thread; - int code; -public slots: - void slot() - { thread->exit(code); } -}; - -class Exit_Thread : public Simple_Thread -{ -public: - Exit_Object *object; - int code; - int result; - - void run() - { - Simple_Thread::run(); - if (object) { - object->thread = this; - object->code = code; - QTimer::singleShot(100, object, SLOT(slot())); - } - result = exec(); - } -}; - -class Terminate_Thread : public Simple_Thread -{ -public: - void run() - { - setTerminationEnabled(false); - { - QMutexLocker locker(&mutex); - cond.wakeOne(); - cond.wait(&mutex, five_minutes); - } - setTerminationEnabled(true); - qFatal("tst_QThread: test case hung"); - } -}; - -class Quit_Object : public QObject -{ - Q_OBJECT -public: - QThread *thread; -public slots: - void slot() - { thread->quit(); } -}; - -class Quit_Thread : public Simple_Thread -{ -public: - Quit_Object *object; - int result; - - void run() - { - Simple_Thread::run(); - if (object) { - object->thread = this; - QTimer::singleShot(100, object, SLOT(slot())); - } - result = exec(); - } -}; - -class Sleep_Thread : public Simple_Thread -{ -public: - enum SleepType { Second, Millisecond, Microsecond }; - - SleepType sleepType; - int interval; - - int elapsed; // result, in *MILLISECONDS* - - void run() - { - QMutexLocker locker(&mutex); - - elapsed = 0; - QTime time; - time.start(); - switch (sleepType) { - case Second: - sleep(interval); - break; - case Millisecond: - msleep(interval); - break; - case Microsecond: - usleep(interval); - break; - } - elapsed = time.elapsed(); - - cond.wakeOne(); - } -}; - -tst_QThread::tst_QThread() - -{ -} - -tst_QThread::~tst_QThread() -{ - -} - -void tst_QThread::currentThreadId() -{ - Current_Thread thread; - thread.id = 0; - thread.thread = 0; - thread.start(); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.id != 0); - QVERIFY(thread.id != QThread::currentThreadId()); -} - -void tst_QThread::currentThread() -{ - QVERIFY(QThread::currentThread() != 0); - QCOMPARE(QThread::currentThread(), thread()); - - Current_Thread thread; - thread.id = 0; - thread.thread = 0; - thread.start(); - QVERIFY(thread.wait(five_minutes)); - QCOMPARE(thread.thread, (QThread *)&thread); -} - -void tst_QThread::idealThreadCount() -{ - QVERIFY(QThread::idealThreadCount() > 0); - qDebug() << "Available cpu cores:" << QThread::idealThreadCount(); -} - -void tst_QThread::isFinished() -{ - Simple_Thread thread; - QVERIFY(!thread.isFinished()); - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(!thread.isFinished()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); -} - -void tst_QThread::isRunning() -{ - Simple_Thread thread; - QVERIFY(!thread.isRunning()); - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(!thread.isRunning()); -} - -void tst_QThread::setPriority() -{ - Simple_Thread thread; - - // cannot change the priority, since the thread is not running - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::IdlePriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::LowestPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::LowPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::NormalPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::HighPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::HighestPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::TimeCriticalPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - - QCOMPARE(thread.priority(), QThread::InheritPriority); - QMutexLocker locker(&thread.mutex); - thread.start(); - - // change the priority of a running thread - QCOMPARE(thread.priority(), QThread::InheritPriority); - thread.setPriority(QThread::IdlePriority); - QCOMPARE(thread.priority(), QThread::IdlePriority); - thread.setPriority(QThread::LowestPriority); - QCOMPARE(thread.priority(), QThread::LowestPriority); - thread.setPriority(QThread::LowPriority); - QCOMPARE(thread.priority(), QThread::LowPriority); - thread.setPriority(QThread::NormalPriority); - QCOMPARE(thread.priority(), QThread::NormalPriority); - thread.setPriority(QThread::HighPriority); - QCOMPARE(thread.priority(), QThread::HighPriority); - thread.setPriority(QThread::HighestPriority); - QCOMPARE(thread.priority(), QThread::HighestPriority); - thread.setPriority(QThread::TimeCriticalPriority); - QCOMPARE(thread.priority(), QThread::TimeCriticalPriority); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::IdlePriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::LowestPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::LowPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::NormalPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::HighPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::HighestPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); - QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running"); - thread.setPriority(QThread::TimeCriticalPriority); - QCOMPARE(thread.priority(), QThread::InheritPriority); -} - -void tst_QThread::priority() -{ DEPENDS_ON("setPriority"); } - -void tst_QThread::setStackSize() -{ - Simple_Thread thread; - QCOMPARE(thread.stackSize(), 0u); - thread.setStackSize(8192u); - QCOMPARE(thread.stackSize(), 8192u); - thread.setStackSize(0u); - QCOMPARE(thread.stackSize(), 0u); -} - -void tst_QThread::stackSize() -{ - DEPENDS_ON("setStackSize"); -} - -void tst_QThread::exit() -{ - Exit_Thread thread; - thread.object = new Exit_Object; - thread.object->moveToThread(&thread); - thread.code = 42; - thread.result = 0; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, thread.code); - delete thread.object; - - Exit_Thread thread2; - thread2.object = 0; - thread2.code = 53; - thread2.result = 0; - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - thread2.exit(thread2.code); - thread2.cond.wait(locker2.mutex()); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, thread2.code); -} - -void tst_QThread::start() -{ - QThread::Priority priorities[] = { - QThread::IdlePriority, - QThread::LowestPriority, - QThread::LowPriority, - QThread::NormalPriority, - QThread::HighPriority, - QThread::HighestPriority, - QThread::TimeCriticalPriority, - QThread::InheritPriority - }; - const int prio_count = sizeof(priorities) / sizeof(QThread::Priority); - - for (int i = 0; i < prio_count; ++i) { - Simple_Thread thread; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - QMutexLocker locker(&thread.mutex); - thread.start(priorities[i]); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - } -} - -void tst_QThread::terminate() -{ - Terminate_Thread thread; - { - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.cond.wait(locker.mutex(), five_minutes)); - thread.terminate(); - thread.cond.wakeOne(); - } - QVERIFY(thread.wait(five_minutes)); -} - -void tst_QThread::quit() -{ - Quit_Thread thread; - thread.object = new Quit_Object; - thread.object->moveToThread(&thread); - thread.result = -1; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, 0); - delete thread.object; - - Quit_Thread thread2; - thread2.object = 0; - thread2.result = -1; - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - thread2.quit(); - thread2.cond.wait(locker2.mutex()); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, 0); -} - -void tst_QThread::wait() -{ - DEPENDS_ON("isRunning"); - DEPENDS_ON("isFinished"); -} - -void tst_QThread::started() -{ - SignalRecorder recorder; - Simple_Thread thread; - connect(&thread, SIGNAL(started()), &recorder, SLOT(slot()), Qt::DirectConnection); - thread.start(); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(recorder.wasActivated()); -} - -void tst_QThread::finished() -{ - SignalRecorder recorder; - Simple_Thread thread; - connect(&thread, SIGNAL(finished()), &recorder, SLOT(slot()), Qt::DirectConnection); - thread.start(); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(recorder.wasActivated()); -} - -void tst_QThread::terminated() -{ - SignalRecorder recorder; - Terminate_Thread thread; - connect(&thread, SIGNAL(terminated()), &recorder, SLOT(slot()), Qt::DirectConnection); - { - QMutexLocker locker(&thread.mutex); - thread.start(); - thread.cond.wait(locker.mutex()); - thread.terminate(); - thread.cond.wakeOne(); - } - QVERIFY(thread.wait(five_minutes)); - QVERIFY(recorder.wasActivated()); -} - -void tst_QThread::run() -{ DEPENDS_ON("wait()"); } - -void tst_QThread::exec() -{ - DEPENDS_ON("exit()"); - DEPENDS_ON("quit()"); - - class MultipleExecThread : public QThread - { - public: - int res1, res2; - - MultipleExecThread() : res1(-2), res2(-2) { } - - void run() - { - { - Exit_Object o; - o.thread = this; - o.code = 1; - QTimer::singleShot(100, &o, SLOT(slot())); - res1 = exec(); - } - { - Exit_Object o; - o.thread = this; - o.code = 2; - QTimer::singleShot(100, &o, SLOT(slot())); - res2 = exec(); - } - } - }; - - MultipleExecThread thread; - thread.start(); - QVERIFY(thread.wait()); - - QCOMPARE(thread.res1, 1); - QCOMPARE(thread.res2, 2); -} - -void tst_QThread::setTerminationEnabled() -{ DEPENDS_ON("terminate"); } - -void tst_QThread::sleep() -{ - Sleep_Thread thread; - thread.sleepType = Sleep_Thread::Second; - thread.interval = 2; - thread.start(); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.elapsed >= 2000); -} - -void tst_QThread::msleep() -{ - Sleep_Thread thread; - thread.sleepType = Sleep_Thread::Millisecond; - thread.interval = 120; - thread.start(); - QVERIFY(thread.wait(five_minutes)); -#if defined (Q_OS_WIN) - // Since the resolution of QTime is so coarse... - QVERIFY(thread.elapsed >= 100); -#else - QVERIFY(thread.elapsed >= 120); -#endif -} - -void tst_QThread::usleep() -{ - Sleep_Thread thread; - thread.sleepType = Sleep_Thread::Microsecond; - thread.interval = 120000; - thread.start(); - QVERIFY(thread.wait(five_minutes)); -#if defined (Q_OS_WIN) - // Since the resolution of QTime is so coarse... - QVERIFY(thread.elapsed >= 100); -#else - QVERIFY(thread.elapsed >= 120); -#endif -} - -typedef void (*FunctionPointer)(void *); -void noop(void*) { } - -#ifdef Q_OS_SYMBIAN -typedef RThread ThreadHandle; -#elif defined Q_OS_UNIX - typedef pthread_t ThreadHandle; -#elif defined Q_OS_WIN - typedef HANDLE ThreadHandle; -#endif - -#ifdef Q_OS_WIN -#define WIN_FIX_STDCALL __stdcall -#else -#define WIN_FIX_STDCALL -#endif - -class NativeThreadWrapper -{ -public: - NativeThreadWrapper() : qthread(0), waitForStop(false) {} - void start(FunctionPointer functionPointer = noop, void *data = 0); - void startAndWait(FunctionPointer functionPointer = noop, void *data = 0); - void join(); - void setWaitForStop() { waitForStop = true; } - void stop(); - - ThreadHandle nativeThreadHandle; - QThread *qthread; - QWaitCondition startCondition; - QMutex mutex; - bool waitForStop; - QWaitCondition stopCondition; -protected: - static void *runUnix(void *data); - static unsigned WIN_FIX_STDCALL runWin(void *data); - static int runSymbian(void *data); - - FunctionPointer functionPointer; - void *data; -}; - -void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data) -{ - this->functionPointer = functionPointer; - this->data = data; -#ifdef Q_OS_SYMBIAN - qt_symbian_throwIfError(nativeThreadHandle.Create(KNullDesC(), NativeThreadWrapper::runSymbian, 1024, &User::Allocator(), this)); - nativeThreadHandle.Resume(); -#elif defined Q_OS_UNIX - const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this); - Q_UNUSED(state); -#elif defined(Q_OS_WINCE) - nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL); -#elif defined Q_OS_WIN - unsigned thrdid = 0; - nativeThreadHandle = (Qt::HANDLE) _beginthreadex(NULL, 0, NativeThreadWrapper::runWin, this, 0, &thrdid); -#endif -} - -void NativeThreadWrapper::startAndWait(FunctionPointer functionPointer, void *data) -{ - QMutexLocker locker(&mutex); - start(functionPointer, data); - startCondition.wait(locker.mutex()); -} - -void NativeThreadWrapper::join() -{ -#ifdef Q_OS_SYMBIAN - TRequestStatus stat; - nativeThreadHandle.Logon(stat); - User::WaitForRequest(stat); - nativeThreadHandle.Close(); -#elif defined Q_OS_UNIX - pthread_join(nativeThreadHandle, 0); -#elif defined Q_OS_WIN - WaitForSingleObject(nativeThreadHandle, INFINITE); - CloseHandle(nativeThreadHandle); -#endif -} - -void *NativeThreadWrapper::runUnix(void *that) -{ - NativeThreadWrapper *nativeThreadWrapper = reinterpret_cast<NativeThreadWrapper*>(that); - - // Adopt thread, create QThread object. - nativeThreadWrapper->qthread = QThread::currentThread(); - - // Release main thread. - { - QMutexLocker lock(&nativeThreadWrapper->mutex); - nativeThreadWrapper->startCondition.wakeOne(); - } - - // Run function. - nativeThreadWrapper->functionPointer(nativeThreadWrapper->data); - - // Wait for stop. - { - QMutexLocker lock(&nativeThreadWrapper->mutex); - if (nativeThreadWrapper->waitForStop) - nativeThreadWrapper->stopCondition.wait(lock.mutex()); - } - - return 0; -} - -unsigned WIN_FIX_STDCALL NativeThreadWrapper::runWin(void *data) -{ - runUnix(data); - return 0; -} - -int NativeThreadWrapper::runSymbian(void *data) -{ - runUnix(data); - return 0; -} - -void NativeThreadWrapper::stop() -{ - QMutexLocker lock(&mutex); - waitForStop = false; - stopCondition.wakeOne(); -} - -bool threadAdoptedOk = false; -QThread *mainThread; -void testNativeThreadAdoption(void *) -{ - threadAdoptedOk = (QThread::currentThreadId() != 0 - && QThread::currentThread() != 0 - && QThread::currentThread() != mainThread); -} -void tst_QThread::nativeThreadAdoption() -{ - threadAdoptedOk = false; - mainThread = QThread::currentThread(); - NativeThreadWrapper nativeThread; - nativeThread.setWaitForStop(); - nativeThread.startAndWait(testNativeThreadAdoption); - QVERIFY(nativeThread.qthread); - - nativeThread.stop(); - nativeThread.join(); - - QVERIFY(threadAdoptedOk); -} - -void adoptedThreadAffinityFunction(void *arg) -{ - QThread **affinity = reinterpret_cast<QThread **>(arg); - QThread *current = QThread::currentThread(); - affinity[0] = current; - affinity[1] = current->thread(); -} - -void tst_QThread::adoptedThreadAffinity() -{ - QThread *affinity[2] = { 0, 0 }; - - NativeThreadWrapper thread; - thread.startAndWait(adoptedThreadAffinityFunction, affinity); - thread.join(); - - // adopted thread should have affinity to itself - QCOMPARE(affinity[0], affinity[1]); -} - -void tst_QThread::adoptedThreadSetPriority() -{ - - NativeThreadWrapper nativeThread; - nativeThread.setWaitForStop(); - nativeThread.startAndWait(); - - // change the priority of a running thread - QCOMPARE(nativeThread.qthread->priority(), QThread::InheritPriority); - nativeThread.qthread->setPriority(QThread::IdlePriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::IdlePriority); - nativeThread.qthread->setPriority(QThread::LowestPriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::LowestPriority); - nativeThread.qthread->setPriority(QThread::LowPriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::LowPriority); - nativeThread.qthread->setPriority(QThread::NormalPriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::NormalPriority); - nativeThread.qthread->setPriority(QThread::HighPriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::HighPriority); - nativeThread.qthread->setPriority(QThread::HighestPriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::HighestPriority); - nativeThread.qthread->setPriority(QThread::TimeCriticalPriority); - QCOMPARE(nativeThread.qthread->priority(), QThread::TimeCriticalPriority); - - nativeThread.stop(); - nativeThread.join(); -} - -void tst_QThread::adoptedThreadExit() -{ - NativeThreadWrapper nativeThread; - nativeThread.setWaitForStop(); - - nativeThread.startAndWait(); - QVERIFY(nativeThread.qthread); - QVERIFY(nativeThread.qthread->isRunning()); - QVERIFY(!nativeThread.qthread->isFinished()); - - nativeThread.stop(); - nativeThread.join(); -} - -void adoptedThreadExecFunction(void *) -{ - QThread * const adoptedThread = QThread::currentThread(); - QEventLoop eventLoop(adoptedThread); - - const int code = 1; - Exit_Object o; - o.thread = adoptedThread; - o.code = code; - QTimer::singleShot(100, &o, SLOT(slot())); - - const int result = eventLoop.exec(); - QCOMPARE(result, code); -} - -void tst_QThread::adoptedThreadExec() -{ - NativeThreadWrapper nativeThread; - nativeThread.start(adoptedThreadExecFunction); - nativeThread.join(); -} - -/* - Test that you get the finished signal when an adopted thread exits. -*/ -void tst_QThread::adoptedThreadFinished() -{ - NativeThreadWrapper nativeThread; - nativeThread.setWaitForStop(); - nativeThread.startAndWait(); - - QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - - nativeThread.stop(); - nativeThread.join(); - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); -} - -void tst_QThread::adoptedThreadExecFinished() -{ - NativeThreadWrapper nativeThread; - nativeThread.setWaitForStop(); - nativeThread.startAndWait(adoptedThreadExecFunction); - - QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - - nativeThread.stop(); - nativeThread.join(); - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); -} - -void tst_QThread::adoptMultipleThreads() -{ -#if defined(Q_OS_WIN) - // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already. -# if defined(Q_OS_WINCE) - const int numThreads = 20; -# else - // need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher() - const int numThreads = 200; -# endif -#else - const int numThreads = 5; -#endif - QVector<NativeThreadWrapper*> nativeThreads; - - SignalRecorder recorder; - - for (int i = 0; i < numThreads; ++i) { - nativeThreads.append(new NativeThreadWrapper()); - nativeThreads.at(i)->setWaitForStop(); - nativeThreads.at(i)->startAndWait(); - QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot())); - } - - QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - - for (int i = 0; i < numThreads; ++i) { - nativeThreads.at(i)->stop(); - nativeThreads.at(i)->join(); - delete nativeThreads.at(i); - } - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(int(recorder.activationCount), numThreads); -} - -void tst_QThread::adoptMultipleThreadsOverlap() -{ -#if defined(Q_OS_WIN) - // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already. -# if defined(Q_OS_WINCE) - const int numThreads = 20; -# else - // need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher() - const int numThreads = 200; -# endif -#elif defined(Q_OS_SYMBIAN) - // stress the monitoring thread's add function - const int numThreads = 100; -#else - const int numThreads = 5; -#endif - QVector<NativeThreadWrapper*> nativeThreads; - - SignalRecorder recorder; - - for (int i = 0; i < numThreads; ++i) { - nativeThreads.append(new NativeThreadWrapper()); - nativeThreads.at(i)->setWaitForStop(); - nativeThreads.at(i)->mutex.lock(); - nativeThreads.at(i)->start(); - } - for (int i = 0; i < numThreads; ++i) { - nativeThreads.at(i)->startCondition.wait(&nativeThreads.at(i)->mutex); - QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot())); - nativeThreads.at(i)->mutex.unlock(); - } - - QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - - for (int i = 0; i < numThreads; ++i) { - nativeThreads.at(i)->stop(); - nativeThreads.at(i)->join(); - delete nativeThreads.at(i); - } - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(!QTestEventLoop::instance().timeout()); - QCOMPARE(int(recorder.activationCount), numThreads); -} -void tst_QThread::stressTest() -{ -#if defined(Q_OS_WINCE) - QSKIP("Disconnects on WinCE, skipping...", SkipAll); -#endif - QTime t; - t.start(); - while (t.elapsed() < one_minute) { - Current_Thread t; - t.start(); - t.wait(one_minute); - } -} - -class Syncronizer : public QObject -{ Q_OBJECT -public slots: - void setProp(int p) { - if(m_prop != p) { - m_prop = p; - emit propChanged(p); - } - } -signals: - void propChanged(int); -public: - Syncronizer() : m_prop(42) {} - int m_prop; -}; - -void tst_QThread::QTBUG13810_exitAndStart() -{ - QThread thread; - thread.exit(555); //should do nothing - - thread.start(); - - //test that the thread is running by executing queued connected signal there - Syncronizer sync1; - sync1.moveToThread(&thread); - Syncronizer sync2; - sync2.moveToThread(&thread); - connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection); - connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection); - QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89)); - QTest::qWait(50); - while(!thread.wait(10)) - QTest::qWait(10); - QCOMPARE(sync2.m_prop, 89); - QCOMPARE(sync1.m_prop, 89); -} - -void tst_QThread::QTBUG15378_exitAndExec() -{ - class Thread : public QThread { - public: - QSemaphore sem1; - QSemaphore sem2; - volatile int value; - void run() { - sem1.acquire(); - value = exec(); //First entrence - sem2.release(); - value = exec(); // Second loop - } - }; - Thread thread; - thread.value = 0; - thread.start(); - thread.exit(556); - thread.sem1.release(); //should exit the first loop - thread.sem2.acquire(); - int v = thread.value; - QCOMPARE(v, 556); - - //test that the thread is running by executing queued connected signal there - Syncronizer sync1; - sync1.moveToThread(&thread); - Syncronizer sync2; - sync2.moveToThread(&thread); - connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection); - connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection); - QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89)); - QTest::qWait(50); - while(!thread.wait(10)) - QTest::qWait(10); - QCOMPARE(sync2.m_prop, 89); - QCOMPARE(sync1.m_prop, 89); -} - -void tst_QThread::connectThreadFinishedSignalToObjectDeleteLaterSlot() -{ - QThread thread; - QObject *object = new QObject; - QWeakPointer<QObject> p = object; - QVERIFY(!p.isNull()); - connect(&thread, SIGNAL(started()), &thread, SLOT(quit()), Qt::DirectConnection); - connect(&thread, SIGNAL(finished()), object, SLOT(deleteLater())); - object->moveToThread(&thread); - thread.start(); - QVERIFY(thread.wait(30000)); - QVERIFY(p.isNull()); -} - -class Waiting_Thread : public QThread -{ -public: - enum { WaitTime = 800 }; - QMutex mutex; - QWaitCondition cond1; - QWaitCondition cond2; - - void run() - { - QMutexLocker locker(&mutex); - cond1.wait(&mutex); - cond2.wait(&mutex, WaitTime); - } -}; - -void tst_QThread::wait2() -{ - QElapsedTimer timer; - Waiting_Thread thread; - thread.start(); - timer.start(); - QVERIFY(!thread.wait(Waiting_Thread::WaitTime)); - qint64 elapsed = timer.elapsed(); - - QVERIFY(elapsed >= Waiting_Thread::WaitTime); - //QVERIFY(elapsed < Waiting_Thread::WaitTime * 1.4); - - timer.start(); - thread.cond1.wakeOne(); - QVERIFY(thread.wait(/*Waiting_Thread::WaitTime * 1.4*/)); - elapsed = timer.elapsed(); - QVERIFY(elapsed >= Waiting_Thread::WaitTime); - //QVERIFY(elapsed < Waiting_Thread::WaitTime * 1.4); -} - - -class SlowSlotObject : public QObject { - Q_OBJECT -public: - QMutex mutex; - QWaitCondition cond; -public slots: - void slowSlot() { - QMutexLocker locker(&mutex); - cond.wait(&mutex); - } -}; - -void tst_QThread::wait3_slowDestructor() -{ - SlowSlotObject slow; - QThread thread; - QObject::connect(&thread, SIGNAL(finished()), &slow, SLOT(slowSlot()), Qt::DirectConnection); - - enum { WaitTime = 1800 }; - QElapsedTimer timer; - - thread.start(); - thread.quit(); - //the quit function will cause the thread to finish and enter the slowSlot that is blocking - - timer.start(); - QVERIFY(!thread.wait(Waiting_Thread::WaitTime)); - qint64 elapsed = timer.elapsed(); - - QVERIFY(elapsed >= Waiting_Thread::WaitTime); - //QVERIFY(elapsed < Waiting_Thread::WaitTime * 1.4); - - slow.cond.wakeOne(); - //now the thread should finish quickly - QVERIFY(thread.wait(one_minute)); -} - -void tst_QThread::destroyFinishRace() -{ - class Thread : public QThread { void run() {} }; - for (int i = 0; i < 15; i++) { - Thread *thr = new Thread; - connect(thr, SIGNAL(finished()), thr, SLOT(deleteLater())); - QWeakPointer<QThread> weak(static_cast<QThread*>(thr)); - thr->start(); - while (weak) { - qApp->processEvents(); - qApp->processEvents(); - qApp->processEvents(); - qApp->processEvents(); - } - } -} - -void tst_QThread::startFinishRace() -{ - class Thread : public QThread { - public: - Thread() : i (50) {} - void run() { - i--; - if (!i) disconnect(this, SIGNAL(finished()), 0, 0); - } - int i; - }; - for (int i = 0; i < 15; i++) { - Thread thr; - connect(&thr, SIGNAL(finished()), &thr, SLOT(start())); - thr.start(); - while (!thr.isFinished() || thr.i != 0) { - qApp->processEvents(); - qApp->processEvents(); - qApp->processEvents(); - qApp->processEvents(); - } - QCOMPARE(thr.i, 0); - } -} - -void tst_QThread::startAndQuitCustomEventLoop() -{ - struct Thread : QThread { - void run() { QEventLoop().exec(); } - }; - - for (int i = 0; i < 5; i++) { - Thread t; - t.start(); - t.quit(); - t.wait(); - } -} - - -QTEST_MAIN(tst_QThread) -#include "tst_qthread.moc" |