File indexing completed on 2025-09-17 09:11:37
0001
0002
0003
0004 #ifndef QTESTEVENTLOOP_H
0005 #define QTESTEVENTLOOP_H
0006
0007 #include <QtTest/qttestglobal.h>
0008 #include <QtTest/qtestcase.h>
0009
0010 #include <QtCore/qbasictimer.h>
0011 #include <QtCore/qcoreapplication.h>
0012 #include <QtCore/qeventloop.h>
0013 #include <QtCore/qobject.h>
0014 #include <QtCore/qpointer.h>
0015 #include <QtCore/qthread.h>
0016
0017 QT_BEGIN_NAMESPACE
0018
0019
0020 class Q_TESTLIB_EXPORT QTestEventLoop : public QObject
0021 {
0022 Q_OBJECT
0023
0024 public:
0025 QTestEventLoop(QObject *parent = nullptr)
0026 : QObject(parent), _timeout(false)
0027 {}
0028
0029 void enterLoopMSecs(int ms) { enterLoop(std::chrono::milliseconds{ms}); }
0030 void enterLoop(int secs) { enterLoop(std::chrono::seconds{secs}); }
0031 inline void enterLoop(std::chrono::milliseconds msecs);
0032
0033 inline void changeInterval(int secs)
0034 { changeInterval(std::chrono::seconds{secs}); }
0035
0036 void changeInterval(std::chrono::nanoseconds nsecs)
0037 { timer.start(nsecs, this); }
0038
0039 inline bool timeout() const
0040 { return _timeout; }
0041
0042 inline static QTestEventLoop &instance()
0043 {
0044 Q_CONSTINIT static QPointer<QTestEventLoop> testLoop;
0045 if (testLoop.isNull())
0046 testLoop = new QTestEventLoop(QCoreApplication::instance());
0047 return *static_cast<QTestEventLoop *>(testLoop);
0048 }
0049
0050 public Q_SLOTS:
0051 inline void exitLoop();
0052
0053 protected:
0054 inline void timerEvent(QTimerEvent *e) override;
0055
0056 private:
0057 QEventLoop *loop = nullptr;
0058 QBasicTimer timer;
0059 uint _timeout :1;
0060 Q_DECL_UNUSED_MEMBER uint reserved :31;
0061 };
0062
0063 inline void QTestEventLoop::enterLoop(std::chrono::milliseconds msecs)
0064 {
0065 Q_ASSERT(!loop);
0066 _timeout = false;
0067
0068 if (QTest::runningTest() && QTest::currentTestResolved())
0069 return;
0070
0071 using namespace std::chrono_literals;
0072 QEventLoop l;
0073
0074 timer.start(msecs, msecs < 1s ? Qt::PreciseTimer : Qt::CoarseTimer, this);
0075
0076 loop = &l;
0077 l.exec();
0078 loop = nullptr;
0079 }
0080
0081 inline void QTestEventLoop::exitLoop()
0082 {
0083 if (thread() != QThread::currentThread())
0084 {
0085 QMetaObject::invokeMethod(this, "exitLoop", Qt::QueuedConnection);
0086 return;
0087 }
0088
0089 timer.stop();
0090
0091 if (loop)
0092 loop->exit();
0093 }
0094
0095 inline void QTestEventLoop::timerEvent(QTimerEvent *e)
0096 {
0097 if (e->id() != timer.id())
0098 return;
0099 _timeout = true;
0100 exitLoop();
0101 }
0102
0103 QT_END_NAMESPACE
0104
0105 #endif