QTest: add QDeadlineTimer qWaitFor() overload

For Forever timers, don't check the remaining time.

Merge src_corelib_kernel_qtestsupport_core_snippet.cpp and
src_corelib_kernel_qtestsupport_core.cpp.

[ChangeLog][QtCore][QTest] Added QDeadlineTimer qWaitFor() overload.

Change-Id: I74c3f362b77206426136a418e656465e43f45b09
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2023-03-05 01:48:18 +02:00
parent 57712e1160
commit fa296ee1dc
4 changed files with 51 additions and 22 deletions

View File

@ -54,18 +54,31 @@ void QTest::qSleep(std::chrono::milliseconds msecs)
/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
\since 5.10
\overload
Waits for \a timeout milliseconds or until the \a predicate returns true.
Returns \c true if the \a predicate returned true at any point, otherwise returns \c false.
This is equivalent to calling:
\code
qWaitFor(predicate, QDeadlineTimer(timeout));
\endcode
*/
/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, QDeadlineTimer deadline)
\since 6.7
Waits until \a deadline has expired, or until \a predicate returns true, whichever
happens first.
Returns \c true if \a predicate returned true at any point, otherwise returns \c false.
Example:
\snippet code/src_corelib_kernel_qtestsupport_core_snippet.cpp 0
\snippet code/src_corelib_kernel_qtestsupport_core.cpp 2
The code above will wait for the object to become ready, for a
maximum of three seconds.
\since 5.10
*/
/*!

View File

@ -16,7 +16,8 @@ Q_CORE_EXPORT void qSleep(int ms);
Q_CORE_EXPORT void qSleep(std::chrono::milliseconds msecs);
template <typename Functor>
[[nodiscard]] static bool qWaitFor(Functor predicate, int timeout = 5000)
[[nodiscard]] static bool
qWaitFor(Functor predicate, QDeadlineTimer deadline = QDeadlineTimer(std::chrono::seconds{5}))
{
// We should not spin the event loop in case the predicate is already true,
// otherwise we might send new events that invalidate the predicate.
@ -27,9 +28,9 @@ template <typename Functor>
// timeout like 1ms, so we we can't use a simple while-loop here based on
// the deadline timer not having timed out. Use do-while instead.
int remaining = timeout;
QDeadlineTimer deadline(remaining, Qt::PreciseTimer);
using namespace std::chrono;
auto remaining = 0ms;
do {
// We explicitly do not pass the remaining time to processEvents, as
// that would keep spinning processEvents for the whole duration if
@ -43,15 +44,27 @@ template <typename Functor>
if (predicate())
return true;
remaining = int(deadline.remainingTime());
if (remaining > 0)
qSleep(qMin(10, remaining));
remaining = int(deadline.remainingTime());
} while (remaining > 0);
if (deadline.isForever()) { // No point checking remaining time
qSleep(10ms);
continue;
}
remaining = ceil<milliseconds>(deadline.remainingTimeAsDuration());
if (remaining == 0ms)
break;
qSleep(std::min(10ms, remaining));
} while (!deadline.hasExpired());
return predicate(); // Last chance
}
template <typename Functor>
[[nodiscard]] static bool qWaitFor(Functor predicate, int timeout)
{
return qWaitFor(predicate, QDeadlineTimer(timeout));
}
Q_CORE_EXPORT void qWait(int ms);
Q_CORE_EXPORT void qWait(std::chrono::milliseconds msecs);

View File

@ -7,6 +7,7 @@ class MyObject
{
public:
int isReady();
bool startup();
};
// dummy function
@ -25,3 +26,15 @@ int MyObject::isReady()
//! [1]
return 1;
}
static bool startup()
{
//! [2]
MyObject obj;
obj.startup();
using namespace std::chrono_literals;
const bool result = QTest::qWaitFor([&obj]() { return obj.isReady(); },
QDeadlineTimer(3s));
//! [2]
return result;
}

View File

@ -1,10 +0,0 @@
// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
MyObject obj;
obj.startup();
QTest::qWaitFor([&]() {
return obj.isReady();
}, 3000);
//! [0]