summaryrefslogtreecommitdiffstats
path: root/src/testlib/qtestsystem.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/testlib/qtestsystem.h')
-rw-r--r--src/testlib/qtestsystem.h71
1 files changed, 48 insertions, 23 deletions
diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h
index f38a156936..79fe68004e 100644
--- a/src/testlib/qtestsystem.h
+++ b/src/testlib/qtestsystem.h
@@ -54,8 +54,46 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
+ template <typename Functor>
+ Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
+ {
+ // We should not spin the event loop in case the predicate is already true,
+ // otherwise we might send new events that invalidate the predicate.
+ if (predicate())
+ return true;
+
+ // qWait() is expected to spin the event loop, even when called with a small
+ // 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);
+
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ remaining = deadline.remainingTime();
+ if (remaining > 0) {
+ QTest::qSleep(qMin(10, remaining));
+ remaining = deadline.remainingTime();
+ }
+
+ if (predicate())
+ return true;
+
+ remaining = deadline.remainingTime();
+ } while (remaining > 0);
+
+ return predicate(); // Last chance
+ }
+
Q_DECL_UNUSED inline static void qWait(int ms)
{
+ // Ideally this method would be implemented in terms of qWaitFor, with
+ // a predicate that always returns false, but due to a compiler bug in
+ // GCC 6 we can't do that.
+
Q_ASSERT(QCoreApplication::instance());
QDeadlineTimer timer(ms, Qt::PreciseTimer);
@@ -72,23 +110,17 @@ namespace QTest
}
#ifdef QT_GUI_LIB
- inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000)
{
- QDeadlineTimer timer(timeout, Qt::PreciseTimer);
- int remaining = timeout;
- while (!window->isActive() && remaining > 0) {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
- QTest::qSleep(10);
- remaining = timer.remainingTime();
- }
+ bool becameActive = qWaitFor([&]() { return window->isActive(); }, timeout);
+
// Try ensuring the platform window receives the real position.
// (i.e. that window->pos() reflects reality)
// isActive() ( == FocusIn in case of X) does not guarantee this. It seems some WMs randomly
// send the final ConfigureNotify (the one with the non-bogus 0,0 position) after the FocusIn.
// If we just let things go, every mapTo/FromGlobal call the tests perform directly after
// qWaitForWindowShown() will generate bogus results.
- if (window->isActive()) {
+ if (becameActive) {
int waitNo = 0; // 0, 0 might be a valid position after all, so do not wait for ever
while (window->position().isNull()) {
if (waitNo++ > timeout / 10)
@@ -99,29 +131,21 @@ namespace QTest
return window->isActive();
}
- inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000)
{
- QDeadlineTimer timer(timeout, Qt::PreciseTimer);
- int remaining = timeout;
- while (!window->isExposed() && remaining > 0) {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
- QTest::qSleep(10);
- remaining = timer.remainingTime();
- }
- return window->isExposed();
+ return qWaitFor([&]() { return window->isExposed(); }, timeout);
}
#endif
#ifdef QT_WIDGETS_LIB
- inline static bool qWaitForWindowActive(QWidget *widget, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWidget *widget, int timeout = 5000)
{
if (QWindow *window = widget->window()->windowHandle())
return qWaitForWindowActive(window, timeout);
return false;
}
- inline static bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000)
+ Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000)
{
if (QWindow *window = widget->window()->windowHandle())
return qWaitForWindowExposed(window, timeout);
@@ -131,7 +155,8 @@ namespace QTest
#if QT_DEPRECATED_SINCE(5, 0)
# ifdef QT_WIDGETS_LIB
- QT_DEPRECATED inline static bool qWaitForWindowShown(QWidget *widget, int timeout = 5000)
+
+ QT_DEPRECATED Q_REQUIRED_RESULT inline static bool qWaitForWindowShown(QWidget *widget, int timeout = 5000)
{
return qWaitForWindowExposed(widget, timeout);
}