diff options
Diffstat (limited to 'tests/auto/corelib/thread/qmutex/tst_qmutex.cpp')
-rw-r--r-- | tests/auto/corelib/thread/qmutex/tst_qmutex.cpp | 207 |
1 files changed, 43 insertions, 164 deletions
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp index e78ebbed2e..4753444ab9 100644 --- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp +++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2016 Intel Corporation. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSemaphore> @@ -14,6 +14,8 @@ #include <qwaitcondition.h> #include <private/qvolatile_p.h> +using namespace std::chrono_literals; + class tst_QMutex : public QObject { Q_OBJECT @@ -27,8 +29,6 @@ public: Q_ENUM(TimeUnit) private slots: - void convertToMilliseconds_data(); - void convertToMilliseconds(); void tryLock_non_recursive(); void try_lock_for_non_recursive(); void try_lock_until_non_recursive(); @@ -61,121 +61,15 @@ static QSemaphore threadsTurn; enum { #ifdef Q_OS_WIN systemTimersResolution = 16, +#elif defined(Q_OS_QNX) + systemTimersResolution = 10, #else systemTimersResolution = 1, #endif waitTime = 100 }; -#if __has_include(<chrono>) static constexpr std::chrono::milliseconds waitTimeAsDuration(waitTime); -#endif - -void tst_QMutex::convertToMilliseconds_data() -{ - QTest::addColumn<TimeUnit>("unit"); - QTest::addColumn<double>("doubleValue"); - QTest::addColumn<qint64>("intValue"); - QTest::addColumn<qint64>("expected"); - -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#endif - - auto add = [](TimeUnit unit, double d, long long i, qint64 expected) { - const QScopedArrayPointer<char> enumName(QTest::toString(unit)); - QTest::addRow("%s:%f:%lld", enumName.data(), d, i) - << unit << d << qint64(i) << expected; - }; - - auto forAllUnitsAdd = [=](double d, long long i, qint64 expected) { - for (auto unit : {TimeUnit::Nanoseconds, TimeUnit::Microseconds, TimeUnit::Milliseconds, TimeUnit::Seconds}) - add(unit, d, i, expected); - }; - - forAllUnitsAdd(-0.5, -1, 0); // all negative values result in 0 - - forAllUnitsAdd(0, 0, 0); - - add(TimeUnit::Nanoseconds, 1, 1, 1); - add(TimeUnit::Nanoseconds, 1000 * 1000, 1000 * 1000, 1); - add(TimeUnit::Nanoseconds, 1000 * 1000 + 0.5, 1000 * 1000 + 1, 2); - - add(TimeUnit::Microseconds, 1, 1, 1); - add(TimeUnit::Microseconds, 1000, 1000, 1); - add(TimeUnit::Microseconds, 1000 + 0.5, 1000 + 1, 2); - - add(TimeUnit::Milliseconds, 1, 1, 1); - add(TimeUnit::Milliseconds, 1.5, 2, 2); - - add(TimeUnit::Seconds, 0.9991, 1, 1000); - - // - // overflowing int results in INT_MAX (equivalent to a spurious wakeup after ~24 days); check it: - // - - // spot on: - add(TimeUnit::Nanoseconds, INT_MAX * 1000. * 1000, INT_MAX * Q_INT64_C(1000) * 1000, INT_MAX); - add(TimeUnit::Microseconds, INT_MAX * 1000., INT_MAX * Q_INT64_C(1000), INT_MAX); - add(TimeUnit::Milliseconds, INT_MAX, INT_MAX, INT_MAX); - - // minimally above: - add(TimeUnit::Nanoseconds, INT_MAX * 1000. * 1000 + 1, INT_MAX * Q_INT64_C(1000) * 1000 + 1, INT_MAX); - add(TimeUnit::Microseconds, INT_MAX * 1000. + 1, INT_MAX * Q_INT64_C(1000) + 1, INT_MAX); - add(TimeUnit::Milliseconds, INT_MAX + 1., INT_MAX + Q_INT64_C(1), INT_MAX); - add(TimeUnit::Seconds, INT_MAX / 1000. + 1, INT_MAX / 1000 + 1, INT_MAX); - - // minimally below: - add(TimeUnit::Nanoseconds, INT_MAX * 1000. * 1000 - 1, INT_MAX * Q_INT64_C(1000) * 1000 - 1, INT_MAX); - add(TimeUnit::Microseconds, INT_MAX * 1000. - 1, INT_MAX * Q_INT64_C(1000) - 1, INT_MAX); - add(TimeUnit::Milliseconds, INT_MAX - 0.1, INT_MAX , INT_MAX); - -} - -void tst_QMutex::convertToMilliseconds() -{ -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else - QFETCH(TimeUnit, unit); - QFETCH(double, doubleValue); - QFETCH(qint64, intValue); - QFETCH(qint64, expected); - - constexpr qint64 maxShort = std::numeric_limits<short>::max(); - constexpr qint64 maxInt = std::numeric_limits<int>::max(); - constexpr qint64 maxUInt = std::numeric_limits<uint>::max(); - - switch (unit) { -#define CASE(Unit, Period) \ - case TimeUnit::Unit: \ - DO(double, Period, doubleValue); \ - if (intValue < maxShort) \ - DO(short, Period, short(intValue)); \ - if (intValue < maxInt) \ - DO(int, Period, int(intValue)); \ - DO(qint64, Period, intValue); \ - if (intValue >= 0) { \ - if (intValue < maxUInt) \ - DO(uint, Period, uint(intValue)); \ - DO(quint64, Period, quint64(intValue)); \ - } \ - break -#define DO(Rep, Period, val) \ - do { \ - const std::chrono::duration<Rep, Period> wait((val)); \ - QCOMPARE(QtPrivate::convertToMilliseconds(wait), expected); \ - } while (0) - - CASE(Nanoseconds, std::nano); - CASE(Microseconds, std::micro); - CASE(Milliseconds, std::milli); - CASE(Seconds, std::ratio<1>); -#undef DO -#undef CASE - } -#endif -} void tst_QMutex::tryLock_non_recursive() { @@ -205,19 +99,19 @@ void tst_QMutex::tryLock_non_recursive() QElapsedTimer timer; timer.start(); QVERIFY(!normalMutex.tryLock(waitTime)); - QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); + QCOMPARE_GE(timer.elapsed(), waitTime - systemTimersResolution); testsTurn.release(); // TEST 4: thread can acquire lock, timeout = waitTime threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.tryLock(waitTime)); - QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution); + QCOMPARE_LE(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); timer.start(); // it's non-recursive, so the following lock needs to fail QVERIFY(!normalMutex.tryLock(waitTime)); - QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); + QCOMPARE_GE(timer.elapsed(), waitTime - systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); testsTurn.release(); @@ -231,7 +125,7 @@ void tst_QMutex::tryLock_non_recursive() threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.tryLock(0)); - QVERIFY(timer.elapsed() < waitTime + systemTimersResolution); + QCOMPARE_LT(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(!normalMutex.tryLock(0)); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); @@ -242,7 +136,7 @@ void tst_QMutex::tryLock_non_recursive() threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.tryLock(3000)); - QVERIFY(timer.elapsed() < 3000 + systemTimersResolution); + QCOMPARE_LT(timer.elapsed(), 3000 + systemTimersResolution); normalMutex.unlock(); testsTurn.release(); @@ -253,47 +147,47 @@ void tst_QMutex::tryLock_non_recursive() Thread thread; thread.start(); - // TEST 1: thread can't acquire lock + qDebug("TEST 1: thread can't acquire lock"); testsTurn.acquire(); normalMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); threadsTurn.release(); - // TEST 2: thread can acquire lock + qDebug("TEST 2: thread can acquire lock"); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); threadsTurn.release(); - // TEST 3: thread can't acquire lock, timeout = waitTime + qDebug("TEST 3: thread can't acquire lock, timeout = waitTime"); testsTurn.acquire(); normalMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); threadsTurn.release(); - // TEST 4: thread can acquire lock, timeout = waitTime + qDebug("TEST 4: thread can acquire lock, timeout = waitTime"); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); threadsTurn.release(); - // TEST 5: thread can't acquire lock, timeout = 0 + qDebug("TEST 5: thread can't acquire lock, timeout = 0"); testsTurn.acquire(); normalMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); threadsTurn.release(); - // TEST 6: thread can acquire lock, timeout = 0 + qDebug("TEST 6: thread can acquire lock, timeout = 0"); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); threadsTurn.release(); - // TEST 7: thread can acquire lock, timeout = 3000 (QTBUG-24795) + qDebug("TEST 7: thread can acquire lock, timeout = 3000 (QTBUG-24795)"); testsTurn.acquire(); normalMutex.lock(); threadsTurn.release(); - QThread::msleep(100); + QThread::sleep(100ms); normalMutex.unlock(); // wait for thread to finish @@ -302,10 +196,8 @@ void tst_QMutex::tryLock_non_recursive() thread.wait(); } -void tst_QMutex::try_lock_for_non_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else +void tst_QMutex::try_lock_for_non_recursive() +{ class Thread : public QThread { public: @@ -332,19 +224,19 @@ void tst_QMutex::try_lock_for_non_recursive() { QElapsedTimer timer; timer.start(); QVERIFY(!normalMutex.try_lock_for(waitTimeAsDuration)); - QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); + QCOMPARE_GE(timer.elapsed(), waitTime - systemTimersResolution); testsTurn.release(); // TEST 4: thread can acquire lock, timeout = waitTime threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.try_lock_for(waitTimeAsDuration)); - QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution); + QCOMPARE_LE(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); timer.start(); // it's non-recursive, so the following lock needs to fail QVERIFY(!normalMutex.try_lock_for(waitTimeAsDuration)); - QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); + QCOMPARE_GE(timer.elapsed(), waitTime - systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); testsTurn.release(); @@ -358,7 +250,7 @@ void tst_QMutex::try_lock_for_non_recursive() { threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.try_lock_for(std::chrono::milliseconds::zero())); - QVERIFY(timer.elapsed() < waitTime + systemTimersResolution); + QCOMPARE_LT(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(!normalMutex.try_lock_for(std::chrono::milliseconds::zero())); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); @@ -369,7 +261,7 @@ void tst_QMutex::try_lock_for_non_recursive() { threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.try_lock_for(std::chrono::milliseconds(3000))); - QVERIFY(timer.elapsed() < 3000 + systemTimersResolution); + QCOMPARE_LT(timer.elapsed(), 3000 + systemTimersResolution); normalMutex.unlock(); testsTurn.release(); @@ -420,21 +312,17 @@ void tst_QMutex::try_lock_for_non_recursive() { testsTurn.acquire(); normalMutex.lock(); threadsTurn.release(); - QThread::msleep(100); + QThread::sleep(100ms); normalMutex.unlock(); // wait for thread to finish testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } void tst_QMutex::try_lock_until_non_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else class Thread : public QThread { public: @@ -461,19 +349,19 @@ void tst_QMutex::try_lock_until_non_recursive() threadsTurn.acquire(); auto endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(!normalMutex.try_lock_until(endTimePoint)); - QVERIFY(std::chrono::steady_clock::now() >= endTimePoint - systemTimersResolutionAsDuration); + QCOMPARE_GE(std::chrono::steady_clock::now(), endTimePoint - systemTimersResolutionAsDuration); testsTurn.release(); // TEST 4: thread can acquire lock, timeout = waitTime threadsTurn.acquire(); endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(normalMutex.try_lock_until(endTimePoint)); - QVERIFY(std::chrono::steady_clock::now() <= endTimePoint + systemTimersResolutionAsDuration); + QCOMPARE_LE(std::chrono::steady_clock::now(), endTimePoint + systemTimersResolutionAsDuration); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; // it's non-recursive, so the following lock needs to fail QVERIFY(!normalMutex.try_lock_until(endTimePoint)); - QVERIFY(std::chrono::steady_clock::now() >= endTimePoint - systemTimersResolutionAsDuration); + QCOMPARE_GE(std::chrono::steady_clock::now(), endTimePoint - systemTimersResolutionAsDuration); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); testsTurn.release(); @@ -487,7 +375,7 @@ void tst_QMutex::try_lock_until_non_recursive() threadsTurn.acquire(); endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(normalMutex.try_lock_until(std::chrono::steady_clock::now())); - QVERIFY(std::chrono::steady_clock::now() < endTimePoint + systemTimersResolutionAsDuration); + QCOMPARE_LT(std::chrono::steady_clock::now(), endTimePoint + systemTimersResolutionAsDuration); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(!normalMutex.try_lock_until(std::chrono::steady_clock::now())); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); @@ -498,7 +386,7 @@ void tst_QMutex::try_lock_until_non_recursive() threadsTurn.acquire(); endTimePoint = std::chrono::steady_clock::now() + std::chrono::milliseconds(3000); QVERIFY(normalMutex.try_lock_until(endTimePoint)); - QVERIFY(std::chrono::steady_clock::now() < endTimePoint + systemTimersResolutionAsDuration); + QCOMPARE_LT(std::chrono::steady_clock::now(), endTimePoint + systemTimersResolutionAsDuration); normalMutex.unlock(); testsTurn.release(); @@ -549,14 +437,13 @@ void tst_QMutex::try_lock_until_non_recursive() testsTurn.acquire(); normalMutex.lock(); threadsTurn.release(); - QThread::msleep(100); + QThread::sleep(100ms); normalMutex.unlock(); // wait for thread to finish testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } void tst_QMutex::tryLock_recursive() @@ -587,14 +474,14 @@ void tst_QMutex::tryLock_recursive() QElapsedTimer timer; timer.start(); QVERIFY(!recursiveMutex.tryLock(waitTime)); - QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); + QCOMPARE_GE(timer.elapsed(), waitTime - systemTimersResolution); QVERIFY(!recursiveMutex.tryLock(0)); testsTurn.release(); threadsTurn.acquire(); timer.start(); QVERIFY(recursiveMutex.tryLock(waitTime)); - QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution); + QCOMPARE_LE(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.tryLock(waitTime)); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); @@ -612,7 +499,7 @@ void tst_QMutex::tryLock_recursive() threadsTurn.acquire(); timer.start(); QVERIFY(recursiveMutex.tryLock(0)); - QVERIFY(timer.elapsed() < waitTime + systemTimersResolution); + QCOMPARE_LT(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.tryLock(0)); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); @@ -685,9 +572,6 @@ void tst_QMutex::tryLock_recursive() void tst_QMutex::try_lock_for_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else class Thread : public QThread { public: @@ -714,14 +598,14 @@ void tst_QMutex::try_lock_for_recursive() QElapsedTimer timer; timer.start(); QVERIFY(!recursiveMutex.try_lock_for(waitTimeAsDuration)); - QVERIFY(timer.elapsed() >= waitTime - systemTimersResolution); + QCOMPARE_GE(timer.elapsed(), waitTime - systemTimersResolution); QVERIFY(!recursiveMutex.try_lock_for(std::chrono::milliseconds::zero())); testsTurn.release(); threadsTurn.acquire(); timer.start(); QVERIFY(recursiveMutex.try_lock_for(waitTimeAsDuration)); - QVERIFY(timer.elapsed() <= waitTime + systemTimersResolution); + QCOMPARE_LE(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.try_lock_for(waitTimeAsDuration)); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); @@ -739,7 +623,7 @@ void tst_QMutex::try_lock_for_recursive() threadsTurn.acquire(); timer.start(); QVERIFY(recursiveMutex.try_lock_for(std::chrono::milliseconds::zero())); - QVERIFY(timer.elapsed() < waitTime + systemTimersResolution); + QCOMPARE_LT(timer.elapsed(), waitTime + systemTimersResolution); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.try_lock_for(std::chrono::milliseconds::zero())); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); @@ -808,14 +692,10 @@ void tst_QMutex::try_lock_for_recursive() testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } void tst_QMutex::try_lock_until_recursive() { -#if !__has_include(<chrono>) - QSKIP("This test requires <chrono>"); -#else class Thread : public QThread { public: @@ -842,14 +722,14 @@ void tst_QMutex::try_lock_until_recursive() threadsTurn.acquire(); auto endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(!recursiveMutex.try_lock_until(endTimePoint)); - QVERIFY(std::chrono::steady_clock::now() >= endTimePoint - systemTimersResolutionAsDuration); + QCOMPARE_GE(std::chrono::steady_clock::now(), endTimePoint - systemTimersResolutionAsDuration); QVERIFY(!recursiveMutex.try_lock()); testsTurn.release(); threadsTurn.acquire(); endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(recursiveMutex.try_lock_until(endTimePoint)); - QVERIFY(std::chrono::steady_clock::now() <= endTimePoint + systemTimersResolutionAsDuration); + QCOMPARE_LE(std::chrono::steady_clock::now(), endTimePoint + systemTimersResolutionAsDuration); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(recursiveMutex.try_lock_until(endTimePoint)); @@ -868,7 +748,7 @@ void tst_QMutex::try_lock_until_recursive() threadsTurn.acquire(); endTimePoint = std::chrono::steady_clock::now() + waitTimeAsDuration; QVERIFY(recursiveMutex.try_lock_until(std::chrono::steady_clock::now())); - QVERIFY(std::chrono::steady_clock::now() <= endTimePoint + systemTimersResolutionAsDuration); + QCOMPARE_LE(std::chrono::steady_clock::now(), endTimePoint + systemTimersResolutionAsDuration); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.try_lock_until(std::chrono::steady_clock::now())); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); @@ -937,7 +817,6 @@ void tst_QMutex::try_lock_until_recursive() testsTurn.acquire(); threadsTurn.release(); thread.wait(); -#endif } class mutex_Thread : public QThread @@ -1063,8 +942,8 @@ void tst_QMutex::lock_unlock_locked_tryLock() } } -enum { one_minute = 6 * 1000, //not really one minute, but else it is too long. - threadCount = 10 }; +constexpr int one_minute = 6 * 1000; // not really one minute, but else it is too long. +constexpr int threadCount = 10; class StressTestThread : public QThread { |