1/****************************************************************************
2**
3** Copyright (C) 2016 Intel Corporation.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtCore/QString>
30#include <QtCore/QTime>
31#include <QtCore/QDeadlineTimer>
32#include <QtCore/QElapsedTimer>
33#include <QtTest/QtTest>
34
35#if __has_include(<chrono>)
36# include <chrono>
37#endif
38
39static const int minResolution = 400; // the minimum resolution for the tests
40
41Q_DECLARE_METATYPE(Qt::TimerType)
42
43class tst_QDeadlineTimer : public QObject
44{
45 Q_OBJECT
46
47private Q_SLOTS:
48 void initTestCase_data();
49 void basics();
50 void foreverness();
51 void current();
52 void deadlines();
53 void setDeadline();
54 void overflow();
55 void expire();
56 void stdchrono();
57};
58
59void tst_QDeadlineTimer::initTestCase_data()
60{
61 qRegisterMetaType<Qt::TimerType>();
62 QTest::addColumn<Qt::TimerType>(name: "timerType");
63 QTest::newRow(dataTag: "precise") << Qt::PreciseTimer;
64 QTest::newRow(dataTag: "coarse") << Qt::CoarseTimer;
65}
66
67void tst_QDeadlineTimer::basics()
68{
69 QDeadlineTimer deadline;
70 QCOMPARE(deadline.timerType(), Qt::CoarseTimer);
71
72 QFETCH_GLOBAL(Qt::TimerType, timerType);
73 deadline = QDeadlineTimer(timerType);
74 QCOMPARE(deadline.timerType(), timerType);
75 QVERIFY(!deadline.isForever());
76 QCOMPARE(deadline, QDeadlineTimer(timerType));
77 QVERIFY(!(deadline != QDeadlineTimer(timerType)));
78 QVERIFY(!(deadline < QDeadlineTimer()));
79 QVERIFY(deadline <= QDeadlineTimer());
80 QVERIFY(deadline >= QDeadlineTimer());
81 QVERIFY(!(deadline > QDeadlineTimer()));
82 QVERIFY(!(deadline < deadline));
83 QVERIFY(deadline <= deadline);
84 QVERIFY(deadline >= deadline);
85 QVERIFY(!(deadline > deadline));
86
87 // should have expired, but we may be running too early after boot
88 QTRY_VERIFY_WITH_TIMEOUT(deadline.hasExpired(), 100);
89
90 QCOMPARE(deadline.remainingTime(), qint64(0));
91 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
92 QCOMPARE(deadline.deadline(), qint64(0));
93 QCOMPARE(deadline.deadlineNSecs(), qint64(0));
94
95 deadline.setRemainingTime(msecs: 0, type: timerType);
96 QCOMPARE(deadline.remainingTime(), qint64(0));
97 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
98 QVERIFY(deadline.deadline() != 0);
99 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
100 QVERIFY(deadline.deadlineNSecs() != 0);
101 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
102
103 deadline.setPreciseRemainingTime(secs: 0, nsecs: 0, type: timerType);
104 QCOMPARE(deadline.remainingTime(), qint64(0));
105 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
106 QVERIFY(deadline.deadline() != 0);
107 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
108 QVERIFY(deadline.deadlineNSecs() != 0);
109 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
110
111 deadline.setDeadline(msecs: 0, timerType);
112 QCOMPARE(deadline.remainingTime(), qint64(0));
113 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
114 QCOMPARE(deadline.deadline(), qint64(0));
115 QCOMPARE(deadline.deadlineNSecs(), qint64(0));
116
117 deadline.setPreciseDeadline(secs: 0, nsecs: 0, type: timerType);
118 QCOMPARE(deadline.remainingTime(), qint64(0));
119 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
120 QCOMPARE(deadline.deadline(), qint64(0));
121 QCOMPARE(deadline.deadlineNSecs(), qint64(0));
122}
123
124void tst_QDeadlineTimer::foreverness()
125{
126 QFETCH_GLOBAL(Qt::TimerType, timerType);
127 // we don't check whether timerType() is our type since it's possible it detects it's forever
128
129 QDeadlineTimer deadline = QDeadlineTimer::Forever;
130 QCOMPARE(deadline.timerType(), Qt::CoarseTimer);
131 QVERIFY(deadline.isForever());
132 QVERIFY(!deadline.hasExpired());
133 QCOMPARE(deadline.remainingTime(), qint64(-1));
134 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
135 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
136 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
137
138 deadline = QDeadlineTimer(-1, timerType);
139 QVERIFY(deadline.isForever());
140 QVERIFY(!deadline.hasExpired());
141 QCOMPARE(deadline.remainingTime(), qint64(-1));
142 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
143 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
144 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
145
146 deadline.setRemainingTime(msecs: -1, type: timerType);
147 QVERIFY(deadline.isForever());
148 QVERIFY(!deadline.hasExpired());
149 QCOMPARE(deadline.remainingTime(), qint64(-1));
150 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
151 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
152 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
153
154 deadline.setPreciseRemainingTime(secs: -1, nsecs: 0, type: timerType);
155 QVERIFY(deadline.isForever());
156 QVERIFY(!deadline.hasExpired());
157 QCOMPARE(deadline.remainingTime(), qint64(-1));
158 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
159 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
160 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
161
162 deadline.setPreciseRemainingTime(secs: -1, nsecs: -1, type: timerType);
163 QVERIFY(deadline.isForever());
164 QVERIFY(!deadline.hasExpired());
165 QCOMPARE(deadline.remainingTime(), qint64(-1));
166 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
167 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
168 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
169
170 deadline.setDeadline(msecs: std::numeric_limits<qint64>::max(), timerType);
171 QVERIFY(deadline.isForever());
172 QVERIFY(!deadline.hasExpired());
173 QCOMPARE(deadline.remainingTime(), qint64(-1));
174 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
175 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
176 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
177
178 deadline.setPreciseDeadline(secs: std::numeric_limits<qint64>::max(), nsecs: 0, type: timerType);
179 QVERIFY(deadline.isForever());
180 QVERIFY(!deadline.hasExpired());
181 QCOMPARE(deadline.remainingTime(), qint64(-1));
182 QCOMPARE(deadline.remainingTimeNSecs(), qint64(-1));
183 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
184 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
185
186 QCOMPARE(deadline, deadline);
187 QVERIFY(!(deadline < deadline));
188 QVERIFY(deadline <= deadline);
189 QVERIFY(deadline >= deadline);
190 QVERIFY(!(deadline > deadline));
191
192 // adding to forever must still be forever
193 QDeadlineTimer deadline2 = deadline + 1;
194 QVERIFY(deadline2.isForever());
195 QVERIFY(!deadline2.hasExpired());
196 QCOMPARE(deadline2.remainingTime(), qint64(-1));
197 QCOMPARE(deadline2.remainingTimeNSecs(), qint64(-1));
198 QCOMPARE(deadline2.deadline(), std::numeric_limits<qint64>::max());
199 QCOMPARE(deadline2.deadlineNSecs(), std::numeric_limits<qint64>::max());
200 QCOMPARE(deadline2.timerType(), deadline.timerType());
201
202 QCOMPARE(deadline2 - deadline, qint64(0));
203 QCOMPARE(deadline2, deadline);
204 QVERIFY(!(deadline2 < deadline));
205 QVERIFY(deadline2 <= deadline);
206 QVERIFY(deadline2 >= deadline);
207 QVERIFY(!(deadline2 > deadline));
208
209 // subtracting from forever is *also* forever
210 deadline2 = deadline - 1;
211 QVERIFY(deadline2.isForever());
212 QVERIFY(!deadline2.hasExpired());
213 QCOMPARE(deadline2.remainingTime(), qint64(-1));
214 QCOMPARE(deadline2.remainingTimeNSecs(), qint64(-1));
215 QCOMPARE(deadline2.deadline(), std::numeric_limits<qint64>::max());
216 QCOMPARE(deadline2.deadlineNSecs(), std::numeric_limits<qint64>::max());
217 QCOMPARE(deadline2.timerType(), deadline.timerType());
218
219 QCOMPARE(deadline2 - deadline, qint64(0));
220 QCOMPARE(deadline2, deadline);
221 QVERIFY(!(deadline2 < deadline));
222 QVERIFY(deadline2 <= deadline);
223 QVERIFY(deadline2 >= deadline);
224 QVERIFY(!(deadline2 > deadline));
225
226 // compare and order against a default-constructed object
227 QDeadlineTimer expired;
228 QVERIFY(!(deadline == expired));
229 QVERIFY(deadline != expired);
230 QVERIFY(!(deadline < expired));
231 QVERIFY(!(deadline <= expired));
232 QVERIFY(deadline >= expired);
233 QVERIFY(deadline > expired);
234}
235
236void tst_QDeadlineTimer::current()
237{
238 QFETCH_GLOBAL(Qt::TimerType, timerType);
239 auto deadline = QDeadlineTimer::current(timerType);
240 QVERIFY(deadline.hasExpired());
241 QVERIFY(!deadline.isForever());
242 QCOMPARE(deadline.timerType(), timerType);
243 QCOMPARE(deadline.remainingTime(), qint64(0));
244 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
245 QVERIFY(deadline.deadline() != 0);
246 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
247 QVERIFY(deadline.deadlineNSecs() != 0);
248 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
249
250 // subtracting from current should be "more expired"
251 QDeadlineTimer earlierDeadline = deadline - 1;
252 QVERIFY(earlierDeadline.hasExpired());
253 QVERIFY(!earlierDeadline.isForever());
254 QCOMPARE(earlierDeadline.timerType(), timerType);
255 QCOMPARE(earlierDeadline.remainingTime(), qint64(0));
256 QCOMPARE(earlierDeadline.remainingTimeNSecs(), qint64(0));
257 QVERIFY(earlierDeadline.deadline() != 0);
258 QVERIFY(earlierDeadline.deadline() != std::numeric_limits<qint64>::max());
259 QVERIFY(earlierDeadline.deadlineNSecs() != 0);
260 QVERIFY(earlierDeadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
261 QCOMPARE(earlierDeadline.deadline(), deadline.deadline() - 1);
262 QCOMPARE(earlierDeadline.deadlineNSecs(), deadline.deadlineNSecs() - 1000*1000);
263
264 QCOMPARE(earlierDeadline - deadline, qint64(-1));
265 QVERIFY(earlierDeadline != deadline);
266 QVERIFY(earlierDeadline < deadline);
267 QVERIFY(earlierDeadline <= deadline);
268 QVERIFY(!(earlierDeadline >= deadline));
269 QVERIFY(!(earlierDeadline > deadline));
270}
271
272void tst_QDeadlineTimer::deadlines()
273{
274 QFETCH_GLOBAL(Qt::TimerType, timerType);
275
276 QDeadlineTimer deadline(4 * minResolution, timerType);
277 QVERIFY(!deadline.hasExpired());
278 QVERIFY(!deadline.isForever());
279 QCOMPARE(deadline.timerType(), timerType);
280 QVERIFY(deadline.remainingTime() > (3 * minResolution));
281 QVERIFY(deadline.remainingTime() <= (4 * minResolution));
282 QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
283 QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
284 QVERIFY(deadline.deadline() != 0);
285 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
286 QVERIFY(deadline.deadlineNSecs() != 0);
287 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
288
289 deadline.setRemainingTime(msecs: 4 * minResolution, type: timerType);
290 QVERIFY(!deadline.hasExpired());
291 QVERIFY(!deadline.isForever());
292 QCOMPARE(deadline.timerType(), timerType);
293 QVERIFY(deadline.remainingTime() > (3 * minResolution));
294 QVERIFY(deadline.remainingTime() <= (4 * minResolution));
295 QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
296 QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
297 QVERIFY(deadline.deadline() != 0);
298 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
299 QVERIFY(deadline.deadlineNSecs() != 0);
300 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
301
302 deadline.setPreciseRemainingTime(secs: 0, nsecs: 4000000 * minResolution, type: timerType);
303 QVERIFY(!deadline.hasExpired());
304 QVERIFY(!deadline.isForever());
305 QCOMPARE(deadline.timerType(), timerType);
306 QVERIFY(deadline.remainingTime() > (3 * minResolution));
307 QVERIFY(deadline.remainingTime() <= (4 * minResolution));
308 QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
309 QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
310 QVERIFY(deadline.deadline() != 0);
311 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
312 QVERIFY(deadline.deadlineNSecs() != 0);
313 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
314
315 deadline.setPreciseRemainingTime(secs: 1, nsecs: 0, type: timerType); // 1 sec
316 QVERIFY(!deadline.hasExpired());
317 QVERIFY(!deadline.isForever());
318 QCOMPARE(deadline.timerType(), timerType);
319 QVERIFY(deadline.remainingTime() > (1000 - minResolution));
320 QVERIFY(deadline.remainingTime() <= 1000);
321 QVERIFY(deadline.remainingTimeNSecs() > (1000 - minResolution)*1000*1000);
322 QVERIFY(deadline.remainingTimeNSecs() <= (1000*1000*1000));
323 QVERIFY(deadline.deadline() != 0);
324 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
325 QVERIFY(deadline.deadlineNSecs() != 0);
326 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
327
328 // adding to a future deadline must still be further in the future
329 QDeadlineTimer laterDeadline = deadline + 1;
330 QVERIFY(!laterDeadline.hasExpired());
331 QVERIFY(!laterDeadline.isForever());
332 QCOMPARE(laterDeadline.timerType(), timerType);
333 QVERIFY(laterDeadline.remainingTime() > (1000 - minResolution));
334 QVERIFY(laterDeadline.remainingTime() <= 1001);
335 QVERIFY(laterDeadline.remainingTimeNSecs() > (1001 - minResolution)*1000*1000);
336 QVERIFY(laterDeadline.remainingTimeNSecs() <= (1001*1000*1000));
337 QVERIFY(laterDeadline.deadline() != 0);
338 QVERIFY(laterDeadline.deadline() != std::numeric_limits<qint64>::max());
339 QVERIFY(laterDeadline.deadlineNSecs() != 0);
340 QVERIFY(laterDeadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
341 QCOMPARE(laterDeadline.deadline(), deadline.deadline() + 1);
342 QCOMPARE(laterDeadline.deadlineNSecs(), deadline.deadlineNSecs() + 1000*1000);
343
344 QCOMPARE(laterDeadline - deadline, qint64(1));
345 QVERIFY(laterDeadline != deadline);
346 QVERIFY(!(laterDeadline < deadline));
347 QVERIFY(!(laterDeadline <= deadline));
348 QVERIFY(laterDeadline >= deadline);
349 QVERIFY(laterDeadline > deadline);
350
351 // compare and order against a default-constructed object
352 QDeadlineTimer expired;
353 QVERIFY(!(deadline == expired));
354 QVERIFY(deadline != expired);
355 QVERIFY(!(deadline < expired));
356 QVERIFY(!(deadline <= expired));
357 QVERIFY(deadline >= expired);
358 QVERIFY(deadline > expired);
359
360 // compare and order against a forever deadline
361 QDeadlineTimer forever_(QDeadlineTimer::Forever);
362 QVERIFY(!(deadline == forever_));
363 QVERIFY(deadline != forever_);
364 QVERIFY(deadline < forever_);
365 QVERIFY(deadline <= forever_);
366 QVERIFY(!(deadline >= forever_));
367 QVERIFY(!(deadline > forever_));
368}
369
370void tst_QDeadlineTimer::setDeadline()
371{
372 QFETCH_GLOBAL(Qt::TimerType, timerType);
373 auto now = QDeadlineTimer::current(timerType);
374 QDeadlineTimer deadline;
375
376 deadline.setDeadline(msecs: now.deadline(), timerType);
377 QVERIFY(deadline.hasExpired());
378 QVERIFY(!deadline.isForever());
379 QCOMPARE(deadline.timerType(), timerType);
380 QCOMPARE(deadline.remainingTime(), qint64(0));
381 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
382 QCOMPARE(deadline.deadline(), now.deadline());
383 // don't check deadlineNSecs!
384
385 deadline.setPreciseDeadline(secs: now.deadlineNSecs() / (1000 * 1000 * 1000),
386 nsecs: now.deadlineNSecs() % (1000 * 1000 * 1000), type: timerType);
387 QVERIFY(deadline.hasExpired());
388 QVERIFY(!deadline.isForever());
389 QCOMPARE(deadline.timerType(), timerType);
390 QCOMPARE(deadline.remainingTime(), qint64(0));
391 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
392 QCOMPARE(deadline.deadline(), now.deadline());
393 QCOMPARE(deadline.deadlineNSecs(), now.deadlineNSecs());
394
395 now = QDeadlineTimer::current(timerType);
396 deadline.setDeadline(msecs: now.deadline() + 4 * minResolution, timerType);
397 QVERIFY(!deadline.hasExpired());
398 QVERIFY(!deadline.isForever());
399 QCOMPARE(deadline.timerType(), timerType);
400 QVERIFY(deadline.remainingTime() > (3 * minResolution));
401 QVERIFY(deadline.remainingTime() <= (4 * minResolution));
402 QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
403 QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
404 QCOMPARE(deadline.deadline(), now.deadline() + 4 * minResolution); // yes, it's exact
405 // don't check deadlineNSecs!
406
407 now = QDeadlineTimer::current(timerType);
408 qint64 nsec = now.deadlineNSecs() + 4000000 * minResolution;
409 deadline.setPreciseDeadline(secs: nsec / (1000 * 1000 * 1000),
410 nsecs: nsec % (1000 * 1000 * 1000), type: timerType);
411 QVERIFY(!deadline.hasExpired());
412 QVERIFY(!deadline.isForever());
413 QCOMPARE(deadline.timerType(), timerType);
414 QVERIFY(deadline.remainingTime() > (3 * minResolution));
415 QVERIFY(deadline.remainingTime() <= (4 * minResolution));
416 QVERIFY(deadline.remainingTimeNSecs() > (3000000 * minResolution));
417 QVERIFY(deadline.remainingTimeNSecs() <= (4000000 * minResolution));
418 QCOMPARE(deadline.deadline(), nsec / (1000 * 1000));
419 QCOMPARE(deadline.deadlineNSecs(), nsec);
420}
421
422void tst_QDeadlineTimer::overflow()
423{
424 QFETCH_GLOBAL(Qt::TimerType, timerType);
425 // Check the constructor for overflows (should also cover saturating the result of the deadline() method if overflowing)
426 QDeadlineTimer now = QDeadlineTimer::current(timerType), deadline(std::numeric_limits<qint64>::max() - 1, timerType);
427 QVERIFY(deadline.isForever() || deadline.deadline() >= now.deadline());
428
429 // Check the setDeadline with milliseconds (should also cover implicitly setting the nanoseconds as qint64 max)
430 deadline.setDeadline(msecs: std::numeric_limits<qint64>::max() - 1, timerType);
431 QVERIFY(deadline.isForever() || deadline.deadline() >= now.deadline());
432
433 // Check the setRemainingTime with milliseconds (should also cover implicitly setting the nanoseconds as qint64 max)
434 deadline.setRemainingTime(msecs: std::numeric_limits<qint64>::max() - 1, type: timerType);
435 QVERIFY(deadline.isForever() || deadline.deadline() >= now.deadline());
436
437 // Check that the deadline gets saturated when the arguments of setPreciseDeadline are large
438 deadline.setPreciseDeadline(secs: std::numeric_limits<qint64>::max() - 1, nsecs: std::numeric_limits<qint64>::max() - 1, type: timerType);
439 QCOMPARE(deadline.deadline(), std::numeric_limits<qint64>::max());
440 QVERIFY(deadline.isForever());
441
442 // Check that remainingTime gets saturated if we overflow
443 deadline.setPreciseRemainingTime(secs: std::numeric_limits<qint64>::max() - 1, nsecs: std::numeric_limits<qint64>::max() - 1, type: timerType);
444 QCOMPARE(deadline.remainingTime(), qint64(-1));
445 QVERIFY(deadline.isForever());
446
447 // Check that we saturate the getter for nanoseconds
448 deadline.setPreciseDeadline(secs: std::numeric_limits<qint64>::max() - 1, nsecs: 0, type: timerType);
449 QCOMPARE(deadline.deadlineNSecs(), std::numeric_limits<qint64>::max());
450
451 // Check that adding nanoseconds and overflowing is consistent and saturates the timer
452 deadline = QDeadlineTimer::addNSecs(dt: deadline, nsecs: std::numeric_limits<qint64>::max() - 1);
453 QVERIFY(deadline.isForever());
454
455 // Make sure forever is forever, regardless of us subtracting time from it
456 deadline = QDeadlineTimer(QDeadlineTimer::Forever, timerType);
457 deadline = QDeadlineTimer::addNSecs(dt: deadline, nsecs: -10000);
458 QVERIFY(deadline.isForever());
459
460 // Make sure we get the correct result when moving the deadline back and forth in time
461 QDeadlineTimer current = QDeadlineTimer::current(timerType);
462 QDeadlineTimer takenNSecs = QDeadlineTimer::addNSecs(dt: current, nsecs: -1000);
463 QVERIFY(takenNSecs.deadlineNSecs() - current.deadlineNSecs() == -1000);
464 QDeadlineTimer addedNSecs = QDeadlineTimer::addNSecs(dt: current, nsecs: 1000);
465 QVERIFY(addedNSecs.deadlineNSecs() - current.deadlineNSecs() == 1000);
466
467 // Make sure the calculation goes as expected when we need to subtract nanoseconds
468 // We make use of an additional timer to be certain that
469 // even when the environment is under load we can track the
470 // time needed to do the calls
471 static constexpr qint64 nsExpected = 1000 * 1000 * 1000 - 1000; // 1s - 1000ns, what we pass to setPreciseRemainingTime() later
472
473 QElapsedTimer callTimer;
474 callTimer.start();
475
476 deadline = QDeadlineTimer::current(timerType);
477 qint64 nsDeadline = deadline.deadlineNSecs();
478 // We adjust in relation to current() here, so we expect the difference to be a tad over the exact number.
479 // However we are tracking the elapsed time, so it shouldn't be a problem.
480 deadline.setPreciseRemainingTime(secs: 1, nsecs: -1000, type: timerType);
481 qint64 difference = (deadline.deadlineNSecs() - nsDeadline) - nsExpected;
482 QVERIFY(difference >= 0); // Should always be true, but just in case
483 QVERIFY(difference <= callTimer.nsecsElapsed()); // Ideally difference should be 0 exactly
484
485 // Make sure setRemainingTime underflows gracefully
486 deadline.setPreciseRemainingTime(secs: std::numeric_limits<qint64>::min() / 10, nsecs: 0, type: timerType);
487 QVERIFY(!deadline.isForever()); // On Win/macOS the above underflows, make sure we don't saturate to Forever
488 QVERIFY(deadline.remainingTime() == 0);
489 // If the timer is saturated we don't want to get a valid number of milliseconds
490 QVERIFY(deadline.deadline() == std::numeric_limits<qint64>::min());
491
492 // Check that the conversion to milliseconds and nanoseconds underflows gracefully
493 deadline.setPreciseDeadline(secs: std::numeric_limits<qint64>::min() / 10, nsecs: 0, type: timerType);
494 QVERIFY(!deadline.isForever()); // On Win/macOS the above underflows, make sure we don't saturate to Forever
495 QVERIFY(deadline.deadline() == std::numeric_limits<qint64>::min());
496 QVERIFY(deadline.deadlineNSecs() == std::numeric_limits<qint64>::min());
497}
498
499void tst_QDeadlineTimer::expire()
500{
501 QFETCH_GLOBAL(Qt::TimerType, timerType);
502
503 QDeadlineTimer deadline(minResolution, timerType);
504 QVERIFY(!deadline.hasExpired());
505 QVERIFY(!deadline.isForever());
506
507 qint64 previousDeadline = deadline.deadlineNSecs();
508
509 QTest::qSleep(ms: 2 * minResolution);
510
511 QCOMPARE(deadline.remainingTime(), qint64(0));
512 QCOMPARE(deadline.remainingTimeNSecs(), qint64(0));
513 QVERIFY(deadline.deadline() != 0);
514 QVERIFY(deadline.deadline() != std::numeric_limits<qint64>::max());
515 QVERIFY(deadline.deadlineNSecs() != 0);
516 QVERIFY(deadline.deadlineNSecs() != std::numeric_limits<qint64>::max());
517 QCOMPARE(deadline.deadlineNSecs(), previousDeadline);
518}
519
520void tst_QDeadlineTimer::stdchrono()
521{
522#if !__has_include(<chrono>)
523 QSKIP("std::chrono not found on this system");
524#else
525 using namespace std::chrono;
526 QFETCH_GLOBAL(Qt::TimerType, timerType);
527
528 // create some forevers
529 QDeadlineTimer deadline = milliseconds::max();
530 QVERIFY(deadline.isForever());
531 deadline = milliseconds::max();
532 QVERIFY(deadline.isForever());
533 deadline.setRemainingTime(remaining: milliseconds::max(), type_: timerType);
534 QVERIFY(deadline.isForever());
535 QCOMPARE(deadline.timerType(), timerType);
536 deadline = nanoseconds::max();
537 QVERIFY(deadline.isForever());
538 deadline.setRemainingTime(remaining: nanoseconds::max(), type_: timerType);
539 QVERIFY(deadline.isForever());
540 QCOMPARE(deadline.timerType(), timerType);
541 deadline = hours::max();
542 QVERIFY(deadline.isForever());
543 deadline.setRemainingTime(remaining: hours::max(), type_: timerType);
544 QVERIFY(deadline.isForever());
545 QCOMPARE(deadline.timerType(), timerType);
546
547 deadline = time_point<system_clock>::max();
548 QVERIFY(deadline.isForever());
549 deadline.setDeadline(deadline_: time_point<system_clock>::max(), type_: timerType);
550 QVERIFY(deadline.isForever());
551 QCOMPARE(deadline.timerType(), timerType);
552 deadline = time_point<steady_clock>::max();
553 QVERIFY(deadline.isForever());
554 deadline.setDeadline(deadline_: time_point<steady_clock>::max(), type_: timerType);
555 QVERIFY(deadline.isForever());
556 QCOMPARE(deadline.timerType(), timerType);
557
558 QVERIFY(deadline == time_point<steady_clock>::max());
559 QVERIFY(deadline == time_point<system_clock>::max());
560 QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::max());
561
562 // make it expired
563 deadline = time_point<system_clock>();
564 QVERIFY(deadline.hasExpired());
565 deadline.setDeadline(deadline_: time_point<system_clock>(), type_: timerType);
566 QVERIFY(deadline.hasExpired());
567 QCOMPARE(deadline.timerType(), timerType);
568 deadline = time_point<steady_clock>();
569 QVERIFY(deadline.hasExpired());
570 deadline.setDeadline(deadline_: time_point<steady_clock>(), type_: timerType);
571 QVERIFY(deadline.hasExpired());
572 QCOMPARE(deadline.timerType(), timerType);
573
574 QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero());
575
576 /*
577 Call QTest::qSleep, and return true if the time actually slept is
578 within \a deviationPercent percent of the requested sleep time.
579 Otherwise, return false, in which case the test should to abort.
580 */
581 auto sleepHelper = [](int ms, int deviationPercent = 10) -> bool {
582 auto before = steady_clock::now();
583 QTest::qSleep(ms);
584 auto after = steady_clock::now();
585 auto diff = duration_cast<milliseconds>(d: after - before).count();
586 bool inRange = qAbs(t: diff - ms) < ms * deviationPercent/100.0;
587 if (!inRange)
588 qWarning() << "sleeping" << diff << "instead of" << ms << inRange;
589 return inRange;
590 };
591
592 auto steady_before = steady_clock::now();
593 auto system_before = system_clock::now();
594
595 if (!sleepHelper(minResolution))
596 QSKIP("Slept too long");
597 auto now = QDeadlineTimer::current(timerType);
598 auto steady_reference = steady_clock::now();
599 auto system_reference = system_clock::now();
600 if (!sleepHelper(minResolution))
601 QSKIP("Slept too long");
602
603 auto sampling_start = steady_clock::now();
604 auto steady_deadline = now.deadline<steady_clock>();
605 auto system_deadline = now.deadline<system_clock>();
606 auto steady_after = steady_clock::now();
607 auto system_after = system_clock::now();
608 auto sampling_end = steady_clock::now();
609
610 auto sampling_diff = duration_cast<milliseconds>(d: sampling_end - sampling_start).count();
611 if (sampling_diff > minResolution/2) {
612 qWarning() << "Sampling clock took" << sampling_diff << "ms";
613 QSKIP("Sampling clock took too long, aborting test", Abort);
614 }
615 auto total_diff = duration_cast<milliseconds>(d: steady_after - steady_before).count();
616 if (total_diff >= 3*minResolution) {
617 qWarning() << "Measurement took" << total_diff << "ms";
618 QSKIP("Measurement took too long, aborting test", Abort);
619 }
620
621 {
622 auto reference = duration_cast<milliseconds>(d: steady_after - steady_reference).count();
623 auto diff = duration_cast<milliseconds>(d: steady_after - steady_deadline).count();
624 QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
625 QDeadlineTimer dt_after(steady_after, timerType);
626 QVERIFY2(now < dt_after,
627 ("now = " + QLocale().toString(now.deadlineNSecs()) +
628 "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
629
630 reference = duration_cast<milliseconds>(d: steady_reference - steady_before).count();
631 diff = duration_cast<milliseconds>(d: steady_deadline - steady_before).count();
632 QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
633 QDeadlineTimer dt_before(steady_before, timerType);
634 QVERIFY2(now > dt_before,
635 ("now = " + QLocale().toString(now.deadlineNSecs()) +
636 "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
637 }
638 {
639 auto reference = duration_cast<milliseconds>(d: system_after - system_reference).count();
640 auto diff = duration_cast<milliseconds>(d: system_after - system_deadline).count();
641 QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType);
642 QVERIFY2(now < dt_after,
643 ("now = " + QLocale().toString(now.deadlineNSecs()) +
644 "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
645
646 reference = duration_cast<milliseconds>(d: system_reference - system_before).count();
647 diff = duration_cast<milliseconds>(d: steady_deadline - steady_before).count();
648 QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType);
649 QVERIFY2(now > dt_before,
650 ("now = " + QLocale().toString(now.deadlineNSecs()) +
651 "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
652 }
653
654 // make it regular
655 now = QDeadlineTimer::current(timerType);
656 deadline.setRemainingTime(remaining: milliseconds(4 * minResolution), type_: timerType);
657 QVERIFY(!deadline.hasExpired());
658 QVERIFY(!deadline.isForever());
659 QCOMPARE(deadline.timerType(), timerType);
660 QVERIFY(deadline.remainingTimeAsDuration() > milliseconds(3 * minResolution));
661 QVERIFY(deadline.remainingTimeAsDuration() < milliseconds(5 * minResolution));
662 QVERIFY(deadline.remainingTimeAsDuration() > nanoseconds(3000000 * minResolution));
663 QVERIFY(deadline.remainingTimeAsDuration() < nanoseconds(5000000 * minResolution));
664 QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + milliseconds(3 * minResolution)));
665 QVERIFY(deadline.deadline<steady_clock>() < (steady_clock::now() + milliseconds(5 * minResolution)));
666 QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + milliseconds(3 * minResolution)));
667 QVERIFY(deadline.deadline<system_clock>() < (system_clock::now() + milliseconds(5 * minResolution)));
668 if (timerType == Qt::CoarseTimer) {
669 QVERIFY(deadline > (now + milliseconds(3 * minResolution)));
670 QVERIFY(deadline < (now + milliseconds(5 * minResolution)));
671 QVERIFY(deadline > (now + nanoseconds(3000000 * minResolution)));
672 QVERIFY(deadline < (now + nanoseconds(5000000 * minResolution)));
673 QVERIFY(deadline > milliseconds(3 * minResolution));
674 QVERIFY(deadline < milliseconds(5 * minResolution));
675 QVERIFY(deadline > nanoseconds(3000000 * minResolution));
676 QVERIFY(deadline < nanoseconds(5000000 * minResolution));
677 QVERIFY(deadline >= steady_clock::now());
678 QVERIFY(deadline >= system_clock::now());
679 }
680
681 now = QDeadlineTimer::current(timerType);
682 deadline = QDeadlineTimer(seconds(1), timerType);
683 QVERIFY(!deadline.hasExpired());
684 QVERIFY(!deadline.isForever());
685 QCOMPARE(deadline.timerType(), timerType);
686 QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution)));
687 QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1));
688 QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
689 QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
690 QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
691 QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
692 if (timerType == Qt::CoarseTimer) {
693 QVERIFY(deadline > (seconds(1) - milliseconds(minResolution)));
694 QVERIFY(deadline <= seconds(1));
695 }
696
697 now = QDeadlineTimer::current(timerType);
698 deadline.setRemainingTime(remaining: hours(1), type_: timerType);
699 QVERIFY(!deadline.hasExpired());
700 QVERIFY(!deadline.isForever());
701 QCOMPARE(deadline.timerType(), timerType);
702 QVERIFY(deadline.remainingTimeAsDuration() > (hours(1) - milliseconds(minResolution)));
703 QVERIFY(deadline.remainingTimeAsDuration() <= hours(1));
704 QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + hours(1) - milliseconds(minResolution)));
705 QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + hours(1) + milliseconds(minResolution)));
706 QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + hours(1) - milliseconds(minResolution)));
707 QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + hours(1) + milliseconds(minResolution)));
708
709 now = QDeadlineTimer::current(timerType);
710 deadline.setDeadline(deadline_: system_clock::now() + seconds(1), type_: timerType);
711 QVERIFY(!deadline.hasExpired());
712 QVERIFY(!deadline.isForever());
713 QCOMPARE(deadline.timerType(), timerType);
714 QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution)));
715 QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1));
716 QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
717 QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
718 QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
719 QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
720
721 now = QDeadlineTimer::current(timerType);
722 deadline.setDeadline(deadline_: steady_clock::now() + seconds(1), type_: timerType);
723 QVERIFY(!deadline.hasExpired());
724 QVERIFY(!deadline.isForever());
725 QCOMPARE(deadline.timerType(), timerType);
726 QVERIFY(deadline.remainingTimeAsDuration() > (seconds(1) - milliseconds(minResolution)));
727 QVERIFY(deadline.remainingTimeAsDuration() <= seconds(1));
728 QVERIFY(deadline.deadline<steady_clock>() > (steady_clock::now() + seconds(1) - milliseconds(minResolution)));
729 QVERIFY(deadline.deadline<steady_clock>() <= (steady_clock::now() + seconds(1) + milliseconds(minResolution)));
730 QVERIFY(deadline.deadline<system_clock>() > (system_clock::now() + seconds(1) - milliseconds(minResolution)));
731 QVERIFY(deadline.deadline<system_clock>() <= (system_clock::now() + seconds(1) + milliseconds(minResolution)));
732#endif
733}
734
735QTEST_MAIN(tst_QDeadlineTimer)
736
737#include "tst_qdeadlinetimer.moc"
738

source code of qtbase/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp