tests/auto/qsharedpointer/tst_qsharedpointer.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 #define QT_SHAREDPOINTER_TRACK_POINTERS
       
    43 #include "qsharedpointer.h"
       
    44 #include <QtTest/QtTest>
       
    45 #include <QtCore/QThread>
       
    46 #include <QtCore/QVector>
       
    47 
       
    48 #include "externaltests.h"
       
    49 #include "wrapper.h"
       
    50 
       
    51 #include <stdlib.h>
       
    52 #include <time.h>
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 namespace QtSharedPointer {
       
    56     Q_CORE_EXPORT void internalSafetyCheckCleanCheck();
       
    57 }
       
    58 QT_END_NAMESPACE
       
    59 
       
    60 #ifdef Q_OS_SYMBIAN
       
    61 #define SRCDIR "."
       
    62 #endif
       
    63 
       
    64 class tst_QSharedPointer: public QObject
       
    65 {
       
    66     Q_OBJECT
       
    67 
       
    68 private slots:
       
    69     void basics_data();
       
    70     void basics();
       
    71     void swap();
       
    72     void forwardDeclaration1();
       
    73     void forwardDeclaration2();
       
    74     void memoryManagement();
       
    75     void downCast();
       
    76     void upCast();
       
    77     void qobjectWeakManagement();
       
    78     void noSharedPointerFromWeakQObject();
       
    79     void weakQObjectFromSharedPointer();
       
    80     void objectCast();
       
    81     void differentPointers();
       
    82     void virtualBaseDifferentPointers();
       
    83 #ifndef QTEST_NO_RTTI
       
    84     void dynamicCast();
       
    85     void dynamicCastDifferentPointers();
       
    86     void dynamicCastVirtualBase();
       
    87     void dynamicCastFailure();
       
    88 #endif
       
    89     void constCorrectness();
       
    90     void customDeleter();
       
    91     void creating();
       
    92     void creatingQObject();
       
    93     void mixTrackingPointerCode();
       
    94     void threadStressTest_data();
       
    95     void threadStressTest();
       
    96     void validConstructs();
       
    97     void invalidConstructs_data();
       
    98     void invalidConstructs();
       
    99 
       
   100 public slots:
       
   101     void cleanup() { check(); }
       
   102 
       
   103 public:
       
   104     inline void check()
       
   105     {
       
   106 #ifdef QT_BUILD_INTERNAL
       
   107         QtSharedPointer::internalSafetyCheckCleanCheck();
       
   108 #endif
       
   109     }
       
   110 };
       
   111 
       
   112 template <typename Base>
       
   113 class RefCountHack: public Base
       
   114 {
       
   115 public:
       
   116     using Base::d;
       
   117 };
       
   118 template<typename Base> static inline
       
   119 QtSharedPointer::ExternalRefCountData *refCountData(const Base &b)
       
   120 { return static_cast<const RefCountHack<Base> *>(&b)->d; }
       
   121 
       
   122 class Data
       
   123 {
       
   124 public:
       
   125     static int destructorCounter;
       
   126     static int generationCounter;
       
   127     int generation;
       
   128 
       
   129     Data() : generation(++generationCounter)
       
   130     { }
       
   131 
       
   132     virtual ~Data()
       
   133     {
       
   134         Q_ASSERT_X(generation > 0, "tst_QSharedPointer", "Double deletion!");
       
   135         generation = 0;
       
   136         ++destructorCounter;
       
   137     }
       
   138 
       
   139     void doDelete()
       
   140     {
       
   141         delete this;
       
   142     }
       
   143 
       
   144     bool alsoDelete()
       
   145     {
       
   146         doDelete();
       
   147         return true;
       
   148     }
       
   149 
       
   150     virtual void virtualDelete()
       
   151     {
       
   152         delete this;
       
   153     }
       
   154 
       
   155     virtual int classLevel() { return 1; }
       
   156 };
       
   157 int Data::generationCounter = 0;
       
   158 int Data::destructorCounter = 0;
       
   159 
       
   160 void tst_QSharedPointer::basics_data()
       
   161 {
       
   162     QTest::addColumn<bool>("isNull");
       
   163     QTest::newRow("null") << true;
       
   164     QTest::newRow("non-null") << false;
       
   165 }
       
   166 
       
   167 void tst_QSharedPointer::basics()
       
   168 {
       
   169     {
       
   170         QSharedPointer<Data> ptr;
       
   171         QWeakPointer<Data> weakref;
       
   172 
       
   173         QCOMPARE(sizeof(ptr), 2*sizeof(void*));
       
   174         QCOMPARE(sizeof(weakref), 2*sizeof(void*));
       
   175     }
       
   176 
       
   177     QFETCH(bool, isNull);
       
   178     Data *aData = 0;
       
   179     if (!isNull)
       
   180         aData = new Data;
       
   181     Data *otherData = new Data;
       
   182     QSharedPointer<Data> ptr(aData);
       
   183 
       
   184     {
       
   185         // basic self tests
       
   186         QCOMPARE(ptr.isNull(), isNull);
       
   187         QCOMPARE(bool(ptr), !isNull);
       
   188         QCOMPARE(!ptr, isNull);
       
   189 
       
   190         QCOMPARE(ptr.data(), aData);
       
   191         QCOMPARE(ptr.operator->(), aData);
       
   192         Data &dataReference = *ptr;
       
   193         QCOMPARE(&dataReference, aData);
       
   194 
       
   195         QVERIFY(ptr == aData);
       
   196         QVERIFY(!(ptr != aData));
       
   197         QVERIFY(aData == ptr);
       
   198         QVERIFY(!(aData != ptr));
       
   199 
       
   200         QVERIFY(ptr != otherData);
       
   201         QVERIFY(otherData != ptr);
       
   202         QVERIFY(! (ptr == otherData));
       
   203         QVERIFY(! (otherData == ptr));
       
   204     }
       
   205     QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1);
       
   206     QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1);
       
   207 
       
   208     {
       
   209         // create another object:
       
   210         QSharedPointer<Data> otherCopy(otherData);
       
   211         QVERIFY(ptr != otherCopy);
       
   212         QVERIFY(otherCopy != ptr);
       
   213         QVERIFY(! (ptr == otherCopy));
       
   214         QVERIFY(! (otherCopy == ptr));
       
   215 
       
   216         // otherData is deleted here
       
   217     }
       
   218     QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1);
       
   219     QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1);
       
   220 
       
   221     {
       
   222         // create a copy:
       
   223         QSharedPointer<Data> copy(ptr);
       
   224         QVERIFY(copy == ptr);
       
   225         QVERIFY(ptr == copy);
       
   226         QVERIFY(! (copy != ptr));
       
   227         QVERIFY(! (ptr != copy));
       
   228         QCOMPARE(copy, ptr);
       
   229         QCOMPARE(ptr, copy);
       
   230 
       
   231         QCOMPARE(copy.isNull(), isNull);
       
   232         QCOMPARE(copy.data(), aData);
       
   233         QVERIFY(copy == aData);
       
   234     }
       
   235     QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1);
       
   236     QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1);
       
   237 
       
   238     {
       
   239         // create a weak reference:
       
   240         QWeakPointer<Data> weak(ptr);
       
   241         QCOMPARE(weak.isNull(), isNull);
       
   242         QCOMPARE(!weak, isNull);
       
   243         QCOMPARE(bool(weak), !isNull);
       
   244 
       
   245         QVERIFY(ptr == weak);
       
   246         QVERIFY(weak == ptr);
       
   247         QVERIFY(! (ptr != weak));
       
   248         QVERIFY(! (weak != ptr));
       
   249 
       
   250         // create another reference:
       
   251         QWeakPointer<Data> weak2(weak);
       
   252         QCOMPARE(weak2.isNull(), isNull);
       
   253         QCOMPARE(!weak2, isNull);
       
   254         QCOMPARE(bool(weak2), !isNull);
       
   255 
       
   256         QVERIFY(weak2 == weak);
       
   257         QVERIFY(weak == weak2);
       
   258         QVERIFY(! (weak2 != weak));
       
   259         QVERIFY(! (weak != weak2));
       
   260 
       
   261         // create a strong reference back:
       
   262         QSharedPointer<Data> strong(weak);
       
   263         QVERIFY(strong == weak);
       
   264         QVERIFY(strong == ptr);
       
   265         QCOMPARE(strong.data(), aData);
       
   266     }
       
   267     QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1);
       
   268     QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1);
       
   269 
       
   270     // aData is deleted here
       
   271 }
       
   272 
       
   273 void tst_QSharedPointer::swap()
       
   274 {
       
   275     QSharedPointer<int> p1, p2(new int(42)), control = p2;
       
   276     QVERIFY(p1 != control);
       
   277     QVERIFY(p1.isNull());
       
   278     QVERIFY(p2 == control);
       
   279     QVERIFY(!p2.isNull());
       
   280     QVERIFY(*p2 == 42);
       
   281 
       
   282     p1.swap(p2);
       
   283     QVERIFY(p1 == control);
       
   284     QVERIFY(!p1.isNull());
       
   285     QVERIFY(p2 != control);
       
   286     QVERIFY(p2.isNull());
       
   287     QVERIFY(*p1 == 42);
       
   288 
       
   289     p1.swap(p2);
       
   290     QVERIFY(p1 != control);
       
   291     QVERIFY(p1.isNull());
       
   292     QVERIFY(p2 == control);
       
   293     QVERIFY(!p2.isNull());
       
   294     QVERIFY(*p2 == 42);
       
   295 
       
   296     qSwap(p1, p2);
       
   297     QVERIFY(p1 == control);
       
   298     QVERIFY(!p1.isNull());
       
   299     QVERIFY(p2 != control);
       
   300     QVERIFY(p2.isNull());
       
   301     QVERIFY(*p1 == 42);
       
   302 }
       
   303 
       
   304 class ForwardDeclared;
       
   305 ForwardDeclared *forwardPointer();
       
   306 void externalForwardDeclaration();
       
   307 extern int forwardDeclaredDestructorRunCount;
       
   308 
       
   309 void tst_QSharedPointer::forwardDeclaration1()
       
   310 {
       
   311 #if defined(Q_CC_SUN) || defined(Q_CC_WINSCW) || defined(Q_CC_RVCT)
       
   312     QSKIP("This type of forward declaration is not valid with this compiler", SkipAll);
       
   313 #else
       
   314     externalForwardDeclaration();
       
   315 
       
   316     struct Wrapper { QSharedPointer<ForwardDeclared> pointer; };
       
   317 
       
   318     forwardDeclaredDestructorRunCount = 0;
       
   319     {
       
   320         Wrapper w;
       
   321         w.pointer = QSharedPointer<ForwardDeclared>(forwardPointer());
       
   322         QVERIFY(!w.pointer.isNull());
       
   323     }
       
   324     QCOMPARE(forwardDeclaredDestructorRunCount, 1);
       
   325 #endif
       
   326 }
       
   327 
       
   328 #include "forwarddeclared.h"
       
   329 
       
   330 void tst_QSharedPointer::forwardDeclaration2()
       
   331 {
       
   332     forwardDeclaredDestructorRunCount = 0;
       
   333     {
       
   334         struct Wrapper { QSharedPointer<ForwardDeclared> pointer; };
       
   335         Wrapper w1, w2;
       
   336         w1.pointer = QSharedPointer<ForwardDeclared>(forwardPointer());
       
   337         QVERIFY(!w1.pointer.isNull());
       
   338     }
       
   339     QCOMPARE(forwardDeclaredDestructorRunCount, 1);
       
   340 }
       
   341 
       
   342 void tst_QSharedPointer::memoryManagement()
       
   343 {
       
   344     int generation = Data::generationCounter + 1;
       
   345     int destructorCounter = Data::destructorCounter;
       
   346 
       
   347     QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data);
       
   348     QCOMPARE(ptr->generation, generation);
       
   349     QCOMPARE(Data::destructorCounter, destructorCounter);
       
   350     QCOMPARE(Data::generationCounter, generation);
       
   351 
       
   352     ptr = ptr;
       
   353     QCOMPARE(ptr->generation, generation);
       
   354     QCOMPARE(Data::destructorCounter, destructorCounter);
       
   355     QCOMPARE(Data::generationCounter, generation);
       
   356 
       
   357     {
       
   358         QSharedPointer<Data> copy = ptr;
       
   359         QCOMPARE(ptr->generation, generation);
       
   360         QCOMPARE(copy->generation, generation);
       
   361 
       
   362         // copy goes out of scope, ptr continues
       
   363     }
       
   364     QCOMPARE(ptr->generation, generation);
       
   365     QCOMPARE(Data::destructorCounter, destructorCounter);
       
   366     QCOMPARE(Data::generationCounter, generation);
       
   367 
       
   368     {
       
   369         QWeakPointer<Data> weak = ptr;
       
   370         weak = ptr;
       
   371         QCOMPARE(ptr->generation, generation);
       
   372         QCOMPARE(Data::destructorCounter, destructorCounter);
       
   373         QCOMPARE(Data::generationCounter, generation);
       
   374 
       
   375         weak = weak;
       
   376         QCOMPARE(ptr->generation, generation);
       
   377         QCOMPARE(Data::destructorCounter, destructorCounter);
       
   378         QCOMPARE(Data::generationCounter, generation);
       
   379 
       
   380         QSharedPointer<Data> strong = weak;
       
   381         QCOMPARE(ptr->generation, generation);
       
   382         QCOMPARE(strong->generation, generation);
       
   383         QCOMPARE(Data::destructorCounter, destructorCounter);
       
   384         QCOMPARE(Data::generationCounter, generation);
       
   385 
       
   386         // both weak and strong go out of scope
       
   387     }
       
   388     QCOMPARE(ptr->generation, generation);
       
   389     QCOMPARE(Data::destructorCounter, destructorCounter);
       
   390     QCOMPARE(Data::generationCounter, generation);
       
   391 
       
   392     QWeakPointer<Data> weak = ptr;
       
   393     ptr = QSharedPointer<Data>();
       
   394 
       
   395     // destructor must have been called
       
   396     QCOMPARE(Data::destructorCounter, destructorCounter + 1);
       
   397     QVERIFY(ptr.isNull());
       
   398     QVERIFY(weak.isNull());
       
   399 
       
   400     // if we create a strong pointer from the weak, it must still be null
       
   401     ptr = weak;
       
   402     QVERIFY(ptr.isNull());
       
   403     QVERIFY(ptr == 0);
       
   404     QCOMPARE(ptr.data(), (Data*)0);
       
   405 }
       
   406 
       
   407 class DerivedData: public Data
       
   408 {
       
   409 public:
       
   410     static int derivedDestructorCounter;
       
   411     int moreData;
       
   412     DerivedData() : moreData(0) { }
       
   413     ~DerivedData() { ++derivedDestructorCounter; }
       
   414 
       
   415     virtual void virtualDelete()
       
   416     {
       
   417         delete this;
       
   418     }
       
   419 
       
   420     virtual int classLevel() { return 2; }
       
   421 };
       
   422 int DerivedData::derivedDestructorCounter = 0;
       
   423 
       
   424 class Stuffing
       
   425 {
       
   426 public:
       
   427     char buffer[16];
       
   428     Stuffing() { for (uint i = 0; i < sizeof buffer; ++i) buffer[i] = 16 - i; }
       
   429     virtual ~Stuffing() { }
       
   430 };
       
   431 
       
   432 class DiffPtrDerivedData: public Stuffing, public Data
       
   433 {
       
   434 public:
       
   435     virtual int classLevel() { return 3; }
       
   436 };
       
   437 
       
   438 class VirtualDerived: virtual public Data
       
   439 {
       
   440 public:
       
   441     int moreData;
       
   442 
       
   443     VirtualDerived() : moreData(0xc0ffee) { }
       
   444     virtual int classLevel() { return 4; }
       
   445 };
       
   446 
       
   447 void tst_QSharedPointer::downCast()
       
   448 {
       
   449     {
       
   450         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
       
   451         QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
       
   452         QSharedPointer<Data> other;
       
   453 
       
   454         QVERIFY(ptr == baseptr);
       
   455         QVERIFY(baseptr == ptr);
       
   456         QVERIFY(! (ptr != baseptr));
       
   457         QVERIFY(! (baseptr != ptr));
       
   458 
       
   459         QVERIFY(ptr != other);
       
   460         QVERIFY(other != ptr);
       
   461         QVERIFY(! (ptr == other));
       
   462         QVERIFY(! (other == ptr));
       
   463     }
       
   464 
       
   465     {
       
   466         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
       
   467         QSharedPointer<Data> baseptr = ptr;
       
   468     }
       
   469 
       
   470     int destructorCount;
       
   471     destructorCount = DerivedData::derivedDestructorCounter;
       
   472     {
       
   473         QSharedPointer<Data> baseptr;
       
   474         {
       
   475             QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
       
   476             baseptr = ptr;
       
   477             QVERIFY(baseptr == ptr);
       
   478         }
       
   479     }
       
   480     QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
       
   481 
       
   482     destructorCount = DerivedData::derivedDestructorCounter;
       
   483     {
       
   484         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
       
   485         QWeakPointer<Data> baseptr = ptr;
       
   486         QVERIFY(baseptr == ptr);
       
   487 
       
   488         ptr = QSharedPointer<DerivedData>();
       
   489         QVERIFY(baseptr.isNull());
       
   490     }
       
   491     QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
       
   492 
       
   493     destructorCount = DerivedData::derivedDestructorCounter;
       
   494     {
       
   495         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
       
   496         QWeakPointer<DerivedData> weakptr(ptr);
       
   497 
       
   498         QSharedPointer<Data> baseptr = weakptr;
       
   499         QVERIFY(baseptr == ptr);
       
   500         QWeakPointer<Data> baseweakptr = weakptr;
       
   501         QVERIFY(baseweakptr == ptr);
       
   502     }
       
   503     QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
       
   504 }
       
   505 
       
   506 void tst_QSharedPointer::upCast()
       
   507 {
       
   508     QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);
       
   509 
       
   510     {
       
   511         QSharedPointer<DerivedData> derivedptr = qSharedPointerCast<DerivedData>(baseptr);
       
   512         QVERIFY(baseptr == derivedptr);
       
   513         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   514     }
       
   515     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   516     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   517 
       
   518     {
       
   519         QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr);
       
   520         QVERIFY(baseptr == derivedptr);
       
   521     }
       
   522     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   523     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   524 
       
   525     {
       
   526         QWeakPointer<Data> weakptr = baseptr;
       
   527         QSharedPointer<DerivedData> derivedptr = qSharedPointerCast<DerivedData>(weakptr);
       
   528         QVERIFY(baseptr == derivedptr);
       
   529         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   530     }
       
   531     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   532     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   533 
       
   534     {
       
   535         QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>();
       
   536         QVERIFY(baseptr == derivedptr);
       
   537         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   538     }
       
   539     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   540     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   541 }
       
   542 
       
   543 class OtherObject: public QObject
       
   544 {
       
   545     Q_OBJECT
       
   546 };
       
   547 
       
   548 void tst_QSharedPointer::qobjectWeakManagement()
       
   549 {
       
   550     {
       
   551         QWeakPointer<QObject> weak;
       
   552         weak = QWeakPointer<QObject>();
       
   553         QVERIFY(weak.isNull());
       
   554         QVERIFY(!weak.data());
       
   555     }
       
   556 
       
   557     {
       
   558         QObject *obj = new QObject;
       
   559         QWeakPointer<QObject> weak(obj);
       
   560         QVERIFY(!weak.isNull());
       
   561         QVERIFY(weak.data() == obj);
       
   562 
       
   563         // now delete
       
   564         delete obj;
       
   565         QVERIFY(weak.isNull());
       
   566     }
       
   567     check();
       
   568 
       
   569     {
       
   570         // same, bit with operator=
       
   571         QObject *obj = new QObject;
       
   572         QWeakPointer<QObject> weak;
       
   573         weak = obj;
       
   574         QVERIFY(!weak.isNull());
       
   575         QVERIFY(weak.data() == obj);
       
   576 
       
   577         // now delete
       
   578         delete obj;
       
   579         QVERIFY(weak.isNull());
       
   580     }
       
   581     check();
       
   582 
       
   583     {
       
   584         // delete triggered by parent
       
   585         QObject *obj, *parent;
       
   586         parent = new QObject;
       
   587         obj = new QObject(parent);
       
   588         QWeakPointer<QObject> weak(obj);
       
   589 
       
   590         // now delete the parent
       
   591         delete parent;
       
   592         QVERIFY(weak.isNull());
       
   593     }
       
   594     check();
       
   595 
       
   596     {
       
   597         // same as above, but set the parent after QWeakPointer is created
       
   598         QObject *obj, *parent;
       
   599         obj = new QObject;
       
   600         QWeakPointer<QObject> weak(obj);
       
   601 
       
   602         parent = new QObject;
       
   603         obj->setParent(parent);
       
   604 
       
   605         // now delete the parent
       
   606         delete parent;
       
   607         QVERIFY(weak.isNull());
       
   608     }
       
   609     check();
       
   610 
       
   611     {
       
   612         // with two QWeakPointers
       
   613         QObject *obj = new QObject;
       
   614         QWeakPointer<QObject> weak(obj);
       
   615 
       
   616         {
       
   617             QWeakPointer<QObject> weak2(obj);
       
   618             QVERIFY(!weak2.isNull());
       
   619             QVERIFY(weak == weak2);
       
   620         }
       
   621         QVERIFY(!weak.isNull());
       
   622 
       
   623         delete obj;
       
   624         QVERIFY(weak.isNull());
       
   625     }
       
   626     check();
       
   627 
       
   628     {
       
   629         // same, but delete the pointer while two QWeakPointers exist
       
   630         QObject *obj = new QObject;
       
   631         QWeakPointer<QObject> weak(obj);
       
   632 
       
   633         {
       
   634             QWeakPointer<QObject> weak2(obj);
       
   635             QVERIFY(!weak2.isNull());
       
   636 
       
   637             delete obj;
       
   638             QVERIFY(weak.isNull());
       
   639             QVERIFY(weak2.isNull());
       
   640         }
       
   641         QVERIFY(weak.isNull());
       
   642     }
       
   643     check();
       
   644 }
       
   645 
       
   646 void tst_QSharedPointer::noSharedPointerFromWeakQObject()
       
   647 {
       
   648     // you're not allowed to create a QSharedPointer from an unmanaged QObject
       
   649     QObject obj;
       
   650     QWeakPointer<QObject> weak(&obj);
       
   651 
       
   652     QSharedPointer<QObject> strong = weak.toStrongRef();
       
   653     QVERIFY(strong.isNull());
       
   654 
       
   655     // is something went wrong, we'll probably crash here
       
   656 }
       
   657 
       
   658 void tst_QSharedPointer::weakQObjectFromSharedPointer()
       
   659 {
       
   660     // this is the inverse of the above: you're allowed to create a QWeakPointer
       
   661     // from a managed QObject
       
   662     QSharedPointer<QObject> shared(new QObject);
       
   663     QWeakPointer<QObject> weak = shared.data();
       
   664     QVERIFY(!weak.isNull());
       
   665 
       
   666     // delete:
       
   667     shared.clear();
       
   668     QVERIFY(weak.isNull());
       
   669 }
       
   670 
       
   671 void tst_QSharedPointer::objectCast()
       
   672 {
       
   673     {
       
   674         OtherObject *data = new OtherObject;
       
   675         QSharedPointer<QObject> baseptr = QSharedPointer<QObject>(data);
       
   676         QVERIFY(baseptr == data);
       
   677         QVERIFY(data == baseptr);
       
   678 
       
   679         // perform object cast
       
   680         QSharedPointer<OtherObject> ptr = qSharedPointerObjectCast<OtherObject>(baseptr);
       
   681         QVERIFY(!ptr.isNull());
       
   682         QCOMPARE(ptr.data(), data);
       
   683         QVERIFY(ptr == data);
       
   684 
       
   685         // again:
       
   686         ptr = baseptr.objectCast<OtherObject>();
       
   687         QVERIFY(ptr == data);
       
   688 
       
   689 #ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
       
   690         // again:
       
   691         ptr = qobject_cast<OtherObject *>(baseptr);
       
   692         QVERIFY(ptr == data);
       
   693 
       
   694         // again:
       
   695         ptr = qobject_cast<QSharedPointer<OtherObject> >(baseptr);
       
   696         QVERIFY(ptr == data);
       
   697 #endif
       
   698     }
       
   699     check();
       
   700 
       
   701     {
       
   702         const OtherObject *data = new OtherObject;
       
   703         QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(data);
       
   704         QVERIFY(baseptr == data);
       
   705         QVERIFY(data == baseptr);
       
   706 
       
   707         // perform object cast
       
   708         QSharedPointer<const OtherObject> ptr = qSharedPointerObjectCast<const OtherObject>(baseptr);
       
   709         QVERIFY(!ptr.isNull());
       
   710         QCOMPARE(ptr.data(), data);
       
   711         QVERIFY(ptr == data);
       
   712 
       
   713         // again:
       
   714         ptr = baseptr.objectCast<const OtherObject>();
       
   715         QVERIFY(ptr == data);
       
   716 
       
   717 #ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
       
   718         // again:
       
   719         ptr = qobject_cast<const OtherObject *>(baseptr);
       
   720         QVERIFY(ptr == data);
       
   721 
       
   722         // again:
       
   723         ptr = qobject_cast<QSharedPointer<const OtherObject> >(baseptr);
       
   724         QVERIFY(ptr == data);
       
   725 #endif
       
   726     }
       
   727     check();
       
   728 
       
   729     {
       
   730         OtherObject *data = new OtherObject;
       
   731         QPointer<OtherObject> qptr = data;
       
   732         QSharedPointer<OtherObject> ptr = QSharedPointer<OtherObject>(data);
       
   733         QWeakPointer<QObject> weakptr = ptr;
       
   734 
       
   735         {
       
   736             // perform object cast
       
   737             QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr);
       
   738             QVERIFY(otherptr == ptr);
       
   739 
       
   740             // again:
       
   741             otherptr = qobject_cast<OtherObject *>(weakptr);
       
   742             QVERIFY(otherptr == ptr);
       
   743 
       
   744             // again:
       
   745             otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr);
       
   746             QVERIFY(otherptr == ptr);
       
   747         }
       
   748 
       
   749         // drop the reference:
       
   750         ptr.clear();
       
   751         QVERIFY(ptr.isNull());
       
   752         QVERIFY(qptr.isNull());
       
   753         QVERIFY(weakptr.toStrongRef().isNull());
       
   754 
       
   755         // verify that the object casts fail without crash
       
   756         QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr);
       
   757         QVERIFY(otherptr.isNull());
       
   758 
       
   759 #ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
       
   760         // again:
       
   761         otherptr = qobject_cast<OtherObject *>(weakptr);
       
   762         QVERIFY(otherptr.isNull());
       
   763 
       
   764         // again:
       
   765         otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr);
       
   766         QVERIFY(otherptr.isNull());
       
   767 #endif
       
   768     }
       
   769     check();
       
   770 }
       
   771 
       
   772 void tst_QSharedPointer::differentPointers()
       
   773 {
       
   774     {
       
   775         DiffPtrDerivedData *aData = new DiffPtrDerivedData;
       
   776         Data *aBase = aData;
       
   777 
       
   778         // ensure that this compiler isn't broken
       
   779         if (*reinterpret_cast<quintptr *>(&aData) == *reinterpret_cast<quintptr *>(&aBase))
       
   780             qFatal("Something went very wrong -- we couldn't create two different pointers to the same object");
       
   781         if (aData != aBase)
       
   782             QSKIP("Broken compiler", SkipAll);
       
   783         if (aBase != aData)
       
   784             QSKIP("Broken compiler", SkipAll);
       
   785 
       
   786         QSharedPointer<DiffPtrDerivedData> ptr = QSharedPointer<DiffPtrDerivedData>(aData);
       
   787         QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
       
   788         qDebug("naked: orig: %p; base: %p (%s) -- QSharedPointer: orig: %p; base %p (%s) -- result: %s",
       
   789                aData, aBase, aData == aBase ? "equal" : "not equal",
       
   790                ptr.data(), baseptr.data(), ptr.data() == baseptr.data() ? "equal" : "not equal",
       
   791                baseptr.data() == aData ? "equal" : "not equal");
       
   792 
       
   793         QVERIFY(ptr.data() == baseptr.data());
       
   794         QVERIFY(baseptr.data() == ptr.data());
       
   795         QVERIFY(ptr == baseptr);
       
   796         QVERIFY(baseptr == ptr);
       
   797 
       
   798         QVERIFY(ptr.data() == aBase);
       
   799         QVERIFY(aBase == ptr.data());
       
   800         QVERIFY(ptr.data() == aData);
       
   801         QVERIFY(aData == ptr.data());
       
   802 
       
   803         QVERIFY(ptr == aBase);
       
   804         QVERIFY(aBase == ptr);
       
   805         QVERIFY(ptr == aData);
       
   806         QVERIFY(aData == ptr);
       
   807 
       
   808         QVERIFY(baseptr.data() == aBase);
       
   809         QVERIFY(aBase == baseptr.data());
       
   810         QVERIFY(baseptr == aBase);
       
   811         QVERIFY(aBase == baseptr);
       
   812 
       
   813         QVERIFY(baseptr.data() == aData);
       
   814         QVERIFY(aData == baseptr.data());
       
   815 
       
   816 #if defined(Q_CC_MSVC) && _MSC_VER < 1400
       
   817         QEXPECT_FAIL("", "Compiler bug", Continue);
       
   818 #endif
       
   819         QVERIFY(baseptr == aData);
       
   820 #if defined(Q_CC_MSVC) && _MSC_VER < 1400
       
   821         QEXPECT_FAIL("", "Compiler bug", Continue);
       
   822 #endif
       
   823         QVERIFY(aData == baseptr);
       
   824     }
       
   825     check();
       
   826 
       
   827     {
       
   828         DiffPtrDerivedData *aData = new DiffPtrDerivedData;
       
   829         Data *aBase = aData;
       
   830         Q_ASSERT(aData == aBase);
       
   831         Q_ASSERT(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
       
   832 
       
   833         QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
       
   834         QSharedPointer<DiffPtrDerivedData> ptr = qSharedPointerCast<DiffPtrDerivedData>(baseptr);
       
   835         QVERIFY(ptr == baseptr);
       
   836         QVERIFY(ptr.data() == baseptr.data());
       
   837         QVERIFY(ptr == aBase);
       
   838 #if defined(Q_CC_MSVC) && _MSC_VER < 1400
       
   839         QEXPECT_FAIL("", "Compiler bug", Continue);
       
   840 #endif
       
   841         QVERIFY(baseptr == aData);
       
   842     }
       
   843     check();
       
   844 
       
   845     {
       
   846         DiffPtrDerivedData *aData = new DiffPtrDerivedData;
       
   847         Data *aBase = aData;
       
   848         Q_ASSERT(aData == aBase);
       
   849         Q_ASSERT(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
       
   850 
       
   851         QSharedPointer<DiffPtrDerivedData> ptr = QSharedPointer<DiffPtrDerivedData>(aData);
       
   852         QSharedPointer<Data> baseptr = ptr;
       
   853         QVERIFY(ptr == baseptr);
       
   854         QVERIFY(ptr.data() == baseptr.data());
       
   855         QVERIFY(ptr == aBase);
       
   856         QVERIFY(ptr == aData);
       
   857 #if defined(Q_CC_MSVC) && _MSC_VER < 1400
       
   858         QEXPECT_FAIL("", "Compiler bug", Continue);
       
   859 #endif
       
   860         QVERIFY(baseptr == aData);
       
   861         QVERIFY(baseptr == aBase);
       
   862     }
       
   863     check();
       
   864 }
       
   865 
       
   866 void tst_QSharedPointer::virtualBaseDifferentPointers()
       
   867 {
       
   868     {
       
   869         VirtualDerived *aData = new VirtualDerived;
       
   870         Data *aBase = aData;
       
   871         Q_ASSERT(aData == aBase);
       
   872         Q_ASSERT(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
       
   873 
       
   874         QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>(aData);
       
   875         QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
       
   876         QVERIFY(ptr == baseptr);
       
   877         QVERIFY(ptr.data() == baseptr.data());
       
   878         QVERIFY(ptr == aBase);
       
   879         QVERIFY(ptr == aData);
       
   880 #if defined(Q_CC_MSVC) && _MSC_VER < 1400
       
   881         QEXPECT_FAIL("", "Compiler bug", Continue);
       
   882 #endif
       
   883         QVERIFY(baseptr == aData);
       
   884         QVERIFY(baseptr == aBase);
       
   885     }
       
   886     check();
       
   887 
       
   888     {
       
   889         VirtualDerived *aData = new VirtualDerived;
       
   890         Data *aBase = aData;
       
   891         Q_ASSERT(aData == aBase);
       
   892         Q_ASSERT(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
       
   893 
       
   894         QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>(aData);
       
   895         QSharedPointer<Data> baseptr = ptr;
       
   896         QVERIFY(ptr == baseptr);
       
   897         QVERIFY(ptr.data() == baseptr.data());
       
   898         QVERIFY(ptr == aBase);
       
   899         QVERIFY(ptr == aData);
       
   900 #if defined(Q_CC_MSVC) && _MSC_VER < 1400
       
   901         QEXPECT_FAIL("", "Compiler bug", Continue);
       
   902 #endif
       
   903         QVERIFY(baseptr == aData);
       
   904         QVERIFY(baseptr == aBase);
       
   905     }
       
   906     check();
       
   907 }
       
   908 
       
   909 #ifndef QTEST_NO_RTTI
       
   910 void tst_QSharedPointer::dynamicCast()
       
   911 {
       
   912     DerivedData *aData = new DerivedData;
       
   913     QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
       
   914 
       
   915     {
       
   916         QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
       
   917         QVERIFY(baseptr == derivedptr);
       
   918         QCOMPARE(derivedptr.data(), aData);
       
   919         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   920     }
       
   921     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   922     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   923 
       
   924     {
       
   925         QWeakPointer<Data> weakptr = baseptr;
       
   926         QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(weakptr);
       
   927         QVERIFY(baseptr == derivedptr);
       
   928         QCOMPARE(derivedptr.data(), aData);
       
   929         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   930     }
       
   931     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   932     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   933 
       
   934     {
       
   935         QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
       
   936         QVERIFY(baseptr == derivedptr);
       
   937         QCOMPARE(derivedptr.data(), aData);
       
   938         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   939     }
       
   940     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   941     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   942 }
       
   943 
       
   944 void tst_QSharedPointer::dynamicCastDifferentPointers()
       
   945 {
       
   946     // DiffPtrDerivedData derives from both Data and Stuffing
       
   947     DiffPtrDerivedData *aData = new DiffPtrDerivedData;
       
   948     QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
       
   949 
       
   950     {
       
   951         QSharedPointer<DiffPtrDerivedData> derivedptr = qSharedPointerDynamicCast<DiffPtrDerivedData>(baseptr);
       
   952         QVERIFY(baseptr == derivedptr);
       
   953         QCOMPARE(derivedptr.data(), aData);
       
   954         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   955     }
       
   956     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   957     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   958 
       
   959     {
       
   960         QWeakPointer<Data> weakptr = baseptr;
       
   961         QSharedPointer<DiffPtrDerivedData> derivedptr = qSharedPointerDynamicCast<DiffPtrDerivedData>(weakptr);
       
   962         QVERIFY(baseptr == derivedptr);
       
   963         QCOMPARE(derivedptr.data(), aData);
       
   964         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   965     }
       
   966     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   967     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   968 
       
   969     {
       
   970         QSharedPointer<DiffPtrDerivedData> derivedptr = baseptr.dynamicCast<DiffPtrDerivedData>();
       
   971         QVERIFY(baseptr == derivedptr);
       
   972         QCOMPARE(derivedptr.data(), aData);
       
   973         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
   974     }
       
   975     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
   976     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
   977 
       
   978     {
       
   979         Stuffing *nakedptr = dynamic_cast<Stuffing *>(baseptr.data());
       
   980         QVERIFY(nakedptr);
       
   981 
       
   982         QSharedPointer<Stuffing> otherbaseptr = qSharedPointerDynamicCast<Stuffing>(baseptr);
       
   983         QVERIFY(!otherbaseptr.isNull());
       
   984         QVERIFY(otherbaseptr == nakedptr);
       
   985         QCOMPARE(otherbaseptr.data(), nakedptr);
       
   986         QCOMPARE(static_cast<DiffPtrDerivedData*>(otherbaseptr.data()), aData);
       
   987     }
       
   988 }
       
   989 
       
   990 void tst_QSharedPointer::dynamicCastVirtualBase()
       
   991 {
       
   992     VirtualDerived *aData = new VirtualDerived;
       
   993     QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
       
   994 
       
   995     {
       
   996         QSharedPointer<VirtualDerived> derivedptr = qSharedPointerDynamicCast<VirtualDerived>(baseptr);
       
   997         QVERIFY(baseptr == derivedptr);
       
   998         QCOMPARE(derivedptr.data(), aData);
       
   999         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
  1000     }
       
  1001     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
  1002     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
  1003 
       
  1004     {
       
  1005         QWeakPointer<Data> weakptr = baseptr;
       
  1006         QSharedPointer<VirtualDerived> derivedptr = qSharedPointerDynamicCast<VirtualDerived>(weakptr);
       
  1007         QVERIFY(baseptr == derivedptr);
       
  1008         QCOMPARE(derivedptr.data(), aData);
       
  1009         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
  1010     }
       
  1011     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
  1012     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
  1013 
       
  1014     {
       
  1015         QSharedPointer<VirtualDerived> derivedptr = baseptr.dynamicCast<VirtualDerived>();
       
  1016         QVERIFY(baseptr == derivedptr);
       
  1017         QCOMPARE(derivedptr.data(), aData);
       
  1018         QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
       
  1019     }
       
  1020     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
  1021     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
  1022 }
       
  1023 
       
  1024 void tst_QSharedPointer::dynamicCastFailure()
       
  1025 {
       
  1026     QSharedPointer<Data> baseptr = QSharedPointer<Data>(new Data);
       
  1027     QVERIFY(dynamic_cast<DerivedData *>(baseptr.data()) == 0);
       
  1028 
       
  1029     {
       
  1030         QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
       
  1031         QVERIFY(derivedptr.isNull());
       
  1032     }
       
  1033     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
  1034     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
  1035 
       
  1036     {
       
  1037         QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
       
  1038         QVERIFY(derivedptr.isNull());
       
  1039     }
       
  1040     QCOMPARE(int(refCountData(baseptr)->weakref), 1);
       
  1041     QCOMPARE(int(refCountData(baseptr)->strongref), 1);
       
  1042 }
       
  1043 #endif
       
  1044 
       
  1045 void tst_QSharedPointer::constCorrectness()
       
  1046 {
       
  1047     {
       
  1048         QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data);
       
  1049         QSharedPointer<const Data> cptr(ptr);
       
  1050         QSharedPointer<volatile Data> vptr(ptr);
       
  1051         cptr = ptr;
       
  1052         vptr = ptr;
       
  1053 
       
  1054         ptr = qSharedPointerConstCast<Data>(cptr);
       
  1055         ptr = qSharedPointerConstCast<Data>(vptr);
       
  1056         ptr = cptr.constCast<Data>();
       
  1057         ptr = vptr.constCast<Data>();
       
  1058 
       
  1059 #if !defined(Q_CC_HPACC) && !defined(QT_ARCH_PARISC)
       
  1060         // the aCC series 3 compiler we have on the PA-RISC
       
  1061         // machine crashes compiling this code
       
  1062 
       
  1063         QSharedPointer<const volatile Data> cvptr(ptr);
       
  1064         QSharedPointer<const volatile Data> cvptr2(cptr);
       
  1065         QSharedPointer<const volatile Data> cvptr3(vptr);
       
  1066         cvptr = ptr;
       
  1067         cvptr2 = cptr;
       
  1068         cvptr3 = vptr;
       
  1069         ptr = qSharedPointerConstCast<Data>(cvptr);
       
  1070         ptr = cvptr.constCast<Data>();
       
  1071 #endif
       
  1072     }
       
  1073     check();
       
  1074 
       
  1075     {
       
  1076         Data *aData = new Data;
       
  1077         QSharedPointer<Data> ptr = QSharedPointer<Data>(aData);
       
  1078         const QSharedPointer<Data> cptr = ptr;
       
  1079 
       
  1080         ptr = cptr;
       
  1081         QSharedPointer<Data> other = qSharedPointerCast<Data>(cptr);
       
  1082 
       
  1083 #ifndef QT_NO_DYNAMIC_CAST
       
  1084         other = qSharedPointerDynamicCast<Data>(cptr);
       
  1085 #endif
       
  1086 
       
  1087         QCOMPARE(cptr.data(), aData);
       
  1088         QCOMPARE(cptr.operator->(), aData);
       
  1089     }
       
  1090     check();
       
  1091 }
       
  1092 
       
  1093 static int customDeleterFnCallCount;
       
  1094 void customDeleterFn(Data *ptr)
       
  1095 {
       
  1096     ++customDeleterFnCallCount;
       
  1097     delete ptr;
       
  1098 }
       
  1099 
       
  1100 static int refcount;
       
  1101 
       
  1102 template <typename T>
       
  1103 struct CustomDeleter
       
  1104 {
       
  1105     CustomDeleter() { ++refcount; }
       
  1106     CustomDeleter(const CustomDeleter &) { ++refcount; }
       
  1107     ~CustomDeleter() { --refcount; }
       
  1108     inline void operator()(T *ptr)
       
  1109     {
       
  1110         delete ptr;
       
  1111         ++callCount;
       
  1112     }
       
  1113     static int callCount;
       
  1114 };
       
  1115 template<typename T> int CustomDeleter<T>::callCount = 0;
       
  1116 
       
  1117 void tst_QSharedPointer::customDeleter()
       
  1118 {
       
  1119     {
       
  1120         QSharedPointer<Data> ptr(new Data, &Data::doDelete);
       
  1121         QSharedPointer<Data> ptr2(new Data, &Data::alsoDelete);
       
  1122         QSharedPointer<Data> ptr3(new Data, &Data::virtualDelete);
       
  1123     }
       
  1124     check();
       
  1125     {
       
  1126         QSharedPointer<DerivedData> ptr(new DerivedData, &Data::doDelete);
       
  1127         QSharedPointer<DerivedData> ptr2(new DerivedData, &Data::alsoDelete);
       
  1128         QSharedPointer<DerivedData> ptr3(new DerivedData, &Data::virtualDelete);
       
  1129     }
       
  1130     check();
       
  1131 
       
  1132     customDeleterFnCallCount = 0;
       
  1133     {
       
  1134         QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
       
  1135         ptr.data();
       
  1136         QCOMPARE(customDeleterFnCallCount, 0);
       
  1137     }
       
  1138     QCOMPARE(customDeleterFnCallCount, 1);
       
  1139     check();
       
  1140 
       
  1141     customDeleterFnCallCount = 0;
       
  1142     {
       
  1143         QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
       
  1144         QCOMPARE(customDeleterFnCallCount, 0);
       
  1145         ptr.clear();
       
  1146         QCOMPARE(customDeleterFnCallCount, 1);
       
  1147     }
       
  1148     QCOMPARE(customDeleterFnCallCount, 1);
       
  1149     check();
       
  1150 
       
  1151     customDeleterFnCallCount = 0;
       
  1152     {
       
  1153         QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
       
  1154         QCOMPARE(customDeleterFnCallCount, 0);
       
  1155         ptr = QSharedPointer<Data>(new Data);
       
  1156         QCOMPARE(customDeleterFnCallCount, 1);
       
  1157     }
       
  1158     QCOMPARE(customDeleterFnCallCount, 1);
       
  1159     check();
       
  1160 
       
  1161     customDeleterFnCallCount = 0;
       
  1162     {
       
  1163         QSharedPointer<Data> ptr = QSharedPointer<Data>(new DerivedData, customDeleterFn);
       
  1164         ptr.data();
       
  1165         QCOMPARE(customDeleterFnCallCount, 0);
       
  1166     }
       
  1167     QCOMPARE(customDeleterFnCallCount, 1);
       
  1168     check();
       
  1169 
       
  1170     customDeleterFnCallCount = 0;
       
  1171     {
       
  1172         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, customDeleterFn);
       
  1173         ptr.data();
       
  1174         QCOMPARE(customDeleterFnCallCount, 0);
       
  1175     }
       
  1176     QCOMPARE(customDeleterFnCallCount, 1);
       
  1177     check();
       
  1178 
       
  1179     customDeleterFnCallCount = 0;
       
  1180     {
       
  1181         QSharedPointer<Data> other;
       
  1182         {
       
  1183             QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
       
  1184             other = ptr;
       
  1185             QCOMPARE(customDeleterFnCallCount, 0);
       
  1186         }
       
  1187         QCOMPARE(customDeleterFnCallCount, 0);
       
  1188     }
       
  1189     QCOMPARE(customDeleterFnCallCount, 1);
       
  1190     check();
       
  1191 
       
  1192     customDeleterFnCallCount = 0;
       
  1193     {
       
  1194         QSharedPointer<Data> other;
       
  1195         {
       
  1196             QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, customDeleterFn);
       
  1197             other = ptr;
       
  1198             QCOMPARE(customDeleterFnCallCount, 0);
       
  1199         }
       
  1200         QCOMPARE(customDeleterFnCallCount, 0);
       
  1201     }
       
  1202     QCOMPARE(customDeleterFnCallCount, 1);
       
  1203     check();
       
  1204 
       
  1205     refcount = 0;
       
  1206     CustomDeleter<Data> dataDeleter;
       
  1207     dataDeleter.callCount = 0;
       
  1208     {
       
  1209         QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
       
  1210         ptr.data();
       
  1211         QCOMPARE(dataDeleter.callCount, 0);
       
  1212     }
       
  1213     QCOMPARE(dataDeleter.callCount, 1);
       
  1214     QCOMPARE(refcount, 1);
       
  1215     check();
       
  1216 
       
  1217     dataDeleter.callCount = 0;
       
  1218     {
       
  1219         QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
       
  1220         QSharedPointer<Data> other = ptr;
       
  1221         other.clear();
       
  1222         QCOMPARE(dataDeleter.callCount, 0);
       
  1223     }
       
  1224     QCOMPARE(dataDeleter.callCount, 1);
       
  1225     QCOMPARE(refcount, 1);
       
  1226     check();
       
  1227 
       
  1228     dataDeleter.callCount = 0;
       
  1229     {
       
  1230         QSharedPointer<Data> other;
       
  1231         {
       
  1232             QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
       
  1233             other = ptr;
       
  1234             QCOMPARE(dataDeleter.callCount, 0);
       
  1235         }
       
  1236         QCOMPARE(dataDeleter.callCount, 0);
       
  1237     }
       
  1238     QCOMPARE(dataDeleter.callCount, 1);
       
  1239     QCOMPARE(refcount, 1);
       
  1240     check();
       
  1241 
       
  1242     dataDeleter.callCount = 0;
       
  1243     {
       
  1244         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, dataDeleter);
       
  1245         ptr.data();
       
  1246         QCOMPARE(dataDeleter.callCount, 0);
       
  1247     }
       
  1248     QCOMPARE(dataDeleter.callCount, 1);
       
  1249     QCOMPARE(refcount, 1);
       
  1250     check();
       
  1251 
       
  1252     CustomDeleter<DerivedData> derivedDataDeleter;
       
  1253     derivedDataDeleter.callCount = 0;
       
  1254     dataDeleter.callCount = 0;
       
  1255     {
       
  1256         QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, derivedDataDeleter);
       
  1257         ptr.data();
       
  1258         QCOMPARE(dataDeleter.callCount, 0);
       
  1259         QCOMPARE(derivedDataDeleter.callCount, 0);
       
  1260     }
       
  1261     QCOMPARE(dataDeleter.callCount, 0);
       
  1262     QCOMPARE(derivedDataDeleter.callCount, 1);
       
  1263     QCOMPARE(refcount, 2);
       
  1264     check();
       
  1265 
       
  1266     derivedDataDeleter.callCount = 0;
       
  1267     dataDeleter.callCount = 0;
       
  1268     {
       
  1269         QSharedPointer<Data> other;
       
  1270         {
       
  1271             QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, dataDeleter);
       
  1272             other = ptr;
       
  1273             QCOMPARE(dataDeleter.callCount, 0);
       
  1274             QCOMPARE(derivedDataDeleter.callCount, 0);
       
  1275         }
       
  1276         QCOMPARE(dataDeleter.callCount, 0);
       
  1277         QCOMPARE(derivedDataDeleter.callCount, 0);
       
  1278     }
       
  1279     QCOMPARE(dataDeleter.callCount, 1);
       
  1280     QCOMPARE(derivedDataDeleter.callCount, 0);
       
  1281     QCOMPARE(refcount, 2);
       
  1282     check();
       
  1283 
       
  1284     derivedDataDeleter.callCount = 0;
       
  1285     dataDeleter.callCount = 0;
       
  1286     {
       
  1287         QSharedPointer<Data> other;
       
  1288         {
       
  1289             QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, derivedDataDeleter);
       
  1290             other = ptr;
       
  1291             QCOMPARE(dataDeleter.callCount, 0);
       
  1292             QCOMPARE(derivedDataDeleter.callCount, 0);
       
  1293         }
       
  1294         QCOMPARE(dataDeleter.callCount, 0);
       
  1295         QCOMPARE(derivedDataDeleter.callCount, 0);
       
  1296     }
       
  1297     QCOMPARE(dataDeleter.callCount, 0);
       
  1298     QCOMPARE(derivedDataDeleter.callCount, 1);
       
  1299     QCOMPARE(refcount, 2);
       
  1300     check();
       
  1301 }
       
  1302 
       
  1303 void customQObjectDeleterFn(QObject *obj)
       
  1304 {
       
  1305     ++customDeleterFnCallCount;
       
  1306     delete obj;
       
  1307 }
       
  1308 
       
  1309 void tst_QSharedPointer::creating()
       
  1310 {
       
  1311     Data::generationCounter = Data::destructorCounter = 0;
       
  1312     {
       
  1313         QSharedPointer<Data> ptr = QSharedPointer<Data>::create();
       
  1314         QVERIFY(ptr.data());
       
  1315         QCOMPARE(Data::generationCounter, 1);
       
  1316         QCOMPARE(ptr->generation, 1);
       
  1317         QCOMPARE(Data::destructorCounter, 0);
       
  1318 
       
  1319         QCOMPARE(ptr->classLevel(), 1);
       
  1320 
       
  1321         ptr.clear();
       
  1322         QCOMPARE(Data::destructorCounter, 1);
       
  1323     }
       
  1324     check();
       
  1325 
       
  1326     Data::generationCounter = Data::destructorCounter = 0;
       
  1327     {
       
  1328         QSharedPointer<Data> ptr = QSharedPointer<Data>::create();
       
  1329         QWeakPointer<Data> weakptr = ptr;
       
  1330         QtSharedPointer::ExternalRefCountData *d = refCountData(ptr);
       
  1331 
       
  1332         ptr.clear();
       
  1333         QVERIFY(ptr.isNull());
       
  1334         QCOMPARE(Data::destructorCounter, 1);
       
  1335 
       
  1336         // valgrind will complain here if something happened to the pointer
       
  1337         QVERIFY(d->weakref == 1);
       
  1338         QVERIFY(d->strongref == 0);
       
  1339     }
       
  1340     check();
       
  1341 
       
  1342     Data::generationCounter = Data::destructorCounter = 0;
       
  1343     DerivedData::derivedDestructorCounter = 0;
       
  1344     {
       
  1345         QSharedPointer<Data> ptr = QSharedPointer<DerivedData>::create();
       
  1346         QCOMPARE(ptr->classLevel(), 2);
       
  1347         QCOMPARE(ptr.staticCast<DerivedData>()->moreData, 0);
       
  1348         ptr.clear();
       
  1349 
       
  1350         QCOMPARE(Data::destructorCounter, 1);
       
  1351         QCOMPARE(DerivedData::derivedDestructorCounter, 1);
       
  1352     }
       
  1353     check();
       
  1354 
       
  1355     {
       
  1356         QSharedPointer<Data> ptr = QSharedPointer<DiffPtrDerivedData>::create();
       
  1357         QCOMPARE(ptr->classLevel(), 3);
       
  1358         QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[7]+0, 16-7);
       
  1359         QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[3]+0, 16-3);
       
  1360         QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[0]+0, 16);
       
  1361     }
       
  1362     check();
       
  1363 
       
  1364     {
       
  1365         QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>::create();
       
  1366         QCOMPARE(ptr->classLevel(), 4);
       
  1367         QCOMPARE(ptr->moreData, 0xc0ffee);
       
  1368 
       
  1369         QSharedPointer<Data> baseptr = ptr;
       
  1370         QCOMPARE(baseptr->classLevel(), 4);
       
  1371     }
       
  1372     check();
       
  1373 }
       
  1374 
       
  1375 void tst_QSharedPointer::creatingQObject()
       
  1376 {
       
  1377     {
       
  1378         QSharedPointer<QObject> ptr = QSharedPointer<QObject>::create();
       
  1379         QCOMPARE(ptr->metaObject(), &QObject::staticMetaObject);
       
  1380 
       
  1381         QPointer<QObject> qptr = ptr.data();
       
  1382         ptr.clear();
       
  1383 
       
  1384         QVERIFY(qptr.isNull());
       
  1385     }
       
  1386     check();
       
  1387 
       
  1388     {
       
  1389         QSharedPointer<QObject> ptr = QSharedPointer<OtherObject>::create();
       
  1390         QCOMPARE(ptr->metaObject(), &OtherObject::staticMetaObject);
       
  1391     }
       
  1392     check();
       
  1393 }
       
  1394 
       
  1395 void tst_QSharedPointer::mixTrackingPointerCode()
       
  1396 {
       
  1397     {
       
  1398         // pointer created with tracking
       
  1399         // deleted in code without tracking
       
  1400         QSharedPointer<int> ptr = QSharedPointer<int>(new int(42));
       
  1401         Wrapper w(ptr);
       
  1402         ptr.clear();
       
  1403     }
       
  1404     check();
       
  1405 
       
  1406     {
       
  1407         // pointer created without tracking
       
  1408         // deleted in code with tracking
       
  1409         Wrapper w = Wrapper::create();
       
  1410         w.ptr.clear();
       
  1411     }
       
  1412 }
       
  1413 
       
  1414 class ThreadData
       
  1415 {
       
  1416     QAtomicInt * volatile ptr;
       
  1417 public:
       
  1418     ThreadData(QAtomicInt *p) : ptr(p) { }
       
  1419     ~ThreadData() { ++ptr; }
       
  1420     void ref()
       
  1421     {
       
  1422         // if we're called after the destructor, we'll crash
       
  1423         ptr->ref();
       
  1424     }
       
  1425 };
       
  1426 
       
  1427 class StrongThread: public QThread
       
  1428 {
       
  1429 protected:
       
  1430     void run()
       
  1431     {
       
  1432         usleep(rand() % 2000);
       
  1433         ptr->ref();
       
  1434         ptr.clear();
       
  1435     }
       
  1436 public:
       
  1437     QSharedPointer<ThreadData> ptr;
       
  1438 };
       
  1439 
       
  1440 class WeakThread: public QThread
       
  1441 {
       
  1442 protected:
       
  1443     void run()
       
  1444     {
       
  1445         usleep(rand() % 2000);
       
  1446         QSharedPointer<ThreadData> ptr = weak;
       
  1447         if (ptr)
       
  1448             ptr->ref();
       
  1449         ptr.clear();
       
  1450     }
       
  1451 public:
       
  1452     QWeakPointer<ThreadData> weak;
       
  1453 };
       
  1454 
       
  1455 void tst_QSharedPointer::threadStressTest_data()
       
  1456 {
       
  1457     QTest::addColumn<int>("strongThreadCount");
       
  1458     QTest::addColumn<int>("weakThreadCount");
       
  1459 
       
  1460     QTest::newRow("0+0") << 0 << 0;
       
  1461     QTest::newRow("1+0") << 1 << 0;
       
  1462     QTest::newRow("2+0") << 2 << 0;
       
  1463     QTest::newRow("10+0") << 10 << 0;
       
  1464 
       
  1465     QTest::newRow("0+1") << 0 << 1;
       
  1466     QTest::newRow("1+1") << 1 << 1;
       
  1467 
       
  1468     QTest::newRow("2+10") << 2 << 10;
       
  1469 #ifndef Q_OS_WINCE
       
  1470     // Windows CE cannot run this many threads
       
  1471     QTest::newRow("5+10") << 5 << 10;
       
  1472     QTest::newRow("5+30") << 5 << 30;
       
  1473 
       
  1474     QTest::newRow("100+100") << 100 << 100;
       
  1475 #endif
       
  1476 }
       
  1477 
       
  1478 void tst_QSharedPointer::threadStressTest()
       
  1479 {
       
  1480     QFETCH(int, strongThreadCount);
       
  1481     QFETCH(int, weakThreadCount);
       
  1482 
       
  1483     int guard1[128];
       
  1484     QAtomicInt counter;
       
  1485     int guard2[128];
       
  1486 
       
  1487     memset(guard1, 0, sizeof guard1);
       
  1488     memset(guard2, 0, sizeof guard2);
       
  1489 
       
  1490     for (int r = 0; r < 5; ++r) {
       
  1491         QVector<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0);
       
  1492         QSharedPointer<ThreadData> base = QSharedPointer<ThreadData>(new ThreadData(&counter));
       
  1493         counter = 0;
       
  1494 
       
  1495         // set the pointers
       
  1496         for (int i = 0; i < strongThreadCount; ++i) {
       
  1497             StrongThread *t = new StrongThread;
       
  1498             t->ptr = base;
       
  1499             allThreads[2 * i] = t;
       
  1500         }
       
  1501         for (int i = 0; i < weakThreadCount; ++i) {
       
  1502             WeakThread *t = new WeakThread;
       
  1503             t->weak = base;
       
  1504             allThreads[6 * i + 3] = t;
       
  1505         }
       
  1506 
       
  1507         base.clear();
       
  1508 
       
  1509 #ifdef Q_OS_WINCE
       
  1510         srand(QDateTime::currentDateTime().toTime_t());
       
  1511 #else
       
  1512         srand(time(NULL));
       
  1513 #endif
       
  1514         // start threads
       
  1515         for (int i = 0; i < allThreads.count(); ++i)
       
  1516             if (allThreads[i]) allThreads[i]->start();
       
  1517 
       
  1518         // wait for them to finish
       
  1519         for (int i = 0; i < allThreads.count(); ++i)
       
  1520             if (allThreads[i]) allThreads[i]->wait();
       
  1521         qDeleteAll(allThreads);
       
  1522 
       
  1523         // ensure the guards aren't touched
       
  1524         for (uint i = 0; i < sizeof guard1 / sizeof guard1[0]; ++i)
       
  1525             QVERIFY(!guard1[i]);
       
  1526         for (uint i = 0; i < sizeof guard2 / sizeof guard2[0]; ++i)
       
  1527             QVERIFY(!guard2[i]);
       
  1528 
       
  1529         // verify that the count is the right range
       
  1530         int minValue = strongThreadCount;
       
  1531         int maxValue = strongThreadCount + weakThreadCount;
       
  1532         QVERIFY(counter >= minValue);
       
  1533         QVERIFY(counter <= maxValue);
       
  1534     }
       
  1535 }
       
  1536 
       
  1537 void tst_QSharedPointer::validConstructs()
       
  1538 {
       
  1539     {
       
  1540         Data *aData = new Data;
       
  1541         QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);
       
  1542 
       
  1543         ptr1 = ptr1;            // valid
       
  1544 
       
  1545         QSharedPointer<Data> ptr2(ptr1);
       
  1546 
       
  1547         ptr1 = ptr2;
       
  1548         ptr2 = ptr1;
       
  1549 
       
  1550         ptr1 = QSharedPointer<Data>();
       
  1551         ptr1 = ptr2;
       
  1552     }
       
  1553 }
       
  1554 
       
  1555 typedef bool (QTest::QExternalTest:: * TestFunction)(const QByteArray &body);
       
  1556 Q_DECLARE_METATYPE(TestFunction)
       
  1557 void tst_QSharedPointer::invalidConstructs_data()
       
  1558 {
       
  1559     QTest::addColumn<TestFunction>("testFunction");
       
  1560     QTest::addColumn<QString>("code");
       
  1561     QTest::newRow("sanity-checking") << &QTest::QExternalTest::tryCompile << "";
       
  1562 
       
  1563     // QSharedPointer<void> is not allowed
       
  1564     QTest::newRow("void") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<void> ptr;";
       
  1565 
       
  1566     // implicit initialization
       
  1567     QTest::newRow("implicit-initialization1")
       
  1568         << &QTest::QExternalTest::tryCompileFail
       
  1569         << "QSharedPointer<Data> ptr = new Data;";
       
  1570     QTest::newRow("implicit-initialization2")
       
  1571         << &QTest::QExternalTest::tryCompileFail
       
  1572         << "QSharedPointer<Data> ptr;"
       
  1573            "ptr = new Data;";
       
  1574     QTest::newRow("implicit-initialization3")
       
  1575         << &QTest::QExternalTest::tryCompileFail
       
  1576         << "QWeakPointer<Data> ptr = new Data;";
       
  1577     QTest::newRow("implicit-initialization4")
       
  1578         << &QTest::QExternalTest::tryCompileFail
       
  1579         << "QWeakPointer<Data> ptr;"
       
  1580            "ptr = new Data;";
       
  1581 
       
  1582     // use of forward-declared class
       
  1583     QTest::newRow("forward-declaration")
       
  1584         << &QTest::QExternalTest::tryRun
       
  1585         << "forwardDeclaredDestructorRunCount = 0;\n"
       
  1586            "{ QSharedPointer<ForwardDeclared> ptr = QSharedPointer<ForwardDeclared>(forwardPointer()); }\n"
       
  1587            "exit(forwardDeclaredDestructorRunCount);";
       
  1588     QTest::newRow("creating-forward-declaration")
       
  1589         << &QTest::QExternalTest::tryCompileFail
       
  1590         << "QSharedPointer<ForwardDeclared>::create();";
       
  1591 
       
  1592     // upcast without cast operator:
       
  1593     QTest::newRow("upcast1")
       
  1594         << &QTest::QExternalTest::tryCompileFail
       
  1595         << "QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);\n"
       
  1596            "QSharedPointer<DerivedData> ptr(baseptr);";
       
  1597     QTest::newRow("upcast2")
       
  1598         << &QTest::QExternalTest::tryCompileFail
       
  1599         << "QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);\n"
       
  1600            "QSharedPointer<DerivedData> ptr;\n"
       
  1601            "ptr = baseptr;";
       
  1602 
       
  1603     // dropping of const
       
  1604     QTest::newRow("const-dropping1")
       
  1605         << &QTest::QExternalTest::tryCompileFail
       
  1606         << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
       
  1607            "QSharedPointer<Data> ptr(baseptr);";
       
  1608     QTest::newRow("const-dropping2")
       
  1609         << &QTest::QExternalTest::tryCompileFail
       
  1610         << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
       
  1611            "QSharedPointer<Data> ptr;"
       
  1612            "ptr = baseptr;";
       
  1613     QTest::newRow("const-dropping-static-cast")
       
  1614         << &QTest::QExternalTest::tryCompileFail
       
  1615         << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
       
  1616         "qSharedPointerCast<DerivedData>(baseptr);";
       
  1617 #ifndef QTEST_NO_RTTI
       
  1618     QTest::newRow("const-dropping-dynamic-cast")
       
  1619         << &QTest::QExternalTest::tryCompileFail
       
  1620         << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
       
  1621         "qSharedPointerDynamicCast<DerivedData>(baseptr);";
       
  1622 #endif
       
  1623     QTest::newRow("const-dropping-object-cast1")
       
  1624         << &QTest::QExternalTest::tryCompileFail
       
  1625         << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n"
       
  1626         "qSharedPointerObjectCast<QCoreApplication>(baseptr);";
       
  1627 #ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION
       
  1628     QTest::newRow("const-dropping-object-cast2")
       
  1629         << &QTest::QExternalTest::tryCompileFail
       
  1630         << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n"
       
  1631         "qobject_cast<QCoreApplication *>(baseptr);";
       
  1632 #endif
       
  1633 
       
  1634     // arithmethics through automatic cast operators
       
  1635     QTest::newRow("arithmethic1")
       
  1636         << &QTest::QExternalTest::tryCompileFail
       
  1637         << "QSharedPointer<int> a;"
       
  1638            "QSharedPointer<Data> b;\n"
       
  1639            "if (a == b) return;";
       
  1640     QTest::newRow("arithmethic2")
       
  1641         << &QTest::QExternalTest::tryCompileFail
       
  1642         << "QSharedPointer<int> a;"
       
  1643            "QSharedPointer<Data> b;\n"
       
  1644            "if (a + b) return;";
       
  1645 
       
  1646 #if QT_VERSION >= 0x040600
       
  1647     // two objects with the same pointer
       
  1648     QTest::newRow("same-pointer")
       
  1649         << &QTest::QExternalTest::tryRunFail
       
  1650         << "Data *aData = new Data;\n"
       
  1651            "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);\n"
       
  1652            "QSharedPointer<Data> ptr2 = QSharedPointer<Data>(aData);\n";
       
  1653 
       
  1654     // re-creation:
       
  1655     QTest::newRow("re-creation")
       
  1656         << &QTest::QExternalTest::tryRunFail
       
  1657         << "Data *aData = new Data;\n"
       
  1658            "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);"
       
  1659            "ptr1 = QSharedPointer<Data>(aData);";
       
  1660 #endif
       
  1661 
       
  1662     // any type of cast for unrelated types:
       
  1663     // (we have no reinterpret_cast)
       
  1664     QTest::newRow("invalid-cast1")
       
  1665         << &QTest::QExternalTest::tryCompileFail
       
  1666         << "QSharedPointer<Data> ptr1;\n"
       
  1667            "QSharedPointer<int> ptr2 = qSharedPointerCast<int>(ptr1);";
       
  1668 #ifndef QTEST_NO_RTTI
       
  1669     QTest::newRow("invalid-cast2")
       
  1670         << &QTest::QExternalTest::tryCompileFail
       
  1671         << "QSharedPointer<Data> ptr1;\n"
       
  1672            "QSharedPointer<int> ptr2 = qSharedPointerDynamicCast<int>(ptr1);";
       
  1673 #endif
       
  1674     QTest::newRow("invalid-cast3")
       
  1675         << &QTest::QExternalTest::tryCompileFail
       
  1676         << "QSharedPointer<Data> ptr1;\n"
       
  1677            "QSharedPointer<int> ptr2 = qSharedPointerConstCast<int>(ptr1);";
       
  1678     QTest::newRow("invalid-cast4")
       
  1679         << &QTest::QExternalTest::tryCompileFail
       
  1680         << "QSharedPointer<Data> ptr1;\n"
       
  1681            "QSharedPointer<int> ptr2 = qSharedPointerObjectCast<int>(ptr1);";
       
  1682 
       
  1683     QTest::newRow("weak-pointer-from-regular-pointer")
       
  1684         << &QTest::QExternalTest::tryCompileFail
       
  1685         << "Data *ptr = 0;\n"
       
  1686            "QWeakPointer<Data> weakptr(ptr);\n";
       
  1687 
       
  1688     QTest::newRow("shared-pointer-from-unmanaged-qobject")
       
  1689         << &QTest::QExternalTest::tryRunFail
       
  1690         << "QObject *ptr = new QObject;\n"
       
  1691            "QWeakPointer<QObject> weak = ptr;\n"    // this makes the object unmanaged
       
  1692            "QSharedPointer<QObject> shared(ptr);\n";
       
  1693 
       
  1694     QTest::newRow("shared-pointer-implicit-from-uninitialized")
       
  1695         << &QTest::QExternalTest::tryCompileFail
       
  1696         << "Data *ptr = 0;\n"
       
  1697            "QSharedPointer<Data> weakptr = Qt::Uninitialized;\n";
       
  1698 }
       
  1699 
       
  1700 void tst_QSharedPointer::invalidConstructs()
       
  1701 {
       
  1702 #ifdef Q_CC_MINGW
       
  1703     QSKIP("The maintainer of QSharedPointer: 'We don't know what the problem is so skip the tests.'", SkipAll);
       
  1704 #endif
       
  1705 #ifdef QTEST_CROSS_COMPILED
       
  1706     QSKIP("This test does not work on cross compiled systems", SkipAll);
       
  1707 #endif
       
  1708 
       
  1709     QTest::QExternalTest test;
       
  1710     test.setDebugMode(true);
       
  1711     test.setQtModules(QTest::QExternalTest::QtCore);
       
  1712     test.setExtraProgramSources(QStringList() << SRCDIR "forwarddeclared.cpp");
       
  1713     test.setProgramHeader(
       
  1714         "#define QT_SHAREDPOINTER_TRACK_POINTERS\n"
       
  1715         "#include <QtCore/qsharedpointer.h>\n"
       
  1716         "#include <QtCore/qcoreapplication.h>\n"
       
  1717         "\n"
       
  1718         "struct Data { int i; };\n"
       
  1719         "struct DerivedData: public Data { int j; };\n"
       
  1720         "\n"
       
  1721         "extern int forwardDeclaredDestructorRunCount;\n"
       
  1722         "class ForwardDeclared;\n"
       
  1723         "ForwardDeclared *forwardPointer();\n"
       
  1724         );
       
  1725 
       
  1726     QFETCH(QString, code);
       
  1727     static bool sane = true;
       
  1728     if (code.isEmpty()) {
       
  1729         static const char snippet[] = "QSharedPointer<Data> baseptr; QSharedPointer<DerivedData> ptr;";
       
  1730         if (!test.tryCompile("")
       
  1731             || !test.tryRun("")
       
  1732             || !test.tryRunFail("exit(1);")
       
  1733             || !test.tryCompile(snippet)
       
  1734             || !test.tryLink(snippet)
       
  1735             || !test.tryRun(snippet)) {
       
  1736             sane = false;
       
  1737             qWarning("Sanity checking failed\nCode:\n%s\n",
       
  1738                      qPrintable(test.errorReport()));
       
  1739         }
       
  1740     }
       
  1741     if (!sane)
       
  1742         QFAIL("External testing failed sanity checking, cannot proceed");
       
  1743 
       
  1744     QFETCH(TestFunction, testFunction);
       
  1745 
       
  1746     QByteArray body = code.toLatin1();
       
  1747 
       
  1748     bool result = (test.*testFunction)(body);
       
  1749     if (qgetenv("QTEST_EXTERNAL_DEBUG").toInt() > 0) {
       
  1750         qDebug("External test output:");
       
  1751 #ifdef Q_CC_MSVC
       
  1752         // MSVC prints errors to stdout
       
  1753         printf("%s\n", test.standardOutput().constData());
       
  1754 #endif
       
  1755         printf("%s\n", test.standardError().constData());
       
  1756     }
       
  1757     if (!result) {
       
  1758         qWarning("External code testing failed\nCode:\n%s\n", body.constData());
       
  1759         QFAIL("Fail");
       
  1760     }
       
  1761 }
       
  1762 
       
  1763 QTEST_MAIN(tst_QSharedPointer)
       
  1764 
       
  1765 #include "tst_qsharedpointer.moc"