diff options
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r-- | tests/auto/corelib/io/qsettings/tst_qsettings.cpp | 4 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp | 65 | ||||
-rw-r--r-- | tests/auto/corelib/text/qchar/tst_qchar.cpp | 19 | ||||
-rw-r--r-- | tests/auto/corelib/text/qlocale/tst_qlocale.cpp | 30 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/tst_qstring.cpp | 32 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qfuture/tst_qfuture.cpp | 79 | ||||
-rw-r--r-- | tests/auto/corelib/thread/qresultstore/tst_qresultstore.cpp | 16 |
7 files changed, 220 insertions, 25 deletions
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() |