diff options
Diffstat (limited to 'tests/auto/corelib/tools/qsharedpointer')
12 files changed, 556 insertions, 514 deletions
diff --git a/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt b/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt new file mode 100644 index 0000000000..0db0cba4c0 --- /dev/null +++ b/tests/auto/corelib/tools/qsharedpointer/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qsharedpointer Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsharedpointer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qsharedpointer + SOURCES + forwarddeclared.cpp + nontracked.cpp + wrapper.cpp + tst_qsharedpointer.cpp + LIBRARIES + Qt::CorePrivate +) diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp index d1bb89f549..c676924668 100644 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "externaltests.h" @@ -80,32 +55,34 @@ namespace QTest { { if (process.state() == QProcess::Running) { process.terminate(); - QThread::msleep(20); + QThread::sleep(std::chrono::milliseconds{20}); if (process.state() == QProcess::Running) process.kill(); } } +# ifdef Q_OS_UNIX class QExternalProcess: public QProcess { - protected: -#ifdef Q_OS_UNIX - void setupChildProcess() + public: + QExternalProcess() { - // 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); - } + setChildProcessModifier([this]() { + // run in user code + 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 }; +# else + using QExternalProcess = QProcess; +# endif #endif // QT_CONFIG(process) class QExternalTestPrivate @@ -341,7 +318,7 @@ namespace QTest { if (qtModules & QExternalTest::QtScript) sourceCode += "#include <QtScript/QtScript>\n"; if (qtModules & QExternalTest::QtTest) - sourceCode += "#include <QtTest/QtTest>\n"; + sourceCode += "#include <QTest>\n"; if (qtModules & QExternalTest::QtDBus) sourceCode += "#include <QtDBus/QtDBus>\n"; if (qtModules & QExternalTest::QtWebKit) @@ -360,7 +337,7 @@ namespace QTest { "}\n" "\n" "#ifdef Q_OS_WIN\n" - "#include <windows.h>\n" + "#include <qt_windows.h>\n" "#if defined(Q_CC_MSVC)\n" "#include <crtdbg.h>\n" "#endif\n" @@ -588,7 +565,7 @@ namespace QTest { << QLatin1String("project.pro"); qmake.setWorkingDirectory(temporaryDirPath); - QString cmd = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmake"; + QString cmd = QLibraryInfo::path(QLibraryInfo::BinariesPath) + "/qmake"; #ifdef Q_OS_WIN cmd.append(".exe"); #endif diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.h b/tests/auto/corelib/tools/qsharedpointer/externaltests.h index bae6adaefe..790ca61992 100644 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.h +++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QTEST_EXTERNAL_TESTS_H diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.pri b/tests/auto/corelib/tools/qsharedpointer/externaltests.pri deleted file mode 100644 index 604bd7f59f..0000000000 --- a/tests/auto/corelib/tools/qsharedpointer/externaltests.pri +++ /dev/null @@ -1,6 +0,0 @@ -SOURCES += $$PWD/externaltests.cpp -HEADERS += $$PWD/externaltests.h -cleanedQMAKESPEC = $$replace(QMAKESPEC, \\\\, /) -DEFINES += DEFAULT_MAKESPEC=\\\"$$cleanedQMAKESPEC\\\" - -cross_compile:DEFINES += QTEST_NO_RTTI QTEST_CROSS_COMPILED diff --git a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp index df343b5ebc..5a0af60c11 100644 --- a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "forwarddeclared.h" #include "qsharedpointer.h" diff --git a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h index c72324841c..ba436d99cf 100644 --- a/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h +++ b/tests/auto/corelib/tools/qsharedpointer/forwarddeclared.h @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef FORWARDDECLARED_H #define FORWARDDECLARED_H diff --git a/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp b/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp index e0780f8a9a..b572fa1b9f 100644 --- a/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/nontracked.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only /* * This file exists because tst_qsharedpointer.cpp is compiled with @@ -40,7 +15,7 @@ */ #include <qsharedpointer.h> -#include <QtTest> +#include <QTest> #include "nontracked.h" diff --git a/tests/auto/corelib/tools/qsharedpointer/nontracked.h b/tests/auto/corelib/tools/qsharedpointer/nontracked.h index 76af80d2d7..e10ea08a4d 100644 --- a/tests/auto/corelib/tools/qsharedpointer/nontracked.h +++ b/tests/auto/corelib/tools/qsharedpointer/nontracked.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef NONTRACKED_H #define NONTRACKED_H diff --git a/tests/auto/corelib/tools/qsharedpointer/qsharedpointer.pro b/tests/auto/corelib/tools/qsharedpointer/qsharedpointer.pro deleted file mode 100644 index 240137d563..0000000000 --- a/tests/auto/corelib/tools/qsharedpointer/qsharedpointer.pro +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG += testcase -TARGET = tst_qsharedpointer -QT = core testlib - -SOURCES = tst_qsharedpointer.cpp \ - forwarddeclared.cpp \ - nontracked.cpp \ - wrapper.cpp - -HEADERS = forwarddeclared.h \ - nontracked.h \ - wrapper.h - -TESTDATA += forwarddeclared.cpp forwarddeclared.h - -include(externaltests.pri) -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index ade9c5e754..f42637a3fe 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -1,49 +1,29 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// Copyright (C) 2021 Klarälvdalens Datakonsult AB. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #define QT_SHAREDPOINTER_TRACK_POINTERS #include "qsharedpointer.h" -#include <QtTest/QtTest> +#include <QTest> +#include <QPointer> +#include <QRandomGenerator> #include <QtCore/QHash> +#include <QtCore/QList> #include <QtCore/QMap> #include <QtCore/QThread> -#include <QtCore/QVector> +#include <QtCore/private/qvolatile_p.h> -#include "externaltests.h" #include "forwarddeclared.h" #include "nontracked.h" #include "wrapper.h" +#include <array> +#include <memory> #include <stdlib.h> #include <time.h> -#ifdef Q_OS_UNIX +#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) #include <sys/resource.h> #endif @@ -74,10 +54,9 @@ private slots: void functionCallDownCast(); void upCast(); void qobjectWeakManagement(); - void noSharedPointerFromWeakQObject(); - void sharedPointerFromQObjectWithWeak(); void weakQObjectFromSharedPointer(); void objectCast(); + void objectCastStdSharedPtr(); void differentPointers(); void virtualBaseDifferentPointers(); #ifndef QTEST_NO_RTTI @@ -89,9 +68,8 @@ private slots: #endif void constCorrectness(); void customDeleter(); -#ifdef Q_COMPILER_LAMBDA void lambdaCustomDeleter(); -#endif + void customDeleterOnNullptr(); void creating(); void creatingCvQualified(); void creatingVariadic(); @@ -104,12 +82,17 @@ private slots: void sharedFromThis(); void constructorThrow(); + void overloads(); void threadStressTest_data(); void threadStressTest(); void validConstructs(); +#if 0 void invalidConstructs_data(); void invalidConstructs(); +#endif + void ownerComparisons(); + // let invalidConstructs be the last test, because it's the slowest; // add new tests above this block public slots: @@ -126,7 +109,7 @@ public: void tst_QSharedPointer::initTestCase() { -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) // The tests create a lot of threads, which require file descriptors. On systems like // OS X low defaults such as 256 as the limit for the number of simultaneously // open files is not sufficient. @@ -147,7 +130,7 @@ QtSharedPointer::ExternalRefCountData *refCountData(const QSharedPointer<T> &b) QtSharedPointer::ExternalRefCountData* data; }; // sanity checks: - Q_STATIC_ASSERT(sizeof(QSharedPointer<T>) == sizeof(Dummy)); + static_assert(sizeof(QSharedPointer<T>) == sizeof(Dummy)); Q_ASSERT(static_cast<const Dummy*>(static_cast<const void*>(&b))->value == b.data()); return static_cast<const Dummy*>(static_cast<const void*>(&b))->data; } @@ -226,13 +209,17 @@ struct NoDefaultConstructorConstRef2 NoDefaultConstructorConstRef2(const QByteArray &ba, int i = 42) : str(QString::fromLatin1(ba)), i(i) {} }; -#ifdef Q_COMPILER_RVALUE_REFS struct NoDefaultConstructorRRef1 { int &i; NoDefaultConstructorRRef1(int &&i) : i(i) {} }; -#endif + +struct NoDefaultConstructorRRef2 +{ + std::unique_ptr<int> i; + NoDefaultConstructorRRef2(std::unique_ptr<int> &&i) : i(std::move(i)) {} +}; void tst_QSharedPointer::basics_data() { @@ -290,8 +277,8 @@ void tst_QSharedPointer::basics() QVERIFY(! (ptr == otherData)); QVERIFY(! (otherData == ptr)); } - QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1); - QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1); { // create another object: @@ -303,8 +290,8 @@ void tst_QSharedPointer::basics() // otherData is deleted here } - QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1); - QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1); { // create a copy: @@ -321,8 +308,8 @@ void tst_QSharedPointer::basics() QCOMPARE(copy.get(), aData); QVERIFY(copy == aData); } - QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1); - QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1); { // create a weak reference: @@ -331,6 +318,11 @@ void tst_QSharedPointer::basics() QCOMPARE(!weak, isNull); QCOMPARE(bool(weak), !isNull); + QCOMPARE(weak.isNull(), (weak == nullptr)); + QCOMPARE(weak.isNull(), (nullptr == weak)); + QCOMPARE(!weak.isNull(), (weak != nullptr)); + QCOMPARE(!weak.isNull(), (nullptr != weak)); + QVERIFY(ptr == weak); QVERIFY(weak == ptr); QVERIFY(! (ptr != weak)); @@ -354,8 +346,8 @@ void tst_QSharedPointer::basics() QCOMPARE(strong.data(), aData); QCOMPARE(strong.get(), aData); } - QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.load() == 1); - QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.load() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->weakref.loadRelaxed() == 1); + QVERIFY(!refCountData(ptr) || refCountData(ptr)->strongref.loadRelaxed() == 1); // aData is deleted here } @@ -416,6 +408,12 @@ void tst_QSharedPointer::nullptrOps() QVERIFY(!p2.get()); QVERIFY(p1 == p2); + QWeakPointer<char> wp1 = p1; + QVERIFY(wp1 == nullptr); + QVERIFY(nullptr == wp1); + QCOMPARE(wp1, nullptr); + QCOMPARE(nullptr, wp1); + QSharedPointer<char> p3 = p1; QVERIFY(p3 == p1); QVERIFY(p3 == null); @@ -442,6 +440,10 @@ void tst_QSharedPointer::nullptrOps() QVERIFY(p4 != p2); QVERIFY(p4 != null); QVERIFY(p4 != p3); + + QWeakPointer<char> wp2 = p4; + QVERIFY(wp2 != nullptr); + QVERIFY(nullptr != wp2); } void tst_QSharedPointer::swap() @@ -501,7 +503,6 @@ void tst_QSharedPointer::swap() void tst_QSharedPointer::moveSemantics() { -#ifdef Q_COMPILER_RVALUE_REFS QSharedPointer<int> p1, p2(new int(42)), control = p2; QVERIFY(p1 != control); QVERIFY(p1.isNull()); @@ -554,9 +555,6 @@ void tst_QSharedPointer::moveSemantics() QVERIFY(w1.isNull()); QVERIFY(w2.isNull()); QVERIFY(w3.isNull()); -#else - QSKIP("This test requires C++11 rvalue/move semantics support in the compiler."); -#endif } void tst_QSharedPointer::useOfForwardDeclared() @@ -573,10 +571,10 @@ void tst_QSharedPointer::useOfForwardDeclared() // move assignment: QSharedPointer<ForwardDeclared> sp4; - sp4 = qMove(sp); + sp4 = std::move(sp); // and move constuction: - QSharedPointer<ForwardDeclared> sp5 = qMove(sp2); + QSharedPointer<ForwardDeclared> sp5 = std::move(sp2); // swapping: sp4.swap(sp3); @@ -588,6 +586,9 @@ void tst_QSharedPointer::useOfForwardDeclared() void tst_QSharedPointer::memoryManagement() { +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded") + int generation = Data::generationCounter + 1; int destructorCounter = Data::destructorCounter; @@ -649,6 +650,7 @@ void tst_QSharedPointer::memoryManagement() QVERIFY(ptr.isNull()); QVERIFY(ptr == 0); QCOMPARE(ptr.data(), (Data*)0); +QT_WARNING_POP } void tst_QSharedPointer::dropLastReferenceOfForwardDeclared() @@ -734,12 +736,12 @@ public: DerivedData() : moreData(0) { } ~DerivedData() { ++derivedDestructorCounter; } - virtual void virtualDelete() + void virtualDelete() override { delete this; } - virtual int classLevel() { return 2; } + int classLevel() override { return 2; } }; int DerivedData::derivedDestructorCounter = 0; @@ -754,7 +756,7 @@ public: class DiffPtrDerivedData: public Stuffing, public Data { public: - virtual int classLevel() { return 3; } + int classLevel() override { return 3; } }; class VirtualDerived: virtual public Data @@ -763,15 +765,20 @@ public: int moreData; VirtualDerived() : moreData(0xc0ffee) { } - virtual int classLevel() { return 4; } + int classLevel() override { return 4; } }; void tst_QSharedPointer::downCast() { { + // copy construction QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData); + QSharedPointer<DerivedData> copy = ptr; QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr); QSharedPointer<Data> other; + QWeakPointer<DerivedData> weak = ptr; + QWeakPointer<Data> baseweak = qSharedPointerCast<Data>(ptr); + QWeakPointer<Data> baseweak2 = qSharedPointerCast<Data>(weak); QVERIFY(ptr == baseptr); QVERIFY(baseptr == ptr); @@ -782,11 +789,55 @@ void tst_QSharedPointer::downCast() QVERIFY(other != ptr); QVERIFY(! (ptr == other)); QVERIFY(! (other == ptr)); + + // copy assignments + baseptr = qSharedPointerCast<Data>(ptr); + baseweak = qSharedPointerCast<Data>(ptr); + baseweak2 = baseweak; + + // move assignments (these don't actually move) + baseptr = qSharedPointerCast<Data>(std::move(ptr)); + ptr = copy; + baseweak = qSharedPointerCast<Data>(std::move(ptr)); + ptr = copy; + baseweak2 = qSharedPointerCast<Data>(std::move(baseweak)); + + // move construction (these don't actually move) + ptr = copy; + QSharedPointer<Data> ptr3(qSharedPointerCast<Data>(std::move(ptr))); + ptr = copy; + QWeakPointer<Data> baseweak3(qSharedPointerCast<Data>(std::move(ptr))); + ptr = copy; + QWeakPointer<Data> baseweak4(qSharedPointerCast<Data>(std::move(weak))); } { + // copy construction QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData); + QSharedPointer<DerivedData> copy = ptr; QSharedPointer<Data> baseptr = ptr; + QWeakPointer<DerivedData> weak = ptr; + QWeakPointer<Data> baseweak = ptr; + QWeakPointer<Data> baseweak2 = weak; + + // copy assignments + baseptr = ptr; + baseweak = ptr; + baseweak2 = weak; + + // move assignments (only the QSharedPointer-QSharedPointer actually moves) + baseweak = std::move(ptr); + baseweak2 = std::move(weak); + ptr = copy; + baseptr = std::move(ptr); + + // move construction (only the QSharedPointer-QSharedPointer actually moves) + ptr = copy; + QWeakPointer<Data> baseweak3(std::move(ptr)); + ptr = copy; + QWeakPointer<Data> baseweak4(std::move(weak)); + ptr = copy; + QSharedPointer<Data> baseptr2(std::move(ptr)); } int destructorCount; @@ -843,15 +894,15 @@ void tst_QSharedPointer::upCast() QVERIFY(baseptr == derivedptr); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr); QVERIFY(baseptr == derivedptr); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -859,16 +910,16 @@ void tst_QSharedPointer::upCast() QVERIFY(baseptr == derivedptr); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>(); QVERIFY(baseptr == derivedptr); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); } class OtherObject: public QObject @@ -882,17 +933,18 @@ void tst_QSharedPointer::qobjectWeakManagement() QWeakPointer<QObject> weak; weak = QWeakPointer<QObject>(); QVERIFY(weak.isNull()); - QVERIFY(!weak.data()); + QVERIFY(weak.toStrongRef().isNull()); } { QObject *obj = new QObject; - QWeakPointer<QObject> weak(obj); + QSharedPointer<QObject> shared(obj); + QWeakPointer<QObject> weak(shared); QVERIFY(!weak.isNull()); - QVERIFY(weak.data() == obj); + QVERIFY(weak.toStrongRef() == obj); // now delete - delete obj; + shared.reset(); QVERIFY(weak.isNull()); } safetyCheck(); @@ -900,41 +952,14 @@ void tst_QSharedPointer::qobjectWeakManagement() { // same, bit with operator= QObject *obj = new QObject; + QSharedPointer<QObject> shared(obj); QWeakPointer<QObject> weak; - weak = obj; + weak = shared; QVERIFY(!weak.isNull()); - QVERIFY(weak.data() == obj); + QVERIFY(weak.toStrongRef() == obj); // now delete - delete obj; - QVERIFY(weak.isNull()); - } - safetyCheck(); - - { - // delete triggered by parent - QObject *obj, *parent; - parent = new QObject; - obj = new QObject(parent); - QWeakPointer<QObject> weak(obj); - - // now delete the parent - delete parent; - QVERIFY(weak.isNull()); - } - safetyCheck(); - - { - // same as above, but set the parent after QWeakPointer is created - QObject *obj, *parent; - obj = new QObject; - QWeakPointer<QObject> weak(obj); - - parent = new QObject; - obj->setParent(parent); - - // now delete the parent - delete parent; + shared.reset(); QVERIFY(weak.isNull()); } safetyCheck(); @@ -942,16 +967,17 @@ void tst_QSharedPointer::qobjectWeakManagement() { // with two QWeakPointers QObject *obj = new QObject; - QWeakPointer<QObject> weak(obj); + QSharedPointer<QObject> shared(obj); + QWeakPointer<QObject> weak(shared); { - QWeakPointer<QObject> weak2(obj); + QWeakPointer<QObject> weak2(shared); QVERIFY(!weak2.isNull()); QVERIFY(weak == weak2); } QVERIFY(!weak.isNull()); - delete obj; + shared.reset(); QVERIFY(weak.isNull()); } safetyCheck(); @@ -959,13 +985,14 @@ void tst_QSharedPointer::qobjectWeakManagement() { // same, but delete the pointer while two QWeakPointers exist QObject *obj = new QObject; - QWeakPointer<QObject> weak(obj); + QSharedPointer<QObject> shared(obj); + QWeakPointer<QObject> weak(shared); { - QWeakPointer<QObject> weak2(obj); + QWeakPointer<QObject> weak2(shared); QVERIFY(!weak2.isNull()); - delete obj; + shared.reset(); QVERIFY(weak.isNull()); QVERIFY(weak2.isNull()); } @@ -974,51 +1001,17 @@ void tst_QSharedPointer::qobjectWeakManagement() safetyCheck(); } -void tst_QSharedPointer::noSharedPointerFromWeakQObject() -{ - // you're not allowed to create a QSharedPointer from an unmanaged QObject - QObject obj; - QWeakPointer<QObject> weak(&obj); - - { - QTest::ignoreMessage(QtWarningMsg , "QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer"); - QSharedPointer<QObject> strong = weak.toStrongRef(); - QVERIFY(strong.isNull()); - } - { - QTest::ignoreMessage(QtWarningMsg , "QSharedPointer: cannot create a QSharedPointer from a QObject-tracking QWeakPointer"); - QSharedPointer<QObject> strong = weak; - QVERIFY(strong.isNull()); - } - - QCOMPARE(weak.data(), &obj); - // if something went wrong, we'll probably crash here -} - -void tst_QSharedPointer::sharedPointerFromQObjectWithWeak() +void tst_QSharedPointer::weakQObjectFromSharedPointer() { - QObject *ptr = new QObject; - QWeakPointer<QObject> weak = ptr; { - QSharedPointer<QObject> shared(ptr); + QSharedPointer<QObject> shared(new QObject); + QWeakPointer<QObject> weak = shared; QVERIFY(!weak.isNull()); - QCOMPARE(shared.data(), ptr); - QCOMPARE(weak.data(), ptr); - } - QVERIFY(weak.isNull()); -} -void tst_QSharedPointer::weakQObjectFromSharedPointer() -{ - // this is the inverse of the above: you're allowed to create a QWeakPointer - // from a managed QObject - QSharedPointer<QObject> shared(new QObject); - QWeakPointer<QObject> weak = shared.data(); - QVERIFY(!weak.isNull()); - - // delete: - shared.clear(); - QVERIFY(weak.isNull()); + // delete: + shared.clear(); + QVERIFY(weak.isNull()); + } } void tst_QSharedPointer::objectCast() @@ -1115,6 +1108,60 @@ void tst_QSharedPointer::objectCast() safetyCheck(); } + +void tst_QSharedPointer::objectCastStdSharedPtr() +{ + { + OtherObject *data = new OtherObject; + std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data); + QVERIFY(baseptr.get() == data); + + // perform successful object cast + std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr); + QVERIFY(ptr.get()); + QVERIFY(ptr.get() == data); + + QVERIFY(baseptr.get() == data); + } + + { + OtherObject *data = new OtherObject; + std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data); + QVERIFY(baseptr.get() == data); + + // perform successful object cast + std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr)); + QVERIFY(ptr.get()); + QVERIFY(ptr.get() == data); + + QVERIFY(!baseptr.get()); + } + + { + QObject *data = new QObject; + std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data); + QVERIFY(baseptr.get() == data); + + // perform unsuccessful object cast + std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(baseptr); + QVERIFY(!ptr.get()); + + QVERIFY(baseptr.get() == data); + } + + { + QObject *data = new QObject; + std::shared_ptr<QObject> baseptr = std::shared_ptr<QObject>(data); + QVERIFY(baseptr.get() == data); + + // perform unsuccessful object cast + std::shared_ptr<OtherObject> ptr = qobject_pointer_cast<OtherObject>(std::move(baseptr)); + QVERIFY(!ptr.get()); + + QVERIFY(baseptr.get() == data); + } +} + void tst_QSharedPointer::differentPointers() { { @@ -1229,6 +1276,22 @@ void tst_QSharedPointer::virtualBaseDifferentPointers() QVERIFY(baseptr == aBase); } safetyCheck(); + { + VirtualDerived *aData = new VirtualDerived; + + QSharedPointer<VirtualDerived> ptr = QSharedPointer<VirtualDerived>(aData); + QWeakPointer<VirtualDerived> wptr = ptr; + + ptr.reset(); + QVERIFY(wptr.toStrongRef().isNull()); + + QWeakPointer<Data> wptr2 = wptr; + QVERIFY(wptr2.toStrongRef().isNull()); + + QWeakPointer<Data> wptr3 = std::move(wptr); + QVERIFY(wptr3.toStrongRef().isNull()); + } + safetyCheck(); } #ifndef QTEST_NO_RTTI @@ -1243,8 +1306,8 @@ void tst_QSharedPointer::dynamicCast() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -1253,8 +1316,8 @@ void tst_QSharedPointer::dynamicCast() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>(); @@ -1262,8 +1325,8 @@ void tst_QSharedPointer::dynamicCast() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); } void tst_QSharedPointer::dynamicCastDifferentPointers() @@ -1278,8 +1341,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -1288,8 +1351,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QSharedPointer<DiffPtrDerivedData> derivedptr = baseptr.dynamicCast<DiffPtrDerivedData>(); @@ -1297,8 +1360,8 @@ void tst_QSharedPointer::dynamicCastDifferentPointers() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { Stuffing *nakedptr = dynamic_cast<Stuffing *>(baseptr.data()); @@ -1323,8 +1386,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QWeakPointer<Data> weakptr = baseptr; @@ -1333,8 +1396,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QSharedPointer<VirtualDerived> derivedptr = baseptr.dynamicCast<VirtualDerived>(); @@ -1342,8 +1405,8 @@ void tst_QSharedPointer::dynamicCastVirtualBase() QCOMPARE(derivedptr.data(), aData); QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); } void tst_QSharedPointer::dynamicCastFailure() @@ -1355,15 +1418,15 @@ void tst_QSharedPointer::dynamicCastFailure() QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr); QVERIFY(derivedptr.isNull()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); { QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>(); QVERIFY(derivedptr.isNull()); } - QCOMPARE(int(refCountData(baseptr)->weakref.load()), 1); - QCOMPARE(int(refCountData(baseptr)->strongref.load()), 1); + QCOMPARE(int(refCountData(baseptr)->weakref.loadRelaxed()), 1); + QCOMPARE(int(refCountData(baseptr)->strongref.loadRelaxed()), 1); } void tst_QSharedPointer::dynamicCastFailureNoLeak() @@ -1670,7 +1733,6 @@ void tst_QSharedPointer::customDeleter() safetyCheck(); } -#ifdef Q_COMPILER_LAMBDA // The compiler needs to be in C++11 mode and to support lambdas void tst_QSharedPointer::lambdaCustomDeleter() { @@ -1698,7 +1760,33 @@ void tst_QSharedPointer::lambdaCustomDeleter() } safetyCheck(); } -#endif + +void tst_QSharedPointer::customDeleterOnNullptr() +{ + Data *null = nullptr; + int callCount = 0; + auto deleter = [&callCount](Data *) { ++callCount; }; + { + QSharedPointer<Data> ptr(null, deleter); + } + safetyCheck(); + QCOMPARE(callCount, 1); + + callCount = 0; + { + QSharedPointer<Data> ptr(nullptr, deleter); + } + safetyCheck(); + QCOMPARE(callCount, 1); + + callCount = 0; + { + QSharedPointer<Data> ptr1(null, deleter); + QSharedPointer<Data> ptr2(nullptr, deleter); + } + safetyCheck(); + QCOMPARE(callCount, 2); +} void customQObjectDeleterFn(QObject *obj) { @@ -1734,8 +1822,8 @@ void tst_QSharedPointer::creating() QCOMPARE(Data::destructorCounter, 1); // valgrind will complain here if something happened to the pointer - QVERIFY(d->weakref.load() == 1); - QVERIFY(d->strongref.load() == 0); + QVERIFY(d->weakref.loadRelaxed() == 1); + QVERIFY(d->strongref.loadRelaxed() == 0); } safetyCheck(); @@ -1820,15 +1908,20 @@ void tst_QSharedPointer::creatingVariadic() QCOMPARE(&ptr->i, &i); } { - NoDefaultConstructorRRef1(1); // control check - QSharedPointer<NoDefaultConstructorRRef1> ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(1); - QCOMPARE(ptr->i, 1); - NoDefaultConstructorRRef1(std::move(i)); // control check - ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(std::move(i)); + QSharedPointer<NoDefaultConstructorRRef1> ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(std::move(i)); QCOMPARE(ptr->i, i); } { + NoDefaultConstructorRRef2(std::unique_ptr<int>(new int(1))); // control check + QSharedPointer<NoDefaultConstructorRRef2> ptr = QSharedPointer<NoDefaultConstructorRRef2>::create(std::unique_ptr<int>(new int(1))); + QCOMPARE(*ptr->i, 1); + + std::unique_ptr<int> p(new int(i)); + ptr = QSharedPointer<NoDefaultConstructorRRef2>::create(std::move(p)); + QCOMPARE(*ptr->i, i); + } + { QString text("Hello, World"); NoDefaultConstructorRef2(text, 1); // control check QSharedPointer<NoDefaultConstructorRef2> ptr = QSharedPointer<NoDefaultConstructorRef2>::create(text, 1); @@ -1893,7 +1986,7 @@ class ThreadData QAtomicInt * volatile ptr; public: ThreadData(QAtomicInt *p) : ptr(p) { } - ~ThreadData() { ++ptr; } + ~ThreadData() { QtPrivate::volatilePreIncrement(ptr); } void ref() { // if we're called after the destructor, we'll crash @@ -1904,9 +1997,9 @@ public: class StrongThread: public QThread { protected: - void run() + void run() override { - usleep(QRandomGenerator::global()->bounded(2000)); + sleep(std::chrono::microseconds{QRandomGenerator::global()->bounded(2000)}); ptr->ref(); ptr.clear(); } @@ -1917,9 +2010,9 @@ public: class WeakThread: public QThread { protected: - void run() + void run() override { - usleep(QRandomGenerator::global()->bounded(2000)); + sleep(std::chrono::microseconds{QRandomGenerator::global()->bounded(2000)}); QSharedPointer<ThreadData> ptr = weak; if (ptr) ptr->ref(); @@ -1963,9 +2056,9 @@ void tst_QSharedPointer::threadStressTest() memset(guard2, 0, sizeof guard2); for (int r = 0; r < 5; ++r) { - QVector<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0); + QList<QThread*> allThreads(6 * qMax(strongThreadCount, weakThreadCount) + 3, 0); QSharedPointer<ThreadData> base = QSharedPointer<ThreadData>(new ThreadData(&counter)); - counter.store(0); + counter.storeRelaxed(0); // set the pointers for (int i = 0; i < strongThreadCount; ++i) { @@ -1982,11 +2075,11 @@ void tst_QSharedPointer::threadStressTest() base.clear(); // start threads - for (int i = 0; i < allThreads.count(); ++i) + for (int i = 0; i < allThreads.size(); ++i) if (allThreads[i]) allThreads[i]->start(); // wait for them to finish - for (int i = 0; i < allThreads.count(); ++i) + for (int i = 0; i < allThreads.size(); ++i) if (allThreads[i]) allThreads[i]->wait(); qDeleteAll(allThreads); @@ -1999,12 +2092,12 @@ void tst_QSharedPointer::threadStressTest() // verify that the count is the right range int minValue = strongThreadCount; int maxValue = strongThreadCount + weakThreadCount; - QVERIFY(counter.load() >= minValue); - QVERIFY(counter.load() <= maxValue); + QVERIFY(counter.loadRelaxed() >= minValue); + QVERIFY(counter.loadRelaxed() <= maxValue); } } -template<typename Container, bool Ordered> +template<typename Container, bool Ordered, bool Multi> void hashAndMapTest() { typedef typename Container::key_type Key; @@ -2049,26 +2142,30 @@ void hashAndMapTest() QVERIFY(it == c.end()); } - c.insertMulti(k1, Value(47)); - it = c.find(k1); - QVERIFY(it != c.end()); - QCOMPARE(it.key(), k1); - ++it; - QVERIFY(it != c.end()); - QCOMPARE(it.key(), k1); - ++it; - if (Ordered) - QVERIFY(it == c.end()); + if (Multi) { + c.insert(k1, Value(47)); + it = c.find(k1); + QVERIFY(it != c.end()); + QCOMPARE(it.key(), k1); + ++it; + QVERIFY(it != c.end()); + QCOMPARE(it.key(), k1); + ++it; + if (Ordered) + QVERIFY(it == c.end()); + } } void tst_QSharedPointer::map() { - hashAndMapTest<QMap<QSharedPointer<int>, int>, true>(); + hashAndMapTest<QMap<QSharedPointer<int>, int>, true, false>(); + hashAndMapTest<QMultiMap<QSharedPointer<int>, int>, true, true>(); } void tst_QSharedPointer::hash() { - hashAndMapTest<QHash<QSharedPointer<int>, int>, false>(); + hashAndMapTest<QHash<QSharedPointer<int>, int>, false, false>(); + hashAndMapTest<QMultiHash<QSharedPointer<int>, int>, false, true>(); } void tst_QSharedPointer::validConstructs() @@ -2077,7 +2174,10 @@ void tst_QSharedPointer::validConstructs() Data *aData = new Data; QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData); +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wself-assign-overloaded") ptr1 = ptr1; // valid +QT_WARNING_POP QSharedPointer<Data> ptr2(ptr1); @@ -2089,6 +2189,7 @@ void tst_QSharedPointer::validConstructs() } } +#if 0 typedef bool (QTest::QExternalTest:: * TestFunction)(const QByteArray &body); Q_DECLARE_METATYPE(TestFunction) void tst_QSharedPointer::invalidConstructs_data() @@ -2217,12 +2318,12 @@ void tst_QSharedPointer::invalidConstructs_data() QTest::newRow("weak-pointer-from-regular-pointer") << &QTest::QExternalTest::tryCompileFail - << "Data *ptr = 0;\n" + << "Data *ptr = nullptr;\n" "QWeakPointer<Data> weakptr(ptr);\n"; QTest::newRow("shared-pointer-implicit-from-uninitialized") << &QTest::QExternalTest::tryCompileFail - << "Data *ptr = 0;\n" + << "Data *ptr = nullptr;\n" "QSharedPointer<Data> weakptr = Qt::Uninitialized;\n"; QTest::newRow("incompatible-custom-deleter1") @@ -2233,11 +2334,14 @@ void tst_QSharedPointer::invalidConstructs_data() << &QTest::QExternalTest::tryCompileFail << "struct IncompatibleCustomDeleter { void operator()(int *); };\n" "QSharedPointer<Data> ptr(new Data, IncompatibleCustomDeleter());\n"; -#ifdef Q_COMPILER_LAMBDA QTest::newRow("incompatible-custom-lambda-deleter") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<Data> ptr(new Data, [](int *) {});\n"; -#endif + + QTest::newRow("incompatible-overload") + << &QTest::QExternalTest::tryCompileFail + << "void foo(QSharedPointer<DerivedData>) {}\n" + "void bar() { foo(QSharedPointer<Data>()); }\n"; } void tst_QSharedPointer::invalidConstructs() @@ -2295,6 +2399,7 @@ void tst_QSharedPointer::invalidConstructs() QFAIL("Fail"); } } +#endif // #if 0 void tst_QSharedPointer::qvariantCast() { @@ -2320,50 +2425,6 @@ void tst_QSharedPointer::qvariantCast() } // Intentionally does not compile. // QSharedPointer<int> sop = qSharedPointerFromVariant<int>(v); - - v = QVariant::fromValue(sp.toWeakRef()); - - { - QWeakPointer<QObject> other = qWeakPointerFromVariant<QObject>(v); - QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); - } - { - QWeakPointer<QIODevice> other = qWeakPointerFromVariant<QIODevice>(v); - QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); - } - { - QWeakPointer<QFile> other = qWeakPointerFromVariant<QFile>(v); - QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); - } - { - QWeakPointer<QThread> other = qWeakPointerFromVariant<QThread>(v); - QVERIFY(!other); - } - - // Intentionally does not compile. -// QWeakPointer<int> sop = qWeakPointerFromVariant<int>(v); - - QFile file; - QWeakPointer<QFile> tracking = &file; - tracking.data()->setObjectName("A test name"); - v = QVariant::fromValue(tracking); - - { - QWeakPointer<QObject> other = qWeakPointerFromVariant<QObject>(v); - QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); - } - { - QWeakPointer<QIODevice> other = qWeakPointerFromVariant<QIODevice>(v); - QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); - } - { - QWeakPointer<QFile> other = qWeakPointerFromVariant<QFile>(v); - QCOMPARE(other.data()->objectName(), QString::fromLatin1("A test name")); - } - { - QWeakPointer<QThread> other = qWeakPointerFromVariant<QThread>(v); - QVERIFY(!other); - } } class SomeClass : public QEnableSharedFromThis<SomeClass> @@ -2668,7 +2729,7 @@ void tst_QSharedPointer::constructorThrow() int childDestructorCounter = ThrowData::childDestructorCounter; QSharedPointer<ThrowData> ptr; - QVERIFY_EXCEPTION_THROWN(ptr = QSharedPointer<ThrowData>::create(), QString); + QVERIFY_THROWS_EXCEPTION(QString, ptr = QSharedPointer<ThrowData>::create()); QVERIFY(ptr.isNull()); QCOMPARE(ThrowData::childGenerationCounter, childGeneration + 1); // destructor should never be called, if a constructor throws @@ -2710,7 +2771,7 @@ namespace ReentrancyWhileDestructing { { QSharedPointer<IB> b; - virtual QSharedPointer<IB> getB() + virtual QSharedPointer<IB> getB() override { return b; } @@ -2736,5 +2797,185 @@ void tst_QSharedPointer::reentrancyWhileDestructing() ReentrancyWhileDestructing::A obj; } +namespace { +struct Base1 {}; +struct Base2 {}; + +struct Child1 : Base1 {}; +struct Child2 : Base2 {}; + +template<template<typename> class SmartPtr> +struct Overloaded +{ + std::array<int, 1> call(const SmartPtr<const Base1> &) + { + return {}; + } + std::array<int, 2> call(const SmartPtr<const Base2> &) + { + return {}; + } + static const constexpr uint base1Called = sizeof(std::array<int, 1>); + static const constexpr uint base2Called = sizeof(std::array<int, 2>); + + void test() + { +#define QVERIFY_CALLS(expr, base) static_assert(sizeof(call(expr)) == base##Called) + QVERIFY_CALLS(SmartPtr<Base1>{}, base1); + QVERIFY_CALLS(SmartPtr<Base2>{}, base2); + QVERIFY_CALLS(SmartPtr<const Base1>{}, base1); + QVERIFY_CALLS(SmartPtr<const Base2>{}, base2); + QVERIFY_CALLS(SmartPtr<Child1>{}, base1); + QVERIFY_CALLS(SmartPtr<Child2>{}, base2); + QVERIFY_CALLS(SmartPtr<const Child1>{}, base1); + QVERIFY_CALLS(SmartPtr<const Child2>{}, base2); +#undef QVERIFY_CALLS + } +}; +} + +void tst_QSharedPointer::overloads() +{ + Overloaded<QSharedPointer> sharedOverloaded; + sharedOverloaded.test(); + Overloaded<QWeakPointer> weakOverloaded; + weakOverloaded.test(); +} + +void tst_QSharedPointer::ownerComparisons() +{ + using SP = QSharedPointer<int>; + using WP = QWeakPointer<int>; + +#define CHECK_EQ(a, b) \ + do { \ + QVERIFY(a.owner_equal(b)); \ + QVERIFY(b.owner_equal(a)); \ + QVERIFY(!a.owner_before(b)); \ + QVERIFY(!b.owner_before(a)); \ + QVERIFY(a.owner_hash() == b.owner_hash()); \ + } while (false) + +#define CHECK_NOT_EQ(a, b) \ + do { \ + QVERIFY(!a.owner_equal(b)); \ + QVERIFY(!b.owner_equal(a)); \ + QVERIFY(a.owner_before(b) || b.owner_before(a)); \ + } while (false) + + // null + { + SP sp1; + SP sp2; + WP wp1 = sp1; + WP wp2; + + CHECK_EQ(sp1, sp1); + CHECK_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp1, wp2); + CHECK_EQ(wp2, wp2); + } + + // same owner + { + SP sp1 = SP::create(123); + SP sp2 = sp1; + WP wp1 = sp1; + SP wp2 = sp2; + + CHECK_EQ(sp1, sp1); + CHECK_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp1, wp2); + } + + // owning vs null + { + SP sp1 = SP::create(123); + SP sp2; + WP wp1 = sp1; + WP wp2 = sp2; + + CHECK_EQ(sp1, sp1); + CHECK_NOT_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + // different owners + { + SP sp1 = SP::create(123); + SP sp2 = SP::create(456); + WP wp1 = sp1; + WP wp2 = sp2; + + CHECK_EQ(sp1, sp1); + CHECK_NOT_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + // reset vs. null + { + SP sp1 = SP::create(123); + SP sp2; + WP wp1 = sp1; + WP wp2; + + CHECK_EQ(sp1, sp1); + CHECK_NOT_EQ(sp1, sp2); + CHECK_EQ(sp1, wp1); + CHECK_NOT_EQ(sp1, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + + sp1.reset(); + + CHECK_EQ(sp1, sp1); + CHECK_EQ(sp1, sp2); + CHECK_NOT_EQ(sp1, wp1); + CHECK_EQ(sp2, wp2); + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + // expired weak pointers + { + WP wp1 = SP::create(123); + WP wp2; + + CHECK_EQ(wp1, wp1); + CHECK_NOT_EQ(wp1, wp2); + } + + { + WP wp1 = SP::create(123); + WP wp2 = wp1; + + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp1, wp2); + } + + { + WP wp1 = SP::create(123); + WP wp2 = SP::create(456); + + CHECK_EQ(wp1, wp1); + CHECK_EQ(wp2, wp2); + CHECK_NOT_EQ(wp1, wp2); + } +#undef CHECK_EQ +#undef CHECK_NOT_EQ +} + QTEST_MAIN(tst_QSharedPointer) #include "tst_qsharedpointer.moc" diff --git a/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp b/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp index 24a0cdc9c1..b39eee7d98 100644 --- a/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/wrapper.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifdef QT_SHAREDPOINTER_TRACK_POINTERS # undef QT_SHAREDPOINTER_TRACK_POINTERS diff --git a/tests/auto/corelib/tools/qsharedpointer/wrapper.h b/tests/auto/corelib/tools/qsharedpointer/wrapper.h index 18cea6e199..3b0bc09fed 100644 --- a/tests/auto/corelib/tools/qsharedpointer/wrapper.h +++ b/tests/auto/corelib/tools/qsharedpointer/wrapper.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef WRAPPER_H #define WRAPPER_H |