diff options
Diffstat (limited to 'tests/auto')
35 files changed, 924 insertions, 95 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; diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 1d77f70919..417514607f 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -120,6 +120,7 @@ private slots: void copy(); void deepCopyPreservesDpr(); + void fillPreservesDpr(); void dprPassthrough(); void depthOfNullObjects(); @@ -1156,6 +1157,19 @@ void tst_QPixmap::deepCopyPreservesDpr() QCOMPARE(dest.devicePixelRatio(), dpr); } +// Check that the DPR is preserved after doing a fill after an +// assigned copy of the QPixmap +void tst_QPixmap::fillPreservesDpr() +{ + const qreal dpr = 2; + QPixmap src(32, 32); + src.setDevicePixelRatio(dpr); + src.fill(Qt::red); + QPixmap dest = src; + dest.fill(Qt::blue); + QCOMPARE(dest.devicePixelRatio(), dpr); +} + void tst_QPixmap::dprPassthrough() { const qreal dpr = 2; diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp index edbb090e42..15e0ecadaa 100644 --- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp @@ -33,6 +33,8 @@ #include <qfontmetrics.h> #include <qtextlayout.h> #include <private/qrawfont_p.h> +#include <private/qfont_p.h> +#include <private/qfontengine_p.h> #include <qpa/qplatformfontdatabase.h> Q_LOGGING_CATEGORY(lcTests, "qt.text.tests") @@ -411,7 +413,11 @@ void tst_QFontDatabase::condensedFontMatching() tfcByStyleName.setStyleName("Condensed"); #ifdef Q_OS_WIN - QEXPECT_FAIL("","No matching of sub-family by stretch on Windows", Continue); + QFont f; + f.setStyleStrategy(QFont::NoFontMerging); + QFontPrivate *font_d = QFontPrivate::get(f); + if (font_d->engineForScript(QChar::Script_Common)->type() != QFontEngine::Freetype) + QEXPECT_FAIL("","No matching of sub-family by stretch on Windows", Continue); #endif #ifdef Q_OS_ANDROID diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp index 7bc9fe47c5..a61824b51c 100644 --- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp +++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp @@ -197,6 +197,9 @@ private slots: void clearUndoRedoStacks(); void mergeFontFamilies(); + void contentsChangeIndices_data(); + void contentsChangeIndices(); + private: void backgroundImage_checkExpectedHtml(const QTextDocument &doc); void buildRegExpData(); @@ -3716,5 +3719,62 @@ void tst_QTextDocument::clearUndoRedoStacks() } +void tst_QTextDocument::contentsChangeIndices_data() +{ + QTest::addColumn<QString>("html"); + // adding list entries change the entire block, so change position is + // not the same as the cursor position if this value is >= 0 + QTest::addColumn<int>("expectedBegin"); + + QTest::addRow("text") << "Test" << -1; + QTest::addRow("unnumbered list") << "<ul><li>Test</li></ul>" << 0; + QTest::addRow("numbered list") << "<ol><li>Test</li></ol>" << 0; + QTest::addRow("table") << "<table><tr><td>Test</td></tr></table>" << -1; +} + +void tst_QTextDocument::contentsChangeIndices() +{ + QFETCH(QString, html); + QFETCH(int, expectedBegin); + + QTextDocument doc; + QTestDocumentLayout *layout = new QTestDocumentLayout(&doc); + doc.setDocumentLayout(layout); + doc.setHtml(QString("<html><body>%1</body></html>").arg(html)); + + int documentLength = 0; + int cursorLength = 0; + int changeBegin = 0; + int changeRemoved = 0; + int changeAdded = 0; + connect(&doc, &QTextDocument::contentsChange, this, [&](int pos, int removed, int added){ + documentLength = doc.characterCount(); + + QTextCursor cursor(&doc); + cursor.movePosition(QTextCursor::End); + // includes end-of-paragraph character + cursorLength = cursor.position() + 1; + + changeBegin = pos; + changeRemoved = removed; + changeAdded = added; + }); + + QTextCursor cursor(&doc); + cursor.movePosition(QTextCursor::End); + if (expectedBegin < 0) + expectedBegin = cursor.position(); + cursor.insertBlock(); + + const int changeEnd = changeBegin + changeAdded; + + QVERIFY(documentLength > 0); + QCOMPARE(documentLength, cursorLength); + QVERIFY(documentLength >= changeEnd); + QCOMPARE(changeBegin, expectedBegin); + QCOMPARE(changeAdded - changeRemoved, 1); +} + + QTEST_MAIN(tst_QTextDocument) #include "tst_qtextdocument.moc" diff --git a/tests/auto/gui/text/qtextlayout/BLACKLIST b/tests/auto/gui/text/qtextlayout/BLACKLIST new file mode 100644 index 0000000000..c05b0de4eb --- /dev/null +++ b/tests/auto/gui/text/qtextlayout/BLACKLIST @@ -0,0 +1,3 @@ +[softHyphens] +winrt + diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 2feca77f40..f3bb5eaffb 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -141,6 +141,7 @@ private slots: void showLineAndParagraphSeparatorsCrash(); void koreanWordWrap(); void tooManyDirectionalCharctersCrash_qtbug77819(); + void softHyphens_data(); void softHyphens(); void min_maximumWidth(); @@ -2429,22 +2430,45 @@ void tst_QTextLayout::tooManyDirectionalCharctersCrash_qtbug77819() tl.endLayout(); } +void tst_QTextLayout::softHyphens_data() +{ + QTest::addColumn<int>("fontSize"); + + QTest::newRow("12") << 12; + QTest::newRow("14") << 14; + QTest::newRow("16") << 16; +} + void tst_QTextLayout::softHyphens() { + QFETCH(int, fontSize); QString text = QStringLiteral("xxxx\u00ad") + QStringLiteral("xxxx\u00ad"); QFont font; - font.setPixelSize(14); + font.setPixelSize(fontSize); font.setHintingPreference(QFont::PreferNoHinting); - const float xAdvance = QFontMetricsF(font).horizontalAdvance(QChar('x')); - const float shyAdvance = QFontMetricsF(font).horizontalAdvance(QChar::SoftHyphen); - if (xAdvance < (shyAdvance + 1.0f)) - QSKIP("Default font not suitable for this test."); + const float xAdvance = QFontMetricsF(font).horizontalAdvance(QChar::fromLatin1('x')); + float shyWidth = 0.0f; QTextLayout layout(text, font); QTextOption option; option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); layout.setTextOption(option); - + { + // Calculate the effective width of a line-ending hyphen + // This calculation is currently done to work-around odditities on + // macOS 11 (see QTBUG-90698). + QTextLayout test(QStringLiteral("x\u00ad"), font); + // Note: This only works because Qt show the soft-hyphen when ending a text. + // This _could_ be considered a bug and the test would need to be changed + // if we stop doing that. + test.beginLayout(); + QTextLine line = test.createLine(); + line.setLineWidth(10 * xAdvance); + line.setPosition(QPoint(0, 0)); + shyWidth = line.naturalTextWidth() - xAdvance; + test.endLayout(); + } + qreal linefit; // Loose fit // xxxx- | // xxxx- | @@ -2453,21 +2477,22 @@ void tst_QTextLayout::softHyphens() int y = 0; layout.beginLayout(); QTextLine line = layout.createLine(); - line.setLineWidth(qCeil(5 * xAdvance) + 1); + line.setLineWidth(qCeil(5 * xAdvance + shyWidth) + 1); line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 5); - QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1); + linefit = line.naturalTextWidth(); + QVERIFY(qAbs(linefit - qCeil(4 * xAdvance + shyWidth)) <= 1.0); pos += line.textLength(); y += qRound(line.ascent() + line.descent()); line = layout.createLine(); - line.setLineWidth(qCeil(5 * xAdvance) + 1); + line.setLineWidth(qCeil(5 * xAdvance + shyWidth) + 1); line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 5); - QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1); + QVERIFY(qAbs(line.naturalTextWidth() - linefit) <= 1.0); layout.endLayout(); } @@ -2479,21 +2504,21 @@ void tst_QTextLayout::softHyphens() int y = 0; layout.beginLayout(); QTextLine line = layout.createLine(); - line.setLineWidth(qCeil(4 * xAdvance + shyAdvance) + 1); + line.setLineWidth(qCeil(linefit) + 1); line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 5); - QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1); + QVERIFY(qAbs(line.naturalTextWidth() - linefit) <= 1.0); pos += line.textLength(); y += qRound(line.ascent() + line.descent()); line = layout.createLine(); - line.setLineWidth(qCeil(4 * xAdvance + shyAdvance) + 1); + line.setLineWidth(qCeil(linefit) + 1); line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 5); - QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1); + QVERIFY(qAbs(line.naturalTextWidth() - linefit) <= 1.0); layout.endLayout(); } @@ -2510,7 +2535,7 @@ void tst_QTextLayout::softHyphens() line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 4); - QVERIFY(qAbs(line.naturalTextWidth() - 4 * xAdvance) <= 1); + QVERIFY(qAbs(line.naturalTextWidth() - qCeil(4 * xAdvance)) <= 1.0); pos += line.textLength(); y += qRound(line.ascent() + line.descent()); @@ -2520,7 +2545,7 @@ void tst_QTextLayout::softHyphens() line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 5); - QVERIFY(qAbs(line.naturalTextWidth() - 4 * xAdvance) <= 1); + QVERIFY(qAbs(line.naturalTextWidth() - qCeil(4 * xAdvance)) <= 1.0); pos += line.textLength(); y += qRound(line.ascent() + line.descent()); @@ -2530,7 +2555,7 @@ void tst_QTextLayout::softHyphens() line.setPosition(QPoint(0, y)); QCOMPARE(line.textStart(), pos); QCOMPARE(line.textLength(), 1); - QVERIFY(qAbs(line.naturalTextWidth() - shyAdvance) <= 1); + QVERIFY(qAbs(line.naturalTextWidth() - shyWidth) <= 1.0); layout.endLayout(); } } diff --git a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp index 474079037b..7d4921203c 100644 --- a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp +++ b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp @@ -29,7 +29,7 @@ #include <QtTest/QtTest> - +#include <qbuffer.h> #include <qtextdocument.h> #include <qtextdocumentfragment.h> #include <qtexttable.h> @@ -44,6 +44,7 @@ #include <QPainter> #include <QPaintEngine> #endif +#include <private/qtextdocumentlayout_p.h> #include <private/qpagedpaintdevice_p.h> typedef QList<int> IntList; @@ -100,6 +101,13 @@ private slots: void checkBorderAttributes_data(); void checkBorderAttributes(); +#ifndef QT_NO_WIDGETS + void columnWidthWithSpans(); + + void columnWidthWithImage_data(); + void columnWidthWithImage(); +#endif + private: QTextTable *create2x2Table(); QTextTable *create4x4Table(); @@ -1278,5 +1286,84 @@ void tst_QTextTable::checkBorderAttributes() } } +#ifndef QT_NO_WIDGETS +void tst_QTextTable::columnWidthWithSpans() +{ + cleanup(); + init(); + QTextTable *table = cursor.insertTable(4, 4); + QTextEdit textEdit; + textEdit.setDocument(doc); + textEdit.show(); + QVERIFY(QTest::qWaitForWindowExposed(&textEdit)); + + for (int i = 0; i < table->columns(); ++i) + table->cellAt(0, i).firstCursorPosition().insertText(QString("Header %1").arg(i)); + + QTextBlock block = table->cellAt(0, 0).firstCursorPosition().block(); + const QRectF beforeRect = table->document()->documentLayout()->blockBoundingRect(block); + table->mergeCells(1, 0, 1, table->columns()); + block = table->cellAt(0, 0).firstCursorPosition().block(); + const QRectF afterRect = table->document()->documentLayout()->blockBoundingRect(block); + QCOMPARE(afterRect, beforeRect); +} + +void tst_QTextTable::columnWidthWithImage_data() +{ + const auto imageHtml = [](int width, int height) { + QImage image(width, height, QImage::Format_RGB32); + image.fill(Qt::red); + QByteArray imageBytes; + QBuffer buffer(&imageBytes); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "png"); + return QString("<td><img src='data:image/png;base64,%1'/></td>") + .arg(QString::fromLatin1(imageBytes.toBase64())); + }; + + QTest::addColumn<QString>("leftHtml"); + QTest::addColumn<QString>("rightHtml"); + QTest::addColumn<QSize>("imageSize"); + QTest::addRow("image") + << imageHtml(500, 32) << "<td></td>" << QSize(500, 32); + QTest::addRow("image, text") + << imageHtml(32, 32) << "<td>abc</td>" << QSize(32, 32); + QTest::addRow("image, 100%% text") + << imageHtml(32, 32) << "<td style='background-color: grey' width='100%'>abc</td>" + << QSize(32, 32); + QTest::addRow("image, image") + << imageHtml(256, 32) << imageHtml(256, 32) << QSize(256, 32); +} + +void tst_QTextTable::columnWidthWithImage() +{ + const QString tableTemplate = "<table><tr>%1 %2</tr></table>"; + + QFETCH(QString, leftHtml); + QFETCH(QString, rightHtml); + QFETCH(QSize, imageSize); + + QTextDocument doc; + doc.setHtml(tableTemplate.arg(leftHtml).arg(rightHtml)); + QTextEdit textEdit; + textEdit.setDocument(&doc); + textEdit.show(); + QVERIFY(QTest::qWaitForWindowExposed(&textEdit)); + + QTextCursor cursor(doc.firstBlock()); + cursor.movePosition(QTextCursor::Right); + + QTextTable *currentTable = cursor.currentTable(); + QVERIFY(currentTable); + + QTextBlock block = currentTable->cellAt(0, 0).firstCursorPosition().block(); + const QRectF leftRect = currentTable->document()->documentLayout()->blockBoundingRect(block); + block = currentTable->cellAt(0, 1).firstCursorPosition().block(); + const QRectF rightRect = currentTable->document()->documentLayout()->blockBoundingRect(block); + QCOMPARE(leftRect.size().toSize(), imageSize); + QVERIFY(rightRect.left() > leftRect.right()); +} +#endif + QTEST_MAIN(tst_QTextTable) #include "tst_qtexttable.moc" diff --git a/tests/auto/network/access/qdecompresshelper/BLACKLIST b/tests/auto/network/access/qdecompresshelper/BLACKLIST new file mode 100644 index 0000000000..d189fd9e00 --- /dev/null +++ b/tests/auto/network/access/qdecompresshelper/BLACKLIST @@ -0,0 +1,2 @@ +[bigZlib] +macos arm diff --git a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp index cec05f8806..6ae53e2ccd 100644 --- a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp +++ b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp @@ -48,6 +48,8 @@ private Q_SLOTS: void ntlmAuth_data(); void ntlmAuth(); + void sha256AndMd5Digest(); + void equalityOperators(); }; @@ -149,6 +151,34 @@ void tst_QAuthenticator::ntlmAuth() QVERIFY(priv->calculateResponse("GET", "/", "").startsWith("NTLM ")); } +// We don't (currently) support SHA256. So, when presented with the option of MD5 or SHA256, +// we should always pick MD5. +void tst_QAuthenticator::sha256AndMd5Digest() +{ + QByteArray md5 = "Digest realm=\"\", nonce=\"\", algorithm=MD5, qop=\"auth\""; + QByteArray sha256 = "Digest realm=\"\", nonce=\"\", algorithm=SHA-256, qop=\"auth\""; + + QAuthenticator auth; + auth.setUser("unimportant"); + auth.setPassword("unimportant"); + + QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(auth); + + QCOMPARE(priv->phase, QAuthenticatorPrivate::Start); + QList<QPair<QByteArray, QByteArray>> headers; + // Put sha256 first, so that its parsed first... + headers.push_back({"WWW-Authenticate", sha256}); + headers.push_back({"WWW-Authenticate", md5}); + priv->parseHttpResponse(headers, false, QString()); + + QByteArray response = priv->calculateResponse("GET", "/index", {}); + QCOMPARE(priv->phase, QAuthenticatorPrivate::Done); + + QVERIFY(!response.isEmpty()); + QVERIFY(!response.contains("algorithm=SHA-256")); + QVERIFY(response.contains("algorithm=MD5")); +} + void tst_QAuthenticator::equalityOperators() { QAuthenticator s1, s2; diff --git a/tests/auto/network/socket/qtcpserver/BLACKLIST b/tests/auto/network/socket/qtcpserver/BLACKLIST index e268468bdb..c6d4d49908 100644 --- a/tests/auto/network/socket/qtcpserver/BLACKLIST +++ b/tests/auto/network/socket/qtcpserver/BLACKLIST @@ -14,3 +14,6 @@ windows-10 windows-7sp1 windows-10 +[linkLocal] +macos arm + diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST index 129e9f0b4e..fb57715a49 100644 --- a/tests/auto/network/socket/qtcpsocket/BLACKLIST +++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST @@ -2,3 +2,5 @@ windows # QTBUG-66247 +[bind] +macos arm diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST index 40e06ca10a..690d814a2c 100644 --- a/tests/auto/network/socket/qudpsocket/BLACKLIST +++ b/tests/auto/network/socket/qudpsocket/BLACKLIST @@ -7,3 +7,7 @@ opensuse-leap opensuse-42.3 [readyReadForEmptyDatagram] linux +[multicast] +macos arm +[linkLocalIPv6] +macos arm diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index a40ec30622..0dc211dc7d 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1623,6 +1623,9 @@ void tst_QSslSocket::setSocketDescriptor() void tst_QSslSocket::setSslConfiguration_data() { +#if QT_CONFIG(securetransport) + QSKIP("Skipping the cases with certificate, SecureTransport does not like old certificate on the test server"); +#endif // securetransport QTest::addColumn<QSslConfiguration>("configuration"); QTest::addColumn<bool>("works"); diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp index 7c43c52236..c5441770f3 100644 --- a/tests/auto/opengl/qgl/tst_qgl.cpp +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -44,6 +44,7 @@ #include <QGraphicsView> #include <QGraphicsProxyWidget> #include <QVBoxLayout> +#include <QOperatingSystemVersion> #ifdef QT_BUILD_INTERNAL #include <qpa/qplatformpixmap.h> @@ -2537,6 +2538,10 @@ public: void tst_QGL::closeAndThenShow() { +#ifdef Q_OS_MACOS + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur) + QSKIP("Test is crashing flaky on macos-11.0 - QTBUG-96271"); +#endif QWidget *w = new QWidget; w->resize(640, 480); QVBoxLayout *layout = new QVBoxLayout(w); diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm index d97a0db939..174d86a941 100644 --- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm +++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm @@ -86,6 +86,7 @@ QDebug operator<<(QDebug dbg, AXErrorTag err) return false; \ } \ +#define TRY_EXPECT(cond) EXPECT(QTest::qWaitFor([&]{ return (cond); })) @interface TestAXObject : NSObject { @@ -546,21 +547,17 @@ bool notifications(QWidget *w) EXPECT(notificationList.length() == 0); le2->setFocus(); - QCoreApplication::processEvents(); - EXPECT(notificationList.length() == 1); - EXPECT(notificationList.at(0) == QAccessible::Focus); + TRY_EXPECT(notificationList.length() == 1); + TRY_EXPECT(notificationList.at(0) == QAccessible::Focus); le1->setFocus(); - QCoreApplication::processEvents(); - EXPECT(notificationList.length() == 2); - EXPECT(notificationList.at(1) == QAccessible::Focus); + TRY_EXPECT(notificationList.length() == 2); + TRY_EXPECT(notificationList.at(1) == QAccessible::Focus); le1->setText("hello"); - QCoreApplication::processEvents(); - EXPECT(notificationList.length() == 3); - EXPECT(notificationList.at(2) == QAccessible::ValueChanged); + TRY_EXPECT(notificationList.length() == 3); + TRY_EXPECT(notificationList.at(2) == QAccessible::ValueChanged); le1->setText("foo"); - QCoreApplication::processEvents(); - EXPECT(notificationList.length() == 4); - EXPECT(notificationList.at(3) == QAccessible::ValueChanged); + TRY_EXPECT(notificationList.length() == 4); + TRY_EXPECT(notificationList.at(3) == QAccessible::ValueChanged); return true; } diff --git a/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp b/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp index 9fc490417c..fc12738604 100644 --- a/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp +++ b/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp @@ -112,12 +112,16 @@ void tst_VerifyExceptionThrown::testCorrectMyExceptions() const void tst_VerifyExceptionThrown::testFailInt() const { - QVERIFY_EXCEPTION_THROWN(throw int(5), double); + try { + QVERIFY_EXCEPTION_THROWN(throw int(5), double); + } catch (int) {} } void tst_VerifyExceptionThrown::testFailStdString() const { - QVERIFY_EXCEPTION_THROWN(throw std::string("some string"), char*); + try { + QVERIFY_EXCEPTION_THROWN(throw std::string("some string"), char*); + } catch (const std::string &) {} } void tst_VerifyExceptionThrown::testFailStdRuntimeError() const diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 29158faf95..56448c1723 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -47,6 +47,7 @@ #include <QStringListModel> #include <QStyledItemDelegate> #include <QTableWidget> +#include <QTimer> #include <QTreeWidget> #include <QTest> #include <QVBoxLayout> @@ -152,6 +153,8 @@ private slots: void dragSelectAfterNewPress(); void dragWithSecondClick_data(); void dragWithSecondClick(); + void clickAfterDoubleClick(); + private: static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr) { @@ -2606,5 +2609,41 @@ void tst_QAbstractItemView::dragWithSecondClick() QTest::mouseRelease(view->viewport(), Qt::LeftButton, Qt::NoModifier, dragTo); } +void tst_QAbstractItemView::clickAfterDoubleClick() +{ + QTableWidget view(5, 5); + view.horizontalHeader()->hide(); + view.verticalHeader()->hide(); + view.setEditTriggers(QAbstractItemView::NoEditTriggers); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + const QModelIndex index = view.model()->index(1, 1); + QVERIFY(index.isValid()); + const QPoint clickPoint = view.visualRect(index).center(); + + // must use the QWindow overloads so that modality is respected + QWindow *window = view.window()->windowHandle(); + int clickCount = 0; + + connect(&view, &QAbstractItemView::doubleClicked, [&]{ + QDialog dialog(&view); + dialog.setModal(true); + QTimer::singleShot(0, [&]{ dialog.close(); }); + dialog.exec(); + }); + connect(&view, &QAbstractItemView::clicked, [&]{ + ++clickCount; + }); + + QTest::mouseClick(window, Qt::LeftButton, {}, clickPoint); + QCOMPARE(clickCount, 1); + // generates a click followed by a double click; double click opens + // dialog that eats second release + QTest::mouseDClick(window, Qt::LeftButton, {}, clickPoint); + QCOMPARE(clickCount, 2); + QTest::mouseClick(window, Qt::LeftButton, {}, clickPoint); + QCOMPARE(clickCount, 3); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index ec38d565e4..1f1e3804fc 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -25,6 +25,8 @@ macos osx [optimizedResize_topLevel] osx +[render_windowOpacity] +macos arm [render_systemClip] osx [showMinimizedKeepsFocus] diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 1a72ca298f..2b11aec902 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -186,6 +186,7 @@ private slots: void defaultTabOrder(); void reverseTabOrder(); void tabOrderWithProxy(); + void tabOrderWithProxyDisabled(); void tabOrderWithCompoundWidgets(); void tabOrderWithCompoundWidgetsNoFocusPolicy(); void tabOrderNoChange(); @@ -366,6 +367,8 @@ private slots: void focusWidget_task254563(); void rectOutsideCoordinatesLimit_task144779(); void setGraphicsEffect(); + void render_graphicsEffect_data(); + void render_graphicsEffect(); #ifdef QT_BUILD_INTERNAL void destroyBackingStore(); @@ -2006,6 +2009,57 @@ void tst_QWidget::tabOrderWithProxy() QVERIFY(firstEdit->hasFocus()); } +void tst_QWidget::tabOrderWithProxyDisabled() +{ + Container container; + container.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + + QLineEdit lineEdit1; + lineEdit1.setObjectName("lineEdit1"); + + QWidget containingWidget; + containingWidget.setFocusPolicy(Qt::StrongFocus); + auto *containingLayout = new QVBoxLayout; + QLineEdit lineEdit2; + lineEdit2.setObjectName("lineEdit2"); + QLineEdit lineEdit3; + lineEdit3.setObjectName("lineEdit3"); + containingLayout->addWidget(&lineEdit2); + containingLayout->addWidget(&lineEdit3); + containingWidget.setLayout(containingLayout); + containingWidget.setFocusProxy(&lineEdit2); + lineEdit2.setEnabled(false); + + container.box->addWidget(&lineEdit1); + container.box->addWidget(&containingWidget); + + container.show(); + container.activateWindow(); + + QApplication::setActiveWindow(&container); + if (!QTest::qWaitForWindowActive(&container)) + QSKIP("Window failed to activate, skipping test"); + + QVERIFY2(lineEdit1.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); + container.tab(); + QVERIFY2(!lineEdit2.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); + QVERIFY2(lineEdit3.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); + container.tab(); + QVERIFY2(lineEdit1.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); + container.backTab(); + QVERIFY2(lineEdit3.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); + container.backTab(); + QVERIFY2(!lineEdit2.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); + QVERIFY2(lineEdit1.hasFocus(), + qPrintable(QApplication::focusWidget()->objectName())); +} + void tst_QWidget::tabOrderWithCompoundWidgets() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -10096,6 +10150,157 @@ void tst_QWidget::setGraphicsEffect() QVERIFY(!blurEffect); } + +class TestGraphicsEffect : public QGraphicsEffect +{ +public: + TestGraphicsEffect(QObject *parent = nullptr) + : QGraphicsEffect(parent) + { + m_pattern = QPixmap(10, 10); + m_pattern.fill(Qt::lightGray); + QPainter p(&m_pattern); + p.fillRect(QRectF(0, 0, 5, 5), QBrush(Qt::darkGray)); + p.fillRect(QRectF(5, 5, 5, 5), QBrush(Qt::darkGray)); + } + void setExtent(int extent) + { + m_extent = extent; + } + QRectF boundingRectFor(const QRectF &sr) const override + { + return QRectF(sr.x() - m_extent, sr.y() - m_extent, + sr.width() + 2 * m_extent, sr.height() + 2 * m_extent); + } +protected: + void draw(QPainter *painter) override + { + QBrush brush; + brush.setTexture(m_pattern); + brush.setStyle(Qt::TexturePattern); + QPaintDevice *p = painter->device(); + painter->fillRect(QRect(-m_extent, -m_extent, + p->width() + m_extent, p->height() + m_extent), brush); + } + QPixmap m_pattern; + int m_extent = 0; +}; + +static QImage fillExpected1() +{ + QImage expected(QSize(40, 40), QImage::Format_RGB32); + QPainter p(&expected); + p.fillRect(QRect{{0, 0}, expected.size()}, QBrush(Qt::gray)); + p.fillRect(QRect(10, 10, 10, 10), QBrush(Qt::red)); + p.fillRect(QRect(20, 20, 10, 10), QBrush(Qt::blue)); + return expected; +} +static QImage fillExpected2() +{ + QImage expected = fillExpected1(); + QPainter p(&expected); + p.fillRect(QRect(10, 10, 5, 5), QBrush(Qt::darkGray)); + p.fillRect(QRect(15, 15, 5, 5), QBrush(Qt::darkGray)); + p.fillRect(QRect(15, 10, 5, 5), QBrush(Qt::lightGray)); + p.fillRect(QRect(10, 15, 5, 5), QBrush(Qt::lightGray)); + return expected; +} +static QImage fillExpected3() +{ + QImage expected(QSize(40, 40), QImage::Format_RGB32); + QPixmap pattern; + pattern = QPixmap(10, 10); + pattern.fill(Qt::lightGray); + QPainter p(&pattern); + p.fillRect(QRectF(0, 0, 5, 5), QBrush(Qt::darkGray)); + p.fillRect(QRectF(5, 5, 5, 5), QBrush(Qt::darkGray)); + QBrush brush; + brush.setTexture(pattern); + brush.setStyle(Qt::TexturePattern); + QPainter p2(&expected); + p2.fillRect(QRect{{0, 0}, expected.size()}, brush); + return expected; +} +static QImage fillExpected4() +{ + QImage expected = fillExpected1(); + QPixmap pattern; + pattern = QPixmap(10, 10); + pattern.fill(Qt::lightGray); + QPainter p(&pattern); + p.fillRect(QRectF(0, 0, 5, 5), QBrush(Qt::darkGray)); + p.fillRect(QRectF(5, 5, 5, 5), QBrush(Qt::darkGray)); + QBrush brush; + brush.setTexture(pattern); + brush.setStyle(Qt::TexturePattern); + QPainter p2(&expected); + p2.fillRect(QRect{{15, 15}, QSize{20, 20}}, brush); + return expected; +} + +void tst_QWidget::render_graphicsEffect_data() +{ + QTest::addColumn<QImage>("expected"); + QTest::addColumn<bool>("topLevelEffect"); + QTest::addColumn<bool>("child1Effect"); + QTest::addColumn<bool>("child2Effect"); + QTest::addColumn<int>("extent"); + + QTest::addRow("no_effect") << fillExpected1() << false << false << false << 0; + QTest::addRow("first_child_effect") << fillExpected2() << false << true << false << 0; + QTest::addRow("top_level_effect") << fillExpected3() << true << false << false << 0; + QTest::addRow("effect_with_extent") << fillExpected4() << false << false << true << 5; +} + +void tst_QWidget::render_graphicsEffect() +{ + QFETCH(QImage, expected); + QFETCH(bool, topLevelEffect); + QFETCH(bool, child1Effect); + QFETCH(bool, child2Effect); + QFETCH(int, extent); + + QScopedPointer<QWidget> topLevel(new QWidget); + topLevel->setPalette(Qt::gray); + topLevel->resize(40, 40); + topLevel->setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String("::") + + QLatin1String(QTest::currentDataTag())); + + // Render widget with 2 child widgets + QImage image(topLevel->size(), QImage::Format_RGB32); + image.fill(QColor(Qt::gray).rgb()); + + QPainter painter(&image); + + QWidget *childWidget1(new QWidget(topLevel.data())); + childWidget1->setAutoFillBackground(true); + childWidget1->setPalette(Qt::red); + childWidget1->resize(10, 10); + childWidget1->move(10, 10); + QWidget *childWidget2(new QWidget(topLevel.data())); + childWidget2->setAutoFillBackground(true); + childWidget2->setPalette(Qt::blue); + childWidget2->resize(10, 10); + childWidget2->move(20, 20); + + TestGraphicsEffect *graphicsEffect(new TestGraphicsEffect(topLevel.data())); + if (topLevelEffect) + topLevel->setGraphicsEffect(graphicsEffect); + if (child1Effect) + childWidget1->setGraphicsEffect(graphicsEffect); + if (child2Effect) + childWidget2->setGraphicsEffect(graphicsEffect); + graphicsEffect->setExtent(extent); + + // Render without effect + topLevel->render(&painter); +#ifdef RENDER_DEBUG + image.save("render_GraphicsEffect" + QTest::currentDataTag() + ".png"); + expected.save("render_GraphicsEffect_expected" + QTest::currentDataTag() + ".png"); +#endif + QCOMPARE(image, expected); +} + void tst_QWidget::activateWindow() { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp index 01ecfb2ca9..ec1013a078 100644 --- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp +++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp @@ -37,6 +37,7 @@ #include <qlabel.h> #include <qwidget.h> #include <qdialog.h> +#include <qscroller.h> class tst_QAbstractScrollArea : public QObject { @@ -57,6 +58,7 @@ private slots: void task214488_layoutDirection(); void margins(); + void resizeWithOvershoot(); }; tst_QAbstractScrollArea::tst_QAbstractScrollArea() @@ -398,5 +400,42 @@ void tst_QAbstractScrollArea::margins() QCOMPARE(area.viewportMargins(), margins); } +void tst_QAbstractScrollArea::resizeWithOvershoot() +{ + QWidget window; + + QScrollArea scrollArea(&window); + scrollArea.setWidget([]{ + QWidget *widget = new QWidget; + widget->setFixedSize(QSize(0, 200)); + return widget; + }()); + scrollArea.setGeometry(0, 20, 100, 100); + + QScroller::grabGesture(&scrollArea, QScroller::LeftMouseButtonGesture); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + const QPoint originAtRest = scrollArea.viewport()->pos(); + + QPoint center = scrollArea.viewport()->mapToGlobal(scrollArea.viewport()->rect().center()); + center = window.windowHandle()->mapFromGlobal(center); + QTest::mousePress(window.windowHandle(), Qt::LeftButton, {}, center); + QTest::mouseMove(window.windowHandle(), center + QPoint(0, 50)); + QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest + QPoint(0, 25)); + QPoint overshootPosition = scrollArea.viewport()->pos(); + + // trigger a layout of the scroll area while there's overshoot + scrollArea.setGeometry(0, 0, 100, 120); + QCOMPARE(scrollArea.viewport()->pos(), overshootPosition); + QTest::mouseRelease(window.windowHandle(), Qt::LeftButton, {}, center + QPoint(0, 50)); + QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest); + // Process a few more events and verify that the scroll area + // doesn't overcompensate for the overshoot. + QApplication::processEvents(); + QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest); +} + QTEST_MAIN(tst_QAbstractScrollArea) #include "tst_qabstractscrollarea.moc" diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp index bd3ea5686a..75f595e959 100644 --- a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp +++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp @@ -261,15 +261,18 @@ void tst_QFontComboBox::writingSystem() // protected void currentFontChanged(QFont const& f) void tst_QFontComboBox::currentFontChanged() { - SubQFontComboBox box; - QSignalSpy spy0(&box, SIGNAL(currentFontChanged(QFont))); + // The absence of this file does not affect the test results + QFontDatabase::addApplicationFont("ArianaVioleta-dz2K.ttf"); + + SubQFontComboBox *box = new SubQFontComboBox; + QSignalSpy spy0(box, SIGNAL(currentFontChanged(QFont))); - if (box.model()->rowCount() > 2) { - QTest::keyPress(&box, Qt::Key_Down); + if (box->model()->rowCount() > 2) { + QTest::keyPress(box, Qt::Key_Down); QCOMPARE(spy0.count(), 1); QFont f( "Sans Serif" ); - box.setCurrentFont(f); + box->setCurrentFont(f); QCOMPARE(spy0.count(), 2); } else qWarning("Not enough fonts installed on test system. Consider adding some"); |