diff options
Diffstat (limited to 'tests')
29 files changed, 876 insertions, 383 deletions
diff --git a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp index 3c77b1ba0b..212c0a2e13 100644 --- a/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp +++ b/tests/auto/concurrent/qtconcurrentiteratekernel/tst_qtconcurrentiteratekernel.cpp @@ -126,7 +126,8 @@ public: void tst_QtConcurrentIterateKernel::instantiate() { - startThreadEngine(new PrintFor(0, 40)).startBlocking(); + auto future = startThreadEngine(new PrintFor(0, 40)).startAsynchronously(); + future.waitForFinished(); QCOMPARE(iterations.loadRelaxed(), 40); } @@ -165,8 +166,10 @@ void tst_QtConcurrentIterateKernel::stresstest() const int times = 50; for (int i = 0; i < times; ++i) { counter.storeRelaxed(0); - CountFor f(0, iterations); - f.startBlocking(); + // ThreadEngine will delete f when it finishes + auto f = new CountFor(0, iterations); + auto future = f->startAsynchronously(); + future.waitForFinished(); QCOMPARE(counter.loadRelaxed(), iterations); } } @@ -174,8 +177,11 @@ void tst_QtConcurrentIterateKernel::stresstest() void tst_QtConcurrentIterateKernel::noIterations() { const int times = 20000; - for (int i = 0; i < times; ++i) - startThreadEngine(new IterateKernel<TestIterator, void>(0, 0)).startBlocking(); + for (int i = 0; i < times; ++i) { + auto future = startThreadEngine(new IterateKernel<TestIterator, void>(0, 0)) + .startAsynchronously(); + future.waitForFinished(); + } } QMutex threadsMutex; @@ -230,8 +236,10 @@ void tst_QtConcurrentIterateKernel::throttling() threads.clear(); - ThrottleFor f(0, totalIterations); - f.startBlocking(); + // ThreadEngine will delete f when it finishes + auto f = new ThrottleFor(0, totalIterations); + auto future = f->startAsynchronously(); + future.waitForFinished(); QCOMPARE(iterations.loadRelaxed(), totalIterations); diff --git a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp index d4c669cddc..ac7be7acdd 100644 --- a/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp +++ b/tests/auto/concurrent/qtconcurrentthreadengine/tst_qtconcurrentthreadengine.cpp @@ -65,16 +65,9 @@ public: void tst_QtConcurrentThreadEngine::runDirectly() { - { - PrintUser engine; - engine.startSingleThreaded(); - engine.startBlocking(); - } - { - PrintUser *engine = new PrintUser(); - QFuture<void> f = engine->startAsynchronously(); - f.waitForFinished(); - } + PrintUser *engine = new PrintUser(); + QFuture<void> f = engine->startAsynchronously(); + f.waitForFinished(); } class StringResultUser : public ThreadEngine<QString> @@ -106,8 +99,10 @@ public: void tst_QtConcurrentThreadEngine::result() { - StringResultUser engine; - QCOMPARE(*engine.startBlocking(), QString("Foo")); + // ThreadEngine will delete 'engine' when it finishes + auto engine = new StringResultUser(); + auto future = engine->startAsynchronously(); + QCOMPARE(future.result(), QString("Foo")); } class VoidResultUser : public ThreadEngine<void> @@ -133,17 +128,9 @@ public: void tst_QtConcurrentThreadEngine::runThroughStarter() { - { - ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser()); - QFuture<QString> f = starter.startAsynchronously(); - QCOMPARE(f.result(), QString("Foo")); - } - - { - ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser()); - QString str = starter.startBlocking(); - QCOMPARE(str, QString("Foo")); - } + ThreadEngineStarter<QString> starter = startThreadEngine(new StringResultUser()); + QFuture<QString> f = starter.startAsynchronously(); + QCOMPARE(f.result(), QString("Foo")); } class CancelUser : public ThreadEngine<void> @@ -226,12 +213,6 @@ void tst_QtConcurrentThreadEngine::throttle() f.waitForFinished(); QCOMPARE(count.loadRelaxed(), 0); } - - for (int i = 0; i < repeats; ++i) { - ThrottleAlwaysUser t; - t.startBlocking(); - QCOMPARE(count.loadRelaxed(), 0); - } } QSet<QThread *> threads; @@ -266,40 +247,21 @@ public: void tst_QtConcurrentThreadEngine::threadCount() { - //QTBUG-23333: This test is unstable - const int repeats = 10; for (int i = 0; i < repeats; ++i) { - ThreadCountUser t; - t.startBlocking(); - int count = threads.count(); - int count_expected = QThreadPool::globalInstance()->maxThreadCount() + 1; // +1 for the main thread. - if (count != count_expected) - QEXPECT_FAIL("", "QTBUG-23333", Abort); - QCOMPARE(count, count_expected); - (new ThreadCountUser())->startAsynchronously().waitForFinished(); - count = threads.count(); - count_expected = QThreadPool::globalInstance()->maxThreadCount(); - if (count != count_expected) - QEXPECT_FAIL("", "QTBUG-23333", Abort); - QCOMPARE(count, count_expected); + const auto count = threads.count(); + const auto maxThreadCount = QThreadPool::globalInstance()->maxThreadCount(); + QVERIFY(count <= maxThreadCount); + QVERIFY(!threads.contains(QThread::currentThread())); } // Set the finish flag immediately, this should give us one thread only. for (int i = 0; i < repeats; ++i) { - ThreadCountUser t(true /*finishImmediately*/); - t.startBlocking(); - int count = threads.count(); - if (count != 1) - QEXPECT_FAIL("", "QTBUG-23333", Abort); - QCOMPARE(count, 1); - (new ThreadCountUser(true /*finishImmediately*/))->startAsynchronously().waitForFinished(); - count = threads.count(); - if (count != 1) - QEXPECT_FAIL("", "QTBUG-23333", Abort); + const auto count = threads.count(); QCOMPARE(count, 1); + QVERIFY(!threads.contains(QThread::currentThread())); } } @@ -438,7 +400,6 @@ public: void tst_QtConcurrentThreadEngine::exceptions() { - // Asynchronous mode: { bool caught = false; try { @@ -451,32 +412,6 @@ void tst_QtConcurrentThreadEngine::exceptions() QVERIFY2(caught, "did not get exception"); } - // Blocking mode: - // test throwing the exception from a worker thread. - { - bool caught = false; - try { - QtConcurrentExceptionThrower e(QThread::currentThread()); - e.startBlocking(); - } catch (const QException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // test throwing the exception from the main thread (different code path) - { - bool caught = false; - try { - QtConcurrentExceptionThrower e(0); - e.startBlocking(); - } catch (const QException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // Asynchronous mode: { bool caught = false; try { @@ -488,31 +423,6 @@ void tst_QtConcurrentThreadEngine::exceptions() } QVERIFY2(caught, "did not get exception"); } - - // Blocking mode: - // test throwing the exception from a worker thread. - { - bool caught = false; - try { - UnrelatedExceptionThrower e(QThread::currentThread()); - e.startBlocking(); - } catch (const QUnhandledException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } - - // test throwing the exception from the main thread (different code path) - { - bool caught = false; - try { - UnrelatedExceptionThrower e(0); - e.startBlocking(); - } catch (const QUnhandledException &) { - caught = true; - } - QVERIFY2(caught, "did not get exception"); - } } #endif diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 84f4a47585..7c69f5f4b5 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -742,6 +742,10 @@ void tst_QSettings::embeddedZeroByte_data() QTest::newRow("@bytearray\\0") << QVariant(bytes); QTest::newRow("@string\\0") << QVariant(QString::fromLatin1(bytes.data(), bytes.size())); + + bytes = QByteArray("@\xdd\x7d", 3); + QTest::newRow("@-prefixed data") << QVariant(bytes); + QTest::newRow("@-prefixed data as string") << QVariant(QString::fromLatin1(bytes.data(), bytes.size())); } void tst_QSettings::embeddedZeroByte() diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 1bd27cd0ce..3c0adda5de 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -135,24 +135,53 @@ void tst_QTimer::timeout() void tst_QTimer::remainingTime() { - QTimer timer; - QSignalSpy timeoutSpy(&timer, &QTimer::timeout); - timer.setTimerType(Qt::PreciseTimer); - timer.start(200); - - QCOMPARE(timeoutSpy.count(), 0); - QTest::qWait(50); - QCOMPARE(timeoutSpy.count(), 0); - - int remainingTime = timer.remainingTime(); - QVERIFY2(remainingTime >= 50 && remainingTime <= 200, qPrintable(QString::number(remainingTime))); - - QVERIFY(timeoutSpy.wait()); - QCOMPARE(timeoutSpy.count(), 1); - - // the timer is still active, so it should have a non-zero remaining time - remainingTime = timer.remainingTime(); - QVERIFY2(remainingTime >= 50, qPrintable(QString::number(remainingTime))); + QTimer tested; + tested.setTimerType(Qt::PreciseTimer); + + QTimer tester; + tester.setTimerType(Qt::PreciseTimer); + tester.setSingleShot(true); + + const int testedInterval = 200; + const int testerInterval = 50; + const int expectedRemainingTime = testedInterval - testerInterval; + + int testIteration = 0; + const int desiredTestCount = 2; + + auto connection = QObject::connect(&tested, &QTimer::timeout, [&tester]() { + // We let tested (which isn't a single-shot) run repeatedly, to verify + // it *does* repeat, and check that the single-shot tester, starting + // at the same time, does finish first each time, by about the right duration. + tester.start(); // Start tester again. + }); + + QObject::connect(&tester, &QTimer::timeout, [&]() { + const int remainingTime = tested.remainingTime(); + // We expect that remainingTime is at most 150 and not overdue. + const bool remainingTimeInRange = remainingTime > 0 + && remainingTime <= expectedRemainingTime; + if (remainingTimeInRange) + ++testIteration; + else + testIteration = desiredTestCount; // We are going to fail on QVERIFY2() + // below, so we don't want to iterate + // anymore and quickly exit the QTRY_...() + // with this failure. + if (testIteration == desiredTestCount) + QObject::disconnect(connection); // Last iteration, don't start tester again. + QVERIFY2(remainingTimeInRange, qPrintable("Remaining time " + + QByteArray::number(remainingTime) + "ms outside expected range (0ms, " + + QByteArray::number(expectedRemainingTime) + "ms]")); + }); + + tested.start(testedInterval); + tester.start(testerInterval); // Start tester for the 1st time. + + // Test it desiredTestCount times, give it reasonable amount of time + // (twice as much as needed). + QTRY_COMPARE_WITH_TIMEOUT(testIteration, desiredTestCount, + testedInterval * desiredTestCount * 2); } void tst_QTimer::remainingTimeInitial_data() diff --git a/tests/auto/corelib/text/qchar/tst_qchar.cpp b/tests/auto/corelib/text/qchar/tst_qchar.cpp index cf4f6d21e2..1f6f36e972 100644 --- a/tests/auto/corelib/text/qchar/tst_qchar.cpp +++ b/tests/auto/corelib/text/qchar/tst_qchar.cpp @@ -980,6 +980,25 @@ void tst_QChar::normalization_manual() QVERIFY(decomposed.normalized(QString::NormalizationForm_KD) == decomposed); QVERIFY(decomposed.normalized(QString::NormalizationForm_KC) == composed); } + // QTBUG-71894 - erratum fixed in Unicode 4.1.0; SCount bounds are < not <= + { + // Hangul compose, test 0x11a7: + const QChar c[] = { QChar(0xae30), QChar(0x11a7), {} }; + const QChar d[] = { QChar(0x1100), QChar(0x1175), QChar(0x11a7), {} }; + const QString composed(c, 2); + const QString decomposed(d, 3); + + QCOMPARE(decomposed.normalized(QString::NormalizationForm_C), composed); + } + { + // Hangul compose, test 0x11c3: + const QChar c[] = { QChar(0xae30), QChar(0x11c3), {} }; + const QChar d[] = { QChar(0x1100), QChar(0x1175), QChar(0x11c3), {} }; + const QString composed(c, 2); + const QString decomposed(d, 3); + + QCOMPARE(decomposed.normalized(QString::NormalizationForm_C), composed); + } } void tst_QChar::normalizationCorrections() diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp index f924bd1560..43698e5a19 100644 --- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp @@ -2983,13 +2983,13 @@ void tst_QLocale::bcp47Name() class MySystemLocale : public QSystemLocale { public: - MySystemLocale(const QLocale &locale) : m_locale(locale) + MySystemLocale(const QString &locale) : m_name(locale), m_locale(locale) { } - QVariant query(QueryType /*type*/, QVariant /*in*/) const override + QVariant query(QueryType type, QVariant /*in*/) const override { - return QVariant(); + return type == UILanguages ? QVariant(QStringList{m_name}) : QVariant(); } QLocale fallbackUiLocale() const override @@ -2998,16 +2998,32 @@ public: } private: + const QString m_name; const QLocale m_locale; }; void tst_QLocale::systemLocale_data() { + // Test uses MySystemLocale, so is platform-independent. QTest::addColumn<QString>("name"); QTest::addColumn<QLocale::Language>("language"); - QTest::addRow("catalan") << QString("ca") << QLocale::Catalan; - QTest::addRow("ukrainian") << QString("uk") << QLocale::Ukrainian; - QTest::addRow("german") << QString("de") << QLocale::German; + QTest::addColumn<QStringList>("uiLanguages"); + + QTest::addRow("catalan") + << QString("ca") << QLocale::Catalan + << QStringList{QStringLiteral("ca"), QStringLiteral("ca-ES"), QStringLiteral("ca-Latn-ES")}; + QTest::addRow("ukrainian") + << QString("uk") << QLocale::Ukrainian + << QStringList{QStringLiteral("uk"), QStringLiteral("uk-UA"), QStringLiteral("uk-Cyrl-UA")}; + QTest::addRow("german") + << QString("de") << QLocale::German + << QStringList{QStringLiteral("de"), QStringLiteral("de-DE"), QStringLiteral("de-Latn-DE")}; + QTest::addRow("chinese-min") + << QString("zh") << QLocale::Chinese + << QStringList{QStringLiteral("zh"), QStringLiteral("zh-CN"), QStringLiteral("zh-Hans-CN")}; + QTest::addRow("chinese-full") + << QString("zh-Hans-CN") << QLocale::Chinese + << QStringList{QStringLiteral("zh-Hans-CN"), QStringLiteral("zh"), QStringLiteral("zh-CN")}; } void tst_QLocale::systemLocale() @@ -3017,11 +3033,13 @@ void tst_QLocale::systemLocale() QFETCH(QString, name); QFETCH(QLocale::Language, language); + QFETCH(QStringList, uiLanguages); { MySystemLocale sLocale(name); QCOMPARE(QLocale().language(), language); QCOMPARE(QLocale::system().language(), language); + QCOMPARE(QLocale::system().uiLanguages(), uiLanguages); } QCOMPARE(QLocale(), originalLocale); diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 8f53824050..696b8159ac 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -600,6 +600,7 @@ private slots: void isValidUtf16_data(); void isValidUtf16(); void unicodeStrings(); + void vasprintfWithPrecision(); }; template <class T> const T &verifyZeroTermination(const T &t) { return t; } @@ -1674,7 +1675,7 @@ void tst_QString::lastIndexOf() QCOMPARE(haystack.lastIndexOf(needle.toLatin1(), from, cs), expected); QCOMPARE(haystack.lastIndexOf(needle.toLatin1().data(), from, cs), expected); - if (from >= -1 && from < haystack.size() && needle.size() > 0) { + if (from >= -1 && from < haystack.size()) { // unfortunately, QString and QRegExp don't have the same out of bound semantics // I think QString is wrong -- See file log for contact information. { @@ -7148,6 +7149,35 @@ void tst_QString::isValidUtf16() QTEST(string.isValidUtf16(), "valid"); } +static QString doVasprintf(const char *msg, ...) { + va_list args; + va_start(args, msg); + const QString result = QString::vasprintf(msg, args); + va_end(args); + return result; +} + +void tst_QString::vasprintfWithPrecision() +{ + { + const char *msg = "Endpoint %.*s with"; + static const char arg0[3] = { 'a', 'b', 'c' }; + static const char arg1[4] = { 'a', 'b', 'c', '\0' }; + QCOMPARE(doVasprintf(msg, 3, arg0), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 9, arg1), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 0, nullptr), QStringLiteral("Endpoint with")); + } + + { + const char *msg = "Endpoint %.*ls with"; + static const ushort arg0[3] = { 'a', 'b', 'c' }; + static const ushort arg1[4] = { 'a', 'b', 'c', '\0' }; + QCOMPARE(doVasprintf(msg, 3, arg0), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 9, arg1), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 0, nullptr), QStringLiteral("Endpoint with")); + } +} + QTEST_APPLESS_MAIN(tst_QString) #include "tst_qstring.moc" diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp index 0bdadedfac..49c8ec2113 100644 --- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp +++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp @@ -94,6 +94,7 @@ private slots: void nestedExceptions(); #endif void nonGlobalThreadPool(); + void resultsReadyAt(); }; void tst_QFuture::resultStore() @@ -627,6 +628,26 @@ void tst_QFuture::futureInterface() VoidResult a; a.run().waitForFinished(); } + + { + QFutureInterface<int> fi; + fi.reportStarted(); + fi.reportResults(QVector<int> {}); + fi.reportFinished(); + + QVERIFY(fi.results().empty()); + } + + { + QFutureInterface<int> fi; + fi.reportStarted(); + QVector<int> values = { 1, 2, 3 }; + fi.reportResults(values); + fi.reportResults(QVector<int> {}); + fi.reportFinished(); + + QCOMPARE(fi.results(), values.toList()); + } } template <typename T> @@ -1557,5 +1578,63 @@ void tst_QFuture::nonGlobalThreadPool() } } +void tst_QFuture::resultsReadyAt() +{ + QFutureInterface<int> iface; + QFutureWatcher<int> watcher; + watcher.setFuture(iface.future()); + + QTestEventLoop eventProcessor; + connect(&watcher, &QFutureWatcher<int>::finished, &eventProcessor, &QTestEventLoop::exitLoop); + + const int nExpectedResults = 4; + int reported = 0; + int taken = 0; + connect(&watcher, &QFutureWatcher<int>::resultsReadyAt, + [&iface, &reported, &taken](int begin, int end) + { + auto future = iface.future(); + QVERIFY(end - begin > 0); + for (int i = begin; i < end; ++i, ++reported) { + QVERIFY(future.isResultReadyAt(i)); + taken |= 1 << i; + } + }); + + auto report = [&iface](int index) + { + int dummyResult = 0b101010; + iface.reportResult(&dummyResult, index); + }; + + const QSignalSpy readyCounter(&watcher, &QFutureWatcher<int>::resultsReadyAt); + QTimer::singleShot(0, [&iface, &report]{ + // With filter mode == true, the result may go into the pending results. + // Reporting it as ready will allow an application to try and access the + // result, crashing on invalid (store.end()) iterator dereferenced. + iface.setFilterMode(true); + iface.reportStarted(); + report(0); + report(1); + // This one - should not be reported (it goes into pending): + report(3); + // Let's close the 'gap' and make them all ready: + report(-1); + iface.reportFinished(); + }); + + // Run event loop, QCoreApplication::postEvent is in use + // in QFutureInterface: + eventProcessor.enterLoopMSecs(2000); + QVERIFY(!eventProcessor.timeout()); + if (QTest::currentTestFailed()) // Failed in our lambda observing 'ready at' + return; + + QCOMPARE(reported, nExpectedResults); + QCOMPARE(nExpectedResults, iface.future().resultCount()); + QCOMPARE(readyCounter.count(), 3); + QCOMPARE(taken, 0b1111); +} + QTEST_MAIN(tst_QFuture) #include "tst_qfuture.moc" diff --git a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp index fba617e34d..a1742b3182 100644 --- a/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp +++ b/tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp @@ -175,6 +175,14 @@ void tst_QtConcurrentResultStore::addResults() ++it; QCOMPARE(it, store.end()); + + QVector<int> empty; + const auto countBefore = store.count(); + QCOMPARE(store.addResults(countBefore, &empty), -1); + QCOMPARE(store.count(), countBefore); + + QCOMPARE(store.addResults(countBefore, &vec1), countBefore); + QCOMPARE(store.count(), countBefore + vec1.size()); } void tst_QtConcurrentResultStore::resultIndex() @@ -338,6 +346,14 @@ void tst_QtConcurrentResultStore::filterMode() QCOMPARE(store.contains(6), true); QCOMPARE(store.contains(7), true); QCOMPARE(store.contains(8), false); + + QVector<int> empty; + const auto countBefore = store.count(); + QCOMPARE(store.addResults(countBefore, &empty), -1); + QCOMPARE(store.count(), countBefore); + + QCOMPARE(store.addResult(countBefore, &int2), countBefore); + QCOMPARE(store.count(), countBefore + 1); } void tst_QtConcurrentResultStore::addCanceledResult() diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index 8041fb5439..7dbd587451 100644 --- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp @@ -1088,35 +1088,38 @@ void tst_QQuaternion::fromEulerAngles_data() QTest::addColumn<float>("yaw"); QTest::addColumn<float>("roll"); + QTest::addColumn<QQuaternion>("quaternion"); + QTest::newRow("null") - << 0.0f << 0.0f << 0.0f; + << 0.0f << 0.0f << 0.0f << QQuaternion(1.0f, 0.0f, 0.0f, 0.0f); QTest::newRow("xonly") - << 90.0f << 0.0f << 0.0f; + << 90.0f << 0.0f << 0.0f << QQuaternion(0.707107f, 0.707107f, 0.0f, 0.0f); QTest::newRow("yonly") - << 0.0f << 180.0f << 0.0f; + << 0.0f << 180.0f << 0.0f << QQuaternion(0.0f, 0.0f, 1.0f, 0.0f); QTest::newRow("zonly") - << 0.0f << 0.0f << 270.0f; + << 0.0f << 0.0f << 270.0f << QQuaternion(-0.707107f, 0.0f, 0.0f, 0.707107f); QTest::newRow("x+z") - << 30.0f << 0.0f << 45.0f; + << 30.0f << 0.0f << 45.0f << QQuaternion(0.892399f, 0.239118f, -0.099046f, 0.369644f); QTest::newRow("x+y") - << 30.0f << 90.0f << 0.0f; + << 30.0f << 90.0f << 0.0f << QQuaternion(0.683013f, 0.183013f, 0.683013f, -0.183013f); QTest::newRow("y+z") - << 0.0f << 45.0f << 30.0f; + << 0.0f << 45.0f << 30.0f << QQuaternion(0.892399f, 0.099046f, 0.369644f, 0.239118f); QTest::newRow("complex") - << 30.0f << 240.0f << -45.0f; + << 30.0f << 240.0f << -45.0f << QQuaternion(-0.531976f, -0.43968f, 0.723317f, -0.02226f); } void tst_QQuaternion::fromEulerAngles() { QFETCH(float, pitch); QFETCH(float, yaw); QFETCH(float, roll); + QFETCH(QQuaternion, quaternion); // Use a straight-forward implementation of the algorithm at: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60 @@ -1132,11 +1135,22 @@ void tst_QQuaternion::fromEulerAngles() QVERIFY(myFuzzyCompare(answer.z(), result.z())); QVERIFY(myFuzzyCompare(answer.scalar(), result.scalar())); + // quaternion should be the same as the result + QVERIFY(myFuzzyCompare(answer.x(), quaternion.x())); + QVERIFY(myFuzzyCompare(answer.y(), quaternion.y())); + QVERIFY(myFuzzyCompare(answer.z(), quaternion.z())); + QVERIFY(myFuzzyCompare(answer.scalar(), quaternion.scalar())); + { QVector3D answerEulerAngles = answer.toEulerAngles(); QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.x(), pitch)); QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.y(), yaw)); QVERIFY(myFuzzyCompareDegrees(answerEulerAngles.z(), roll)); + + QVector3D quaternionEulerAngles = quaternion.toEulerAngles(); + QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.x(), pitch)); + QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.y(), yaw)); + QVERIFY(myFuzzyCompareDegrees(quaternionEulerAngles.z(), roll)); } answer = QQuaternion::fromEulerAngles(pitch, yaw, roll); @@ -1151,6 +1165,12 @@ void tst_QQuaternion::fromEulerAngles() QVERIFY(myFuzzyCompareDegrees(answerPitch, pitch)); QVERIFY(myFuzzyCompareDegrees(answerYaw, yaw)); QVERIFY(myFuzzyCompareDegrees(answerRoll, roll)); + + float quaternionPitch, quaternionYaw, quaternionRoll; + quaternion.getEulerAngles(&quaternionPitch, &quaternionYaw, &quaternionRoll); + QVERIFY(myFuzzyCompareDegrees(quaternionPitch, pitch)); + QVERIFY(myFuzzyCompareDegrees(quaternionYaw, yaw)); + QVERIFY(myFuzzyCompareDegrees(quaternionRoll, roll)); } } diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 42e98ce363..d7c3f95f1d 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -308,6 +308,7 @@ private slots: void fillPolygon(); void drawImageAtPointF(); + void scaledDashes(); private: void fillData(); @@ -5468,6 +5469,36 @@ void tst_QPainter::drawImageAtPointF() paint.end(); } +void tst_QPainter::scaledDashes() +{ + // Test that we do not hit the limit-huge-number-of-dashes path + QRgb fore = qRgb(0, 0, 0xff); + QRgb back = qRgb(0xff, 0xff, 0); + QImage image(5, 32, QImage::Format_RGB32); + image.fill(back); + QPainter p(&image); + QPen pen(QColor(fore), 3, Qt::DotLine); + p.setPen(pen); + p.scale(1, 2); + p.drawLine(2, 0, 2, 16); + p.end(); + + bool foreFound = false; + bool backFound = false; + int i = 0; + while (i < 32 && (!foreFound || !backFound)) { + QRgb pix = image.pixel(3, i); + if (pix == fore) + foreFound = true; + else if (pix == back) + backFound = true; + i++; + } + + QVERIFY(foreFound); + QVERIFY(backFound); +} + QTEST_MAIN(tst_QPainter) #include "tst_qpainter.moc" diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index c1dd2d97a1..2feca77f40 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -1909,6 +1909,20 @@ void tst_QTextLayout::longText() QFontMetricsF fm(layout.font()); QVERIFY(layout.maximumWidth() - fm.horizontalAdvance(' ') <= QFIXED_MAX); } + + { + QTextLayout layout(QString("AAAAAAAA").repeated(200000)); + layout.setCacheEnabled(true); + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + } + layout.endLayout(); + QFontMetricsF fm(layout.font()); + QVERIFY(layout.maximumWidth() - fm.horizontalAdvance('A') <= QFIXED_MAX); + } } void tst_QTextLayout::widthOfTabs() diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 0d851cd3df..392419e066 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -271,6 +271,10 @@ void tst_Http2::singleRequest() request.setAttribute(h2Attribute, QVariant(true)); auto reply = manager->get(request); +#if QT_CONFIG(ssl) + QSignalSpy encSpy(reply, &QNetworkReply::encrypted); +#endif // QT_CONFIG(ssl) + connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished); // Since we're using self-signed certificates, // ignore SSL errors: @@ -285,6 +289,11 @@ void tst_Http2::singleRequest() QCOMPARE(reply->error(), QNetworkReply::NoError); QVERIFY(reply->isFinished()); + +#if QT_CONFIG(ssl) + if (connectionType == H2Type::h2Alpn || connectionType == H2Type::h2Direct) + QCOMPARE(encSpy.count(), 1); +#endif // QT_CONFIG(ssl) } void tst_Http2::multipleRequests() diff --git a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index 856033fb63..98b2a0d2f7 100644 --- a/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -35,6 +35,7 @@ #include <algorithm> #define EXAMPLE_URL "http://user:pass@localhost:4/#foo" +#define EXAMPLE_URL2 "http://user:pass@localhost:4/bar" //cached objects are organized into these many subdirs #define NUM_SUBDIRECTORIES 16 @@ -141,7 +142,7 @@ class SubQNetworkDiskCache : public QNetworkDiskCache public: ~SubQNetworkDiskCache() { - if (!cacheDirectory().isEmpty()) + if (!cacheDirectory().isEmpty() && clearOnDestruction) clear(); } @@ -170,6 +171,11 @@ public: d->write("Hello World!"); insert(d); } + + void setClearCacheOnDestruction(bool value) { clearOnDestruction = value; } + +private: + bool clearOnDestruction = true; }; tst_QNetworkDiskCache::tst_QNetworkDiskCache() @@ -241,17 +247,39 @@ void tst_QNetworkDiskCache::prepare() // public qint64 cacheSize() const void tst_QNetworkDiskCache::cacheSize() { - SubQNetworkDiskCache cache; - cache.setCacheDirectory(tempDir.path()); - QCOMPARE(cache.cacheSize(), qint64(0)); + qint64 cacheSize = 0; + { + SubQNetworkDiskCache cache; + cache.setCacheDirectory(tempDir.path()); + QCOMPARE(cache.cacheSize(), qint64(0)); - QUrl url(EXAMPLE_URL); - QNetworkCacheMetaData metaData; - metaData.setUrl(url); - QIODevice *d = cache.prepare(metaData); - cache.insert(d); - QVERIFY(cache.cacheSize() > qint64(0)); + { + QUrl url(EXAMPLE_URL); + QNetworkCacheMetaData metaData; + metaData.setUrl(url); + QIODevice *d = cache.prepare(metaData); + cache.insert(d); + cacheSize = cache.cacheSize(); + QVERIFY(cacheSize > qint64(0)); + } + // Add a second item, some difference in behavior when the cache is not empty + { + QUrl url(EXAMPLE_URL2); + QNetworkCacheMetaData metaData; + metaData.setUrl(url); + QIODevice *d = cache.prepare(metaData); + cache.insert(d); + QVERIFY(cache.cacheSize() > cacheSize); + cacheSize = cache.cacheSize(); + } + // Don't clear the cache on destruction so we can re-open the cache and test its size. + cache.setClearCacheOnDestruction(false); + } + + SubQNetworkDiskCache cache; + cache.setCacheDirectory(tempDir.path()); + QCOMPARE(cache.cacheSize(), cacheSize); cache.clear(); QCOMPARE(cache.cacheSize(), qint64(0)); } diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index 115d111974..445e6a2d98 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -1128,6 +1128,7 @@ void tst_QSslCertificate::verify() #if QT_CONFIG(securetransport) QSKIP("Not implemented in SecureTransport"); #endif + QList<QSslError> errors; QList<QSslCertificate> toVerify; diff --git a/tests/auto/tools/moc/enum_with_include.h b/tests/auto/tools/moc/enum_with_include.h index b8abf77f12..cd53ba6a28 100644 --- a/tests/auto/tools/moc/enum_with_include.h +++ b/tests/auto/tools/moc/enum_with_include.h @@ -34,6 +34,11 @@ class Foo : public QObject { enum en { #include <enum_inc.h> }; + + enum class en2 { + #include <enum_inc.h> + reference = 42 + }; Q_OBJECT }; #endif diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 0bdf61e1e1..29158faf95 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -150,6 +150,8 @@ private slots: void checkFocusAfterActivationChanges_data(); void checkFocusAfterActivationChanges(); void dragSelectAfterNewPress(); + void dragWithSecondClick_data(); + void dragWithSecondClick(); private: static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr) { @@ -2511,5 +2513,98 @@ void tst_QAbstractItemView::dragSelectAfterNewPress() QVERIFY(selected.contains(model.index(i, 0))); } +void tst_QAbstractItemView::dragWithSecondClick_data() +{ + QTest::addColumn<QString>("viewClass"); + QTest::addColumn<bool>("doubleClick"); + for (QString viewClass : {"QListView", "QTreeView"}) { + QTest::addRow("DoubleClick") << viewClass << true; + QTest::addRow("Two Single Clicks") << viewClass << false; + } +} + +// inject the ability to record which indexes get dragged into any QAbstractItemView class +struct DragRecorder +{ + virtual ~DragRecorder() = default; + bool dragStarted = false; + QModelIndexList draggedIndexes; + QAbstractItemView *view; +}; + +template<class ViewClass> +class DragRecorderView : public ViewClass, public DragRecorder +{ +public: + DragRecorderView() + { view = this; } +protected: + void startDrag(Qt::DropActions) override + { + draggedIndexes = ViewClass::selectedIndexes(); + dragStarted = true; + } +}; + +void tst_QAbstractItemView::dragWithSecondClick() +{ + QFETCH(QString, viewClass); + QFETCH(bool, doubleClick); + + QStandardItemModel model; + QStandardItem *parentItem = model.invisibleRootItem(); + for (int i = 0; i < 10; ++i) { + QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); + item->setDragEnabled(true); + item->setEditable(false); + parentItem->appendRow(item); + } + + std::unique_ptr<DragRecorder> dragRecorder; + if (viewClass == "QTreeView") + dragRecorder.reset(new DragRecorderView<QTreeView>); + else if (viewClass == "QListView") + dragRecorder.reset(new DragRecorderView<QListView>); + + QAbstractItemView *view = dragRecorder->view; + view->setModel(&model); + view->setFixedSize(160, 650); // Minimum width for windows with frame on Windows 8 + view->setSelectionMode(QAbstractItemView::MultiSelection); + view->setDragDropMode(QAbstractItemView::InternalMove); + centerOnScreen(view); + moveCursorAway(view); + view->show(); + QVERIFY(QTest::qWaitForWindowExposed(view)); + + QModelIndex index0 = model.index(0, 0); + QModelIndex index1 = model.index(1, 0); + // Select item 0 using a single click + QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier, + view->visualRect(index0).center()); + QCOMPARE(view->currentIndex(), index0); + + if (doubleClick) { + // press on same item within the double click interval + QTest::mouseDClick(view->viewport(), Qt::LeftButton, Qt::NoModifier, + view->visualRect(index0).center()); + } else { + // or on different item with a slow second press + QTest::mousePress(view->viewport(), Qt::LeftButton, Qt::NoModifier, + view->visualRect(index1).center()); + } + // then drag far enough with left button held + const QPoint dragTo = view->visualRect(index1).center() + + QPoint(2 * QApplication::startDragDistance(), + 2 * QApplication::startDragDistance()); + QMouseEvent mouseMoveEvent(QEvent::MouseMove, dragTo, + Qt::NoButton, Qt::LeftButton, Qt::NoModifier); + QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent)); + // twice since the view will first enter dragging state, then start the drag + // (not necessary to actually move the mouse) + QVERIFY(QApplication::sendEvent(view->viewport(), &mouseMoveEvent)); + QVERIFY(dragRecorder->dragStarted); + QTest::mouseRelease(view->viewport(), Qt::LeftButton, Qt::NoModifier, dragTo); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index dadb9f836c..875b2c08e5 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -169,6 +169,8 @@ private slots: void itemAlignment(); void internalDragDropMove_data(); void internalDragDropMove(); + void scrollOnRemove_data(); + void scrollOnRemove(); }; // Testing get/set functions @@ -2550,6 +2552,7 @@ void tst_QListView::internalDragDropMove_data() | Qt::ItemIsEditable | Qt::ItemIsDragEnabled; + const QStringList unchanged = QStringList{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; const QStringList reordered = QStringList{"0", "2", "3", "4", "5", "6", "7", "8", "9", "1"}; const QStringList replaced = QStringList{"0", "2", "3", "4", "1", "6", "7", "8", "9"}; @@ -2564,7 +2567,8 @@ void tst_QListView::internalDragDropMove_data() << Qt::MoveAction << defaultFlags << modelMoves - << reordered; + // listview in IconMode doesn't change the model + << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered); QTest::newRow((rowName + ", only move").constData()) << viewMode @@ -2573,7 +2577,8 @@ void tst_QListView::internalDragDropMove_data() << Qt::MoveAction << defaultFlags << modelMoves - << reordered; + // listview in IconMode doesn't change the model + << ((viewMode == QListView::IconMode && !modelMoves) ? unchanged : reordered); QTest::newRow((rowName + ", replace item").constData()) << viewMode @@ -2719,5 +2724,72 @@ void tst_QListView::internalDragDropMove() } +void tst_QListView::scrollOnRemove_data() +{ + QTest::addColumn<QListView::ViewMode>("viewMode"); + QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode"); + + const QMetaObject &mo = QListView::staticMetaObject; + const auto viewModeEnum = mo.enumerator(mo.indexOfEnumerator("ViewMode")); + const auto selectionModeEnum = mo.enumerator(mo.indexOfEnumerator("SelectionMode")); + for (auto viewMode : { QListView::ListMode, QListView::IconMode }) { + const char *viewModeName = viewModeEnum.valueToKey(viewMode); + for (int index = 0; index < selectionModeEnum.keyCount(); ++index) { + const auto selectionMode = QAbstractItemView::SelectionMode(selectionModeEnum.value(index)); + const char *selectionModeName = selectionModeEnum.valueToKey(selectionMode); + QTest::addRow("%s, %s", viewModeName, selectionModeName) << viewMode << selectionMode; + } + } +} + +void tst_QListView::scrollOnRemove() +{ + QFETCH(QListView::ViewMode, viewMode); + QFETCH(QAbstractItemView::SelectionMode, selectionMode); + + QPixmap pixmap; + if (viewMode == QListView::IconMode) { + pixmap = QPixmap(25, 25); + pixmap.fill(Qt::red); + } + + QStandardItemModel model; + for (int i = 0; i < 50; ++i) { + QStandardItem *item = new QStandardItem(QString::number(i)); + item->setIcon(pixmap); + model.appendRow(item); + } + + QWidget widget; + QListView view(&widget); + view.setFixedSize(100, 100); + view.setAutoScroll(true); + if (viewMode == QListView::IconMode) + view.setWrapping(true); + view.setModel(&model); + view.setSelectionMode(selectionMode); + view.setViewMode(viewMode); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QCOMPARE(view.verticalScrollBar()->value(), 0); + const QModelIndex item25 = model.index(25, 0); + view.scrollTo(item25); + QTRY_VERIFY(view.verticalScrollBar()->value() > 0); // layout and scrolling are delayed + const int item25Position = view.verticalScrollBar()->value(); + // selecting a fully visible item shouldn't scroll + view.selectionModel()->setCurrentIndex(item25, QItemSelectionModel::SelectCurrent); + QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position); + + // removing the selected item might scroll if another item is selected + model.removeRow(25); + + // if nothing is selected now, then the view should not have scrolled + if (!view.selectionModel()->selectedIndexes().count()) + QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position); +} + + QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp index 89c4a74739..364bc36dff 100644 --- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp @@ -113,6 +113,8 @@ private slots: #endif void fileSystemModel_data(); void fileSystemModel(); + void fileDialog_data(); + void fileDialog(); void changingModel_data(); void changingModel(); @@ -695,7 +697,26 @@ void tst_QCompleter::fileSystemModel() #ifdef Q_OS_WINRT QSKIP("WinRT cannot access directories outside of the application's sandbox"); #endif - //QFileSystemModel is assync. + //QFileSystemModel is async. + filter(true); +} + +/*! + In the file dialog, the completer uses the EditRole. + See QTBUG-94799 +*/ +void tst_QCompleter::fileDialog_data() +{ + fileSystemModel_data(); + completer->setCompletionRole(Qt::EditRole); +} + +void tst_QCompleter::fileDialog() +{ +#ifdef Q_OS_WINRT + QSKIP("WinRT cannot access directories outside of the application's sandbox"); +#endif + //QFileSystemModel is async. filter(true); } diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index 456d0d55e0..c670147920 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -1370,19 +1370,19 @@ void tst_QDateTimeEdit::editingRanged() QFETCH(QString, userInput); QFETCH(QDateTime, expected); - QDateTimeEdit *edit; + QScopedPointer<QDateTimeEdit> edit; if (minTime.isValid()) { - edit = new QDateTimeEdit; + edit.reset(new QDateTimeEdit); edit->setDisplayFormat("dd.MM.yyyy hh:mm"); edit->setDateTimeRange(QDateTime(minDate, minTime), QDateTime(maxDate, maxTime)); } else { - edit = new QDateEdit; + edit.reset(new QDateEdit); edit->setDisplayFormat("dd.MM.yyyy"); edit->setDateRange(minDate, maxDate); } int callCount = 0; - connect(edit, &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) { + connect(edit.get(), &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) { ++callCount; if (minTime.isValid()) { QVERIFY(dateTime >= QDateTime(minDate, minTime)); @@ -1394,15 +1394,15 @@ void tst_QDateTimeEdit::editingRanged() }); edit->show(); - QApplication::setActiveWindow(edit); - if (!QTest::qWaitForWindowActive(edit)) + QApplication::setActiveWindow(edit.get()); + if (!QTest::qWaitForWindowActive(edit.get())) QSKIP("Failed to make window active, aborting"); edit->setFocus(); // with keyboard tracking, never get a signal with an out-of-range value edit->setKeyboardTracking(true); - QTest::keyClicks(edit, userInput); - QTest::keyClick(edit, Qt::Key_Return); + QTest::keyClicks(edit.get(), userInput); + QTest::keyClick(edit.get(), Qt::Key_Return); QVERIFY(callCount > 0); // QDateTimeEdit blocks these dates from being entered - see QTBUG-65 @@ -1418,12 +1418,10 @@ void tst_QDateTimeEdit::editingRanged() callCount = 0; edit->setKeyboardTracking(false); - QTest::keyClicks(edit, userInput); - QTest::keyClick(edit, Qt::Key_Return); + QTest::keyClicks(edit.get(), userInput); + QTest::keyClick(edit.get(), Qt::Key_Return); QCOMPARE(edit->dateTime(), expected); QCOMPARE(callCount, 1); - - delete edit; } void tst_QDateTimeEdit::wrappingTime_data() @@ -3807,7 +3805,6 @@ void tst_QDateTimeEdit::deleteCalendarWidget() { { // setup - QCalendarWidget *cw = 0; QDateEdit edit; QVERIFY(!edit.calendarWidget()); edit.setCalendarPopup(true); @@ -3815,8 +3812,7 @@ void tst_QDateTimeEdit::deleteCalendarWidget() edit.calendarWidget()->setObjectName("cw1");; // delete - cw = edit.calendarWidget(); - delete cw; + delete edit.calendarWidget(); // it should create a new widget QVERIFY(edit.calendarWidget()); diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 6408df3f11..7c2203deb4 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -292,6 +292,7 @@ private slots: void clearButtonVisibleAfterSettingText_QTBUG_45518(); void sideWidgets(); void sideWidgetsActionEvents(); + void sideWidgetsEffectiveMargins(); void shouldShowPlaceholderText_data(); void shouldShowPlaceholderText(); @@ -4646,6 +4647,71 @@ void tst_QLineEdit::sideWidgetsActionEvents() QCOMPARE(toolButton2->x(), toolButton1X); } +/*! + Verify that side widgets are positioned correctly and result in + correct effective text margins. +*/ +void tst_QLineEdit::sideWidgetsEffectiveMargins() +{ +#ifndef QT_BUILD_INTERNAL + QSKIP("This test requires a developer build."); +#else + QLineEdit edit; + edit.setPlaceholderText("placeholder"); + edit.setClearButtonEnabled(true); + edit.show(); + QLineEditPrivate *priv = QLineEditPrivate::get(&edit); + const auto sideWidgetParameters = priv->sideWidgetParameters(); + const int sideWidgetWidth = sideWidgetParameters.widgetWidth + sideWidgetParameters.margin; + QVERIFY(QTest::qWaitForWindowExposed(&edit)); + + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.setText("Left to right"); // clear button fades in on the right + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.setLayoutDirection(Qt::RightToLeft); + edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), 0); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.setLayoutDirection(Qt::LeftToRight); + + const QIcon leftIcon = edit.style()->standardIcon(QStyle::SP_FileIcon); + const QIcon rightIcon = edit.style()->standardIcon(QStyle::SP_DirIcon); + edit.addAction(leftIcon, QLineEdit::ActionPosition::LeadingPosition); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), 0); + + edit.addAction(rightIcon, QLineEdit::ActionPosition::TrailingPosition); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + + edit.setText("Left to right"); // clear button on the right + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), 2 * sideWidgetWidth); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + + edit.setLayoutDirection(Qt::RightToLeft); + edit.setText("ئۇيغۇر تىلى"); // clear button fades in on the left + QCOMPARE(priv->effectiveTextMargins().left(), 2 * sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); + edit.clear(); + QCOMPARE(priv->effectiveTextMargins().left(), sideWidgetWidth); + QCOMPARE(priv->effectiveTextMargins().right(), sideWidgetWidth); +#endif +} + Q_DECLARE_METATYPE(Qt::AlignmentFlag) void tst_QLineEdit::shouldShowPlaceholderText_data() { diff --git a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp index 79a963f532..f04f803ecf 100644 --- a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp +++ b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp @@ -98,6 +98,9 @@ private slots: void mouseReleaseOutsideTabBar(); + void scrollButtons_data(); + void scrollButtons(); + private: void checkPositions(const TabBar &tabbar, const QList<int> &positions); }; @@ -869,5 +872,71 @@ void tst_QTabBar::checkPositions(const TabBar &tabbar, const QList<int> &positio } } +void tst_QTabBar::scrollButtons_data() +{ + QTest::addColumn<QTabWidget::TabPosition>("tabPosition"); + QTest::addColumn<Qt::LayoutDirection>("layoutDirection"); + + for (auto ld : {Qt::LeftToRight, Qt::RightToLeft}) { + const char *ldStr = ld == Qt::LeftToRight ? "LTR" : "RTL"; + QTest::addRow("North, %s", ldStr) << QTabWidget::North << ld; + QTest::addRow("South, %s", ldStr) << QTabWidget::South << ld; + QTest::addRow("West, %s", ldStr) << QTabWidget::West << ld; + QTest::addRow("East, %s", ldStr) << QTabWidget::East << ld; + } +} + +void tst_QTabBar::scrollButtons() +{ + QFETCH(QTabWidget::TabPosition, tabPosition); + QFETCH(Qt::LayoutDirection, layoutDirection); + + QWidget window; + QTabWidget tabWidget(&window); + tabWidget.setLayoutDirection(layoutDirection); + tabWidget.setTabPosition(tabPosition); + tabWidget.setElideMode(Qt::ElideNone); + tabWidget.setUsesScrollButtons(true); + + const int tabCount = 5; + for (int i = 0; i < tabCount; ++i) + { + const QString num = QString::number(i); + tabWidget.addTab(new QPushButton(num), num + " - Really long tab name to force arrows"); + } + tabWidget.move(0, 0); + tabWidget.resize(tabWidget.minimumSizeHint()); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + + auto *leftB = tabWidget.tabBar()->findChild<QAbstractButton*>(QStringLiteral("ScrollLeftButton")); + auto *rightB = tabWidget.tabBar()->findChild<QAbstractButton*>(QStringLiteral("ScrollRightButton")); + + QVERIFY(leftB->isVisible()); + QVERIFY(!leftB->isEnabled()); + QVERIFY(rightB->isVisible()); + QVERIFY(rightB->isEnabled()); + QVERIFY(!tabWidget.tabBar()->tabRect(1).intersects(tabWidget.tabBar()->rect())); + + int index = 0; + for (; index < tabWidget.count(); ++index) { + QCOMPARE(leftB->isEnabled(), index > 0); + QCOMPARE(rightB->isEnabled(), index < tabWidget.count() - 1); + QVERIFY(tabWidget.tabBar()->tabRect(index).intersects(tabWidget.tabBar()->rect())); + QCOMPARE(tabWidget.tabBar()->tabAt(tabWidget.tabBar()->rect().center()), index); + if (rightB->isEnabled()) + rightB->click(); + } + for (--index; index >= 0; --index) { + QCOMPARE(leftB->isEnabled(), index >= 0); + QCOMPARE(rightB->isEnabled(), index < tabWidget.count() - 1); + + QVERIFY(tabWidget.tabBar()->tabRect(index).intersects(tabWidget.tabBar()->rect())); + if (leftB->isEnabled()) + leftB->click(); + } + QVERIFY(!leftB->isEnabled()); +} + QTEST_MAIN(tst_QTabBar) #include "tst_qtabbar.moc" diff --git a/tests/benchmarks/corelib/io/qdiriterator/main.cpp b/tests/benchmarks/corelib/io/qdiriterator/main.cpp index eae752d99a..0bbe755f4e 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/main.cpp +++ b/tests/benchmarks/corelib/io/qdiriterator/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -57,24 +57,23 @@ private slots: void data(); }; - void tst_qdiriterator::data() { -#if defined(Q_OS_WIN) - const char *qtdir = "C:\\depot\\qt\\main"; -#else - const char *qtdir = ::getenv("QTDIR"); -#endif - if (!qtdir) { - fprintf(stderr, "QTDIR not set\n"); - exit(1); - } + const char hereRelative[] = "tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro"; + QString proname = QTest::qFindTestData(QStringLiteral("qdiriterator.pro")); + // qDebug("Source pro: %s", proname.toLocal8Bit().constData()); + // Size chopped counts the '\0', making up for the omitted leading '/': + QByteArray dir(QStringRef(&proname).chopped(sizeof(hereRelative)).toLocal8Bit()); + // qDebug("Root dir: %s", dir.constData()); QTest::addColumn<QByteArray>("dirpath"); - QByteArray ba = QByteArray(qtdir) + "/src/corelib"; - QByteArray ba1 = ba + "/io"; - QTest::newRow(ba) << ba; - //QTest::newRow(ba1) << ba1; + const QByteArray ba = dir + "/src/corelib"; + + if (!QFileInfo(QString::fromLocal8Bit(ba)).isDir()) + QSKIP("Missing Qt directory"); + + QTest::newRow("corelib") << ba; + QTest::newRow("corelib/io") << (ba + "/io"); } #ifdef Q_OS_WIN diff --git a/tests/benchmarks/corelib/io/qfile/main.cpp b/tests/benchmarks/corelib/io/qfile/main.cpp index 1966b30773..eca2f642b1 100644 --- a/tests/benchmarks/corelib/io/qfile/main.cpp +++ b/tests/benchmarks/corelib/io/qfile/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -108,72 +108,110 @@ private slots: void readBigFile_Win32(); private: - void readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); + void readFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); void readBigFile(); - void readSmallFiles_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); void readSmallFiles(); - void createFile(); - void fillFile(int factor=FACTOR); - void removeFile(); - void createSmallFiles(); - void removeSmallFiles(); - QString filename; - QString tmpDirName; + + class TestDataDir : public QTemporaryDir + { + void createFile(); + void createSmallFiles(); + public: + TestDataDir() : QTemporaryDir(), fail(errorString().toLocal8Bit()) + { + if (fail.isEmpty() && !QTemporaryDir::isValid()) + fail = "Failed to create temporary directory for data"; + if (isValid()) + createSmallFiles(); + if (isValid()) + createFile(); + if (isValid()) + QTest::qSleep(2000); // let IO settle + } + bool isValid() { return QTemporaryDir::isValid() && fail.isEmpty(); } + QByteArray fail; + QString filename; + } tempDir; }; Q_DECLARE_METATYPE(tst_qfile::BenchmarkType) Q_DECLARE_METATYPE(QIODevice::OpenMode) Q_DECLARE_METATYPE(QIODevice::OpenModeFlag) -void tst_qfile::createFile() +/* None of the tests modify the test data in tempDir, so it's OK to only create + * and tear down the directory once. + */ +void tst_qfile::TestDataDir::createFile() { - removeFile(); // Cleanup in case previous test case aborted before cleaning up - - QTemporaryFile tmpFile; - tmpFile.setAutoRemove(false); - if (!tmpFile.open()) - ::exit(1); + QFile tmpFile(filePath("testFile")); + if (!tmpFile.open(QIODevice::WriteOnly)) { + fail = "Unable to prepare files for test"; + return; + } +#if 0 // Varied data, rather than filling with '\0' bytes: + for (int row = 0; row < FACTOR; ++row) { + tmpFile.write(QByteArray().fill('0' + row % ('0' - 'z'), 80)); + tmpFile.write("\n"); + } +#else + tmpFile.seek(FACTOR * 80); + tmpFile.putChar('\n'); +#endif filename = tmpFile.fileName(); tmpFile.close(); } -void tst_qfile::removeFile() +void tst_qfile::TestDataDir::createSmallFiles() { - if (!filename.isEmpty()) - QFile::remove(filename); + for (int i = 0; i < 1000; ++i) { + QFile f(filePath(QString::number(i))); + if (!f.open(QIODevice::WriteOnly)) { + fail = "Unable to prepare small files for test"; + return; + } + f.seek(511); + f.putChar('\n'); + f.close(); + } } -void tst_qfile::fillFile(int factor) +void tst_qfile::initTestCase() { - QFile tmpFile(filename); - tmpFile.open(QIODevice::WriteOnly); - //for (int row=0; row<factor; ++row) { - // tmpFile.write(QByteArray().fill('0'+row%('0'-'z'), 80)); - // tmpFile.write("\n"); - //} - tmpFile.seek(factor*80); - tmpFile.putChar('\n'); - tmpFile.close(); - // let IO settle - QTest::qSleep(2000); + QVERIFY2(tempDir.isValid(), tempDir.fail.constData()); } -void tst_qfile::initTestCase() +void tst_qfile::cleanupTestCase() { } -void tst_qfile::cleanupTestCase() +void tst_qfile::readFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, + QIODevice::OpenModeFlag b) { + QTest::addColumn<tst_qfile::BenchmarkType>("testType"); + QTest::addColumn<int>("blockSize"); + QTest::addColumn<QFile::OpenModeFlag>("textMode"); + QTest::addColumn<QFile::OpenModeFlag>("bufferedMode"); + + QByteArray flagstring; + if (t & QIODevice::Text) + flagstring += "textMode "; + if (b & QIODevice::Unbuffered) + flagstring += "unbuffered "; + if (flagstring.isEmpty()) + flagstring = "none"; + + const int kbs[] = {1, 2, 8, 16, 32, 512}; + for (int kb : kbs) { + const int size = 1024 * kb; + QTest::addRow("BS: %d, Flags: %s", size, flagstring.constData()) + << type << size << t << b; + } } void tst_qfile::readBigFile_QFile() { readBigFile(); } void tst_qfile::readBigFile_QFSFileEngine() { -#ifdef QT_BUILD_INTERNAL readBigFile(); -#else - QSKIP("This test requires -developer-build."); -#endif } void tst_qfile::readBigFile_posix() { @@ -183,54 +221,36 @@ void tst_qfile::readBigFile_Win32() { readBigFile(); } void tst_qfile::readBigFile_QFile_data() { - readBigFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); - readBigFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readBigFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); - readBigFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); } void tst_qfile::readBigFile_QFSFileEngine_data() { #ifdef QT_BUILD_INTERNAL - readBigFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); - readBigFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readBigFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::NotOpen); - readBigFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); + // Support for buffering dropped at 5.10, so only test Unbuffered + readFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); #else - QTest::addColumn<int>("dummy"); - QTest::newRow("Test will be skipped") << -1; + QSKIP("This test requires -developer-build."); #endif } void tst_qfile::readBigFile_posix_data() { - readBigFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); } void tst_qfile::readBigFile_Win32_data() { - readBigFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); -} - - -void tst_qfile::readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b) -{ - QTest::addColumn<tst_qfile::BenchmarkType>("testType"); - QTest::addColumn<int>("blockSize"); - QTest::addColumn<QFile::OpenModeFlag>("textMode"); - QTest::addColumn<QFile::OpenModeFlag>("bufferedMode"); - - const int bs[] = {1024, 1024*2, 1024*8, 1024*16, 1024*32,1024*512}; - int bs_entries = sizeof(bs)/sizeof(const int); - - QString flagstring; - if (t & QIODevice::Text) flagstring += "textMode "; - if (b & QIODevice::Unbuffered) flagstring += "unbuffered "; - if (flagstring.isEmpty()) flagstring = "none"; - - for (int i=0; i<bs_entries; ++i) - QTest::newRow((QString("BS: %1, Flags: %2" )).arg(bs[i]).arg(flagstring).toLatin1().constData()) << type << bs[i] << t << b; +#ifdef Q_OS_WIN + readFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); +#else + QSKIP("This is Windows only benchmark."); +#endif } void tst_qfile::readBigFile() @@ -240,18 +260,10 @@ void tst_qfile::readBigFile() QFETCH(QFile::OpenModeFlag, textMode); QFETCH(QFile::OpenModeFlag, bufferedMode); -#ifndef Q_OS_WIN - if (testType == Win32Benchmark) - QSKIP("This is Windows only benchmark."); -#endif - - char *buffer = new char[BUFSIZE]; - createFile(); - fillFile(); - + char buffer[BUFSIZE]; switch (testType) { case(QFileBenchmark): { - QFile file(filename); + QFile file(tempDir.filename); file.open(QIODevice::ReadOnly|textMode|bufferedMode); QBENCHMARK { while(!file.atEnd()) @@ -263,7 +275,7 @@ void tst_qfile::readBigFile() break; #ifdef QT_BUILD_INTERNAL case(QFSFileEngineBenchmark): { - QFSFileEngine fse(filename); + QFSFileEngine fse(tempDir.filename); fse.open(QIODevice::ReadOnly|textMode|bufferedMode); QBENCHMARK { //qWarning() << fse.supportsExtension(QAbstractFileEngine::AtEndExtension); @@ -275,7 +287,7 @@ void tst_qfile::readBigFile() break; #endif case(PosixBenchmark): { - QByteArray data = filename.toLocal8Bit(); + QByteArray data = tempDir.filename.toLocal8Bit(); const char* cfilename = data.constData(); FILE* cfile = ::fopen(cfilename, "rb"); QBENCHMARK { @@ -295,7 +307,7 @@ void tst_qfile::readBigFile() HANDLE hndl; // ensure we don't account string conversion - wchar_t* cfilename = (wchar_t*)filename.utf16(); + const wchar_t *cfilename = reinterpret_cast<const wchar_t *>(tempDir.filename.utf16()); #ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); @@ -325,9 +337,6 @@ void tst_qfile::readBigFile() } break; } - - removeFile(); - delete[] buffer; } void tst_qfile::seek_data() @@ -348,12 +357,9 @@ void tst_qfile::seek() QFETCH(tst_qfile::BenchmarkType, testType); int i = 0; - createFile(); - fillFile(); - switch (testType) { case(QFileBenchmark): { - QFile file(filename); + QFile file(tempDir.filename); file.open(QIODevice::ReadOnly); QBENCHMARK { i=(i+1)%sp_size; @@ -364,8 +370,8 @@ void tst_qfile::seek() break; #ifdef QT_BUILD_INTERNAL case(QFSFileEngineBenchmark): { - QFSFileEngine fse(filename); - fse.open(QIODevice::ReadOnly); + QFSFileEngine fse(tempDir.filename); + fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); QBENCHMARK { i=(i+1)%sp_size; fse.seek(seekpos[i]); @@ -375,7 +381,7 @@ void tst_qfile::seek() break; #endif case(PosixBenchmark): { - QByteArray data = filename.toLocal8Bit(); + QByteArray data = tempDir.filename.toLocal8Bit(); const char* cfilename = data.constData(); FILE* cfile = ::fopen(cfilename, "rb"); QBENCHMARK { @@ -394,7 +400,7 @@ void tst_qfile::seek() HANDLE hndl; // ensure we don't account string conversion - wchar_t* cfilename = (wchar_t*)filename.utf16(); + const wchar_t *cfilename = reinterpret_cast<const wchar_t *>(tempDir.filename.utf16()); #ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); @@ -413,13 +419,11 @@ void tst_qfile::seek() } CloseHandle(hndl); #else - QFAIL("Not running on a Windows plattform!"); + QFAIL("Not running on a Windows platform!"); #endif } break; } - - removeFile(); } void tst_qfile::open_data() @@ -440,13 +444,11 @@ void tst_qfile::open() { QFETCH(tst_qfile::BenchmarkType, testType); - createFile(); - switch (testType) { case(QFileBenchmark): { QBENCHMARK { - QFile file( filename ); - file.open( QIODevice::ReadOnly ); + QFile file(tempDir.filename); + file.open(QIODevice::ReadOnly); file.close(); } } @@ -454,8 +456,8 @@ void tst_qfile::open() #ifdef QT_BUILD_INTERNAL case(QFSFileEngineBenchmark): { QBENCHMARK { - QFSFileEngine fse(filename); - fse.open(QIODevice::ReadOnly); + QFSFileEngine fse(tempDir.filename); + fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); fse.close(); } } @@ -463,7 +465,7 @@ void tst_qfile::open() #endif case(PosixBenchmark): { // ensure we don't account toLocal8Bit() - QByteArray data = filename.toLocal8Bit(); + QByteArray data = tempDir.filename.toLocal8Bit(); const char* cfilename = data.constData(); QBENCHMARK { @@ -474,7 +476,7 @@ void tst_qfile::open() break; case(QFileFromPosixBenchmark): { // ensure we don't account toLocal8Bit() - QByteArray data = filename.toLocal8Bit(); + QByteArray data = tempDir.filename.toLocal8Bit(); const char* cfilename = data.constData(); FILE* cfile = ::fopen(cfilename, "rb"); @@ -491,7 +493,7 @@ void tst_qfile::open() HANDLE hndl; // ensure we don't account string conversion - wchar_t* cfilename = (wchar_t*)filename.utf16(); + const wchar_t *cfilename = reinterpret_cast<const wchar_t *>(tempDir.filename.utf16()); QBENCHMARK { #ifndef Q_OS_WINRT @@ -508,19 +510,13 @@ void tst_qfile::open() } break; } - - removeFile(); } void tst_qfile::readSmallFiles_QFile() { readSmallFiles(); } void tst_qfile::readSmallFiles_QFSFileEngine() { -#ifdef QT_BUILD_INTERNAL readSmallFiles(); -#else - QSKIP("This test requires -developer-build."); -#endif } void tst_qfile::readSmallFiles_posix() { @@ -533,82 +529,39 @@ void tst_qfile::readSmallFiles_Win32() void tst_qfile::readSmallFiles_QFile_data() { - readSmallFiles_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); - readSmallFiles_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readSmallFiles_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); - readSmallFiles_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); } void tst_qfile::readSmallFiles_QFSFileEngine_data() { #ifdef QT_BUILD_INTERNAL - readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); - readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::NotOpen); - readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); + // Support for buffering dropped at 5.10, so only test Unbuffered + readFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); #else - QTest::addColumn<int>("dummy"); - QTest::newRow("Test will be skipped") << -1; + QSKIP("This test requires -developer-build."); #endif } void tst_qfile::readSmallFiles_posix_data() { - readSmallFiles_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); } void tst_qfile::readSmallFiles_Win32_data() { - readSmallFiles_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); -} - - -void tst_qfile::readSmallFiles_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b) -{ - QTest::addColumn<tst_qfile::BenchmarkType>("testType"); - QTest::addColumn<int>("blockSize"); - QTest::addColumn<QFile::OpenModeFlag>("textMode"); - QTest::addColumn<QFile::OpenModeFlag>("bufferedMode"); - - const int bs[] = {1024, 1024*2, 1024*8, 1024*16, 1024*32,1024*512}; - int bs_entries = sizeof(bs)/sizeof(const int); - - QString flagstring; - if (t & QIODevice::Text) flagstring += "textMode "; - if (b & QIODevice::Unbuffered) flagstring += "unbuffered "; - if (flagstring.isEmpty()) flagstring = "none"; - - for (int i=0; i<bs_entries; ++i) - QTest::newRow((QString("BS: %1, Flags: %2" )).arg(bs[i]).arg(flagstring).toLatin1().constData()) << type << bs[i] << t << b; - -} - -void tst_qfile::createSmallFiles() -{ - QDir dir = QDir::temp(); - dir.mkdir("tst"); - dir.cd("tst"); - tmpDirName = dir.absolutePath(); - - for (int i = 0; i < 1000; ++i) { - QFile f(tmpDirName + QLatin1Char('/') + QString::number(i)); - f.open(QIODevice::WriteOnly); - f.seek(511); - f.putChar('\n'); - f.close(); - } -} -void tst_qfile::removeSmallFiles() -{ - QDirIterator it(tmpDirName, QDirIterator::FollowSymlinks); - while (it.hasNext()) - QFile::remove(it.next()); - QDir::temp().rmdir("tst"); +#ifdef Q_OS_WIN + readFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); +#else + QSKIP("This is Windows only benchmark."); +#endif } - void tst_qfile::readSmallFiles() { QFETCH(tst_qfile::BenchmarkType, testType); @@ -616,22 +569,15 @@ void tst_qfile::readSmallFiles() QFETCH(QFile::OpenModeFlag, textMode); QFETCH(QFile::OpenModeFlag, bufferedMode); -#ifndef Q_OS_WIN - if (testType == Win32Benchmark) - QSKIP("This is Windows only benchmark."); -#endif - - createSmallFiles(); - - QDir dir(tmpDirName); + QDir dir(tempDir.path()); const QStringList files = dir.entryList(QDir::NoDotAndDotDot|QDir::NoSymLinks|QDir::Files); - char *buffer = new char[BUFSIZE]; + char buffer[BUFSIZE]; switch (testType) { case(QFileBenchmark): { QList<QFile*> fileList; Q_FOREACH(QString file, files) { - QFile *f = new QFile(tmpDirName + QLatin1Char('/') + file); + QFile *f = new QFile(tempDir.filePath(file)); f->open(QIODevice::ReadOnly|textMode|bufferedMode); fileList.append(f); } @@ -654,7 +600,7 @@ void tst_qfile::readSmallFiles() case(QFSFileEngineBenchmark): { QList<QFSFileEngine*> fileList; Q_FOREACH(QString file, files) { - QFSFileEngine *fse = new QFSFileEngine(tmpDirName + QLatin1Char('/') + file); + QFSFileEngine *fse = new QFSFileEngine(tempDir.filePath(file)); fse->open(QIODevice::ReadOnly|textMode|bufferedMode); fileList.append(fse); } @@ -675,7 +621,7 @@ void tst_qfile::readSmallFiles() case(PosixBenchmark): { QList<FILE*> fileList; Q_FOREACH(QString file, files) { - fileList.append(::fopen(QFile::encodeName(tmpDirName + QLatin1Char('/') + file).constData(), "rb")); + fileList.append(::fopen(QFile::encodeName(tempDir.filePath(file)).constData(), "rb")); } QBENCHMARK { @@ -700,7 +646,7 @@ void tst_qfile::readSmallFiles() HANDLE hndl; // ensure we don't account string conversion - wchar_t* cfilename = (wchar_t*)filename.utf16(); + const wchar_t *cfilename = reinterpret_cast<const wchar_t *>(tempDir.filename.utf16()); #ifndef Q_OS_WINRT hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); @@ -723,9 +669,6 @@ void tst_qfile::readSmallFiles() } break; } - - removeSmallFiles(); - delete[] buffer; } QTEST_MAIN(tst_qfile) diff --git a/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro b/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro index 1f56ad6ee6..89fea90d90 100644 --- a/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro +++ b/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro @@ -1,4 +1,3 @@ -CONFIG += benchmark CONFIG -= qt CONFIG += cmdline winrt: QMAKE_LFLAGS += /ENTRY:mainCRTStartup diff --git a/tests/benchmarks/corelib/io/qprocess/tst_bench_qprocess.cpp b/tests/benchmarks/corelib/io/qprocess/tst_bench_qprocess.cpp index 1fd3b9d5da..6cf7529d55 100644 --- a/tests/benchmarks/corelib/io/qprocess/tst_bench_qprocess.cpp +++ b/tests/benchmarks/corelib/io/qprocess/tst_bench_qprocess.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -39,10 +39,16 @@ private slots: void echoTest_performance(); }; +#ifdef Q_OS_WIN +# define EXE ".exe" +#else +# define EXE "" +#endif + void tst_QProcess::echoTest_performance() { QProcess process; - process.start("testProcessLoopback/testProcessLoopback"); + process.start(QFINDTESTDATA("testProcessLoopback/testProcessLoopback" EXE), QStringList()); QByteArray array; array.resize(1024 * 1024); diff --git a/tests/benchmarks/dbus/qdbusperformance/test/test.pro b/tests/benchmarks/dbus/qdbusperformance/test/test.pro index ddc5410759..faa2fe81ba 100644 --- a/tests/benchmarks/dbus/qdbusperformance/test/test.pro +++ b/tests/benchmarks/dbus/qdbusperformance/test/test.pro @@ -1,3 +1,4 @@ +CONFIG += benchmark SOURCES += ../tst_qdbusperformance.cpp HEADERS += ../serverobject.h TARGET = ../tst_qdbusperformance diff --git a/tests/benchmarks/dbus/qdbusperformance/tst_qdbusperformance.cpp b/tests/benchmarks/dbus/qdbusperformance/tst_qdbusperformance.cpp index 39c9129456..4bb71c4775 100644 --- a/tests/benchmarks/dbus/qdbusperformance/tst_qdbusperformance.cpp +++ b/tests/benchmarks/dbus/qdbusperformance/tst_qdbusperformance.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -79,7 +79,7 @@ void tst_QDBusPerformance::initTestCase() #else # define EXE "" #endif - proc.start(QFINDTESTDATA("server/server" EXE)); + proc.start(QFINDTESTDATA("server/server" EXE), QStringList()); QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString())); QVERIFY(proc.waitForReadyRead()); diff --git a/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp b/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp index 8d7e70f8c9..6a5d353324 100644 --- a/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp +++ b/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** - ** Copyright (C) 2018 The Qt Company Ltd. + ** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -178,15 +178,18 @@ void tst_QSqlRecord::benchmarkRecord() const auto tableName = qTableName("record", __FILE__, db); { QSqlQuery qry(db); - QVERIFY_SQL(qry, exec("create table " + tableName + " (id int NOT NULL, t_varchar varchar(20), " + QVERIFY_SQL(qry, exec("create table " + tableName + + " (id int NOT NULL, t_varchar varchar(20), " "t_char char(20), primary key(id))")); - for (int i = 0; i < 1000; i++) + // Limit to 500: at 600, the set-up takes nearly 5 minutes + for (int i = 0; i < 500; i++) QVERIFY_SQL(qry, exec(QString("INSERT INTO " + tableName + " VALUES (%1, 'VarChar%1', 'Char%1')").arg(i))); QVERIFY_SQL(qry, exec(QString("SELECT * from ") + tableName)); QBENCHMARK { while (qry.next()) qry.record(); + QVERIFY(qry.seek(0)); } } tst_Databases::safeDropTables(db, QStringList() << tableName); @@ -202,6 +205,7 @@ void tst_QSqlRecord::benchFieldName() QBENCHMARK { while (qry.next()) qry.value("r"); + QVERIFY(qry.seek(0)); } } } @@ -217,6 +221,7 @@ void tst_QSqlRecord::benchFieldIndex() QBENCHMARK { while (qry.next()) qry.value(0); + QVERIFY(qry.seek(0)); } } } |