diff options
Diffstat (limited to 'tests/auto/qsharedpointer')
-rw-r--r-- | tests/auto/qsharedpointer/externaltests.cpp | 108 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/externaltests.h | 4 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/externaltests.pri | 1 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/forwarddeclaration.cpp | 52 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/forwarddeclared.cpp | 53 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/forwarddeclared.h | 54 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/qsharedpointer.pro | 11 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 562 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/wrapper.cpp | 60 | ||||
-rw-r--r-- | tests/auto/qsharedpointer/wrapper.h | 55 |
10 files changed, 899 insertions, 61 deletions
diff --git a/tests/auto/qsharedpointer/externaltests.cpp b/tests/auto/qsharedpointer/externaltests.cpp index 18df37c..6153c76 100644 --- a/tests/auto/qsharedpointer/externaltests.cpp +++ b/tests/auto/qsharedpointer/externaltests.cpp @@ -59,11 +59,16 @@ # error DEFAULT_MAKESPEC not defined #endif +#ifdef Q_OS_UNIX +# include <fcntl.h> +# include <unistd.h> +#endif + static QString makespec() { static const char default_makespec[] = DEFAULT_MAKESPEC; const char *p; - for (p = default_makespec + sizeof(default_makespec); p >= default_makespec; --p) + for (p = default_makespec + sizeof(default_makespec) - 1; p >= default_makespec; --p) if (*p == '/' || *p == '\\') break; @@ -108,6 +113,27 @@ static bool removeRecursive(const QString &pathname) QT_BEGIN_NAMESPACE namespace QTest { + class QExternalProcess: public QProcess + { + protected: +#ifdef Q_OS_UNIX + void setupChildProcess() + { + // run in user code + QProcess::setupChildProcess(); + + if (processChannelMode() == ForwardedChannels) { + // reopen /dev/tty into stdin + int fd = ::open("/dev/tty", O_RDONLY); + if (fd == -1) + return; + ::dup2(fd, 0); + ::close(fd); + } + } +#endif + }; + class QExternalTestPrivate { public: @@ -126,6 +152,7 @@ namespace QTest { enum Target { Compile, Link, Run }; QList<QByteArray> qmakeLines; + QStringList extraProgramSources; QByteArray programHeader; QExternalTest::QtModules qtModules; QExternalTest::ApplicationType appType; @@ -203,6 +230,16 @@ namespace QTest { d->appType = type; } + QStringList QExternalTest::extraProgramSources() const + { + return d->extraProgramSources; + } + + void QExternalTest::setExtraProgramSources(const QStringList &extra) + { + d->extraProgramSources = extra; + } + QByteArray QExternalTest::programHeader() const { return d->programHeader; @@ -327,6 +364,8 @@ namespace QTest { sourceCode.clear(); sourceCode.reserve(8192); + sourceCode += programHeader; + // Add Qt header includes if (qtModules & QExternalTest::QtCore) sourceCode += "#include <QtCore/QtCore>\n"; @@ -360,17 +399,11 @@ namespace QTest { "#include <stdlib.h>\n" "#include <stddef.h>\n"; - sourceCode += programHeader; - sourceCode += "\n" "void q_external_test_user_code()\n" "{\n" - " // HERE STARTS THE USER CODE\n"; - sourceCode += body; - sourceCode += - "\n" - " // HERE ENDS THE USER CODE\n" + "#include \"user_code.cpp\"\n" "}\n" "\n" "#ifdef Q_OS_WIN\n" @@ -435,6 +468,15 @@ namespace QTest { } sourceFile.write(sourceCode); + sourceFile.close(); + + sourceFile.setFileName(temporaryDir + QLatin1String("/user_code.cpp")); + if (!sourceFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { + std_err = sourceFile.errorString().toLocal8Bit(); + return false; + } + sourceFile.write(body); + return true; } @@ -487,6 +529,13 @@ namespace QTest { else projectFile.write("\nCONFIG += release\n"); + QByteArray extraSources = QFile::encodeName(extraProgramSources.join(" ")); + if (!extraSources.isEmpty()) { + projectFile.write("SOURCES += "); + projectFile.write(extraSources); + projectFile.putChar('\n'); + } + // Add Qt modules if (qtModules & QExternalTest::QtCore) projectFile.write("QT += core\n"); @@ -538,6 +587,24 @@ namespace QTest { "embedded:test_run.commands += -qws\n" "QMAKE_EXTRA_TARGETS += test_run\n"); + // Use qmake to debug: + projectFile.write( + "\n" + "*-g++* {\n" + " unix:test_debug.commands = gdb --args ./$(QMAKE_TARGET)\n" + " else:test_debug.commands = gdb --args $(QMAKE_TARGET)\n" + " embedded:test_debug.commands += -qws\n" + " QMAKE_EXTRA_TARGETS += test_debug\n" + "}\n"); + + // Also use qmake to run the app with valgrind: + projectFile.write( + "\n" + "unix:test_valgrind.commands = valgrind ./$(QMAKE_TARGET)\n" + "else:test_valgrind.commands = valgrind $(QMAKE_TARGET)\n" + "embedded:test_valgrind.commands += -qws\n" + "QMAKE_EXTRA_TARGETS += test_valgrind\n"); + return true; } @@ -579,7 +646,7 @@ namespace QTest { { Q_ASSERT(!temporaryDir.isEmpty()); - QProcess make; + QExternalProcess make; make.setWorkingDirectory(temporaryDir); QStringList environment = QProcess::systemEnvironment(); @@ -587,10 +654,22 @@ namespace QTest { make.setEnvironment(environment); QStringList args; - if (target == Compile) + QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; + if (target == Compile) { args << QLatin1String("test_compile"); - else if (target == Run) - args << QLatin1String("test_run"); + } else if (target == Run) { + QByteArray run = qgetenv("QTEST_EXTERNAL_RUN"); + if (run == "valgrind") + args << QLatin1String("test_valgrind"); + else if (run == "debug") + args << QLatin1String("test_debug"); + else + args << QLatin1String("test_run"); + if (!run.isEmpty()) + channelMode = QProcess::ForwardedChannels; + } + + make.setProcessChannelMode(channelMode); #if defined(Q_OS_WIN) && !defined(Q_CC_MINGW) make.start(QLatin1String("nmake.exe"), args); @@ -616,7 +695,10 @@ namespace QTest { return false; } - bool ok = make.waitForFinished(); + make.closeWriteChannel(); + bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : 60000); + if (!ok) + make.terminate(); exitCode = make.exitCode(); std_out += make.readAllStandardOutput(); std_err += make.readAllStandardError(); diff --git a/tests/auto/qsharedpointer/externaltests.h b/tests/auto/qsharedpointer/externaltests.h index 24a3236..ecc107e 100644 --- a/tests/auto/qsharedpointer/externaltests.h +++ b/tests/auto/qsharedpointer/externaltests.h @@ -45,6 +45,7 @@ #include <QList> #include <QByteArray> +#include <QStringList> QT_BEGIN_NAMESPACE namespace QTest { @@ -102,6 +103,9 @@ namespace QTest { ApplicationType applicationType() const; void setApplicationType(ApplicationType type); + QStringList extraProgramSources() const; + void setExtraProgramSources(const QStringList &list); + QByteArray programHeader() const; void setProgramHeader(const QByteArray &header); diff --git a/tests/auto/qsharedpointer/externaltests.pri b/tests/auto/qsharedpointer/externaltests.pri index 0ded149..627af87 100644 --- a/tests/auto/qsharedpointer/externaltests.pri +++ b/tests/auto/qsharedpointer/externaltests.pri @@ -1,4 +1,5 @@ SOURCES += $$PWD/externaltests.cpp +HEADERS += $$PWD/externaltests.h cleanedQMAKESPEC = $$replace(QMAKESPEC, \\\\, /) !symbian:DEFINES += DEFAULT_MAKESPEC=\\\"$$cleanedQMAKESPEC\\\" diff --git a/tests/auto/qsharedpointer/forwarddeclaration.cpp b/tests/auto/qsharedpointer/forwarddeclaration.cpp new file mode 100644 index 0000000..1dbbeec --- /dev/null +++ b/tests/auto/qsharedpointer/forwarddeclaration.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#define QT_SHAREDPOINTER_TRACK_POINTERS +#include "qsharedpointer.h" + +class ForwardDeclared; +ForwardDeclared *forwardPointer(); + +void externalForwardDeclaration() +{ + struct Wrapper { QSharedPointer<ForwardDeclared> pointer; }; +} + diff --git a/tests/auto/qsharedpointer/forwarddeclared.cpp b/tests/auto/qsharedpointer/forwarddeclared.cpp new file mode 100644 index 0000000..4ab467a --- /dev/null +++ b/tests/auto/qsharedpointer/forwarddeclared.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "forwarddeclared.h" + +ForwardDeclared *forwardPointer() +{ + return new ForwardDeclared; +} + +int forwardDeclaredDestructorRunCount; +ForwardDeclared::~ForwardDeclared() +{ + ++forwardDeclaredDestructorRunCount; +} diff --git a/tests/auto/qsharedpointer/forwarddeclared.h b/tests/auto/qsharedpointer/forwarddeclared.h new file mode 100644 index 0000000..a4cc2b4 --- /dev/null +++ b/tests/auto/qsharedpointer/forwarddeclared.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORWARDDECLARED_H +#define FORWARDDECLARED_H + +extern int forwardDeclaredDestructorRunCount; +class ForwardDeclared +{ +public: + ~ForwardDeclared(); +}; + +ForwardDeclared *forwardPointer(); + +#endif // FORWARDDECLARED_H diff --git a/tests/auto/qsharedpointer/qsharedpointer.pro b/tests/auto/qsharedpointer/qsharedpointer.pro index 4532260..bbd31d7 100644 --- a/tests/auto/qsharedpointer/qsharedpointer.pro +++ b/tests/auto/qsharedpointer/qsharedpointer.pro @@ -1,7 +1,14 @@ load(qttest_p4) -SOURCES += tst_qsharedpointer.cpp +SOURCES += tst_qsharedpointer.cpp \ + forwarddeclaration.cpp \ + forwarddeclared.cpp \ + wrapper.cpp + +HEADERS += forwarddeclared.h \ + wrapper.h + QT = core -!symbian:DEFINES += SRCDIR=\\\"$$PWD\\\" +!symbian:DEFINES += SRCDIR=\\\"$$PWD/\\\" include(externaltests.pri) diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index 3adef09..98fbeb5 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -41,8 +41,19 @@ #define QT_SHAREDPOINTER_TRACK_POINTERS #include "qsharedpointer.h" -#include "externaltests.h" #include <QtTest/QtTest> +#include <QtCore/QThread> +#include <QtCore/QVector> + +#include "externaltests.h" +#include "wrapper.h" + +#include <stdlib.h> +#include <time.h> + +namespace QtSharedPointer { + Q_CORE_EXPORT void internalSafetyCheckCleanCheck(); +} #ifdef Q_OS_SYMBIAN #define SRCDIR "." @@ -60,6 +71,7 @@ private slots: void memoryManagement(); void downCast(); void upCast(); + void objectCast(); void differentPointers(); void virtualBaseDifferentPointers(); #ifndef QTEST_NO_RTTI @@ -68,13 +80,38 @@ private slots: void dynamicCastVirtualBase(); void dynamicCastFailure(); #endif - void customDeleter(); void constCorrectness(); + void customDeleter(); + void creating(); + void mixTrackingPointerCode(); + void threadStressTest_data(); + void threadStressTest(); void validConstructs(); void invalidConstructs_data(); void invalidConstructs(); + +public slots: + void cleanup() { check(); } + +public: + inline void check() + { +#ifdef QT_BUILD_INTERNAL + QtSharedPointer::internalSafetyCheckCleanCheck(); +#endif + } }; +template <typename Base> +class RefCountHack: public Base +{ +public: + using Base::d; +}; +template<typename Base> static inline +QtSharedPointer::ExternalRefCountData *refCountData(const Base &b) +{ return static_cast<const RefCountHack<Base> *>(&b)->d; } + class Data { public: @@ -107,6 +144,8 @@ public: { delete this; } + + virtual int classLevel() { return 1; } }; int Data::generationCounter = 0; int Data::destructorCounter = 0; @@ -156,8 +195,8 @@ void tst_QSharedPointer::basics() QVERIFY(! (ptr == otherData)); QVERIFY(! (otherData == ptr)); } - QVERIFY(!ptr.d || ptr.d->weakref == 1); - QVERIFY(!ptr.d || ptr.d->strongref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1); { // create another object: @@ -169,8 +208,8 @@ void tst_QSharedPointer::basics() // otherData is deleted here } - QVERIFY(!ptr.d || ptr.d->weakref == 1); - QVERIFY(!ptr.d || ptr.d->strongref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1); { // create a copy: @@ -186,8 +225,8 @@ void tst_QSharedPointer::basics() QCOMPARE(copy.data(), aData); QVERIFY(copy == aData); } - QVERIFY(!ptr.d || ptr.d->weakref == 1); - QVERIFY(!ptr.d || ptr.d->strongref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1); { // create a weak reference: @@ -218,23 +257,48 @@ void tst_QSharedPointer::basics() QVERIFY(strong == ptr); QCOMPARE(strong.data(), aData); } - QVERIFY(!ptr.d || ptr.d->weakref == 1); - QVERIFY(!ptr.d || ptr.d->strongref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref == 1); // aData is deleted here } class ForwardDeclared; +ForwardDeclared *forwardPointer(); +void externalForwardDeclaration(); +extern int forwardDeclaredDestructorRunCount; + void tst_QSharedPointer::forwardDeclaration1() { - class Wrapper { QSharedPointer<ForwardDeclared> pointer; }; +#if defined(Q_CC_SUN) + QSKIP("This type of forward declaration is not valid with this compiler", SkipAll); +#else + externalForwardDeclaration(); + + struct Wrapper { QSharedPointer<ForwardDeclared> pointer; }; + + forwardDeclaredDestructorRunCount = 0; + { + Wrapper w; + w.pointer = QSharedPointer<ForwardDeclared>(forwardPointer()); + QVERIFY(!w.pointer.isNull()); + } + QCOMPARE(forwardDeclaredDestructorRunCount, 1); +#endif } -class ForwardDeclared { }; +#include "forwarddeclared.h" + void tst_QSharedPointer::forwardDeclaration2() { - class Wrapper { QSharedPointer<ForwardDeclared> pointer; }; - Wrapper w; + forwardDeclaredDestructorRunCount = 0; + { + struct Wrapper { QSharedPointer<ForwardDeclared> pointer; }; + Wrapper w1, w2; + w1.pointer = QSharedPointer<ForwardDeclared>(forwardPointer()); + QVERIFY(!w1.pointer.isNull()); + } + QCOMPARE(forwardDeclaredDestructorRunCount, 1); } void tst_QSharedPointer::memoryManagement() @@ -314,6 +378,8 @@ public: { delete this; } + + virtual int classLevel() { return 2; } }; int DerivedData::derivedDestructorCounter = 0; @@ -321,15 +387,23 @@ class Stuffing { public: char buffer[16]; + Stuffing() { for (uint i = 0; i < sizeof buffer; ++i) buffer[i] = 16 - i; } virtual ~Stuffing() { } }; class DiffPtrDerivedData: public Stuffing, public Data { +public: + virtual int classLevel() { return 3; } }; class VirtualDerived: virtual public Data { +public: + int moreData; + + VirtualDerived() : moreData(0xc0ffee) { } + virtual int classLevel() { return 4; } }; void tst_QSharedPointer::downCast() @@ -400,15 +474,15 @@ void tst_QSharedPointer::upCast() QVERIFY(baseptr == derivedptr); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr); QVERIFY(baseptr == derivedptr); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -416,16 +490,122 @@ void tst_QSharedPointer::upCast() QVERIFY(baseptr == derivedptr); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>(); QVERIFY(baseptr == derivedptr); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); +} + +class OtherObject: public QObject +{ + Q_OBJECT +}; + +void tst_QSharedPointer::objectCast() +{ + { + OtherObject *data = new OtherObject; + QSharedPointer<QObject> baseptr = QSharedPointer<QObject>(data); + QVERIFY(baseptr == data); + QVERIFY(data == baseptr); + + // perform object cast + QSharedPointer<OtherObject> ptr = qSharedPointerObjectCast<OtherObject>(baseptr); + QVERIFY(!ptr.isNull()); + QCOMPARE(ptr.data(), data); + QVERIFY(ptr == data); + + // again: + ptr = baseptr.objectCast<OtherObject>(); + QVERIFY(ptr == data); + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + // again: + ptr = qobject_cast<OtherObject *>(baseptr); + QVERIFY(ptr == data); + + // again: + ptr = qobject_cast<QSharedPointer<OtherObject> >(baseptr); + QVERIFY(ptr == data); +#endif + } + check(); + + { + const OtherObject *data = new OtherObject; + QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(data); + QVERIFY(baseptr == data); + QVERIFY(data == baseptr); + + // perform object cast + QSharedPointer<const OtherObject> ptr = qSharedPointerObjectCast<const OtherObject>(baseptr); + QVERIFY(!ptr.isNull()); + QCOMPARE(ptr.data(), data); + QVERIFY(ptr == data); + + // again: + ptr = baseptr.objectCast<const OtherObject>(); + QVERIFY(ptr == data); + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + // again: + ptr = qobject_cast<const OtherObject *>(baseptr); + QVERIFY(ptr == data); + + // again: + ptr = qobject_cast<QSharedPointer<const OtherObject> >(baseptr); + QVERIFY(ptr == data); +#endif + } + check(); + + { + OtherObject *data = new OtherObject; + QPointer<OtherObject> qptr = data; + QSharedPointer<OtherObject> ptr = QSharedPointer<OtherObject>(data); + QWeakPointer<QObject> weakptr = ptr; + + { + // perform object cast + QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr); + QVERIFY(otherptr == ptr); + + // again: + otherptr = qobject_cast<OtherObject *>(weakptr); + QVERIFY(otherptr == ptr); + + // again: + otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr); + QVERIFY(otherptr == ptr); + } + + // drop the reference: + ptr.clear(); + QVERIFY(ptr.isNull()); + QVERIFY(qptr.isNull()); + QVERIFY(weakptr.toStrongRef().isNull()); + + // verify that the object casts fail without crash + QSharedPointer<OtherObject> otherptr = qSharedPointerObjectCast<OtherObject>(weakptr); + QVERIFY(otherptr.isNull()); + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + // again: + otherptr = qobject_cast<OtherObject *>(weakptr); + QVERIFY(otherptr.isNull()); + + // again: + otherptr = qobject_cast<QSharedPointer<OtherObject> >(weakptr); + QVERIFY(otherptr.isNull()); +#endif + } + check(); } void tst_QSharedPointer::differentPointers() @@ -445,6 +625,7 @@ void tst_QSharedPointer::differentPointers() QVERIFY(baseptr == aData); QVERIFY(baseptr == aBase); } + check(); { DiffPtrDerivedData *aData = new DiffPtrDerivedData; @@ -459,6 +640,7 @@ void tst_QSharedPointer::differentPointers() QVERIFY(ptr == aBase); QVERIFY(baseptr == aData); } + check(); { DiffPtrDerivedData *aData = new DiffPtrDerivedData; @@ -475,6 +657,7 @@ void tst_QSharedPointer::differentPointers() QVERIFY(baseptr == aData); QVERIFY(baseptr == aBase); } + check(); } void tst_QSharedPointer::virtualBaseDifferentPointers() @@ -494,6 +677,7 @@ void tst_QSharedPointer::virtualBaseDifferentPointers() QVERIFY(baseptr == aData); QVERIFY(baseptr == aBase); } + check(); { VirtualDerived *aData = new VirtualDerived; @@ -510,6 +694,7 @@ void tst_QSharedPointer::virtualBaseDifferentPointers() QVERIFY(baseptr == aData); QVERIFY(baseptr == aBase); } + check(); } #ifndef QTEST_NO_RTTI @@ -524,8 +709,8 @@ void tst_QSharedPointer::dynamicCast() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -534,8 +719,8 @@ void tst_QSharedPointer::dynamicCast() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>(); @@ -543,8 +728,8 @@ void tst_QSharedPointer::dynamicCast() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); } void tst_QSharedPointer::dynamicCastDifferentPointers() @@ -559,8 +744,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -569,8 +754,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QSharedPointer<DiffPtrDerivedData> derivedptr = baseptr.dynamicCast<DiffPtrDerivedData>(); @@ -578,8 +763,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { Stuffing *nakedptr = dynamic_cast<Stuffing *>(baseptr.data()); @@ -604,8 +789,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -614,8 +799,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QSharedPointer<VirtualDerived> derivedptr = baseptr.dynamicCast<VirtualDerived>(); @@ -623,8 +808,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); } void tst_QSharedPointer::dynamicCastFailure() @@ -636,15 +821,15 @@ void tst_QSharedPointer::dynamicCastFailure() QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr); QVERIFY(derivedptr.isNull()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); { QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>(); QVERIFY(derivedptr.isNull()); } - QCOMPARE(int(baseptr.d->weakref), 1); - QCOMPARE(int(baseptr.d->strongref), 1); + QCOMPARE(int(refCountData(baseptr)->weakref), 1); + QCOMPARE(int(refCountData(baseptr)->strongref), 1); } #endif @@ -676,6 +861,7 @@ void tst_QSharedPointer::constCorrectness() ptr = cvptr.constCast<Data>(); #endif } + check(); { Data *aData = new Data; @@ -689,6 +875,7 @@ void tst_QSharedPointer::constCorrectness() QCOMPARE(cptr.data(), aData); QCOMPARE(cptr.operator->(), aData); } + check(); } static int customDeleterFnCallCount; @@ -698,9 +885,14 @@ void customDeleterFn(Data *ptr) delete ptr; } +static int refcount; + template <typename T> struct CustomDeleter { + CustomDeleter() { ++refcount; } + CustomDeleter(const CustomDeleter &) { ++refcount; } + ~CustomDeleter() { --refcount; } inline void operator()(T *ptr) { delete ptr; @@ -717,11 +909,13 @@ void tst_QSharedPointer::customDeleter() QSharedPointer<Data> ptr2(new Data, &Data::alsoDelete); QSharedPointer<Data> ptr3(new Data, &Data::virtualDelete); } + check(); { QSharedPointer<DerivedData> ptr(new DerivedData, &Data::doDelete); QSharedPointer<DerivedData> ptr2(new DerivedData, &Data::alsoDelete); QSharedPointer<DerivedData> ptr3(new DerivedData, &Data::virtualDelete); } + check(); customDeleterFnCallCount = 0; { @@ -730,6 +924,7 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 0); } QCOMPARE(customDeleterFnCallCount, 1); + check(); customDeleterFnCallCount = 0; { @@ -739,6 +934,7 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 1); } QCOMPARE(customDeleterFnCallCount, 1); + check(); customDeleterFnCallCount = 0; { @@ -748,6 +944,7 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 1); } QCOMPARE(customDeleterFnCallCount, 1); + check(); customDeleterFnCallCount = 0; { @@ -756,6 +953,7 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 0); } QCOMPARE(customDeleterFnCallCount, 1); + check(); customDeleterFnCallCount = 0; { @@ -764,6 +962,7 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 0); } QCOMPARE(customDeleterFnCallCount, 1); + check(); customDeleterFnCallCount = 0; { @@ -776,6 +975,7 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 0); } QCOMPARE(customDeleterFnCallCount, 1); + check(); customDeleterFnCallCount = 0; { @@ -788,7 +988,9 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(customDeleterFnCallCount, 0); } QCOMPARE(customDeleterFnCallCount, 1); + check(); + refcount = 0; CustomDeleter<Data> dataDeleter; dataDeleter.callCount = 0; { @@ -797,6 +999,8 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(dataDeleter.callCount, 0); } QCOMPARE(dataDeleter.callCount, 1); + QCOMPARE(refcount, 1); + check(); dataDeleter.callCount = 0; { @@ -806,6 +1010,8 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(dataDeleter.callCount, 0); } QCOMPARE(dataDeleter.callCount, 1); + QCOMPARE(refcount, 1); + check(); dataDeleter.callCount = 0; { @@ -818,6 +1024,8 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(dataDeleter.callCount, 0); } QCOMPARE(dataDeleter.callCount, 1); + QCOMPARE(refcount, 1); + check(); dataDeleter.callCount = 0; { @@ -826,6 +1034,8 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(dataDeleter.callCount, 0); } QCOMPARE(dataDeleter.callCount, 1); + QCOMPARE(refcount, 1); + check(); CustomDeleter<DerivedData> derivedDataDeleter; derivedDataDeleter.callCount = 0; @@ -838,6 +1048,8 @@ void tst_QSharedPointer::customDeleter() } QCOMPARE(dataDeleter.callCount, 0); QCOMPARE(derivedDataDeleter.callCount, 1); + QCOMPARE(refcount, 2); + check(); derivedDataDeleter.callCount = 0; dataDeleter.callCount = 0; @@ -854,6 +1066,8 @@ void tst_QSharedPointer::customDeleter() } QCOMPARE(dataDeleter.callCount, 1); QCOMPARE(derivedDataDeleter.callCount, 0); + QCOMPARE(refcount, 2); + check(); derivedDataDeleter.callCount = 0; dataDeleter.callCount = 0; @@ -870,6 +1084,225 @@ void tst_QSharedPointer::customDeleter() } QCOMPARE(dataDeleter.callCount, 0); QCOMPARE(derivedDataDeleter.callCount, 1); + QCOMPARE(refcount, 2); +} + +void tst_QSharedPointer::creating() +{ + Data::generationCounter = Data::destructorCounter = 0; + { + QSharedPointer<Data> ptr = QSharedPointer<Data>::create(); + QVERIFY(ptr.data()); + QCOMPARE(Data::generationCounter, 1); + QCOMPARE(ptr->generation, 1); + QCOMPARE(Data::destructorCounter, 0); + + QCOMPARE(ptr->classLevel(), 1); + + ptr.clear(); + QCOMPARE(Data::destructorCounter, 1); + } + check(); + + Data::generationCounter = Data::destructorCounter = 0; + { + QSharedPointer<Data> ptr = QSharedPointer<Data>::create(); + QWeakPointer<Data> weakptr = ptr; + QtSharedPointer::ExternalRefCountData *d = refCountData(ptr); + + ptr.clear(); + QVERIFY(ptr.isNull()); + QCOMPARE(Data::destructorCounter, 1); + + // valgrind will complain here if something happened to the pointer + QVERIFY(d->weakref == 1); + QVERIFY(d->strongref == 0); + } + check(); + + Data::generationCounter = Data::destructorCounter = 0; + DerivedData::derivedDestructorCounter = 0; + { + QSharedPointer<Data> ptr = QSharedPointer<DerivedData>::create(); + QCOMPARE(ptr->classLevel(), 2); + QCOMPARE(ptr.staticCast<DerivedData>()->moreData, 0); + ptr.clear(); + + QCOMPARE(Data::destructorCounter, 1); + QCOMPARE(DerivedData::derivedDestructorCounter, 1); + } + check(); + + { + QSharedPointer<Data> ptr = QSharedPointer<DiffPtrDerivedData>::create(); + QCOMPARE(ptr->classLevel(), 3); + QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[7]+0, 16-7); + QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[3]+0, 16-3); + QCOMPARE(ptr.staticCast<DiffPtrDerivedData>()->buffer[0]+0, 16); + } + check(); + + { + QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>::create(); + QCOMPARE(ptr->classLevel(), 4); + QCOMPARE(ptr->moreData, 0xc0ffee); + + QSharedPointer<Data> baseptr = ptr; + QCOMPARE(baseptr->classLevel(), 4); + } + check(); + + { + QSharedPointer<QObject> ptr = QSharedPointer<QObject>::create(); + QCOMPARE(ptr->metaObject(), &QObject::staticMetaObject); + + QPointer<QObject> qptr = ptr.data(); + ptr.clear(); + + QVERIFY(qptr.isNull()); + } + check(); + + { + QSharedPointer<QObject> ptr = QSharedPointer<OtherObject>::create(); + QCOMPARE(ptr->metaObject(), &OtherObject::staticMetaObject); + } + check(); +} + +void tst_QSharedPointer::mixTrackingPointerCode() +{ + { + // pointer created with tracking + // deleted in code without tracking + QSharedPointer<int> ptr = QSharedPointer<int>(new int(42)); + Wrapper w(ptr); + ptr.clear(); + } + check(); + + { + // pointer created without tracking + // deleted in code with tracking + Wrapper w = Wrapper::create(); + w.ptr.clear(); + } +} + +class ThreadData +{ + QAtomicInt * volatile ptr; +public: + ThreadData(QAtomicInt *p) : ptr(p) { } + ~ThreadData() { ++ptr; } + void ref() + { + // if we're called after the destructor, we'll crash + ptr->ref(); + } +}; + +class StrongThread: public QThread +{ +protected: + void run() + { + usleep(rand() % 2000); + ptr->ref(); + ptr.clear(); + } +public: + QSharedPointer<ThreadData> ptr; +}; + +class WeakThread: public QThread +{ +protected: + void run() + { + usleep(rand() % 2000); + QSharedPointer<ThreadData> ptr = weak; + if (ptr) + ptr->ref(); + ptr.clear(); + } +public: + QWeakPointer<ThreadData> weak; +}; + +void tst_QSharedPointer::threadStressTest_data() +{ + QTest::addColumn<int>("strongThreadCount"); + QTest::addColumn<int>("weakThreadCount"); + + QTest::newRow("0+0") << 0 << 0; + QTest::newRow("1+0") << 1 << 0; + QTest::newRow("2+0") << 2 << 0; + QTest::newRow("10+0") << 10 << 0; + + QTest::newRow("0+1") << 0 << 1; + QTest::newRow("1+1") << 1 << 1; + + QTest::newRow("2+10") << 2 << 10; + QTest::newRow("5+10") << 5 << 10; + QTest::newRow("5+30") << 5 << 30; + + QTest::newRow("100+100") << 100 << 100; +} + +void tst_QSharedPointer::threadStressTest() +{ + QFETCH(int, strongThreadCount); + QFETCH(int, weakThreadCount); + + int guard1[128]; + QAtomicInt counter; + int guard2[128]; + + memset(guard1, 0, sizeof guard1); + memset(guard2, 0, sizeof guard2); + + for (int r = 0; r < 5; ++r) { + QVector<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0); + QSharedPointer<ThreadData> base = QSharedPointer<ThreadData>(new ThreadData(&counter)); + counter = 0; + + // set the pointers + for (int i = 0; i < strongThreadCount; ++i) { + StrongThread *t = new StrongThread; + t->ptr = base; + allThreads[2 * i] = t; + } + for (int i = 0; i < weakThreadCount; ++i) { + WeakThread *t = new WeakThread; + t->weak = base; + allThreads[6 * i + 3] = t; + } + + base.clear(); + + srand(time(NULL)); + // start threads + for (int i = 0; i < allThreads.count(); ++i) + if (allThreads[i]) allThreads[i]->start(); + + // wait for them to finish + for (int i = 0; i < allThreads.count(); ++i) + if (allThreads[i]) allThreads[i]->wait(); + qDeleteAll(allThreads); + + // ensure the guards aren't touched + for (uint i = 0; i < sizeof guard1 / sizeof guard1[0]; ++i) + QVERIFY(!guard1[i]); + for (uint i = 0; i < sizeof guard2 / sizeof guard2[0]; ++i) + QVERIFY(!guard2[i]); + + // verify that the count is the right range + int minValue = strongThreadCount; + int maxValue = strongThreadCount + weakThreadCount; + QVERIFY(counter >= minValue); + QVERIFY(counter <= maxValue); + } } void tst_QSharedPointer::validConstructs() @@ -919,8 +1352,13 @@ void tst_QSharedPointer::invalidConstructs_data() // use of forward-declared class QTest::newRow("forward-declaration") + << &QTest::QExternalTest::tryRun + << "forwardDeclaredDestructorRunCount = 0;\n" + "{ QSharedPointer<ForwardDeclared> ptr = QSharedPointer<ForwardDeclared>(forwardPointer()); }\n" + "exit(forwardDeclaredDestructorRunCount);"; + QTest::newRow("creating-forward-declaration") << &QTest::QExternalTest::tryCompileFail - << "QSharedPointer<ForwardDeclared> ptr;"; + << "QSharedPointer<ForwardDeclared>::create();"; // upcast without cast operator: QTest::newRow("upcast1") @@ -943,6 +1381,26 @@ void tst_QSharedPointer::invalidConstructs_data() << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n" "QSharedPointer<Data> ptr;" "ptr = baseptr;"; + QTest::newRow("const-dropping-static-cast") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n" + "qSharedPointerCast<DerivedData>(baseptr);"; +#ifndef QTEST_NO_RTTI + QTest::newRow("const-dropping-dynamic-cast") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n" + "qSharedPointerDynamicCast<DerivedData>(baseptr);"; +#endif + QTest::newRow("const-dropping-object-cast1") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n" + "qSharedPointerObjectCast<QCoreApplication>(baseptr);"; +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + QTest::newRow("const-dropping-object-cast2") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer<const QObject> baseptr = QSharedPointer<const QObject>(new QObject);\n" + "qobject_cast<QCoreApplication *>(baseptr);"; +#endif // arithmethics through automatic cast operators QTest::newRow("arithmethic1") @@ -956,6 +1414,7 @@ void tst_QSharedPointer::invalidConstructs_data() "QSharedPointer<Data> b;\n" "if (a + b) return;"; +#if QT_VERSION >= 0x040600 // two objects with the same pointer QTest::newRow("same-pointer") << &QTest::QExternalTest::tryRunFail @@ -969,6 +1428,7 @@ void tst_QSharedPointer::invalidConstructs_data() << "Data *aData = new Data;\n" "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);" "ptr1 = QSharedPointer<Data>(aData);"; +#endif // any type of cast for unrelated types: // (we have no reinterpret_cast) @@ -986,6 +1446,10 @@ void tst_QSharedPointer::invalidConstructs_data() << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<Data> ptr1;\n" "QSharedPointer<int> ptr2 = qSharedPointerConstCast<int>(ptr1);"; + QTest::newRow("invalid-cast4") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer<Data> ptr1;\n" + "QSharedPointer<int> ptr2 = qSharedPointerObjectCast<int>(ptr1);"; } void tst_QSharedPointer::invalidConstructs() @@ -1000,13 +1464,19 @@ void tst_QSharedPointer::invalidConstructs() QTest::QExternalTest test; test.setDebugMode(true); test.setQtModules(QTest::QExternalTest::QtCore); + test.setExtraProgramSources(QStringList() << SRCDIR "forwarddeclared.cpp"); test.setProgramHeader( "#define QT_SHAREDPOINTER_TRACK_POINTERS\n" "#include <QtCore/qsharedpointer.h>\n" + "#include <QtCore/qcoreapplication.h>\n" "\n" "struct Data { int i; };\n" "struct DerivedData: public Data { int j; };\n" - "struct ForwardDeclared;"); + "\n" + "extern int forwardDeclaredDestructorRunCount;\n" + "struct ForwardDeclared;\n" + "ForwardDeclared *forwardPointer();\n" + ); QFETCH(QString, code); static bool sane = true; diff --git a/tests/auto/qsharedpointer/wrapper.cpp b/tests/auto/qsharedpointer/wrapper.cpp new file mode 100644 index 0000000..7640e68 --- /dev/null +++ b/tests/auto/qsharedpointer/wrapper.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef QT_SHAREDPOINTER_TRACK_POINTERS +# undef QT_SHAREDPOINTER_TRACK_POINTERS +#endif +#include <QtCore/qsharedpointer.h> +#include "wrapper.h" + +Wrapper::Wrapper(const QSharedPointer<int> &value) + : ptr(value) +{ +} + +Wrapper::~Wrapper() +{ +} + +Wrapper Wrapper::create() +{ + return Wrapper(QSharedPointer<int>(new int(-47))); +} diff --git a/tests/auto/qsharedpointer/wrapper.h b/tests/auto/qsharedpointer/wrapper.h new file mode 100644 index 0000000..a888063 --- /dev/null +++ b/tests/auto/qsharedpointer/wrapper.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef WRAPPER_H +#define WRAPPER_H + +template <class T> class QSharedPointer; +class Wrapper +{ +public: + QSharedPointer<int> ptr; + Wrapper(const QSharedPointer<int> &); + ~Wrapper(); + + static Wrapper create(); +}; + +#endif // WRAPPER_H |