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