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 | |
8 | using namespace std::chrono_literals; |
9 | |
10 | QT_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 | */ |
22 | void 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 | */ |
49 | void 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 | */ |
92 | Q_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 | \sa QTest::qSleep(), QSignalSpy::wait() |
111 | */ |
112 | Q_CORE_EXPORT void QTest::qWait(std::chrono::milliseconds msecs) |
113 | { |
114 | // Ideally this method would be implemented in terms of qWaitFor(), with a |
115 | // predicate that always returns false, but qWaitFor() uses the 1-arg overload |
116 | // of processEvents(), which doesn't handle events posted in this round of event |
117 | // processing, which, together with the 10ms qSleep() after every processEvents(), |
118 | // lead to a 10x slow-down in some webengine tests. |
119 | |
120 | Q_ASSERT(QCoreApplication::instance()); |
121 | |
122 | using namespace std::chrono; |
123 | |
124 | QDeadlineTimer deadline(msecs, Qt::PreciseTimer); |
125 | |
126 | do { |
127 | QCoreApplication::processEvents(flags: QEventLoop::AllEvents, deadline); |
128 | QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); |
129 | |
130 | // If dealine is Forever, processEvents() has already looped forever |
131 | if (deadline.isForever()) |
132 | break; |
133 | |
134 | msecs = ceil<milliseconds>(d: deadline.remainingTimeAsDuration()); |
135 | if (msecs == 0ms) |
136 | break; |
137 | |
138 | QTest::qSleep(msecs: std::min(a: 10ms, b: msecs)); |
139 | } while (!deadline.hasExpired()); |
140 | } |
141 | |
142 | QT_END_NAMESPACE |
143 | |