Use QPointer instead of QWeakPointer.
[profile/ivi/qtbase.git] / tests / auto / corelib / thread / qthread / tst_qthread.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43
44 #include <qcoreapplication.h>
45 #include <qdatetime.h>
46 #include <qmutex.h>
47 #include <qthread.h>
48 #include <qtimer.h>
49 #include <qwaitcondition.h>
50 #include <qdebug.h>
51 #include <qmetaobject.h>
52
53 #ifdef Q_OS_UNIX
54 #include <pthread.h>
55 #endif
56 #if defined(Q_OS_WINCE)
57 #include <windows.h>
58 #elif defined(Q_OS_WIN)
59 #include <process.h>
60 #include <windows.h>
61 #endif
62
63 class tst_QThread : public QObject
64 {
65     Q_OBJECT
66 private slots:
67     void currentThreadId();
68     void currentThread();
69     void idealThreadCount();
70     void isFinished();
71     void isRunning();
72     void setPriority();
73     void setStackSize();
74     void exit();
75     void start();
76     void terminate();
77     void quit();
78     void started();
79     void finished();
80     void terminated();
81     void exec();
82     void sleep();
83     void msleep();
84     void usleep();
85
86     void nativeThreadAdoption();
87     void adoptedThreadAffinity();
88     void adoptedThreadSetPriority();
89     void adoptedThreadExit();
90     void adoptedThreadExec();
91     void adoptedThreadFinished();
92     void adoptedThreadExecFinished();
93     void adoptMultipleThreads();
94     void adoptMultipleThreadsOverlap();
95
96     void exitAndStart();
97     void exitAndExec();
98
99     void connectThreadFinishedSignalToObjectDeleteLaterSlot();
100     void wait2();
101     void wait3_slowDestructor();
102     void destroyFinishRace();
103     void startFinishRace();
104     void startAndQuitCustomEventLoop();
105     void isRunningInFinished();
106
107     void customEventDispatcher();
108
109     void stressTest();
110
111     void quitLock();
112 };
113
114 enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
115
116 class SignalRecorder : public QObject
117 {
118     Q_OBJECT
119 public:
120     QAtomicInt activationCount;
121
122     inline SignalRecorder()
123         : activationCount(0)
124     { }
125
126     bool wasActivated()
127     { return activationCount.load() > 0; }
128
129 public slots:
130     void slot();
131 };
132
133 void SignalRecorder::slot()
134 { activationCount.ref(); }
135
136 class Current_Thread : public QThread
137 {
138 public:
139     Qt::HANDLE id;
140     QThread *thread;
141
142     void run()
143     {
144         id = QThread::currentThreadId();
145         thread = QThread::currentThread();
146     }
147 };
148
149 class Simple_Thread : public QThread
150 {
151 public:
152     QMutex mutex;
153     QWaitCondition cond;
154
155     void run()
156     {
157         QMutexLocker locker(&mutex);
158         cond.wakeOne();
159     }
160 };
161
162 class Exit_Object : public QObject
163 {
164     Q_OBJECT
165 public:
166     QThread *thread;
167     int code;
168 public slots:
169     void slot()
170     { thread->exit(code); }
171 };
172
173 class Exit_Thread : public Simple_Thread
174 {
175 public:
176     Exit_Object *object;
177     int code;
178     int result;
179
180     void run()
181     {
182         Simple_Thread::run();
183         if (object) {
184             object->thread = this;
185             object->code = code;
186             QTimer::singleShot(100, object, SLOT(slot()));
187         }
188         result = exec();
189     }
190 };
191
192 class Terminate_Thread : public Simple_Thread
193 {
194 public:
195     void run()
196     {
197         setTerminationEnabled(false);
198         {
199             QMutexLocker locker(&mutex);
200             cond.wakeOne();
201             cond.wait(&mutex, five_minutes);
202         }
203         setTerminationEnabled(true);
204         qFatal("tst_QThread: test case hung");
205     }
206 };
207
208 class Quit_Object : public QObject
209 {
210     Q_OBJECT
211 public:
212     QThread *thread;
213 public slots:
214     void slot()
215     { thread->quit(); }
216 };
217
218 class Quit_Thread : public Simple_Thread
219 {
220 public:
221     Quit_Object *object;
222     int result;
223
224     void run()
225     {
226         Simple_Thread::run();
227         if (object) {
228             object->thread = this;
229             QTimer::singleShot(100, object, SLOT(slot()));
230         }
231         result = exec();
232     }
233 };
234
235 class Sleep_Thread : public Simple_Thread
236 {
237 public:
238     enum SleepType { Second, Millisecond, Microsecond };
239
240     SleepType sleepType;
241     int interval;
242
243     int elapsed; // result, in *MILLISECONDS*
244
245     void run()
246     {
247         QMutexLocker locker(&mutex);
248
249         elapsed = 0;
250         QTime time;
251         time.start();
252         switch (sleepType) {
253         case Second:
254             sleep(interval);
255             break;
256         case Millisecond:
257             msleep(interval);
258             break;
259         case Microsecond:
260             usleep(interval);
261             break;
262         }
263         elapsed = time.elapsed();
264
265         cond.wakeOne();
266     }
267 };
268
269 void tst_QThread::currentThreadId()
270 {
271     Current_Thread thread;
272     thread.id = 0;
273     thread.thread = 0;
274     thread.start();
275     QVERIFY(thread.wait(five_minutes));
276     QVERIFY(thread.id != 0);
277     QVERIFY(thread.id != QThread::currentThreadId());
278 }
279
280 void tst_QThread::currentThread()
281 {
282     QVERIFY(QThread::currentThread() != 0);
283     QCOMPARE(QThread::currentThread(), thread());
284
285     Current_Thread thread;
286     thread.id = 0;
287     thread.thread = 0;
288     thread.start();
289     QVERIFY(thread.wait(five_minutes));
290     QCOMPARE(thread.thread, (QThread *)&thread);
291 }
292
293 void tst_QThread::idealThreadCount()
294 {
295     QVERIFY(QThread::idealThreadCount() > 0);
296     qDebug() << "Ideal thread count:" << QThread::idealThreadCount();
297 }
298
299 void tst_QThread::isFinished()
300 {
301     Simple_Thread thread;
302     QVERIFY(!thread.isFinished());
303     QMutexLocker locker(&thread.mutex);
304     thread.start();
305     QVERIFY(!thread.isFinished());
306     thread.cond.wait(locker.mutex());
307     QVERIFY(thread.wait(five_minutes));
308     QVERIFY(thread.isFinished());
309 }
310
311 void tst_QThread::isRunning()
312 {
313     Simple_Thread thread;
314     QVERIFY(!thread.isRunning());
315     QMutexLocker locker(&thread.mutex);
316     thread.start();
317     QVERIFY(thread.isRunning());
318     thread.cond.wait(locker.mutex());
319     QVERIFY(thread.wait(five_minutes));
320     QVERIFY(!thread.isRunning());
321 }
322
323 void tst_QThread::setPriority()
324 {
325     Simple_Thread thread;
326
327     // cannot change the priority, since the thread is not running
328     QCOMPARE(thread.priority(), QThread::InheritPriority);
329     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
330     thread.setPriority(QThread::IdlePriority);
331     QCOMPARE(thread.priority(), QThread::InheritPriority);
332     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
333     thread.setPriority(QThread::LowestPriority);
334     QCOMPARE(thread.priority(), QThread::InheritPriority);
335     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
336     thread.setPriority(QThread::LowPriority);
337     QCOMPARE(thread.priority(), QThread::InheritPriority);
338     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
339     thread.setPriority(QThread::NormalPriority);
340     QCOMPARE(thread.priority(), QThread::InheritPriority);
341     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
342     thread.setPriority(QThread::HighPriority);
343     QCOMPARE(thread.priority(), QThread::InheritPriority);
344     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
345     thread.setPriority(QThread::HighestPriority);
346     QCOMPARE(thread.priority(), QThread::InheritPriority);
347     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
348     thread.setPriority(QThread::TimeCriticalPriority);
349     QCOMPARE(thread.priority(), QThread::InheritPriority);
350
351     QCOMPARE(thread.priority(), QThread::InheritPriority);
352     QMutexLocker locker(&thread.mutex);
353     thread.start();
354
355     // change the priority of a running thread
356     QCOMPARE(thread.priority(), QThread::InheritPriority);
357     thread.setPriority(QThread::IdlePriority);
358     QCOMPARE(thread.priority(), QThread::IdlePriority);
359     thread.setPriority(QThread::LowestPriority);
360     QCOMPARE(thread.priority(), QThread::LowestPriority);
361     thread.setPriority(QThread::LowPriority);
362     QCOMPARE(thread.priority(), QThread::LowPriority);
363     thread.setPriority(QThread::NormalPriority);
364     QCOMPARE(thread.priority(), QThread::NormalPriority);
365     thread.setPriority(QThread::HighPriority);
366     QCOMPARE(thread.priority(), QThread::HighPriority);
367     thread.setPriority(QThread::HighestPriority);
368     QCOMPARE(thread.priority(), QThread::HighestPriority);
369     thread.setPriority(QThread::TimeCriticalPriority);
370     QCOMPARE(thread.priority(), QThread::TimeCriticalPriority);
371     thread.cond.wait(locker.mutex());
372     QVERIFY(thread.wait(five_minutes));
373
374     QCOMPARE(thread.priority(), QThread::InheritPriority);
375     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
376     thread.setPriority(QThread::IdlePriority);
377     QCOMPARE(thread.priority(), QThread::InheritPriority);
378     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
379     thread.setPriority(QThread::LowestPriority);
380     QCOMPARE(thread.priority(), QThread::InheritPriority);
381     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
382     thread.setPriority(QThread::LowPriority);
383     QCOMPARE(thread.priority(), QThread::InheritPriority);
384     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
385     thread.setPriority(QThread::NormalPriority);
386     QCOMPARE(thread.priority(), QThread::InheritPriority);
387     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
388     thread.setPriority(QThread::HighPriority);
389     QCOMPARE(thread.priority(), QThread::InheritPriority);
390     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
391     thread.setPriority(QThread::HighestPriority);
392     QCOMPARE(thread.priority(), QThread::InheritPriority);
393     QTest::ignoreMessage(QtWarningMsg, "QThread::setPriority: Cannot set priority, thread is not running");
394     thread.setPriority(QThread::TimeCriticalPriority);
395     QCOMPARE(thread.priority(), QThread::InheritPriority);
396 }
397
398 void tst_QThread::setStackSize()
399 {
400     Simple_Thread thread;
401     QCOMPARE(thread.stackSize(), 0u);
402     thread.setStackSize(8192u);
403     QCOMPARE(thread.stackSize(), 8192u);
404     thread.setStackSize(0u);
405     QCOMPARE(thread.stackSize(), 0u);
406 }
407
408 void tst_QThread::exit()
409 {
410     Exit_Thread thread;
411     thread.object = new Exit_Object;
412     thread.object->moveToThread(&thread);
413     thread.code = 42;
414     thread.result = 0;
415     QVERIFY(!thread.isFinished());
416     QVERIFY(!thread.isRunning());
417     QMutexLocker locker(&thread.mutex);
418     thread.start();
419     QVERIFY(thread.isRunning());
420     QVERIFY(!thread.isFinished());
421     thread.cond.wait(locker.mutex());
422     QVERIFY(thread.wait(five_minutes));
423     QVERIFY(thread.isFinished());
424     QVERIFY(!thread.isRunning());
425     QCOMPARE(thread.result, thread.code);
426     delete thread.object;
427
428     Exit_Thread thread2;
429     thread2.object = 0;
430     thread2.code = 53;
431     thread2.result = 0;
432     QMutexLocker locker2(&thread2.mutex);
433     thread2.start();
434     thread2.exit(thread2.code);
435     thread2.cond.wait(locker2.mutex());
436     QVERIFY(thread2.wait(five_minutes));
437     QCOMPARE(thread2.result, thread2.code);
438 }
439
440 void tst_QThread::start()
441 {
442     QThread::Priority priorities[] = {
443         QThread::IdlePriority,
444         QThread::LowestPriority,
445         QThread::LowPriority,
446         QThread::NormalPriority,
447         QThread::HighPriority,
448         QThread::HighestPriority,
449         QThread::TimeCriticalPriority,
450         QThread::InheritPriority
451     };
452     const int prio_count = sizeof(priorities) / sizeof(QThread::Priority);
453
454     for (int i = 0; i < prio_count; ++i) {
455         Simple_Thread thread;
456         QVERIFY(!thread.isFinished());
457         QVERIFY(!thread.isRunning());
458         QMutexLocker locker(&thread.mutex);
459         thread.start(priorities[i]);
460         QVERIFY(thread.isRunning());
461         QVERIFY(!thread.isFinished());
462         thread.cond.wait(locker.mutex());
463         QVERIFY(thread.wait(five_minutes));
464         QVERIFY(thread.isFinished());
465         QVERIFY(!thread.isRunning());
466     }
467 }
468
469 void tst_QThread::terminate()
470 {
471     Terminate_Thread thread;
472     {
473         QMutexLocker locker(&thread.mutex);
474         thread.start();
475         QVERIFY(thread.cond.wait(locker.mutex(), five_minutes));
476         thread.terminate();
477         thread.cond.wakeOne();
478     }
479     QVERIFY(thread.wait(five_minutes));
480 }
481
482 void tst_QThread::quit()
483 {
484     Quit_Thread thread;
485     thread.object = new Quit_Object;
486     thread.object->moveToThread(&thread);
487     thread.result = -1;
488     QVERIFY(!thread.isFinished());
489     QVERIFY(!thread.isRunning());
490     QMutexLocker locker(&thread.mutex);
491     thread.start();
492     QVERIFY(thread.isRunning());
493     QVERIFY(!thread.isFinished());
494     thread.cond.wait(locker.mutex());
495     QVERIFY(thread.wait(five_minutes));
496     QVERIFY(thread.isFinished());
497     QVERIFY(!thread.isRunning());
498     QCOMPARE(thread.result, 0);
499     delete thread.object;
500
501     Quit_Thread thread2;
502     thread2.object = 0;
503     thread2.result = -1;
504     QMutexLocker locker2(&thread2.mutex);
505     thread2.start();
506     thread2.quit();
507     thread2.cond.wait(locker2.mutex());
508     QVERIFY(thread2.wait(five_minutes));
509     QCOMPARE(thread2.result, 0);
510 }
511
512 void tst_QThread::started()
513 {
514     SignalRecorder recorder;
515     Simple_Thread thread;
516     connect(&thread, SIGNAL(started()), &recorder, SLOT(slot()), Qt::DirectConnection);
517     thread.start();
518     QVERIFY(thread.wait(five_minutes));
519     QVERIFY(recorder.wasActivated());
520 }
521
522 void tst_QThread::finished()
523 {
524     SignalRecorder recorder;
525     Simple_Thread thread;
526     connect(&thread, SIGNAL(finished()), &recorder, SLOT(slot()), Qt::DirectConnection);
527     thread.start();
528     QVERIFY(thread.wait(five_minutes));
529     QVERIFY(recorder.wasActivated());
530 }
531
532 void tst_QThread::terminated()
533 {
534     SignalRecorder recorder;
535     Terminate_Thread thread;
536     connect(&thread, SIGNAL(terminated()), &recorder, SLOT(slot()), Qt::DirectConnection);
537     {
538         QMutexLocker locker(&thread.mutex);
539         thread.start();
540         thread.cond.wait(locker.mutex());
541         thread.terminate();
542         thread.cond.wakeOne();
543     }
544     QVERIFY(thread.wait(five_minutes));
545     QVERIFY(recorder.wasActivated());
546 }
547
548 void tst_QThread::exec()
549 {
550     class MultipleExecThread : public QThread
551     {
552     public:
553         int res1, res2;
554
555         MultipleExecThread() : res1(-2), res2(-2) { }
556
557         void run()
558         {
559             {
560                 Exit_Object o;
561                 o.thread = this;
562                 o.code = 1;
563                 QTimer::singleShot(100, &o, SLOT(slot()));
564                 res1 = exec();
565             }
566             {
567                 Exit_Object o;
568                 o.thread = this;
569                 o.code = 2;
570                 QTimer::singleShot(100, &o, SLOT(slot()));
571                 res2 = exec();
572             }
573         }
574     };
575
576     MultipleExecThread thread;
577     thread.start();
578     QVERIFY(thread.wait());
579
580     QCOMPARE(thread.res1, 1);
581     QCOMPARE(thread.res2, 2);
582 }
583
584 void tst_QThread::sleep()
585 {
586     Sleep_Thread thread;
587     thread.sleepType = Sleep_Thread::Second;
588     thread.interval = 2;
589     thread.start();
590     QVERIFY(thread.wait(five_minutes));
591     QVERIFY(thread.elapsed >= 2000);
592 }
593
594 void tst_QThread::msleep()
595 {
596     Sleep_Thread thread;
597     thread.sleepType = Sleep_Thread::Millisecond;
598     thread.interval = 120;
599     thread.start();
600     QVERIFY(thread.wait(five_minutes));
601 #if defined (Q_OS_WIN)
602     // Since the resolution of QTime is so coarse...
603     QVERIFY(thread.elapsed >= 100);
604 #else
605     QVERIFY(thread.elapsed >= 120);
606 #endif
607 }
608
609 void tst_QThread::usleep()
610 {
611     Sleep_Thread thread;
612     thread.sleepType = Sleep_Thread::Microsecond;
613     thread.interval = 120000;
614     thread.start();
615     QVERIFY(thread.wait(five_minutes));
616 #if defined (Q_OS_WIN)
617     // Since the resolution of QTime is so coarse...
618     QVERIFY(thread.elapsed >= 100);
619 #else
620     QVERIFY(thread.elapsed >= 120);
621 #endif
622 }
623
624 typedef void (*FunctionPointer)(void *);
625 void noop(void*) { }
626
627 #if defined Q_OS_UNIX
628     typedef pthread_t ThreadHandle;
629 #elif defined Q_OS_WIN
630     typedef HANDLE ThreadHandle;
631 #endif
632
633 #ifdef Q_OS_WIN
634 #define WIN_FIX_STDCALL __stdcall
635 #else
636 #define WIN_FIX_STDCALL
637 #endif
638
639 class NativeThreadWrapper
640 {
641 public:
642     NativeThreadWrapper() : qthread(0), waitForStop(false) {}
643     void start(FunctionPointer functionPointer = noop, void *data = 0);
644     void startAndWait(FunctionPointer functionPointer = noop, void *data = 0);
645     void join();
646     void setWaitForStop() { waitForStop = true; }
647     void stop();
648
649     ThreadHandle nativeThreadHandle;
650     QThread *qthread;
651     QWaitCondition startCondition;
652     QMutex mutex;
653     bool waitForStop;
654     QWaitCondition stopCondition;
655 protected:
656     static void *runUnix(void *data);
657     static unsigned WIN_FIX_STDCALL runWin(void *data);
658
659     FunctionPointer functionPointer;
660     void *data;
661 };
662
663 void NativeThreadWrapper::start(FunctionPointer functionPointer, void *data)
664 {
665     this->functionPointer = functionPointer;
666     this->data = data;
667 #if defined Q_OS_UNIX
668     const int state = pthread_create(&nativeThreadHandle, 0, NativeThreadWrapper::runUnix, this);
669     Q_UNUSED(state);
670 #elif defined(Q_OS_WINCE)
671         nativeThreadHandle = CreateThread(NULL, 0 , (LPTHREAD_START_ROUTINE)NativeThreadWrapper::runWin , this, 0, NULL);
672 #elif defined Q_OS_WIN
673     unsigned thrdid = 0;
674     nativeThreadHandle = (Qt::HANDLE) _beginthreadex(NULL, 0, NativeThreadWrapper::runWin, this, 0, &thrdid);
675 #endif
676 }
677
678 void NativeThreadWrapper::startAndWait(FunctionPointer functionPointer, void *data)
679 {
680     QMutexLocker locker(&mutex);
681     start(functionPointer, data);
682     startCondition.wait(locker.mutex());
683 }
684
685 void NativeThreadWrapper::join()
686 {
687 #if defined Q_OS_UNIX
688     pthread_join(nativeThreadHandle, 0);
689 #elif defined Q_OS_WIN
690     WaitForSingleObject(nativeThreadHandle, INFINITE);
691     CloseHandle(nativeThreadHandle);
692 #endif
693 }
694
695 void *NativeThreadWrapper::runUnix(void *that)
696 {
697     NativeThreadWrapper *nativeThreadWrapper = reinterpret_cast<NativeThreadWrapper*>(that);
698
699     // Adopt thread, create QThread object.
700     nativeThreadWrapper->qthread = QThread::currentThread();
701
702     // Release main thread.
703     {
704         QMutexLocker lock(&nativeThreadWrapper->mutex);
705         nativeThreadWrapper->startCondition.wakeOne();
706     }
707
708     // Run function.
709     nativeThreadWrapper->functionPointer(nativeThreadWrapper->data);
710
711     // Wait for stop.
712     {
713         QMutexLocker lock(&nativeThreadWrapper->mutex);
714         if (nativeThreadWrapper->waitForStop)
715             nativeThreadWrapper->stopCondition.wait(lock.mutex());
716     }
717
718     return 0;
719 }
720
721 unsigned WIN_FIX_STDCALL NativeThreadWrapper::runWin(void *data)
722 {
723     runUnix(data);
724     return 0;
725 }
726
727 void NativeThreadWrapper::stop()
728 {
729     QMutexLocker lock(&mutex);
730     waitForStop = false;
731     stopCondition.wakeOne();
732 }
733
734 bool threadAdoptedOk = false;
735 QThread *mainThread;
736 void testNativeThreadAdoption(void *)
737 {
738     threadAdoptedOk = (QThread::currentThreadId() != 0
739                        && QThread::currentThread() != 0
740                        && QThread::currentThread() != mainThread);
741 }
742 void tst_QThread::nativeThreadAdoption()
743 {
744     threadAdoptedOk = false;
745     mainThread = QThread::currentThread();
746     NativeThreadWrapper nativeThread;
747     nativeThread.setWaitForStop();
748     nativeThread.startAndWait(testNativeThreadAdoption);
749     QVERIFY(nativeThread.qthread);
750
751     nativeThread.stop();
752     nativeThread.join();
753
754     QVERIFY(threadAdoptedOk);
755 }
756
757 void adoptedThreadAffinityFunction(void *arg)
758 {
759     QThread **affinity = reinterpret_cast<QThread **>(arg);
760     QThread *current = QThread::currentThread();
761     affinity[0] = current;
762     affinity[1] = current->thread();
763 }
764
765 void tst_QThread::adoptedThreadAffinity()
766 {
767     QThread *affinity[2] = { 0, 0 };
768
769     NativeThreadWrapper thread;
770     thread.startAndWait(adoptedThreadAffinityFunction, affinity);
771     thread.join();
772
773     // adopted thread should have affinity to itself
774     QCOMPARE(affinity[0], affinity[1]);
775 }
776
777 void tst_QThread::adoptedThreadSetPriority()
778 {
779
780     NativeThreadWrapper nativeThread;
781     nativeThread.setWaitForStop();
782     nativeThread.startAndWait();
783
784     // change the priority of a running thread
785     QCOMPARE(nativeThread.qthread->priority(), QThread::InheritPriority);
786     nativeThread.qthread->setPriority(QThread::IdlePriority);
787     QCOMPARE(nativeThread.qthread->priority(), QThread::IdlePriority);
788     nativeThread.qthread->setPriority(QThread::LowestPriority);
789     QCOMPARE(nativeThread.qthread->priority(), QThread::LowestPriority);
790     nativeThread.qthread->setPriority(QThread::LowPriority);
791     QCOMPARE(nativeThread.qthread->priority(), QThread::LowPriority);
792     nativeThread.qthread->setPriority(QThread::NormalPriority);
793     QCOMPARE(nativeThread.qthread->priority(), QThread::NormalPriority);
794     nativeThread.qthread->setPriority(QThread::HighPriority);
795     QCOMPARE(nativeThread.qthread->priority(), QThread::HighPriority);
796     nativeThread.qthread->setPriority(QThread::HighestPriority);
797     QCOMPARE(nativeThread.qthread->priority(), QThread::HighestPriority);
798     nativeThread.qthread->setPriority(QThread::TimeCriticalPriority);
799     QCOMPARE(nativeThread.qthread->priority(), QThread::TimeCriticalPriority);
800
801     nativeThread.stop();
802     nativeThread.join();
803 }
804
805 void tst_QThread::adoptedThreadExit()
806 {
807     NativeThreadWrapper nativeThread;
808     nativeThread.setWaitForStop();
809
810     nativeThread.startAndWait();
811     QVERIFY(nativeThread.qthread);
812     QVERIFY(nativeThread.qthread->isRunning());
813     QVERIFY(!nativeThread.qthread->isFinished());
814
815     nativeThread.stop();
816     nativeThread.join();
817 }
818
819 void adoptedThreadExecFunction(void *)
820 {
821     QThread  * const adoptedThread = QThread::currentThread();
822     QEventLoop eventLoop(adoptedThread);
823
824     const int code = 1;
825     Exit_Object o;
826     o.thread = adoptedThread;
827     o.code = code;
828     QTimer::singleShot(100, &o, SLOT(slot()));
829
830     const int result = eventLoop.exec();
831     QCOMPARE(result, code);
832 }
833
834 void tst_QThread::adoptedThreadExec()
835 {
836     NativeThreadWrapper nativeThread;
837     nativeThread.start(adoptedThreadExecFunction);
838     nativeThread.join();
839 }
840
841 /*
842     Test that you get the finished signal when an adopted thread exits.
843 */
844 void tst_QThread::adoptedThreadFinished()
845 {
846     NativeThreadWrapper nativeThread;
847     nativeThread.setWaitForStop();
848     nativeThread.startAndWait();
849
850     QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
851
852     nativeThread.stop();
853     nativeThread.join();
854
855     QTestEventLoop::instance().enterLoop(5);
856     QVERIFY(!QTestEventLoop::instance().timeout());
857 }
858
859 void tst_QThread::adoptedThreadExecFinished()
860 {
861     NativeThreadWrapper nativeThread;
862     nativeThread.setWaitForStop();
863     nativeThread.startAndWait(adoptedThreadExecFunction);
864
865     QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
866
867     nativeThread.stop();
868     nativeThread.join();
869
870     QTestEventLoop::instance().enterLoop(5);
871     QVERIFY(!QTestEventLoop::instance().timeout());
872 }
873
874 void tst_QThread::adoptMultipleThreads()
875 {
876 #if defined(Q_OS_WIN)
877     // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already.
878 #  if defined(Q_OS_WINCE)
879     const int numThreads = 20;
880 #  else
881     // need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher()
882     const int numThreads = 200;
883 #  endif
884 #else
885     const int numThreads = 5;
886 #endif
887     QVector<NativeThreadWrapper*> nativeThreads;
888
889     SignalRecorder recorder;
890
891     for (int i = 0; i < numThreads; ++i) {
892         nativeThreads.append(new NativeThreadWrapper());
893         nativeThreads.at(i)->setWaitForStop();
894         nativeThreads.at(i)->startAndWait();
895         QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot()));
896     }
897
898     QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
899
900     for (int i = 0; i < numThreads; ++i) {
901         nativeThreads.at(i)->stop();
902         nativeThreads.at(i)->join();
903         delete nativeThreads.at(i);
904     }
905
906     QTestEventLoop::instance().enterLoop(5);
907     QVERIFY(!QTestEventLoop::instance().timeout());
908     QCOMPARE(recorder.activationCount.load(), numThreads);
909 }
910
911 void tst_QThread::adoptMultipleThreadsOverlap()
912 {
913 #if defined(Q_OS_WIN)
914     // Windows CE is not capable of handling that many threads. On the emulator it is dead with 26 threads already.
915 #  if defined(Q_OS_WINCE)
916     const int numThreads = 20;
917 #  else
918     // need to test lots of threads, so that we exceed MAXIMUM_WAIT_OBJECTS in qt_adopted_thread_watcher()
919     const int numThreads = 200;
920 #  endif
921 #else
922     const int numThreads = 5;
923 #endif
924     QVector<NativeThreadWrapper*> nativeThreads;
925
926     SignalRecorder recorder;
927
928     for (int i = 0; i < numThreads; ++i) {
929         nativeThreads.append(new NativeThreadWrapper());
930         nativeThreads.at(i)->setWaitForStop();
931         nativeThreads.at(i)->mutex.lock();
932         nativeThreads.at(i)->start();
933     }
934     for (int i = 0; i < numThreads; ++i) {
935         nativeThreads.at(i)->startCondition.wait(&nativeThreads.at(i)->mutex);
936         QObject::connect(nativeThreads.at(i)->qthread, SIGNAL(finished()), &recorder, SLOT(slot()));
937         nativeThreads.at(i)->mutex.unlock();
938     }
939
940     QObject::connect(nativeThreads.at(numThreads - 1)->qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
941
942     for (int i = 0; i < numThreads; ++i) {
943         nativeThreads.at(i)->stop();
944         nativeThreads.at(i)->join();
945         delete nativeThreads.at(i);
946     }
947
948     QTestEventLoop::instance().enterLoop(5);
949     QVERIFY(!QTestEventLoop::instance().timeout());
950     QCOMPARE(recorder.activationCount.load(), numThreads);
951 }
952 void tst_QThread::stressTest()
953 {
954 #if defined(Q_OS_WINCE)
955     QSKIP("Disconnects on WinCE, skipping...");
956 #endif
957     QTime t;
958     t.start();
959     while (t.elapsed() < one_minute) {
960         Current_Thread t;
961         t.start();
962         t.wait(one_minute);
963     }
964 }
965
966 class Syncronizer : public QObject
967 { Q_OBJECT
968 public slots:
969     void setProp(int p) {
970         if(m_prop != p) {
971             m_prop = p;
972             emit propChanged(p);
973         }
974     }
975 signals:
976     void propChanged(int);
977 public:
978     Syncronizer() : m_prop(42) {}
979     int m_prop;
980 };
981
982 void tst_QThread::exitAndStart()
983 {
984     QThread thread;
985     thread.exit(555); //should do nothing
986
987     thread.start();
988
989     //test that the thread is running by executing queued connected signal there
990     Syncronizer sync1;
991     sync1.moveToThread(&thread);
992     Syncronizer sync2;
993     sync2.moveToThread(&thread);
994     connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
995     connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
996     QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
997     QTest::qWait(50);
998     while(!thread.wait(10))
999         QTest::qWait(10);
1000     QCOMPARE(sync2.m_prop, 89);
1001     QCOMPARE(sync1.m_prop, 89);
1002 }
1003
1004 void tst_QThread::exitAndExec()
1005 {
1006     class Thread : public QThread {
1007     public:
1008         QSemaphore sem1;
1009         QSemaphore sem2;
1010         volatile int value;
1011         void run() {
1012             sem1.acquire();
1013             value = exec();  //First entrence
1014             sem2.release();
1015             value = exec(); // Second loop
1016         }
1017     };
1018     Thread thread;
1019     thread.value = 0;
1020     thread.start();
1021     thread.exit(556);
1022     thread.sem1.release(); //should exit the first loop
1023     thread.sem2.acquire();
1024     int v = thread.value;
1025     QCOMPARE(v, 556);
1026     
1027     //test that the thread is running by executing queued connected signal there
1028     Syncronizer sync1;
1029     sync1.moveToThread(&thread);
1030     Syncronizer sync2;
1031     sync2.moveToThread(&thread);
1032     connect(&sync2, SIGNAL(propChanged(int)), &sync1, SLOT(setProp(int)), Qt::QueuedConnection);
1033     connect(&sync1, SIGNAL(propChanged(int)), &thread, SLOT(quit()), Qt::QueuedConnection);
1034     QMetaObject::invokeMethod(&sync2, "setProp", Qt::QueuedConnection , Q_ARG(int, 89));
1035     QTest::qWait(50);
1036     while(!thread.wait(10))
1037         QTest::qWait(10);
1038     QCOMPARE(sync2.m_prop, 89);
1039     QCOMPARE(sync1.m_prop, 89);
1040 }
1041
1042 void tst_QThread::connectThreadFinishedSignalToObjectDeleteLaterSlot()
1043 {
1044     QThread thread;
1045     QObject *object = new QObject;
1046     QPointer<QObject> p = object;
1047     QVERIFY(!p.isNull());
1048     connect(&thread, SIGNAL(started()), &thread, SLOT(quit()), Qt::DirectConnection);
1049     connect(&thread, SIGNAL(finished()), object, SLOT(deleteLater()));
1050     object->moveToThread(&thread);
1051     thread.start();
1052     QVERIFY(thread.wait(30000));
1053     QVERIFY(p.isNull());
1054 }
1055
1056 class Waiting_Thread : public QThread
1057 {
1058 public:
1059     enum { WaitTime = 800 };
1060     QMutex mutex;
1061     QWaitCondition cond1;
1062     QWaitCondition cond2;
1063
1064     void run()
1065     {
1066         QMutexLocker locker(&mutex);
1067         cond1.wait(&mutex);
1068         cond2.wait(&mutex, WaitTime);
1069     }
1070 };
1071
1072 void tst_QThread::wait2()
1073 {
1074     QElapsedTimer timer;
1075     Waiting_Thread thread;
1076     thread.start();
1077     timer.start();
1078     QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
1079     qint64 elapsed = timer.elapsed(); // On Windows, we sometimes get (WaitTime - 1).
1080     QVERIFY2(elapsed >= Waiting_Thread::WaitTime - 1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
1081
1082     timer.start();
1083     thread.cond1.wakeOne();
1084     QVERIFY(thread.wait(/*Waiting_Thread::WaitTime * 1.4*/));
1085     elapsed = timer.elapsed();
1086     QVERIFY2(elapsed - Waiting_Thread::WaitTime >= -1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
1087 }
1088
1089
1090 class SlowSlotObject : public QObject {
1091     Q_OBJECT
1092 public:
1093     QMutex mutex;
1094     QWaitCondition cond;
1095 public slots:
1096     void slowSlot() {
1097         QMutexLocker locker(&mutex);
1098         cond.wait(&mutex);
1099     }
1100 };
1101
1102 void tst_QThread::wait3_slowDestructor()
1103 {
1104     SlowSlotObject slow;
1105     QThread thread;
1106     QObject::connect(&thread, SIGNAL(finished()), &slow, SLOT(slowSlot()), Qt::DirectConnection);
1107
1108     enum { WaitTime = 1800 };
1109     QElapsedTimer timer;
1110
1111     thread.start();
1112     thread.quit();
1113     //the quit function will cause the thread to finish and enter the slowSlot that is blocking
1114
1115     timer.start();
1116     QVERIFY(!thread.wait(Waiting_Thread::WaitTime));
1117     qint64 elapsed = timer.elapsed();
1118     QVERIFY2(elapsed >= Waiting_Thread::WaitTime - 1, qPrintable(QString::fromLatin1("elapsed: %1").arg(elapsed)));
1119
1120     slow.cond.wakeOne();
1121     //now the thread should finish quickly
1122     QVERIFY(thread.wait(one_minute));
1123 }
1124
1125 void tst_QThread::destroyFinishRace()
1126 {
1127     class Thread : public QThread { void run() {} };
1128     for (int i = 0; i < 15; i++) {
1129         Thread *thr = new Thread;
1130         connect(thr, SIGNAL(finished()), thr, SLOT(deleteLater()));
1131         QPointer<QThread> weak(static_cast<QThread*>(thr));
1132         thr->start();
1133         while (weak) {
1134             qApp->processEvents();
1135             qApp->processEvents();
1136             qApp->processEvents();
1137             qApp->processEvents();
1138         }
1139     }
1140 }
1141
1142 void tst_QThread::startFinishRace()
1143 {
1144     class Thread : public QThread {
1145     public:
1146         Thread() : i (50) {}
1147         void run() {
1148             i--;
1149             if (!i) disconnect(this, SIGNAL(finished()), 0, 0);
1150         }
1151         int i;
1152     };
1153     for (int i = 0; i < 15; i++) {
1154         Thread thr;
1155         connect(&thr, SIGNAL(finished()), &thr, SLOT(start()));
1156         thr.start();
1157         while (!thr.isFinished() || thr.i != 0) {
1158             qApp->processEvents();
1159             qApp->processEvents();
1160             qApp->processEvents();
1161             qApp->processEvents();
1162         }
1163         QCOMPARE(thr.i, 0);
1164     }
1165 }
1166
1167 void tst_QThread::startAndQuitCustomEventLoop()
1168 {
1169     struct Thread : QThread {
1170         void run() { QEventLoop().exec(); }
1171     };
1172
1173    for (int i = 0; i < 5; i++) {
1174        Thread t;
1175        t.start();
1176        t.quit();
1177        t.wait();
1178    }
1179 }
1180
1181 class FinishedTestObject : public QObject {
1182     Q_OBJECT
1183 public:
1184     FinishedTestObject() : ok(false) {}
1185     bool ok;
1186 public slots:
1187     void slotFinished() {
1188         QThread *t = qobject_cast<QThread *>(sender());
1189         ok = t && t->isFinished() && !t->isRunning();
1190     }
1191 };
1192
1193 void tst_QThread::isRunningInFinished()
1194 {
1195     for (int i = 0; i < 15; i++) {
1196         QThread thread;
1197         thread.start();
1198         FinishedTestObject localObject;
1199         FinishedTestObject inThreadObject;
1200         localObject.setObjectName("...");
1201         inThreadObject.moveToThread(&thread);
1202         connect(&thread, SIGNAL(finished()), &localObject, SLOT(slotFinished()));
1203         connect(&thread, SIGNAL(finished()), &inThreadObject, SLOT(slotFinished()));
1204         QEventLoop loop;
1205         connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
1206         QMetaObject::invokeMethod(&thread, "quit", Qt::QueuedConnection);
1207         loop.exec();
1208         QVERIFY(!thread.isRunning());
1209         QVERIFY(thread.isFinished());
1210         QVERIFY(localObject.ok);
1211         QVERIFY(inThreadObject.ok);
1212     }
1213 }
1214
1215 QT_BEGIN_NAMESPACE
1216 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
1217 QT_END_NAMESPACE
1218
1219 class DummyEventDispatcher : public QAbstractEventDispatcher {
1220 public:
1221     DummyEventDispatcher() : QAbstractEventDispatcher(), visited(false) {}
1222     bool processEvents(QEventLoop::ProcessEventsFlags) {
1223         visited = true;
1224         emit awake();
1225         QCoreApplication::sendPostedEvents();
1226         return false;
1227     }
1228     bool hasPendingEvents() {
1229         return qGlobalPostedEventsCount();
1230     }
1231     void registerSocketNotifier(QSocketNotifier *) {}
1232     void unregisterSocketNotifier(QSocketNotifier *) {}
1233     void registerTimer(int, int, Qt::TimerType, QObject *) {}
1234     bool unregisterTimer(int ) { return false; }
1235     bool unregisterTimers(QObject *) { return false; }
1236     QList<TimerInfo> registeredTimers(QObject *) const { return QList<TimerInfo>(); }
1237     int remainingTime(int) { return 0; }
1238     void wakeUp() {}
1239     void interrupt() {}
1240     void flush() {}
1241
1242 #ifdef Q_OS_WIN
1243     bool registerEventNotifier(QWinEventNotifier *) { return false; }
1244     void unregisterEventNotifier(QWinEventNotifier *) { }
1245 #endif
1246
1247     bool visited;
1248 };
1249
1250 class ThreadObj : public QObject
1251 {
1252     Q_OBJECT
1253 public slots:
1254     void visit() {
1255         emit visited();
1256     }
1257 signals:
1258     void visited();
1259 };
1260
1261 void tst_QThread::customEventDispatcher()
1262 {
1263     QThread thr;
1264     // there should be no ED yet
1265     QVERIFY(!thr.eventDispatcher());
1266     DummyEventDispatcher *ed = new DummyEventDispatcher;
1267     thr.setEventDispatcher(ed);
1268     // the new ED should be set
1269     QCOMPARE(thr.eventDispatcher(), ed);
1270     // test the alternative API of QAbstractEventDispatcher
1271     QCOMPARE(QAbstractEventDispatcher::instance(&thr), ed);
1272     thr.start();
1273     // start() should not overwrite the ED
1274     QCOMPARE(thr.eventDispatcher(), ed);
1275
1276     ThreadObj obj;
1277     obj.moveToThread(&thr);
1278     // move was successful?
1279     QCOMPARE(obj.thread(), &thr);
1280     QEventLoop loop;
1281     connect(&obj, SIGNAL(visited()), &loop, SLOT(quit()), Qt::QueuedConnection);
1282     QMetaObject::invokeMethod(&obj, "visit", Qt::QueuedConnection);
1283     loop.exec();
1284     // test that the ED has really been used
1285     QVERIFY(ed->visited);
1286
1287     QPointer<DummyEventDispatcher> weak_ed(ed);
1288     QVERIFY(!weak_ed.isNull());
1289     thr.quit();
1290     // wait for thread to be stopped
1291     QVERIFY(thr.wait(30000));
1292     // test that ED has been deleted
1293     QVERIFY(weak_ed.isNull());
1294 }
1295
1296 class Job : public QObject
1297 {
1298     Q_OBJECT
1299 public:
1300     Job(QThread *thread, int deleteDelay, QObject *parent = 0)
1301       : QObject(parent), quitLocker(thread), exitThreadCalled(false)
1302     {
1303         moveToThread(thread);
1304         QTimer::singleShot(deleteDelay, this, SLOT(deleteLater()));
1305         QTimer::singleShot(1000, this, SLOT(exitThread()));
1306     }
1307
1308 private slots:
1309     void exitThread()
1310     {
1311         exitThreadCalled = true;
1312         thread()->exit(1);
1313     }
1314
1315 private:
1316     QEventLoopLocker quitLocker;
1317 public:
1318     bool exitThreadCalled;
1319 };
1320
1321 void tst_QThread::quitLock()
1322 {
1323     QThread thread;
1324
1325     QEventLoop loop;
1326     connect(&thread, SIGNAL(finished()), &loop, SLOT(quit()));
1327
1328     Job *job;
1329
1330     thread.start();
1331     job = new Job(&thread, 500);
1332     QCOMPARE(job->thread(), &thread);
1333     loop.exec();
1334     QVERIFY(!job->exitThreadCalled);
1335
1336     thread.start();
1337     job = new Job(&thread, 2500);
1338     QCOMPARE(job->thread(), &thread);
1339     loop.exec();
1340     QVERIFY(job->exitThreadCalled);
1341 }
1342
1343 QTEST_MAIN(tst_QThread)
1344 #include "tst_qthread.moc"