tests/auto/qobject/tst_qobject.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #define QT3_SUPPORT
       
    44 #include <QtTest/QtTest>
       
    45 
       
    46 
       
    47 #include <qcoreapplication.h>
       
    48 
       
    49 #include <qpointer.h>
       
    50 #include <qtimer.h>
       
    51 #include <qregexp.h>
       
    52 #include <qmetaobject.h>
       
    53 #include <qvariant.h>
       
    54 
       
    55 #include <QTcpServer>
       
    56 #include <QTcpSocket>
       
    57 #include <QThread>
       
    58 #include <QMutex>
       
    59 #include <QWaitCondition>
       
    60 #include <QProcess>
       
    61 
       
    62 #include "qobject.h"
       
    63 
       
    64 #include <math.h>
       
    65 
       
    66 //TESTED_CLASS=
       
    67 //TESTED_FILES=
       
    68 
       
    69 class tst_QObject : public QObject
       
    70 {
       
    71     Q_OBJECT
       
    72 
       
    73 public:
       
    74     tst_QObject();
       
    75     virtual ~tst_QObject();
       
    76 
       
    77 
       
    78 public slots:
       
    79     void initTestCase();
       
    80     void cleanupTestCase();
       
    81     void init();
       
    82     void cleanup();
       
    83 private slots:
       
    84     void disconnect();
       
    85     void connectByName();
       
    86     void connectSignalsToSignalsWithDefaultArguments();
       
    87     void receivers();
       
    88     void normalize();
       
    89     void qobject_castTemplate();
       
    90     void findChildren();
       
    91     void connectDisconnectNotify_data();
       
    92     void connectDisconnectNotify();
       
    93     void emitInDefinedOrder();
       
    94     void customTypes();
       
    95     void streamCustomTypes();
       
    96     void metamethod();
       
    97     void namespaces();
       
    98     void threadSignalEmissionCrash();
       
    99     void thread();
       
   100     void thread0();
       
   101     void moveToThread();
       
   102     void sender();
       
   103     void declareInterface();
       
   104     void qpointerResetBeforeDestroyedSignal();
       
   105     void testUserData();
       
   106     void childDeletesItsSibling();
       
   107     void dynamicProperties();
       
   108     void floatProperty();
       
   109     void qrealProperty();
       
   110     void property();
       
   111     void recursiveSignalEmission();
       
   112     void blockingQueuedConnection();
       
   113     void compatibilityChildInsertedEvents();
       
   114     void installEventFilter();
       
   115     void deleteSelfInSlot();
       
   116     void disconnectSelfInSlotAndDeleteAfterEmit();
       
   117     void dumpObjectInfo();
       
   118     void connectToSender();
       
   119     void qobjectConstCast();
       
   120     void uniqConnection();
       
   121     void interfaceIid();
       
   122     void deleteQObjectWhenDeletingEvent();
       
   123     void overloads();
       
   124 protected:
       
   125 };
       
   126 
       
   127 tst_QObject::tst_QObject()
       
   128 {
       
   129 
       
   130 }
       
   131 
       
   132 tst_QObject::~tst_QObject()
       
   133 {
       
   134 
       
   135 }
       
   136 
       
   137 void tst_QObject::initTestCase()
       
   138 {
       
   139 }
       
   140 
       
   141 void tst_QObject::cleanupTestCase()
       
   142 {
       
   143 }
       
   144 
       
   145 void tst_QObject::init()
       
   146 {
       
   147 }
       
   148 
       
   149 void tst_QObject::cleanup()
       
   150 {
       
   151 }
       
   152 
       
   153 class SenderObject : public QObject
       
   154 {
       
   155     Q_OBJECT
       
   156 
       
   157 public:
       
   158     SenderObject() : recursionCount(0) {}
       
   159 
       
   160     void emitSignal1AfterRecursion()
       
   161     {
       
   162         if (recursionCount++ < 100)
       
   163             emitSignal1AfterRecursion();
       
   164         else
       
   165             emitSignal1();
       
   166     }
       
   167 
       
   168     void emitSignal1() { emit signal1(); }
       
   169     void emitSignal2() { emit signal2(); }
       
   170     void emitSignal3() { emit signal3(); }
       
   171     void emitSignal4() { emit signal4(); }
       
   172 
       
   173 signals:
       
   174     void signal1();
       
   175     void signal2();
       
   176     void signal3();
       
   177     void signal4();
       
   178     QT_MOC_COMPAT void signal5();
       
   179 
       
   180 public slots:
       
   181     void aPublicSlot(){}
       
   182 
       
   183 public:
       
   184     Q_INVOKABLE void invoke1(){}
       
   185     Q_SCRIPTABLE void sinvoke1(){}
       
   186 protected:
       
   187     Q_INVOKABLE QT_MOC_COMPAT void invoke2(){}
       
   188     Q_INVOKABLE QT_MOC_COMPAT void invoke2(int){}
       
   189     Q_SCRIPTABLE QT_MOC_COMPAT void sinvoke2(){}
       
   190 private:
       
   191     Q_INVOKABLE void invoke3(int hinz = 0, int kunz = 0){Q_UNUSED(hinz) Q_UNUSED(kunz)}
       
   192     Q_SCRIPTABLE void sinvoke3(){}
       
   193 
       
   194     int recursionCount;
       
   195 };
       
   196 
       
   197 class ReceiverObject : public QObject
       
   198 {
       
   199     Q_OBJECT
       
   200 
       
   201 public:
       
   202     ReceiverObject() : sequence_slot1( 0 ),
       
   203 		       sequence_slot2( 0 ),
       
   204 		       sequence_slot3( 0 ),
       
   205 		       sequence_slot4( 0 ) {}
       
   206 
       
   207     void reset() {
       
   208 	sequence_slot4 = 0;
       
   209 	sequence_slot3 = 0;
       
   210 	sequence_slot2 = 0;
       
   211 	sequence_slot1 = 0;
       
   212         count_slot1 = 0;
       
   213         count_slot2 = 0;
       
   214         count_slot3 = 0;
       
   215         count_slot4 = 0;
       
   216     }
       
   217 
       
   218     int sequence_slot1;
       
   219     int sequence_slot2;
       
   220     int sequence_slot3;
       
   221     int sequence_slot4;
       
   222     int count_slot1;
       
   223     int count_slot2;
       
   224     int count_slot3;
       
   225     int count_slot4;
       
   226 
       
   227     bool called(int slot) {
       
   228         switch (slot) {
       
   229         case 1: return sequence_slot1;
       
   230         case 2: return sequence_slot2;
       
   231         case 3: return sequence_slot3;
       
   232         case 4: return sequence_slot4;
       
   233         default: return false;
       
   234         }
       
   235     }
       
   236 
       
   237     static int sequence;
       
   238 
       
   239 public slots:
       
   240     void slot1() { sequence_slot1 = ++sequence; count_slot1++; }
       
   241     void slot2() { sequence_slot2 = ++sequence; count_slot2++; }
       
   242     void slot3() { sequence_slot3 = ++sequence; count_slot3++; }
       
   243     void slot4() { sequence_slot4 = ++sequence; count_slot4++; }
       
   244 
       
   245 };
       
   246 
       
   247 int ReceiverObject::sequence = 0;
       
   248 
       
   249 void tst_QObject::disconnect()
       
   250 {
       
   251     SenderObject *s = new SenderObject;
       
   252     ReceiverObject *r1 = new ReceiverObject;
       
   253     ReceiverObject *r2 = new ReceiverObject;
       
   254 
       
   255     connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
       
   256 
       
   257     connect( s, SIGNAL( signal2() ), r1, SLOT( slot2() ) );
       
   258     connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) );
       
   259     connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
       
   260 
       
   261     s->emitSignal1();
       
   262     s->emitSignal2();
       
   263     s->emitSignal3();
       
   264     s->emitSignal4();
       
   265 
       
   266     QCOMPARE( r1->called(1), TRUE );
       
   267     QCOMPARE( r1->called(2), TRUE );
       
   268     QCOMPARE( r1->called(3), TRUE );
       
   269     QCOMPARE( r1->called(4), TRUE );
       
   270     r1->reset();
       
   271 
       
   272     // usual disconnect with all parameters given
       
   273     bool ret = QObject::disconnect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
       
   274 
       
   275     s->emitSignal1();
       
   276 
       
   277     QCOMPARE( r1->called(1), FALSE );
       
   278     r1->reset();
       
   279 
       
   280     QCOMPARE( ret, TRUE );
       
   281     ret = QObject::disconnect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
       
   282     QCOMPARE( ret, FALSE  );
       
   283 
       
   284     // disconnect all signals from s from all slots from r1
       
   285     QObject::disconnect( s, 0, r1, 0 );
       
   286 
       
   287     s->emitSignal2();
       
   288     s->emitSignal3();
       
   289     s->emitSignal4();
       
   290 
       
   291     QCOMPARE( r1->called(2), FALSE );
       
   292     QCOMPARE( r1->called(3), FALSE );
       
   293     QCOMPARE( r1->called(4), FALSE );
       
   294     r1->reset();
       
   295 
       
   296     connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
       
   297     connect( s, SIGNAL( signal1() ), r1, SLOT( slot2() ) );
       
   298     connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) );
       
   299     connect( s, SIGNAL( signal2() ), r1, SLOT( slot4() ) );
       
   300 
       
   301     // disconnect s's signal1() from all slots of r1
       
   302     QObject::disconnect( s, SIGNAL( signal1() ), r1, 0 );
       
   303 
       
   304     s->emitSignal1();
       
   305     s->emitSignal2();
       
   306 
       
   307     QCOMPARE( r1->called(1), FALSE );
       
   308     QCOMPARE( r1->called(2), FALSE );
       
   309     QCOMPARE( r1->called(3), FALSE );
       
   310     QCOMPARE( r1->called(4), TRUE );
       
   311     r1->reset();
       
   312     // make sure all is disconnected again
       
   313     QObject::disconnect( s, 0, r1, 0 );
       
   314 
       
   315     connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
       
   316     connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) );
       
   317     connect( s, SIGNAL( signal2() ), r1, SLOT( slot2() ) );
       
   318     connect( s, SIGNAL( signal2() ), r2, SLOT( slot2() ) );
       
   319     connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) );
       
   320     connect( s, SIGNAL( signal3() ), r2, SLOT( slot3() ) );
       
   321 
       
   322     // disconnect signal1() from all receivers
       
   323     QObject::disconnect( s, SIGNAL( signal1() ), 0, 0 );
       
   324     s->emitSignal1();
       
   325     s->emitSignal2();
       
   326     s->emitSignal3();
       
   327 
       
   328     QCOMPARE( r1->called(1), FALSE );
       
   329     QCOMPARE( r2->called(1), FALSE );
       
   330     QCOMPARE( r1->called(2), TRUE );
       
   331     QCOMPARE( r2->called(2), TRUE );
       
   332     QCOMPARE( r1->called(2), TRUE );
       
   333     QCOMPARE( r2->called(2), TRUE );
       
   334 
       
   335     r1->reset();
       
   336     r2->reset();
       
   337 
       
   338     // disconnect all signals of s from all receivers
       
   339     QObject::disconnect( s, 0, 0, 0 );
       
   340 
       
   341     QCOMPARE( r1->called(2), FALSE );
       
   342     QCOMPARE( r2->called(2), FALSE );
       
   343     QCOMPARE( r1->called(2), FALSE );
       
   344     QCOMPARE( r2->called(2), FALSE );
       
   345 
       
   346     delete r2;
       
   347     delete r1;
       
   348     delete s;
       
   349 }
       
   350 
       
   351 class AutoConnectSender : public QObject
       
   352 {
       
   353     Q_OBJECT
       
   354 
       
   355 public:
       
   356     AutoConnectSender(QObject *parent)
       
   357         : QObject(parent)
       
   358     {}
       
   359 
       
   360     void emitSignalNoParams() { emit signalNoParams(); }
       
   361     void emitSignalWithParams(int i) { emit signalWithParams(i); }
       
   362     void emitSignalWithParams(int i, QString string) { emit signalWithParams(i, string); }
       
   363     void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams(i1, i2, i3, string, onoff); }
       
   364     void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams2(i1, i2, i3, string, onoff); }
       
   365     void emitSignalLoopBack() { emit signalLoopBack(); }
       
   366 
       
   367 signals:
       
   368     void signalNoParams();
       
   369     void signalWithParams(int i);
       
   370     void signalWithParams(int i, QString string);
       
   371     void signalManyParams(int i1, int i2, int i3, QString string, bool onoff);
       
   372     void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool);
       
   373     void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff);
       
   374     void signalLoopBack();
       
   375 };
       
   376 
       
   377 class AutoConnectReceiver : public QObject
       
   378 {
       
   379     Q_OBJECT
       
   380 
       
   381 public:
       
   382     AutoConnectReceiver()
       
   383     {
       
   384         reset();
       
   385 
       
   386         connect(this, SIGNAL(on_Sender_signalLoopBack()), this, SLOT(slotLoopBack()));
       
   387     }
       
   388 
       
   389     void reset() {
       
   390         called_slot8 = 0;
       
   391         called_slot7 = 0;
       
   392         called_slot6 = 0;
       
   393         called_slot5 = 0;
       
   394         called_slot4 = 0;
       
   395         called_slot3 = 0;
       
   396         called_slot2 = 0;
       
   397         called_slot1 = 0;
       
   398     }
       
   399 
       
   400     int called_slot1;
       
   401     int called_slot2;
       
   402     int called_slot3;
       
   403     int called_slot4;
       
   404     int called_slot5;
       
   405     int called_slot6;
       
   406     int called_slot7;
       
   407     int called_slot8;
       
   408 
       
   409     bool called(int slot) {
       
   410         switch (slot) {
       
   411         case 1: return called_slot1;
       
   412         case 2: return called_slot2;
       
   413         case 3: return called_slot3;
       
   414         case 4: return called_slot4;
       
   415         case 5: return called_slot5;
       
   416         case 6: return called_slot6;
       
   417         case 7: return called_slot7;
       
   418         case 8: return called_slot8;
       
   419         default: return false;
       
   420         }
       
   421     }
       
   422 
       
   423 public slots:
       
   424     void on_Sender_signalNoParams() { ++called_slot1; }
       
   425     void on_Sender_signalWithParams(int i = 0) { ++called_slot2; }
       
   426     void on_Sender_signalWithParams(int i, QString string) { ++called_slot3; }
       
   427     void on_Sender_signalManyParams() { ++called_slot4; }
       
   428     void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot5; }
       
   429     void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) { ++called_slot6; }
       
   430     void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot7; }
       
   431     void slotLoopBack() { ++called_slot8; }
       
   432 
       
   433 protected slots:
       
   434     void o() { Q_ASSERT(0); }
       
   435     void on() { Q_ASSERT(0); }
       
   436 
       
   437 signals:
       
   438     void on_Sender_signalLoopBack();
       
   439 };
       
   440 
       
   441 void tst_QObject::connectByName()
       
   442 {
       
   443     AutoConnectReceiver receiver;
       
   444     AutoConnectSender sender(&receiver);
       
   445     sender.setObjectName("Sender");
       
   446 
       
   447     QMetaObject::connectSlotsByName(&receiver);
       
   448 
       
   449     sender.emitSignalNoParams();
       
   450     QCOMPARE(receiver.called(1), true);
       
   451     QCOMPARE(receiver.called(2), false);
       
   452     QCOMPARE(receiver.called(3), false);
       
   453     QCOMPARE(receiver.called(4), false);
       
   454     QCOMPARE(receiver.called(5), false);
       
   455     QCOMPARE(receiver.called(6), false);
       
   456     QCOMPARE(receiver.called(7), false);
       
   457     QCOMPARE(receiver.called(8), false);
       
   458     receiver.reset();
       
   459 
       
   460     sender.emitSignalWithParams(0);
       
   461     QCOMPARE(receiver.called(1), false);
       
   462     QCOMPARE(receiver.called(2), true);
       
   463     QCOMPARE(receiver.called(3), false);
       
   464     QCOMPARE(receiver.called(4), false);
       
   465     QCOMPARE(receiver.called(5), false);
       
   466     QCOMPARE(receiver.called(6), false);
       
   467     QCOMPARE(receiver.called(7), false);
       
   468     QCOMPARE(receiver.called(8), false);
       
   469     receiver.reset();
       
   470 
       
   471     sender.emitSignalWithParams(0, "string");
       
   472     QCOMPARE(receiver.called(1), false);
       
   473     QCOMPARE(receiver.called(2), false);
       
   474     QCOMPARE(receiver.called(3), true);
       
   475     QCOMPARE(receiver.called(4), false);
       
   476     QCOMPARE(receiver.called(5), false);
       
   477     QCOMPARE(receiver.called(6), false);
       
   478     QCOMPARE(receiver.called(7), false);
       
   479     QCOMPARE(receiver.called(8), false);
       
   480     receiver.reset();
       
   481 
       
   482     sender.emitSignalManyParams(1, 2, 3, "string", true);
       
   483     QCOMPARE(receiver.called(1), false);
       
   484     QCOMPARE(receiver.called(2), false);
       
   485     QCOMPARE(receiver.called(3), false);
       
   486     QCOMPARE(receiver.called(4), true);
       
   487     QCOMPARE(receiver.called(5), true);
       
   488     QCOMPARE(receiver.called(6), false);
       
   489     QCOMPARE(receiver.called(7), false);
       
   490     QCOMPARE(receiver.called(8), false);
       
   491     receiver.reset();
       
   492 
       
   493     sender.emitSignalManyParams2(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), false);
       
   498     QCOMPARE(receiver.called(5), false);
       
   499     QCOMPARE(receiver.called(6), false);
       
   500     QCOMPARE(receiver.called(7), true);
       
   501     QCOMPARE(receiver.called(8), false);
       
   502     receiver.reset();
       
   503 
       
   504     sender.emitSignalLoopBack();
       
   505     QCOMPARE(receiver.called(1), false);
       
   506     QCOMPARE(receiver.called(2), false);
       
   507     QCOMPARE(receiver.called(3), false);
       
   508     QCOMPARE(receiver.called(4), false);
       
   509     QCOMPARE(receiver.called(5), false);
       
   510     QCOMPARE(receiver.called(6), false);
       
   511     QCOMPARE(receiver.called(7), false);
       
   512     QCOMPARE(receiver.called(8), true);
       
   513     receiver.reset();
       
   514 }
       
   515 
       
   516 void tst_QObject::qobject_castTemplate()
       
   517 {
       
   518     QObject *o = 0;
       
   519     QVERIFY( !::qobject_cast<QObject*>(o) );
       
   520 
       
   521     o = new SenderObject;
       
   522     QVERIFY( ::qobject_cast<SenderObject*>(o) );
       
   523     QVERIFY( ::qobject_cast<QObject*>(o) );
       
   524     QVERIFY( !::qobject_cast<ReceiverObject*>(o) );
       
   525     delete o;
       
   526 }
       
   527 
       
   528 void tst_QObject::findChildren()
       
   529 {
       
   530     QObject o;
       
   531     QObject o1(&o);
       
   532     QObject o2(&o);
       
   533     QObject o11(&o1);
       
   534     QObject o12(&o1);
       
   535     QObject o111(&o11);
       
   536     QObject unnamed(&o);
       
   537     QTimer t1(&o);
       
   538     QTimer t121(&o12);
       
   539     QTimer emptyname(&o);
       
   540 
       
   541     o.setObjectName("o");
       
   542     o1.setObjectName("o1");
       
   543     o2.setObjectName("o2");
       
   544     o11.setObjectName("o11");
       
   545     o12.setObjectName("o12");
       
   546     o111.setObjectName("o111");
       
   547     t1.setObjectName("t1");
       
   548     t121.setObjectName("t121");
       
   549     emptyname.setObjectName("");
       
   550 
       
   551     QObject *op = 0;
       
   552 
       
   553     op = qFindChild<QObject*>(&o, "o1");
       
   554     QCOMPARE(op, &o1);
       
   555     op = qFindChild<QObject*>(&o, "o2");
       
   556     QCOMPARE(op, &o2);
       
   557     op = qFindChild<QObject*>(&o, "o11");
       
   558     QCOMPARE(op, &o11);
       
   559     op = qFindChild<QObject*>(&o, "o12");
       
   560     QCOMPARE(op, &o12);
       
   561     op = qFindChild<QObject*>(&o, "o111");
       
   562     QCOMPARE(op, &o111);
       
   563     op = qFindChild<QObject*>(&o, "t1");
       
   564     QCOMPARE(op, static_cast<QObject *>(&t1));
       
   565     op = qFindChild<QObject*>(&o, "t121");
       
   566     QCOMPARE(op, static_cast<QObject *>(&t121));
       
   567     op = qFindChild<QTimer*>(&o, "t1");
       
   568     QCOMPARE(op, static_cast<QObject *>(&t1));
       
   569     op = qFindChild<QTimer*>(&o, "t121");
       
   570     QCOMPARE(op, static_cast<QObject *>(&t121));
       
   571     op = qFindChild<QTimer*>(&o, "o12");
       
   572     QCOMPARE(op, static_cast<QObject *>(0));
       
   573     op = qFindChild<QObject*>(&o, "o");
       
   574     QCOMPARE(op, static_cast<QObject *>(0));
       
   575     op = qFindChild<QObject*>(&o, "harry");
       
   576     QCOMPARE(op, static_cast<QObject *>(0));
       
   577     op = qFindChild<QObject*>(&o, "o1");
       
   578     QCOMPARE(op, &o1);
       
   579 
       
   580     QList<QObject*> l;
       
   581     QList<QTimer*> tl;
       
   582 
       
   583     l = qFindChildren<QObject*>(&o, "o1");
       
   584     QCOMPARE(l.size(), 1);
       
   585     QCOMPARE(l.at(0), &o1);
       
   586     l = qFindChildren<QObject*>(&o, "o2");
       
   587     QCOMPARE(l.size(), 1);
       
   588     QCOMPARE(l.at(0), &o2);
       
   589     l = qFindChildren<QObject*>(&o, "o11");
       
   590     QCOMPARE(l.size(), 1);
       
   591     QCOMPARE(l.at(0), &o11);
       
   592     l = qFindChildren<QObject*>(&o, "o12");
       
   593     QCOMPARE(l.size(), 1);
       
   594     QCOMPARE(l.at(0), &o12);
       
   595     l = qFindChildren<QObject*>(&o, "o111");
       
   596     QCOMPARE(l.size(), 1);
       
   597     QCOMPARE(l.at(0), &o111);
       
   598     l = qFindChildren<QObject*>(&o, "t1");
       
   599     QCOMPARE(l.size(), 1);
       
   600     QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
       
   601     l = qFindChildren<QObject*>(&o, "t121");
       
   602     QCOMPARE(l.size(), 1);
       
   603     QCOMPARE(l.at(0), static_cast<QObject *>(&t121));
       
   604     tl = qFindChildren<QTimer*>(&o, "t1");
       
   605     QCOMPARE(tl.size(), 1);
       
   606     QCOMPARE(tl.at(0), &t1);
       
   607     tl = qFindChildren<QTimer*>(&o, "t121");
       
   608     QCOMPARE(tl.size(), 1);
       
   609     QCOMPARE(tl.at(0), &t121);
       
   610     l = qFindChildren<QObject*>(&o, "o");
       
   611     QCOMPARE(l.size(), 0);
       
   612     l = qFindChildren<QObject*>(&o, "harry");
       
   613     QCOMPARE(l.size(), 0);
       
   614     tl = qFindChildren<QTimer*>(&o, "o12");
       
   615     QCOMPARE(tl.size(), 0);
       
   616     l = qFindChildren<QObject*>(&o, "o1");
       
   617     QCOMPARE(l.size(), 1);
       
   618     QCOMPARE(l.at(0), &o1);
       
   619 
       
   620     l = qFindChildren<QObject*>(&o, QRegExp("o.*"));
       
   621     QCOMPARE(l.size(), 5);
       
   622     QVERIFY(l.contains(&o1));
       
   623     QVERIFY(l.contains(&o2));
       
   624     QVERIFY(l.contains(&o11));
       
   625     QVERIFY(l.contains(&o12));
       
   626     QVERIFY(l.contains(&o111));
       
   627     l = qFindChildren<QObject*>(&o, QRegExp("t.*"));
       
   628     QCOMPARE(l.size(), 2);
       
   629     QVERIFY(l.contains(&t1));
       
   630     QVERIFY(l.contains(&t121));
       
   631     tl = qFindChildren<QTimer*>(&o, QRegExp(".*"));
       
   632     QCOMPARE(tl.size(), 3);
       
   633     QVERIFY(tl.contains(&t1));
       
   634     QVERIFY(tl.contains(&t121));
       
   635     tl = qFindChildren<QTimer*>(&o, QRegExp("o.*"));
       
   636     QCOMPARE(tl.size(), 0);
       
   637     l = qFindChildren<QObject*>(&o, QRegExp("harry"));
       
   638     QCOMPARE(l.size(), 0);
       
   639 
       
   640     // empty and null string check
       
   641     op = qFindChild<QObject*>(&o);
       
   642     QCOMPARE(op, &o1);
       
   643     op = qFindChild<QObject*>(&o, "");
       
   644     QCOMPARE(op, &unnamed);
       
   645     op = qFindChild<QObject*>(&o, "unnamed");
       
   646     QCOMPARE(op, static_cast<QObject *>(0));
       
   647 
       
   648     l = qFindChildren<QObject*>(&o);
       
   649     QCOMPARE(l.size(), 9);
       
   650     l = qFindChildren<QObject*>(&o, "");
       
   651     QCOMPARE(l.size(), 2);
       
   652     l = qFindChildren<QObject*>(&o, "unnamed");
       
   653     QCOMPARE(l.size(), 0);
       
   654 
       
   655 #ifndef QT_NO_MEMBER_TEMPLATES
       
   656     tl = o.findChildren<QTimer *>("t1");
       
   657     QCOMPARE(tl.size(), 1);
       
   658     QCOMPARE(tl.at(0), &t1);
       
   659 #endif
       
   660 }
       
   661 
       
   662 
       
   663 class NotifyObject : public SenderObject, public ReceiverObject
       
   664 {
       
   665 public:
       
   666     NotifyObject() : SenderObject(), ReceiverObject()
       
   667     {}
       
   668 
       
   669     QString org_signal;
       
   670     QString nw_signal;
       
   671 
       
   672 protected:
       
   673     void connectNotify( const char *signal )
       
   674     {
       
   675     	org_signal = signal;
       
   676     	nw_signal = QMetaObject::normalizedSignature(signal);
       
   677     };
       
   678     void disconnectNotify( const char *signal )
       
   679     {
       
   680     	org_signal = signal;
       
   681     	nw_signal = QMetaObject::normalizedSignature(signal);
       
   682     };
       
   683 };
       
   684 
       
   685 void tst_QObject::connectDisconnectNotify_data()
       
   686 {
       
   687     QTest::addColumn<QString>("a_signal");
       
   688     QTest::addColumn<QString>("a_slot");
       
   689 
       
   690     QTest::newRow("combo1") << SIGNAL( signal1() )        << SLOT( slot1() );
       
   691     QTest::newRow("combo2") << SIGNAL( signal2(void) )    << SLOT( slot2(  ) );
       
   692     QTest::newRow("combo3") << SIGNAL( signal3(  ) )      << SLOT( slot3(void) );
       
   693     QTest::newRow("combo4") << SIGNAL(  signal4( void )  )<< SLOT(  slot4( void )  );
       
   694 }
       
   695 
       
   696 void tst_QObject::connectDisconnectNotify()
       
   697 {
       
   698     NotifyObject *s = new NotifyObject;
       
   699     NotifyObject *r = new NotifyObject;
       
   700 
       
   701     QFETCH(QString, a_signal);
       
   702     QFETCH(QString, a_slot);
       
   703 
       
   704     // Test connectNotify
       
   705     connect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
       
   706     QCOMPARE( s->org_signal, s->nw_signal );
       
   707     QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
       
   708 
       
   709     // Test disconnectNotify
       
   710     QObject::disconnect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
       
   711     QCOMPARE( s->org_signal, s->nw_signal );
       
   712     QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
       
   713 
       
   714     // Reconnect
       
   715     connect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
       
   716     // Test disconnectNotify for a complete disconnect
       
   717     ((SenderObject*)s)->disconnect((ReceiverObject*)r);
       
   718 
       
   719     delete s;
       
   720     delete r;
       
   721 }
       
   722 
       
   723 class SequenceObject : public ReceiverObject
       
   724 {
       
   725     Q_OBJECT
       
   726 
       
   727 public:
       
   728     QObject *next;
       
   729     SequenceObject() : next(0) { }
       
   730 
       
   731 public slots:
       
   732     void slot1_disconnectThis()
       
   733     {
       
   734         slot1();
       
   735         disconnect(sender(), SIGNAL(signal1()), this, SLOT(slot1_disconnectThis()));
       
   736     }
       
   737 
       
   738     void slot2_reconnectThis()
       
   739     {
       
   740         slot2();
       
   741 
       
   742         const QObject *s = sender();
       
   743         disconnect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
       
   744         connect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
       
   745     }
       
   746 
       
   747     void slot1_disconnectNext()
       
   748     {
       
   749         slot1();
       
   750         disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot1()));
       
   751     }
       
   752 
       
   753     void slot2_reconnectNext()
       
   754     {
       
   755         slot2();
       
   756 
       
   757         // modify the connection list in 'this'
       
   758         disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
       
   759         connect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
       
   760 
       
   761         // modify the sender list in 'this'
       
   762         connect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
       
   763         connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
       
   764         disconnect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
       
   765         disconnect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
       
   766     }
       
   767 
       
   768     void slot1_deleteNext()
       
   769     {
       
   770         slot1();
       
   771         delete next;
       
   772     }
       
   773 
       
   774     void slot2_deleteSender()
       
   775     {
       
   776         slot2();
       
   777         delete sender();
       
   778     }
       
   779 };
       
   780 
       
   781 void tst_QObject::emitInDefinedOrder()
       
   782 {
       
   783     SenderObject sender;
       
   784     ReceiverObject receiver1, receiver2, receiver3, receiver4;
       
   785 
       
   786     connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
       
   787     connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
       
   788     connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot1()));
       
   789     connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot1()));
       
   790     connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot2()));
       
   791     connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot2()));
       
   792     connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot2()));
       
   793     connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot2()));
       
   794 
       
   795     int sequence;
       
   796     ReceiverObject::sequence = sequence = 0;
       
   797     sender.emitSignal1();
       
   798     QCOMPARE(receiver1.sequence_slot1, ++sequence);
       
   799     QCOMPARE(receiver2.sequence_slot1, ++sequence);
       
   800     QCOMPARE(receiver3.sequence_slot1, ++sequence);
       
   801     QCOMPARE(receiver4.sequence_slot1, ++sequence);
       
   802     QCOMPARE(receiver1.sequence_slot2, ++sequence);
       
   803     QCOMPARE(receiver2.sequence_slot2, ++sequence);
       
   804     QCOMPARE(receiver3.sequence_slot2, ++sequence);
       
   805     QCOMPARE(receiver4.sequence_slot2, ++sequence);
       
   806 
       
   807     QObject::disconnect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
       
   808     connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
       
   809 
       
   810     ReceiverObject::sequence = sequence =  0;
       
   811     sender.emitSignal1();
       
   812     QCOMPARE(receiver1.sequence_slot1, ++sequence);
       
   813     QCOMPARE(receiver3.sequence_slot1, ++sequence);
       
   814     QCOMPARE(receiver4.sequence_slot1, ++sequence);
       
   815     QCOMPARE(receiver1.sequence_slot2, ++sequence);
       
   816     QCOMPARE(receiver2.sequence_slot2, ++sequence);
       
   817     QCOMPARE(receiver3.sequence_slot2, ++sequence);
       
   818     QCOMPARE(receiver4.sequence_slot2, ++sequence);
       
   819     QCOMPARE(receiver2.sequence_slot1, ++sequence);
       
   820 
       
   821     QObject::disconnect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
       
   822     connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
       
   823 
       
   824     ReceiverObject::sequence = sequence =  0;
       
   825     sender.emitSignal1();
       
   826     QCOMPARE(receiver3.sequence_slot1, ++sequence);
       
   827     QCOMPARE(receiver4.sequence_slot1, ++sequence);
       
   828     QCOMPARE(receiver1.sequence_slot2, ++sequence);
       
   829     QCOMPARE(receiver2.sequence_slot2, ++sequence);
       
   830     QCOMPARE(receiver3.sequence_slot2, ++sequence);
       
   831     QCOMPARE(receiver4.sequence_slot2, ++sequence);
       
   832     QCOMPARE(receiver2.sequence_slot1, ++sequence);
       
   833     QCOMPARE(receiver1.sequence_slot1, ++sequence);
       
   834 
       
   835     // ensure emission order even if the connections change during emission
       
   836     SenderObject *sender2 = new SenderObject;
       
   837     SequenceObject seq1, seq2, *seq3 = new SequenceObject, seq4;
       
   838     seq1.next = &seq2;
       
   839     seq2.next = seq3;
       
   840     seq3->next = &seq4;
       
   841 
       
   842     // try 1
       
   843     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
       
   844     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
       
   845     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
       
   846     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
       
   847     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
       
   848     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
       
   849     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
       
   850     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
       
   851 
       
   852     SequenceObject::sequence = sequence = 0;
       
   853     sender2->emitSignal1();
       
   854     QCOMPARE(seq1.called(1), TRUE);
       
   855     QCOMPARE(seq2.called(1), TRUE);
       
   856     QCOMPARE(seq3->called(1), FALSE);
       
   857     QCOMPARE(seq4.called(1), TRUE);
       
   858     QCOMPARE(seq1.called(2), TRUE);
       
   859     QCOMPARE(seq2.called(2), TRUE);
       
   860     QCOMPARE(seq3->called(2), FALSE);
       
   861     QCOMPARE(seq4.called(2), TRUE);
       
   862     QCOMPARE(seq1.sequence_slot1, ++sequence);
       
   863     QCOMPARE(seq2.sequence_slot1, ++sequence);
       
   864     QCOMPARE(seq4.sequence_slot1, ++sequence);
       
   865     QCOMPARE(seq1.sequence_slot2, ++sequence);
       
   866     QCOMPARE(seq2.sequence_slot2, ++sequence);
       
   867     QCOMPARE(seq4.sequence_slot2, ++sequence);
       
   868 
       
   869     QObject::disconnect(sender2, 0, &seq1, 0);
       
   870     QObject::disconnect(sender2, 0, &seq2, 0);
       
   871     QObject::disconnect(sender2, 0, seq3, 0);
       
   872     QObject::disconnect(sender2, 0, &seq4, 0);
       
   873     seq1.reset();
       
   874     seq2.reset();
       
   875     seq3->reset();
       
   876     seq4.reset();
       
   877 
       
   878     // try 2
       
   879     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
       
   880     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
       
   881     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
       
   882     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
       
   883     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
       
   884     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
       
   885     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
       
   886     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
       
   887 
       
   888     SequenceObject::sequence = sequence = 0;
       
   889     sender2->emitSignal1();
       
   890     QCOMPARE(seq1.called(2), TRUE);
       
   891     QCOMPARE(seq2.called(2), TRUE);
       
   892     QCOMPARE(seq3->called(2), FALSE);
       
   893     QCOMPARE(seq4.called(2), TRUE);
       
   894     QCOMPARE(seq1.called(1), TRUE);
       
   895     QCOMPARE(seq2.called(1), TRUE);
       
   896     QCOMPARE(seq3->called(1), FALSE);
       
   897     QCOMPARE(seq4.called(1), TRUE);
       
   898     QCOMPARE(seq1.sequence_slot2, ++sequence);
       
   899     QCOMPARE(seq2.sequence_slot2, ++sequence);
       
   900     QCOMPARE(seq4.sequence_slot2, ++sequence);
       
   901     QCOMPARE(seq1.sequence_slot1, ++sequence);
       
   902     QCOMPARE(seq2.sequence_slot1, ++sequence);
       
   903     QCOMPARE(seq4.sequence_slot1, ++sequence);
       
   904 
       
   905     QObject::disconnect(sender2, 0, &seq1, 0);
       
   906     QObject::disconnect(sender2, 0, &seq2, 0);
       
   907     QObject::disconnect(sender2, 0, seq3, 0);
       
   908     QObject::disconnect(sender2, 0, &seq4, 0);
       
   909     seq1.reset();
       
   910     seq2.reset();
       
   911     seq3->reset();
       
   912     seq4.reset();
       
   913 
       
   914     // try 3
       
   915     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
       
   916     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
       
   917     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
       
   918     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
       
   919     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
       
   920     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
       
   921     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
       
   922     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
       
   923 
       
   924     SequenceObject::sequence = sequence = 0;
       
   925     sender2->emitSignal1();
       
   926     QCOMPARE(seq1.called(1), TRUE);
       
   927     QCOMPARE(seq2.called(1), TRUE);
       
   928     QCOMPARE(seq3->called(1), FALSE);
       
   929     QCOMPARE(seq4.called(1), TRUE);
       
   930     QCOMPARE(seq1.called(2), TRUE);
       
   931     QCOMPARE(seq2.called(2), TRUE);
       
   932     QCOMPARE(seq3->called(2), FALSE);
       
   933     QCOMPARE(seq4.called(2), TRUE);
       
   934     QCOMPARE(seq1.sequence_slot1, ++sequence);
       
   935     QCOMPARE(seq2.sequence_slot1, ++sequence);
       
   936     QCOMPARE(seq4.sequence_slot1, ++sequence);
       
   937     QCOMPARE(seq1.sequence_slot2, ++sequence);
       
   938     QCOMPARE(seq2.sequence_slot2, ++sequence);
       
   939     QCOMPARE(seq4.sequence_slot2, ++sequence);
       
   940 
       
   941     // ensure emission order even if objects are destroyed during emission
       
   942     QObject::disconnect(sender2, 0, &seq1, 0);
       
   943     QObject::disconnect(sender2, 0, &seq2, 0);
       
   944     QObject::disconnect(sender2, 0, seq3, 0);
       
   945     QObject::disconnect(sender2, 0, &seq4, 0);
       
   946     seq1.reset();
       
   947     seq2.reset();
       
   948     seq3->reset();
       
   949     seq4.reset();
       
   950 
       
   951     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
       
   952     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_deleteNext()));
       
   953     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
       
   954     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
       
   955     connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
       
   956     connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_deleteSender()));
       
   957     connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
       
   958     connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
       
   959 
       
   960     QPointer<SenderObject> psender = sender2;
       
   961     QPointer<SequenceObject> pseq3 = seq3;
       
   962 
       
   963     SequenceObject::sequence = sequence = 0;
       
   964     sender2->emitSignal1();
       
   965     QCOMPARE(static_cast<QObject *>(psender), static_cast<QObject *>(0));
       
   966     QCOMPARE(static_cast<QObject *>(pseq3), static_cast<QObject *>(0));
       
   967     QCOMPARE(seq1.called(1), TRUE);
       
   968     QCOMPARE(seq2.called(1), TRUE);
       
   969     QCOMPARE(seq4.called(1), TRUE);
       
   970     QCOMPARE(seq1.called(2), TRUE);
       
   971     QCOMPARE(seq2.called(2), TRUE);
       
   972     QCOMPARE(seq4.called(2), FALSE);
       
   973     QCOMPARE(seq1.sequence_slot1, ++sequence);
       
   974     QCOMPARE(seq2.sequence_slot1, ++sequence);
       
   975     QCOMPARE(seq4.sequence_slot1, ++sequence);
       
   976     QCOMPARE(seq1.sequence_slot2, ++sequence);
       
   977     QCOMPARE(seq2.sequence_slot2, ++sequence);
       
   978 
       
   979     QPointer<SenderObject> psender3 = new SenderObject;
       
   980     connect(psender3, SIGNAL(signal1()), psender3, SIGNAL(signal2()));
       
   981     connect(psender3, SIGNAL(signal2()), &seq1, SLOT(slot2_deleteSender()));
       
   982     psender3->emitSignal1();
       
   983     QVERIFY(!psender3);
       
   984 }
       
   985 
       
   986 static int instanceCount = 0;
       
   987 
       
   988 struct CustomType
       
   989 {
       
   990     CustomType(int l1 = 0, int l2 = 0, int l3 = 0): i1(l1), i2(l2), i3(l3)
       
   991     { ++instanceCount; }
       
   992     CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3)
       
   993     { ++instanceCount; }
       
   994     ~CustomType() { --instanceCount; }
       
   995 
       
   996     int i1, i2, i3;
       
   997     int value() { return i1 + i2 + i3; }
       
   998 };
       
   999 
       
  1000 Q_DECLARE_METATYPE(CustomType*)
       
  1001 
       
  1002 class QCustomTypeChecker: public QObject
       
  1003 {
       
  1004     Q_OBJECT
       
  1005 
       
  1006 public:
       
  1007     QCustomTypeChecker(QObject *parent = 0): QObject(parent) {}
       
  1008     void doEmit(CustomType ct)
       
  1009     { emit signal1(ct); }
       
  1010 
       
  1011 public slots:
       
  1012     void slot1(CustomType ct);
       
  1013 
       
  1014 signals:
       
  1015     void signal1(CustomType ct);
       
  1016 
       
  1017 public:
       
  1018     CustomType received;
       
  1019 };
       
  1020 
       
  1021 void QCustomTypeChecker::slot1(CustomType ct)
       
  1022 { received = ct; }
       
  1023 
       
  1024 
       
  1025 void tst_QObject::customTypes()
       
  1026 {
       
  1027     CustomType t0;
       
  1028     CustomType t1(1, 2, 3);
       
  1029     CustomType t2(2, 3, 4);
       
  1030 
       
  1031     {
       
  1032         QCustomTypeChecker checker;
       
  1033         QCOMPARE(instanceCount, 4);
       
  1034 
       
  1035         connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
       
  1036                 Qt::DirectConnection);
       
  1037         QCOMPARE(checker.received.value(), 0);
       
  1038         checker.doEmit(t1);
       
  1039         QCOMPARE(checker.received.value(), t1.value());
       
  1040         checker.received = t0;
       
  1041 
       
  1042         int idx = qRegisterMetaType<CustomType>("CustomType");
       
  1043         QCOMPARE(QMetaType::type("CustomType"), idx);
       
  1044 
       
  1045         checker.disconnect();
       
  1046         connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
       
  1047                 Qt::QueuedConnection);
       
  1048         QCOMPARE(instanceCount, 4);
       
  1049         checker.doEmit(t2);
       
  1050         QCOMPARE(instanceCount, 5);
       
  1051         QCOMPARE(checker.received.value(), t0.value());
       
  1052 
       
  1053         QCoreApplication::processEvents();
       
  1054         QCOMPARE(checker.received.value(), t2.value());
       
  1055         QCOMPARE(instanceCount, 4);
       
  1056 
       
  1057         QVERIFY(QMetaType::isRegistered(idx));
       
  1058         QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
       
  1059         QCOMPARE(QMetaType::type("CustomType"), idx);
       
  1060         QVERIFY(QMetaType::isRegistered(idx));
       
  1061     }
       
  1062     QCOMPARE(instanceCount, 3);
       
  1063 }
       
  1064 
       
  1065 QDataStream &operator<<(QDataStream &stream, const CustomType &ct)
       
  1066 {
       
  1067     stream << ct.i1 << ct.i2 << ct.i3;
       
  1068     return stream;
       
  1069 }
       
  1070 
       
  1071 QDataStream &operator>>(QDataStream &stream, CustomType &ct)
       
  1072 {
       
  1073     stream >> ct.i1;
       
  1074     stream >> ct.i2;
       
  1075     stream >> ct.i3;
       
  1076     return stream;
       
  1077 }
       
  1078 
       
  1079 void tst_QObject::streamCustomTypes()
       
  1080 {
       
  1081     QByteArray ba;
       
  1082 
       
  1083     int idx = qRegisterMetaType<CustomType>("CustomType");
       
  1084     qRegisterMetaTypeStreamOperators<CustomType>("CustomType");
       
  1085 
       
  1086     {
       
  1087         CustomType t1(1, 2, 3);
       
  1088         QCOMPARE(instanceCount, 1);
       
  1089         QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::WriteOnly);
       
  1090         QMetaType::save(stream, idx, &t1);
       
  1091     }
       
  1092 
       
  1093     QCOMPARE(instanceCount, 0);
       
  1094 
       
  1095     {
       
  1096         CustomType t2;
       
  1097         QCOMPARE(instanceCount, 1);
       
  1098         QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::ReadOnly);
       
  1099         QMetaType::load(stream, idx, &t2);
       
  1100         QCOMPARE(instanceCount, 1);
       
  1101         QCOMPARE(t2.i1, 1);
       
  1102         QCOMPARE(t2.i2, 2);
       
  1103         QCOMPARE(t2.i3, 3);
       
  1104     }
       
  1105     QCOMPARE(instanceCount, 0);
       
  1106 }
       
  1107 
       
  1108 class PropertyObject : public QObject
       
  1109 {
       
  1110     Q_OBJECT
       
  1111     Q_ENUMS(Alpha Priority)
       
  1112 
       
  1113     Q_PROPERTY(Alpha alpha READ alpha WRITE setAlpha)
       
  1114     Q_PROPERTY(Priority priority READ priority WRITE setPriority)
       
  1115     Q_PROPERTY(int number READ number WRITE setNumber)
       
  1116     Q_PROPERTY(QString string READ string WRITE setString)
       
  1117     Q_PROPERTY(QVariant variant READ variant WRITE setVariant)
       
  1118     Q_PROPERTY(CustomType* custom READ custom WRITE setCustom)
       
  1119     Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat)
       
  1120     Q_PROPERTY(qreal myQReal READ myQReal WRITE setMyQReal)
       
  1121 
       
  1122 public:
       
  1123     enum Alpha {
       
  1124         Alpha0,
       
  1125         Alpha1,
       
  1126         Alpha2
       
  1127     };
       
  1128 
       
  1129     enum Priority { High, Low, VeryHigh, VeryLow };
       
  1130 
       
  1131     PropertyObject()
       
  1132         : m_alpha(Alpha0), m_priority(High), m_number(0), m_custom(0), m_float(42)
       
  1133     {}
       
  1134 
       
  1135     Alpha alpha() const { return m_alpha; }
       
  1136     void setAlpha(Alpha alpha) { m_alpha = alpha; }
       
  1137 
       
  1138     Priority priority() const { return m_priority; }
       
  1139     void setPriority(Priority priority) { m_priority = priority; }
       
  1140 
       
  1141     int number() const { return m_number; }
       
  1142     void setNumber(int number) { m_number = number; }
       
  1143 
       
  1144     QString string() const { return m_string; }
       
  1145     void setString(const QString &string) { m_string = string; }
       
  1146 
       
  1147     QVariant variant() const { return m_variant; }
       
  1148     void setVariant(const QVariant &variant) { m_variant = variant; }
       
  1149 
       
  1150     CustomType *custom() const { return m_custom; }
       
  1151     void setCustom(CustomType *custom) { m_custom = custom; }
       
  1152 
       
  1153     void setMyFloat(float value) { m_float = value; }
       
  1154     inline float myFloat() const { return m_float; }
       
  1155 
       
  1156     void setMyQReal(qreal value) { m_qreal = value; }
       
  1157     qreal myQReal() const { return m_qreal; }
       
  1158 
       
  1159 private:
       
  1160     Alpha m_alpha;
       
  1161     Priority m_priority;
       
  1162     int m_number;
       
  1163     QString m_string;
       
  1164     QVariant m_variant;
       
  1165     CustomType *m_custom;
       
  1166     float m_float;
       
  1167     qreal m_qreal;
       
  1168 };
       
  1169 
       
  1170 Q_DECLARE_METATYPE(PropertyObject::Priority)
       
  1171 
       
  1172 void tst_QObject::threadSignalEmissionCrash()
       
  1173 {
       
  1174 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
       
  1175     int loopCount = 100;
       
  1176 #else
       
  1177     int loopCount = 1000;
       
  1178 #endif
       
  1179     for (int i = 0; i < loopCount; ++i) {
       
  1180         QTcpSocket socket;
       
  1181         socket.connectToHost("localhost", 80);
       
  1182     }
       
  1183 }
       
  1184 
       
  1185 class TestThread : public QThread
       
  1186 {
       
  1187     Q_OBJECT
       
  1188 public:
       
  1189     inline void run()
       
  1190     {
       
  1191         *object = new QObject;
       
  1192         *child = new QObject(*object);
       
  1193         mutex.lock();
       
  1194         cond.wakeOne();
       
  1195         cond.wait(&mutex);
       
  1196         mutex.unlock();
       
  1197     }
       
  1198 
       
  1199     QObject **object, **child;
       
  1200     QMutex mutex;
       
  1201     QWaitCondition cond;
       
  1202 };
       
  1203 
       
  1204 void tst_QObject::thread()
       
  1205 {
       
  1206     QThread *currentThread = QThread::currentThread();
       
  1207     // the current thread is the same as the QApplication
       
  1208     // thread... see tst_QApplication::thread()
       
  1209 
       
  1210     {
       
  1211         QObject object;
       
  1212         // thread affinity for objects with no parent should be the
       
  1213         // current thread
       
  1214         QVERIFY(object.thread() != 0);
       
  1215         QCOMPARE(object.thread(), currentThread);
       
  1216         // children inherit their parent's thread
       
  1217         QObject child(&object);
       
  1218         QCOMPARE(child.thread(), object.thread());
       
  1219     }
       
  1220 
       
  1221     QObject *object = 0;
       
  1222     QObject *child = 0;
       
  1223 
       
  1224     {
       
  1225         TestThread thr;
       
  1226         QVERIFY(thr.thread() != 0);
       
  1227         QCOMPARE(thr.thread(), currentThread);
       
  1228 
       
  1229         thr.object = &object;
       
  1230         thr.child = &child;
       
  1231 
       
  1232         thr.mutex.lock();
       
  1233         thr.start();
       
  1234         thr.cond.wait(&thr.mutex);
       
  1235 
       
  1236         // thread affinity for an object with no parent should be the
       
  1237         // thread in which the object was created
       
  1238         QCOMPARE(object->thread(), (QThread *)&thr);
       
  1239         // children inherit their parent's thread
       
  1240         QCOMPARE(child->thread(), object->thread());
       
  1241 
       
  1242         thr.cond.wakeOne();
       
  1243         thr.mutex.unlock();
       
  1244         thr.wait();
       
  1245 
       
  1246         // even though the thread is no longer running, the affinity
       
  1247         // should not change
       
  1248         QCOMPARE(object->thread(), (QThread *)&thr);
       
  1249         QCOMPARE(child->thread(), object->thread());
       
  1250     }
       
  1251 
       
  1252     // the thread has been destroyed, thread affinity should
       
  1253     // automatically reset to no thread
       
  1254     QCOMPARE(object->thread(), (QThread *)0);
       
  1255     QCOMPARE(child->thread(), object->thread());
       
  1256 
       
  1257     delete object;
       
  1258 }
       
  1259 
       
  1260 class MoveToThreadObject : public QObject
       
  1261 {
       
  1262     Q_OBJECT
       
  1263 public:
       
  1264     QThread *timerEventThread;
       
  1265     QThread *customEventThread;
       
  1266     QThread *slotThread;
       
  1267 
       
  1268     MoveToThreadObject(QObject *parent = 0)
       
  1269         : QObject(parent), timerEventThread(0), customEventThread(0), slotThread(0)
       
  1270     { }
       
  1271 
       
  1272     void customEvent(QEvent *)
       
  1273     {
       
  1274         Q_ASSERT(customEventThread == 0);
       
  1275         customEventThread = QThread::currentThread();
       
  1276         emit theSignal();
       
  1277     }
       
  1278 
       
  1279     void timerEvent(QTimerEvent *)
       
  1280     {
       
  1281         Q_ASSERT(timerEventThread == 0);
       
  1282         timerEventThread = QThread::currentThread();
       
  1283         emit theSignal();
       
  1284     }
       
  1285 
       
  1286 public slots:
       
  1287     void theSlot()
       
  1288     {
       
  1289         Q_ASSERT(slotThread == 0);
       
  1290         slotThread = QThread::currentThread();
       
  1291         emit theSignal();
       
  1292     }
       
  1293 
       
  1294 signals:
       
  1295     void theSignal();
       
  1296 };
       
  1297 
       
  1298 class MoveToThreadThread : public QThread
       
  1299 {
       
  1300 public:
       
  1301     ~MoveToThreadThread()
       
  1302     {
       
  1303         if (isRunning()) {
       
  1304             terminate();
       
  1305             wait();
       
  1306         }
       
  1307     }
       
  1308     void start()
       
  1309     {
       
  1310         QEventLoop eventLoop;
       
  1311         connect(this, SIGNAL(started()), &eventLoop, SLOT(quit()), Qt::QueuedConnection);
       
  1312         QThread::start();
       
  1313         // wait for thread to start
       
  1314         (void) eventLoop.exec();
       
  1315     }
       
  1316     void run()
       
  1317     { (void) exec(); }
       
  1318 };
       
  1319 
       
  1320 void tst_QObject::thread0()
       
  1321 {
       
  1322     QObject *object = new QObject;
       
  1323     object->moveToThread(0);
       
  1324     QObject *child = new QObject(object);
       
  1325     QCOMPARE(child->parent(), object);
       
  1326     QCOMPARE(child->thread(), (QThread *)0);
       
  1327 
       
  1328 #if 0
       
  1329     // We don't support moving children into a parent that has no thread
       
  1330     // affinity (yet?).
       
  1331     QObject *child2 = new QObject;
       
  1332     child2->moveToThread(0);
       
  1333     child2->setParent(object);
       
  1334     QCOMPARE(child2->parent(), object);
       
  1335     QCOMPARE(child2->thread(), (QThread *)0);
       
  1336 #endif
       
  1337 
       
  1338     delete object;
       
  1339 }
       
  1340 
       
  1341 void tst_QObject::moveToThread()
       
  1342 {
       
  1343     QThread *currentThread = QThread::currentThread();
       
  1344 
       
  1345     {
       
  1346         QObject *object = new QObject;
       
  1347         QObject *child = new QObject(object);
       
  1348         QCOMPARE(object->thread(), currentThread);
       
  1349         QCOMPARE(child->thread(), currentThread);
       
  1350         object->moveToThread(0);
       
  1351         QCOMPARE(object->thread(), (QThread *)0);
       
  1352         QCOMPARE(child->thread(), (QThread *)0);
       
  1353         object->moveToThread(currentThread);
       
  1354         QCOMPARE(object->thread(), currentThread);
       
  1355         QCOMPARE(child->thread(), currentThread);
       
  1356         object->moveToThread(0);
       
  1357         QCOMPARE(object->thread(), (QThread *)0);
       
  1358         QCOMPARE(child->thread(), (QThread *)0);
       
  1359         // can delete an object with no thread anywhere
       
  1360         delete object;
       
  1361     }
       
  1362 
       
  1363     {
       
  1364         MoveToThreadThread thread;
       
  1365         thread.start();
       
  1366 
       
  1367         QObject *object = new QObject;
       
  1368         QObject *child = new QObject(object);
       
  1369         QPointer<QObject> opointer = object;
       
  1370         QPointer<QObject> cpointer = object;
       
  1371 
       
  1372         QCOMPARE(object->thread(), currentThread);
       
  1373         QCOMPARE(child->thread(), currentThread);
       
  1374         object->moveToThread(&thread);
       
  1375         QCOMPARE(object->thread(), (QThread *)&thread);
       
  1376         QCOMPARE(child->thread(), (QThread *)&thread);
       
  1377 
       
  1378         connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1379         QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
       
  1380         thread.wait();
       
  1381 
       
  1382         QVERIFY(opointer == 0);
       
  1383         QVERIFY(cpointer == 0);
       
  1384     }
       
  1385 
       
  1386     {
       
  1387         // make sure posted events are moved with the object
       
  1388         MoveToThreadThread thread;
       
  1389         thread.start();
       
  1390 
       
  1391         MoveToThreadObject *object = new MoveToThreadObject;
       
  1392         MoveToThreadObject *child = new MoveToThreadObject(object);
       
  1393 
       
  1394         connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1395         QCoreApplication::postEvent(child, new QEvent(QEvent::User));
       
  1396         QCoreApplication::postEvent(object, new QEvent(QEvent::User));
       
  1397 
       
  1398         QCOMPARE(object->thread(), currentThread);
       
  1399         QCOMPARE(child->thread(), currentThread);
       
  1400         object->moveToThread(&thread);
       
  1401         QCOMPARE(object->thread(), (QThread *)&thread);
       
  1402         QCOMPARE(child->thread(), (QThread *)&thread);
       
  1403 
       
  1404         thread.wait();
       
  1405 
       
  1406         QCOMPARE(object->customEventThread, (QThread *)&thread);
       
  1407         QCOMPARE(child->customEventThread, (QThread *)&thread);
       
  1408 
       
  1409         thread.start();
       
  1410         connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1411         QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
       
  1412         thread.wait();
       
  1413     }
       
  1414 
       
  1415     {
       
  1416         // make sure timers are moved with the object
       
  1417         MoveToThreadThread thread;
       
  1418         thread.start();
       
  1419 
       
  1420         MoveToThreadObject *object = new MoveToThreadObject;
       
  1421         MoveToThreadObject *child = new MoveToThreadObject(object);
       
  1422 
       
  1423         connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1424 
       
  1425 #if defined(Q_OS_SYMBIAN)
       
  1426         // Child timer will be registered after parent timer in the new
       
  1427         // thread, and 10ms is less than symbian timer resolution, so
       
  1428         // child->timerEventThread compare after thread.wait() will
       
  1429         // usually fail unless timers are farther apart.
       
  1430         child->startTimer(100);
       
  1431         object->startTimer(150);
       
  1432 #else
       
  1433         child->startTimer(90);
       
  1434         object->startTimer(100);
       
  1435 #endif
       
  1436 
       
  1437         QCOMPARE(object->thread(), currentThread);
       
  1438         QCOMPARE(child->thread(), currentThread);
       
  1439         object->moveToThread(&thread);
       
  1440         QCOMPARE(object->thread(), (QThread *)&thread);
       
  1441         QCOMPARE(child->thread(), (QThread *)&thread);
       
  1442 
       
  1443         thread.wait();
       
  1444 
       
  1445         QCOMPARE(object->timerEventThread, (QThread *)&thread);
       
  1446         QCOMPARE(child->timerEventThread, (QThread *)&thread);
       
  1447 
       
  1448         thread.start();
       
  1449         connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1450         QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
       
  1451         thread.wait();
       
  1452     }
       
  1453 
       
  1454     {
       
  1455         // make sure socket notifiers are moved with the object
       
  1456         MoveToThreadThread thread;
       
  1457         thread.start();
       
  1458 
       
  1459         QTcpServer server;
       
  1460         QVERIFY(server.listen(QHostAddress::LocalHost, 0));
       
  1461         QTcpSocket *socket = new QTcpSocket;
       
  1462         MoveToThreadObject *child = new MoveToThreadObject(socket);
       
  1463         connect(socket, SIGNAL(disconnected()), child, SLOT(theSlot()), Qt::DirectConnection);
       
  1464         connect(child, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1465 
       
  1466         socket->connectToHost(server.serverAddress(), server.serverPort());
       
  1467 
       
  1468         QVERIFY(server.waitForNewConnection(1000));
       
  1469         QTcpSocket *serverSocket = server.nextPendingConnection();
       
  1470         QVERIFY(serverSocket);
       
  1471 
       
  1472         socket->waitForConnected();
       
  1473 
       
  1474         QCOMPARE(socket->thread(), currentThread);
       
  1475         socket->moveToThread(&thread);
       
  1476         QCOMPARE(socket->thread(), (QThread *)&thread);
       
  1477 
       
  1478         serverSocket->close();
       
  1479 
       
  1480         QVERIFY(thread.wait(10000));
       
  1481 
       
  1482         QCOMPARE(child->slotThread, (QThread *)&thread);
       
  1483 
       
  1484         thread.start();
       
  1485         connect(socket, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
       
  1486         QMetaObject::invokeMethod(socket, "deleteLater", Qt::QueuedConnection);
       
  1487         thread.wait();
       
  1488     }
       
  1489 }
       
  1490 
       
  1491 
       
  1492 void tst_QObject::property()
       
  1493 {
       
  1494     PropertyObject object;
       
  1495     const QMetaObject *mo = object.metaObject();
       
  1496     QMetaProperty property;
       
  1497     QVERIFY(mo);
       
  1498 
       
  1499     QVERIFY(mo->indexOfProperty("alpha") != -1);
       
  1500     property = mo->property(mo->indexOfProperty("alpha"));
       
  1501     QVERIFY(property.isEnumType());
       
  1502     QCOMPARE(property.typeName(), "Alpha");
       
  1503     QCOMPARE(property.type(), QVariant::Int);
       
  1504 
       
  1505     QVariant var = object.property("alpha");
       
  1506     QVERIFY(!var.isNull());
       
  1507     QCOMPARE(var.toInt(), int(PropertyObject::Alpha0));
       
  1508     object.setAlpha(PropertyObject::Alpha1);
       
  1509     QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
       
  1510     QVERIFY(object.setProperty("alpha", PropertyObject::Alpha2));
       
  1511     QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha2));
       
  1512     QVERIFY(object.setProperty("alpha", "Alpha1"));
       
  1513     QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
       
  1514     QVERIFY(!object.setProperty("alpha", QVariant()));
       
  1515 
       
  1516     QVERIFY(mo->indexOfProperty("number") != -1);
       
  1517     QCOMPARE(object.property("number").toInt(), 0);
       
  1518     object.setNumber(24);
       
  1519     QCOMPARE(object.property("number"), QVariant(24));
       
  1520     QVERIFY(object.setProperty("number", 12));
       
  1521     QCOMPARE(object.property("number"), QVariant(12));
       
  1522     QVERIFY(object.setProperty("number", "42"));
       
  1523     QCOMPARE(object.property("number"), QVariant(42));
       
  1524 
       
  1525     QVERIFY(mo->indexOfProperty("string") != -1);
       
  1526     QCOMPARE(object.property("string").toString(), QString());
       
  1527     object.setString("String1");
       
  1528     QCOMPARE(object.property("string"), QVariant("String1"));
       
  1529     QVERIFY(object.setProperty("string", "String2"));
       
  1530     QCOMPARE(object.property("string"), QVariant("String2"));
       
  1531     QVERIFY(!object.setProperty("string", QVariant()));
       
  1532 
       
  1533     const int idx = mo->indexOfProperty("variant");
       
  1534     QVERIFY(idx != -1);
       
  1535     QVERIFY(mo->property(idx).type() == QVariant::LastType);
       
  1536     QCOMPARE(object.property("variant"), QVariant());
       
  1537     QVariant variant1(42);
       
  1538     QVariant variant2("string");
       
  1539     object.setVariant(variant1);
       
  1540     QCOMPARE(object.property("variant"), variant1);
       
  1541     QVERIFY(object.setProperty("variant", variant2));
       
  1542     QCOMPARE(object.variant(), QVariant(variant2));
       
  1543     QCOMPARE(object.property("variant"), variant2);
       
  1544     QVERIFY(object.setProperty("variant", QVariant()));
       
  1545     QCOMPARE(object.property("variant"), QVariant());
       
  1546 
       
  1547     QVERIFY(mo->indexOfProperty("custom") != -1);
       
  1548     property = mo->property(mo->indexOfProperty("custom"));
       
  1549     QVERIFY(property.isValid());
       
  1550     QVERIFY(property.isWritable());
       
  1551     QVERIFY(!property.isEnumType());
       
  1552     QCOMPARE(property.typeName(), "CustomType*");
       
  1553     QCOMPARE(property.type(), QVariant::UserType);
       
  1554 
       
  1555     CustomType *customPointer = 0;
       
  1556     QVariant customVariant = object.property("custom");
       
  1557     customPointer = qVariantValue<CustomType *>(customVariant);
       
  1558     QCOMPARE(customPointer, object.custom());
       
  1559 
       
  1560     CustomType custom;
       
  1561     customPointer = &custom;
       
  1562     qVariantSetValue(customVariant, customPointer);
       
  1563 
       
  1564     property = mo->property(mo->indexOfProperty("custom"));
       
  1565     QVERIFY(property.isWritable());
       
  1566     QCOMPARE(property.typeName(), "CustomType*");
       
  1567     QCOMPARE(property.type(), QVariant::UserType);
       
  1568 
       
  1569     QVERIFY(object.setProperty("custom", customVariant));
       
  1570     QCOMPARE(object.custom(), customPointer);
       
  1571 
       
  1572     customVariant = object.property("custom");
       
  1573     customPointer = qVariantValue<CustomType *>(customVariant);
       
  1574     QCOMPARE(object.custom(), customPointer);
       
  1575 
       
  1576     // this enum property has a meta type, but it's not yet registered, so we know this fails
       
  1577     QVERIFY(mo->indexOfProperty("priority") != -1);
       
  1578     property = mo->property(mo->indexOfProperty("priority"));
       
  1579     QVERIFY(property.isEnumType());
       
  1580     QCOMPARE(property.typeName(), "Priority");
       
  1581     QCOMPARE(property.type(), QVariant::Int);
       
  1582 
       
  1583     var = object.property("priority");
       
  1584     QVERIFY(!var.isNull());
       
  1585     QCOMPARE(var.toInt(), int(PropertyObject::High));
       
  1586     object.setPriority(PropertyObject::Low);
       
  1587     QCOMPARE(object.property("priority").toInt(), int(PropertyObject::Low));
       
  1588     QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
       
  1589     QCOMPARE(object.property("priority").toInt(), int(PropertyObject::VeryHigh));
       
  1590     QVERIFY(object.setProperty("priority", "High"));
       
  1591     QCOMPARE(object.property("priority").toInt(), int(PropertyObject::High));
       
  1592     QVERIFY(!object.setProperty("priority", QVariant()));
       
  1593 
       
  1594     // now it's registered, so it works as expected
       
  1595     int priorityMetaTypeId = qRegisterMetaType<PropertyObject::Priority>("PropertyObject::Priority");
       
  1596 
       
  1597     QVERIFY(mo->indexOfProperty("priority") != -1);
       
  1598     property = mo->property(mo->indexOfProperty("priority"));
       
  1599     QVERIFY(property.isEnumType());
       
  1600     QCOMPARE(property.typeName(), "Priority");
       
  1601     QCOMPARE(property.type(), QVariant::UserType);
       
  1602     QCOMPARE(property.userType(), priorityMetaTypeId);
       
  1603 
       
  1604     var = object.property("priority");
       
  1605     QVERIFY(!var.isNull());
       
  1606     QVERIFY(qVariantCanConvert<PropertyObject::Priority>(var));
       
  1607     QCOMPARE(qVariantValue<PropertyObject::Priority>(var), PropertyObject::High);
       
  1608     object.setPriority(PropertyObject::Low);
       
  1609     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
       
  1610     QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
       
  1611     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::VeryHigh);
       
  1612     QVERIFY(object.setProperty("priority", "High"));
       
  1613     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
       
  1614     QVERIFY(!object.setProperty("priority", QVariant()));
       
  1615 
       
  1616     var = object.property("priority");
       
  1617     QCOMPARE(qVariantValue<PropertyObject::Priority>(var), PropertyObject::High);
       
  1618     object.setPriority(PropertyObject::Low);
       
  1619     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
       
  1620     object.setProperty("priority", var);
       
  1621     QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
       
  1622 }
       
  1623 
       
  1624 void tst_QObject::metamethod()
       
  1625 {
       
  1626     SenderObject obj;
       
  1627     const QMetaObject *mobj = obj.metaObject();
       
  1628     QMetaMethod m;
       
  1629 
       
  1630     m = mobj->method(mobj->indexOfMethod("invoke1()"));
       
  1631     QVERIFY(QByteArray(m.signature()) == "invoke1()");
       
  1632     QVERIFY(m.methodType() == QMetaMethod::Method);
       
  1633     QVERIFY(m.access() == QMetaMethod::Public);
       
  1634     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
       
  1635     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
       
  1636 
       
  1637     m = mobj->method(mobj->indexOfMethod("sinvoke1()"));
       
  1638     QVERIFY(QByteArray(m.signature()) == "sinvoke1()");
       
  1639     QVERIFY(m.methodType() == QMetaMethod::Method);
       
  1640     QVERIFY(m.access() == QMetaMethod::Public);
       
  1641     QVERIFY((m.attributes() & QMetaMethod::Scriptable));
       
  1642     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
       
  1643 
       
  1644     m = mobj->method(mobj->indexOfMethod("invoke2()"));
       
  1645     QVERIFY(QByteArray(m.signature()) == "invoke2()");
       
  1646     QVERIFY(m.methodType() == QMetaMethod::Method);
       
  1647     QVERIFY(m.access() == QMetaMethod::Protected);
       
  1648     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
       
  1649     QVERIFY((m.attributes() & QMetaMethod::Compatibility));
       
  1650 
       
  1651     m = mobj->method(mobj->indexOfMethod("sinvoke2()"));
       
  1652     QVERIFY(QByteArray(m.signature()) == "sinvoke2()");
       
  1653     QVERIFY(m.methodType() == QMetaMethod::Method);
       
  1654     QVERIFY(m.access() == QMetaMethod::Protected);
       
  1655     QVERIFY((m.attributes() & QMetaMethod::Scriptable));
       
  1656     QVERIFY((m.attributes() & QMetaMethod::Compatibility));
       
  1657 
       
  1658     m = mobj->method(mobj->indexOfMethod("invoke3()"));
       
  1659     QVERIFY(QByteArray(m.signature()) == "invoke3()");
       
  1660     QVERIFY(m.methodType() == QMetaMethod::Method);
       
  1661     QVERIFY(m.access() == QMetaMethod::Private);
       
  1662     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
       
  1663     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
       
  1664 
       
  1665     m = mobj->method(mobj->indexOfMethod("sinvoke3()"));
       
  1666     QVERIFY(QByteArray(m.signature()) == "sinvoke3()");
       
  1667     QVERIFY(m.methodType() == QMetaMethod::Method);
       
  1668     QVERIFY(m.access() == QMetaMethod::Private);
       
  1669     QVERIFY((m.attributes() & QMetaMethod::Scriptable));
       
  1670     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
       
  1671 
       
  1672     m = mobj->method(mobj->indexOfMethod("signal5()"));
       
  1673     QVERIFY(QByteArray(m.signature()) == "signal5()");
       
  1674     QVERIFY(m.methodType() == QMetaMethod::Signal);
       
  1675     QVERIFY(m.access() == QMetaMethod::Protected);
       
  1676     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
       
  1677     QVERIFY((m.attributes() & QMetaMethod::Compatibility));
       
  1678 
       
  1679     m = mobj->method(mobj->indexOfMethod("aPublicSlot()"));
       
  1680     QVERIFY(QByteArray(m.signature()) == "aPublicSlot()");
       
  1681     QVERIFY(m.methodType() == QMetaMethod::Slot);
       
  1682     QVERIFY(m.access() == QMetaMethod::Public);
       
  1683     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
       
  1684     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
       
  1685 
       
  1686     m = mobj->method(mobj->indexOfMethod("invoke1()"));
       
  1687     QCOMPARE(m.parameterNames().count(), 0);
       
  1688     QCOMPARE(m.parameterTypes().count(), 0);
       
  1689 
       
  1690     m = mobj->method(mobj->indexOfMethod("invoke2(int)"));
       
  1691     QCOMPARE(m.parameterNames().count(), 1);
       
  1692     QCOMPARE(m.parameterTypes().count(), 1);
       
  1693     QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
       
  1694     QVERIFY(m.parameterNames().at(0).isEmpty());
       
  1695 
       
  1696     m = mobj->method(mobj->indexOfMethod("invoke3(int,int)"));
       
  1697     QCOMPARE(m.parameterNames().count(), 2);
       
  1698     QCOMPARE(m.parameterTypes().count(), 2);
       
  1699     QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
       
  1700     QCOMPARE(m.parameterNames().at(0), QByteArray("hinz"));
       
  1701     QCOMPARE(m.parameterTypes().at(1), QByteArray("int"));
       
  1702     QCOMPARE(m.parameterNames().at(1), QByteArray("kunz"));
       
  1703 
       
  1704 }
       
  1705 
       
  1706 namespace QObjectTest
       
  1707 {
       
  1708     class TestObject: public QObject
       
  1709     {
       
  1710     Q_OBJECT
       
  1711     public:
       
  1712         TestObject(): QObject(), i(0) {}
       
  1713         void doEmit() { emit aSignal(); }
       
  1714         int i;
       
  1715     public slots:
       
  1716         void aSlot() { ++i; }
       
  1717     signals:
       
  1718         void aSignal();
       
  1719     };
       
  1720 }
       
  1721 
       
  1722 void tst_QObject::namespaces()
       
  1723 {
       
  1724     QObjectTest::TestObject obj;
       
  1725 
       
  1726     QVERIFY(connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot())));
       
  1727     obj.doEmit();
       
  1728     QCOMPARE(obj.i, 1);
       
  1729 }
       
  1730 
       
  1731 class SuperObject : public QObject
       
  1732 {
       
  1733     Q_OBJECT
       
  1734 public:
       
  1735     QObject *theSender;
       
  1736     SuperObject()
       
  1737     {
       
  1738         theSender = 0;
       
  1739     }
       
  1740 
       
  1741     friend class tst_QObject;
       
  1742 
       
  1743     using QObject::sender;
       
  1744 
       
  1745 public slots:
       
  1746     void rememberSender()
       
  1747     {
       
  1748         theSender = sender();
       
  1749     }
       
  1750 
       
  1751     void deleteAndRememberSender()
       
  1752     {
       
  1753         delete theSender;
       
  1754         theSender = sender();
       
  1755     }
       
  1756 signals:
       
  1757     void theSignal();
       
  1758 
       
  1759 };
       
  1760 
       
  1761 void tst_QObject::sender()
       
  1762 {
       
  1763     {
       
  1764         SuperObject sender;
       
  1765         SuperObject receiver;
       
  1766         connect(&sender, SIGNAL(theSignal()),
       
  1767                 &receiver, SLOT(rememberSender()));
       
  1768         QCOMPARE(receiver.sender(), (QObject *)0);
       
  1769         emit sender.theSignal();
       
  1770         QCOMPARE(receiver.theSender, (QObject *)&sender);
       
  1771         QCOMPARE(receiver.sender(), (QObject *)0);
       
  1772     }
       
  1773 
       
  1774     {
       
  1775         SuperObject *sender = new SuperObject;
       
  1776         SuperObject *receiver = new SuperObject;
       
  1777         connect(sender, SIGNAL(theSignal()),
       
  1778                 receiver, SLOT(rememberSender()),
       
  1779                 Qt::BlockingQueuedConnection);
       
  1780 
       
  1781         QThread thread;
       
  1782         receiver->moveToThread(&thread);
       
  1783         connect(sender, SIGNAL(theSignal()),
       
  1784                 &thread, SLOT(quit()),
       
  1785                 Qt::DirectConnection);
       
  1786 
       
  1787         QCOMPARE(receiver->sender(), (QObject *)0);
       
  1788         receiver->theSender = 0;
       
  1789         thread.start();
       
  1790         emit sender->theSignal();
       
  1791         QCOMPARE(receiver->theSender, (QObject *) sender);
       
  1792         QCOMPARE(receiver->sender(), (QObject *)0);
       
  1793 
       
  1794         QVERIFY(thread.wait(10000));
       
  1795         delete receiver;
       
  1796         delete sender;
       
  1797     }
       
  1798 
       
  1799     {
       
  1800         SuperObject *sender = new SuperObject;
       
  1801         SuperObject receiver;
       
  1802         connect(sender, SIGNAL(theSignal()),
       
  1803                 &receiver, SLOT(deleteAndRememberSender()));
       
  1804         QCOMPARE(receiver.sender(), (QObject *)0);
       
  1805         receiver.theSender = sender;
       
  1806         emit sender->theSignal();
       
  1807         QCOMPARE(receiver.theSender, (QObject *)0);
       
  1808         QCOMPARE(receiver.sender(), (QObject *)0);
       
  1809     }
       
  1810 
       
  1811     {
       
  1812         SuperObject *sender = new SuperObject;
       
  1813         SuperObject *receiver = new SuperObject;
       
  1814         connect(sender, SIGNAL(theSignal()),
       
  1815                 receiver, SLOT(deleteAndRememberSender()),
       
  1816                 Qt::BlockingQueuedConnection);
       
  1817 
       
  1818         QThread thread;
       
  1819         receiver->moveToThread(&thread);
       
  1820         connect(sender, SIGNAL(destroyed()),
       
  1821                 &thread, SLOT(quit()),
       
  1822                 Qt::DirectConnection);
       
  1823 
       
  1824         QCOMPARE(receiver->sender(), (QObject *)0);
       
  1825         receiver->theSender = sender;
       
  1826         thread.start();
       
  1827         emit sender->theSignal();
       
  1828         QCOMPARE(receiver->theSender, (QObject *)0);
       
  1829         QCOMPARE(receiver->sender(), (QObject *)0);
       
  1830 
       
  1831         QVERIFY(thread.wait(10000));
       
  1832         delete receiver;
       
  1833     }
       
  1834 }
       
  1835 
       
  1836 namespace Foo
       
  1837 {
       
  1838     struct Bar
       
  1839     {
       
  1840         virtual ~Bar() {}
       
  1841         virtual int rtti() const = 0;
       
  1842     };
       
  1843 
       
  1844     struct Bleh
       
  1845     {
       
  1846         virtual ~Bleh() {}
       
  1847         virtual int rtti() const = 0;
       
  1848     };
       
  1849 }
       
  1850 
       
  1851 QT_BEGIN_NAMESPACE
       
  1852 Q_DECLARE_INTERFACE(Foo::Bar, "com.qtest.foobar")
       
  1853 QT_END_NAMESPACE
       
  1854 
       
  1855 #define Bleh_iid "com.qtest.bleh"
       
  1856 QT_BEGIN_NAMESPACE
       
  1857 Q_DECLARE_INTERFACE(Foo::Bleh, Bleh_iid)
       
  1858 QT_END_NAMESPACE
       
  1859 
       
  1860 class FooObject: public QObject, public Foo::Bar
       
  1861 {
       
  1862     Q_OBJECT
       
  1863     Q_INTERFACES(Foo::Bar)
       
  1864 public:
       
  1865     int rtti() const { return 42; }
       
  1866 };
       
  1867 
       
  1868 class BlehObject : public QObject, public Foo::Bleh
       
  1869 {
       
  1870     Q_OBJECT
       
  1871     Q_INTERFACES(Foo::Bleh)
       
  1872 public:
       
  1873     int rtti() const { return 43; }
       
  1874 };
       
  1875 
       
  1876 void tst_QObject::declareInterface()
       
  1877 {
       
  1878     FooObject obj;
       
  1879 
       
  1880     Foo::Bar *bar = qobject_cast<Foo::Bar *>(&obj);
       
  1881     QVERIFY(bar);
       
  1882     QCOMPARE(bar->rtti(), 42);
       
  1883     QCOMPARE(static_cast<Foo::Bar *>(&obj), bar);
       
  1884 
       
  1885     BlehObject bleh;
       
  1886 
       
  1887     bar = qobject_cast<Foo::Bar *>(&bleh);
       
  1888     QVERIFY(!bar);
       
  1889     Foo::Bleh *b = qobject_cast<Foo::Bleh *>(&bleh);
       
  1890     QCOMPARE(b->rtti(), 43);
       
  1891     QCOMPARE(static_cast<Foo::Bleh *>(&bleh), b);
       
  1892 
       
  1893 }
       
  1894 
       
  1895 class CustomData : public QObjectUserData
       
  1896 {
       
  1897 public:
       
  1898     int id;
       
  1899 };
       
  1900 
       
  1901 void tst_QObject::testUserData()
       
  1902 {
       
  1903     const int USER_DATA_COUNT = 100;
       
  1904     int user_data_ids[USER_DATA_COUNT];
       
  1905 
       
  1906     // Register a few
       
  1907     for (int i=0; i<USER_DATA_COUNT; ++i) {
       
  1908         user_data_ids[i] = QObject::registerUserData();
       
  1909     }
       
  1910 
       
  1911     // Randomize the table a bit
       
  1912     for (int i=0; i<100; ++i) {
       
  1913         int p1 = rand() % USER_DATA_COUNT;
       
  1914         int p2 = rand() % USER_DATA_COUNT;
       
  1915 
       
  1916         int tmp = user_data_ids[p1];
       
  1917         user_data_ids[p1] = user_data_ids[p2];
       
  1918         user_data_ids[p2] = tmp;
       
  1919     }
       
  1920 
       
  1921     // insert the user data into an object
       
  1922     QObject my_test_object;
       
  1923     for (int i=0; i<USER_DATA_COUNT; ++i) {
       
  1924         CustomData *data = new CustomData;
       
  1925         data->id = user_data_ids[i];
       
  1926         my_test_object.setUserData(data->id, data);
       
  1927     }
       
  1928 
       
  1929     // verify that all ids and positions are matching
       
  1930     for (int i=0; i<USER_DATA_COUNT; ++i) {
       
  1931         int id = user_data_ids[i];
       
  1932         CustomData *data = static_cast<CustomData *>(my_test_object.userData(id));
       
  1933         QVERIFY(data != 0);
       
  1934         QVERIFY(data->id == id);
       
  1935     }
       
  1936 }
       
  1937 
       
  1938 class DestroyedListener : public QObject
       
  1939 {
       
  1940     Q_OBJECT
       
  1941 public:
       
  1942     inline DestroyedListener() : pointerWasZero(false) {}
       
  1943 
       
  1944     QPointer<QObject> pointer;
       
  1945     bool pointerWasZero;
       
  1946 
       
  1947 private slots:
       
  1948     inline void otherObjectDestroyed()
       
  1949     { pointerWasZero = pointer.isNull(); }
       
  1950 };
       
  1951 
       
  1952 void tst_QObject::qpointerResetBeforeDestroyedSignal()
       
  1953 {
       
  1954     QObject *obj = new QObject;
       
  1955     DestroyedListener listener;
       
  1956     listener.pointer = obj;
       
  1957     listener.pointerWasZero = false;
       
  1958     connect(obj, SIGNAL(destroyed()), &listener, SLOT(otherObjectDestroyed()));
       
  1959     delete obj;
       
  1960     QVERIFY(listener.pointerWasZero);
       
  1961     QVERIFY(listener.pointer.isNull());
       
  1962 }
       
  1963 
       
  1964 class DefaultArguments : public QObject
       
  1965 {
       
  1966     Q_OBJECT
       
  1967 
       
  1968 public slots:
       
  1969 
       
  1970     void theSlot(const QString &s) { result = s; }
       
  1971 
       
  1972 signals:
       
  1973     void theOriginalSignal();
       
  1974     void theSecondSignal(const QString &s = QString("secondDefault"));
       
  1975 
       
  1976 public:
       
  1977 
       
  1978     void emitTheOriginalSignal() { emit theOriginalSignal(); }
       
  1979     void emitTheSecondSignal() { emit theSecondSignal(); }
       
  1980     QString result;
       
  1981 };
       
  1982 
       
  1983 void tst_QObject::connectSignalsToSignalsWithDefaultArguments()
       
  1984 {
       
  1985     DefaultArguments o;
       
  1986     connect(&o, SIGNAL(theOriginalSignal()), &o, SIGNAL(theSecondSignal()));
       
  1987     connect(&o, SIGNAL(theSecondSignal(QString)), &o, SLOT(theSlot(QString)));
       
  1988     QVERIFY( o.result.isEmpty() );
       
  1989     o.emitTheSecondSignal();
       
  1990     QCOMPARE(o.result, QString("secondDefault"));
       
  1991     o.result = "Not called";
       
  1992     o.emitTheOriginalSignal();
       
  1993     QCOMPARE(o.result, QString("secondDefault"));
       
  1994 
       
  1995 }
       
  1996 
       
  1997 void tst_QObject::receivers()
       
  1998 {
       
  1999     class Object : public QObject
       
  2000     {
       
  2001     public:
       
  2002         int receivers(const char* signal) const
       
  2003         { return QObject::receivers(signal); }
       
  2004     };
       
  2005 
       
  2006     Object object;
       
  2007     QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
       
  2008     object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
       
  2009     QCOMPARE(object.receivers(SIGNAL(destroyed())), 1);
       
  2010     object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
       
  2011     QCOMPARE(object.receivers(SIGNAL(destroyed())), 2);
       
  2012     object.disconnect(SIGNAL(destroyed()), &object, SLOT(deleteLater()));
       
  2013     QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
       
  2014 }
       
  2015 
       
  2016 enum Enum { };
       
  2017 
       
  2018 struct Struct { };
       
  2019 class Class { };
       
  2020 
       
  2021 class NormalizeObject : public QObject
       
  2022 {
       
  2023     Q_OBJECT
       
  2024 
       
  2025 public:
       
  2026 
       
  2027 signals:
       
  2028     void uintPointerSignal(uint *);
       
  2029     void ulongPointerSignal(ulong *);
       
  2030     void constUintPointerSignal(const uint *);
       
  2031     void constUlongPointerSignal(const ulong *);
       
  2032 
       
  2033     void structSignal(Struct s);
       
  2034     void classSignal(Class c);
       
  2035     void enumSignal(Enum e);
       
  2036 
       
  2037     void structPointerSignal(Struct *s);
       
  2038     void classPointerSignal(Class *c);
       
  2039     void enumPointerSignal(Enum *e);
       
  2040 
       
  2041     void constStructPointerSignal(const Struct *s);
       
  2042     void constClassPointerSignal(const Class *c);
       
  2043     void constEnumPointerSignal(const Enum *e);
       
  2044 
       
  2045     void constStructPointerConstPointerSignal(const Struct * const *s);
       
  2046     void constClassPointerConstPointerSignal(const Class * const *c);
       
  2047     void constEnumPointerConstPointerSignal(const Enum * const *e);
       
  2048 
       
  2049     void unsignedintSignal(unsigned int);
       
  2050     void unsignedSignal(unsigned);
       
  2051     void unsignedlongSignal(unsigned long);
       
  2052     void unsignedlonglongSignal(quint64);
       
  2053     void unsignedlongintSignal(unsigned long int);
       
  2054     void unsignedshortSignal(unsigned short);
       
  2055     void unsignedcharSignal(unsigned char);
       
  2056 
       
  2057 public slots:
       
  2058     void uintPointerSlot(uint *) { }
       
  2059     void ulongPointerSlot(ulong *) { }
       
  2060     void constUintPointerSlot(const uint *) { }
       
  2061     void constUlongPointerSlot(const ulong *) { }
       
  2062 
       
  2063     void structSlot(Struct s) { }
       
  2064     void classSlot(Class c) { }
       
  2065     void enumSlot(Enum e) { }
       
  2066 
       
  2067     void structPointerSlot(Struct *s) { }
       
  2068     void classPointerSlot(Class *c) { }
       
  2069     void enumPointerSlot(Enum *e) { }
       
  2070 
       
  2071     void constStructPointerSlot(const Struct *s) { }
       
  2072     void constClassPointerSlot(const Class *c) { }
       
  2073     void constEnumPointerSlot(const Enum *e) { }
       
  2074 
       
  2075     void constStructPointerConstPointerSlot(const Struct * const *s) { }
       
  2076     void constClassPointerConstPointerSlot(const Class * const *c) { }
       
  2077     void constEnumPointerConstPointerSlot(const Enum * const *e) { }
       
  2078 
       
  2079     void uintSlot(uint) {};
       
  2080     void unsignedintSlot(unsigned int) {};
       
  2081     void unsignedSlot(unsigned) {};
       
  2082     void unsignedlongSlot(unsigned long) {};
       
  2083     void unsignedlonglongSlot(quint64) {};
       
  2084     void unsignedlongintSlot(unsigned long int) {};
       
  2085     void unsignedshortSlot(unsigned short) {};
       
  2086     void unsignedcharSlot(unsigned char) {};
       
  2087 
       
  2088 };
       
  2089 
       
  2090 void tst_QObject::normalize()
       
  2091 {
       
  2092     NormalizeObject object;
       
  2093 
       
  2094     // unsigned int -> uint, unsigned long -> ulong
       
  2095     QVERIFY(object.connect(&object,
       
  2096                            SIGNAL(uintPointerSignal(uint *)),
       
  2097                            SLOT(uintPointerSlot(uint *))));
       
  2098     QVERIFY(object.connect(&object,
       
  2099                            SIGNAL(uintPointerSignal(unsigned int *)),
       
  2100                            SLOT(uintPointerSlot(uint *))));
       
  2101     QVERIFY(object.connect(&object,
       
  2102                            SIGNAL(uintPointerSignal(uint *)),
       
  2103                            SLOT(uintPointerSlot(unsigned int *))));
       
  2104 
       
  2105     QVERIFY(object.connect(&object,
       
  2106                            SIGNAL(constUintPointerSignal(const uint *)),
       
  2107                            SLOT(constUintPointerSlot(const uint *))));
       
  2108     QVERIFY(object.connect(&object,
       
  2109                            SIGNAL(constUintPointerSignal(const unsigned int *)),
       
  2110                            SLOT(constUintPointerSlot(const uint *))));
       
  2111     QVERIFY(object.connect(&object,
       
  2112                            SIGNAL(constUintPointerSignal(const uint *)),
       
  2113                            SLOT(constUintPointerSlot(const unsigned int *))));
       
  2114 
       
  2115     QVERIFY(object.connect(&object,
       
  2116                            SIGNAL(ulongPointerSignal(ulong *)),
       
  2117                            SLOT(ulongPointerSlot(ulong *))));
       
  2118     QVERIFY(object.connect(&object,
       
  2119                            SIGNAL(ulongPointerSignal(unsigned long *)),
       
  2120                            SLOT(ulongPointerSlot(ulong *))));
       
  2121     QVERIFY(object.connect(&object,
       
  2122                            SIGNAL(ulongPointerSignal(ulong *)),
       
  2123                            SLOT(ulongPointerSlot(unsigned long *))));
       
  2124 
       
  2125     QVERIFY(object.connect(&object,
       
  2126                            SIGNAL(constUlongPointerSignal(const ulong *)),
       
  2127                            SLOT(constUlongPointerSlot(const ulong *))));
       
  2128     QVERIFY(object.connect(&object,
       
  2129                            SIGNAL(constUlongPointerSignal(const unsigned long *)),
       
  2130                            SLOT(constUlongPointerSlot(const ulong *))));
       
  2131     QVERIFY(object.connect(&object,
       
  2132                            SIGNAL(constUlongPointerSignal(const ulong *)),
       
  2133                            SLOT(constUlongPointerSlot(const unsigned long *))));
       
  2134 
       
  2135     // struct, class, and enum are optional
       
  2136     QVERIFY(object.connect(&object,
       
  2137                            SIGNAL(structSignal(struct Struct)),
       
  2138                            SLOT(structSlot(struct Struct))));
       
  2139     QVERIFY(object.connect(&object,
       
  2140                            SIGNAL(structSignal(Struct)),
       
  2141                            SLOT(structSlot(struct Struct))));
       
  2142     QVERIFY(object.connect(&object,
       
  2143                            SIGNAL(structSignal(struct Struct)),
       
  2144                            SLOT(structSlot(Struct))));
       
  2145     QVERIFY(object.connect(&object,
       
  2146                            SIGNAL(classSignal(class Class)),
       
  2147                            SLOT(classSlot(class Class))));
       
  2148     QVERIFY(object.connect(&object,
       
  2149                            SIGNAL(classSignal(Class)),
       
  2150                            SLOT(classSlot(class Class))));
       
  2151     QVERIFY(object.connect(&object,
       
  2152                            SIGNAL(classSignal(class Class)),
       
  2153                            SLOT(classSlot(Class))));
       
  2154     QVERIFY(object.connect(&object,
       
  2155                            SIGNAL(enumSignal(enum Enum)),
       
  2156                            SLOT(enumSlot(enum Enum))));
       
  2157     QVERIFY(object.connect(&object,
       
  2158                            SIGNAL(enumSignal(Enum)),
       
  2159                            SLOT(enumSlot(enum Enum))));
       
  2160     QVERIFY(object.connect(&object,
       
  2161                            SIGNAL(enumSignal(enum Enum)),
       
  2162                            SLOT(enumSlot(Enum))));
       
  2163 
       
  2164     QVERIFY(object.connect(&object,
       
  2165                            SIGNAL(structPointerSignal(struct Struct *)),
       
  2166                            SLOT(structPointerSlot(struct Struct *))));
       
  2167     QVERIFY(object.connect(&object,
       
  2168                            SIGNAL(structPointerSignal(Struct *)),
       
  2169                            SLOT(structPointerSlot(struct Struct *))));
       
  2170     QVERIFY(object.connect(&object,
       
  2171                            SIGNAL(structPointerSignal(struct Struct *)),
       
  2172                            SLOT(structPointerSlot(Struct *))));
       
  2173     QVERIFY(object.connect(&object,
       
  2174                            SIGNAL(classPointerSignal(class Class *)),
       
  2175                            SLOT(classPointerSlot(class Class *))));
       
  2176     QVERIFY(object.connect(&object,
       
  2177                            SIGNAL(classPointerSignal(Class *)),
       
  2178                            SLOT(classPointerSlot(class Class *))));
       
  2179     QVERIFY(object.connect(&object,
       
  2180                            SIGNAL(classPointerSignal(class Class *)),
       
  2181                            SLOT(classPointerSlot(Class *))));
       
  2182     QVERIFY(object.connect(&object,
       
  2183                            SIGNAL(enumPointerSignal(enum Enum *)),
       
  2184                            SLOT(enumPointerSlot(enum Enum *))));
       
  2185     QVERIFY(object.connect(&object,
       
  2186                            SIGNAL(enumPointerSignal(Enum *)),
       
  2187                            SLOT(enumPointerSlot(enum Enum *))));
       
  2188     QVERIFY(object.connect(&object,
       
  2189                            SIGNAL(enumPointerSignal(enum Enum *)),
       
  2190                            SLOT(enumPointerSlot(Enum *))));
       
  2191 
       
  2192     QVERIFY(object.connect(&object,
       
  2193                            SIGNAL(constStructPointerSignal(const struct Struct *)),
       
  2194                            SLOT(constStructPointerSlot(const struct Struct *))));
       
  2195     QVERIFY(object.connect(&object,
       
  2196                            SIGNAL(constStructPointerSignal(const Struct *)),
       
  2197                            SLOT(constStructPointerSlot(const struct Struct *))));
       
  2198     QVERIFY(object.connect(&object,
       
  2199                            SIGNAL(constStructPointerSignal(const struct Struct *)),
       
  2200                            SLOT(constStructPointerSlot(const Struct *))));
       
  2201     QVERIFY(object.connect(&object,
       
  2202                            SIGNAL(constClassPointerSignal(const class Class *)),
       
  2203                            SLOT(constClassPointerSlot(const class Class *))));
       
  2204     QVERIFY(object.connect(&object,
       
  2205                            SIGNAL(constClassPointerSignal(const Class *)),
       
  2206                            SLOT(constClassPointerSlot(const class Class *))));
       
  2207     QVERIFY(object.connect(&object,
       
  2208                            SIGNAL(constClassPointerSignal(const class Class *)),
       
  2209                            SLOT(constClassPointerSlot(const Class *))));
       
  2210     QVERIFY(object.connect(&object,
       
  2211                            SIGNAL(constEnumPointerSignal(const enum Enum *)),
       
  2212                            SLOT(constEnumPointerSlot(const enum Enum *))));
       
  2213     QVERIFY(object.connect(&object,
       
  2214                            SIGNAL(constEnumPointerSignal(const Enum *)),
       
  2215                            SLOT(constEnumPointerSlot(const enum Enum *))));
       
  2216     QVERIFY(object.connect(&object,
       
  2217                            SIGNAL(constEnumPointerSignal(const enum Enum *)),
       
  2218                            SLOT(constEnumPointerSlot(const Enum *))));
       
  2219 
       
  2220     QVERIFY(object.connect(&object,
       
  2221                            SIGNAL(constStructPointerSignal(struct Struct const *)),
       
  2222                            SLOT(constStructPointerSlot(struct Struct const *))));
       
  2223     QVERIFY(object.connect(&object,
       
  2224                            SIGNAL(constStructPointerSignal(Struct const *)),
       
  2225                            SLOT(constStructPointerSlot(struct Struct const *))));
       
  2226     QVERIFY(object.connect(&object,
       
  2227                            SIGNAL(constStructPointerSignal(struct Struct const *)),
       
  2228                            SLOT(constStructPointerSlot(Struct const *))));
       
  2229     QVERIFY(object.connect(&object,
       
  2230                            SIGNAL(constClassPointerSignal(class Class const *)),
       
  2231                            SLOT(constClassPointerSlot(class Class const *))));
       
  2232     QVERIFY(object.connect(&object,
       
  2233                            SIGNAL(constClassPointerSignal(Class const *)),
       
  2234                            SLOT(constClassPointerSlot(class Class const *))));
       
  2235     QVERIFY(object.connect(&object,
       
  2236                            SIGNAL(constClassPointerSignal(class Class const *)),
       
  2237                            SLOT(constClassPointerSlot(Class const *))));
       
  2238     QVERIFY(object.connect(&object,
       
  2239                            SIGNAL(constEnumPointerSignal(enum Enum const *)),
       
  2240                            SLOT(constEnumPointerSlot(enum Enum const *))));
       
  2241     QVERIFY(object.connect(&object,
       
  2242                            SIGNAL(constEnumPointerSignal(Enum const *)),
       
  2243                            SLOT(constEnumPointerSlot(enum Enum const *))));
       
  2244     QVERIFY(object.connect(&object,
       
  2245                            SIGNAL(constEnumPointerSignal(enum Enum const *)),
       
  2246                            SLOT(constEnumPointerSlot(Enum const *))));
       
  2247 
       
  2248     QVERIFY(object.connect(&object,
       
  2249                            SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
       
  2250                            SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
       
  2251     QVERIFY(object.connect(&object,
       
  2252                            SIGNAL(constStructPointerConstPointerSignal(const Struct * const *)),
       
  2253                            SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
       
  2254     QVERIFY(object.connect(&object,
       
  2255                            SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
       
  2256                            SLOT(constStructPointerConstPointerSlot(const Struct * const *))));
       
  2257     QVERIFY(object.connect(&object,
       
  2258                            SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
       
  2259                            SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
       
  2260     QVERIFY(object.connect(&object,
       
  2261                            SIGNAL(constClassPointerConstPointerSignal(const Class * const *)),
       
  2262                            SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
       
  2263     QVERIFY(object.connect(&object,
       
  2264                            SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
       
  2265                            SLOT(constClassPointerConstPointerSlot(const Class * const *))));
       
  2266     QVERIFY(object.connect(&object,
       
  2267                            SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
       
  2268                            SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
       
  2269     QVERIFY(object.connect(&object,
       
  2270                            SIGNAL(constEnumPointerConstPointerSignal(const Enum * const *)),
       
  2271                            SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
       
  2272     QVERIFY(object.connect(&object,
       
  2273                            SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
       
  2274                            SLOT(constEnumPointerConstPointerSlot(const Enum * const *))));
       
  2275 
       
  2276     QVERIFY(object.connect(&object,
       
  2277                            SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
       
  2278                            SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
       
  2279     QVERIFY(object.connect(&object,
       
  2280                            SIGNAL(constStructPointerConstPointerSignal(Struct const * const *)),
       
  2281                            SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
       
  2282     QVERIFY(object.connect(&object,
       
  2283                            SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
       
  2284                            SLOT(constStructPointerConstPointerSlot(Struct const * const *))));
       
  2285     QVERIFY(object.connect(&object,
       
  2286                            SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
       
  2287                            SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
       
  2288     QVERIFY(object.connect(&object,
       
  2289                            SIGNAL(constClassPointerConstPointerSignal(Class const * const *)),
       
  2290                            SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
       
  2291     QVERIFY(object.connect(&object,
       
  2292                            SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
       
  2293                            SLOT(constClassPointerConstPointerSlot(Class const * const *))));
       
  2294     QVERIFY(object.connect(&object,
       
  2295                            SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
       
  2296                            SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
       
  2297     QVERIFY(object.connect(&object,
       
  2298                            SIGNAL(constEnumPointerConstPointerSignal(Enum const * const *)),
       
  2299                            SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
       
  2300     QVERIFY(object.connect(&object,
       
  2301                            SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
       
  2302                            SLOT(constEnumPointerConstPointerSlot(Enum const * const *))));
       
  2303 
       
  2304     QVERIFY(object.connect(&object,
       
  2305                            SIGNAL(unsignedintSignal(unsigned int)),
       
  2306                            SLOT(unsignedintSlot(unsigned int))));
       
  2307     QVERIFY(object.connect(&object,
       
  2308                            SIGNAL(unsignedSignal(unsigned)),
       
  2309                            SLOT(unsignedSlot(unsigned))));
       
  2310     QVERIFY(object.connect(&object,
       
  2311                            SIGNAL(unsignedSignal(unsigned)),
       
  2312                            SLOT(uintSlot(uint))));
       
  2313     QVERIFY(object.connect(&object,
       
  2314                            SIGNAL(unsignedlongSignal(unsigned long)),
       
  2315                            SLOT(unsignedlongSlot(unsigned long))));
       
  2316     QVERIFY(object.connect(&object,
       
  2317                            SIGNAL(unsignedlonglongSignal(quint64)),
       
  2318                            SLOT(unsignedlonglongSlot(quint64))));
       
  2319     QVERIFY(object.connect(&object,
       
  2320                            SIGNAL(unsignedlongintSignal(unsigned long int)),
       
  2321                            SLOT(unsignedlongintSlot(unsigned long int))));
       
  2322     QVERIFY(object.connect(&object,
       
  2323                            SIGNAL(unsignedshortSignal(unsigned short)),
       
  2324                            SLOT(unsignedshortSlot(unsigned short))));
       
  2325     QVERIFY(object.connect(&object,
       
  2326                            SIGNAL(unsignedcharSignal(unsigned char)),
       
  2327                            SLOT(unsignedcharSlot(unsigned char))));
       
  2328 
       
  2329 
       
  2330 }
       
  2331 
       
  2332 class SiblingDeleter : public QObject
       
  2333 {
       
  2334 public:
       
  2335     inline SiblingDeleter(QObject *sibling, QObject *parent)
       
  2336         : QObject(parent), sibling(sibling) {}
       
  2337     inline virtual ~SiblingDeleter() { delete sibling; }
       
  2338 
       
  2339 private:
       
  2340     QPointer<QObject> sibling;
       
  2341 };
       
  2342 
       
  2343 
       
  2344 void tst_QObject::childDeletesItsSibling()
       
  2345 {
       
  2346     QObject *commonParent = new QObject(0);
       
  2347     QPointer<QObject> child = new QObject(0);
       
  2348     QPointer<QObject> siblingDeleter = new SiblingDeleter(child, commonParent);
       
  2349     child->setParent(commonParent);
       
  2350     delete commonParent; // don't crash
       
  2351     QVERIFY(!child);
       
  2352     QVERIFY(!siblingDeleter);
       
  2353 }
       
  2354 
       
  2355 void tst_QObject::floatProperty()
       
  2356 {
       
  2357     PropertyObject obj;
       
  2358     const int idx = obj.metaObject()->indexOfProperty("myFloat");
       
  2359     QVERIFY(idx > 0);
       
  2360     QMetaProperty prop = obj.metaObject()->property(idx);
       
  2361     QVERIFY(prop.isValid());
       
  2362     QVERIFY(prop.type() == uint(QMetaType::type("float")));
       
  2363     QVERIFY(!prop.write(&obj, QVariant("Hello")));
       
  2364     QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
       
  2365     QVariant v = prop.read(&obj);
       
  2366     QVERIFY(int(v.userType()) == QMetaType::Float);
       
  2367     QVERIFY(qVariantValue<float>(v) == 128.0f);
       
  2368 }
       
  2369 
       
  2370 void tst_QObject::qrealProperty()
       
  2371 {
       
  2372     PropertyObject obj;
       
  2373     const int idx = obj.metaObject()->indexOfProperty("myQReal");
       
  2374     QVERIFY(idx > 0);
       
  2375     QMetaProperty prop = obj.metaObject()->property(idx);
       
  2376     QVERIFY(prop.isValid());
       
  2377     QVERIFY(prop.type() == uint(QMetaType::type("qreal")));
       
  2378     QVERIFY(!prop.write(&obj, QVariant("Hello")));
       
  2379 
       
  2380     QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
       
  2381     QVariant v = prop.read(&obj);
       
  2382     QCOMPARE(v.userType(), qMetaTypeId<qreal>());
       
  2383     QVERIFY(qVariantValue<qreal>(v) == 128.0);
       
  2384 
       
  2385     QVERIFY(prop.write(&obj, qVariantFromValue(double(127))));
       
  2386     v = prop.read(&obj);
       
  2387     QCOMPARE(v.userType(), qMetaTypeId<qreal>());
       
  2388     QVERIFY(qVariantValue<qreal>(v) == 127.0);
       
  2389 }
       
  2390 
       
  2391 class DynamicPropertyObject : public PropertyObject
       
  2392 {
       
  2393 public:
       
  2394     inline DynamicPropertyObject() {}
       
  2395 
       
  2396     inline virtual bool event(QEvent *e) {
       
  2397         if (e->type() == QEvent::DynamicPropertyChange) {
       
  2398             changedDynamicProperties.append(static_cast<QDynamicPropertyChangeEvent *>(e)->propertyName());
       
  2399         }
       
  2400         return QObject::event(e);
       
  2401     }
       
  2402 
       
  2403     QList<QByteArray> changedDynamicProperties;
       
  2404 };
       
  2405 
       
  2406 void tst_QObject::dynamicProperties()
       
  2407 {
       
  2408     DynamicPropertyObject obj;
       
  2409 
       
  2410     QVERIFY(obj.dynamicPropertyNames().isEmpty());
       
  2411 
       
  2412     QVERIFY(obj.setProperty("number", 42));
       
  2413     QVERIFY(obj.changedDynamicProperties.isEmpty());
       
  2414     QCOMPARE(obj.property("number").toInt(), 42);
       
  2415 
       
  2416     QVERIFY(!obj.setProperty("number", "invalid string"));
       
  2417     QVERIFY(obj.changedDynamicProperties.isEmpty());
       
  2418 
       
  2419     QVERIFY(!obj.setProperty("myuserproperty", "Hello"));
       
  2420     QCOMPARE(obj.changedDynamicProperties.count(), 1);
       
  2421     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
       
  2422     obj.changedDynamicProperties.clear();
       
  2423 
       
  2424     QCOMPARE(obj.property("myuserproperty").toString(), QString("Hello"));
       
  2425 
       
  2426     QCOMPARE(obj.dynamicPropertyNames().count(), 1);
       
  2427     QCOMPARE(obj.dynamicPropertyNames().first(), QByteArray("myuserproperty"));
       
  2428 
       
  2429     QVERIFY(!obj.setProperty("myuserproperty", QVariant()));
       
  2430 
       
  2431     QCOMPARE(obj.changedDynamicProperties.count(), 1);
       
  2432     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
       
  2433     obj.changedDynamicProperties.clear();
       
  2434 
       
  2435     QVERIFY(obj.property("myuserproperty").isNull());
       
  2436 
       
  2437     QVERIFY(obj.dynamicPropertyNames().isEmpty());
       
  2438 }
       
  2439 
       
  2440 void tst_QObject::recursiveSignalEmission()
       
  2441 {
       
  2442 #if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86)
       
  2443     QSKIP("Emulator builds in Symbian do not support launching processes linking to Qt", SkipAll);
       
  2444 #elif defined(QT_NO_PROCESS)
       
  2445     QSKIP("Test requires QProcess", SkipAll);
       
  2446 #else
       
  2447     QProcess proc;
       
  2448     proc.start("./signalbug");
       
  2449     QVERIFY(proc.waitForFinished());
       
  2450     QVERIFY(proc.exitStatus() == QProcess::NormalExit);
       
  2451     QCOMPARE(proc.exitCode(), 0);
       
  2452 #endif
       
  2453 }
       
  2454 
       
  2455 void tst_QObject::blockingQueuedConnection()
       
  2456 {
       
  2457     {
       
  2458         SenderObject sender;
       
  2459 
       
  2460         MoveToThreadThread thread;
       
  2461         ReceiverObject receiver;
       
  2462         receiver.moveToThread(&thread);
       
  2463         thread.start();
       
  2464 
       
  2465         receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1()), Qt::BlockingQueuedConnection);
       
  2466         sender.emitSignal1();
       
  2467         QVERIFY(receiver.called(1));
       
  2468 
       
  2469         receiver.reset();
       
  2470         QVERIFY(QMetaObject::invokeMethod(&receiver, "slot1", Qt::BlockingQueuedConnection));
       
  2471         QVERIFY(receiver.called(1));
       
  2472 
       
  2473         thread.quit();
       
  2474         QVERIFY(thread.wait());
       
  2475     }
       
  2476 }
       
  2477 
       
  2478 class EventSpy : public QObject
       
  2479 {
       
  2480     Q_OBJECT
       
  2481 
       
  2482 public:
       
  2483     typedef QList<QPair<QObject *, QEvent::Type> > EventList;
       
  2484 
       
  2485     EventSpy(QObject *parent = 0)
       
  2486         : QObject(parent)
       
  2487     { }
       
  2488 
       
  2489     EventList eventList()
       
  2490     {
       
  2491         return events;
       
  2492     }
       
  2493 
       
  2494     void clear()
       
  2495     {
       
  2496         events.clear();
       
  2497     }
       
  2498 
       
  2499     bool eventFilter(QObject *object, QEvent *event)
       
  2500     {
       
  2501         events.append(qMakePair(object, event->type()));
       
  2502         return false;
       
  2503     }
       
  2504 
       
  2505 private:
       
  2506     EventList events;
       
  2507 };
       
  2508 
       
  2509 void tst_QObject::compatibilityChildInsertedEvents()
       
  2510 {
       
  2511     EventSpy::EventList expected;
       
  2512 
       
  2513     {
       
  2514         // no children created, so we expect no events
       
  2515         QObject object;
       
  2516         EventSpy spy;
       
  2517         object.installEventFilter(&spy);
       
  2518 
       
  2519         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
       
  2520 
       
  2521         QCoreApplication::processEvents();
       
  2522 
       
  2523         expected =
       
  2524             EventSpy::EventList()
       
  2525             << qMakePair(&object, QEvent::Type(QEvent::User + 1));
       
  2526         QCOMPARE(spy.eventList(), expected);
       
  2527     }
       
  2528 
       
  2529     {
       
  2530         // 2 children, so we expect 2 ChildAdded and 2 ChildInserted events
       
  2531         QObject object;
       
  2532         EventSpy spy;
       
  2533         object.installEventFilter(&spy);
       
  2534 
       
  2535         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
       
  2536 
       
  2537         QObject child1(&object);
       
  2538         QObject child2;
       
  2539         child2.setParent(&object);
       
  2540 
       
  2541         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2)));
       
  2542 
       
  2543         expected =
       
  2544             EventSpy::EventList()
       
  2545             << qMakePair(&object, QEvent::ChildAdded)
       
  2546             << qMakePair(&object, QEvent::ChildAdded);
       
  2547         QCOMPARE(spy.eventList(), expected);
       
  2548         spy.clear();
       
  2549 
       
  2550         QCoreApplication::processEvents();
       
  2551 
       
  2552         expected =
       
  2553             EventSpy::EventList()
       
  2554 #ifdef QT_HAS_QT3SUPPORT
       
  2555             << qMakePair(&object, QEvent::ChildInsertedRequest)
       
  2556             << qMakePair(&object, QEvent::ChildInserted)
       
  2557             << qMakePair(&object, QEvent::ChildInserted)
       
  2558 #endif
       
  2559             << qMakePair(&object, QEvent::Type(QEvent::User + 1))
       
  2560             << qMakePair(&object, QEvent::Type(QEvent::User + 2));
       
  2561         QCOMPARE(spy.eventList(), expected);
       
  2562     }
       
  2563 
       
  2564     {
       
  2565         // 2 children, but one is reparented away, so we expect:
       
  2566         // 2 ChildAdded, 1 ChildRemoved, and 1 ChildInserted
       
  2567         QObject object;
       
  2568         EventSpy spy;
       
  2569         object.installEventFilter(&spy);
       
  2570 
       
  2571         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
       
  2572 
       
  2573         QObject child1(&object);
       
  2574         QObject child2;
       
  2575         child2.setParent(&object);
       
  2576         child2.setParent(0);
       
  2577 
       
  2578         QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2)));
       
  2579 
       
  2580         expected =
       
  2581             EventSpy::EventList()
       
  2582             << qMakePair(&object, QEvent::ChildAdded)
       
  2583             << qMakePair(&object, QEvent::ChildAdded)
       
  2584             << qMakePair(&object, QEvent::ChildRemoved);
       
  2585         QCOMPARE(spy.eventList(), expected);
       
  2586         spy.clear();
       
  2587 
       
  2588         QCoreApplication::processEvents();
       
  2589 
       
  2590         expected =
       
  2591             EventSpy::EventList()
       
  2592 #ifdef QT_HAS_QT3SUPPORT
       
  2593             << qMakePair(&object, QEvent::ChildInsertedRequest)
       
  2594             << qMakePair(&object, QEvent::ChildInserted)
       
  2595 #endif
       
  2596             << qMakePair(&object, QEvent::Type(QEvent::User + 1))
       
  2597             << qMakePair(&object, QEvent::Type(QEvent::User + 2));
       
  2598         QCOMPARE(spy.eventList(), expected);
       
  2599     }
       
  2600 }
       
  2601 
       
  2602 void tst_QObject::installEventFilter()
       
  2603 {
       
  2604     QEvent event(QEvent::User);
       
  2605     EventSpy::EventList expected;
       
  2606 
       
  2607     QObject object;
       
  2608     EventSpy spy;
       
  2609     object.installEventFilter(&spy);
       
  2610 
       
  2611     // nothing special, should just work
       
  2612     QCoreApplication::sendEvent(&object, &event);
       
  2613     expected =
       
  2614         EventSpy::EventList()
       
  2615         << qMakePair(&object, QEvent::User);
       
  2616     QCOMPARE(spy.eventList(), expected);
       
  2617     spy.clear();
       
  2618 
       
  2619     // moving the filter causes QCoreApplication to skip the filter
       
  2620     spy.moveToThread(0);
       
  2621     QTest::ignoreMessage(QtWarningMsg, "QCoreApplication: Object event filter cannot be in a different thread.");
       
  2622     QCoreApplication::sendEvent(&object, &event);
       
  2623     QVERIFY(spy.eventList().isEmpty());
       
  2624 
       
  2625     // move it back, and the filter works again
       
  2626     spy.moveToThread(object.thread());
       
  2627     QCoreApplication::sendEvent(&object, &event);
       
  2628     expected =
       
  2629         EventSpy::EventList()
       
  2630         << qMakePair(&object, QEvent::User);
       
  2631     QCOMPARE(spy.eventList(), expected);
       
  2632     spy.clear();
       
  2633 
       
  2634     // cannot install an event filter that lives in a different thread
       
  2635     object.removeEventFilter(&spy);
       
  2636     spy.moveToThread(0);
       
  2637     QTest::ignoreMessage(QtWarningMsg, "QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
       
  2638     object.installEventFilter(&spy);
       
  2639     QCoreApplication::sendEvent(&object, &event);
       
  2640     QVERIFY(spy.eventList().isEmpty());
       
  2641 }
       
  2642 
       
  2643 class DeleteObject : public QObject
       
  2644 {
       
  2645     Q_OBJECT
       
  2646 
       
  2647 public slots:
       
  2648     void deleteSelf()
       
  2649     {
       
  2650         delete this;
       
  2651     }
       
  2652 
       
  2653     void relaySignalAndProcessEvents()
       
  2654     {
       
  2655         emit relayedSignal();
       
  2656         QCoreApplication::processEvents();
       
  2657     }
       
  2658 
       
  2659 signals:
       
  2660     void relayedSignal();
       
  2661 };
       
  2662 
       
  2663 void tst_QObject::deleteSelfInSlot()
       
  2664 {
       
  2665     {
       
  2666         SenderObject sender;
       
  2667         DeleteObject *receiver = new DeleteObject();
       
  2668         receiver->connect(&sender,
       
  2669                           SIGNAL(signal1()),
       
  2670                           SLOT(deleteSelf()),
       
  2671                           Qt::BlockingQueuedConnection);
       
  2672 
       
  2673         QThread thread;
       
  2674         receiver->moveToThread(&thread);
       
  2675         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
       
  2676         thread.start();
       
  2677 
       
  2678         QPointer<DeleteObject> p = receiver;
       
  2679         sender.emitSignal1();
       
  2680         QVERIFY(p.isNull());
       
  2681 
       
  2682         QVERIFY(thread.wait(10000));
       
  2683     }
       
  2684 
       
  2685     {
       
  2686         SenderObject sender;
       
  2687         DeleteObject *receiver = new DeleteObject();
       
  2688         receiver->connect(&sender,
       
  2689                           SIGNAL(signal1()),
       
  2690                           SLOT(relaySignalAndProcessEvents()),
       
  2691                           Qt::BlockingQueuedConnection);
       
  2692         receiver->connect(receiver,
       
  2693                           SIGNAL(relayedSignal()),
       
  2694                           SLOT(deleteSelf()),
       
  2695                           Qt::QueuedConnection);
       
  2696 
       
  2697         QThread thread;
       
  2698         receiver->moveToThread(&thread);
       
  2699         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
       
  2700         thread.start();
       
  2701 
       
  2702         QPointer<DeleteObject> p = receiver;
       
  2703         sender.emitSignal1();
       
  2704         QVERIFY(p.isNull());
       
  2705 
       
  2706         QVERIFY(thread.wait(10000));
       
  2707     }
       
  2708 }
       
  2709 
       
  2710 class DisconnectObject : public QObject
       
  2711 {
       
  2712     Q_OBJECT
       
  2713 
       
  2714 public slots:
       
  2715     void disconnectSelf()
       
  2716     {
       
  2717         disconnect(sender(), 0, this, 0);
       
  2718     }
       
  2719 
       
  2720     void relaySignalAndProcessEvents()
       
  2721     {
       
  2722         emit relayedSignal();
       
  2723         QCoreApplication::processEvents();
       
  2724     }
       
  2725 
       
  2726 signals:
       
  2727     void relayedSignal();
       
  2728 };
       
  2729 
       
  2730 void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit()
       
  2731 {
       
  2732     {
       
  2733         SenderObject sender;
       
  2734         DisconnectObject *receiver = new DisconnectObject();
       
  2735         receiver->connect(&sender, SIGNAL(signal1()), SLOT(disconnectSelf()));
       
  2736         sender.emitSignal1AfterRecursion();
       
  2737         delete receiver;
       
  2738     }
       
  2739 
       
  2740     {
       
  2741         SenderObject sender;
       
  2742         DisconnectObject *receiver = new DisconnectObject();
       
  2743         receiver->connect(&sender,
       
  2744                           SIGNAL(signal1()),
       
  2745                           SLOT(disconnectSelf()),
       
  2746                           Qt::BlockingQueuedConnection);
       
  2747 
       
  2748         QThread thread;
       
  2749         receiver->moveToThread(&thread);
       
  2750         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
       
  2751         thread.start();
       
  2752 
       
  2753         QPointer<DisconnectObject> p = receiver;
       
  2754         sender.emitSignal1();
       
  2755         QVERIFY(!p.isNull());
       
  2756 
       
  2757         receiver->deleteLater();
       
  2758 
       
  2759         QVERIFY(thread.wait(10000));
       
  2760         QVERIFY(p.isNull());
       
  2761     }
       
  2762 
       
  2763     {
       
  2764         SenderObject sender;
       
  2765         DisconnectObject *receiver = new DisconnectObject();
       
  2766         receiver->connect(&sender,
       
  2767                           SIGNAL(signal1()),
       
  2768                           SLOT(relaySignalAndProcessEvents()),
       
  2769                           Qt::BlockingQueuedConnection);
       
  2770         receiver->connect(receiver,
       
  2771                           SIGNAL(relayedSignal()),
       
  2772                           SLOT(disconnectSelf()),
       
  2773                           Qt::QueuedConnection);
       
  2774 
       
  2775         QThread thread;
       
  2776         receiver->moveToThread(&thread);
       
  2777         thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
       
  2778         thread.start();
       
  2779 
       
  2780         QPointer<DisconnectObject> p = receiver;
       
  2781         sender.emitSignal1();
       
  2782         QVERIFY(!p.isNull());
       
  2783 
       
  2784         receiver->deleteLater();
       
  2785 
       
  2786         QVERIFY(thread.wait(10000));
       
  2787         QVERIFY(p.isNull());
       
  2788     }
       
  2789 }
       
  2790 
       
  2791 void tst_QObject::dumpObjectInfo()
       
  2792 {
       
  2793     QObject a, b;
       
  2794     QObject::connect(&a, SIGNAL(destroyed(QObject *)), &b, SLOT(deleteLater()));
       
  2795     a.disconnect(&b);
       
  2796     a.dumpObjectInfo(); // should not crash
       
  2797 }
       
  2798 
       
  2799 class ConnectToSender : public QObject
       
  2800 { Q_OBJECT
       
  2801     public slots:
       
  2802         void uselessSlot() { count++; }
       
  2803 
       
  2804         void harmfullSlot() {
       
  2805             //this used to crash
       
  2806             connect(sender(), SIGNAL(signal4()), this, SLOT(uselessSlot()));
       
  2807             //play a little bit with the memory in order to really get a segfault.
       
  2808             connect(sender(), SIGNAL(signal1()), this, SLOT(uselessSlot()));
       
  2809             QList<double>() << 45 << 78 << 65 << 121 << 45 << 78 << 12;
       
  2810         }
       
  2811     public:
       
  2812         int count;
       
  2813 };
       
  2814 
       
  2815 void tst_QObject::connectToSender()
       
  2816 {
       
  2817     SenderObject s;
       
  2818     ConnectToSender r;
       
  2819     r.count = 0;
       
  2820     QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(harmfullSlot()));
       
  2821     QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(uselessSlot()));
       
  2822 
       
  2823     s.emitSignal1();
       
  2824 
       
  2825     QCOMPARE(r.count, 1);
       
  2826     s.emitSignal4();
       
  2827     QCOMPARE(r.count, 2);
       
  2828 }
       
  2829 
       
  2830 void tst_QObject::qobjectConstCast()
       
  2831 {
       
  2832     FooObject obj;
       
  2833 
       
  2834     QObject *ptr = &obj;
       
  2835     const QObject *cptr = &obj;
       
  2836 
       
  2837     QVERIFY(qobject_cast<FooObject *>(ptr));
       
  2838     QVERIFY(qobject_cast<const FooObject *>(cptr));
       
  2839 }
       
  2840 
       
  2841 void tst_QObject::uniqConnection()
       
  2842 {
       
  2843     SenderObject *s = new SenderObject;
       
  2844     ReceiverObject *r1 = new ReceiverObject;
       
  2845     ReceiverObject *r2 = new ReceiverObject;
       
  2846     r1->reset();
       
  2847     r2->reset();
       
  2848     ReceiverObject::sequence = 0;
       
  2849 
       
  2850     QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) , Qt::UniqueConnection) );
       
  2851     QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) , Qt::UniqueConnection) );
       
  2852     QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
       
  2853     QVERIFY( connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
       
  2854 
       
  2855     s->emitSignal1();
       
  2856     s->emitSignal2();
       
  2857     s->emitSignal3();
       
  2858     s->emitSignal4();
       
  2859 
       
  2860     QCOMPARE( r1->count_slot1, 1 );
       
  2861     QCOMPARE( r1->count_slot2, 0 );
       
  2862     QCOMPARE( r1->count_slot3, 2 );
       
  2863     QCOMPARE( r1->count_slot4, 0 );
       
  2864     QCOMPARE( r2->count_slot1, 1 );
       
  2865     QCOMPARE( r2->count_slot2, 0 );
       
  2866     QCOMPARE( r2->count_slot3, 0 );
       
  2867     QCOMPARE( r2->count_slot4, 0 );
       
  2868     QCOMPARE( r1->sequence_slot1, 1 );
       
  2869     QCOMPARE( r2->sequence_slot1, 2 );
       
  2870     QCOMPARE( r1->sequence_slot3, 4 );
       
  2871 
       
  2872     r1->reset();
       
  2873     r2->reset();
       
  2874     ReceiverObject::sequence = 0;
       
  2875 
       
  2876     QVERIFY( connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
       
  2877     QVERIFY( connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
       
  2878     QVERIFY(!connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
       
  2879     QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
       
  2880     QVERIFY(!connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
       
  2881 
       
  2882     s->emitSignal4();
       
  2883     QCOMPARE( r1->count_slot4, 1 );
       
  2884     QCOMPARE( r2->count_slot4, 1 );
       
  2885     QCOMPARE( r1->sequence_slot4, 1 );
       
  2886     QCOMPARE( r2->sequence_slot4, 2 );
       
  2887 
       
  2888     r1->reset();
       
  2889     r2->reset();
       
  2890     ReceiverObject::sequence = 0;
       
  2891 
       
  2892     connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
       
  2893 
       
  2894     s->emitSignal4();
       
  2895     QCOMPARE( r1->count_slot4, 2 );
       
  2896     QCOMPARE( r2->count_slot4, 1 );
       
  2897     QCOMPARE( r1->sequence_slot4, 3 );
       
  2898     QCOMPARE( r2->sequence_slot4, 2 );
       
  2899 
       
  2900     delete s;
       
  2901     delete r1;
       
  2902     delete r2;
       
  2903 }
       
  2904 
       
  2905 void tst_QObject::interfaceIid()
       
  2906 {
       
  2907     QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),
       
  2908              QByteArray(Bleh_iid));
       
  2909     QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()),
       
  2910              QByteArray("com.qtest.foobar"));
       
  2911     QCOMPARE(QByteArray(qobject_interface_iid<FooObject *>()),
       
  2912              QByteArray());
       
  2913 }
       
  2914 
       
  2915 void tst_QObject::deleteQObjectWhenDeletingEvent()
       
  2916 {
       
  2917     //this is related to task 259514
       
  2918     //before the fix this used to dead lock when the QObject from the event was destroyed
       
  2919 
       
  2920     struct MyEvent : public QEvent
       
  2921     {
       
  2922         MyEvent() : QEvent(QEvent::User) { }
       
  2923         QObject obj;
       
  2924     };
       
  2925 
       
  2926     QObject o;
       
  2927     QApplication::postEvent(&o, new MyEvent);
       
  2928     QCoreApplication::removePostedEvents(&o); // here you would get a deadlock
       
  2929 }
       
  2930 
       
  2931 class OverloadObject : public QObject
       
  2932 {
       
  2933     friend class tst_QObject;
       
  2934     Q_OBJECT
       
  2935     signals:
       
  2936         void sig(int i, char c, qreal m = 12);
       
  2937         void sig(int i, int j = 12);
       
  2938         void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const;
       
  2939         void other(int a = 0);
       
  2940         void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0);
       
  2941         void sig(double r = 0.5);
       
  2942     public slots:
       
  2943         void slo(int i, int j = 43)
       
  2944         {
       
  2945             s_num += 1;
       
  2946             i1_num = i;
       
  2947             i2_num = j;
       
  2948         }
       
  2949         void slo(QObject *o, QObject *p = qApp, QObject *q = qApp, QObject *r = qApp)
       
  2950         {
       
  2951             s_num += 10;
       
  2952             o1_obj = o;
       
  2953             o2_obj = p;
       
  2954             o3_obj = q;
       
  2955             o4_obj = r;
       
  2956         }
       
  2957         void slo()
       
  2958         {
       
  2959             s_num += 100;
       
  2960         }
       
  2961 
       
  2962     public:
       
  2963         int s_num;
       
  2964         int i1_num;
       
  2965         int i2_num;
       
  2966         QObject *o1_obj;
       
  2967         QObject *o2_obj;
       
  2968         QObject *o3_obj;
       
  2969         QObject *o4_obj;
       
  2970 };
       
  2971 
       
  2972 void tst_QObject::overloads()
       
  2973 {
       
  2974     OverloadObject obj1;
       
  2975     OverloadObject obj2;
       
  2976     QObject obj3;
       
  2977     obj1.s_num = 0;
       
  2978     obj2.s_num = 0;
       
  2979 
       
  2980     connect (&obj1, SIGNAL(sig(int)) , &obj1, SLOT(slo(int)));
       
  2981     connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *)) , &obj1, SLOT(slo(QObject * , QObject *, QObject *)));
       
  2982 
       
  2983     connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *, QObject *)) , &obj2, SLOT(slo(QObject * , QObject *, QObject *)));
       
  2984     connect (&obj1, SIGNAL(sig(QObject *)) , &obj2, SLOT(slo()));
       
  2985     connect (&obj1, SIGNAL(sig(int, int)) , &obj2, SLOT(slo(int, int)));
       
  2986 
       
  2987     emit obj1.sig(0.5); //connected to nothing
       
  2988     emit obj1.sig(1, 'a'); //connected to nothing
       
  2989     QCOMPARE(obj1.s_num, 0);
       
  2990     QCOMPARE(obj2.s_num, 0);
       
  2991 
       
  2992     emit obj1.sig(1); //this signal is connected
       
  2993     QCOMPARE(obj1.s_num, 1);
       
  2994     QCOMPARE(obj1.i1_num, 1);
       
  2995     QCOMPARE(obj1.i2_num, 43); //default argument of the slot
       
  2996 
       
  2997     QCOMPARE(obj2.s_num, 1);
       
  2998     QCOMPARE(obj2.i1_num, 1);
       
  2999     QCOMPARE(obj2.i2_num, 12); //default argument of the signal
       
  3000 
       
  3001 
       
  3002     emit obj1.sig(&obj2); //this signal is conencted to obj2
       
  3003     QCOMPARE(obj1.s_num, 1);
       
  3004     QCOMPARE(obj2.s_num, 101);
       
  3005     emit obj1.sig(&obj2, &obj3); //this signal is connected
       
  3006     QCOMPARE(obj1.s_num, 11);
       
  3007     QCOMPARE(obj1.o1_obj, &obj2);
       
  3008     QCOMPARE(obj1.o2_obj, &obj3);
       
  3009     QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal
       
  3010     QCOMPARE(obj1.o4_obj, qApp); //default arg of the slot
       
  3011 
       
  3012     QCOMPARE(obj2.s_num, 111);
       
  3013     QCOMPARE(obj2.o1_obj, &obj2);
       
  3014     QCOMPARE(obj2.o2_obj, &obj3);
       
  3015     QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal
       
  3016     QCOMPARE(obj2.o4_obj, qApp); //default arg of the slot
       
  3017 }
       
  3018 
       
  3019 QTEST_MAIN(tst_QObject)
       
  3020 #include "tst_qobject.moc"