7d54409c231be509ab3a1aefc566e1b69b82d748
[profile/ivi/qtbase.git] / tests / auto / corelib / kernel / qobject / tst_qobject.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43
44 #include <qcoreapplication.h>
45 #include <qpointer.h>
46 #include <qtimer.h>
47 #include <qregexp.h>
48 #include <qmetaobject.h>
49 #include <qvariant.h>
50 #include <QTcpServer>
51 #include <QTcpSocket>
52 #include <QThread>
53 #include <QMutex>
54 #include <QWaitCondition>
55 #include <QProcess>
56
57 #include "qobject.h"
58 #ifdef QT_BUILD_INTERNAL
59 #include <private/qobject_p.h>
60 #endif
61
62 #include <math.h>
63
64 class tst_QObject : public QObject
65 {
66     Q_OBJECT
67 private slots:
68     void initTestCase();
69     void disconnect();
70     void connectByName();
71     void connectSignalsToSignalsWithDefaultArguments();
72     void receivers();
73     void normalize();
74     void qobject_castTemplate();
75     void findChildren();
76     void connectDisconnectNotify_data();
77     void connectDisconnectNotify();
78     void emitInDefinedOrder();
79     void customTypes();
80     void streamCustomTypes();
81     void metamethod();
82     void namespaces();
83     void threadSignalEmissionCrash();
84     void thread();
85     void thread0();
86     void moveToThread();
87     void sender();
88     void declareInterface();
89     void qpointerResetBeforeDestroyedSignal();
90     void testUserData();
91     void childDeletesItsSibling();
92     void dynamicProperties();
93     void floatProperty();
94     void qrealProperty();
95     void property();
96 #ifndef QT_NO_PROCESS
97     void recursiveSignalEmission();
98 #endif
99     void blockingQueuedConnection();
100     void childEvents();
101     void installEventFilter();
102     void deleteSelfInSlot();
103     void disconnectSelfInSlotAndDeleteAfterEmit();
104     void dumpObjectInfo();
105     void connectToSender();
106     void qobjectConstCast();
107     void uniqConnection();
108     void uniqConnectionPtr();
109     void interfaceIid();
110     void deleteQObjectWhenDeletingEvent();
111     void overloads();
112     void isSignalConnected();
113     void qMetaObjectConnect();
114     void qMetaObjectDisconnectOne();
115     void sameName();
116     void connectByMetaMethods();
117     void connectByMetaMethodSlotInsteadOfSignal();
118     void connectConstructorByMetaMethod();
119     void disconnectByMetaMethod();
120     void disconnectNotSignalMetaMethod();
121     void autoConnectionBehavior();
122     void baseDestroyed();
123     void pointerConnect();
124     void pointerDisconnect();
125     void emitInDefinedOrderPointer();
126     void customTypesPointer();
127     void connectCxx0x();
128     void connectToStaticCxx0x();
129     void connectCxx0xTypeMatching();
130     void connectConvert();
131     void connectWithReference();
132     void connectManyArguments();
133     void returnValue_data();
134     void returnValue();
135     void returnValue2_data();
136     void returnValue2();
137 };
138
139 class SenderObject : public QObject
140 {
141     Q_OBJECT
142
143 public:
144     SenderObject() : aPublicSlotCalled(0), recursionCount(0) {}
145
146     void emitSignal1AfterRecursion()
147     {
148         if (recursionCount++ < 100)
149             emitSignal1AfterRecursion();
150         else
151             emitSignal1();
152     }
153
154     void emitSignal1() { emit signal1(); }
155     void emitSignal2() { emit signal2(); }
156     void emitSignal3() { emit signal3(); }
157     void emitSignal4() { emit signal4(); }
158
159 signals:
160     void signal1();
161     void signal2();
162     void signal3();
163     void signal4();
164     QT_MOC_COMPAT void signal5();
165
166 public slots:
167     void aPublicSlot() { aPublicSlotCalled++; }
168
169 public:
170     Q_INVOKABLE void invoke1(){}
171     Q_SCRIPTABLE void sinvoke1(){}
172     int aPublicSlotCalled;
173 protected:
174     Q_INVOKABLE QT_MOC_COMPAT void invoke2(){}
175     Q_INVOKABLE QT_MOC_COMPAT void invoke2(int){}
176     Q_SCRIPTABLE QT_MOC_COMPAT void sinvoke2(){}
177 private:
178     Q_INVOKABLE void invoke3(int hinz = 0, int kunz = 0){Q_UNUSED(hinz) Q_UNUSED(kunz)}
179     Q_SCRIPTABLE void sinvoke3(){}
180
181     int recursionCount;
182 };
183
184 class ReceiverObject : public QObject
185 {
186     Q_OBJECT
187
188 public:
189     ReceiverObject()
190         : sequence_slot1( 0 )
191         , sequence_slot2( 0 )
192         , sequence_slot3( 0 )
193         , sequence_slot4( 0 )
194     {}
195
196     void reset()
197     {
198         sequence_slot4 = 0;
199         sequence_slot3 = 0;
200         sequence_slot2 = 0;
201         sequence_slot1 = 0;
202         count_slot1 = 0;
203         count_slot2 = 0;
204         count_slot3 = 0;
205         count_slot4 = 0;
206     }
207
208     int sequence_slot1;
209     int sequence_slot2;
210     int sequence_slot3;
211     int sequence_slot4;
212     int count_slot1;
213     int count_slot2;
214     int count_slot3;
215     int count_slot4;
216
217     bool called(int slot)
218     {
219         switch (slot) {
220         case 1: return sequence_slot1;
221         case 2: return sequence_slot2;
222         case 3: return sequence_slot3;
223         case 4: return sequence_slot4;
224         default: return false;
225         }
226     }
227
228     static int sequence;
229
230 public slots:
231     void slot1() { sequence_slot1 = ++sequence; count_slot1++; }
232     void slot2() { sequence_slot2 = ++sequence; count_slot2++; }
233     void slot3() { sequence_slot3 = ++sequence; count_slot3++; }
234     void slot4() { sequence_slot4 = ++sequence; count_slot4++; }
235
236 };
237
238 int ReceiverObject::sequence = 0;
239
240 void tst_QObject::initTestCase()
241 {
242     const QString testDataDir = QFileInfo(QFINDTESTDATA("signalbug")).absolutePath();
243     QVERIFY2(QDir::setCurrent(testDataDir), qPrintable("Could not chdir to " + testDataDir));
244 }
245
246 void tst_QObject::disconnect()
247 {
248     SenderObject *s = new SenderObject;
249     ReceiverObject *r1 = new ReceiverObject;
250     ReceiverObject *r2 = new ReceiverObject;
251
252     connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
253
254     connect( s, SIGNAL( signal2() ), r1, SLOT( slot2() ) );
255     connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) );
256     connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
257
258     s->emitSignal1();
259     s->emitSignal2();
260     s->emitSignal3();
261     s->emitSignal4();
262
263     QVERIFY(r1->called(1));
264     QVERIFY(r1->called(2));
265     QVERIFY(r1->called(3));
266     QVERIFY(r1->called(4));
267     r1->reset();
268
269     // usual disconnect with all parameters given
270     bool ret = QObject::disconnect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
271
272     s->emitSignal1();
273
274     QVERIFY(!r1->called(1));
275     r1->reset();
276
277     QVERIFY(ret);
278     ret = QObject::disconnect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
279     QVERIFY(!ret);
280
281     // disconnect all signals from s from all slots from r1
282     QObject::disconnect( s, 0, r1, 0 );
283
284     s->emitSignal2();
285     s->emitSignal3();
286     s->emitSignal4();
287
288     QVERIFY(!r1->called(2));
289     QVERIFY(!r1->called(3));
290     QVERIFY(!r1->called(4));
291     r1->reset();
292
293     connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
294     connect( s, SIGNAL( signal1() ), r1, SLOT( slot2() ) );
295     connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) );
296     connect( s, SIGNAL( signal2() ), r1, SLOT( slot4() ) );
297
298     // disconnect s's signal1() from all slots of r1
299     QObject::disconnect( s, SIGNAL( signal1() ), r1, 0 );
300
301     s->emitSignal1();
302     s->emitSignal2();
303
304     QVERIFY(!r1->called(1));
305     QVERIFY(!r1->called(2));
306     QVERIFY(!r1->called(3));
307     QVERIFY(r1->called(4));
308     r1->reset();
309     // make sure all is disconnected again
310     QObject::disconnect( s, 0, r1, 0 );
311
312     connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
313     connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) );
314     connect( s, SIGNAL( signal2() ), r1, SLOT( slot2() ) );
315     connect( s, SIGNAL( signal2() ), r2, SLOT( slot2() ) );
316     connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) );
317     connect( s, SIGNAL( signal3() ), r2, SLOT( slot3() ) );
318
319     // disconnect signal1() from all receivers
320     QObject::disconnect( s, SIGNAL( signal1() ), 0, 0 );
321     s->emitSignal1();
322     s->emitSignal2();
323     s->emitSignal3();
324
325     QVERIFY(!r1->called(1));
326     QVERIFY(!r2->called(1));
327     QVERIFY(r1->called(2));
328     QVERIFY(r2->called(2));
329     QVERIFY(r1->called(2));
330     QVERIFY(r2->called(2));
331
332     r1->reset();
333     r2->reset();
334
335     // disconnect all signals of s from all receivers
336     QObject::disconnect( s, 0, 0, 0 );
337
338     QVERIFY(!r1->called(2));
339     QVERIFY(!r2->called(2));
340     QVERIFY(!r1->called(2));
341     QVERIFY(!r2->called(2));
342
343     delete r2;
344     delete r1;
345     delete s;
346 }
347
348 class AutoConnectSender : public QObject
349 {
350     Q_OBJECT
351
352 public:
353     AutoConnectSender(QObject *parent)
354         : QObject(parent)
355     {}
356
357     void emitSignalNoParams() { emit signalNoParams(); }
358     void emitSignalWithParams(int i) { emit signalWithParams(i); }
359     void emitSignalWithParams(int i, QString string) { emit signalWithParams(i, string); }
360     void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams(i1, i2, i3, string, onoff); }
361     void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams2(i1, i2, i3, string, onoff); }
362     void emitSignalLoopBack() { emit signalLoopBack(); }
363
364 signals:
365     void signalNoParams();
366     void signalWithParams(int i);
367     void signalWithParams(int i, QString string);
368     void signalManyParams(int i1, int i2, int i3, QString string, bool onoff);
369     void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool);
370     void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff);
371     void signalLoopBack();
372 };
373
374 class AutoConnectReceiver : public QObject
375 {
376     Q_OBJECT
377
378 public:
379     AutoConnectReceiver()
380     {
381         reset();
382
383         connect(this, SIGNAL(on_Sender_signalLoopBack()), this, SLOT(slotLoopBack()));
384     }
385
386     void reset() {
387         called_slot10 = 0;
388         called_slot9 = 0;
389         called_slot8 = 0;
390         called_slot7 = 0;
391         called_slot6 = 0;
392         called_slot5 = 0;
393         called_slot4 = 0;
394         called_slot3 = 0;
395         called_slot2 = 0;
396         called_slot1 = 0;
397     }
398
399     int called_slot1;
400     int called_slot2;
401     int called_slot3;
402     int called_slot4;
403     int called_slot5;
404     int called_slot6;
405     int called_slot7;
406     int called_slot8;
407     int called_slot9;
408     int called_slot10;
409
410     bool called(int slot) {
411         switch (slot) {
412         case 1: return called_slot1;
413         case 2: return called_slot2;
414         case 3: return called_slot3;
415         case 4: return called_slot4;
416         case 5: return called_slot5;
417         case 6: return called_slot6;
418         case 7: return called_slot7;
419         case 8: return called_slot8;
420         case 9: return called_slot9;
421         case 10: return called_slot10;
422         default: return false;
423         }
424     }
425
426 public slots:
427     void on_Sender_signalNoParams() { ++called_slot1; }
428     void on_Sender_signalWithParams(int i = 0) { ++called_slot2; Q_UNUSED(i); }
429     void on_Sender_signalWithParams(int i, QString string) { ++called_slot3; Q_UNUSED(i);Q_UNUSED(string); }
430     void on_Sender_signalManyParams() { ++called_slot4; }
431     void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot5; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); }
432     void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy)
433     { ++called_slot6; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); Q_UNUSED(dummy);}
434     void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff)
435     { ++called_slot7; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); }
436     void slotLoopBack() { ++called_slot8; }
437
438 protected slots:
439     void o() { ++called_slot9; }
440     void on() { ++called_slot10; }
441
442 signals:
443     void on_Sender_signalLoopBack();
444 };
445
446 void tst_QObject::connectByName()
447 {
448     AutoConnectReceiver receiver;
449     AutoConnectSender sender(&receiver);
450     sender.setObjectName("Sender");
451
452     QMetaObject::connectSlotsByName(&receiver);
453
454     sender.emitSignalNoParams();
455     QCOMPARE(receiver.called(1), true);
456     QCOMPARE(receiver.called(2), false);
457     QCOMPARE(receiver.called(3), false);
458     QCOMPARE(receiver.called(4), false);
459     QCOMPARE(receiver.called(5), false);
460     QCOMPARE(receiver.called(6), false);
461     QCOMPARE(receiver.called(7), false);
462     QCOMPARE(receiver.called(8), false);
463     QCOMPARE(receiver.called(9), false);
464     QCOMPARE(receiver.called(10), false);
465     receiver.reset();
466
467     sender.emitSignalWithParams(0);
468     QCOMPARE(receiver.called(1), false);
469     QCOMPARE(receiver.called(2), true);
470     QCOMPARE(receiver.called(3), false);
471     QCOMPARE(receiver.called(4), false);
472     QCOMPARE(receiver.called(5), false);
473     QCOMPARE(receiver.called(6), false);
474     QCOMPARE(receiver.called(7), false);
475     QCOMPARE(receiver.called(8), false);
476     QCOMPARE(receiver.called(9), false);
477     QCOMPARE(receiver.called(10), false);
478     receiver.reset();
479
480     sender.emitSignalWithParams(0, "string");
481     QCOMPARE(receiver.called(1), false);
482     QCOMPARE(receiver.called(2), false);
483     QCOMPARE(receiver.called(3), true);
484     QCOMPARE(receiver.called(4), false);
485     QCOMPARE(receiver.called(5), false);
486     QCOMPARE(receiver.called(6), false);
487     QCOMPARE(receiver.called(7), false);
488     QCOMPARE(receiver.called(8), false);
489     QCOMPARE(receiver.called(9), false);
490     QCOMPARE(receiver.called(10), false);
491     receiver.reset();
492
493     sender.emitSignalManyParams(1, 2, 3, "string", true);
494     QCOMPARE(receiver.called(1), false);
495     QCOMPARE(receiver.called(2), false);
496     QCOMPARE(receiver.called(3), false);
497     QCOMPARE(receiver.called(4), true);
498     QCOMPARE(receiver.called(5), true);
499     QCOMPARE(receiver.called(6), false);
500     QCOMPARE(receiver.called(7), false);
501     QCOMPARE(receiver.called(8), false);
502     QCOMPARE(receiver.called(9), false);
503     QCOMPARE(receiver.called(10), false);
504     receiver.reset();
505
506     sender.emitSignalManyParams2(1, 2, 3, "string", true);
507     QCOMPARE(receiver.called(1), false);
508     QCOMPARE(receiver.called(2), false);
509     QCOMPARE(receiver.called(3), false);
510     QCOMPARE(receiver.called(4), false);
511     QCOMPARE(receiver.called(5), false);
512     QCOMPARE(receiver.called(6), false);
513     QCOMPARE(receiver.called(7), true);
514     QCOMPARE(receiver.called(8), false);
515     QCOMPARE(receiver.called(9), false);
516     QCOMPARE(receiver.called(10), false);
517     receiver.reset();
518
519     sender.emitSignalLoopBack();
520     QCOMPARE(receiver.called(1), false);
521     QCOMPARE(receiver.called(2), false);
522     QCOMPARE(receiver.called(3), false);
523     QCOMPARE(receiver.called(4), false);
524     QCOMPARE(receiver.called(5), false);
525     QCOMPARE(receiver.called(6), false);
526     QCOMPARE(receiver.called(7), false);
527     QCOMPARE(receiver.called(8), true);
528     QCOMPARE(receiver.called(9), false);
529     QCOMPARE(receiver.called(10), false);
530     receiver.reset();
531 }
532
533 void tst_QObject::qobject_castTemplate()
534 {
535     QObject *o = 0;
536     QVERIFY( !::qobject_cast<QObject*>(o) );
537
538     o = new SenderObject;
539     QVERIFY( ::qobject_cast<SenderObject*>(o) );
540     QVERIFY( ::qobject_cast<QObject*>(o) );
541     QVERIFY( !::qobject_cast<ReceiverObject*>(o) );
542     delete o;
543 }
544
545 void tst_QObject::findChildren()
546 {
547     QObject o;
548     QObject o1(&o);
549     QObject o2(&o);
550     QObject o11(&o1);
551     QObject o12(&o1);
552     QObject o111(&o11);
553     QObject unnamed(&o);
554     QTimer t1(&o);
555     QTimer t121(&o12);
556     QTimer emptyname(&o);
557
558     o.setObjectName("o");
559     o1.setObjectName("o1");
560     o2.setObjectName("o2");
561     o11.setObjectName("o11");
562     o12.setObjectName("o12");
563     o111.setObjectName("o111");
564     t1.setObjectName("t1");
565     t121.setObjectName("t121");
566     emptyname.setObjectName("");
567
568     QObject *op = 0;
569
570     op = qFindChild<QObject*>(&o, "o1");
571     QCOMPARE(op, &o1);
572     op = qFindChild<QObject*>(&o, "o2");
573     QCOMPARE(op, &o2);
574     op = qFindChild<QObject*>(&o, "o11");
575     QCOMPARE(op, &o11);
576     op = qFindChild<QObject*>(&o, "o12");
577     QCOMPARE(op, &o12);
578     op = qFindChild<QObject*>(&o, "o111");
579     QCOMPARE(op, &o111);
580     op = qFindChild<QObject*>(&o, "t1");
581     QCOMPARE(op, static_cast<QObject *>(&t1));
582     op = qFindChild<QObject*>(&o, "t121");
583     QCOMPARE(op, static_cast<QObject *>(&t121));
584     op = qFindChild<QTimer*>(&o, "t1");
585     QCOMPARE(op, static_cast<QObject *>(&t1));
586     op = qFindChild<QTimer*>(&o, "t121");
587     QCOMPARE(op, static_cast<QObject *>(&t121));
588     op = qFindChild<QTimer*>(&o, "o12");
589     QCOMPARE(op, static_cast<QObject *>(0));
590     op = qFindChild<QObject*>(&o, "o");
591     QCOMPARE(op, static_cast<QObject *>(0));
592     op = qFindChild<QObject*>(&o, "harry");
593     QCOMPARE(op, static_cast<QObject *>(0));
594     op = qFindChild<QObject*>(&o, "o1");
595     QCOMPARE(op, &o1);
596
597     QList<QObject*> l;
598     QList<QTimer*> tl;
599
600     l = qFindChildren<QObject*>(&o, "o1");
601     QCOMPARE(l.size(), 1);
602     QCOMPARE(l.at(0), &o1);
603     l = qFindChildren<QObject*>(&o, "o2");
604     QCOMPARE(l.size(), 1);
605     QCOMPARE(l.at(0), &o2);
606     l = qFindChildren<QObject*>(&o, "o11");
607     QCOMPARE(l.size(), 1);
608     QCOMPARE(l.at(0), &o11);
609     l = qFindChildren<QObject*>(&o, "o12");
610     QCOMPARE(l.size(), 1);
611     QCOMPARE(l.at(0), &o12);
612     l = qFindChildren<QObject*>(&o, "o111");
613     QCOMPARE(l.size(), 1);
614     QCOMPARE(l.at(0), &o111);
615     l = qFindChildren<QObject*>(&o, "t1");
616     QCOMPARE(l.size(), 1);
617     QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
618     l = qFindChildren<QObject*>(&o, "t121");
619     QCOMPARE(l.size(), 1);
620     QCOMPARE(l.at(0), static_cast<QObject *>(&t121));
621     tl = qFindChildren<QTimer*>(&o, "t1");
622     QCOMPARE(tl.size(), 1);
623     QCOMPARE(tl.at(0), &t1);
624     tl = qFindChildren<QTimer*>(&o, "t121");
625     QCOMPARE(tl.size(), 1);
626     QCOMPARE(tl.at(0), &t121);
627     l = qFindChildren<QObject*>(&o, "o");
628     QCOMPARE(l.size(), 0);
629     l = qFindChildren<QObject*>(&o, "harry");
630     QCOMPARE(l.size(), 0);
631     tl = qFindChildren<QTimer*>(&o, "o12");
632     QCOMPARE(tl.size(), 0);
633     l = qFindChildren<QObject*>(&o, "o1");
634     QCOMPARE(l.size(), 1);
635     QCOMPARE(l.at(0), &o1);
636
637     l = qFindChildren<QObject*>(&o, QRegExp("o.*"));
638     QCOMPARE(l.size(), 5);
639     QVERIFY(l.contains(&o1));
640     QVERIFY(l.contains(&o2));
641     QVERIFY(l.contains(&o11));
642     QVERIFY(l.contains(&o12));
643     QVERIFY(l.contains(&o111));
644     l = qFindChildren<QObject*>(&o, QRegExp("t.*"));
645     QCOMPARE(l.size(), 2);
646     QVERIFY(l.contains(&t1));
647     QVERIFY(l.contains(&t121));
648     tl = qFindChildren<QTimer*>(&o, QRegExp(".*"));
649     QCOMPARE(tl.size(), 3);
650     QVERIFY(tl.contains(&t1));
651     QVERIFY(tl.contains(&t121));
652     tl = qFindChildren<QTimer*>(&o, QRegExp("o.*"));
653     QCOMPARE(tl.size(), 0);
654     l = qFindChildren<QObject*>(&o, QRegExp("harry"));
655     QCOMPARE(l.size(), 0);
656
657     // empty and null string check
658     op = qFindChild<QObject*>(&o);
659     QCOMPARE(op, &o1);
660     op = qFindChild<QObject*>(&o, "");
661     QCOMPARE(op, &unnamed);
662     op = qFindChild<QObject*>(&o, "unnamed");
663     QCOMPARE(op, static_cast<QObject *>(0));
664
665     l = qFindChildren<QObject*>(&o);
666     QCOMPARE(l.size(), 9);
667     l = qFindChildren<QObject*>(&o, "");
668     QCOMPARE(l.size(), 2);
669     l = qFindChildren<QObject*>(&o, "unnamed");
670     QCOMPARE(l.size(), 0);
671
672     tl = o.findChildren<QTimer *>("t1");
673     QCOMPARE(tl.size(), 1);
674     QCOMPARE(tl.at(0), &t1);
675
676     // Find direct child/children
677
678     op = o.findChild<QObject*>("o1", Qt::FindDirectChildrenOnly);
679     QCOMPARE(op, &o1);
680     op = o.findChild<QObject*>("o2", Qt::FindDirectChildrenOnly);
681     QCOMPARE(op, &o2);
682     op = o.findChild<QObject*>("o11", Qt::FindDirectChildrenOnly);
683     QCOMPARE(op, static_cast<QObject *>(0));
684     op = o.findChild<QObject*>("o12", Qt::FindDirectChildrenOnly);
685     QCOMPARE(op, static_cast<QObject *>(0));
686     op = o.findChild<QObject*>("o111", Qt::FindDirectChildrenOnly);
687     QCOMPARE(op, static_cast<QObject *>(0));
688     op = o.findChild<QObject*>("t1", Qt::FindDirectChildrenOnly);
689     QCOMPARE(op, static_cast<QObject *>(&t1));
690     op = o.findChild<QObject*>("t121", Qt::FindDirectChildrenOnly);
691     QCOMPARE(op, static_cast<QObject *>(0));
692     op = o.findChild<QTimer*>("t1", Qt::FindDirectChildrenOnly);
693     QCOMPARE(op, static_cast<QObject *>(&t1));
694     op = o.findChild<QTimer*>("t121", Qt::FindDirectChildrenOnly);
695     QCOMPARE(op, static_cast<QObject *>(0));
696     op = o.findChild<QTimer*>("o12", Qt::FindDirectChildrenOnly);
697     QCOMPARE(op, static_cast<QObject *>(0));
698     op = o.findChild<QObject*>("o", Qt::FindDirectChildrenOnly);
699     QCOMPARE(op, static_cast<QObject *>(0));
700     op = o.findChild<QObject*>("harry", Qt::FindDirectChildrenOnly);
701     QCOMPARE(op, static_cast<QObject *>(0));
702     op = o.findChild<QObject*>("o1", Qt::FindDirectChildrenOnly);
703     QCOMPARE(op, &o1);
704
705     l = o.findChildren<QObject*>("o1", Qt::FindDirectChildrenOnly);
706     QCOMPARE(l.size(), 1);
707     QCOMPARE(l.at(0), &o1);
708     l = o.findChildren<QObject*>("o2", Qt::FindDirectChildrenOnly);
709     QCOMPARE(l.size(), 1);
710     QCOMPARE(l.at(0), &o2);
711     l = o.findChildren<QObject*>("o11", Qt::FindDirectChildrenOnly);
712     QCOMPARE(l.size(), 0);
713     l = o.findChildren<QObject*>("o12", Qt::FindDirectChildrenOnly);
714     QCOMPARE(l.size(), 0);
715     l = o.findChildren<QObject*>("o111", Qt::FindDirectChildrenOnly);
716     QCOMPARE(l.size(), 0);
717     l = o.findChildren<QObject*>("t1", Qt::FindDirectChildrenOnly);
718     QCOMPARE(l.size(), 1);
719     QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
720     l = o.findChildren<QObject*>("t121", Qt::FindDirectChildrenOnly);
721     QCOMPARE(l.size(), 0);
722     tl = o.findChildren<QTimer*>("t1", Qt::FindDirectChildrenOnly);
723     QCOMPARE(tl.size(), 1);
724     QCOMPARE(tl.at(0), &t1);
725     tl = o.findChildren<QTimer*>("t121", Qt::FindDirectChildrenOnly);
726     QCOMPARE(tl.size(), 0);
727     l = o.findChildren<QObject*>("o", Qt::FindDirectChildrenOnly);
728     QCOMPARE(l.size(), 0);
729     l = o.findChildren<QObject*>("harry", Qt::FindDirectChildrenOnly);
730     QCOMPARE(l.size(), 0);
731     tl = o.findChildren<QTimer*>("o12", Qt::FindDirectChildrenOnly);
732     QCOMPARE(tl.size(), 0);
733     l = o.findChildren<QObject*>("o1", Qt::FindDirectChildrenOnly);
734     QCOMPARE(l.size(), 1);
735     QCOMPARE(l.at(0), &o1);
736
737     l = o.findChildren<QObject*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
738     QCOMPARE(l.size(), 2);
739     QVERIFY(l.contains(&o1));
740     QVERIFY(l.contains(&o2));
741     l = o.findChildren<QObject*>(QRegExp("t.*"), Qt::FindDirectChildrenOnly);
742     QCOMPARE(l.size(), 1);
743     QVERIFY(l.contains(&t1));
744     tl = o.findChildren<QTimer*>(QRegExp(".*"), Qt::FindDirectChildrenOnly);
745     QCOMPARE(tl.size(), 2);
746     QVERIFY(tl.contains(&t1));
747     tl = o.findChildren<QTimer*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
748     QCOMPARE(tl.size(), 0);
749     l = o.findChildren<QObject*>(QRegExp("harry"), Qt::FindDirectChildrenOnly);
750     QCOMPARE(l.size(), 0);
751
752     // empty and null string check
753     op = o.findChild<QObject*>(QString(), Qt::FindDirectChildrenOnly);
754     QCOMPARE(op, &o1);
755     op = o.findChild<QObject*>("", Qt::FindDirectChildrenOnly);
756     QCOMPARE(op, &unnamed);
757     op = o.findChild<QObject*>("unnamed", Qt::FindDirectChildrenOnly);
758     QCOMPARE(op, static_cast<QObject *>(0));
759
760     l = o.findChildren<QObject*>(QString(), Qt::FindDirectChildrenOnly);
761     QCOMPARE(l.size(), 5);
762     l = o.findChildren<QObject*>("", Qt::FindDirectChildrenOnly);
763     QCOMPARE(l.size(), 2);
764     l = o.findChildren<QObject*>("unnamed", Qt::FindDirectChildrenOnly);
765     QCOMPARE(l.size(), 0);
766
767     tl = o.findChildren<QTimer *>("t1", Qt::FindDirectChildrenOnly);
768     QCOMPARE(tl.size(), 1);
769     QCOMPARE(tl.at(0), &t1);
770 }
771
772
773 class NotifyObject : public SenderObject, public ReceiverObject
774 {
775 public:
776     NotifyObject() : SenderObject(), ReceiverObject()
777     {}
778
779     QString org_signal;
780     QString nw_signal;
781
782 protected:
783     void connectNotify( const char *signal )
784     {
785         org_signal = signal;
786         nw_signal = QMetaObject::normalizedSignature(signal);
787     };
788     void disconnectNotify( const char *signal )
789     {
790         org_signal = signal;
791         nw_signal = QMetaObject::normalizedSignature(signal);
792     };
793 };
794
795 void tst_QObject::connectDisconnectNotify_data()
796 {
797     QTest::addColumn<QString>("a_signal");
798     QTest::addColumn<QString>("a_slot");
799
800     QTest::newRow("combo1") << SIGNAL( signal1() )        << SLOT( slot1() );
801     QTest::newRow("combo2") << SIGNAL( signal2(void) )    << SLOT( slot2(  ) );
802     QTest::newRow("combo3") << SIGNAL( signal3(  ) )      << SLOT( slot3(void) );
803     QTest::newRow("combo4") << SIGNAL(  signal4( void )  )<< SLOT(  slot4( void )  );
804 }
805
806 void tst_QObject::connectDisconnectNotify()
807 {
808     NotifyObject *s = new NotifyObject;
809     NotifyObject *r = new NotifyObject;
810
811     QFETCH(QString, a_signal);
812     QFETCH(QString, a_slot);
813
814     // Test connectNotify
815     connect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
816     QCOMPARE( s->org_signal, s->nw_signal );
817     QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
818
819     // Test disconnectNotify
820     QObject::disconnect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
821     QCOMPARE( s->org_signal, s->nw_signal );
822     QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
823
824     // Reconnect
825     connect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
826     // Test disconnectNotify for a complete disconnect
827     ((SenderObject*)s)->disconnect((ReceiverObject*)r);
828
829     // Obtaining meta methods
830     int signalIndx = ((SenderObject*)s)->metaObject()->indexOfSignal(
831             QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData());
832     int methodIndx = ((ReceiverObject*)r)->metaObject()->indexOfMethod(
833             QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData());
834     QMetaMethod signal = ((SenderObject*)s)->metaObject()->method(signalIndx);
835     QMetaMethod method = ((ReceiverObject*)r)->metaObject()->method(methodIndx);
836
837     // Test connectNotify when connecting by QMetaMethod
838     connect( (SenderObject*)s, signal, (ReceiverObject*)r, method );
839     QCOMPARE( s->org_signal, s->nw_signal );
840     QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
841
842     // Test disconnectNotify when disconnecting by QMetaMethod
843     QObject::disconnect( (SenderObject*)s, signal, (ReceiverObject*)r, method );
844     QCOMPARE( s->org_signal, s->nw_signal );
845     QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
846
847     delete s;
848     delete r;
849 }
850
851 class SequenceObject : public ReceiverObject
852 {
853     Q_OBJECT
854
855 public:
856     QObject *next;
857     SequenceObject() : next(0) { }
858
859 public slots:
860     void slot1_disconnectThis()
861     {
862         slot1();
863         disconnect(sender(), SIGNAL(signal1()), this, SLOT(slot1_disconnectThis()));
864     }
865
866     void slot2_reconnectThis()
867     {
868         slot2();
869
870         const QObject *s = sender();
871         disconnect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
872         connect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
873     }
874
875     void slot1_disconnectNext()
876     {
877         slot1();
878         disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot1()));
879     }
880
881     void slot2_reconnectNext()
882     {
883         slot2();
884
885         // modify the connection list in 'this'
886         disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
887         connect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
888
889         // modify the sender list in 'this'
890         connect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
891         connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
892         disconnect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
893         disconnect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
894     }
895
896     void slot1_deleteNext()
897     {
898         slot1();
899         delete next;
900     }
901
902     void slot2_deleteSender()
903     {
904         slot2();
905         delete sender();
906     }
907 };
908
909 void tst_QObject::emitInDefinedOrder()
910 {
911     SenderObject sender;
912     ReceiverObject receiver1, receiver2, receiver3, receiver4;
913
914     connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
915     connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
916     connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot1()));
917     connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot1()));
918     connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot2()));
919     connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot2()));
920     connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot2()));
921     connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot2()));
922
923     int sequence;
924     ReceiverObject::sequence = sequence = 0;
925     sender.emitSignal1();
926     QCOMPARE(receiver1.sequence_slot1, ++sequence);
927     QCOMPARE(receiver2.sequence_slot1, ++sequence);
928     QCOMPARE(receiver3.sequence_slot1, ++sequence);
929     QCOMPARE(receiver4.sequence_slot1, ++sequence);
930     QCOMPARE(receiver1.sequence_slot2, ++sequence);
931     QCOMPARE(receiver2.sequence_slot2, ++sequence);
932     QCOMPARE(receiver3.sequence_slot2, ++sequence);
933     QCOMPARE(receiver4.sequence_slot2, ++sequence);
934
935     QObject::disconnect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
936     connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
937
938     ReceiverObject::sequence = sequence =  0;
939     sender.emitSignal1();
940     QCOMPARE(receiver1.sequence_slot1, ++sequence);
941     QCOMPARE(receiver3.sequence_slot1, ++sequence);
942     QCOMPARE(receiver4.sequence_slot1, ++sequence);
943     QCOMPARE(receiver1.sequence_slot2, ++sequence);
944     QCOMPARE(receiver2.sequence_slot2, ++sequence);
945     QCOMPARE(receiver3.sequence_slot2, ++sequence);
946     QCOMPARE(receiver4.sequence_slot2, ++sequence);
947     QCOMPARE(receiver2.sequence_slot1, ++sequence);
948
949     QObject::disconnect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
950     connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
951
952     ReceiverObject::sequence = sequence =  0;
953     sender.emitSignal1();
954     QCOMPARE(receiver3.sequence_slot1, ++sequence);
955     QCOMPARE(receiver4.sequence_slot1, ++sequence);
956     QCOMPARE(receiver1.sequence_slot2, ++sequence);
957     QCOMPARE(receiver2.sequence_slot2, ++sequence);
958     QCOMPARE(receiver3.sequence_slot2, ++sequence);
959     QCOMPARE(receiver4.sequence_slot2, ++sequence);
960     QCOMPARE(receiver2.sequence_slot1, ++sequence);
961     QCOMPARE(receiver1.sequence_slot1, ++sequence);
962
963     // ensure emission order even if the connections change during emission
964     SenderObject *sender2 = new SenderObject;
965     SequenceObject seq1, seq2, *seq3 = new SequenceObject, seq4;
966     seq1.next = &seq2;
967     seq2.next = seq3;
968     seq3->next = &seq4;
969
970     // try 1
971     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
972     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
973     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
974     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
975     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
976     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
977     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
978     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
979
980     SequenceObject::sequence = sequence = 0;
981     sender2->emitSignal1();
982     QVERIFY(seq1.called(1));
983     QVERIFY(seq2.called(1));
984     QVERIFY(!seq3->called(1));
985     QVERIFY(seq4.called(1));
986     QVERIFY(seq1.called(2));
987     QVERIFY(seq2.called(2));
988     QVERIFY(!seq3->called(2));
989     QVERIFY(seq4.called(2));
990     QCOMPARE(seq1.sequence_slot1, ++sequence);
991     QCOMPARE(seq2.sequence_slot1, ++sequence);
992     QCOMPARE(seq4.sequence_slot1, ++sequence);
993     QCOMPARE(seq1.sequence_slot2, ++sequence);
994     QCOMPARE(seq2.sequence_slot2, ++sequence);
995     QCOMPARE(seq4.sequence_slot2, ++sequence);
996
997     QObject::disconnect(sender2, 0, &seq1, 0);
998     QObject::disconnect(sender2, 0, &seq2, 0);
999     QObject::disconnect(sender2, 0, seq3, 0);
1000     QObject::disconnect(sender2, 0, &seq4, 0);
1001     seq1.reset();
1002     seq2.reset();
1003     seq3->reset();
1004     seq4.reset();
1005
1006     // try 2
1007     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
1008     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1009     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1010     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1011     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
1012     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1013     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1014     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1015
1016     SequenceObject::sequence = sequence = 0;
1017     sender2->emitSignal1();
1018     QVERIFY(seq1.called(2));
1019     QVERIFY(seq2.called(2));
1020     QVERIFY(!seq3->called(2));
1021     QVERIFY(seq4.called(2));
1022     QVERIFY(seq1.called(1));
1023     QVERIFY(seq2.called(1));
1024     QVERIFY(!seq3->called(1));
1025     QVERIFY(seq4.called(1));
1026     QCOMPARE(seq1.sequence_slot2, ++sequence);
1027     QCOMPARE(seq2.sequence_slot2, ++sequence);
1028     QCOMPARE(seq4.sequence_slot2, ++sequence);
1029     QCOMPARE(seq1.sequence_slot1, ++sequence);
1030     QCOMPARE(seq2.sequence_slot1, ++sequence);
1031     QCOMPARE(seq4.sequence_slot1, ++sequence);
1032
1033     QObject::disconnect(sender2, 0, &seq1, 0);
1034     QObject::disconnect(sender2, 0, &seq2, 0);
1035     QObject::disconnect(sender2, 0, seq3, 0);
1036     QObject::disconnect(sender2, 0, &seq4, 0);
1037     seq1.reset();
1038     seq2.reset();
1039     seq3->reset();
1040     seq4.reset();
1041
1042     // try 3
1043     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
1044     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1045     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1046     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1047     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
1048     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1049     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1050     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1051
1052     SequenceObject::sequence = sequence = 0;
1053     sender2->emitSignal1();
1054     QVERIFY(seq1.called(1));
1055     QVERIFY(seq2.called(1));
1056     QVERIFY(!seq3->called(1));
1057     QVERIFY(seq4.called(1));
1058     QVERIFY(seq1.called(2));
1059     QVERIFY(seq2.called(2));
1060     QVERIFY(!seq3->called(2));
1061     QVERIFY(seq4.called(2));
1062     QCOMPARE(seq1.sequence_slot1, ++sequence);
1063     QCOMPARE(seq2.sequence_slot1, ++sequence);
1064     QCOMPARE(seq4.sequence_slot1, ++sequence);
1065     QCOMPARE(seq1.sequence_slot2, ++sequence);
1066     QCOMPARE(seq2.sequence_slot2, ++sequence);
1067     QCOMPARE(seq4.sequence_slot2, ++sequence);
1068
1069     // ensure emission order even if objects are destroyed during emission
1070     QObject::disconnect(sender2, 0, &seq1, 0);
1071     QObject::disconnect(sender2, 0, &seq2, 0);
1072     QObject::disconnect(sender2, 0, seq3, 0);
1073     QObject::disconnect(sender2, 0, &seq4, 0);
1074     seq1.reset();
1075     seq2.reset();
1076     seq3->reset();
1077     seq4.reset();
1078
1079     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
1080     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_deleteNext()));
1081     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1082     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1083     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
1084     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_deleteSender()));
1085     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1086     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1087
1088     QPointer<SenderObject> psender = sender2;
1089     QPointer<SequenceObject> pseq3 = seq3;
1090
1091     SequenceObject::sequence = sequence = 0;
1092     sender2->emitSignal1();
1093     QCOMPARE(static_cast<QObject *>(psender), static_cast<QObject *>(0));
1094     QCOMPARE(static_cast<QObject *>(pseq3), static_cast<QObject *>(0));
1095     QVERIFY(seq1.called(1));
1096     QVERIFY(seq2.called(1));
1097     QVERIFY(seq4.called(1));
1098     QVERIFY(seq1.called(2));
1099     QVERIFY(seq2.called(2));
1100     QVERIFY(!seq4.called(2));
1101     QCOMPARE(seq1.sequence_slot1, ++sequence);
1102     QCOMPARE(seq2.sequence_slot1, ++sequence);
1103     QCOMPARE(seq4.sequence_slot1, ++sequence);
1104     QCOMPARE(seq1.sequence_slot2, ++sequence);
1105     QCOMPARE(seq2.sequence_slot2, ++sequence);
1106
1107     QPointer<SenderObject> psender3 = new SenderObject;
1108     connect(psender3, SIGNAL(signal1()), psender3, SIGNAL(signal2()));
1109     connect(psender3, SIGNAL(signal2()), &seq1, SLOT(slot2_deleteSender()));
1110     psender3->emitSignal1();
1111     QVERIFY(!psender3);
1112 }
1113
1114 static int instanceCount = 0;
1115
1116 struct CheckInstanceCount
1117 {
1118     const int saved;
1119     CheckInstanceCount() : saved(instanceCount) {}
1120     ~CheckInstanceCount() { QCOMPARE(saved, instanceCount); }
1121 };
1122
1123
1124 struct CustomType
1125 {
1126     CustomType(int l1 = 0, int l2 = 0, int l3 = 0): i1(l1), i2(l2), i3(l3)
1127     { ++instanceCount; }
1128     CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3)
1129     { ++instanceCount; }
1130     ~CustomType() { --instanceCount; }
1131
1132     int i1, i2, i3;
1133     int value() { return i1 + i2 + i3; }
1134 };
1135
1136 Q_DECLARE_METATYPE(CustomType*)
1137 Q_DECLARE_METATYPE(CustomType)
1138
1139 class QCustomTypeChecker: public QObject
1140 {
1141     Q_OBJECT
1142
1143 public:
1144     QCustomTypeChecker(QObject *parent = 0): QObject(parent) {}
1145     void doEmit(CustomType ct)
1146     { emit signal1(ct); }
1147
1148 public slots:
1149     void slot1(CustomType ct);
1150
1151 signals:
1152     void signal1(CustomType ct);
1153
1154 public:
1155     CustomType received;
1156 };
1157
1158 void QCustomTypeChecker::slot1(CustomType ct)
1159 { received = ct; }
1160
1161
1162 void tst_QObject::customTypes()
1163 {
1164     CustomType t0;
1165     CustomType t1(1, 2, 3);
1166     CustomType t2(2, 3, 4);
1167
1168     {
1169         QCustomTypeChecker checker;
1170         QCOMPARE(instanceCount, 4);
1171
1172         connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
1173                 Qt::DirectConnection);
1174         QCOMPARE(checker.received.value(), 0);
1175         checker.doEmit(t1);
1176         QCOMPARE(checker.received.value(), t1.value());
1177         checker.received = t0;
1178
1179         int idx = qRegisterMetaType<CustomType>("CustomType");
1180         QCOMPARE(QMetaType::type("CustomType"), idx);
1181
1182         checker.disconnect();
1183         connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
1184                 Qt::QueuedConnection);
1185         QCOMPARE(instanceCount, 4);
1186         checker.doEmit(t2);
1187         QCOMPARE(instanceCount, 5);
1188         QCOMPARE(checker.received.value(), t0.value());
1189
1190         QCoreApplication::processEvents();
1191         QCOMPARE(checker.received.value(), t2.value());
1192         QCOMPARE(instanceCount, 4);
1193
1194         QVERIFY(QMetaType::isRegistered(idx));
1195         QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
1196         QCOMPARE(QMetaType::type("CustomType"), idx);
1197         QVERIFY(QMetaType::isRegistered(idx));
1198     }
1199     QCOMPARE(instanceCount, 3);
1200 }
1201
1202 QDataStream &operator<<(QDataStream &stream, const CustomType &ct)
1203 {
1204     stream << ct.i1 << ct.i2 << ct.i3;
1205     return stream;
1206 }
1207
1208 QDataStream &operator>>(QDataStream &stream, CustomType &ct)
1209 {
1210     stream >> ct.i1;
1211     stream >> ct.i2;
1212     stream >> ct.i3;
1213     return stream;
1214 }
1215
1216 void tst_QObject::streamCustomTypes()
1217 {
1218     QByteArray ba;
1219
1220     int idx = qRegisterMetaType<CustomType>("CustomType");
1221     qRegisterMetaTypeStreamOperators<CustomType>("CustomType");
1222
1223     {
1224         CustomType t1(1, 2, 3);
1225         QCOMPARE(instanceCount, 1);
1226         QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::WriteOnly);
1227         QMetaType::save(stream, idx, &t1);
1228     }
1229
1230     QCOMPARE(instanceCount, 0);
1231
1232     {
1233         CustomType t2;
1234         QCOMPARE(instanceCount, 1);
1235         QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::ReadOnly);
1236         QMetaType::load(stream, idx, &t2);
1237         QCOMPARE(instanceCount, 1);
1238         QCOMPARE(t2.i1, 1);
1239         QCOMPARE(t2.i2, 2);
1240         QCOMPARE(t2.i3, 3);
1241     }
1242     QCOMPARE(instanceCount, 0);
1243 }
1244
1245 typedef QString CustomString;
1246
1247 class PropertyObject : public QObject
1248 {
1249     Q_OBJECT
1250     Q_ENUMS(Alpha Priority)
1251
1252     Q_PROPERTY(Alpha alpha READ alpha WRITE setAlpha)
1253     Q_PROPERTY(Priority priority READ priority WRITE setPriority)
1254     Q_PROPERTY(int number READ number WRITE setNumber)
1255     Q_PROPERTY(QString string READ string WRITE setString)
1256     Q_PROPERTY(QVariant variant READ variant WRITE setVariant)
1257     Q_PROPERTY(CustomType* custom READ custom WRITE setCustom)
1258     Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat)
1259     Q_PROPERTY(qreal myQReal READ myQReal WRITE setMyQReal)
1260     Q_PROPERTY(CustomString customString READ customString WRITE setCustomString )
1261
1262 public:
1263     enum Alpha {
1264         Alpha0,
1265         Alpha1,
1266         Alpha2
1267     };
1268
1269     enum Priority { High, Low, VeryHigh, VeryLow };
1270
1271     PropertyObject()
1272         : m_alpha(Alpha0), m_priority(High), m_number(0), m_custom(0), m_float(42)
1273     {}
1274
1275     Alpha alpha() const { return m_alpha; }
1276     void setAlpha(Alpha alpha) { m_alpha = alpha; }
1277
1278     Priority priority() const { return m_priority; }
1279     void setPriority(Priority priority) { m_priority = priority; }
1280
1281     int number() const { return m_number; }
1282     void setNumber(int number) { m_number = number; }
1283
1284     QString string() const { return m_string; }
1285     void setString(const QString &string) { m_string = string; }
1286
1287     QVariant variant() const { return m_variant; }
1288     void setVariant(const QVariant &variant) { m_variant = variant; }
1289
1290     CustomType *custom() const { return m_custom; }
1291     void setCustom(CustomType *custom) { m_custom = custom; }
1292
1293     void setMyFloat(float value) { m_float = value; }
1294     inline float myFloat() const { return m_float; }
1295
1296     void setMyQReal(qreal value) { m_qreal = value; }
1297     qreal myQReal() const { return m_qreal; }
1298
1299     CustomString customString() const { return m_customString; }
1300     void setCustomString(const QString &string) { m_customString = string; }
1301
1302 private:
1303     Alpha m_alpha;
1304     Priority m_priority;
1305     int m_number;
1306     QString m_string;
1307     QVariant m_variant;
1308     CustomType *m_custom;
1309     float m_float;
1310     qreal m_qreal;
1311     CustomString m_customString;
1312 };
1313
1314 Q_DECLARE_METATYPE(PropertyObject::Priority)
1315
1316 void tst_QObject::threadSignalEmissionCrash()
1317 {
1318 #if defined(Q_OS_WINCE)
1319     int loopCount = 100;
1320 #else
1321     int loopCount = 1000;
1322 #endif
1323     for (int i = 0; i < loopCount; ++i) {
1324         QTcpSocket socket;
1325         socket.connectToHost("localhost", 80);
1326     }
1327 }
1328
1329 class TestThread : public QThread
1330 {
1331     Q_OBJECT
1332 public:
1333     inline void run()
1334     {
1335         *object = new QObject;
1336         *child = new QObject(*object);
1337         mutex.lock();
1338         cond.wakeOne();
1339         cond.wait(&mutex);
1340         mutex.unlock();
1341     }
1342
1343     QObject **object, **child;
1344     QMutex mutex;
1345     QWaitCondition cond;
1346 };
1347
1348 void tst_QObject::thread()
1349 {
1350     QThread *currentThread = QThread::currentThread();
1351     // the current thread is the same as the QApplication
1352     // thread... see tst_QApplication::thread()
1353
1354     {
1355         QObject object;
1356         // thread affinity for objects with no parent should be the
1357         // current thread
1358         QVERIFY(object.thread() != 0);
1359         QCOMPARE(object.thread(), currentThread);
1360         // children inherit their parent's thread
1361         QObject child(&object);
1362         QCOMPARE(child.thread(), object.thread());
1363     }
1364
1365     QObject *object = 0;
1366     QObject *child = 0;
1367
1368     {
1369         TestThread thr;
1370         QVERIFY(thr.thread() != 0);
1371         QCOMPARE(thr.thread(), currentThread);
1372
1373         thr.object = &object;
1374         thr.child = &child;
1375
1376         thr.mutex.lock();
1377         thr.start();
1378         thr.cond.wait(&thr.mutex);
1379
1380         // thread affinity for an object with no parent should be the
1381         // thread in which the object was created
1382         QCOMPARE(object->thread(), (QThread *)&thr);
1383         // children inherit their parent's thread
1384         QCOMPARE(child->thread(), object->thread());
1385
1386         thr.cond.wakeOne();
1387         thr.mutex.unlock();
1388         thr.wait();
1389
1390         // even though the thread is no longer running, the affinity
1391         // should not change
1392         QCOMPARE(object->thread(), (QThread *)&thr);
1393         QCOMPARE(child->thread(), object->thread());
1394     }
1395
1396     // the thread has been destroyed, thread affinity should
1397     // automatically reset to no thread
1398     QCOMPARE(object->thread(), (QThread *)0);
1399     QCOMPARE(child->thread(), object->thread());
1400
1401     delete object;
1402 }
1403
1404 class MoveToThreadObject : public QObject
1405 {
1406     Q_OBJECT
1407 public:
1408     QThread *timerEventThread;
1409     QThread *customEventThread;
1410     QThread *slotThread;
1411
1412     MoveToThreadObject(QObject *parent = 0)
1413         : QObject(parent), timerEventThread(0), customEventThread(0), slotThread(0)
1414     { }
1415
1416     void customEvent(QEvent *)
1417     {
1418         if (customEventThread)
1419             qFatal("%s: customEventThread should be null", Q_FUNC_INFO);
1420         customEventThread = QThread::currentThread();
1421         emit theSignal();
1422     }
1423
1424     void timerEvent(QTimerEvent *)
1425     {
1426         if (timerEventThread)
1427             qFatal("%s: timerEventThread should be null", Q_FUNC_INFO);
1428         timerEventThread = QThread::currentThread();
1429         emit theSignal();
1430     }
1431
1432 public slots:
1433     void theSlot()
1434     {
1435         if (slotThread)
1436             qFatal("%s: slotThread should be null", Q_FUNC_INFO);
1437         slotThread = QThread::currentThread();
1438         emit theSignal();
1439     }
1440
1441 signals:
1442     void theSignal();
1443 };
1444
1445 class MoveToThreadThread : public QThread
1446 {
1447 public:
1448     ~MoveToThreadThread()
1449     {
1450         if (isRunning()) {
1451             terminate();
1452             wait();
1453         }
1454     }
1455     void start()
1456     {
1457         QEventLoop eventLoop;
1458         connect(this, SIGNAL(started()), &eventLoop, SLOT(quit()), Qt::QueuedConnection);
1459         QThread::start();
1460         // wait for thread to start
1461         (void) eventLoop.exec();
1462     }
1463     void run()
1464     { (void) exec(); }
1465 };
1466
1467 void tst_QObject::thread0()
1468 {
1469     QObject *object = new QObject;
1470     object->moveToThread(0);
1471     QObject *child = new QObject(object);
1472     QCOMPARE(child->parent(), object);
1473     QCOMPARE(child->thread(), (QThread *)0);
1474
1475 #if 0
1476     // We don't support moving children into a parent that has no thread
1477     // affinity (yet?).
1478     QObject *child2 = new QObject;
1479     child2->moveToThread(0);
1480     child2->setParent(object);
1481     QCOMPARE(child2->parent(), object);
1482     QCOMPARE(child2->thread(), (QThread *)0);
1483 #endif
1484
1485     delete object;
1486 }
1487
1488 void tst_QObject::moveToThread()
1489 {
1490     QThread *currentThread = QThread::currentThread();
1491
1492     {
1493         QObject *object = new QObject;
1494         QObject *child = new QObject(object);
1495         QCOMPARE(object->thread(), currentThread);
1496         QCOMPARE(child->thread(), currentThread);
1497         object->moveToThread(0);
1498         QCOMPARE(object->thread(), (QThread *)0);
1499         QCOMPARE(child->thread(), (QThread *)0);
1500         object->moveToThread(currentThread);
1501         QCOMPARE(object->thread(), currentThread);
1502         QCOMPARE(child->thread(), currentThread);
1503         object->moveToThread(0);
1504         QCOMPARE(object->thread(), (QThread *)0);
1505         QCOMPARE(child->thread(), (QThread *)0);
1506         // can delete an object with no thread anywhere
1507         delete object;
1508     }
1509
1510     {
1511         MoveToThreadThread thread;
1512         thread.start();
1513
1514         QObject *object = new QObject;
1515         QObject *child = new QObject(object);
1516         QPointer<QObject> opointer = object;
1517         QPointer<QObject> cpointer = object;
1518
1519         QCOMPARE(object->thread(), currentThread);
1520         QCOMPARE(child->thread(), currentThread);
1521         object->moveToThread(&thread);
1522         QCOMPARE(object->thread(), (QThread *)&thread);
1523         QCOMPARE(child->thread(), (QThread *)&thread);
1524
1525         connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1526         QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1527         thread.wait();
1528
1529         QVERIFY(opointer == 0);
1530         QVERIFY(cpointer == 0);
1531     }
1532
1533     {
1534         // make sure posted events are moved with the object
1535         MoveToThreadThread thread;
1536         thread.start();
1537
1538         MoveToThreadObject *object = new MoveToThreadObject;
1539         MoveToThreadObject *child = new MoveToThreadObject(object);
1540
1541         connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1542         QCoreApplication::postEvent(child, new QEvent(QEvent::User));
1543         QCoreApplication::postEvent(object, new QEvent(QEvent::User));
1544
1545         QCOMPARE(object->thread(), currentThread);
1546         QCOMPARE(child->thread(), currentThread);
1547         object->moveToThread(&thread);
1548         QCOMPARE(object->thread(), (QThread *)&thread);
1549         QCOMPARE(child->thread(), (QThread *)&thread);
1550
1551         thread.wait();
1552
1553         QCOMPARE(object->customEventThread, (QThread *)&thread);
1554         QCOMPARE(child->customEventThread, (QThread *)&thread);
1555
1556         thread.start();
1557         connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1558         QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1559         thread.wait();
1560     }
1561
1562     {
1563         // make sure timers are moved with the object
1564         MoveToThreadThread thread;
1565         thread.start();
1566
1567         MoveToThreadObject *object = new MoveToThreadObject;
1568         MoveToThreadObject *child = new MoveToThreadObject(object);
1569
1570         connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1571
1572         child->startTimer(90);
1573         object->startTimer(100);
1574
1575         QCOMPARE(object->thread(), currentThread);
1576         QCOMPARE(child->thread(), currentThread);
1577         object->moveToThread(&thread);
1578         QCOMPARE(object->thread(), (QThread *)&thread);
1579         QCOMPARE(child->thread(), (QThread *)&thread);
1580
1581         thread.wait();
1582
1583         QCOMPARE(object->timerEventThread, (QThread *)&thread);
1584         QCOMPARE(child->timerEventThread, (QThread *)&thread);
1585
1586         thread.start();
1587         connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1588         QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1589         thread.wait();
1590     }
1591
1592     {
1593         // make sure socket notifiers are moved with the object
1594         MoveToThreadThread thread;
1595         thread.start();
1596
1597         QTcpServer server;
1598         QVERIFY(server.listen(QHostAddress::LocalHost, 0));
1599         QTcpSocket *socket = new QTcpSocket;
1600         MoveToThreadObject *child = new MoveToThreadObject(socket);
1601         connect(socket, SIGNAL(disconnected()), child, SLOT(theSlot()), Qt::DirectConnection);
1602         connect(child, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1603
1604         socket->connectToHost(server.serverAddress(), server.serverPort());
1605
1606         QVERIFY(server.waitForNewConnection(1000));
1607         QTcpSocket *serverSocket = server.nextPendingConnection();
1608         QVERIFY(serverSocket);
1609
1610         socket->waitForConnected();
1611
1612         QCOMPARE(socket->thread(), currentThread);
1613         socket->moveToThread(&thread);
1614         QCOMPARE(socket->thread(), (QThread *)&thread);
1615
1616         serverSocket->close();
1617
1618         QVERIFY(thread.wait(10000));
1619
1620         QCOMPARE(child->slotThread, (QThread *)&thread);
1621
1622         thread.start();
1623         connect(socket, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1624         QMetaObject::invokeMethod(socket, "deleteLater", Qt::QueuedConnection);
1625         thread.wait();
1626     }
1627 }
1628
1629
1630 void tst_QObject::property()
1631 {
1632     PropertyObject object;
1633     const QMetaObject *mo = object.metaObject();
1634     QMetaProperty property;
1635     QVERIFY(mo);
1636
1637     QVERIFY(mo->indexOfProperty("alpha") != -1);
1638     property = mo->property(mo->indexOfProperty("alpha"));
1639     QVERIFY(property.isEnumType());
1640     QCOMPARE(property.typeName(), "Alpha");
1641     QCOMPARE(property.type(), QVariant::Int);
1642
1643     QVariant var = object.property("alpha");
1644     QVERIFY(!var.isNull());
1645     QCOMPARE(var.toInt(), int(PropertyObject::Alpha0));
1646     object.setAlpha(PropertyObject::Alpha1);
1647     QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
1648     QVERIFY(object.setProperty("alpha", PropertyObject::Alpha2));
1649     QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha2));
1650     QVERIFY(object.setProperty("alpha", "Alpha1"));
1651     QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
1652     QVERIFY(!object.setProperty("alpha", QVariant()));
1653
1654     QVERIFY(mo->indexOfProperty("number") != -1);
1655     QCOMPARE(object.property("number").toInt(), 0);
1656     object.setNumber(24);
1657     QCOMPARE(object.property("number"), QVariant(24));
1658     QVERIFY(object.setProperty("number", 12));
1659     QCOMPARE(object.property("number"), QVariant(12));
1660     QVERIFY(object.setProperty("number", "42"));
1661     QCOMPARE(object.property("number"), QVariant(42));
1662
1663     QVERIFY(mo->indexOfProperty("string") != -1);
1664     QCOMPARE(object.property("string").toString(), QString());
1665     object.setString("String1");
1666     QCOMPARE(object.property("string"), QVariant("String1"));
1667     QVERIFY(object.setProperty("string", "String2"));
1668     QCOMPARE(object.property("string"), QVariant("String2"));
1669     QVERIFY(!object.setProperty("string", QVariant()));
1670
1671     const int idx = mo->indexOfProperty("variant");
1672     QVERIFY(idx != -1);
1673     QVERIFY(mo->property(idx).type() == QVariant::LastType);
1674     QCOMPARE(object.property("variant"), QVariant());
1675     QVariant variant1(42);
1676     QVariant variant2("string");
1677     object.setVariant(variant1);
1678     QCOMPARE(object.property("variant"), variant1);
1679     QVERIFY(object.setProperty("variant", variant2));
1680     QCOMPARE(object.variant(), QVariant(variant2));
1681     QCOMPARE(object.property("variant"), variant2);
1682     QVERIFY(object.setProperty("variant", QVariant()));
1683     QCOMPARE(object.property("variant"), QVariant());
1684
1685     QVERIFY(mo->indexOfProperty("custom") != -1);
1686     property = mo->property(mo->indexOfProperty("custom"));
1687     QVERIFY(property.isValid());
1688     QVERIFY(property.isWritable());
1689     QVERIFY(!property.isEnumType());
1690     QCOMPARE(property.typeName(), "CustomType*");
1691     QCOMPARE(property.type(), QVariant::UserType);
1692
1693     CustomType *customPointer = 0;
1694     QVariant customVariant = object.property("custom");
1695     customPointer = qVariantValue<CustomType *>(customVariant);
1696     QCOMPARE(customPointer, object.custom());
1697
1698     CustomType custom;
1699     customPointer = &custom;
1700     qVariantSetValue(customVariant, customPointer);
1701
1702     property = mo->property(mo->indexOfProperty("custom"));
1703     QVERIFY(property.isWritable());
1704     QCOMPARE(property.typeName(), "CustomType*");
1705     QCOMPARE(property.type(), QVariant::UserType);
1706
1707     QVERIFY(object.setProperty("custom", customVariant));
1708     QCOMPARE(object.custom(), customPointer);
1709
1710     customVariant = object.property("custom");
1711     customPointer = qVariantValue<CustomType *>(customVariant);
1712     QCOMPARE(object.custom(), customPointer);
1713
1714     // this enum property has a meta type, but it's not yet registered, so we know this fails
1715     QVERIFY(mo->indexOfProperty("priority") != -1);
1716     property = mo->property(mo->indexOfProperty("priority"));
1717     QVERIFY(property.isEnumType());
1718     QCOMPARE(property.typeName(), "Priority");
1719     QCOMPARE(property.type(), QVariant::Int);
1720
1721     var = object.property("priority");
1722     QVERIFY(!var.isNull());
1723     QCOMPARE(var.toInt(), int(PropertyObject::High));
1724     object.setPriority(PropertyObject::Low);
1725     QCOMPARE(object.property("priority").toInt(), int(PropertyObject::Low));
1726     QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
1727     QCOMPARE(object.property("priority").toInt(), int(PropertyObject::VeryHigh));
1728     QVERIFY(object.setProperty("priority", "High"));
1729     QCOMPARE(object.property("priority").toInt(), int(PropertyObject::High));
1730     QVERIFY(!object.setProperty("priority", QVariant()));
1731
1732     // now it's registered, so it works as expected
1733     int priorityMetaTypeId = qRegisterMetaType<PropertyObject::Priority>("PropertyObject::Priority");
1734
1735     QVERIFY(mo->indexOfProperty("priority") != -1);
1736     property = mo->property(mo->indexOfProperty("priority"));
1737     QVERIFY(property.isEnumType());
1738     QCOMPARE(property.typeName(), "Priority");
1739     QCOMPARE(property.type(), QVariant::UserType);
1740     QCOMPARE(property.userType(), priorityMetaTypeId);
1741
1742     var = object.property("priority");
1743     QVERIFY(!var.isNull());
1744     QVERIFY(qVariantCanConvert<PropertyObject::Priority>(var));
1745     QCOMPARE(qVariantValue<PropertyObject::Priority>(var), PropertyObject::High);
1746     object.setPriority(PropertyObject::Low);
1747     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
1748     QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
1749     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::VeryHigh);
1750     QVERIFY(object.setProperty("priority", "High"));
1751     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
1752     QVERIFY(!object.setProperty("priority", QVariant()));
1753
1754     var = object.property("priority");
1755     QCOMPARE(qVariantValue<PropertyObject::Priority>(var), PropertyObject::High);
1756     object.setPriority(PropertyObject::Low);
1757     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
1758     object.setProperty("priority", var);
1759     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
1760
1761     qRegisterMetaType<CustomString>("CustomString");
1762     QVERIFY(mo->indexOfProperty("customString") != -1);
1763     QCOMPARE(object.property("customString").toString(), QString());
1764     object.setCustomString("String1");
1765     QCOMPARE(object.property("customString"), QVariant("String1"));
1766     QVERIFY(object.setProperty("customString", "String2"));
1767     QCOMPARE(object.property("customString"), QVariant("String2"));
1768     QVERIFY(!object.setProperty("customString", QVariant()));
1769 }
1770
1771 void tst_QObject::metamethod()
1772 {
1773     SenderObject obj;
1774     const QMetaObject *mobj = obj.metaObject();
1775     QMetaMethod m;
1776
1777     m = mobj->method(mobj->indexOfMethod("invoke1()"));
1778     QVERIFY(QByteArray(m.signature()) == "invoke1()");
1779     QVERIFY(m.methodType() == QMetaMethod::Method);
1780     QVERIFY(m.access() == QMetaMethod::Public);
1781     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1782     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1783
1784     m = mobj->method(mobj->indexOfMethod("sinvoke1()"));
1785     QVERIFY(QByteArray(m.signature()) == "sinvoke1()");
1786     QVERIFY(m.methodType() == QMetaMethod::Method);
1787     QVERIFY(m.access() == QMetaMethod::Public);
1788     QVERIFY((m.attributes() & QMetaMethod::Scriptable));
1789     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1790
1791     m = mobj->method(mobj->indexOfMethod("invoke2()"));
1792     QVERIFY(QByteArray(m.signature()) == "invoke2()");
1793     QVERIFY(m.methodType() == QMetaMethod::Method);
1794     QVERIFY(m.access() == QMetaMethod::Protected);
1795     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1796     QVERIFY((m.attributes() & QMetaMethod::Compatibility));
1797
1798     m = mobj->method(mobj->indexOfMethod("sinvoke2()"));
1799     QVERIFY(QByteArray(m.signature()) == "sinvoke2()");
1800     QVERIFY(m.methodType() == QMetaMethod::Method);
1801     QVERIFY(m.access() == QMetaMethod::Protected);
1802     QVERIFY((m.attributes() & QMetaMethod::Scriptable));
1803     QVERIFY((m.attributes() & QMetaMethod::Compatibility));
1804
1805     m = mobj->method(mobj->indexOfMethod("invoke3()"));
1806     QVERIFY(QByteArray(m.signature()) == "invoke3()");
1807     QVERIFY(m.methodType() == QMetaMethod::Method);
1808     QVERIFY(m.access() == QMetaMethod::Private);
1809     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1810     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1811
1812     m = mobj->method(mobj->indexOfMethod("sinvoke3()"));
1813     QVERIFY(QByteArray(m.signature()) == "sinvoke3()");
1814     QVERIFY(m.methodType() == QMetaMethod::Method);
1815     QVERIFY(m.access() == QMetaMethod::Private);
1816     QVERIFY((m.attributes() & QMetaMethod::Scriptable));
1817     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1818
1819     m = mobj->method(mobj->indexOfMethod("signal5()"));
1820     QVERIFY(QByteArray(m.signature()) == "signal5()");
1821     QVERIFY(m.methodType() == QMetaMethod::Signal);
1822     QVERIFY(m.access() == QMetaMethod::Protected);
1823     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1824     QVERIFY((m.attributes() & QMetaMethod::Compatibility));
1825
1826     m = mobj->method(mobj->indexOfMethod("aPublicSlot()"));
1827     QVERIFY(QByteArray(m.signature()) == "aPublicSlot()");
1828     QVERIFY(m.methodType() == QMetaMethod::Slot);
1829     QVERIFY(m.access() == QMetaMethod::Public);
1830     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1831     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1832
1833     m = mobj->method(mobj->indexOfMethod("invoke1()"));
1834     QCOMPARE(m.parameterNames().count(), 0);
1835     QCOMPARE(m.parameterTypes().count(), 0);
1836
1837     m = mobj->method(mobj->indexOfMethod("invoke2(int)"));
1838     QCOMPARE(m.parameterNames().count(), 1);
1839     QCOMPARE(m.parameterTypes().count(), 1);
1840     QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
1841     QVERIFY(m.parameterNames().at(0).isEmpty());
1842
1843     m = mobj->method(mobj->indexOfMethod("invoke3(int,int)"));
1844     QCOMPARE(m.parameterNames().count(), 2);
1845     QCOMPARE(m.parameterTypes().count(), 2);
1846     QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
1847     QCOMPARE(m.parameterNames().at(0), QByteArray("hinz"));
1848     QCOMPARE(m.parameterTypes().at(1), QByteArray("int"));
1849     QCOMPARE(m.parameterNames().at(1), QByteArray("kunz"));
1850
1851 }
1852
1853 namespace QObjectTest
1854 {
1855     class TestObject: public QObject
1856     {
1857     Q_OBJECT
1858     public:
1859         TestObject(): QObject(), i(0) {}
1860         void doEmit() { emit aSignal(); }
1861         int i;
1862     public slots:
1863         void aSlot() { ++i; }
1864     signals:
1865         void aSignal();
1866     };
1867 }
1868
1869 void tst_QObject::namespaces()
1870 {
1871     QObjectTest::TestObject obj;
1872
1873     QVERIFY(connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot())));
1874     obj.doEmit();
1875     QCOMPARE(obj.i, 1);
1876 }
1877
1878 class SuperObject : public QObject
1879 {
1880     Q_OBJECT
1881 public:
1882     QObject *theSender;
1883     int theSignalId;
1884
1885     SuperObject()
1886     {
1887         theSender = 0;
1888         theSignalId = 0;
1889     }
1890
1891     friend class tst_QObject;
1892
1893     using QObject::sender;
1894
1895 public slots:
1896     void rememberSender()
1897     {
1898         theSender = sender();
1899         theSignalId = senderSignalIndex();
1900     }
1901
1902     void deleteAndRememberSender()
1903     {
1904         delete theSender;
1905         rememberSender();
1906     }
1907 signals:
1908     void anotherSignal();
1909     void theSignal();
1910 };
1911
1912 void tst_QObject::sender()
1913 {
1914     {
1915         SuperObject sender;
1916         SuperObject receiver;
1917         connect(&sender, SIGNAL(anotherSignal()),
1918                 &receiver, SLOT(rememberSender()));
1919         connect(&sender, SIGNAL(theSignal()),
1920                 &receiver, SLOT(rememberSender()));
1921         QCOMPARE(receiver.sender(), (QObject *)0);
1922         QCOMPARE(receiver.senderSignalIndex(), -1);
1923         emit sender.theSignal();
1924         QCOMPARE(receiver.theSender, (QObject *)&sender);
1925         QCOMPARE(receiver.sender(), (QObject *)0);
1926         QCOMPARE(receiver.theSignalId,
1927                  sender.metaObject()->indexOfSignal("theSignal()"));
1928         QCOMPARE(receiver.senderSignalIndex(), -1);
1929
1930         emit sender.anotherSignal();
1931         QCOMPARE(receiver.theSignalId,
1932                  sender.metaObject()->indexOfSignal("anotherSignal()"));
1933         QCOMPARE(receiver.senderSignalIndex(), -1);
1934     }
1935
1936     {
1937         SuperObject *sender = new SuperObject;
1938         SuperObject *receiver = new SuperObject;
1939         connect(sender, SIGNAL(theSignal()),
1940                 receiver, SLOT(rememberSender()),
1941                 Qt::BlockingQueuedConnection);
1942
1943         QThread thread;
1944         receiver->moveToThread(&thread);
1945         connect(sender, SIGNAL(theSignal()),
1946                 &thread, SLOT(quit()),
1947                 Qt::DirectConnection);
1948
1949         QCOMPARE(receiver->sender(), (QObject *)0);
1950         QCOMPARE(receiver->senderSignalIndex(), -1);
1951         receiver->theSender = 0;
1952         receiver->theSignalId = -1;
1953         thread.start();
1954         emit sender->theSignal();
1955         QCOMPARE(receiver->theSender, (QObject *) sender);
1956         QCOMPARE(receiver->sender(), (QObject *)0);
1957         QCOMPARE(receiver->theSignalId,
1958                  sender->metaObject()->indexOfSignal("theSignal()"));
1959         QCOMPARE(receiver->senderSignalIndex(), -1);
1960
1961         QVERIFY(thread.wait(10000));
1962         delete receiver;
1963         delete sender;
1964     }
1965
1966     {
1967         SuperObject *sender = new SuperObject;
1968         SuperObject receiver;
1969         connect(sender, SIGNAL(theSignal()),
1970                 &receiver, SLOT(deleteAndRememberSender()));
1971         QCOMPARE(receiver.sender(), (QObject *)0);
1972         receiver.theSender = sender;
1973         emit sender->theSignal();
1974         QCOMPARE(receiver.theSender, (QObject *)0);
1975         QCOMPARE(receiver.sender(), (QObject *)0);
1976     }
1977
1978     {
1979         SuperObject *sender = new SuperObject;
1980         SuperObject *receiver = new SuperObject;
1981         connect(sender, SIGNAL(theSignal()),
1982                 receiver, SLOT(deleteAndRememberSender()),
1983                 Qt::BlockingQueuedConnection);
1984
1985         QThread thread;
1986         receiver->moveToThread(&thread);
1987         connect(sender, SIGNAL(destroyed()),
1988                 &thread, SLOT(quit()),
1989                 Qt::DirectConnection);
1990
1991         QCOMPARE(receiver->sender(), (QObject *)0);
1992         receiver->theSender = sender;
1993         thread.start();
1994         emit sender->theSignal();
1995         QCOMPARE(receiver->theSender, (QObject *)0);
1996         QCOMPARE(receiver->sender(), (QObject *)0);
1997
1998         QVERIFY(thread.wait(10000));
1999         delete receiver;
2000     }
2001 }
2002
2003 namespace Foo
2004 {
2005     struct Bar
2006     {
2007         virtual ~Bar() {}
2008         virtual int rtti() const = 0;
2009     };
2010
2011     struct Bleh
2012     {
2013         virtual ~Bleh() {}
2014         virtual int rtti() const = 0;
2015     };
2016 }
2017
2018 QT_BEGIN_NAMESPACE
2019 Q_DECLARE_INTERFACE(Foo::Bar, "com.qtest.foobar")
2020 QT_END_NAMESPACE
2021
2022 #define Bleh_iid "com.qtest.bleh"
2023 QT_BEGIN_NAMESPACE
2024 Q_DECLARE_INTERFACE(Foo::Bleh, Bleh_iid)
2025 QT_END_NAMESPACE
2026
2027 class FooObject: public QObject, public Foo::Bar
2028 {
2029     Q_OBJECT
2030     Q_INTERFACES(Foo::Bar)
2031 public:
2032     int rtti() const { return 42; }
2033 };
2034
2035 class BlehObject : public QObject, public Foo::Bleh
2036 {
2037     Q_OBJECT
2038     Q_INTERFACES(Foo::Bleh)
2039 public:
2040     int rtti() const { return 43; }
2041 };
2042
2043 void tst_QObject::declareInterface()
2044 {
2045     FooObject obj;
2046
2047     Foo::Bar *bar = qobject_cast<Foo::Bar *>(&obj);
2048     QVERIFY(bar);
2049     QCOMPARE(bar->rtti(), 42);
2050     QCOMPARE(static_cast<Foo::Bar *>(&obj), bar);
2051
2052     BlehObject bleh;
2053
2054     bar = qobject_cast<Foo::Bar *>(&bleh);
2055     QVERIFY(!bar);
2056     Foo::Bleh *b = qobject_cast<Foo::Bleh *>(&bleh);
2057     QCOMPARE(b->rtti(), 43);
2058     QCOMPARE(static_cast<Foo::Bleh *>(&bleh), b);
2059
2060 }
2061
2062 class CustomData : public QObjectUserData
2063 {
2064 public:
2065     int id;
2066 };
2067
2068 void tst_QObject::testUserData()
2069 {
2070     const int USER_DATA_COUNT = 100;
2071     int user_data_ids[USER_DATA_COUNT];
2072
2073     // Register a few
2074     for (int i=0; i<USER_DATA_COUNT; ++i) {
2075         user_data_ids[i] = QObject::registerUserData();
2076     }
2077
2078     // Randomize the table a bit
2079     for (int i=0; i<100; ++i) {
2080         int p1 = rand() % USER_DATA_COUNT;
2081         int p2 = rand() % USER_DATA_COUNT;
2082
2083         int tmp = user_data_ids[p1];
2084         user_data_ids[p1] = user_data_ids[p2];
2085         user_data_ids[p2] = tmp;
2086     }
2087
2088     // insert the user data into an object
2089     QObject my_test_object;
2090     for (int i=0; i<USER_DATA_COUNT; ++i) {
2091         CustomData *data = new CustomData;
2092         data->id = user_data_ids[i];
2093         my_test_object.setUserData(data->id, data);
2094     }
2095
2096     // verify that all ids and positions are matching
2097     for (int i=0; i<USER_DATA_COUNT; ++i) {
2098         int id = user_data_ids[i];
2099         CustomData *data = static_cast<CustomData *>(my_test_object.userData(id));
2100         QVERIFY(data != 0);
2101         QVERIFY(data->id == id);
2102     }
2103 }
2104
2105 class DestroyedListener : public QObject
2106 {
2107     Q_OBJECT
2108 public:
2109     inline DestroyedListener() : pointerWasZero(false) {}
2110
2111     QPointer<QObject> pointer;
2112     bool pointerWasZero;
2113
2114 private slots:
2115     inline void otherObjectDestroyed()
2116     { pointerWasZero = pointer.isNull(); }
2117 };
2118
2119 void tst_QObject::qpointerResetBeforeDestroyedSignal()
2120 {
2121     QObject *obj = new QObject;
2122     DestroyedListener listener;
2123     listener.pointer = obj;
2124     listener.pointerWasZero = false;
2125     connect(obj, SIGNAL(destroyed()), &listener, SLOT(otherObjectDestroyed()));
2126     delete obj;
2127     QVERIFY(listener.pointerWasZero);
2128     QVERIFY(listener.pointer.isNull());
2129 }
2130
2131 class DefaultArguments : public QObject
2132 {
2133     Q_OBJECT
2134
2135 public slots:
2136
2137     void theSlot(const QString &s) { result = s; }
2138
2139 signals:
2140     void theOriginalSignal();
2141     void theSecondSignal(const QString &s = QString("secondDefault"));
2142
2143 public:
2144
2145     void emitTheOriginalSignal() { emit theOriginalSignal(); }
2146     void emitTheSecondSignal() { emit theSecondSignal(); }
2147     QString result;
2148 };
2149
2150 void tst_QObject::connectSignalsToSignalsWithDefaultArguments()
2151 {
2152     DefaultArguments o;
2153     connect(&o, SIGNAL(theOriginalSignal()), &o, SIGNAL(theSecondSignal()));
2154     connect(&o, SIGNAL(theSecondSignal(QString)), &o, SLOT(theSlot(QString)));
2155     QVERIFY( o.result.isEmpty() );
2156     o.emitTheSecondSignal();
2157     QCOMPARE(o.result, QString("secondDefault"));
2158     o.result = "Not called";
2159     o.emitTheOriginalSignal();
2160     QCOMPARE(o.result, QString("secondDefault"));
2161
2162 }
2163
2164 void tst_QObject::receivers()
2165 {
2166     class Object : public QObject
2167     {
2168     public:
2169         int receivers(const char* signal) const
2170         { return QObject::receivers(signal); }
2171     };
2172
2173     Object object;
2174     QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
2175     object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
2176     QCOMPARE(object.receivers(SIGNAL(destroyed())), 1);
2177     object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
2178     QCOMPARE(object.receivers(SIGNAL(destroyed())), 2);
2179     object.disconnect(SIGNAL(destroyed()), &object, SLOT(deleteLater()));
2180     QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
2181 }
2182
2183 enum Enum { };
2184
2185 struct Struct { };
2186 class Class { };
2187 template <typename T> class Template { };
2188
2189 class NormalizeObject : public QObject
2190 {
2191     Q_OBJECT
2192
2193 public:
2194
2195 signals:
2196     void uintPointerSignal(uint *);
2197     void ulongPointerSignal(ulong *);
2198     void constUintPointerSignal(const uint *);
2199     void constUlongPointerSignal(const ulong *);
2200
2201     void structSignal(Struct s);
2202     void classSignal(Class c);
2203     void enumSignal(Enum e);
2204
2205     void structPointerSignal(Struct *s);
2206     void classPointerSignal(Class *c);
2207     void enumPointerSignal(Enum *e);
2208
2209     void constStructPointerSignal(const Struct *s);
2210     void constClassPointerSignal(const Class *c);
2211     void constEnumPointerSignal(const Enum *e);
2212
2213     void constStructPointerConstPointerSignal(const Struct * const *s);
2214     void constClassPointerConstPointerSignal(const Class * const *c);
2215     void constEnumPointerConstPointerSignal(const Enum * const *e);
2216
2217     void unsignedintSignal(unsigned int);
2218     void unsignedSignal(unsigned);
2219     void unsignedlongSignal(unsigned long);
2220     void unsignedlonglongSignal(quint64);
2221     void unsignedlongintSignal(unsigned long int);
2222     void unsignedshortSignal(unsigned short);
2223     void unsignedcharSignal(unsigned char);
2224
2225     void typeRefSignal(Template<Class &> &ref);
2226     void constTypeRefSignal(const Template<Class const &> &ref);
2227     void typeConstRefSignal(Template<Class const &> const &ref);
2228
2229     void typePointerConstRefSignal(Class * const &);
2230
2231     void constTemplateSignal1( Template<int > );
2232     void constTemplateSignal2( Template< const int >);
2233
2234 public slots:
2235     void uintPointerSlot(uint *) { }
2236     void ulongPointerSlot(ulong *) { }
2237     void constUintPointerSlot(const uint *) { }
2238     void constUlongPointerSlot(const ulong *) { }
2239
2240     void structSlot(Struct s) { Q_UNUSED(s); }
2241     void classSlot(Class c) { Q_UNUSED(c); }
2242     void enumSlot(Enum e) { Q_UNUSED(e); }
2243
2244     void structPointerSlot(Struct *s) { Q_UNUSED(s); }
2245     void classPointerSlot(Class *c) { Q_UNUSED(c); }
2246     void enumPointerSlot(Enum *e) { Q_UNUSED(e); }
2247
2248     void constStructPointerSlot(const Struct *s) { Q_UNUSED(s); }
2249     void constClassPointerSlot(const Class *c) { Q_UNUSED(c); }
2250     void constEnumPointerSlot(const Enum *e) { Q_UNUSED(e); }
2251
2252     void constStructPointerConstPointerSlot(const Struct * const *s) { Q_UNUSED(s); }
2253     void constClassPointerConstPointerSlot(const Class * const *c) { Q_UNUSED(c); }
2254     void constEnumPointerConstPointerSlot(const Enum * const *e) { Q_UNUSED(e); }
2255
2256     void uintSlot(uint) {};
2257     void unsignedintSlot(unsigned int) {};
2258     void unsignedSlot(unsigned) {};
2259     void unsignedlongSlot(unsigned long) {};
2260     void unsignedlonglongSlot(quint64) {};
2261     void unsignedlongintSlot(unsigned long int) {};
2262     void unsignedshortSlot(unsigned short) {};
2263     void unsignedcharSlot(unsigned char) {};
2264
2265     void typeRefSlot(Template<Class &> &) {}
2266     void constTypeRefSlot(const Template<const Class &> &) {}
2267     void typeConstRefSlot(Template<Class const &> const &) {}
2268
2269     void typePointerConstRefSlot(Class * const &) {}
2270
2271     void constTemplateSlot1(Template<int > const) {}
2272     void constTemplateSlot2(const Template<int > ) {}
2273     void constTemplateSlot3(const Template< const int >) {}
2274 };
2275
2276 #include "oldnormalizeobject.h"
2277
2278 void tst_QObject::normalize()
2279 {
2280     NormalizeObject object;
2281
2282     // unsigned int -> uint, unsigned long -> ulong
2283     QVERIFY(object.connect(&object,
2284                            SIGNAL(uintPointerSignal(uint *)),
2285                            SLOT(uintPointerSlot(uint *))));
2286     QVERIFY(object.connect(&object,
2287                            SIGNAL(uintPointerSignal(unsigned int *)),
2288                            SLOT(uintPointerSlot(uint *))));
2289     QVERIFY(object.connect(&object,
2290                            SIGNAL(uintPointerSignal(uint *)),
2291                            SLOT(uintPointerSlot(unsigned int *))));
2292
2293     QVERIFY(object.connect(&object,
2294                            SIGNAL(constUintPointerSignal(const uint *)),
2295                            SLOT(constUintPointerSlot(const uint *))));
2296     QVERIFY(object.connect(&object,
2297                            SIGNAL(constUintPointerSignal(const unsigned int *)),
2298                            SLOT(constUintPointerSlot(const uint *))));
2299     QVERIFY(object.connect(&object,
2300                            SIGNAL(constUintPointerSignal(const uint *)),
2301                            SLOT(constUintPointerSlot(const unsigned int *))));
2302
2303     QVERIFY(object.connect(&object,
2304                            SIGNAL(ulongPointerSignal(ulong *)),
2305                            SLOT(ulongPointerSlot(ulong *))));
2306     QVERIFY(object.connect(&object,
2307                            SIGNAL(ulongPointerSignal(unsigned long *)),
2308                            SLOT(ulongPointerSlot(ulong *))));
2309     QVERIFY(object.connect(&object,
2310                            SIGNAL(ulongPointerSignal(ulong *)),
2311                            SLOT(ulongPointerSlot(unsigned long *))));
2312
2313     QVERIFY(object.connect(&object,
2314                            SIGNAL(constUlongPointerSignal(const ulong *)),
2315                            SLOT(constUlongPointerSlot(const ulong *))));
2316     QVERIFY(object.connect(&object,
2317                            SIGNAL(constUlongPointerSignal(const unsigned long *)),
2318                            SLOT(constUlongPointerSlot(const ulong *))));
2319     QVERIFY(object.connect(&object,
2320                            SIGNAL(constUlongPointerSignal(const ulong *)),
2321                            SLOT(constUlongPointerSlot(const unsigned long *))));
2322
2323     // struct, class, and enum are optional
2324     QVERIFY(object.connect(&object,
2325                            SIGNAL(structSignal(struct Struct)),
2326                            SLOT(structSlot(struct Struct))));
2327     QVERIFY(object.connect(&object,
2328                            SIGNAL(structSignal(Struct)),
2329                            SLOT(structSlot(struct Struct))));
2330     QVERIFY(object.connect(&object,
2331                            SIGNAL(structSignal(struct Struct)),
2332                            SLOT(structSlot(Struct))));
2333     QVERIFY(object.connect(&object,
2334                            SIGNAL(classSignal(class Class)),
2335                            SLOT(classSlot(class Class))));
2336     QVERIFY(object.connect(&object,
2337                            SIGNAL(classSignal(Class)),
2338                            SLOT(classSlot(class Class))));
2339     QVERIFY(object.connect(&object,
2340                            SIGNAL(classSignal(class Class)),
2341                            SLOT(classSlot(Class))));
2342     QVERIFY(object.connect(&object,
2343                            SIGNAL(enumSignal(enum Enum)),
2344                            SLOT(enumSlot(enum Enum))));
2345     QVERIFY(object.connect(&object,
2346                            SIGNAL(enumSignal(Enum)),
2347                            SLOT(enumSlot(enum Enum))));
2348     QVERIFY(object.connect(&object,
2349                            SIGNAL(enumSignal(enum Enum)),
2350                            SLOT(enumSlot(Enum))));
2351
2352     QVERIFY(object.connect(&object,
2353                            SIGNAL(structPointerSignal(struct Struct *)),
2354                            SLOT(structPointerSlot(struct Struct *))));
2355     QVERIFY(object.connect(&object,
2356                            SIGNAL(structPointerSignal(Struct *)),
2357                            SLOT(structPointerSlot(struct Struct *))));
2358     QVERIFY(object.connect(&object,
2359                            SIGNAL(structPointerSignal(struct Struct *)),
2360                            SLOT(structPointerSlot(Struct *))));
2361     QVERIFY(object.connect(&object,
2362                            SIGNAL(classPointerSignal(class Class *)),
2363                            SLOT(classPointerSlot(class Class *))));
2364     QVERIFY(object.connect(&object,
2365                            SIGNAL(classPointerSignal(Class *)),
2366                            SLOT(classPointerSlot(class Class *))));
2367     QVERIFY(object.connect(&object,
2368                            SIGNAL(classPointerSignal(class Class *)),
2369                            SLOT(classPointerSlot(Class *))));
2370     QVERIFY(object.connect(&object,
2371                            SIGNAL(enumPointerSignal(enum Enum *)),
2372                            SLOT(enumPointerSlot(enum Enum *))));
2373     QVERIFY(object.connect(&object,
2374                            SIGNAL(enumPointerSignal(Enum *)),
2375                            SLOT(enumPointerSlot(enum Enum *))));
2376     QVERIFY(object.connect(&object,
2377                            SIGNAL(enumPointerSignal(enum Enum *)),
2378                            SLOT(enumPointerSlot(Enum *))));
2379
2380     QVERIFY(object.connect(&object,
2381                            SIGNAL(constStructPointerSignal(const struct Struct *)),
2382                            SLOT(constStructPointerSlot(const struct Struct *))));
2383     QVERIFY(object.connect(&object,
2384                            SIGNAL(constStructPointerSignal(const Struct *)),
2385                            SLOT(constStructPointerSlot(const struct Struct *))));
2386     QVERIFY(object.connect(&object,
2387                            SIGNAL(constStructPointerSignal(const struct Struct *)),
2388                            SLOT(constStructPointerSlot(const Struct *))));
2389     QVERIFY(object.connect(&object,
2390                            SIGNAL(constClassPointerSignal(const class Class *)),
2391                            SLOT(constClassPointerSlot(const class Class *))));
2392     QVERIFY(object.connect(&object,
2393                            SIGNAL(constClassPointerSignal(const Class *)),
2394                            SLOT(constClassPointerSlot(const class Class *))));
2395     QVERIFY(object.connect(&object,
2396                            SIGNAL(constClassPointerSignal(const class Class *)),
2397                            SLOT(constClassPointerSlot(const Class *))));
2398     QVERIFY(object.connect(&object,
2399                            SIGNAL(constEnumPointerSignal(const enum Enum *)),
2400                            SLOT(constEnumPointerSlot(const enum Enum *))));
2401     QVERIFY(object.connect(&object,
2402                            SIGNAL(constEnumPointerSignal(const Enum *)),
2403                            SLOT(constEnumPointerSlot(const enum Enum *))));
2404     QVERIFY(object.connect(&object,
2405                            SIGNAL(constEnumPointerSignal(const enum Enum *)),
2406                            SLOT(constEnumPointerSlot(const Enum *))));
2407
2408     QVERIFY(object.connect(&object,
2409                            SIGNAL(constStructPointerSignal(struct Struct const *)),
2410                            SLOT(constStructPointerSlot(struct Struct const *))));
2411     QVERIFY(object.connect(&object,
2412                            SIGNAL(constStructPointerSignal(Struct const *)),
2413                            SLOT(constStructPointerSlot(struct Struct const *))));
2414     QVERIFY(object.connect(&object,
2415                            SIGNAL(constStructPointerSignal(struct Struct const *)),
2416                            SLOT(constStructPointerSlot(Struct const *))));
2417     QVERIFY(object.connect(&object,
2418                            SIGNAL(constClassPointerSignal(class Class const *)),
2419                            SLOT(constClassPointerSlot(class Class const *))));
2420     QVERIFY(object.connect(&object,
2421                            SIGNAL(constClassPointerSignal(Class const *)),
2422                            SLOT(constClassPointerSlot(class Class const *))));
2423     QVERIFY(object.connect(&object,
2424                            SIGNAL(constClassPointerSignal(class Class const *)),
2425                            SLOT(constClassPointerSlot(Class const *))));
2426     QVERIFY(object.connect(&object,
2427                            SIGNAL(constEnumPointerSignal(enum Enum const *)),
2428                            SLOT(constEnumPointerSlot(enum Enum const *))));
2429     QVERIFY(object.connect(&object,
2430                            SIGNAL(constEnumPointerSignal(Enum const *)),
2431                            SLOT(constEnumPointerSlot(enum Enum const *))));
2432     QVERIFY(object.connect(&object,
2433                            SIGNAL(constEnumPointerSignal(enum Enum const *)),
2434                            SLOT(constEnumPointerSlot(Enum const *))));
2435
2436     QVERIFY(object.connect(&object,
2437                            SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
2438                            SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
2439     QVERIFY(object.connect(&object,
2440                            SIGNAL(constStructPointerConstPointerSignal(const Struct * const *)),
2441                            SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
2442     QVERIFY(object.connect(&object,
2443                            SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
2444                            SLOT(constStructPointerConstPointerSlot(const Struct * const *))));
2445     QVERIFY(object.connect(&object,
2446                            SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
2447                            SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
2448     QVERIFY(object.connect(&object,
2449                            SIGNAL(constClassPointerConstPointerSignal(const Class * const *)),
2450                            SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
2451     QVERIFY(object.connect(&object,
2452                            SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
2453                            SLOT(constClassPointerConstPointerSlot(const Class * const *))));
2454     QVERIFY(object.connect(&object,
2455                            SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
2456                            SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
2457     QVERIFY(object.connect(&object,
2458                            SIGNAL(constEnumPointerConstPointerSignal(const Enum * const *)),
2459                            SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
2460     QVERIFY(object.connect(&object,
2461                            SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
2462                            SLOT(constEnumPointerConstPointerSlot(const Enum * const *))));
2463
2464     QVERIFY(object.connect(&object,
2465                            SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
2466                            SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
2467     QVERIFY(object.connect(&object,
2468                            SIGNAL(constStructPointerConstPointerSignal(Struct const * const *)),
2469                            SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
2470     QVERIFY(object.connect(&object,
2471                            SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
2472                            SLOT(constStructPointerConstPointerSlot(Struct const * const *))));
2473     QVERIFY(object.connect(&object,
2474                            SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
2475                            SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
2476     QVERIFY(object.connect(&object,
2477                            SIGNAL(constClassPointerConstPointerSignal(Class const * const *)),
2478                            SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
2479     QVERIFY(object.connect(&object,
2480                            SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
2481                            SLOT(constClassPointerConstPointerSlot(Class const * const *))));
2482     QVERIFY(object.connect(&object,
2483                            SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
2484                            SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
2485     QVERIFY(object.connect(&object,
2486                            SIGNAL(constEnumPointerConstPointerSignal(Enum const * const *)),
2487                            SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
2488     QVERIFY(object.connect(&object,
2489                            SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
2490                            SLOT(constEnumPointerConstPointerSlot(Enum const * const *))));
2491
2492     QVERIFY(object.connect(&object,
2493                            SIGNAL(unsignedintSignal(unsigned int)),
2494                            SLOT(unsignedintSlot(unsigned int))));
2495     QVERIFY(object.connect(&object,
2496                            SIGNAL(unsignedSignal(unsigned)),
2497                            SLOT(unsignedSlot(unsigned))));
2498     QVERIFY(object.connect(&object,
2499                            SIGNAL(unsignedSignal(unsigned)),
2500                            SLOT(uintSlot(uint))));
2501     QVERIFY(object.connect(&object,
2502                            SIGNAL(unsignedlongSignal(unsigned long)),
2503                            SLOT(unsignedlongSlot(unsigned long))));
2504     QVERIFY(object.connect(&object,
2505                            SIGNAL(unsignedlonglongSignal(quint64)),
2506                            SLOT(unsignedlonglongSlot(quint64))));
2507     QVERIFY(object.connect(&object,
2508                            SIGNAL(unsignedlongintSignal(unsigned long int)),
2509                            SLOT(unsignedlongintSlot(unsigned long int))));
2510     QVERIFY(object.connect(&object,
2511                            SIGNAL(unsignedshortSignal(unsigned short)),
2512                            SLOT(unsignedshortSlot(unsigned short))));
2513     QVERIFY(object.connect(&object,
2514                            SIGNAL(unsignedcharSignal(unsigned char)),
2515                            SLOT(unsignedcharSlot(unsigned char))));
2516
2517     // connect when original template signature and mixed usage of 'T<C const &> const &',
2518     // 'const T<const C &> &', and 'T<const C &>'
2519
2520     QVERIFY(object.connect(&object,
2521                            SIGNAL(typeRefSignal(Template<Class &> &)),
2522                            SLOT(typeRefSlot(Template<Class &> &))));
2523
2524     QVERIFY(object.connect(&object,
2525                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2526                            SLOT(constTypeRefSlot(const Template<const Class &> &))));
2527     QVERIFY(object.connect(&object,
2528                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2529                            SLOT(constTypeRefSlot(const Template<Class const &> &))));
2530     QVERIFY(object.connect(&object,
2531                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2532                            SLOT(constTypeRefSlot(Template<Class const &> const &))));
2533     QVERIFY(object.connect(&object,
2534                            SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2535                            SLOT(constTypeRefSlot(Template<Class const &> const &))));
2536     QVERIFY(object.connect(&object,
2537                            SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2538                            SLOT(constTypeRefSlot(Template<Class const &> const &))));
2539
2540     QVERIFY(object.connect(&object,
2541                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2542                            SLOT(typeConstRefSlot(const Template<const Class &> &))));
2543     QVERIFY(object.connect(&object,
2544                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2545                            SLOT(typeConstRefSlot(const Template<Class const &> &))));
2546     QVERIFY(object.connect(&object,
2547                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2548                            SLOT(typeConstRefSlot(Template<Class const &> const &))));
2549     QVERIFY(object.connect(&object,
2550                            SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2551                            SLOT(typeConstRefSlot(Template<Class const &> const &))));
2552     QVERIFY(object.connect(&object,
2553                            SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2554                            SLOT(typeConstRefSlot(Template<Class const &> const &))));
2555
2556     QVERIFY(object.connect(&object,
2557                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2558                            SLOT(constTypeRefSlot(const Template<const Class &> &))));
2559     QVERIFY(object.connect(&object,
2560                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2561                            SLOT(constTypeRefSlot(const Template<Class const &> &))));
2562     QVERIFY(object.connect(&object,
2563                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2564                            SLOT(constTypeRefSlot(Template<Class const &> const &))));
2565     QVERIFY(object.connect(&object,
2566                            SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2567                            SLOT(constTypeRefSlot(Template<Class const &> const &))));
2568     QVERIFY(object.connect(&object,
2569                            SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2570                            SLOT(constTypeRefSlot(Template<Class const &> const &))));
2571
2572     QVERIFY(object.connect(&object,
2573                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2574                            SLOT(typeConstRefSlot(const Template<const Class &> &))));
2575     QVERIFY(object.connect(&object,
2576                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2577                            SLOT(typeConstRefSlot(const Template<Class const &> &))));
2578     QVERIFY(object.connect(&object,
2579                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2580                            SLOT(typeConstRefSlot(Template<Class const &> const &))));
2581     QVERIFY(object.connect(&object,
2582                            SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2583                            SLOT(typeConstRefSlot(Template<Class const &> const &))));
2584     QVERIFY(object.connect(&object,
2585                            SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2586                            SLOT(typeConstRefSlot(Template<Class const &> const &))));
2587
2588     // same test again, this time with an object compiled with old moc output... we know that
2589     // it is not possible to connect everything, whic is the purpose for this test
2590     OldNormalizeObject oldobject;
2591
2592     QVERIFY(oldobject.connect(&oldobject,
2593                               SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2594                               SLOT(constTypeRefSlot(const Template<const Class &> &))));
2595     QVERIFY(oldobject.connect(&oldobject,
2596                               SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2597                               SLOT(constTypeRefSlot(const Template<Class const &> &))));
2598     // this fails in older versions, but passes now due to proper normalizing
2599     QVERIFY(oldobject.connect(&oldobject,
2600                                SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2601                                SLOT(constTypeRefSlot(Template<Class const &> const &))));
2602     // this fails in older versions, but passes now due to proper normalizing
2603     QVERIFY(oldobject.connect(&oldobject,
2604                                SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2605                                SLOT(constTypeRefSlot(Template<Class const &> const &))));
2606     // this fails in older versions, but passes now due to proper normalizing
2607     QVERIFY(oldobject.connect(&oldobject,
2608                                SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2609                                SLOT(constTypeRefSlot(Template<Class const &> const &))));
2610
2611     // these fail in older Qt versions, but pass now due to proper normalizing
2612     QVERIFY(oldobject.connect(&oldobject,
2613                                SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2614                                SLOT(typeConstRefSlot(const Template<const Class &> &))));
2615     QVERIFY(oldobject.connect(&oldobject,
2616                                SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2617                                SLOT(typeConstRefSlot(const Template<Class const &> &))));
2618     QVERIFY(oldobject.connect(&oldobject,
2619                                SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2620                                SLOT(typeConstRefSlot(Template<Class const &> const &))));
2621     QVERIFY(oldobject.connect(&oldobject,
2622                                SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2623                                SLOT(typeConstRefSlot(Template<Class const &> const &))));
2624     QVERIFY(oldobject.connect(&oldobject,
2625                                SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2626                                SLOT(typeConstRefSlot(Template<Class const &> const &))));
2627
2628     // these also fail in older Qt versions, but pass now due to proper normalizing
2629     QVERIFY(oldobject.connect(&oldobject,
2630                                SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2631                                SLOT(constTypeRefSlot(const Template<const Class &> &))));
2632     QVERIFY(oldobject.connect(&oldobject,
2633                                SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2634                                SLOT(constTypeRefSlot(const Template<Class const &> &))));
2635     QVERIFY(oldobject.connect(&oldobject,
2636                                SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2637                                SLOT(constTypeRefSlot(Template<Class const &> const &))));
2638     QVERIFY(oldobject.connect(&oldobject,
2639                                SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2640                                SLOT(constTypeRefSlot(Template<Class const &> const &))));
2641     QVERIFY(oldobject.connect(&oldobject,
2642                                SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2643                                SLOT(constTypeRefSlot(Template<Class const &> const &))));
2644
2645     // this fails in older versions, but passes now due to proper normalizing
2646     QVERIFY(oldobject.connect(&oldobject,
2647                                SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2648                                SLOT(typeConstRefSlot(const Template<const Class &> &))));
2649     // this fails in older versions, but passes now due to proper normalizing
2650     QVERIFY(oldobject.connect(&oldobject,
2651                                SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2652                                SLOT(typeConstRefSlot(const Template<Class const &> &))));
2653     // this fails in older versions, but passes now due to proper normalizing
2654     QVERIFY(oldobject.connect(&oldobject,
2655                                SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2656                                SLOT(typeConstRefSlot(Template<Class const &> const &))));
2657     QVERIFY(oldobject.connect(&oldobject,
2658                                SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2659                                SLOT(typeConstRefSlot(Template<Class const &> const &))));
2660     QVERIFY(oldobject.connect(&oldobject,
2661                                SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2662                                SLOT(typeConstRefSlot(Template<Class const &> const &))));
2663
2664     QVERIFY(object.connect(&object,
2665                            SIGNAL(typePointerConstRefSignal(Class*const&)),
2666                            SLOT(typePointerConstRefSlot(Class*const&))));
2667     QVERIFY(object.connect(&object,
2668                            SIGNAL(typePointerConstRefSignal(Class*const&)),
2669                            SLOT(typePointerConstRefSlot(Class*))));
2670     QVERIFY(object.connect(&object,
2671                            SIGNAL(typePointerConstRefSignal(Class*)),
2672                            SLOT(typePointerConstRefSlot(Class*const&))));
2673     QVERIFY(object.connect(&object,
2674                            SIGNAL(typePointerConstRefSignal(Class*)),
2675                            SLOT(typePointerConstRefSlot(Class*))));
2676
2677     QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2678                      &object , SLOT(constTemplateSlot1 (Template<int > )  ) ));
2679     QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2680                      &object , SLOT(constTemplateSlot2 (Template<int > )  ) ));
2681     QVERIFY( connect(&object, SIGNAL(constTemplateSignal2(Template <const int>)),
2682                      &object , SLOT(constTemplateSlot3(Template<int const > ) ) ));
2683
2684     //type does not match
2685     QTest::ignoreMessage(QtWarningMsg, "QObject::connect: Incompatible sender/receiver arguments\n"
2686                     "        NormalizeObject::constTemplateSignal1(Template<int>) --> NormalizeObject::constTemplateSlot3(Template<const int>)");
2687     QVERIFY(!connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2688                      &object , SLOT(constTemplateSlot3(Template<int const> ) ) ));
2689 }
2690
2691 class SiblingDeleter : public QObject
2692 {
2693 public:
2694     inline SiblingDeleter(QObject *sibling, QObject *parent)
2695         : QObject(parent), sibling(sibling) {}
2696     inline virtual ~SiblingDeleter() { delete sibling; }
2697
2698 private:
2699     QPointer<QObject> sibling;
2700 };
2701
2702
2703 void tst_QObject::childDeletesItsSibling()
2704 {
2705     QObject *commonParent = new QObject(0);
2706     QPointer<QObject> child = new QObject(0);
2707     QPointer<QObject> siblingDeleter = new SiblingDeleter(child, commonParent);
2708     child->setParent(commonParent);
2709     delete commonParent; // don't crash
2710     QVERIFY(!child);
2711     QVERIFY(!siblingDeleter);
2712 }
2713
2714 void tst_QObject::floatProperty()
2715 {
2716     PropertyObject obj;
2717     const int idx = obj.metaObject()->indexOfProperty("myFloat");
2718     QVERIFY(idx > 0);
2719     QMetaProperty prop = obj.metaObject()->property(idx);
2720     QVERIFY(prop.isValid());
2721     QVERIFY(prop.type() == uint(QMetaType::type("float")));
2722     QVERIFY(!prop.write(&obj, QVariant("Hello")));
2723     QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
2724     QVariant v = prop.read(&obj);
2725     QVERIFY(int(v.userType()) == QMetaType::Float);
2726     QVERIFY(qVariantValue<float>(v) == 128.0f);
2727 }
2728
2729 void tst_QObject::qrealProperty()
2730 {
2731     PropertyObject obj;
2732     const int idx = obj.metaObject()->indexOfProperty("myQReal");
2733     QVERIFY(idx > 0);
2734     QMetaProperty prop = obj.metaObject()->property(idx);
2735     QVERIFY(prop.isValid());
2736     QVERIFY(prop.type() == uint(QMetaType::type("qreal")));
2737     QVERIFY(!prop.write(&obj, QVariant("Hello")));
2738
2739     QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
2740     QVariant v = prop.read(&obj);
2741     QCOMPARE(v.userType(), qMetaTypeId<qreal>());
2742     QVERIFY(qVariantValue<qreal>(v) == 128.0);
2743
2744     QVERIFY(prop.write(&obj, qVariantFromValue(double(127))));
2745     v = prop.read(&obj);
2746     QCOMPARE(v.userType(), qMetaTypeId<qreal>());
2747     QVERIFY(qVariantValue<qreal>(v) == 127.0);
2748 }
2749
2750 class DynamicPropertyObject : public PropertyObject
2751 {
2752 public:
2753     inline DynamicPropertyObject() {}
2754
2755     inline virtual bool event(QEvent *e) {
2756         if (e->type() == QEvent::DynamicPropertyChange) {
2757             changedDynamicProperties.append(static_cast<QDynamicPropertyChangeEvent *>(e)->propertyName());
2758         }
2759         return QObject::event(e);
2760     }
2761
2762     QList<QByteArray> changedDynamicProperties;
2763 };
2764
2765 void tst_QObject::dynamicProperties()
2766 {
2767     DynamicPropertyObject obj;
2768
2769     QVERIFY(obj.dynamicPropertyNames().isEmpty());
2770
2771     QVERIFY(obj.setProperty("number", 42));
2772     QVERIFY(obj.changedDynamicProperties.isEmpty());
2773     QCOMPARE(obj.property("number").toInt(), 42);
2774
2775     QVERIFY(!obj.setProperty("number", "invalid string"));
2776     QVERIFY(obj.changedDynamicProperties.isEmpty());
2777
2778     QVERIFY(!obj.setProperty("myuserproperty", "Hello"));
2779     QCOMPARE(obj.changedDynamicProperties.count(), 1);
2780     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
2781     obj.changedDynamicProperties.clear();
2782
2783     QCOMPARE(obj.property("myuserproperty").toString(), QString("Hello"));
2784
2785     QCOMPARE(obj.dynamicPropertyNames().count(), 1);
2786     QCOMPARE(obj.dynamicPropertyNames().first(), QByteArray("myuserproperty"));
2787
2788     QVERIFY(!obj.setProperty("myuserproperty", QVariant()));
2789
2790     QCOMPARE(obj.changedDynamicProperties.count(), 1);
2791     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
2792     obj.changedDynamicProperties.clear();
2793
2794     QVERIFY(obj.property("myuserproperty").isNull());
2795
2796     QVERIFY(obj.dynamicPropertyNames().isEmpty());
2797 }
2798
2799 #ifndef QT_NO_PROCESS
2800 void tst_QObject::recursiveSignalEmission()
2801 {
2802     QProcess proc;
2803     // signalbug helper app should always be next to this test binary
2804     const QString path = QStringLiteral("signalbug/signalbug");
2805     proc.start(path);
2806     QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString())));
2807     QVERIFY(proc.waitForFinished());
2808     QVERIFY(proc.exitStatus() == QProcess::NormalExit);
2809     QCOMPARE(proc.exitCode(), 0);
2810 }
2811 #endif
2812
2813 void tst_QObject::blockingQueuedConnection()
2814 {
2815     {
2816         SenderObject sender;
2817
2818         MoveToThreadThread thread;
2819         ReceiverObject receiver;
2820         receiver.moveToThread(&thread);
2821         thread.start();
2822
2823         receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1()), Qt::BlockingQueuedConnection);
2824         sender.emitSignal1();
2825         QVERIFY(receiver.called(1));
2826
2827         receiver.reset();
2828         QVERIFY(QMetaObject::invokeMethod(&receiver, "slot1", Qt::BlockingQueuedConnection));
2829         QVERIFY(receiver.called(1));
2830
2831         connect(&sender, &SenderObject::signal2, &receiver, &ReceiverObject::slot2, Qt::BlockingQueuedConnection);
2832         sender.emitSignal2();
2833         QVERIFY(receiver.called(2));
2834
2835         thread.quit();
2836         QVERIFY(thread.wait());
2837     }
2838 }
2839
2840 class EventSpy : public QObject
2841 {
2842     Q_OBJECT
2843
2844 public:
2845     typedef QList<QPair<QObject *, QEvent::Type> > EventList;
2846
2847     EventSpy(QObject *parent = 0)
2848         : QObject(parent)
2849     { }
2850
2851     EventList eventList()
2852     {
2853         return events;
2854     }
2855
2856     void clear()
2857     {
2858         events.clear();
2859     }
2860
2861     bool eventFilter(QObject *object, QEvent *event)
2862     {
2863         events.append(qMakePair(object, event->type()));
2864         return false;
2865     }
2866
2867 private:
2868     EventList events;
2869 };
2870
2871 void tst_QObject::childEvents()
2872 {
2873     EventSpy::EventList expected;
2874
2875     {
2876         // no children created, so we expect no events
2877         QObject object;
2878         EventSpy spy;
2879         object.installEventFilter(&spy);
2880
2881         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
2882
2883         QCoreApplication::processEvents();
2884
2885         expected =
2886             EventSpy::EventList()
2887             << qMakePair(&object, QEvent::Type(QEvent::User + 1));
2888         QCOMPARE(spy.eventList(), expected);
2889     }
2890
2891     {
2892         // 2 children, so we expect 2 ChildAdded events
2893         QObject object;
2894         EventSpy spy;
2895         object.installEventFilter(&spy);
2896
2897         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
2898
2899         QObject child1(&object);
2900         QObject child2;
2901         child2.setParent(&object);
2902
2903         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2)));
2904
2905         expected =
2906             EventSpy::EventList()
2907             << qMakePair(&object, QEvent::ChildAdded)
2908             << qMakePair(&object, QEvent::ChildAdded);
2909         QCOMPARE(spy.eventList(), expected);
2910         spy.clear();
2911
2912         QCoreApplication::processEvents();
2913
2914         expected =
2915             EventSpy::EventList()
2916             << qMakePair(&object, QEvent::Type(QEvent::User + 1))
2917             << qMakePair(&object, QEvent::Type(QEvent::User + 2));
2918         QCOMPARE(spy.eventList(), expected);
2919     }
2920
2921     {
2922         // 2 children, but one is reparented away, so we expect:
2923         // 2 ChildAdded, 1 ChildRemoved
2924         QObject object;
2925         EventSpy spy;
2926         object.installEventFilter(&spy);
2927
2928         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
2929
2930         QObject child1(&object);
2931         QObject child2;
2932         child2.setParent(&object);
2933         child2.setParent(0);
2934
2935         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2)));
2936
2937         expected =
2938             EventSpy::EventList()
2939             << qMakePair(&object, QEvent::ChildAdded)
2940             << qMakePair(&object, QEvent::ChildAdded)
2941             << qMakePair(&object, QEvent::ChildRemoved);
2942         QCOMPARE(spy.eventList(), expected);
2943         spy.clear();
2944
2945         QCoreApplication::processEvents();
2946
2947         expected =
2948             EventSpy::EventList()
2949             << qMakePair(&object, QEvent::Type(QEvent::User + 1))
2950             << qMakePair(&object, QEvent::Type(QEvent::User + 2));
2951         QCOMPARE(spy.eventList(), expected);
2952     }
2953 }
2954
2955 void tst_QObject::installEventFilter()
2956 {
2957     QEvent event(QEvent::User);
2958     EventSpy::EventList expected;
2959
2960     QObject object;
2961     EventSpy spy;
2962     object.installEventFilter(&spy);
2963
2964     // nothing special, should just work
2965     QCoreApplication::sendEvent(&object, &event);
2966     expected =
2967         EventSpy::EventList()
2968         << qMakePair(&object, QEvent::User);
2969     QCOMPARE(spy.eventList(), expected);
2970     spy.clear();
2971
2972     // moving the filter causes QCoreApplication to skip the filter
2973     spy.moveToThread(0);
2974     QTest::ignoreMessage(QtWarningMsg, "QCoreApplication: Object event filter cannot be in a different thread.");
2975     QCoreApplication::sendEvent(&object, &event);
2976     QVERIFY(spy.eventList().isEmpty());
2977
2978     // move it back, and the filter works again
2979     spy.moveToThread(object.thread());
2980     QCoreApplication::sendEvent(&object, &event);
2981     expected =
2982         EventSpy::EventList()
2983         << qMakePair(&object, QEvent::User);
2984     QCOMPARE(spy.eventList(), expected);
2985     spy.clear();
2986
2987     // cannot install an event filter that lives in a different thread
2988     object.removeEventFilter(&spy);
2989     spy.moveToThread(0);
2990     QTest::ignoreMessage(QtWarningMsg, "QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2991     object.installEventFilter(&spy);
2992     QCoreApplication::sendEvent(&object, &event);
2993     QVERIFY(spy.eventList().isEmpty());
2994 }
2995
2996 class EmitThread : public QThread
2997 {   Q_OBJECT
2998 public:
2999     void run(void) {
3000         emit work();
3001     }
3002 signals:
3003     void work();
3004 };
3005
3006 namespace QObjectTest { // Do not clash with WinAPI 'DeleteObject'
3007 class DeleteObject : public QObject
3008 {
3009     Q_OBJECT
3010
3011 public slots:
3012     void deleteSelf()
3013     {
3014         delete this;
3015     }
3016
3017     void relaySignalAndProcessEvents()
3018     {
3019         emit relayedSignal();
3020         QCoreApplication::processEvents();
3021     }
3022
3023 signals:
3024     void relayedSignal();
3025 };
3026 } // namespace QObjectTest
3027
3028 void tst_QObject::deleteSelfInSlot()
3029 {
3030     {
3031         SenderObject sender;
3032         QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject();
3033         receiver->connect(&sender,
3034                           SIGNAL(signal1()),
3035                           SLOT(deleteSelf()),
3036                           Qt::BlockingQueuedConnection);
3037
3038         QThread thread;
3039         receiver->moveToThread(&thread);
3040         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3041         thread.start();
3042
3043         QPointer<QObjectTest::DeleteObject> p = receiver;
3044         sender.emitSignal1();
3045         QVERIFY(p.isNull());
3046
3047         QVERIFY(thread.wait(10000));
3048     }
3049
3050     {
3051         SenderObject sender;
3052         QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject();
3053         receiver->connect(&sender,
3054                           SIGNAL(signal1()),
3055                           SLOT(relaySignalAndProcessEvents()),
3056                           Qt::BlockingQueuedConnection);
3057         receiver->connect(receiver,
3058                           SIGNAL(relayedSignal()),
3059                           SLOT(deleteSelf()),
3060                           Qt::QueuedConnection);
3061
3062         QThread thread;
3063         receiver->moveToThread(&thread);
3064         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3065         thread.start();
3066
3067         QPointer<QObjectTest::DeleteObject> p = receiver;
3068         sender.emitSignal1();
3069         QVERIFY(p.isNull());
3070
3071         QVERIFY(thread.wait(10000));
3072     }
3073
3074     {
3075         EmitThread sender;
3076         QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject();
3077         connect(&sender, SIGNAL(work()), receiver, SLOT(deleteSelf()), Qt::DirectConnection);
3078         QPointer<QObjectTest::DeleteObject> p = receiver;
3079         sender.start();
3080         QVERIFY(sender.wait(10000));
3081         QVERIFY(p.isNull());
3082     }
3083 }
3084
3085 class DisconnectObject : public QObject
3086 {
3087     Q_OBJECT
3088
3089 public slots:
3090     void disconnectSelf()
3091     {
3092         disconnect(sender(), 0, this, 0);
3093     }
3094
3095     void relaySignalAndProcessEvents()
3096     {
3097         emit relayedSignal();
3098         QCoreApplication::processEvents();
3099     }
3100
3101 signals:
3102     void relayedSignal();
3103 };
3104
3105 void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit()
3106 {
3107     {
3108         SenderObject sender;
3109         DisconnectObject *receiver = new DisconnectObject();
3110         receiver->connect(&sender, SIGNAL(signal1()), SLOT(disconnectSelf()));
3111         sender.emitSignal1AfterRecursion();
3112         delete receiver;
3113     }
3114
3115     {
3116         SenderObject sender;
3117         DisconnectObject *receiver = new DisconnectObject();
3118         receiver->connect(&sender,
3119                           SIGNAL(signal1()),
3120                           SLOT(disconnectSelf()),
3121                           Qt::BlockingQueuedConnection);
3122
3123         QThread thread;
3124         receiver->moveToThread(&thread);
3125         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3126         thread.start();
3127
3128         QPointer<DisconnectObject> p = receiver;
3129         sender.emitSignal1();
3130         QVERIFY(!p.isNull());
3131
3132         receiver->deleteLater();
3133
3134         QVERIFY(thread.wait(10000));
3135         QVERIFY(p.isNull());
3136     }
3137
3138     {
3139         SenderObject sender;
3140         DisconnectObject *receiver = new DisconnectObject();
3141         receiver->connect(&sender,
3142                           SIGNAL(signal1()),
3143                           SLOT(relaySignalAndProcessEvents()),
3144                           Qt::BlockingQueuedConnection);
3145         receiver->connect(receiver,
3146                           SIGNAL(relayedSignal()),
3147                           SLOT(disconnectSelf()),
3148                           Qt::QueuedConnection);
3149
3150         QThread thread;
3151         receiver->moveToThread(&thread);
3152         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3153         thread.start();
3154
3155         QPointer<DisconnectObject> p = receiver;
3156         sender.emitSignal1();
3157         QVERIFY(!p.isNull());
3158
3159         receiver->deleteLater();
3160
3161         QVERIFY(thread.wait(10000));
3162         QVERIFY(p.isNull());
3163     }
3164 }
3165
3166 void tst_QObject::dumpObjectInfo()
3167 {
3168     QObject a, b;
3169     QObject::connect(&a, SIGNAL(destroyed(QObject *)), &b, SLOT(deleteLater()));
3170     a.disconnect(&b);
3171     a.dumpObjectInfo(); // should not crash
3172 }
3173
3174 class ConnectToSender : public QObject
3175 { Q_OBJECT
3176     public slots:
3177         void uselessSlot() { count++; }
3178
3179         void harmfullSlot() {
3180             //this used to crash
3181             connect(sender(), SIGNAL(signal4()), this, SLOT(uselessSlot()));
3182             //play a little bit with the memory in order to really get a segfault.
3183             connect(sender(), SIGNAL(signal1()), this, SLOT(uselessSlot()));
3184             QList<double>() << 45 << 78 << 65 << 121 << 45 << 78 << 12;
3185         }
3186     public:
3187         int count;
3188 };
3189
3190 void tst_QObject::connectToSender()
3191 {
3192     SenderObject s;
3193     ConnectToSender r;
3194     r.count = 0;
3195     QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(harmfullSlot()));
3196     QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(uselessSlot()));
3197
3198     s.emitSignal1();
3199
3200     QCOMPARE(r.count, 1);
3201     s.emitSignal4();
3202     QCOMPARE(r.count, 2);
3203 }
3204
3205 void tst_QObject::qobjectConstCast()
3206 {
3207     FooObject obj;
3208
3209     QObject *ptr = &obj;
3210     const QObject *cptr = &obj;
3211
3212     QVERIFY(qobject_cast<FooObject *>(ptr));
3213     QVERIFY(qobject_cast<const FooObject *>(cptr));
3214 }
3215
3216 void tst_QObject::uniqConnection()
3217 {
3218     SenderObject *s = new SenderObject;
3219     ReceiverObject *r1 = new ReceiverObject;
3220     ReceiverObject *r2 = new ReceiverObject;
3221     r1->reset();
3222     r2->reset();
3223     ReceiverObject::sequence = 0;
3224
3225     QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) , Qt::UniqueConnection) );
3226     QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) , Qt::UniqueConnection) );
3227     QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
3228     QVERIFY( connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
3229
3230     s->emitSignal1();
3231     s->emitSignal2();
3232     s->emitSignal3();
3233     s->emitSignal4();
3234
3235     QCOMPARE( r1->count_slot1, 1 );
3236     QCOMPARE( r1->count_slot2, 0 );
3237     QCOMPARE( r1->count_slot3, 2 );
3238     QCOMPARE( r1->count_slot4, 0 );
3239     QCOMPARE( r2->count_slot1, 1 );
3240     QCOMPARE( r2->count_slot2, 0 );
3241     QCOMPARE( r2->count_slot3, 0 );
3242     QCOMPARE( r2->count_slot4, 0 );
3243     QCOMPARE( r1->sequence_slot1, 1 );
3244     QCOMPARE( r2->sequence_slot1, 2 );
3245     QCOMPARE( r1->sequence_slot3, 4 );
3246
3247     r1->reset();
3248     r2->reset();
3249     ReceiverObject::sequence = 0;
3250
3251     QVERIFY( connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
3252     QVERIFY( connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
3253     QVERIFY(!connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
3254     QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
3255     QVERIFY(!connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
3256
3257     s->emitSignal4();
3258     QCOMPARE( r1->count_slot4, 1 );
3259     QCOMPARE( r2->count_slot4, 1 );
3260     QCOMPARE( r1->sequence_slot4, 1 );
3261     QCOMPARE( r2->sequence_slot4, 2 );
3262
3263     r1->reset();
3264     r2->reset();
3265     ReceiverObject::sequence = 0;
3266
3267     connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
3268
3269     s->emitSignal4();
3270     QCOMPARE( r1->count_slot4, 2 );
3271     QCOMPARE( r2->count_slot4, 1 );
3272     QCOMPARE( r1->sequence_slot4, 3 );
3273     QCOMPARE( r2->sequence_slot4, 2 );
3274
3275     delete s;
3276     delete r1;
3277     delete r2;
3278 }
3279
3280 void tst_QObject::uniqConnectionPtr()
3281 {
3282     SenderObject *s = new SenderObject;
3283     ReceiverObject *r1 = new ReceiverObject;
3284     ReceiverObject *r2 = new ReceiverObject;
3285     r1->reset();
3286     r2->reset();
3287     ReceiverObject::sequence = 0;
3288
3289     QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 , Qt::UniqueConnection) );
3290     QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 , Qt::UniqueConnection) );
3291     QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
3292     QVERIFY( connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
3293
3294     s->emitSignal1();
3295     s->emitSignal2();
3296     s->emitSignal3();
3297     s->emitSignal4();
3298
3299     QCOMPARE( r1->count_slot1, 1 );
3300     QCOMPARE( r1->count_slot2, 0 );
3301     QCOMPARE( r1->count_slot3, 2 );
3302     QCOMPARE( r1->count_slot4, 0 );
3303     QCOMPARE( r2->count_slot1, 1 );
3304     QCOMPARE( r2->count_slot2, 0 );
3305     QCOMPARE( r2->count_slot3, 0 );
3306     QCOMPARE( r2->count_slot4, 0 );
3307     QCOMPARE( r1->sequence_slot1, 1 );
3308     QCOMPARE( r2->sequence_slot1, 2 );
3309     QCOMPARE( r1->sequence_slot3, 4 );
3310
3311     r1->reset();
3312     r2->reset();
3313     ReceiverObject::sequence = 0;
3314
3315     QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3316     QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3317     QVERIFY(!connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3318     QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3319     QVERIFY(!connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3320
3321     s->emitSignal4();
3322     QCOMPARE( r1->count_slot4, 1 );
3323     QCOMPARE( r2->count_slot4, 1 );
3324     QCOMPARE( r1->sequence_slot4, 1 );
3325     QCOMPARE( r2->sequence_slot4, 2 );
3326
3327     r1->reset();
3328     r2->reset();
3329     ReceiverObject::sequence = 0;
3330
3331     connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
3332
3333     s->emitSignal4();
3334     QCOMPARE( r1->count_slot4, 2 );
3335     QCOMPARE( r2->count_slot4, 1 );
3336     QCOMPARE( r1->sequence_slot4, 3 );
3337     QCOMPARE( r2->sequence_slot4, 2 );
3338
3339     delete s;
3340     delete r1;
3341     delete r2;
3342 }
3343
3344 void tst_QObject::interfaceIid()
3345 {
3346     QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),
3347              QByteArray(Bleh_iid));
3348     QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()),
3349              QByteArray("com.qtest.foobar"));
3350     QCOMPARE(QByteArray(qobject_interface_iid<FooObject *>()),
3351              QByteArray());
3352 }
3353
3354 void tst_QObject::deleteQObjectWhenDeletingEvent()
3355 {
3356     // This is a regression test for an old bug that used to deadlock
3357     // when the QObject from the event was destroyed.
3358
3359     struct MyEvent : public QEvent
3360     {
3361         MyEvent() : QEvent(QEvent::User) { }
3362         QObject obj;
3363     };
3364
3365     QObject o;
3366     QGuiApplication::postEvent(&o, new MyEvent);
3367     QCoreApplication::removePostedEvents(&o); // here you would get a deadlock
3368 }
3369
3370 class OverloadObject : public QObject
3371 {
3372     friend class tst_QObject;
3373     Q_OBJECT
3374     signals:
3375         void sig(int i, char c, qreal m = 12);
3376         void sig(int i, int j = 12);
3377         void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const;
3378         void other(int a = 0);
3379         void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0);
3380         void sig(double r = 0.5);
3381     public slots:
3382         void slo(int i, int j = 43)
3383         {
3384             s_num += 1;
3385             i1_num = i;
3386             i2_num = j;
3387         }
3388         void slo(QObject *o, QObject *p = qApp, QObject *q = qApp, QObject *r = qApp)
3389         {
3390             s_num += 10;
3391             o1_obj = o;
3392             o2_obj = p;
3393             o3_obj = q;
3394             o4_obj = r;
3395         }
3396         void slo()
3397         {
3398             s_num += 100;
3399         }
3400
3401     public:
3402         int s_num;
3403         int i1_num;
3404         int i2_num;
3405         QObject *o1_obj;
3406         QObject *o2_obj;
3407         QObject *o3_obj;
3408         QObject *o4_obj;
3409 };
3410
3411 void tst_QObject::overloads()
3412 {
3413     OverloadObject obj1;
3414     OverloadObject obj2;
3415     QObject obj3;
3416     obj1.s_num = 0;
3417     obj2.s_num = 0;
3418
3419     connect (&obj1, SIGNAL(sig(int)) , &obj1, SLOT(slo(int)));
3420     connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *)) , &obj1, SLOT(slo(QObject * , QObject *, QObject *)));
3421
3422     connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *, QObject *)) , &obj2, SLOT(slo(QObject * , QObject *, QObject *)));
3423     connect (&obj1, SIGNAL(sig(QObject *)) , &obj2, SLOT(slo()));
3424     connect (&obj1, SIGNAL(sig(int, int)) , &obj2, SLOT(slo(int, int)));
3425
3426     emit obj1.sig(0.5); //connected to nothing
3427     emit obj1.sig(1, 'a'); //connected to nothing
3428     QCOMPARE(obj1.s_num, 0);
3429     QCOMPARE(obj2.s_num, 0);
3430
3431     emit obj1.sig(1); //this signal is connected
3432     QCOMPARE(obj1.s_num, 1);
3433     QCOMPARE(obj1.i1_num, 1);
3434     QCOMPARE(obj1.i2_num, 43); //default argument of the slot
3435
3436     QCOMPARE(obj2.s_num, 1);
3437     QCOMPARE(obj2.i1_num, 1);
3438     QCOMPARE(obj2.i2_num, 12); //default argument of the signal
3439
3440
3441     emit obj1.sig(&obj2); //this signal is conencted to obj2
3442     QCOMPARE(obj1.s_num, 1);
3443     QCOMPARE(obj2.s_num, 101);
3444     emit obj1.sig(&obj2, &obj3); //this signal is connected
3445     QCOMPARE(obj1.s_num, 11);
3446     QCOMPARE(obj1.o1_obj, (QObject *)&obj2);
3447     QCOMPARE(obj1.o2_obj, &obj3);
3448     QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal
3449     QCOMPARE(obj1.o4_obj, (QObject *)qApp); //default arg of the slot
3450
3451     QCOMPARE(obj2.s_num, 111);
3452     QCOMPARE(obj2.o1_obj, (QObject *)&obj2);
3453     QCOMPARE(obj2.o2_obj, &obj3);
3454     QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal
3455     QCOMPARE(obj2.o4_obj, (QObject *)qApp); //default arg of the slot
3456 }
3457
3458 class ManySignals : public QObject
3459 {   Q_OBJECT
3460     friend class tst_QObject;
3461 signals:
3462     void sig00(); void sig01(); void sig02(); void sig03(); void sig04();
3463     void sig05(); void sig06(); void sig07(); void sig08(); void sig09();
3464     void sig10(); void sig11(); void sig12(); void sig13(); void sig14();
3465     void sig15(); void sig16(); void sig17(); void sig18(); void sig19();
3466     void sig20(); void sig21(); void sig22(); void sig23(); void sig24();
3467     void sig25(); void sig26(); void sig27(); void sig28(); void sig29();
3468     void sig30(); void sig31(); void sig32(); void sig33(); void sig34();
3469     void sig35(); void sig36(); void sig37(); void sig38(); void sig39();
3470     void sig40(); void sig41(); void sig42(); void sig43(); void sig44();
3471     void sig45(); void sig46(); void sig47(); void sig48(); void sig49();
3472     void sig50(); void sig51(); void sig52(); void sig53(); void sig54();
3473     void sig55(); void sig56(); void sig57(); void sig58(); void sig59();
3474     void sig60(); void sig61(); void sig62(); void sig63(); void sig64();
3475     void sig65(); void sig66(); void sig67(); void sig68(); void sig69();
3476
3477 public slots:
3478     void received() { rec++; }
3479 public:
3480     int rec;
3481 };
3482
3483
3484 void tst_QObject::isSignalConnected()
3485 {
3486     ManySignals o;
3487     o.rec = 0;
3488 #ifdef QT_BUILD_INTERNAL
3489     QObjectPrivate *priv = QObjectPrivate::get(&o);
3490     QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()")));
3491     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig00()")));
3492     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()")));
3493     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()")));
3494     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
3495     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()")));
3496 #endif
3497
3498     QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69()));
3499     QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03()));
3500     QObject::connect(&o, SIGNAL(sig69()), &o, SIGNAL(sig34()));
3501     QObject::connect(&o, SIGNAL(sig03()), &o, SIGNAL(sig18()));
3502
3503 #ifdef QT_BUILD_INTERNAL
3504     QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()")));
3505     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()")));
3506     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()")));
3507     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
3508
3509     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()")));
3510     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()")));
3511     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()")));
3512     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3513     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()")));
3514 #endif
3515
3516     QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29()));
3517     QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62()));
3518     QObject::connect(&o, SIGNAL(sig62()), &o, SIGNAL(sig28()));
3519     QObject::connect(&o, SIGNAL(sig28()), &o, SIGNAL(sig27()));
3520
3521 #ifdef QT_BUILD_INTERNAL
3522     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()")));
3523     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()")));
3524     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()")));
3525     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3526     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()")));
3527 #endif
3528
3529     QCOMPARE(o.rec, 0);
3530     emit o.sig01();
3531     emit o.sig34();
3532     QCOMPARE(o.rec, 0);
3533
3534     QObject::connect(&o, SIGNAL(sig27()), &o, SLOT(received()));
3535
3536 #ifdef QT_BUILD_INTERNAL
3537     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()")));
3538     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()")));
3539     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()")));
3540     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()")));
3541     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()")));
3542     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()")));
3543     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3544     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig27()")));
3545
3546     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig04()")));
3547     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig21()")));
3548     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig25()")));
3549     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig55()")));
3550 #endif
3551
3552     emit o.sig00();
3553     QCOMPARE(o.rec, 1);
3554     emit o.sig69();
3555     QCOMPARE(o.rec, 2);
3556     emit o.sig36();
3557     QCOMPARE(o.rec, 2);
3558 }
3559
3560 void tst_QObject::qMetaObjectConnect()
3561 {
3562     SenderObject *s = new SenderObject;
3563     ReceiverObject *r1 = new ReceiverObject;
3564     ReceiverObject *r2 = new ReceiverObject;
3565     r1->reset();
3566     r2->reset();
3567     ReceiverObject::sequence = 0;
3568
3569     int signal1Index = s->metaObject()->indexOfSignal("signal1()");
3570     int signal3Index = s->metaObject()->indexOfSignal("signal3()");
3571     int slot1Index = r1->metaObject()->indexOfSlot("slot1()");
3572     int slot2Index = r1->metaObject()->indexOfSlot("slot2()");
3573     int slot3Index = r1->metaObject()->indexOfSlot("slot3()");
3574
3575     QVERIFY(slot1Index > 0);
3576     QVERIFY(slot2Index > 0);
3577     QVERIFY(slot3Index > 0);
3578
3579     QVERIFY( QMetaObject::connect( s, signal1Index, r1, slot1Index) );
3580     QVERIFY( QMetaObject::connect( s, signal3Index, r2, slot3Index) );
3581     QVERIFY( QMetaObject::connect( s, -1, r2, slot2Index) );
3582
3583     QCOMPARE( r1->count_slot1, 0 );
3584     QCOMPARE( r1->count_slot2, 0 );
3585     QCOMPARE( r1->count_slot3, 0 );
3586     QCOMPARE( r2->count_slot1, 0 );
3587     QCOMPARE( r2->count_slot2, 0 );
3588     QCOMPARE( r2->count_slot3, 0 );
3589
3590     s->emitSignal1();
3591
3592     QCOMPARE( r1->count_slot1, 1 );
3593     QCOMPARE( r1->count_slot2, 0 );
3594     QCOMPARE( r1->count_slot3, 0 );
3595     QCOMPARE( r2->count_slot1, 0 );
3596     QCOMPARE( r2->count_slot2, 1 );
3597     QCOMPARE( r2->count_slot3, 0 );
3598
3599     s->emitSignal2();
3600     s->emitSignal3();
3601     s->emitSignal4();
3602
3603     QCOMPARE( r1->count_slot1, 1 );
3604     QCOMPARE( r1->count_slot2, 0 );
3605     QCOMPARE( r1->count_slot3, 0 );
3606     QCOMPARE( r2->count_slot1, 0 );
3607     QCOMPARE( r2->count_slot2, 4 );
3608     QCOMPARE( r2->count_slot3, 1 );
3609
3610     QVERIFY( QMetaObject::disconnect( s, signal1Index, r1, slot1Index) );
3611     QVERIFY( QMetaObject::disconnect( s, signal3Index, r2, slot3Index) );
3612     QVERIFY( QMetaObject::disconnect( s, -1, r2, slot2Index) );
3613
3614     s->emitSignal1();
3615     s->emitSignal2();
3616     s->emitSignal3();
3617     s->emitSignal4();
3618
3619     QCOMPARE( r1->count_slot1, 1 );
3620     QCOMPARE( r1->count_slot2, 0 );
3621     QCOMPARE( r1->count_slot3, 0 );
3622     QCOMPARE( r2->count_slot1, 0 );
3623     QCOMPARE( r2->count_slot2, 4 );
3624     QCOMPARE( r2->count_slot3, 1 );
3625
3626     //some "dynamic" signal
3627     QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 20, r1, slot3Index) );
3628     QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 35, r2, slot1Index) );
3629     QVERIFY( QMetaObject::connect( s, -1, r1, slot2Index) );
3630
3631     r1->reset();
3632     r2->reset();
3633
3634     void *args[] = { 0 , 0 };
3635     QMetaObject::activate(s, s->metaObject()->methodOffset() + 20, args);
3636     QMetaObject::activate(s, s->metaObject()->methodOffset() + 48, args);
3637     QCOMPARE( r1->count_slot1, 0 );
3638     QCOMPARE( r1->count_slot2, 2 );
3639     QCOMPARE( r1->count_slot3, 1 );
3640     QCOMPARE( r2->count_slot1, 0 );
3641     QCOMPARE( r2->count_slot2, 0 );
3642     QCOMPARE( r2->count_slot3, 0 );
3643
3644     QMetaObject::activate(s, s->metaObject()->methodOffset() + 35, args);
3645     s->emitSignal1();
3646     s->emitSignal2();
3647
3648     QCOMPARE( r1->count_slot1, 0 );
3649     QCOMPARE( r1->count_slot2, 5 );
3650     QCOMPARE( r1->count_slot3, 1 );
3651     QCOMPARE( r2->count_slot1, 1 );
3652     QCOMPARE( r2->count_slot2, 0 );
3653     QCOMPARE( r2->count_slot3, 0 );
3654
3655     delete s;
3656     r1->reset();
3657     r2->reset();
3658
3659 #define SIGNAL_INDEX(S)  obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S))
3660     OverloadObject obj1;
3661     QObject obj2, obj3;
3662
3663     QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , r1, slot1Index);
3664     QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) , r2, slot1Index);
3665
3666     QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , r1, slot2Index);
3667     QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , r2, slot2Index);
3668     QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , r1, slot3Index);
3669
3670     emit obj1.sig(0.5); //connected to nothing
3671     emit obj1.sig(1, 'a'); //connected to nothing
3672     QCOMPARE( r1->count_slot1, 0 );
3673     QCOMPARE( r1->count_slot2, 0 );
3674     QCOMPARE( r1->count_slot3, 0 );
3675     QCOMPARE( r2->count_slot1, 0 );
3676     QCOMPARE( r2->count_slot2, 0 );
3677     QCOMPARE( r2->count_slot3, 0 );
3678
3679     emit obj1.sig(1); //this signal is connected
3680     emit obj1.sig(&obj2);
3681
3682     QCOMPARE( r1->count_slot1, 1 );
3683     QCOMPARE( r1->count_slot2, 0 );
3684     QCOMPARE( r1->count_slot3, 1 );
3685     QCOMPARE( r2->count_slot1, 0 );
3686     QCOMPARE( r2->count_slot2, 1 );
3687     QCOMPARE( r2->count_slot3, 0 );
3688
3689     emit obj1.sig(&obj2, &obj3); //this signal is connected
3690
3691     QCOMPARE( r1->count_slot1, 1 );
3692     QCOMPARE( r1->count_slot2, 1 );
3693     QCOMPARE( r1->count_slot3, 1 );
3694     QCOMPARE( r2->count_slot1, 1 );
3695     QCOMPARE( r2->count_slot2, 1 );
3696     QCOMPARE( r2->count_slot3, 0 );
3697
3698     delete r1;
3699     delete r2;
3700
3701 }
3702
3703 void tst_QObject::qMetaObjectDisconnectOne()
3704 {
3705     SenderObject *s = new SenderObject;
3706     ReceiverObject *r1 = new ReceiverObject;
3707
3708     int signal1Index = s->metaObject()->indexOfSignal("signal1()");
3709     int signal3Index = s->metaObject()->indexOfSignal("signal3()");
3710     int slot1Index = r1->metaObject()->indexOfSlot("slot1()");
3711     int slot2Index = r1->metaObject()->indexOfSlot("slot2()");
3712
3713     QVERIFY(signal1Index > 0);
3714     QVERIFY(signal3Index > 0);
3715     QVERIFY(slot1Index > 0);
3716     QVERIFY(slot2Index > 0);
3717
3718     QVERIFY( QMetaObject::connect(s, signal1Index, r1, slot1Index) );
3719     QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
3720     QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
3721     QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
3722
3723     r1->reset();
3724     QCOMPARE( r1->count_slot1, 0 );
3725     QCOMPARE( r1->count_slot2, 0 );
3726
3727     s->emitSignal1();
3728     QCOMPARE( r1->count_slot1, 1 );
3729     QCOMPARE( r1->count_slot2, 0 );
3730
3731     s->emitSignal3();
3732     QCOMPARE( r1->count_slot1, 1 );
3733     QCOMPARE( r1->count_slot2, 3 );
3734
3735     r1->reset();
3736     QVERIFY( QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
3737     QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
3738
3739     s->emitSignal1();
3740     QCOMPARE( r1->count_slot1, 0 );
3741     QCOMPARE( r1->count_slot2, 0 );
3742
3743     s->emitSignal3();
3744     QCOMPARE( r1->count_slot1, 0 );
3745     QCOMPARE( r1->count_slot2, 2 );
3746
3747     r1->reset();
3748     QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
3749     QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
3750
3751     s->emitSignal1();
3752     QCOMPARE( r1->count_slot1, 0 );
3753     QCOMPARE( r1->count_slot2, 0 );
3754
3755     s->emitSignal3();
3756     QCOMPARE( r1->count_slot1, 0 );
3757     QCOMPARE( r1->count_slot2, 1 );
3758
3759     r1->reset();
3760     QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
3761     QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
3762
3763     s->emitSignal1();
3764     QCOMPARE( r1->count_slot1, 0 );
3765     QCOMPARE( r1->count_slot2, 0 );
3766
3767     s->emitSignal3();
3768     QCOMPARE( r1->count_slot1, 0 );
3769     QCOMPARE( r1->count_slot2, 0 );
3770
3771     delete s;
3772     delete r1;
3773 }
3774
3775 class ConfusingObject : public SenderObject
3776 { Q_OBJECT
3777 public slots:
3778     void signal1() { s++; }
3779 signals:
3780     void aPublicSlot();
3781 public:
3782     int s;
3783     ConfusingObject() : s(0) {}
3784     friend class tst_QObject;
3785 };
3786
3787 void tst_QObject::sameName()
3788 {
3789     ConfusingObject c1, c2;
3790     QVERIFY(connect(&c1, SIGNAL(signal1()), &c1, SLOT(signal1())));
3791     c1.emitSignal1();
3792     QCOMPARE(c1.s, 1);
3793
3794     QVERIFY(connect(&c2, SIGNAL(signal1()), &c1, SIGNAL(signal1())));
3795     c2.emitSignal1();
3796     QCOMPARE(c1.s, 2);
3797
3798     QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(signal1())));
3799     c2.aPublicSlot();
3800     QCOMPARE(c2.aPublicSlotCalled, 0);
3801     QCOMPARE(c1.aPublicSlotCalled, 0);
3802     QCOMPARE(c1.s, 3);
3803
3804     QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(aPublicSlot())));
3805     c2.aPublicSlot();
3806     QCOMPARE(c2.aPublicSlotCalled, 0);
3807     QCOMPARE(c1.aPublicSlotCalled, 1);
3808     QCOMPARE(c1.s, 4);
3809 }
3810
3811 void tst_QObject::connectByMetaMethods()
3812 {
3813     SenderObject s;
3814     ReceiverObject r;
3815     const QMetaObject *smeta = s.metaObject();
3816     const QMetaObject *rmeta = r.metaObject();
3817     int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()"));
3818     int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
3819     QVERIFY( sigIndx != -1 );
3820     QVERIFY( slotIndx != -1 );
3821     QMetaMethod signal = smeta->method(sigIndx);
3822     QMetaMethod slot = rmeta->method(slotIndx);
3823
3824     QVERIFY(connect(&s,signal, &r,slot));
3825
3826     QVERIFY(!r.called(1));
3827     s.emitSignal1();
3828     QVERIFY(r.called(1));
3829 }
3830
3831 void tst_QObject::connectByMetaMethodSlotInsteadOfSignal()
3832 {
3833     SenderObject s;
3834     ReceiverObject r;
3835     const QMetaObject *smeta = s.metaObject();
3836     const QMetaObject *rmeta = r.metaObject();
3837     int badIndx = smeta->indexOfSlot(QMetaObject::normalizedSignature("aPublicSlot()"));
3838     int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
3839     QVERIFY( badIndx != -1 );
3840     QVERIFY( slotIndx != -1 );
3841     QMetaMethod badMethod = smeta->method(badIndx);
3842     QMetaMethod slot = rmeta->method(slotIndx);
3843
3844     QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::aPublicSlot() to ReceiverObject::slot1()");
3845     QVERIFY(!connect(&s,badMethod, &r,slot));
3846 }
3847
3848 class Constructable: public QObject
3849 {
3850     Q_OBJECT
3851
3852 public:
3853     Q_INVOKABLE Constructable(){}
3854
3855 };
3856
3857 void tst_QObject::connectConstructorByMetaMethod()
3858 {
3859     Constructable sc;
3860     Constructable rc;
3861     SenderObject s;
3862     ReceiverObject r;
3863
3864     const QMetaObject cmeta = Constructable::staticMetaObject;
3865     const QMetaObject *smeta = s.metaObject();
3866     const QMetaObject *rmeta = r.metaObject();
3867     int constructorIndx = cmeta.indexOfConstructor(QMetaObject::normalizedSignature("Constructable()"));
3868     int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()"));
3869     int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
3870     QVERIFY( constructorIndx != -1 );
3871     QVERIFY( sigIndx != -1 );
3872     QVERIFY( slotIndx != -1 );
3873
3874     QMetaMethod constructor = cmeta.constructor(constructorIndx);
3875     QMetaMethod signal = smeta->method(sigIndx);
3876     QMetaMethod slot = rmeta->method(slotIndx);
3877
3878     QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to ReceiverObject::slot1()");
3879     QVERIFY(!connect(&sc,constructor, &r,slot));
3880     QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::signal1() to Constructable::Constructable()");
3881     QVERIFY(!connect(&s,signal, &rc,constructor));
3882     QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to Constructable::Constructable()");
3883     QVERIFY(!connect(&sc,constructor, &rc,constructor));
3884 }
3885
3886 void tst_QObject::disconnectByMetaMethod()
3887 {
3888     SenderObject *s = new SenderObject;
3889     ReceiverObject *r1 = new ReceiverObject;
3890     ReceiverObject *r2 = new ReceiverObject;
3891
3892     QMetaMethod signal1 = s->metaObject()->method(
3893             s->metaObject()->indexOfMethod("signal1()"));
3894     QMetaMethod signal2 = s->metaObject()->method(
3895             s->metaObject()->indexOfMethod("signal2()"));
3896     QMetaMethod signal3 = s->metaObject()->method(
3897             s->metaObject()->indexOfMethod("signal3()"));
3898
3899     QMetaMethod slot1 = r1->metaObject()->method(
3900             r1->metaObject()->indexOfMethod("slot1()"));
3901     QMetaMethod slot2 = r1->metaObject()->method(
3902             r1->metaObject()->indexOfMethod("slot2()"));
3903     QMetaMethod slot3 = r1->metaObject()->method(
3904             r1->metaObject()->indexOfMethod("slot3()"));
3905     QMetaMethod slot4 = r1->metaObject()->method(
3906             r1->metaObject()->indexOfMethod("slot4()"));
3907
3908     connect(s, signal1, r1, slot1);
3909
3910     s->emitSignal1();
3911
3912     QVERIFY(r1->called(1));
3913     r1->reset();
3914
3915     // usual disconnect with all parameters given
3916     bool ret = QObject::disconnect(s, signal1, r1, slot1);
3917
3918     s->emitSignal1();
3919
3920     QVERIFY(!r1->called(1));
3921     r1->reset();
3922
3923     QVERIFY(ret);
3924     ret = QObject::disconnect(s, signal1, r1, slot1);
3925     QVERIFY(!ret);
3926
3927     r1->reset();
3928
3929     connect( s, signal1, r1, slot1 );
3930     connect( s, signal1, r1, slot2 );
3931     connect( s, signal1, r1, slot3 );
3932     connect( s, signal2, r1, slot4 );
3933
3934     // disconnect s's signal1() from all slots of r1
3935     QObject::disconnect(s, signal1, r1, QMetaMethod());
3936
3937     s->emitSignal1();
3938     s->emitSignal2();
3939
3940     QVERIFY(!r1->called(1));
3941     QVERIFY(!r1->called(2));
3942     QVERIFY(!r1->called(3));
3943     QVERIFY(r1->called(4));
3944     r1->reset();
3945     // make sure all is disconnected again
3946     QObject::disconnect(s, 0, r1, 0);
3947
3948     connect(s, signal1, r1, slot1);
3949     connect(s, signal1, r2, slot1);
3950     connect(s, signal2, r1, slot2);
3951     connect(s, signal2, r2, slot2);
3952     connect(s, signal3, r1, slot3);
3953     connect(s, signal3, r2, slot3);
3954
3955     // disconnect signal1() from all receivers
3956     QObject::disconnect(s, signal1, 0, QMetaMethod());
3957     s->emitSignal1();
3958     s->emitSignal2();
3959     s->emitSignal3();
3960
3961     QVERIFY(!r1->called(1));
3962     QVERIFY(!r2->called(1));
3963     QVERIFY(r1->called(2));
3964     QVERIFY(r2->called(2));
3965     QVERIFY(r1->called(2));
3966     QVERIFY(r2->called(2));
3967
3968     r1->reset();
3969     r2->reset();
3970
3971     // disconnect all signals of s from all receivers
3972     QObject::disconnect( s, 0, 0, 0 );
3973
3974     connect( s, signal1, r1, slot1 );
3975     connect( s, signal1, r2, slot1 );
3976
3977     // disconnect all signals from slot1 of r1
3978     QObject::disconnect(s, QMetaMethod(), r1, slot1);
3979
3980     s->emitSignal1();
3981
3982     QVERIFY(!r1->called(1));
3983     QVERIFY(r2->called(1));
3984
3985     delete r2;
3986     delete r1;
3987     delete s;
3988 }
3989
3990 void tst_QObject::disconnectNotSignalMetaMethod()
3991 {
3992     SenderObject s;
3993     ReceiverObject r;
3994
3995     connect(&s, SIGNAL(signal1()), &r, SLOT(slot1()));
3996
3997     QMetaMethod slot = s.metaObject()->method(
3998             s.metaObject()->indexOfMethod("aPublicSlot()"));
3999
4000     QTest::ignoreMessage(QtWarningMsg,"QObject::disconnect: Attempt to unbind non-signal SenderObject::aPublicSlot()");
4001     QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod()));
4002 }
4003
4004 class ThreadAffinityThread : public QThread
4005 {
4006 public:
4007     SenderObject *sender;
4008
4009     ThreadAffinityThread(SenderObject *sender)
4010         : sender(sender)
4011     { }
4012     void run()
4013     {
4014         sender->emitSignal1();
4015     }
4016 };
4017
4018 void tst_QObject::autoConnectionBehavior()
4019 {
4020     SenderObject *sender = new SenderObject;
4021     ReceiverObject *receiver = new ReceiverObject;
4022     connect(sender, SIGNAL(signal1()), receiver, SLOT(slot1()));
4023
4024     // at emit, currentThread == sender->thread(), currentThread == receiver->thread(), sender->thread() == receiver->thread()
4025     QVERIFY(!receiver->called(1));
4026     sender->emitSignal1();
4027     QVERIFY(receiver->called(1));
4028     receiver->reset();
4029
4030     // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() == receiver->thread()
4031     ThreadAffinityThread emitThread1(sender);
4032     QVERIFY(!receiver->called(1));
4033     emitThread1.start();
4034     QVERIFY(emitThread1.wait(30000));
4035     QVERIFY(!receiver->called(1));
4036     QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall);
4037     QVERIFY(receiver->called(1));
4038     receiver->reset();
4039
4040     // at emit, currentThread == sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread()
4041     sender->moveToThread(&emitThread1);
4042     QVERIFY(!receiver->called(1));
4043     emitThread1.start();
4044     QVERIFY(emitThread1.wait(30000));
4045     QVERIFY(!receiver->called(1));
4046     QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall);
4047     QVERIFY(receiver->called(1));
4048     receiver->reset();
4049
4050     // at emit, currentThread != sender->thread(), currentThread == receiver->thread(), sender->thread() != receiver->thread()
4051     QVERIFY(!receiver->called(1));
4052     sender->emitSignal1();
4053     QVERIFY(receiver->called(1));
4054     receiver->reset();
4055
4056     // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread()
4057     ThreadAffinityThread emitThread2(sender);
4058     QThread receiverThread;
4059     QTimer *timer = new QTimer;
4060     timer->setSingleShot(true);
4061     timer->setInterval(100);
4062     connect(&receiverThread, SIGNAL(started()), timer, SLOT(start()));
4063     connect(timer, SIGNAL(timeout()), &receiverThread, SLOT(quit()), Qt::DirectConnection);
4064     connect(&receiverThread, SIGNAL(finished()), timer, SLOT(deleteLater()));
4065     timer->moveToThread(&receiverThread);
4066
4067     receiver->moveToThread(&receiverThread);
4068     QVERIFY(!receiver->called(1));
4069     emitThread2.start();
4070     QVERIFY(emitThread2.wait(30000));
4071     QVERIFY(!receiver->called(1));
4072     receiverThread.start();
4073     QVERIFY(receiverThread.wait(30000));
4074     QVERIFY(receiver->called(1));
4075     receiver->reset();
4076
4077     delete sender;
4078     delete receiver;
4079 }
4080
4081 class BaseDestroyed : public QObject
4082 { Q_OBJECT
4083     QList<QString> fooList;
4084     bool destroyed;
4085 public:
4086     BaseDestroyed() : destroyed(false)
4087     { fooList << "a" << "b"; }
4088     ~BaseDestroyed()
4089     {
4090         QVERIFY(!destroyed);
4091         destroyed = true;
4092     }
4093
4094 public slots:
4095     void slotUseList()
4096     {
4097         QVERIFY(!destroyed);
4098         fooList << "c" << "d";
4099     }
4100 };
4101
4102 static void processEvents()
4103 {
4104     qApp->processEvents();
4105 }
4106
4107 void tst_QObject::baseDestroyed()
4108 {
4109     {
4110         BaseDestroyed d;
4111         connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList()));
4112         //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has
4113         // already been destroyed while ~QObject emit destroyed
4114     }
4115     {
4116         BaseDestroyed d;
4117         connect(&d, &QObject::destroyed, processEvents);
4118         QMetaObject::invokeMethod(&d, "slotUseList", Qt::QueuedConnection);
4119         //the destructor will call processEvents, that should not call the slotUseList
4120     }
4121 }
4122
4123 void tst_QObject::pointerConnect()
4124 {
4125     SenderObject *s = new SenderObject;
4126     ReceiverObject *r1 = new ReceiverObject;
4127     ReceiverObject *r2 = new ReceiverObject;
4128     r1->reset();
4129     r2->reset();
4130     ReceiverObject::sequence = 0;
4131
4132     QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot1 ) );
4133     QVERIFY( connect( s, &SenderObject::signal1 , r2, &ReceiverObject::slot1 ) );
4134     QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot3 ) );
4135     QVERIFY( connect( s, &SenderObject::signal3 , r1, &ReceiverObject::slot3 ) );
4136
4137     s->emitSignal1();
4138     s->emitSignal2();
4139     s->emitSignal3();
4140     s->emitSignal4();
4141
4142     QCOMPARE( r1->count_slot1, 1 );
4143     QCOMPARE( r1->count_slot2, 0 );
4144     QCOMPARE( r1->count_slot3, 2 );
4145     QCOMPARE( r1->count_slot4, 0 );
4146     QCOMPARE( r2->count_slot1, 1 );
4147     QCOMPARE( r2->count_slot2, 0 );
4148     QCOMPARE( r2->count_slot3, 0 );
4149     QCOMPARE( r2->count_slot4, 0 );
4150     QCOMPARE( r1->sequence_slot1, 1 );
4151     QCOMPARE( r2->sequence_slot1, 2 );
4152     QCOMPARE( r1->sequence_slot3, 4 );
4153
4154     r1->reset();
4155     r2->reset();
4156     ReceiverObject::sequence = 0;
4157
4158     QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ) );
4159     QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 ) );
4160     QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 ) );
4161
4162     s->emitSignal4();
4163     QCOMPARE( r1->count_slot4, 1 );
4164     QCOMPARE( r2->count_slot4, 1 );
4165     QCOMPARE( r1->sequence_slot4, 1 );
4166     QCOMPARE( r2->sequence_slot4, 2 );
4167
4168     r1->reset();
4169     r2->reset();
4170     ReceiverObject::sequence = 0;
4171
4172     connect( s, &SenderObject::signal4 , r1, &ReceiverObject::slot4  );
4173
4174     s->emitSignal4();
4175     QCOMPARE( r1->count_slot4, 2 );
4176     QCOMPARE( r2->count_slot4, 1 );
4177     QCOMPARE( r1->sequence_slot4, 3 );
4178     QCOMPARE( r2->sequence_slot4, 2 );
4179
4180     QMetaObject::Connection con;
4181     QVERIFY(!con);
4182     QVERIFY(!QObject::disconnect(con));
4183
4184     //connect a slot to a signal (== error)
4185     QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
4186     con = connect(r1, &ReceiverObject::slot4 , s, &SenderObject::signal4 );
4187     QVERIFY(!con);
4188     QVERIFY(!QObject::disconnect(con));
4189
4190     delete s;
4191     delete r1;
4192     delete r2;
4193 }
4194
4195 void tst_QObject::pointerDisconnect()
4196 {
4197     SenderObject *s = new SenderObject;
4198     ReceiverObject *r1 = new ReceiverObject;
4199     ReceiverObject *r2 = new ReceiverObject;
4200
4201     connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4202
4203     connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
4204     connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
4205     connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
4206
4207     s->emitSignal1();
4208     s->emitSignal2();
4209     s->emitSignal3();
4210     s->emitSignal4();
4211
4212     QVERIFY(r1->called(1));
4213     QVERIFY(r1->called(2));
4214     QVERIFY(r1->called(3));
4215     QVERIFY(r1->called(4));
4216     r1->reset();
4217
4218     // usual disconnect with all parameters given
4219     bool ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4220
4221     s->emitSignal1();
4222
4223     QVERIFY(!r1->called(1));
4224     r1->reset();
4225
4226     QVERIFY(ret);
4227     ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4228     QVERIFY(!ret);
4229
4230     // disconnect all signals from s from all slots from r1
4231     QObject::disconnect( s, 0, r1, 0 );
4232
4233     s->emitSignal2();
4234     s->emitSignal3();
4235     s->emitSignal4();
4236
4237     QVERIFY(!r1->called(2));
4238     QVERIFY(!r1->called(3));
4239     QVERIFY(!r1->called(4));
4240     r1->reset();
4241
4242     connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4243     connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot2 );
4244     connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 );
4245     connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot4 );
4246
4247     // disconnect s's signal1() from all slots of r1
4248     QObject::disconnect( s, &SenderObject::signal1, r1, 0 );
4249
4250     s->emitSignal1();
4251     s->emitSignal2();
4252
4253     QVERIFY(!r1->called(1));
4254     QVERIFY(!r1->called(2));
4255     QVERIFY(!r1->called(3));
4256     QVERIFY(r1->called(4));
4257     r1->reset();
4258     // make sure all is disconnected again
4259     QObject::disconnect( s, 0, r1, 0 );
4260
4261     connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4262     connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 );
4263     connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
4264     connect( s, &SenderObject::signal2, r2, &ReceiverObject::slot2 );
4265     connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
4266     connect( s, &SenderObject::signal3, r2, &ReceiverObject::slot3 );
4267
4268     // disconnect signal1() from all receivers
4269     QObject::disconnect( s, &SenderObject::signal1, 0, 0 );
4270     s->emitSignal1();
4271     s->emitSignal2();
4272     s->emitSignal3();
4273
4274     QVERIFY(!r1->called(1));
4275     QVERIFY(!r2->called(1));
4276     QVERIFY(r1->called(2));
4277     QVERIFY(r2->called(2));
4278     QVERIFY(r1->called(2));
4279     QVERIFY(r2->called(2));
4280
4281     r1->reset();
4282     r2->reset();
4283
4284     // disconnect all signals of s from all receivers
4285     QObject::disconnect( s, 0, 0, 0 );
4286
4287     QVERIFY(!r1->called(2));
4288     QVERIFY(!r2->called(2));
4289     QVERIFY(!r1->called(2));
4290     QVERIFY(!r2->called(2));
4291
4292     delete r2;
4293     delete r1;
4294     delete s;
4295
4296 }
4297
4298
4299 void tst_QObject::emitInDefinedOrderPointer()
4300 {
4301     SenderObject sender;
4302     ReceiverObject receiver1, receiver2, receiver3, receiver4;
4303
4304     QMetaObject::Connection h0 = connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot1);
4305     QMetaObject::Connection h1 = connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot1);
4306     QVERIFY(h0);
4307     QVERIFY(h1);
4308     connect(&sender, &SenderObject::signal1, &receiver3, &SequenceObject::slot1);
4309     connect(&sender, &SenderObject::signal1, &receiver4, &SequenceObject::slot1);
4310     connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot2);
4311     connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot2);
4312     connect(&sender, &SenderObject::signal1, &receiver3, &SequenceObject::slot2);
4313     connect(&sender, &SenderObject::signal1, &receiver4, &SequenceObject::slot2);
4314
4315     int sequence;
4316     ReceiverObject::sequence = sequence = 0;
4317     sender.emitSignal1();
4318     QCOMPARE(receiver1.sequence_slot1, ++sequence);
4319     QCOMPARE(receiver2.sequence_slot1, ++sequence);
4320     QCOMPARE(receiver3.sequence_slot1, ++sequence);
4321     QCOMPARE(receiver4.sequence_slot1, ++sequence);
4322     QCOMPARE(receiver1.sequence_slot2, ++sequence);
4323     QCOMPARE(receiver2.sequence_slot2, ++sequence);
4324     QCOMPARE(receiver3.sequence_slot2, ++sequence);
4325     QCOMPARE(receiver4.sequence_slot2, ++sequence);
4326
4327     QObject::disconnect(h1);
4328     h1 = connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot1);
4329
4330     ReceiverObject::sequence = sequence =  0;
4331     sender.emitSignal1();
4332     QCOMPARE(receiver1.sequence_slot1, ++sequence);
4333     QCOMPARE(receiver3.sequence_slot1, ++sequence);
4334     QCOMPARE(receiver4.sequence_slot1, ++sequence);
4335     QCOMPARE(receiver1.sequence_slot2, ++sequence);
4336     QCOMPARE(receiver2.sequence_slot2, ++sequence);
4337     QCOMPARE(receiver3.sequence_slot2, ++sequence);
4338     QCOMPARE(receiver4.sequence_slot2, ++sequence);
4339     QCOMPARE(receiver2.sequence_slot1, ++sequence);
4340
4341     QObject::disconnect(h0);
4342     h0 = connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot1);
4343
4344     ReceiverObject::sequence = sequence =  0;
4345     sender.emitSignal1();
4346     QCOMPARE(receiver3.sequence_slot1, ++sequence);
4347     QCOMPARE(receiver4.sequence_slot1, ++sequence);
4348     QCOMPARE(receiver1.sequence_slot2, ++sequence);
4349     QCOMPARE(receiver2.sequence_slot2, ++sequence);
4350     QCOMPARE(receiver3.sequence_slot2, ++sequence);
4351     QCOMPARE(receiver4.sequence_slot2, ++sequence);
4352     QCOMPARE(receiver2.sequence_slot1, ++sequence);
4353     QCOMPARE(receiver1.sequence_slot1, ++sequence);
4354
4355     QVERIFY(QObject::disconnect(h0));
4356     QVERIFY(!QObject::disconnect(h0));
4357 }
4358
4359
4360 void tst_QObject::customTypesPointer()
4361 {
4362     CustomType t0;
4363     CustomType t1(1, 2, 3);
4364     CustomType t2(2, 3, 4);
4365
4366     {
4367         QCustomTypeChecker checker;
4368         QCOMPARE(instanceCount, 4);
4369
4370         connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1,
4371                 Qt::DirectConnection);
4372         QCOMPARE(checker.received.value(), 0);
4373         checker.doEmit(t1);
4374         QCOMPARE(checker.received.value(), t1.value());
4375         checker.received = t0;
4376
4377
4378         checker.disconnect();
4379
4380         int idx = qRegisterMetaType<CustomType>("CustomType");
4381         QCOMPARE(QMetaType::type("CustomType"), idx);
4382
4383         connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1,
4384                 Qt::QueuedConnection);
4385         QCOMPARE(instanceCount, 4);
4386         checker.doEmit(t2);
4387         QCOMPARE(instanceCount, 5);
4388         QCOMPARE(checker.received.value(), t0.value());
4389
4390         QCoreApplication::processEvents();
4391         QCOMPARE(checker.received.value(), t2.value());
4392         QCOMPARE(instanceCount, 4);
4393
4394         QVERIFY(QMetaType::isRegistered(idx));
4395         QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
4396         QCOMPARE(QMetaType::type("CustomType"), idx);
4397         QVERIFY(QMetaType::isRegistered(idx));
4398     }
4399     QCOMPARE(instanceCount, 3);
4400 }
4401
4402 void tst_QObject::connectCxx0x()
4403 {
4404     SenderObject *s = new SenderObject;
4405     ReceiverObject *r1 = new ReceiverObject;
4406
4407     QObject::connect(s, &SenderObject::signal1, r1, &ReceiverObject::slot1);
4408     QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
4409     QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
4410     QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
4411
4412     r1->reset();
4413     QCOMPARE( r1->count_slot1, 0 );
4414     QCOMPARE( r1->count_slot2, 0 );
4415
4416     s->emitSignal1();
4417     QCOMPARE( r1->count_slot1, 1 );
4418     QCOMPARE( r1->count_slot2, 0 );
4419
4420     s->emitSignal3();
4421     QCOMPARE( r1->count_slot1, 1 );
4422     QCOMPARE( r1->count_slot2, 3 );
4423
4424     // connect signal to signal
4425     QObject::connect(s, &SenderObject::signal2, s, &SenderObject::signal1);
4426
4427     r1->reset();
4428     s->emitSignal2();
4429     QCOMPARE( r1->count_slot1, 1 );
4430
4431     delete s;
4432     delete r1;
4433 }
4434
4435 int receivedCount;
4436 void receiverFunction() { ++receivedCount; }
4437
4438 void tst_QObject::connectToStaticCxx0x()
4439 {
4440     SenderObject *s = new SenderObject;
4441
4442     void (*receiver)() = receiverFunction;
4443
4444     QObject::connect(s, &SenderObject::signal1, receiver);
4445     receivedCount = 0;
4446     s->emitSignal1();
4447     QCOMPARE(receivedCount, 1);
4448
4449     QObject::connect(s, &SenderObject::signal1, receiver);
4450     receivedCount = 0;
4451     s->emitSignal1();
4452     QCOMPARE(receivedCount, 2);
4453
4454     delete s;
4455 }
4456
4457 class LotsOfSignalsAndSlots: public QObject
4458 {
4459     Q_OBJECT
4460     typedef void (*fptr)();
4461
4462     public slots:
4463         void slot_v() {}
4464         void slot_vi(int) {}
4465         void slot_vii(int, int) {}
4466         void slot_viii(int, int, int) {}
4467         int slot_i() { return 0; }
4468         int slot_ii(int) { return 0; }
4469         int slot_iii(int, int) { return 0; }
4470         int slot_iiii(int, int, int) { return 0; }
4471         void slot_vRi(int &) {}
4472         void slot_vs(short) {}
4473         void slot_vRs(short&) {}
4474    /*     #ifdef Q_COMPILER_RVALUE_REFS
4475         void slot_vOi(int &&) {}
4476         void slot_vOs(short &&) {}
4477         #endif*/
4478         void slot_vPFvvE(fptr) {}
4479
4480         static void static_slot_v() {}
4481         static void static_slot_vi(int) {}
4482         static void static_slot_vii(int, int) {}
4483         static void static_slot_viii(int, int, int) {}
4484         static int static_slot_i() { return 0; }
4485         static int static_slot_ii(int) { return 0; }
4486         static int static_slot_iii(int, int) { return 0; }
4487         static int static_slot_iiii(int, int, int) { return 0; }
4488         static void static_slot_vRi(int &) {}
4489         static void static_slot_vs(short) {}
4490         static void static_slot_vRs(short&) {}
4491 /*        #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4492         static void static_slot_vOi(int &&) {}
4493         static void static_slot_vOs(short &&) {}
4494         #endif*/
4495         static void static_slot_vPFvvE(fptr) {}
4496
4497     signals:
4498         void signal_v();
4499         void signal_vi(int);
4500         void signal_vii(int, int);
4501         void signal_viii(int, int, int);
4502         void signal_vRi(int &);
4503         void signal_vs(short);
4504         void signal_vRs(short &);
4505 /*        #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4506         void signal_vOi(int &&);
4507         void signal_vOs(short &&);
4508         #endif*/
4509         void signal_vPFvvE(fptr);
4510
4511         void signal(short&, short, long long, short);
4512         void otherSignal(const char *);
4513 };
4514
4515 void tst_QObject::connectCxx0xTypeMatching()
4516 {
4517     // this is just about connecting the signals to the slots
4518     // if this fails, this will be a compiler failure
4519     typedef LotsOfSignalsAndSlots Foo;
4520     Foo obj;
4521
4522     // member connects
4523     QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v);
4524     QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i);
4525
4526     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_v);
4527     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_i);
4528     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi);
4529     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_ii);
4530
4531     QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_v);
4532     QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_i);
4533     QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vi);
4534     QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_ii);
4535     QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vii);
4536     QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_iii);
4537
4538     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_v);
4539     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_i);
4540     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vi);
4541     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_ii);
4542     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vii);
4543     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iii);
4544     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_viii);
4545     QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iiii);
4546
4547     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi); // repeated from above
4548     QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vi);
4549     QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vRi);
4550 /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4551     QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vi);
4552     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vOi);
4553     QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vOi);
4554     QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vOi);
4555 #endif*/
4556     // these are not supposed to compile:
4557     //QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vRi);
4558     //QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vRi);
4559
4560     QObject::connect(&obj, &Foo::signal_vs, &obj, &Foo::slot_vi);
4561     QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vi);
4562 /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4563     QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vi);
4564     QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vOi);
4565     QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vOi);
4566     // these are not supposed to compile:
4567     //QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vRi);
4568     //QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vRi);
4569 #endif*/
4570
4571     QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_v);
4572     QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_i);
4573     QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_vPFvvE);
4574
4575     QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_v);
4576     QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_i);
4577
4578     QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_v);
4579     QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_i);
4580     QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vi);
4581     QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_ii);
4582
4583     QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v);
4584     QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i);
4585     QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi);
4586     QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_ii);
4587     QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vii);
4588     QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_iii);
4589
4590     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_v);
4591     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_i);
4592     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vi);
4593     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_ii);
4594     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vii);
4595     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iii);
4596     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_viii);
4597     QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iiii);
4598
4599 /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X)
4600     QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vOi);
4601     QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vi);
4602     QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vRi);
4603     QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vOi);
4604     QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vi);
4605     QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vOi);
4606     //QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vRi);
4607     //QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vRi);
4608 #endif*/
4609
4610     QObject::connect(&obj, &Foo::signal_vs, &Foo::static_slot_vi);
4611     QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vi);
4612 /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X)
4613     QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vi);
4614     QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vOi);
4615     QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vOi);
4616     //QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vRi);
4617     //QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vRi);
4618 #endif*/
4619     QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_v);
4620     QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_i);
4621     QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_vPFvvE);
4622     QVERIFY(true); //compilation only test
4623 }
4624
4625 class StringVariant : public QObject
4626 { Q_OBJECT
4627 signals:
4628     void stringSignal(const QString &str);
4629 public slots:
4630     void variantSlot(const QVariant &v) { var = v; }
4631 public:
4632     QVariant var;
4633     friend class tst_QObject;
4634 };
4635
4636 struct Functor {
4637     QVariant *var;
4638     void operator() (const QVariant &v) {
4639         *var = v;
4640     }
4641 };
4642
4643 void tst_QObject::connectConvert()
4644 {
4645     StringVariant obj;
4646     QVERIFY(connect(&obj, &StringVariant::stringSignal, &obj, &StringVariant::variantSlot));
4647     QString s = QString::fromLatin1("Hello World");
4648     emit obj.stringSignal(s);
4649     QCOMPARE(obj.var.toString(), s);
4650     QVERIFY(obj.var.toString().isSharedWith(s));
4651
4652     QVariant var;
4653     Functor f;
4654     f.var = &var;
4655     QVERIFY(connect(&obj, &StringVariant::stringSignal, f));
4656     s = QString::fromLatin1("GoodBye");
4657     emit obj.stringSignal(s);
4658     QCOMPARE(obj.var.toString(), s);
4659     QVERIFY(obj.var.toString().isSharedWith(s));
4660     QCOMPARE(var, obj.var);
4661 }
4662
4663 class ConnectWithReferenceObject : public QObject {
4664     Q_OBJECT
4665     friend class tst_QObject;
4666 signals:
4667     void boolRef(bool &, bool);
4668     void stringRef(QString &, const QString &);
4669     void boolPtr(bool *, bool);
4670     void stringPtr(QString *, const QString &);
4671 public slots:
4672     void boolRefSlot(bool &b1, bool b2) {  b1 = b2; }
4673     void stringRefSlot(QString &s1, const QString &s2) {  s1 = s2; }
4674     void boolPtrSlot(bool *b1, bool b2) {  *b1 = b2; }
4675     void stringPtrSlot(QString *s1, const QString &s2) {  *s1 = s2; }
4676
4677     void stringSlot1(QString s) { last = s; }
4678     void stringSlot2(const QString &s) { last = s; }
4679     void stringSlot3(QString &s) { last = s; }
4680 public:
4681     QString last;
4682 };
4683
4684 void tst_QObject::connectWithReference()
4685 {
4686     ConnectWithReferenceObject o;
4687     bool b1 = true;
4688     QString s1 = QString::fromLatin1("str1");
4689     const QString s2 = QString::fromLatin1("str2");
4690     const QString s3 = QString::fromLatin1("str3");
4691     o.boolRef(b1, false);
4692     o.stringRef(s1, s2);
4693     QCOMPARE(b1, true);
4694     QCOMPARE(s1, QString::fromLatin1("str1"));
4695     o.boolPtr(&b1, false);
4696     o.stringPtr(&s1, s2);
4697     QCOMPARE(b1, true);
4698     QCOMPARE(s1, QString::fromLatin1("str1"));
4699
4700     QVERIFY(connect(&o, &ConnectWithReferenceObject::boolRef, &o, &ConnectWithReferenceObject::boolRefSlot));
4701     QVERIFY(connect(&o, &ConnectWithReferenceObject::stringRef, &o, &ConnectWithReferenceObject::stringRefSlot));
4702     QVERIFY(connect(&o, &ConnectWithReferenceObject::boolPtr, &o, &ConnectWithReferenceObject::boolPtrSlot));
4703     QVERIFY(connect(&o, &ConnectWithReferenceObject::stringPtr, &o, &ConnectWithReferenceObject::stringPtrSlot));
4704     o.boolRef(b1, false);
4705     o.stringRef(s1, s2);
4706     QCOMPARE(b1, false);
4707     QCOMPARE(s1, QString::fromLatin1("str2"));
4708
4709     o.boolPtr(&b1, true);
4710     o.stringPtr(&s1, s3);
4711     QCOMPARE(b1, true);
4712     QCOMPARE(s1, QString::fromLatin1("str3"));
4713
4714     {
4715         ConnectWithReferenceObject o2;
4716         QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot1));
4717         o2.stringRef(s1, s2);
4718         QCOMPARE(s1, s3);
4719         QCOMPARE(o2.last, s3);
4720     }
4721     {
4722         ConnectWithReferenceObject o2;
4723         QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot2));
4724         o2.stringRef(s1, s2);
4725         QCOMPARE(s1, s3);
4726         QCOMPARE(o2.last, s3);
4727     }
4728     {
4729         ConnectWithReferenceObject o2;
4730         QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot3));
4731         o2.stringRef(s1, s2);
4732         QCOMPARE(s1, s3);
4733         QCOMPARE(o2.last, s3);
4734     }
4735 }
4736
4737 class ManyArgumentObject : public QObject {
4738     Q_OBJECT
4739 signals:
4740     void signal1(const QString &);
4741     void signal2(const QString &, const QString &);
4742     void signal3(const QString &, const QString &, const QString &);
4743     void signal4(const QString &, const QString &, const QString &, const QString&);
4744     void signal5(const QString &, const QString &, const QString &, const QString&, const QString&);
4745     void signal6(const QString &, const QString &, const QString &, const QString&, const QString&, const QString&);
4746
4747 public slots:
4748 #define MANYARGUMENT_COMPARE(L) QCOMPARE(L, QString(#L))
4749     void slot1(const QString &a) {
4750         MANYARGUMENT_COMPARE(a);
4751         count++;
4752     }
4753     void slot2(const QString &a, const QString &b) {
4754         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b);
4755         count++;
4756     }
4757     void slot3(const QString &a, const QString &b, const QString &c) {
4758         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4759         count++;
4760     }
4761     void slot4(const QString &a, const QString &b, const QString &c, const QString&d) {
4762         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4763         MANYARGUMENT_COMPARE(d);
4764         count++;
4765     }
4766     void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
4767         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4768         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e);
4769         count++;
4770     }
4771     void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
4772         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4773         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f);
4774         count++;
4775     }
4776 public:
4777     int count;
4778
4779 };
4780
4781 namespace ManyArgumentNamespace {
4782     int count;
4783     void slot1(const QString &a) {
4784         MANYARGUMENT_COMPARE(a);
4785         count++;
4786     }
4787     void slot2(const QString &a, const QString &b) {
4788         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b);
4789         count++;
4790     }
4791     void slot3(const QString &a, const QString &b, const QString &c) {
4792         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4793         count++;
4794     }
4795     void slot4(const QString &a, const QString &b, const QString &c, const QString&d) {
4796         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4797         MANYARGUMENT_COMPARE(d);
4798         count++;
4799     }
4800     void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
4801         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4802         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e);
4803         count++;
4804     }
4805     void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
4806         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4807         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f);
4808         count++;
4809     }
4810 }
4811
4812 void tst_QObject::connectManyArguments()
4813 {
4814     ManyArgumentObject ob;
4815     ob.count = 0;
4816     ManyArgumentNamespace::count = 0;
4817     connect(&ob, &ManyArgumentObject::signal1, &ob, &ManyArgumentObject::slot1);
4818     connect(&ob, &ManyArgumentObject::signal2, &ob, &ManyArgumentObject::slot2);
4819     connect(&ob, &ManyArgumentObject::signal3, &ob, &ManyArgumentObject::slot3);
4820     connect(&ob, &ManyArgumentObject::signal4, &ob, &ManyArgumentObject::slot4);
4821     connect(&ob, &ManyArgumentObject::signal5, &ob, &ManyArgumentObject::slot5);
4822     connect(&ob, &ManyArgumentObject::signal6, &ob, &ManyArgumentObject::slot6);
4823     connect(&ob, &ManyArgumentObject::signal1, ManyArgumentNamespace::slot1);
4824     connect(&ob, &ManyArgumentObject::signal2, ManyArgumentNamespace::slot2);
4825     connect(&ob, &ManyArgumentObject::signal3, ManyArgumentNamespace::slot3);
4826     connect(&ob, &ManyArgumentObject::signal4, ManyArgumentNamespace::slot4);
4827     connect(&ob, &ManyArgumentObject::signal5, ManyArgumentNamespace::slot5);
4828     connect(&ob, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot6);
4829
4830
4831     connect(&ob, &ManyArgumentObject::signal6, &ob, &ManyArgumentObject::signal5);
4832     connect(&ob, &ManyArgumentObject::signal5, &ob, &ManyArgumentObject::signal4);
4833     connect(&ob, &ManyArgumentObject::signal4, &ob, &ManyArgumentObject::signal3);
4834     connect(&ob, &ManyArgumentObject::signal3, &ob, &ManyArgumentObject::signal2);
4835     connect(&ob, &ManyArgumentObject::signal2, &ob, &ManyArgumentObject::signal1);
4836
4837     emit ob.signal6("a", "b", "c", "d", "e", "f");
4838     QCOMPARE(ob.count, 6);
4839     QCOMPARE(ManyArgumentNamespace::count, 6);
4840
4841
4842     ManyArgumentObject ob2;
4843     ob2.count = 0;
4844     ManyArgumentNamespace::count = 0;
4845     connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot1);
4846     connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot2);
4847     connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot3);
4848     connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot4);
4849     connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot5);
4850     connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot6);
4851     connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot1);
4852     connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot2);
4853     connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot3);
4854     connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot4);
4855     connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot5);
4856     connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot6);
4857
4858     emit ob2.signal6("a", "b", "c", "d", "e", "f");
4859     QCOMPARE(ob2.count, 6);
4860     QCOMPARE(ManyArgumentNamespace::count, 6);
4861 }
4862
4863 class ReturnValue : public QObject {
4864 friend class tst_QObject;
4865 Q_OBJECT
4866 signals:
4867     QVariant returnVariant(int);
4868     QString returnString(int);
4869     int returnInt(int);
4870     void returnVoid(int);
4871     CustomType returnCustomType(int);
4872 public slots:
4873     QVariant returnVariantSlot(int i) { return i; }
4874     QString returnStringSlot(int i) { return QString::number(i); }
4875     int returnIntSlot(int i) { return i; }
4876     CustomType returnCustomTypeSlot(int i) { return CustomType(i); }
4877     void returnVoidSlot() {}
4878     int return23() { return 23; }
4879     QString returnHello() { return QStringLiteral("hello"); }
4880 public:
4881     struct VariantFunctor {
4882         QVariant operator()(int i) { return i; }
4883     };
4884     struct CustomTypeFunctor {
4885         CustomType operator()(int i) { return CustomType(i); }
4886     };
4887     struct StringFunctor {
4888         QString operator()(int i) { return QString::number(i); }
4889     };
4890     struct IntFunctor {
4891         int operator()(int i) { return i; }
4892     };
4893     struct VoidFunctor {
4894         void operator()(int) {}
4895     };
4896 };
4897
4898 QString someFunctionReturningString(int i) {
4899     return '\'' + QString::number(i) + '\'';
4900 }
4901
4902 void tst_QObject::returnValue_data()
4903 {
4904     QTest::addColumn<bool>("isBlockingQueued");
4905
4906     QTest::newRow("DirectConnection") << false;
4907     QTest::newRow("BlockingQueuedConnection") << true;
4908 }
4909
4910 void tst_QObject::returnValue()
4911 {
4912     CheckInstanceCount checker;
4913
4914     QFETCH(bool, isBlockingQueued);
4915     QThread thread;
4916     ReturnValue receiver;
4917     Qt::ConnectionType type = Qt::DirectConnection;
4918     if (isBlockingQueued) {
4919         thread.start();
4920         receiver.moveToThread(&thread);
4921         type = Qt::BlockingQueuedConnection;
4922     }
4923
4924     { // connected to nothing
4925         CheckInstanceCount checker;
4926         ReturnValue r;
4927         QCOMPARE(emit r.returnVariant(45), QVariant());
4928         QCOMPARE(emit r.returnString(45), QString());
4929         QCOMPARE(emit r.returnInt(45), int());
4930         emit r.returnVoid(45);
4931         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
4932     }
4933     { // connected to a slot returning the same type
4934         CheckInstanceCount checker;
4935         ReturnValue r;
4936         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type));
4937         QCOMPARE(emit r.returnVariant(45), QVariant(45));
4938         QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, type));
4939         QCOMPARE(emit r.returnString(45), QString::fromLatin1("45"));
4940         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type));
4941         QCOMPARE(emit r.returnInt(45), int(45));
4942         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, type));
4943         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
4944     }
4945     if (!isBlockingQueued) { // connected to simple functions or functor
4946         CheckInstanceCount checker;
4947         ReturnValue r;
4948         QVERIFY(connect(&r, &ReturnValue::returnString, someFunctionReturningString));
4949         QCOMPARE(emit r.returnString(49), QString::fromLatin1("'49'"));
4950
4951         ReturnValue::CustomTypeFunctor customTypeFunctor;
4952         QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor));
4953         QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value());
4954
4955         ReturnValue::VariantFunctor variantFunctor;
4956         QVERIFY(connect(&r, &ReturnValue::returnVariant, variantFunctor));
4957         QCOMPARE(emit r.returnVariant(45), QVariant(45));
4958
4959         ReturnValue::IntFunctor intFunctor;
4960         QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
4961         QCOMPARE(emit r.returnInt(45), int(45));
4962     }
4963     { // connected to a slot with different type
4964         CheckInstanceCount checker;
4965         ReturnValue r;
4966         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, type));
4967         QCOMPARE(emit r.returnVariant(48), QVariant(QString::fromLatin1("48")));
4968         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, type));
4969         QCOMPARE((emit r.returnCustomType(48)).value(), CustomType(48).value());
4970         QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, type));
4971         emit r.returnVoid(48);
4972     }
4973     if (!isBlockingQueued) { // connected to functor with different type
4974         CheckInstanceCount checker;
4975         ReturnValue r;
4976
4977         ReturnValue::CustomTypeFunctor customTypeFunctor;
4978         QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor));
4979         QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value());
4980
4981         ReturnValue::StringFunctor stringFunctor;
4982         QVERIFY(connect(&r, &ReturnValue::returnVariant, stringFunctor));
4983         QCOMPARE(emit r.returnVariant(45), QVariant(QString::fromLatin1("45")));
4984     }
4985     { // connected to a void
4986         CheckInstanceCount checker;
4987         ReturnValue r;
4988         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type));
4989         QCOMPARE(emit r.returnVariant(45), QVariant());
4990         QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnVoidSlot, type));
4991         QCOMPARE(emit r.returnString(45), QString());
4992         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type));
4993         QCOMPARE(emit r.returnInt(45), int());
4994         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnVoidSlot, type));
4995         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
4996     }
4997     if (!isBlockingQueued) {
4998         // queued connection should not forward the return value
4999         CheckInstanceCount checker;
5000         ReturnValue r;
5001         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, Qt::QueuedConnection));
5002         QCOMPARE(emit r.returnVariant(45), QVariant());
5003         QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection));
5004         QCOMPARE(emit r.returnString(45), QString());
5005         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection));
5006         QCOMPARE(emit r.returnInt(45), int());
5007         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection));
5008         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5009         QCoreApplication::processEvents();
5010
5011         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection));
5012         QCOMPARE(emit r.returnVariant(48), QVariant());
5013         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection));
5014         QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
5015         QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection));
5016         emit r.returnVoid(48);
5017         QCoreApplication::processEvents();
5018     }
5019
5020     { // connected to many slots
5021         ReturnValue::VoidFunctor voidFunctor;
5022         ReturnValue::IntFunctor intFunctor;
5023         ReturnValue r;
5024         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type));
5025         QCOMPARE(emit r.returnVariant(45), QVariant(45));
5026         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, type));
5027         QCOMPARE(emit r.returnVariant(45), QVariant(23));
5028         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type));
5029         QCOMPARE(emit r.returnVariant(45), QVariant(23));
5030         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnHello, type));
5031         QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
5032         QVERIFY(connect(&r, &ReturnValue::returnVariant, voidFunctor));
5033         QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
5034         QVERIFY(connect(&r, &ReturnValue::returnVariant, intFunctor));
5035         QCOMPARE(emit r.returnVariant(45), QVariant(45));
5036         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, Qt::QueuedConnection));
5037         QCOMPARE(emit r.returnVariant(45), QVariant(45));
5038
5039         QCOMPARE(emit r.returnInt(45), int());
5040         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type));
5041         QCOMPARE(emit r.returnInt(45), int());
5042         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type));
5043         QCOMPARE(emit r.returnInt(45), int(45));
5044         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, type));
5045         QCOMPARE(emit r.returnInt(45), int(23));
5046         QVERIFY(connect(&r, &ReturnValue::returnInt, voidFunctor));
5047         QCOMPARE(emit r.returnInt(45), int(23));
5048         QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
5049         QCOMPARE(emit r.returnInt(45), int(45));
5050         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, Qt::QueuedConnection));
5051         QCOMPARE(emit r.returnInt(45), int(45));
5052
5053         QCoreApplication::processEvents();
5054     }
5055
5056     if (isBlockingQueued) {
5057         thread.quit();
5058         thread.wait();
5059     }
5060 }
5061
5062 void tst_QObject::returnValue2_data()
5063 { returnValue_data(); }
5064
5065 //String based syntax
5066 void tst_QObject::returnValue2()
5067 {
5068     CheckInstanceCount checker;
5069
5070     QFETCH(bool, isBlockingQueued);
5071     QThread thread;
5072     ReturnValue receiver;
5073     Qt::ConnectionType type = Qt::DirectConnection;
5074     if (isBlockingQueued) {
5075         thread.start();
5076         receiver.moveToThread(&thread);
5077         type = Qt::BlockingQueuedConnection;
5078     }
5079
5080     { // connected to a simple slot
5081         CheckInstanceCount checker;
5082         ReturnValue r;
5083         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), type));
5084         QCOMPARE(emit r.returnVariant(45), QVariant(45));
5085         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
5086         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5087         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
5088         QCOMPARE(emit r.returnInt(45), int(45));
5089         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), type));
5090         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
5091     }
5092     { // connected to a slot returning void
5093         CheckInstanceCount checker;
5094         ReturnValue r;
5095         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVoidSlot()), type));
5096         QCOMPARE(emit r.returnVariant(45), QVariant());
5097         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type));
5098         QCOMPARE(emit r.returnString(45), QString());
5099         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type));
5100         QCOMPARE(emit r.returnInt(45), int());
5101         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type));
5102         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5103     }
5104     if (!isBlockingQueued) {
5105         // queued connection should not forward the return value
5106         CheckInstanceCount checker;
5107         ReturnValue r;
5108         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), Qt::QueuedConnection));
5109         QCOMPARE(emit r.returnVariant(45), QVariant());
5110         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5111         QCOMPARE(emit r.returnString(45), QString());
5112         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5113         QCOMPARE(emit r.returnInt(45), int());
5114         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
5115         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5116         QCoreApplication::processEvents();
5117
5118         //Queued conneciton with different return type should be safe
5119         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5120         QCOMPARE(emit r.returnVariant(48), QVariant());
5121         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5122         QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
5123         QVERIFY(connect(&r, SIGNAL(returnVoid(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
5124         emit r.returnVoid(48);
5125         QCoreApplication::processEvents();
5126     }
5127     { // connected to many slots
5128         ReturnValue r;
5129         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
5130         QCOMPARE(emit r.returnInt(45), int(45));
5131         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type));
5132         QCOMPARE(emit r.returnInt(45), int(45));
5133         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(return23()), type));
5134         QCOMPARE(emit r.returnInt(45), int(23));
5135         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5136         QCOMPARE(emit r.returnInt(45), int(23));
5137
5138         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
5139         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5140         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type));
5141         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5142         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnHello()), type));
5143         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
5144         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5145         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
5146     }
5147     if (isBlockingQueued) {
5148         thread.quit();
5149         thread.wait();
5150     }
5151 }
5152
5153
5154 QTEST_MAIN(tst_QObject)
5155 #include "tst_qobject.moc"