diff options
Diffstat (limited to 'src/testlib/qtestsystem.h')
-rw-r--r-- | src/testlib/qtestsystem.h | 71 |
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); } |