diff options
author | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2016-08-22 11:30:00 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2016-08-22 11:30:01 +0200 |
commit | d314819fc02139e05e16c56657898c704f7fb48f (patch) | |
tree | a61ba968233634948401c8339f9613844de1c2b5 /tests/auto/corelib | |
parent | 9f888d2fde9c5413e5519e0914e9b13638760985 (diff) | |
parent | e0e9e196a72ffe5457034894eaaadc90ed0d34ef (diff) |
Merge dev into 5.8
Change-Id: I41ee7b50534b01cf042bed8bb8824ba2e5026a29
Diffstat (limited to 'tests/auto/corelib')
33 files changed, 938 insertions, 72 deletions
diff --git a/tests/auto/corelib/global/qflags/qflags.pro b/tests/auto/corelib/global/qflags/qflags.pro index 29dfb0684c..c3c11fa81b 100644 --- a/tests/auto/corelib/global/qflags/qflags.pro +++ b/tests/auto/corelib/global/qflags/qflags.pro @@ -2,5 +2,5 @@ CONFIG += testcase TARGET = tst_qflags QT = core testlib SOURCES = tst_qflags.cpp -contains(QT_CONFIG, c++11): CONFIG += c++11 -contains(QT_CONFIG, c++14): CONFIG += c++14 +qtConfig(c++11): CONFIG += c++11 +qtConfig(c++14): CONFIG += c++14 diff --git a/tests/auto/corelib/global/qlogging/test/test.pro b/tests/auto/corelib/global/qlogging/test/test.pro index b5b75be3a6..93eee7307a 100644 --- a/tests/auto/corelib/global/qlogging/test/test.pro +++ b/tests/auto/corelib/global/qlogging/test/test.pro @@ -1,7 +1,7 @@ CONFIG += testcase CONFIG -= app_bundle debug_and_release_target -contains(QT_CONFIG, c++11): CONFIG += c++11 -contains(QT_CONFIG, c++14): CONFIG += c++14 +qtConfig(c++11): CONFIG += c++11 +qtConfig(c++14): CONFIG += c++14 TARGET = ../tst_qlogging QT = core testlib SOURCES = ../tst_qlogging.cpp diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro index 24c762ed84..0542833456 100644 --- a/tests/auto/corelib/io/io.pro +++ b/tests/auto/corelib/io/io.pro @@ -49,14 +49,14 @@ SUBDIRS=\ qprocess \ qtextstream -!contains(QT_CONFIG, private_tests): SUBDIRS -= \ +!qtConfig(private_tests): SUBDIRS -= \ qabstractfileengine \ qfileinfo \ qipaddress \ qurlinternal \ qloggingregistry -win32:!contains(QT_CONFIG, private_tests): SUBDIRS -= \ +win32:!qtConfig(private_tests): SUBDIRS -= \ qfilesystementry winrt: SUBDIRS -= \ diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 4c9986d50e..021d581aac 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -155,10 +155,12 @@ private slots: void copyRemovesTemporaryFile() const; void copyShouldntOverwrite(); void copyFallback(); +#ifndef Q_OS_WINRT void link(); void linkToDir(); void absolutePathLinkToRelativePath(); void readBrokenLink(); +#endif void readTextFile_data(); void readTextFile(); void readTextFile2(); @@ -568,7 +570,7 @@ void tst_QFile::open() QSKIP("Running this test as root doesn't make sense"); #endif -#if defined(Q_OS_WIN32) +#if defined(Q_OS_WIN32) || defined(Q_OS_WINRT) QEXPECT_FAIL("noreadfile", "Windows does not currently support non-readable files.", Abort); #endif if (filename.isEmpty()) @@ -1226,7 +1228,7 @@ void tst_QFile::permissions() QFile::remove(file); } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) if (qt_ntfs_permission_lookup) QEXPECT_FAIL("readonly", "QTBUG-25630", Abort); #endif @@ -1413,6 +1415,7 @@ static QString getWorkingDirectoryForLink(const QString &linkFileName) } #endif +#ifndef Q_OS_WINRT void tst_QFile::link() { QFile::remove("myLink.lnk"); @@ -1433,7 +1436,7 @@ void tst_QFile::link() QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath()); QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath())); #endif @@ -1487,6 +1490,7 @@ void tst_QFile::readBrokenLink() QVERIFY(QFile::link("ole/..", "myLink2.lnk")); QCOMPARE(QFileInfo("myLink2.lnk").symLinkTarget(), QDir::currentPath()); } +#endif // Q_OS_WINRT void tst_QFile::readTextFile_data() { @@ -2505,7 +2509,7 @@ void tst_QFile::rename() \since 4.5 Some special files have QFile::atEnd() returning true, even though there is - more data available. True for corner cases, as well as some mounts on OS X. + more data available. True for corner cases, as well as some mounts on \macos. Here, we reproduce that condition by having a QFile sub-class with this peculiar atEnd() behavior. diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 0bc1e77925..3f3533c9a1 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -734,6 +734,7 @@ void tst_QProcess::restartProcess() void tst_QProcess::closeWriteChannel() { + QByteArray testData("Data to read"); QProcess more; more.start("testProcessEOF/testProcessEOF"); @@ -741,19 +742,21 @@ void tst_QProcess::closeWriteChannel() QVERIFY(!more.waitForReadyRead(250)); QCOMPARE(more.error(), QProcess::Timedout); - QVERIFY(more.write("Data to read") != -1); + QCOMPARE(more.write(testData), qint64(testData.size())); QVERIFY(!more.waitForReadyRead(250)); QCOMPARE(more.error(), QProcess::Timedout); more.closeWriteChannel(); - - QVERIFY(more.waitForReadyRead(5000)); - QVERIFY(more.readAll().startsWith("Data to read")); + // During closeWriteChannel() call, we might also get an I/O completion + // on the read pipe. So, take this into account before waiting for + // the new incoming data. + while (more.bytesAvailable() < testData.size()) + QVERIFY(more.waitForReadyRead(5000)); + QCOMPARE(more.readAll(), testData); if (more.state() == QProcess::Running) - more.write("q"); - QVERIFY(more.waitForFinished(5000)); + QVERIFY(more.waitForFinished(5000)); QCOMPARE(more.exitStatus(), QProcess::NormalExit); QCOMPARE(more.exitCode(), 0); } diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index e982660bef..f589fe1d6d 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -898,13 +898,11 @@ void tst_QUrl::resolving_data() // Some parsers allow the scheme name to be present in a relative URI // reference if it is the same as the base URI scheme. This is - // considered to be a loophole in prior specifications of partial URI - // [RFC1630]. Its use should be avoided, but is allowed for backward - // compatibility. - // For strict parsers : -// QTest::newRow("http:g [for strict parsers]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http:g"); - // For backward compatibility : - QTest::newRow("http:g [for backward compatibility]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http://a/b/c/g"); + // considered to be a loophole in prior specifications of partial URI [RFC1630], + //QTest::newRow("http:g [for backward compatibility]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http://a/b/c/g"); + // However we don't do that anymore, as per RFC3986, in order for the data:subpage testcase below to work. + QTest::newRow("http:g") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http:g"); + QTest::newRow("data:subpage") << QString::fromLatin1("data:text/plain, main page") << QString::fromLatin1("data:text/plain, subpage") << QString::fromLatin1("data:text/plain, subpage"); // Resolve relative with relative QTest::newRow("../a (1)") << QString::fromLatin1("b") << QString::fromLatin1("../a") << QString::fromLatin1("a"); @@ -916,6 +914,10 @@ void tst_QUrl::resolving_data() QTest::newRow("../a (6)") << QString::fromLatin1("/b/a") << QString::fromLatin1("../a") << QString::fromLatin1("/a"); QTest::newRow("../a (7)") << QString::fromLatin1("/b/c/a") << QString::fromLatin1("../a") << QString::fromLatin1("/b/a"); QTest::newRow("../a (8)") << QString::fromLatin1("/b") << QString::fromLatin1("/a") << QString::fromLatin1("/a"); + + // More tests from KDE + QTest::newRow("brackets") << QString::fromLatin1("http://www.calorieking.com/personal/diary/") << QString::fromLatin1("/personal/diary/rpc.php?C=jsrs1&F=getDiaryDay&P0=[2006-3-8]&U=1141858921458") << QString::fromLatin1("http://www.calorieking.com/personal/diary/rpc.php?C=jsrs1&F=getDiaryDay&P0=[2006-3-8]&U=1141858921458"); + QTest::newRow("javascript")<< QString::fromLatin1("http://www.youtube.com/?v=JvOSnRD5aNk") << QString::fromLatin1("javascript:window.location+\"__flashplugin_unique__\"") << QString::fromLatin1("javascript:window.location+%22__flashplugin_unique__%22"); } void tst_QUrl::resolving() diff --git a/tests/auto/corelib/io/qurlinternal/qurlinternal.pro b/tests/auto/corelib/io/qurlinternal/qurlinternal.pro index ae5e023446..3828512dce 100644 --- a/tests/auto/corelib/io/qurlinternal/qurlinternal.pro +++ b/tests/auto/corelib/io/qurlinternal/qurlinternal.pro @@ -1,5 +1,5 @@ CONFIG += testcase -requires(contains(QT_CONFIG,private_tests)) +requires(qtConfig(private_tests)) TARGET = tst_qurlinternal SOURCES += tst_qurlinternal.cpp ../../codecs/utf8/utf8data.cpp QT = core core-private testlib diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 8e2d583961..38e3c6890d 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -143,6 +143,7 @@ private slots: void noMapAfterSourceDelete(); void forwardDropApi(); void canDropMimeData(); + void filterHint(); protected: void buildHierarchy(const QStringList &data, QAbstractItemModel *model); @@ -2128,17 +2129,23 @@ void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440() QModelIndex index; + // QStringListModel doesn't distinguish between edit and display roles, + // so changing one always changes the other, too. + QVector<int> expectedChangedRoles; + expectedChangedRoles.append(Qt::DisplayRole); + expectedChangedRoles.append(Qt::EditRole); + index = model.index(0, 0); QVERIFY(index.isValid()); model.setData(index, QStringLiteral("teststring"), Qt::DisplayRole); QCOMPARE(spy.length(), 1); - QCOMPARE(spy.at(0).at(2).value<QVector<int> >(), QVector<int>() << Qt::DisplayRole); + QCOMPARE(spy.at(0).at(2).value<QVector<int> >(), expectedChangedRoles); index = model.index(1, 0); QVERIFY(index.isValid()); model.setData(index, QStringLiteral("teststring2"), Qt::EditRole); QCOMPARE(spy.length(), 2); - QCOMPARE(spy.at(1).at(2).value<QVector<int> >(), QVector<int>() << Qt::EditRole); + QCOMPARE(spy.at(1).at(2).value<QVector<int> >(), expectedChangedRoles); } void tst_QSortFilterProxyModel::sortFilterRole() @@ -3802,6 +3809,12 @@ void tst_QSortFilterProxyModel::moveSourceRows() QCOMPARE(filterBeforeParents.size(), 1); QCOMPARE(filterAfterParents.size(), 1); + QCOMPARE( + filterBeforeParentLayoutSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(filterAfterParentLayoutSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0); QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0); } @@ -4123,5 +4136,50 @@ void tst_QSortFilterProxyModel::resortingDoesNotBreakTreeModels() QCOMPARE(proxy.rowCount(pi1), 1); } +void tst_QSortFilterProxyModel::filterHint() +{ + // test that a filtering model does not emit layoutChanged with a hint + QStringListModel model(QStringList() << "one" + << "two" + << "three" + << "four" + << "five" + << "six"); + QSortFilterProxyModel proxy1; + proxy1.setSourceModel(&model); + proxy1.setSortRole(Qt::DisplayRole); + proxy1.setDynamicSortFilter(true); + proxy1.sort(0); + + QSortFilterProxyModel proxy2; + proxy2.setSourceModel(&proxy1); + proxy2.setFilterRole(Qt::DisplayRole); + proxy2.setFilterRegExp("^[^ ]*$"); + proxy2.setDynamicSortFilter(true); + + QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy1AfterSpy(&proxy1, &QSortFilterProxyModel::layoutChanged); + QSignalSpy proxy2BeforeSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy2AfterSpy(&proxy2, &QSortFilterProxyModel::layoutChanged); + + model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole); + + // The first proxy was re-sorted as one item as changed. + QCOMPARE(proxy1BeforeSpy.size(), 1); + QCOMPARE(proxy1BeforeSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(), + QAbstractItemModel::VerticalSortHint); + QCOMPARE(proxy1AfterSpy.size(), 1); + QCOMPARE(proxy1AfterSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(), + QAbstractItemModel::VerticalSortHint); + + // But the second proxy must not have the VerticalSortHint since an item was filtered + QCOMPARE(proxy2BeforeSpy.size(), 1); + QCOMPARE(proxy2BeforeSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(proxy2AfterSpy.size(), 1); + QCOMPARE(proxy2AfterSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(), + QAbstractItemModel::NoLayoutChangeHint); +} + QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp index 61dda782d8..f99241da3b 100644 --- a/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp +++ b/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp @@ -35,6 +35,8 @@ #include "qmodellistener.h" #include <qstringlistmodel.h> +#include <algorithm> + void QModelListener::rowsAboutToBeRemovedOrInserted(const QModelIndex & parent, int start, int end ) { for (int i = 0; start + i <= end; i++) { @@ -75,6 +77,9 @@ private slots: void rowsAboutToBeInserted_rowsInserted(); void rowsAboutToBeInserted_rowsInserted_data(); + + void setData_emits_both_roles_data(); + void setData_emits_both_roles(); }; void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved_data() @@ -129,22 +134,19 @@ void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved() QFETCH(QStringList, aboutto); QFETCH(QStringList, res); - QStringListModel *model = new QStringListModel(input); - QModelListener *pListener = new QModelListener(&aboutto, &res, model); - pListener->connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - pListener, SLOT(rowsAboutToBeRemovedOrInserted(QModelIndex,int,int)) ); + QStringListModel model(input); + QModelListener listener(&aboutto, &res, &model); + connect(&model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + &listener, SLOT(rowsAboutToBeRemovedOrInserted(QModelIndex,int,int))); - pListener->connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - pListener, SLOT(rowsRemovedOrInserted(QModelIndex,int,int)) ); + connect(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + &listener, SLOT(rowsRemovedOrInserted(QModelIndex,int,int))); - model->removeRows(row,count); + model.removeRows(row, count); // At this point, control goes to our connected slots inn this order: // 1. rowsAboutToBeRemovedOrInserted // 2. rowsRemovedOrInserted // Control returns here - - delete pListener; - delete model; } void tst_QStringListModel::rowsAboutToBeInserted_rowsInserted_data() @@ -193,22 +195,59 @@ void tst_QStringListModel::rowsAboutToBeInserted_rowsInserted() QFETCH(QStringList, aboutto); QFETCH(QStringList, res); - QStringListModel *model = new QStringListModel(input); - QModelListener *pListener = new QModelListener(&aboutto, &res, model); - connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - pListener, SLOT(rowsAboutToBeRemovedOrInserted(QModelIndex,int,int)) ); + QStringListModel model(input); + QModelListener listener(&aboutto, &res, &model); + connect(&model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + &listener, SLOT(rowsAboutToBeRemovedOrInserted(QModelIndex,int,int))); - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - pListener, SLOT(rowsRemovedOrInserted(QModelIndex,int,int)) ); + connect(&model, SIGNAL(rowsInserted(QModelIndex,int,int)), + &listener, SLOT(rowsRemovedOrInserted(QModelIndex,int,int))); - model->insertRows(row,count); + model.insertRows(row, count); // At this point, control goes to our connected slots inn this order: // 1. rowsAboutToBeRemovedOrInserted // 2. rowsRemovedOrInserted // Control returns here +} - delete pListener; - delete model; +void tst_QStringListModel::setData_emits_both_roles_data() +{ + QTest::addColumn<int>("row"); + QTest::addColumn<QString>("data"); + QTest::addColumn<int>("role"); + +#define ROW(row, string, role) \ + QTest::newRow(#row " -> " string) << row << QString(string) << int(Qt::role) + ROW(0, "1", EditRole); + ROW(1, "2", DisplayRole); +#undef ROW +} + +template <class C> +C sorted(C c) +{ + std::sort(c.begin(), c.end()); + return qMove(c); +} + +void tst_QStringListModel::setData_emits_both_roles() +{ + QFETCH(int, row); + QFETCH(QString, data); + QFETCH(int, role); + + QStringListModel model(QStringList() << "one" << "two"); + QVector<int> expected; + expected.reserve(2); + expected.append(Qt::DisplayRole); + expected.append(Qt::EditRole); + + QSignalSpy spy(&model, &QAbstractItemModel::dataChanged); + QVERIFY(spy.isValid()); + model.setData(model.index(row, 0), data, role); + QCOMPARE(spy.size(), 1); + QCOMPARE(sorted(spy.at(0).at(2).value<QVector<int> >()), + expected); } QTEST_MAIN(tst_QStringListModel) diff --git a/tests/auto/corelib/json/json.pro b/tests/auto/corelib/json/json.pro index b3038d7ca1..dc9cd3e383 100644 --- a/tests/auto/corelib/json/json.pro +++ b/tests/auto/corelib/json/json.pro @@ -6,7 +6,7 @@ CONFIG += testcase !android:TESTDATA += bom.json test.json test.bjson test3.json test2.json else:RESOURCES += json.qrc -!contains(QT_CONFIG, doubleconversion):!contains(QT_CONFIG, system-doubleconversion) { +!qtConfig(doubleconversion):!qtConfig(system-doubleconversion) { DEFINES += QT_NO_DOUBLECONVERSION } diff --git a/tests/auto/corelib/kernel/kernel.pro b/tests/auto/corelib/kernel/kernel.pro index 431d483339..75b98bcd09 100644 --- a/tests/auto/corelib/kernel/kernel.pro +++ b/tests/auto/corelib/kernel/kernel.pro @@ -1,6 +1,7 @@ TEMPLATE=subdirs SUBDIRS=\ qcoreapplication \ + qdeadlinetimer \ qelapsedtimer \ qeventdispatcher \ qeventloop \ @@ -32,11 +33,11 @@ SUBDIRS=\ qobject \ qsocketnotifier -!contains(QT_CONFIG, private_tests): SUBDIRS -= \ +!qtConfig(private_tests): SUBDIRS -= \ qsocketnotifier \ qsharedmemory # This test is only applicable on Windows !win32*|winrt: SUBDIRS -= qwineventnotifier -android|uikit: SUBDIRS -= qsharedmemory qsystemsemaphore +android|uikit: SUBDIRS -= qclipboard qobject qsharedmemory qsystemsemaphore diff --git a/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro b/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro index a49bb9ae1f..d166351490 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro +++ b/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro @@ -3,4 +3,4 @@ TARGET = tst_qcoreapplication QT = core testlib core-private SOURCES = tst_qcoreapplication.cpp HEADERS = tst_qcoreapplication.h -requires(contains(QT_CONFIG,private_tests)) +requires(qtConfig(private_tests)) diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/qdeadlinetimer.pro b/tests/auto/corelib/kernel/qdeadlinetimer/qdeadlinetimer.pro new file mode 100644 index 0000000000..12ad7dabc2 --- /dev/null +++ b/tests/auto/corelib/kernel/qdeadlinetimer/qdeadlinetimer.pro @@ -0,0 +1,5 @@ +CONFIG += testcase +TARGET = tst_qdeadlinetimer +QT = core testlib +SOURCES = tst_qdeadlinetimer.cpp + diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp new file mode 100644 index 0000000000..7642604cfe --- /dev/null +++ b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp @@ -0,0 +1,625 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QString> +#include <QtCore/QTime> +#include <QtCore/QDeadlineTimer> +#include <QtTest/QtTest> + +#if QT_HAS_INCLUDE(<chrono>) +# include <chrono> +#endif + +static const int minResolution = 100; // the minimum resolution for the tests + +Q_DECLARE_METATYPE(Qt::TimerType) + +class tst_QDeadlineTimer : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase_data(); + void basics(); + void foreverness(); + void current(); + void deadlines(); + void setDeadline(); + void expire(); + void stdchrono(); +}; + +void tst_QDeadlineTimer::initTestCase_data() +{ + qRegisterMetaType<Qt::TimerType>(); + QTest::addColumn<Qt::TimerType>("timerType"); + QTest::newRow("precise") << Qt::PreciseTimer; + QTest::newRow("coarse") << Qt::CoarseTimer; +} + +void tst_QDeadlineTimer::basics() +{ + QDeadlineTimer deadline; + QCOMPARE(deadline.timerType(), Qt::CoarseTimer); + + QFETCH_GLOBAL(Qt::TimerType, timerType); + deadline = QDeadlineTimer(timerType); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline, QDeadlineTimer(timerType)); + QVERIFY(!(deadline != QDeadlineTimer(timerType))); + QVERIFY(!(deadline < QDeadlineTimer())); + QVERIFY(deadline <= QDeadlineTimer()); + QVERIFY(deadline >= QDeadlineTimer()); + QVERIFY(!(deadline > QDeadlineTimer())); + QVERIFY(!(deadline < deadline)); + QVERIFY(deadline <= deadline); + QVERIFY(deadline >= deadline); + QVERIFY(!(deadline > deadline)); + + // should have expired, but we may be running too early after boot + QTRY_VERIFY_WITH_TIMEOUT(deadline.hasExpired(), 100); + + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QCOMPARE(deadline.deadline(), qint64(0)); + QCOMPARE(deadline.deadlineNSecs(), qint64(0)); + + deadline.setRemainingTime(0, timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + deadline.setPreciseRemainingTime(0, 0, timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + deadline.setDeadline(0, timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QCOMPARE(deadline.deadline(), qint64(0)); + QCOMPARE(deadline.deadlineNSecs(), qint64(0)); + + deadline.setPreciseDeadline(0, 0, timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QCOMPARE(deadline.deadline(), qint64(0)); + QCOMPARE(deadline.deadlineNSecs(), qint64(0)); +} + +void tst_QDeadlineTimer::foreverness() +{ + QFETCH_GLOBAL(Qt::TimerType, timerType); + // we don't check whether timerType() is our type since it's possible it detects it's forever + + QDeadlineTimer deadline = QDeadlineTimer::Forever; + QCOMPARE(deadline.timerType(), Qt::CoarseTimer); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + deadline = QDeadlineTimer(-1, timerType); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + deadline.setRemainingTime(-1, timerType); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + deadline.setPreciseRemainingTime(-1, 0, timerType); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + deadline.setPreciseRemainingTime(-1, -1, timerType); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + deadline.setDeadline(std::numeric_limits<qint64>::max(), timerType); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + deadline.setPreciseDeadline(std::numeric_limits<qint64>::max(), 0, timerType); + QVERIFY(deadline.isForever()); + QVERIFY(!deadline.hasExpired()); + QCOMPARE(deadline.remainingTime(), qint64(-1)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max()); + + QCOMPARE(deadline, deadline); + QVERIFY(!(deadline < deadline)); + QVERIFY(deadline <= deadline); + QVERIFY(deadline >= deadline); + QVERIFY(!(deadline > deadline)); + + // adding to forever must still be forever + QDeadlineTimer deadline2 = deadline + 1; + QVERIFY(deadline2.isForever()); + QVERIFY(!deadline2.hasExpired()); + QCOMPARE(deadline2.remainingTime(), qint64(-1)); + QCOMPARE(deadline2.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline2.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline2.deadlineNSecs(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline2.timerType(), deadline.timerType()); + + QCOMPARE(deadline2 - deadline, qint64(0)); + QCOMPARE(deadline2, deadline); + QVERIFY(!(deadline2 < deadline)); + QVERIFY(deadline2 <= deadline); + QVERIFY(deadline2 >= deadline); + QVERIFY(!(deadline2 > deadline)); + + // subtracting from forever is *also* forever + deadline2 = deadline - 1; + QVERIFY(deadline2.isForever()); + QVERIFY(!deadline2.hasExpired()); + QCOMPARE(deadline2.remainingTime(), qint64(-1)); + QCOMPARE(deadline2.remainingTimeNSecs(), qint64(-1)); + QCOMPARE(deadline2.deadline(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline2.deadlineNSecs(), std::numeric_limits<qint64>::max()); + QCOMPARE(deadline2.timerType(), deadline.timerType()); + + QCOMPARE(deadline2 - deadline, qint64(0)); + QCOMPARE(deadline2, deadline); + QVERIFY(!(deadline2 < deadline)); + QVERIFY(deadline2 <= deadline); + QVERIFY(deadline2 >= deadline); + QVERIFY(!(deadline2 > deadline)); + + // compare and order against a default-constructed object + QDeadlineTimer expired; + QVERIFY(!(deadline == expired)); + QVERIFY(deadline != expired); + QVERIFY(!(deadline < expired)); + QVERIFY(!(deadline <= expired)); + QVERIFY(deadline >= expired); + QVERIFY(deadline > expired); +} + +void tst_QDeadlineTimer::current() +{ + QFETCH_GLOBAL(Qt::TimerType, timerType); + auto deadline = QDeadlineTimer::current(timerType); + QVERIFY(deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + // subtracting from current should be "more expired" + QDeadlineTimer earlierDeadline = deadline - 1; + QVERIFY(earlierDeadline.hasExpired()); + QVERIFY(!earlierDeadline.isForever()); + QCOMPARE(earlierDeadline.timerType(), timerType); + QCOMPARE(earlierDeadline.remainingTime(), qint64(0)); + QCOMPARE(earlierDeadline.remainingTimeNSecs(), qint64(0)); + QVERIFY(earlierDeadline.deadline() != 0); + QVERIFY(earlierDeadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(earlierDeadline.deadlineNSecs() != 0); + QVERIFY(earlierDeadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + QCOMPARE(earlierDeadline.deadline(), deadline.deadline() - 1); + QCOMPARE(earlierDeadline.deadlineNSecs(), deadline.deadlineNSecs() - 1000*1000); + + QCOMPARE(earlierDeadline - deadline, qint64(-1)); + QVERIFY(earlierDeadline != deadline); + QVERIFY(earlierDeadline < deadline); + QVERIFY(earlierDeadline <= deadline); + QVERIFY(!(earlierDeadline >= deadline)); + QVERIFY(!(earlierDeadline > deadline)); +} + +void tst_QDeadlineTimer::deadlines() +{ + QFETCH_GLOBAL(Qt::TimerType, timerType); + + QDeadlineTimer deadline(4 * minResolution, timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTime() > (3 * minResolution)); + QVERIFY(deadline.remainingTime() <= (4 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + deadline.setRemainingTime(4 * minResolution, timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTime() > (3 * minResolution)); + QVERIFY(deadline.remainingTime() <= (4 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + deadline.setPreciseRemainingTime(0, 4000000 * minResolution, timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTime() > (3 * minResolution)); + QVERIFY(deadline.remainingTime() <= (4 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + deadline.setPreciseRemainingTime(1, 0, timerType); // 1 sec + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTime() > (1000 - minResolution)); + QVERIFY(deadline.remainingTime() <= 1000); + QVERIFY(deadline.remainingTimeNSecs() > (1000 - minResolution)*1000*1000); + QVERIFY(deadline.remainingTimeNSecs() <= (1000*1000*1000)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + + // adding to a future deadline must still be further in the future + QDeadlineTimer laterDeadline = deadline + 1; + QVERIFY(!laterDeadline.hasExpired()); + QVERIFY(!laterDeadline.isForever()); + QCOMPARE(laterDeadline.timerType(), timerType); + QVERIFY(laterDeadline.remainingTime() > (1000 - minResolution)); + QVERIFY(laterDeadline.remainingTime() <= 1001); + QVERIFY(laterDeadline.remainingTimeNSecs() > (1001 - minResolution)*1000*1000); + QVERIFY(laterDeadline.remainingTimeNSecs() <= (1001*1000*1000)); + QVERIFY(laterDeadline.deadline() != 0); + QVERIFY(laterDeadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(laterDeadline.deadlineNSecs() != 0); + QVERIFY(laterDeadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + QCOMPARE(laterDeadline.deadline(), deadline.deadline() + 1); + QCOMPARE(laterDeadline.deadlineNSecs(), deadline.deadlineNSecs() + 1000*1000); + + QCOMPARE(laterDeadline - deadline, qint64(1)); + QVERIFY(laterDeadline != deadline); + QVERIFY(!(laterDeadline < deadline)); + QVERIFY(!(laterDeadline <= deadline)); + QVERIFY(laterDeadline >= deadline); + QVERIFY(laterDeadline > deadline); + + // compare and order against a default-constructed object + QDeadlineTimer expired; + QVERIFY(!(deadline == expired)); + QVERIFY(deadline != expired); + QVERIFY(!(deadline < expired)); + QVERIFY(!(deadline <= expired)); + QVERIFY(deadline >= expired); + QVERIFY(deadline > expired); + + // compare and order against a forever deadline + QDeadlineTimer forever_(QDeadlineTimer::Forever); + QVERIFY(!(deadline == forever_)); + QVERIFY(deadline != forever_); + QVERIFY(deadline < forever_); + QVERIFY(deadline <= forever_); + QVERIFY(!(deadline >= forever_)); + QVERIFY(!(deadline > forever_)); +} + +void tst_QDeadlineTimer::setDeadline() +{ + QFETCH_GLOBAL(Qt::TimerType, timerType); + auto now = QDeadlineTimer::current(timerType); + QDeadlineTimer deadline; + + deadline.setDeadline(now.deadline(), timerType); + QVERIFY(deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QCOMPARE(deadline.deadline(), now.deadline()); + // don't check deadlineNSecs! + + deadline.setPreciseDeadline(now.deadlineNSecs() / (1000 * 1000 * 1000), + now.deadlineNSecs() % (1000 * 1000 * 1000), timerType); + QVERIFY(deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QCOMPARE(deadline.deadline(), now.deadline()); + QCOMPARE(deadline.deadlineNSecs(), now.deadlineNSecs()); + + now = QDeadlineTimer::current(timerType); + deadline.setDeadline(now.deadline() + 4 * minResolution, timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTime() > (3 * minResolution)); + QVERIFY(deadline.remainingTime() <= (4 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution)); + QCOMPARE(deadline.deadline(), now.deadline() + 4 * minResolution); // yes, it's exact + // don't check deadlineNSecs! + + now = QDeadlineTimer::current(timerType); + qint64 nsec = now.deadlineNSecs() + 4000000 * minResolution; + deadline.setPreciseDeadline(nsec / (1000 * 1000 * 1000), + nsec % (1000 * 1000 * 1000), timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTime() > (3 * minResolution)); + QVERIFY(deadline.remainingTime() <= (4 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution)); + QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution)); + QCOMPARE(deadline.deadline(), nsec / (1000 * 1000)); + QCOMPARE(deadline.deadlineNSecs(), nsec); +} + +void tst_QDeadlineTimer::expire() +{ + QFETCH_GLOBAL(Qt::TimerType, timerType); + + QDeadlineTimer deadline(minResolution, timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + + qint64 previousDeadline = deadline.deadlineNSecs(); + + QTest::qSleep(2 * minResolution); + + QCOMPARE(deadline.remainingTime(), qint64(0)); + QCOMPARE(deadline.remainingTimeNSecs(), qint64(0)); + QVERIFY(deadline.deadline() != 0); + QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max()); + QVERIFY(deadline.deadlineNSecs() != 0); + QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max()); + QCOMPARE(deadline.deadlineNSecs(), previousDeadline); +} + +void tst_QDeadlineTimer::stdchrono() +{ +#if !QT_HAS_INCLUDE(<chrono>) + QSKIP("std::chrono not found on this system"); +#else + using namespace std::chrono; + QFETCH_GLOBAL(Qt::TimerType, timerType); + + // create some forevers + QDeadlineTimer deadline = milliseconds::max(); + QVERIFY(deadline.isForever()); + deadline = milliseconds::max(); + QVERIFY(deadline.isForever()); + deadline.setRemainingTime(milliseconds::max(), timerType); + QVERIFY(deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + deadline = nanoseconds::max(); + QVERIFY(deadline.isForever()); + deadline.setRemainingTime(nanoseconds::max(), timerType); + QVERIFY(deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + deadline = hours::max(); + QVERIFY(deadline.isForever()); + deadline.setRemainingTime(hours::max(), timerType); + QVERIFY(deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + + deadline = time_point<system_clock>::max(); + QVERIFY(deadline.isForever()); + deadline.setDeadline(time_point<system_clock>::max(), timerType); + QVERIFY(deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + deadline = time_point<steady_clock>::max(); + QVERIFY(deadline.isForever()); + deadline.setDeadline(time_point<steady_clock>::max(), timerType); + QVERIFY(deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + + QVERIFY(deadline == time_point<steady_clock>::max()); + QVERIFY(deadline == time_point<system_clock>::max()); + QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::max()); + + // make it expired + deadline = time_point<system_clock>(); + QVERIFY(deadline.hasExpired()); + deadline.setDeadline(time_point<system_clock>(), timerType); + QVERIFY(deadline.hasExpired()); + QCOMPARE(deadline.timerType(), timerType); + deadline = time_point<steady_clock>(); + QVERIFY(deadline.hasExpired()); + deadline.setDeadline(time_point<steady_clock>(), timerType); + QVERIFY(deadline.hasExpired()); + QCOMPARE(deadline.timerType(), timerType); + + QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero()); + + auto steady_before = steady_clock::now(); + auto system_before = system_clock::now(); + + QTest::qSleep(minResolution); + auto now = QDeadlineTimer::current(timerType); + QTest::qSleep(minResolution); + + auto steady_after = steady_clock::now(); + auto system_after = system_clock::now(); + + { + auto diff = duration_cast<milliseconds>(steady_after - now.deadline<steady_clock>()); + QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); + QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); + QDeadlineTimer dt_after(steady_after, timerType); + QVERIFY2(now < dt_after, + ("now = " + QLocale().toString(now.deadlineNSecs()) + + "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); + + diff = duration_cast<milliseconds>(now.deadline<steady_clock>() - steady_before); + QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); + QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); + QDeadlineTimer dt_before(steady_before, timerType); + QVERIFY2(now > dt_before, + ("now = " + QLocale().toString(now.deadlineNSecs()) + + "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); + } + { + auto diff = duration_cast<milliseconds>(system_after - now.deadline<system_clock>()); + QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); + QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); + QDeadlineTimer dt_after(system_after, timerType); + QVERIFY2(now < dt_after, + ("now = " + QLocale().toString(now.deadlineNSecs()) + + "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); + + diff = duration_cast<milliseconds>(now.deadline<system_clock>() - system_before); + QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); + QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); + QDeadlineTimer dt_before(system_before, timerType); + QVERIFY2(now > dt_before, + ("now = " + QLocale().toString(now.deadlineNSecs()) + + "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); + } + + // make it regular + now = QDeadlineTimer::current(timerType); + deadline.setRemainingTime(milliseconds(4 * minResolution), timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTimeAsDuration() > milliseconds(3 * minResolution)); + QVERIFY(deadline.remainingTimeAsDuration() < milliseconds(5 * minResolution)); + QVERIFY(deadline.remainingTimeAsDuration() > nanoseconds(3000000 * minResolution)); + QVERIFY(deadline.remainingTimeAsDuration() < nanoseconds(5000000 * minResolution)); + QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + milliseconds(3 * minResolution))); + QVERIFY(deadline.deadline<steady_clock>() < (steady_clock::now() + milliseconds(5 * minResolution))); + QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + milliseconds(3 * minResolution))); + QVERIFY(deadline.deadline<system_clock>() < (system_clock::now() + milliseconds(5 * minResolution))); + if (timerType == Qt::CoarseTimer) { + QVERIFY(deadline > (now + milliseconds(3 * minResolution))); + QVERIFY(deadline < (now + milliseconds(5 * minResolution))); + QVERIFY(deadline > (now + nanoseconds(3000000 * minResolution))); + QVERIFY(deadline < (now + nanoseconds(5000000 * minResolution))); + QVERIFY(deadline > milliseconds(3 * minResolution)); + QVERIFY(deadline < milliseconds(5 * minResolution)); + QVERIFY(deadline > nanoseconds(3000000 * minResolution)); + QVERIFY(deadline < nanoseconds(5000000 * minResolution)); + QVERIFY(deadline >= steady_clock::now()); + QVERIFY(deadline >= system_clock::now()); + } + + now = QDeadlineTimer::current(timerType); + deadline = QDeadlineTimer(seconds(1), timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1)); + QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution))); + if (timerType == Qt::CoarseTimer) { + QVERIFY(deadline > (seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline <= seconds(1)); + } + + now = QDeadlineTimer::current(timerType); + deadline.setRemainingTime(hours(1), timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTimeAsDuration() > (hours(1) - milliseconds(minResolution))); + QVERIFY(deadline.remainingTimeAsDuration() <= hours(1)); + QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + hours(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + hours(1) + milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + hours(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + hours(1) + milliseconds(minResolution))); + + now = QDeadlineTimer::current(timerType); + deadline.setDeadline(system_clock::now() + seconds(1), timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1)); + QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution))); + + now = QDeadlineTimer::current(timerType); + deadline.setDeadline(steady_clock::now() + seconds(1), timerType); + QVERIFY(!deadline.hasExpired()); + QVERIFY(!deadline.isForever()); + QCOMPARE(deadline.timerType(), timerType); + QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1)); + QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution))); + QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution))); +#endif +} + +QTEST_MAIN(tst_QDeadlineTimer) + +#include "tst_qdeadlinetimer.moc" diff --git a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro index 50072dc612..295a42aa9c 100644 --- a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro +++ b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro @@ -5,4 +5,4 @@ SOURCES = $$PWD/tst_qeventloop.cpp win32:!winrt: LIBS += -luser32 -contains(QT_CONFIG, glib): DEFINES += HAVE_GLIB +qtConfig(glib): DEFINES += HAVE_GLIB diff --git a/tests/auto/corelib/kernel/qsocketnotifier/qsocketnotifier.pro b/tests/auto/corelib/kernel/qsocketnotifier/qsocketnotifier.pro index 58e4b98af7..04806de5f7 100644 --- a/tests/auto/corelib/kernel/qsocketnotifier/qsocketnotifier.pro +++ b/tests/auto/corelib/kernel/qsocketnotifier/qsocketnotifier.pro @@ -3,6 +3,6 @@ TARGET = tst_qsocketnotifier QT = core-private network-private testlib SOURCES = tst_qsocketnotifier.cpp -requires(contains(QT_CONFIG,private_tests)) +requires(qtConfig(private_tests)) include(../../../network/socket/platformsocketengine/platformsocketengine.pri) diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro index 33e8b6e2ad..96071f9f73 100644 --- a/tests/auto/corelib/kernel/qvariant/qvariant.pro +++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro @@ -5,7 +5,7 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common SOURCES = tst_qvariant.cpp RESOURCES += qvariant.qrc DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -contains(QT_CONFIG, c++11): CONFIG += c++11 -!contains(QT_CONFIG, doubleconversion):!contains(QT_CONFIG, system-doubleconversion) { +qtConfig(c++11): CONFIG += c++11 +!qtConfig(doubleconversion):!qtConfig(system-doubleconversion) { DEFINES += QT_NO_DOUBLECONVERSION } diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 262d8ad44b..75fa424ab1 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -275,6 +275,7 @@ private slots: void metaEnums(); void compareSanity_data(); void compareSanity(); + void compareRich(); void accessSequentialContainerKey(); @@ -4775,6 +4776,60 @@ void tst_QVariant::compareSanity() } } +static void richComparison(const QVariant& less, const QVariant& more) +{ + QVERIFY(less.type() == more.type()); + + QVERIFY(less < more); + QVERIFY(!(more < less)); + + QVERIFY(more > less); + QVERIFY(!(less > more)); + + QVERIFY(less <= more); + QVERIFY(!(more <= less)); + QVERIFY(less <= less); + + QVERIFY(more >= less); + QVERIFY(!(less >= more)); + QVERIFY(more >= more); +} + +void tst_QVariant::compareRich() +{ + richComparison(QUuid("{49d8ad2a-2ee8-4c3d-949f-1b5a3765ddf0}"), + QUuid("{f6d56824-16e9-4543-a375-add2877c2d05}")); + richComparison(QByteArray::fromRawData("a", 1), + QByteArray::fromRawData("b", 1)); + richComparison(QStringLiteral("a"), QStringLiteral("b")); + richComparison(QLatin1String("a"), QLatin1String("b")); + richComparison(QChar('a'), QChar('b')); + richComparison(QDate(2016, 7, 23), QDate(2016, 7, 24)); + richComparison(QTime(0, 0), QTime(0, 1)); + richComparison(QDateTime(QDate(2016, 7, 23), QTime(0, 0)), + QDateTime(QDate(2016, 7, 23), QTime(0, 1))); + + richComparison(QStringList(), QStringList() << QStringLiteral("a")); + richComparison(QStringList(), QStringList() << QStringLiteral("a") + << QStringLiteral("b")); + richComparison(QStringList() << QStringLiteral("a"), + QStringList() << QStringLiteral("b")); + richComparison(QStringList() << QStringLiteral("a"), + QStringList() << QStringLiteral("b") + << QStringLiteral("c")); + richComparison(QStringList() << QStringLiteral("a") + << QStringLiteral("c"), + QStringList() << QStringLiteral("b")); + richComparison(QStringList() << QStringLiteral("a") + << QStringLiteral("c"), + QStringList() << QStringLiteral("b") + << QStringLiteral("d")); + richComparison(QStringList() << QStringLiteral("a") + << QStringLiteral("c"), + QStringList() << QStringLiteral("a") + << QStringLiteral("d")); +} + void tst_QVariant::accessSequentialContainerKey() { QString nameResult; diff --git a/tests/auto/corelib/mimetypes/mimetypes.pro b/tests/auto/corelib/mimetypes/mimetypes.pro index 9063d677e7..9dd091374f 100644 --- a/tests/auto/corelib/mimetypes/mimetypes.pro +++ b/tests/auto/corelib/mimetypes/mimetypes.pro @@ -4,5 +4,5 @@ SUBDIRS = \ qmimetype \ qmimedatabase -!contains(QT_CONFIG, private_tests): SUBDIRS -= \ +!qtConfig(private_tests): SUBDIRS -= \ qmimetype diff --git a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro index 83d00f7cd8..c681f5585c 100644 --- a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro +++ b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro @@ -5,7 +5,7 @@ SUBDIRS = lib \ theplugin \ tst !android: !win32: !mac: SUBDIRS += almostplugin -macx-*: contains(QT_CONFIG, private_tests): SUBDIRS += machtest +macx-*: qtConfig(private_tests): SUBDIRS += machtest TARGET = tst_qpluginloader # no special install rule for subdir diff --git a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro index 101392927c..5f9fa6664b 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro +++ b/tests/auto/corelib/plugin/qpluginloader/tst/tst.pro @@ -1,7 +1,7 @@ CONFIG += testcase TARGET = ../tst_qpluginloader QT = core testlib -contains(QT_CONFIG, private_tests): QT += core-private +qtConfig(private_tests): QT += core-private SOURCES = ../tst_qpluginloader.cpp ../fakeplugin.cpp HEADERS = ../theplugin/plugininterface.h CONFIG -= app_bundle diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp index 4e582cc346..49a3b3e4db 100644 --- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp +++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp @@ -200,6 +200,13 @@ void testAdoptedThreadStorageWin(void *p) } QObject::connect(QThread::currentThread(), SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); } +#ifdef Q_OS_WINRT +unsigned __stdcall testAdoptedThreadStorageWinRT(void *p) +{ + testAdoptedThreadStorageWin(p); + return 0; +} +#endif void *testAdoptedThreadStorageUnix(void *pointers) { testAdoptedThreadStorageWin(pointers); @@ -217,7 +224,12 @@ void tst_QThreadStorage::adoptedThreads() const int state = pthread_create(&thread, 0, testAdoptedThreadStorageUnix, &pointers); QCOMPARE(state, 0); pthread_join(thread, 0); -#elif defined Q_OS_WIN && !defined(Q_OS_WINRT) +#elif defined Q_OS_WINRT + HANDLE thread; + thread = (HANDLE) _beginthreadex(NULL, 0, testAdoptedThreadStorageWinRT, &pointers, 0, 0); + QVERIFY(thread); + WaitForSingleObjectEx(thread, INFINITE, FALSE); +#elif defined Q_OS_WIN HANDLE thread; thread = (HANDLE)_beginthread(testAdoptedThreadStorageWin, 0, &pointers); QVERIFY(thread); diff --git a/tests/auto/corelib/tools/qcollator/qcollator.pro b/tests/auto/corelib/tools/qcollator/qcollator.pro index ed879ee70e..7725194e3d 100644 --- a/tests/auto/corelib/tools/qcollator/qcollator.pro +++ b/tests/auto/corelib/tools/qcollator/qcollator.pro @@ -3,4 +3,4 @@ TARGET = tst_qcollator QT = core testlib SOURCES = tst_qcollator.cpp DEFINES += QT_NO_CAST_TO_ASCII -contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU +qtConfig(icu): DEFINES += QT_USE_ICU diff --git a/tests/auto/corelib/tools/qfreelist/qfreelist.pro b/tests/auto/corelib/tools/qfreelist/qfreelist.pro index fb108338bd..4825987bcf 100644 --- a/tests/auto/corelib/tools/qfreelist/qfreelist.pro +++ b/tests/auto/corelib/tools/qfreelist/qfreelist.pro @@ -2,4 +2,4 @@ CONFIG += testcase TARGET = tst_qfreelist QT = core-private testlib SOURCES = tst_qfreelist.cpp -!contains(QT_CONFIG,private_tests): SOURCES += $$QT_SOURCE_TREE/src/corelib/tools/qfreelist.cpp +!qtConfig(private_tests): SOURCES += $$QT_SOURCE_TREE/src/corelib/tools/qfreelist.cpp diff --git a/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro b/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro index a996dab23e..61054b40e4 100644 --- a/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro +++ b/tests/auto/corelib/tools/qlatin1string/qlatin1string.pro @@ -3,7 +3,7 @@ TARGET = tst_qlatin1string QT = core testlib SOURCES = tst_qlatin1string.cpp DEFINES += QT_NO_CAST_TO_ASCII -contains(QT_CONFIG,c++11): CONFIG += c++11 -contains(QT_CONFIG,c++14): CONFIG += c++14 +qtConfig(c++11): CONFIG += c++11 +qtConfig(c++14): CONFIG += c++14 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qlocale/test/test.pro b/tests/auto/corelib/tools/qlocale/test/test.pro index d9004d1eb6..595ee258e7 100644 --- a/tests/auto/corelib/tools/qlocale/test/test.pro +++ b/tests/auto/corelib/tools/qlocale/test/test.pro @@ -4,7 +4,7 @@ QT = core testlib core-private embedded: QT += gui SOURCES = ../tst_qlocale.cpp -!contains(QT_CONFIG, doubleconversion):!contains(QT_CONFIG, system-doubleconversion) { +!qtConfig(doubleconversion):!qtConfig(system-doubleconversion) { DEFINES += QT_NO_DOUBLECONVERSION } diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro index c030f04a27..e1840808ff 100644 --- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro +++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs SUBDIRS = defaultoptimize forceoptimize -contains(QT_CONFIG,private_tests):SUBDIRS += alwaysoptimize +qtConfig(private_tests): SUBDIRS += alwaysoptimize diff --git a/tests/auto/corelib/tools/qstring/qstring.pro b/tests/auto/corelib/tools/qstring/qstring.pro index 1ff9a4fc9e..a94ad3405a 100644 --- a/tests/auto/corelib/tools/qstring/qstring.pro +++ b/tests/auto/corelib/tools/qstring/qstring.pro @@ -3,11 +3,11 @@ TARGET = tst_qstring QT = core testlib SOURCES = tst_qstring.cpp DEFINES += QT_NO_CAST_TO_ASCII -contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU -contains(QT_CONFIG,c++11): CONFIG += c++11 +qtConfig(icu): DEFINES += QT_USE_ICU +qtConfig(c++11): CONFIG += c++11 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -!contains(QT_CONFIG, doubleconversion):!contains(QT_CONFIG, system-doubleconversion) { +!qtConfig(doubleconversion):!qtConfig(system-doubleconversion) { DEFINES += QT_NO_DOUBLECONVERSION } diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 2e35c961c6..a0a872710c 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -123,7 +123,7 @@ template <> class Arg<QStringRef> : ArgBase { QStringRef ref() const - { return this->pinned.isNull() ? QStringRef() : this->pinned.midRef(0) ; } + { return QStringRef(&pinned); } public: explicit Arg(const char *str) : ArgBase(str) {} @@ -499,6 +499,8 @@ private slots: void fromLocal8Bit(); void local8Bit_data(); void local8Bit(); + void invalidToLocal8Bit_data(); + void invalidToLocal8Bit(); void nullFromLocal8Bit(); void fromLatin1Roundtrip_data(); void fromLatin1Roundtrip(); @@ -4293,6 +4295,66 @@ void tst_QString::local8Bit() QCOMPARE(local8Bit.toLocal8Bit(), QByteArray(result)); } +void tst_QString::invalidToLocal8Bit_data() +{ + QTest::addColumn<QString>("unicode"); + QTest::addColumn<QByteArray>("expect"); // Initial validly-converted prefix + + { + const QChar malformed[] = { 'A', 0xd800, 'B', 0 }; + const char expected[] = "A"; + QTest::newRow("LoneHighSurrogate") + << QString(malformed, sizeof(malformed) / sizeof(QChar)) + // Don't include the terminating '\0' of expected: + << QByteArray(expected, sizeof(expected) / sizeof(char) - 1); + } + { + const QChar malformed[] = { 'A', 0xdc00, 'B', 0 }; + const char expected[] = "A"; + QTest::newRow("LoneLowSurrogate") + << QString(malformed, sizeof(malformed) / sizeof(QChar)) + << QByteArray(expected, sizeof(expected) / sizeof(char) - 1); + } + { + const QChar malformed[] = { 'A', 0xd800, 0xd801, 'B', 0 }; + const char expected[] = "A"; + QTest::newRow("DoubleHighSurrogate") + << QString(malformed, sizeof(malformed) / sizeof(QChar)) + << QByteArray(expected, sizeof(expected) / sizeof(char) - 1); + } + { + const QChar malformed[] = { 'A', 0xdc00, 0xdc01, 'B', 0 }; + const char expected[] = "A"; + QTest::newRow("DoubleLowSurrogate") + << QString(malformed, sizeof(malformed) / sizeof(QChar)) + << QByteArray(expected, sizeof(expected) / sizeof(char) - 1); + } + { + const QChar malformed[] = { 'A', 0xdc00, 0xd800, 'B', 0 }; + const char expected[] = "A"; + QTest::newRow("ReversedSurrogates") // low before high + << QString(malformed, sizeof(malformed) / sizeof(QChar)) + << QByteArray(expected, sizeof(expected) / sizeof(char) - 1); + } +} + +void tst_QString::invalidToLocal8Bit() +{ + QFETCH(QString, unicode); + QFETCH(QByteArray, expect); + QByteArray local = unicode.toLocal8Bit(); + /* + The main concern of this test is to check that any error-reporting that + toLocal8Bit() prompts on failure isn't dependent on outputting the data + it's converting via toLocal8Bit(), which would be apt to recurse. So the + real purpose of this QVERIFY(), for all that we should indeed check we get + the borked output that matches what we can reliably expect (despite + variation in how codecs respond to errors), is to verify that we got here + - i.e. we didn't crash in such a recursive stack over-flow. + */ + QVERIFY(local.startsWith(expect)); +} + void tst_QString::nullFromLocal8Bit() { QString a; diff --git a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro b/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro index 76e89c9acd..bc38b17949 100644 --- a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro +++ b/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro @@ -2,4 +2,4 @@ CONFIG += testcase TARGET = tst_qstringapisymmetry QT = core testlib SOURCES = tst_qstringapisymmetry.cpp -contains(QT_CONFIG,c++14): CONFIG += c++14 +qtConfig(c++14): CONFIG += c++14 diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/tools/qtimezone/qtimezone.pro index 4459ed6020..afc4c59dfe 100644 --- a/tests/auto/corelib/tools/qtimezone/qtimezone.pro +++ b/tests/auto/corelib/tools/qtimezone/qtimezone.pro @@ -2,6 +2,6 @@ CONFIG += testcase TARGET = tst_qtimezone QT = core-private testlib SOURCES = tst_qtimezone.cpp -contains(QT_CONFIG,icu) { +qtConfig(icu) { DEFINES += QT_USE_ICU } diff --git a/tests/auto/corelib/tools/qvector/qvector.pro b/tests/auto/corelib/tools/qvector/qvector.pro index d49516923f..b9a4ae747b 100644 --- a/tests/auto/corelib/tools/qvector/qvector.pro +++ b/tests/auto/corelib/tools/qvector/qvector.pro @@ -1,5 +1,5 @@ CONFIG += testcase -contains(QT_CONFIG, c++11):CONFIG += c++11 +qtConfig(c++11): CONFIG += c++11 TARGET = tst_qvector QT = core testlib SOURCES = $$PWD/tst_qvector.cpp diff --git a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro index 834fc85a29..e2ae91cb64 100644 --- a/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro +++ b/tests/auto/corelib/tools/qversionnumber/qversionnumber.pro @@ -1,6 +1,6 @@ CONFIG += testcase -contains(QT_CONFIG, c++11):CONFIG += c++11 -contains(QT_CONFIG, c++14):CONFIG += c++14 +qtConfig(c++11): CONFIG += c++11 +qtConfig(c++14): CONFIG += c++14 TARGET = tst_qversionnumber QT = core testlib SOURCES = tst_qversionnumber.cpp |