| 1 | // Copyright (C) 2018 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | |
| 4 | #ifndef QTESTSUPPORT_CORE_H |
| 5 | #define QTESTSUPPORT_CORE_H |
| 6 | |
| 7 | #include <QtCore/qcoreapplication.h> |
| 8 | #include <QtCore/qdeadlinetimer.h> |
| 9 | |
| 10 | #include <chrono> |
| 11 | |
| 12 | QT_BEGIN_NAMESPACE |
| 13 | |
| 14 | namespace QTest { |
| 15 | |
| 16 | Q_CORE_EXPORT void qSleep(int ms); |
| 17 | Q_CORE_EXPORT void qSleep(std::chrono::milliseconds msecs); |
| 18 | |
| 19 | template <typename Functor> |
| 20 | [[nodiscard]] bool |
| 21 | qWaitFor(Functor predicate, QDeadlineTimer deadline = QDeadlineTimer(std::chrono::seconds{5})) |
| 22 | { |
| 23 | // We should not spin the event loop in case the predicate is already true, |
| 24 | // otherwise we might send new events that invalidate the predicate. |
| 25 | if (predicate()) |
| 26 | return true; |
| 27 | |
| 28 | // qWait() is expected to spin the event loop at least once, even when |
| 29 | // called with a small timeout like 1ns. |
| 30 | |
| 31 | do { |
| 32 | // We explicitly do not pass the remaining time to processEvents, as |
| 33 | // that would keep spinning processEvents for the whole duration if |
| 34 | // new events were posted as part of processing events, and we need |
| 35 | // to return back to this function to check the predicate between |
| 36 | // each pass of processEvents. Our own timer will take care of the |
| 37 | // timeout. |
| 38 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents); |
| 39 | QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); |
| 40 | |
| 41 | if (predicate()) |
| 42 | return true; |
| 43 | |
| 44 | using namespace std::chrono; |
| 45 | |
| 46 | if (const auto remaining = deadline.remainingTimeAsDuration(); remaining > 0ns) |
| 47 | qSleep(msecs: (std::min)(a: 10ms, b: ceil<milliseconds>(d: remaining))); |
| 48 | |
| 49 | } while (!deadline.hasExpired()); |
| 50 | |
| 51 | return predicate(); // Last chance |
| 52 | } |
| 53 | |
| 54 | template <typename Functor> |
| 55 | [[nodiscard]] bool qWaitFor(Functor predicate, int timeout) |
| 56 | { |
| 57 | return qWaitFor(predicate, QDeadlineTimer{timeout, Qt::PreciseTimer}); |
| 58 | } |
| 59 | |
| 60 | Q_CORE_EXPORT void qWait(int ms); |
| 61 | |
| 62 | Q_CORE_EXPORT void qWait(std::chrono::milliseconds msecs); |
| 63 | |
| 64 | } // namespace QTest |
| 65 | |
| 66 | QT_END_NAMESPACE |
| 67 | |
| 68 | #endif |
| 69 | |