Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtesteventloop.h
Go to the documentation of this file.
1// Copyright (C) 2021 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#ifndef QTESTEVENTLOOP_H
5#define QTESTEVENTLOOP_H
6
7#include <QtTest/qttestglobal.h>
8#include <QtTest/qtestcase.h>
9
10#include <QtCore/qbasictimer.h>
11#include <QtCore/qcoreapplication.h>
12#include <QtCore/qeventloop.h>
13#include <QtCore/qobject.h>
14#include <QtCore/qpointer.h>
15#include <QtCore/qthread.h>
16
18
19
20class Q_TESTLIB_EXPORT QTestEventLoop : public QObject
21{
22 Q_OBJECT
23
24public:
25 QTestEventLoop(QObject *parent = nullptr)
26 : QObject(parent), _timeout(false)
27 {}
28
29 void enterLoopMSecs(int ms) { enterLoop(std::chrono::milliseconds{ms}); }
30 void enterLoop(int secs) { enterLoop(std::chrono::seconds{secs}); }
31 inline void enterLoop(std::chrono::milliseconds msecs);
32
33 inline void changeInterval(int secs)
34 { changeInterval(std::chrono::seconds{secs}); }
35
36 void changeInterval(std::chrono::nanoseconds nsecs)
37 { timer.start(nsecs, this); }
38
39 inline bool timeout() const
40 { return _timeout; }
41
42 inline static QTestEventLoop &instance()
43 {
44 Q_CONSTINIT static QPointer<QTestEventLoop> testLoop;
45 if (testLoop.isNull())
46 testLoop = new QTestEventLoop(QCoreApplication::instance());
47 return *static_cast<QTestEventLoop *>(testLoop);
48 }
49
50public Q_SLOTS:
51 inline void exitLoop();
52
53protected:
54 inline void timerEvent(QTimerEvent *e) override;
55
56private:
57 QEventLoop *loop = nullptr;
58 QBasicTimer timer;
59 uint _timeout :1;
60 Q_DECL_UNUSED_MEMBER uint reserved :31;
61};
62
63inline void QTestEventLoop::enterLoop(std::chrono::milliseconds msecs)
64{
65 Q_ASSERT(!loop);
66 _timeout = false;
67
68 if (QTest::runningTest() && QTest::currentTestResolved())
69 return;
70
71 using namespace std::chrono_literals;
72 QEventLoop l;
73 // if tests want to measure sub-second precision, use a precise timer
74 timer.start(msecs, msecs < 1s ? Qt::PreciseTimer : Qt::CoarseTimer, this);
75
76 loop = &l;
77 l.exec();
78 loop = nullptr;
79}
80
81inline void QTestEventLoop::exitLoop()
82{
83 if (thread() != QThread::currentThread())
84 {
85 QMetaObject::invokeMethod(this, "exitLoop", Qt::QueuedConnection);
86 return;
87 }
88
89 timer.stop();
90
91 if (loop)
92 loop->exit();
93}
94
95inline void QTestEventLoop::timerEvent(QTimerEvent *e)
96{
97 if (e->id() != timer.id())
98 return;
99 _timeout = true;
100 exitLoop();
101}
102
103QT_END_NAMESPACE
104
105#endif