1// Copyright (C) 2022 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#include "qtestsupport_core.h"
5
6#include <thread>
7
8using namespace std::chrono_literals;
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \overload
14
15 Sleeps for \a ms milliseconds, blocking execution of the test.
16
17 Equivalent to calling:
18 \code
19 QTest::qSleep(std::chrono::milliseconds{ms});
20 \endcode
21*/
22void QTest::qSleep(int ms)
23{
24 QTest::qSleep(msecs: std::chrono::milliseconds{ms});
25}
26
27/*!
28 \since 6.7
29
30 Sleeps for \a msecs, blocking execution of the test.
31
32 This method will not do any event processing and will leave your test
33 unresponsive. Network communication might time out while sleeping.
34 Use \l {QTest::qWait()} to do non-blocking sleeping.
35
36 \a msecs must be greater than 0ms.
37
38 \note Starting from Qt 6.7, this function is implemented using
39 \c {std::this_thread::sleep_for}, so the accuracy of time spent depends
40 on the Standard Library implementation. Before Qt 6.7 this function called
41 either \c nanosleep() on Unix or \c Sleep() on Windows, so the accuracy of
42 time spent in this function depended on the operating system.
43
44 Example:
45 \snippet code/src_qtestlib_qtestcase.cpp 23
46
47 \sa {QTest::qWait()}
48*/
49void QTest::qSleep(std::chrono::milliseconds msecs)
50{
51 Q_ASSERT(msecs > 0ms);
52 std::this_thread::sleep_for(rtime: msecs);
53}
54
55/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
56
57 \since 5.10
58 \overload
59
60 Waits for \a timeout milliseconds or until the \a predicate returns true.
61
62 This is equivalent to calling:
63 \code
64 qWaitFor(predicate, QDeadlineTimer(timeout));
65 \endcode
66*/
67
68/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, QDeadlineTimer deadline)
69 \since 6.7
70
71 Waits until \a deadline has expired, or until \a predicate returns true, whichever
72 happens first.
73
74 Returns \c true if \a predicate returned true at any point, otherwise returns \c false.
75
76 Example:
77
78 \snippet code/src_corelib_kernel_qtestsupport_core.cpp 2
79
80 The code above will wait for the object to become ready, for a
81 maximum of three seconds.
82*/
83
84/*!
85 \overload
86
87 Waits for \a msecs. Equivalent to calling:
88 \code
89 QTest::qWait(std::chrono::milliseconds{msecs});
90 \endcode
91*/
92Q_CORE_EXPORT void QTest::qWait(int msecs)
93{
94 qWait(msecs: std::chrono::milliseconds{msecs});
95}
96
97/*!
98 \since 6.7
99
100 Waits for \a msecs. While waiting, events will be processed and
101 your test will stay responsive to user interface events or network communication.
102
103 Example:
104
105 \snippet code/src_corelib_kernel_qtestsupport_core.cpp 1
106
107 The code above will wait until the network server is responding for a
108 maximum of about 12.5 seconds.
109
110 The \l{QTRY_COMPARE()}{QTRY_*} macros are usually a better choice than
111 qWait(). qWait() always pauses for the full timeout, which can leave the
112 test idle and slow down execution.
113
114 The \c {QTRY_*} macros poll the condition until it succeeds or the timeout
115 expires. Your test therefore continues as soon as possible and stays more
116 reliable. If the condition still fails, the macros double the timeout once
117 and report the new value so that you can adjust it.
118
119 For example, rewrite the code above as:
120
121 \code
122 QTRY_VERIFY_WITH_TIMEOUT(!myNetworkServerNotResponding(), 12.5s);
123 \endcode
124
125 \sa QTest::qSleep(), QSignalSpy::wait(), QTRY_VERIFY_WITH_TIMEOUT()
126*/
127Q_CORE_EXPORT void QTest::qWait(std::chrono::milliseconds msecs)
128{
129 // Ideally this method would be implemented in terms of qWaitFor(), with a
130 // predicate that always returns false, but qWaitFor() uses the 1-arg overload
131 // of processEvents(), which doesn't handle events posted in this round of event
132 // processing, which, together with the 10ms qSleep() after every processEvents(),
133 // lead to a 10x slow-down in some webengine tests.
134
135 Q_ASSERT(QCoreApplication::instance());
136
137 using namespace std::chrono;
138
139 QDeadlineTimer deadline(msecs, Qt::PreciseTimer);
140
141 do {
142 QCoreApplication::processEvents(flags: QEventLoop::AllEvents, deadline);
143 QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete);
144
145 // If dealine is Forever, processEvents() has already looped forever
146 if (deadline.isForever())
147 break;
148
149 msecs = ceil<milliseconds>(d: deadline.remainingTimeAsDuration());
150 if (msecs == 0ms)
151 break;
152
153 QTest::qSleep(msecs: std::min(a: 10ms, b: msecs));
154 } while (!deadline.hasExpired());
155}
156
157QT_END_NAMESPACE
158

source code of qtbase/src/corelib/kernel/qtestsupport_core.cpp