diff options
Diffstat (limited to 'tests/auto/corelib')
15 files changed, 353 insertions, 57 deletions
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp index 6f608854ae..a6e1f49be2 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp @@ -2220,6 +2220,40 @@ void tst_QSortFilterProxyModel::changeSourceDataProxySendDataChanged_qtbug87781( QCOMPARE(afterDataChangedSpy.size(), 1); } +void tst_QSortFilterProxyModel::changeSourceDataTreeModel() +{ + QStandardItemModel treeModel; + QSortFilterProxyModel treeProxyModelBefore; + QSortFilterProxyModel treeProxyModelAfter; + + QSignalSpy treeBaseDataChangedSpy(&treeModel, &QStandardItemModel::dataChanged); + QSignalSpy treeBeforeDataChangedSpy(&treeProxyModelBefore, &QSortFilterProxyModel::dataChanged); + QSignalSpy treeAfterDataChangedSpy(&treeProxyModelAfter, &QSortFilterProxyModel::dataChanged); + + QVERIFY(treeBaseDataChangedSpy.isValid()); + QVERIFY(treeBeforeDataChangedSpy.isValid()); + QVERIFY(treeAfterDataChangedSpy.isValid()); + + treeProxyModelBefore.setSourceModel(&treeModel); + QStandardItem treeNode1("data1"); + QStandardItem treeNode11("data11"); + QStandardItem treeNode111("data111"); + + treeNode1.appendRow(&treeNode11); + treeNode11.appendRow(&treeNode111); + treeModel.appendRow(&treeNode1); + treeProxyModelAfter.setSourceModel(&treeModel); + + QCOMPARE(treeBaseDataChangedSpy.size(), 0); + QCOMPARE(treeBeforeDataChangedSpy.size(), 0); + QCOMPARE(treeAfterDataChangedSpy.size(), 0); + + treeNode111.setData(QStringLiteral("new data"), Qt::DisplayRole); + QCOMPARE(treeBaseDataChangedSpy.size(), 1); + QCOMPARE(treeBeforeDataChangedSpy.size(), 1); + QCOMPARE(treeAfterDataChangedSpy.size(), 1); +} + void tst_QSortFilterProxyModel::changeSourceDataProxyFilterSingleColumn() { enum modelRow { Row0, Row1, RowCount }; diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h index 7bf87a86c2..97862e804b 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h @@ -91,6 +91,7 @@ private slots: void changeSourceDataKeepsStableSorting_qtbug1548(); void changeSourceDataForwardsRoles_qtbug35440(); void changeSourceDataProxySendDataChanged_qtbug87781(); + void changeSourceDataTreeModel(); void changeSourceDataProxyFilterSingleColumn(); void changeSourceDataProxyFilterMultipleColumns(); void resortingDoesNotBreakTreeModels(); diff --git a/tests/auto/corelib/kernel/qtimer/BLACKLIST b/tests/auto/corelib/kernel/qtimer/BLACKLIST new file mode 100644 index 0000000000..2af0df9432 --- /dev/null +++ b/tests/auto/corelib/kernel/qtimer/BLACKLIST @@ -0,0 +1,3 @@ +[zeroTimer] +ubuntu-20.04 + diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp index aa85a7c35b..0ad0fc7076 100644 --- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp +++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp @@ -228,6 +228,9 @@ static qsizetype locateMetadata(const uchar *data, qsizetype len) void tst_QPlugin::scanInvalidPlugin() { +#if defined(Q_OS_MACOS) && defined(Q_PROCESSOR_ARM) + QSKIP("This test crashes on ARM macOS"); +#endif const auto fileNames = dir.entryList({"*invalid*"}, QDir::Files); QString invalidPluginName; if (fileNames.isEmpty()) diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro index 795dd89895..7cfb7920c0 100644 --- a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro +++ b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest.pro @@ -1,15 +1,11 @@ TEMPLATE = subdirs SUBDIRS = \ - machtest_i386.pro \ + machtest_arm64.pro \ machtest_x86_64.pro \ - machtest_ppc64.pro \ machtest_fat.pro machtest_fat-pro.depends = \ - machtest_i386.pro \ - machtest_x86_64.pro \ - machtest_ppc64.pro - -machtest_ppc64-pro.depends = \ + machtest_arm64.pro \ machtest_x86_64.pro + diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_arm64.pro b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_arm64.pro new file mode 100644 index 0000000000..c2856a8af0 --- /dev/null +++ b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_arm64.pro @@ -0,0 +1,3 @@ +QMAKE_APPLE_DEVICE_ARCHS = arm64 +include(machtest.pri) + diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_fat.pro b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_fat.pro index 9c34a873bc..57c6654984 100644 --- a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_fat.pro +++ b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_fat.pro @@ -7,41 +7,42 @@ load(qt) # Generate a fat binary with three architectures fat_all.target = good.fat.all.dylib fat_all.commands = lipo -create -output $@ \ - -arch ppc64 good.ppc64.dylib \ - -arch i386 good.i386.dylib \ + -arch arm64 good.arm64.dylib \ -arch x86_64 good.x86_64.dylib -fat_all.depends += good.i386.dylib good.x86_64.dylib good.ppc64.dylib +fat_all.depends += good.arm64.dylib good.x86_64.dylib -fat_no_i386.target = good.fat.no-i386.dylib -fat_no_i386.commands = lipo -create -output $@ -arch x86_64 good.x86_64.dylib -arch ppc64 good.ppc64.dylib -fat_no_i386.depends += good.x86_64.dylib good.ppc64.dylib +fat_no_arm64.target = good.fat.no-arm64.dylib +fat_no_arm64.commands = lipo -create -output $@ -arch x86_64 good.x86_64.dylib +fat_no_arm64.depends += good.x86_64.dylib fat_no_x86_64.target = good.fat.no-x86_64.dylib -fat_no_x86_64.commands = lipo -create -output $@ -arch i386 good.i386.dylib -arch ppc64 good.ppc64.dylib -fat_no_x86_64.depends += good.i386.dylib good.ppc64.dylib +fat_no_x86_64.commands = lipo -create -output $@ -arch arm64 good.arm64.dylib +fat_no_x86_64.depends += good.arm64.dylib -stub_i386.commands = $$QMAKE_CXX -shared -arch i386 -o stub.i386.dylib $$PWD/stub.cpp -stub_i386.depends += $$PWD/stub.cpp +stub_flags = -L$$system(xcrun --show-sdk-path)/usr/lib/ -stdlib=libc++ -stub_x86_64.commands = $$QMAKE_CXX -shared -arch x86_64 -o stub.x86_64.dylib $$PWD/stub.cpp +stub_arm64.commands = $$QMAKE_CXX $$stub_flags -shared -arch arm64 -o stub.arm64.dylib $$PWD/stub.cpp +stub_arm64.depends += $$PWD/stub.cpp + +stub_x86_64.commands = $$QMAKE_CXX $$stub_flags -shared -arch x86_64 -o stub.x86_64.dylib $$PWD/stub.cpp stub_x86_64.depends += $$PWD/stub.cpp -fat_stub_i386.target = good.fat.stub-i386.dylib -fat_stub_i386.commands = lipo -create -output $@ -arch ppc64 good.ppc64.dylib -arch i386 stub.i386.dylib -fat_stub_i386.depends += stub_i386 good.x86_64.dylib good.ppc64.dylib +fat_stub_arm64.target = good.fat.stub-arm64.dylib +fat_stub_arm64.commands = lipo -create -output $@ -arch arm64 stub.arm64.dylib +fat_stub_arm64.depends += stub_arm64 good.x86_64.dylib fat_stub_x86_64.target = good.fat.stub-x86_64.dylib -fat_stub_x86_64.commands = lipo -create -output $@ -arch ppc64 good.ppc64.dylib -arch x86_64 stub.x86_64.dylib -fat_stub_x86_64.depends += stub_x86_64 good.i386.dylib good.ppc64.dylib +fat_stub_x86_64.commands = lipo -create -output $@ -arch x86_64 stub.x86_64.dylib +fat_stub_x86_64.depends += stub_x86_64 good.arm64.dylib bad.commands = $$PWD/generate-bad.pl bad.depends += $$PWD/generate-bad.pl -MYTARGETS = $$fat_all.depends fat_all fat_no_x86_64 fat_no_i386 \ - fat_stub_i386 fat_stub_x86_64 bad stub_i386 stub_x86_64 +MYTARGETS = $$fat_all.depends fat_all fat_no_x86_64 fat_no_arm64 \ + fat_stub_arm64 fat_stub_x86_64 bad stub_arm64 stub_x86_64 all.depends += $$MYTARGETS QMAKE_EXTRA_TARGETS += $$MYTARGETS all -QMAKE_CLEAN += $$fat_all.target $$fat_no_i386.target $$fat_no_x86_64.target \ - $$fat_stub_i386.target $$fat_stub_x86_64.target \ +QMAKE_CLEAN += $$fat_all.target $$fat_no_arm64.target $$fat_no_x86_64.target \ + $$fat_stub_arm64.target $$fat_stub_x86_64.target \ "bad*.dylib" diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_i386.pro b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_i386.pro deleted file mode 100644 index bfb2e0930c..0000000000 --- a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_i386.pro +++ /dev/null @@ -1,3 +0,0 @@ -QMAKE_APPLE_DEVICE_ARCHS = i386 -include(machtest.pri) - diff --git a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_ppc64.pro b/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_ppc64.pro deleted file mode 100644 index a73f97ccc6..0000000000 --- a/tests/auto/corelib/plugin/qpluginloader/machtest/machtest_ppc64.pro +++ /dev/null @@ -1,9 +0,0 @@ -QMAKE_APPLE_DEVICE_ARCHS = ppc64 -include(machtest.pri) - -OTHER_FILES += ppcconverter.pl - -# Current macOS toolchains have no compiler for PPC anymore -# So we fake it by converting an x86-64 binary to (little-endian!) PPC64 -goodlib.commands = $$PWD/ppcconverter.pl $< $@ -goodlib.depends = good.x86_64.dylib $$PWD/ppcconverter.pl diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp index 8d548f5260..ce8057372c 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp @@ -341,22 +341,19 @@ void tst_QPluginLoader::loadMachO_data() # ifdef Q_PROCESSOR_X86_64 QTest::newRow("machtest/good.x86_64.dylib") << int(QMachOParser::QtMetaDataSection); - QTest::newRow("machtest/good.i386.dylib") << int(QMachOParser::NotSuitable); + QTest::newRow("machtest/good.arm64.dylib") << int(QMachOParser::NotSuitable); QTest::newRow("machtest/good.fat.no-x86_64.dylib") << int(QMachOParser::NotSuitable); - QTest::newRow("machtest/good.fat.no-i386.dylib") << int(QMachOParser::QtMetaDataSection); -# elif defined(Q_PROCESSOR_X86_32) - QTest::newRow("machtest/good.i386.dylib") << int(QMachOParser::QtMetaDataSection); + QTest::newRow("machtest/good.fat.no-arm64.dylib") << int(QMachOParser::QtMetaDataSection); +# elif defined(Q_PROCESSOR_ARM) + QTest::newRow("machtest/good.arm64.dylib") << int(QMachOParser::QtMetaDataSection); QTest::newRow("machtest/good.x86_64.dylib") << int(QMachOParser::NotSuitable); - QTest::newRow("machtest/good.fat.no-i386.dylib") << int(QMachOParser::NotSuitable); + QTest::newRow("machtest/good.fat.no-arm64.dylib") << int(QMachOParser::NotSuitable); QTest::newRow("machtest/good.fat.no-x86_64.dylib") << int(QMachOParser::QtMetaDataSection); # endif -# ifndef Q_PROCESSOR_POWER_64 - QTest::newRow("machtest/good.ppc64.dylib") << int(QMachOParser::NotSuitable); -# endif QTest::newRow("machtest/good.fat.all.dylib") << int(QMachOParser::QtMetaDataSection); QTest::newRow("machtest/good.fat.stub-x86_64.dylib") << int(QMachOParser::NotSuitable); - QTest::newRow("machtest/good.fat.stub-i386.dylib") << int(QMachOParser::NotSuitable); + QTest::newRow("machtest/good.fat.stub-arm64.dylib") << int(QMachOParser::NotSuitable); QDir d(QFINDTESTDATA("machtest")); QStringList badlist = d.entryList(QStringList() << "bad*.dylib"); diff --git a/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp index 88f8ea0bbb..b24243b98e 100644 --- a/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/text/qregularexpression/tst_qregularexpression.cpp @@ -80,6 +80,7 @@ private slots: void threadSafety_data(); void threadSafety(); + void returnsViewsIntoOriginalString(); void wildcard_data(); void wildcard(); void testInvalidWildcard_data(); @@ -2188,6 +2189,31 @@ void tst_QRegularExpression::threadSafety() } } +void tst_QRegularExpression::returnsViewsIntoOriginalString() +{ + // https://bugreports.qt.io/browse/QTBUG-98653 + + auto to_void = [](const QChar *p) -> const void* { return p; }; + + // GIVEN + // a QString with dynamically-allocated data: + const QString string = QLatin1String("A\nA\nB\nB\n\nC\nC"); // NOT QStringLiteral! + const auto stringDataAddress = to_void(string.data()); + + // and a view over said QString: + QStringView view(string); + const auto viewDataAddress = to_void(view.data()); + QCOMPARE(stringDataAddress, viewDataAddress); + + // WHEN + // we call view.split() with a temporary QRegularExpression object + const auto split = view.split(QRegularExpression( "(\r\n|\n|\r)" ), Qt::KeepEmptyParts); + + // THEN + // the returned views should point into the underlying string: + QCOMPARE(to_void(split.front().data()), stringDataAddress); +} + void tst_QRegularExpression::wildcard_data() { QTest::addColumn<QString>("pattern"); diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index 2c7c8f6514..11f181a955 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -40,8 +40,10 @@ #include <algorithm> #include <functional> #include <vector> // for reference +#include <iostream> #include <list> #include <set> +#include <sstream> #include <map> // MSVC has these containers from the Standard Library, but it lacks @@ -64,6 +66,28 @@ #include <unordered_map> #endif +QT_BEGIN_NAMESPACE +std::ostream &operator<<(std::ostream &os, const QChar &c) +{ + Q_ASSERT(c == QLatin1Char{c.toLatin1()}); + return os << c.toLatin1(); +} +std::istream &operator>>(std::istream &os, QChar &c) +{ + char cL1; + os >> cL1; + c = QLatin1Char{cL1}; + return os; +} +QT_END_NAMESPACE + +namespace { +template <typename T> +struct is_qlist : std::false_type {}; +template <typename T> +struct is_qlist<QList<T>> : std::true_type {}; +} + struct Movable { explicit Movable(int i = 0) Q_DECL_NOTHROW @@ -85,6 +109,11 @@ struct Movable int i; static int instanceCount; + + friend std::ostream &operator<<(std::ostream &os, const Movable &m) + { return os << m.i; } + friend std::istream &operator>>(std::istream &os, Movable &m) + { return os >> m.i; } }; int Movable::instanceCount = 0; @@ -124,6 +153,11 @@ struct Complex int i; static int instanceCount; + + friend std::ostream &operator<<(std::ostream &os, const Complex &c) + { return os << c.i; } + friend std::istream &operator>>(std::istream &os, Complex &c) + { return os >> c.i; } }; int Complex::instanceCount = 0; @@ -550,12 +584,30 @@ void tst_ContainerApiSymmetry::ranged_ctor_non_associative_impl() const // from itself const Container c4(reference.begin(), reference.end()); + // from stringsteam (= pure input_iterator) + const Container c5 = [&] { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // QTBUG-99036 + if constexpr (is_qlist<Container>::value) { + return c4; + } else +#endif + { + std::stringstream ss; + for (auto &v : values1) + ss << v << ' '; + ss.seekg(0); + return Container(std::istream_iterator<V>{ss}, + std::istream_iterator<V>{}); + } + }(); + QCOMPARE(c1, reference); QCOMPARE(c2a, reference); QCOMPARE(c2b, reference); QCOMPARE(c3a, reference); QCOMPARE(c3b, reference); QCOMPARE(c4, reference); + QCOMPARE(c5, reference); } diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp index f76f3aa0c6..4eb8a97051 100644 --- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp +++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp @@ -230,8 +230,14 @@ namespace SomeNamespace { struct Hashable { int i; }; inline uint qHash(Hashable h, uint seed = 0) { return QT_PREPEND_NAMESPACE(qHash)(h.i, seed); } -} + struct AdlHashable { + int i; + private: + friend size_t qHash(AdlHashable h, size_t seed = 0) + { return QT_PREPEND_NAMESPACE(qHash)(h.i, seed); } + }; +} void tst_QHashFunctions::range() { static const int ints[] = {0, 1, 2, 3, 4, 5}; @@ -253,10 +259,16 @@ void tst_QHashFunctions::range() QCOMPARE(qHashRange(ints, ints + numInts, seed), qHashRange(it, end, seed)); } - SomeNamespace::Hashable hashables[] = {{0}, {1}, {2}, {3}, {4}, {5}}; - static const size_t numHashables = sizeof hashables / sizeof *hashables; - // compile check: is qHash() found using ADL? - (void)qHashRange(hashables, hashables + numHashables, seed); + { + SomeNamespace::Hashable hashables[] = {{0}, {1}, {2}, {3}, {4}, {5}}; + // compile check: is qHash() found using ADL? + [[maybe_unused]] auto r = qHashRange(std::begin(hashables), std::end(hashables), seed); + } + { + SomeNamespace::AdlHashable hashables[] = {{0}, {1}, {2}, {3}, {4}, {5}}; + // compile check: is qHash() found as a hidden friend? + [[maybe_unused]] auto r = qHashRange(std::begin(hashables), std::end(hashables), seed); + } } void tst_QHashFunctions::rangeCommutative() @@ -279,10 +291,16 @@ void tst_QHashFunctions::rangeCommutative() QCOMPARE(qHashRangeCommutative(ints, ints + numInts, seed), qHashRangeCommutative(it, end, seed)); } - SomeNamespace::Hashable hashables[] = {{0}, {1}, {2}, {3}, {4}, {5}}; - static const size_t numHashables = sizeof hashables / sizeof *hashables; - // compile check: is qHash() found using ADL? - (void)qHashRangeCommutative(hashables, hashables + numHashables, seed); + { + SomeNamespace::Hashable hashables[] = {{0}, {1}, {2}, {3}, {4}, {5}}; + // compile check: is qHash() found using ADL? + [[maybe_unused]] auto r = qHashRangeCommutative(std::begin(hashables), std::end(hashables), seed); + } + { + SomeNamespace::AdlHashable hashables[] = {{0}, {1}, {2}, {3}, {4}, {5}}; + // compile check: is qHash() found as a hidden friend? + [[maybe_unused]] auto r = qHashRangeCommutative(std::begin(hashables), std::end(hashables), seed); + } } void tst_QHashFunctions::stdHash() diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 5443cf120b..0174885cf3 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -29,6 +29,7 @@ #include <QtTest/QTest> #include <qvarlengtharray.h> #include <qvariant.h> +#include <qscopedvaluerollback.h> #include <memory> @@ -36,10 +37,13 @@ class tst_QVarLengthArray : public QObject { Q_OBJECT private slots: + void defaultConstructor_int() { defaultConstructor<int>(); } + void defaultConstructor_QString() { defaultConstructor<QString>(); } void append(); void removeLast(); void oldTests(); void appendCausingRealloc(); + void appendIsStronglyExceptionSafe(); void resize(); void realloc(); void reverseIterators(); @@ -61,6 +65,8 @@ private slots: void implicitDefaultCtor(); private: + template <typename T> + void defaultConstructor(); template<typename T> void initializeList(); }; @@ -80,6 +86,23 @@ struct Tracker int Tracker::count = 0; +template <typename T> +void tst_QVarLengthArray::defaultConstructor() +{ + { + QVarLengthArray<T, 123> vla; + QCOMPARE(vla.size(), 0); + QVERIFY(vla.empty()); + QVERIFY(vla.isEmpty()); + QCOMPARE(vla.begin(), vla.end()); + QCOMPARE(vla.capacity(), 123); + } + { + QVarLengthArray<T> vla; + QCOMPARE(vla.capacity(), 256); // notice, should we change the default + } +} + void tst_QVarLengthArray::append() { QVarLengthArray<QString, 2> v; @@ -245,6 +268,49 @@ void tst_QVarLengthArray::appendCausingRealloc() d.append(i); } +void tst_QVarLengthArray::appendIsStronglyExceptionSafe() +{ +#ifdef QT_NO_EXCEPTIONS + QSKIP("This test requires exception support enabled in the compiler."); +#else + static bool throwOnCopyNow = false; + static bool throwOnMoveNow = false; + struct Thrower { + Thrower() = default; + Thrower(const Thrower &) + { + if (throwOnCopyNow) + throw 1; + } + Thrower &operator=(const Thrower &) = default; + Thrower(Thrower &&) + { + if (throwOnMoveNow) + throw 1; + } + Thrower &operator=(Thrower &&) = default; + ~Thrower() = default; + }; + + { + // ### TODO: QVLA isn't exception-safe when throwing during reallocation, + // ### so check with size() < capacity() for now + QVarLengthArray<Thrower, 2> vla(1); + { + Thrower t; + const QScopedValueRollback<bool> rb(throwOnCopyNow, true); + QVERIFY_EXCEPTION_THROWN(vla.push_back(t), int); + QCOMPARE(vla.size(), 1); + } + { + const QScopedValueRollback<bool> rb(throwOnMoveNow, true); + QVERIFY_EXCEPTION_THROWN(vla.push_back({}), int); + QCOMPARE(vla.size(), 1); + } + } +#endif +} + void tst_QVarLengthArray::resize() { //MOVABLE diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 08d5a8cd50..01409bd188 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -183,6 +183,94 @@ inline uint qHash(const Custom &key, uint seed = 0) { return qHash(key.i, seed); Q_DECLARE_METATYPE(Custom); +// Similar to Custom but not default-constructible and has move constructor and assignment +struct NonDefaultConstructible { + NonDefaultConstructible() = delete; + NonDefaultConstructible(char input) + : i(input) + , that(this) + , state(Constructed) + { + counter.fetchAndAddRelaxed(1); + } + NonDefaultConstructible(const NonDefaultConstructible &other) + : i(other.i) + , that(this) + , state(Constructed) + { + check(&other); + counter.fetchAndAddRelaxed(1); + } + NonDefaultConstructible(NonDefaultConstructible &&other) + : i(other.i) + , that(this) + , state(Constructed) + { + check(&other); + other.state = MovedFrom; + counter.fetchAndAddRelaxed(1); + } + ~NonDefaultConstructible() + { + check(this, true); + i = 0; + counter.fetchAndAddRelaxed(-1); + state = Destructed; + } + + bool operator==(const NonDefaultConstructible &other) const + { + check(&other); + check(this); + return i == other.i; + } + + bool operator<(const NonDefaultConstructible &other) const + { + check(&other); + check(this); + return i < other.i; + } + + NonDefaultConstructible &operator=(const NonDefaultConstructible &other) + { + check(&other); + check(this, true); + i = other.i; + state = Constructed; + return *this; + } + + NonDefaultConstructible &operator=(NonDefaultConstructible &&other) + { + check(&other); + check(this, true); + i = other.i; + state = Constructed; + other.state = MovedFrom; + return *this; + } + static QAtomicInt counter; + + char i; // used to identify origin of an instance +private: + NonDefaultConstructible *that; // used to catch copying using mem{cpy,move}() + + enum State { Constructed = 106, Destructed = 110, MovedFrom = 120 }; + State state; + + static void check(const NonDefaultConstructible *c, bool movedOk = false) + { + // check if c object has been moved incorrectly + QCOMPARE(c, c->that); + if (!movedOk || c->state != MovedFrom) + QCOMPARE(c->state, Constructed); + } +}; +QAtomicInt NonDefaultConstructible::counter = 0; + +inline uint qHash(const NonDefaultConstructible &key, uint seed = 0) { return qHash(key.i, seed); } + // tests depends on the fact that: Q_STATIC_ASSERT(!QTypeInfo<int>::isStatic); Q_STATIC_ASSERT(!QTypeInfo<int>::isComplex); @@ -190,6 +278,8 @@ Q_STATIC_ASSERT(!QTypeInfo<Movable>::isStatic); Q_STATIC_ASSERT(QTypeInfo<Movable>::isComplex); Q_STATIC_ASSERT(QTypeInfo<Custom>::isStatic); Q_STATIC_ASSERT(QTypeInfo<Custom>::isComplex); +Q_STATIC_ASSERT(QTypeInfo<NonDefaultConstructible>::isStatic); +Q_STATIC_ASSERT(QTypeInfo<NonDefaultConstructible>::isComplex); class tst_QVector : public QObject @@ -263,6 +353,7 @@ private slots: void insertInt() const; void insertMovable() const; void insertCustom() const; + void insertNonDefaultConstructible() const; void isEmpty() const; void last() const; void lastIndexOf() const; @@ -273,6 +364,7 @@ private slots: void prependInt() const; void prependMovable() const; void prependCustom() const; + void prependNonDefaultConstructible() const; void qhashInt() const { qhash<int>(); } void qhashMovable() const { qhash<Movable>(); } void qhashCustom() const { qhash<Custom>(); } @@ -390,6 +482,10 @@ template<> const Movable SimpleValue<Movable>::Values[] = { 110, 105, 101, 114, 111, 98 }; template<> const Custom SimpleValue<Custom>::Values[] = { 110, 105, 101, 114, 111, 98 }; +template<> +const NonDefaultConstructible SimpleValue<NonDefaultConstructible>::Values[] = + { 110, 105, 101, 114, 111, 98 }; + // Make some macros for the tests to use in order to be slightly more readable... #define T_FOO SimpleValue<T>::at(0) @@ -1592,6 +1688,11 @@ void tst_QVector::insertCustom() const insert<Custom>(); } +void tst_QVector::insertNonDefaultConstructible() const +{ + insert<NonDefaultConstructible>(); +} + void tst_QVector::isEmpty() const { QVector<QString> myvec; @@ -1831,6 +1932,13 @@ void tst_QVector::prependCustom() const QCOMPARE(instancesCount, Custom::counter.loadAcquire()); } +void tst_QVector::prependNonDefaultConstructible() const +{ + const int instancesCount = NonDefaultConstructible::counter.loadAcquire(); + prepend<NonDefaultConstructible>(); + QCOMPARE(instancesCount, NonDefaultConstructible::counter.loadAcquire()); +} + void tst_QVector::removeAllWithAlias() const { QVector<QString> strings; |