File indexing completed on 2024-05-12 05:52:46
0001 /* 0002 * SPDX-License-Identifier: GPL-3.0-or-later 0003 * SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com> 0004 */ 0005 #include "account/actions_p.h" 0006 0007 #include "../test-utils/spy.h" 0008 0009 #include <QSignalSpy> 0010 #include <QTest> 0011 #include <QTimer> 0012 #include <QtDebug> 0013 0014 class TestJob: public accounts::AccountJob // clazy:exclude=ctor-missing-parent-argument 0015 { 0016 Q_OBJECT 0017 public: 0018 ~TestJob() 0019 { 0020 qDebug() << "TestJob is being destroyed on thread:" << QThread::currentThread() << "should be:" << thread(); 0021 } 0022 0023 public Q_SLOTS: 0024 void run(void) override 0025 { 0026 Q_EMIT finished(); 0027 qDebug() << "Did finish on thread:" << QThread::currentThread() << "should be:" << thread(); 0028 qDebug() << "Current thread should NOT be finished, check:" << (QThread::currentThread()->isFinished() == false); 0029 } 0030 }; 0031 0032 class DispatchTest: public QObject // clazy:exclude=ctor-missing-parent-argument 0033 { 0034 Q_OBJECT 0035 private Q_SLOTS: 0036 void liveDispatch(void); 0037 void coldDispatch(void); 0038 }; 0039 0040 /* 0041 * Test whether queueing jobs up-front before actually starting a worker thread works, 0042 * i.e. whether the job is automatically dispatched once the worker thread starts 0043 */ 0044 void DispatchTest::coldDispatch(void) 0045 { 0046 0047 QThread *thread = new QThread(this); 0048 QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); 0049 0050 QSignalSpy threadStarted(thread, &QThread::started); 0051 QSignalSpy threadFinished(thread, &QThread::finished); 0052 QSignalSpy threadCleaned(thread, &QThread::destroyed); 0053 0054 accounts::Dispatcher *uut = new accounts::Dispatcher(thread); 0055 QSignalSpy dispatcherDispatched(uut, &accounts::Dispatcher::dispatch); 0056 QSignalSpy dispatcherCleaned(uut, &accounts::Dispatcher::destroyed); 0057 0058 TestJob *job = new TestJob(); 0059 QSignalSpy jobFinished(job, &TestJob::finished); 0060 QSignalSpy jobCleaned(job, &TestJob::destroyed); 0061 0062 bool jobCallBackCalled = false; 0063 uut->queueAndProceed(job, [job, thread, &jobCallBackCalled](void) -> void 0064 { 0065 QCOMPARE(job->thread(), thread); 0066 jobCallBackCalled = true; 0067 }); 0068 QVERIFY2(jobCallBackCalled, "signal setup call back should have been called for job"); 0069 0070 qDebug() << "About to start thread:" << thread; 0071 thread->start(); 0072 QVERIFY2(test::signal_eventually_emitted_once(threadStarted), "worker thread should have started by now"); 0073 0074 QVERIFY2(test::signal_eventually_emitted_once(dispatcherDispatched), "dispatcher should have dispatched the job by now"); 0075 QVERIFY2(test::signal_eventually_emitted_once(jobFinished), "job should be finished by now"); 0076 QVERIFY2(test::signal_eventually_emitted_once(jobCleaned), "job should be disposed of by now"); 0077 0078 QTimer::singleShot(0, thread, &QThread::quit); 0079 QVERIFY2(test::signal_eventually_emitted_once(threadFinished), "worker thread should be finished by now"); 0080 QVERIFY2(test::signal_eventually_emitted_once(threadCleaned), "thread should be disposed of by now"); 0081 0082 uut->deleteLater(); 0083 QVERIFY2(test::signal_eventually_emitted_once(dispatcherCleaned), "dispatcher should be disposed of by now"); 0084 } 0085 0086 /* 0087 * Test whether queueing jobs works while a worker thread is running already, 0088 * i.e. whether the job is dispatched straight away. 0089 */ 0090 void DispatchTest::liveDispatch(void) 0091 { 0092 QThread *thread = new QThread(this); 0093 QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); 0094 0095 QSignalSpy threadStarted(thread, &QThread::started); 0096 QSignalSpy threadFinished(thread, &QThread::finished); 0097 QSignalSpy threadCleaned(thread, &QThread::destroyed); 0098 0099 qDebug() << "About to start thread:" << thread; 0100 thread->start(); 0101 QVERIFY2(test::signal_eventually_emitted_once(threadStarted), "worker thread should have started by now"); 0102 0103 accounts::Dispatcher *uut = new accounts::Dispatcher(thread); 0104 QSignalSpy dispatcherDispatched(uut, &accounts::Dispatcher::dispatch); 0105 QSignalSpy dispatcherCleaned(uut, &accounts::Dispatcher::destroyed); 0106 0107 TestJob *job = new TestJob(); 0108 QSignalSpy jobFinished(job, &TestJob::finished); 0109 QSignalSpy jobCleaned(job, &TestJob::destroyed);\ 0110 0111 bool jobCallBackCalled = false; 0112 0113 uut->queueAndProceed(job, [job, thread, &jobCallBackCalled](void) -> void 0114 { 0115 QCOMPARE(job->thread(), thread); 0116 jobCallBackCalled = true; 0117 }); 0118 QVERIFY2(jobCallBackCalled, "signal setup call back should have been called for job"); 0119 0120 QVERIFY2(test::signal_eventually_emitted_once(dispatcherDispatched), "dispatcher should have dispatched the job by now"); 0121 QVERIFY2(test::signal_eventually_emitted_once(jobFinished), "job should be finished by now"); 0122 QVERIFY2(test::signal_eventually_emitted_once(jobCleaned), "job should be disposed of by now"); 0123 0124 QTimer::singleShot(0, thread, &QThread::quit); 0125 QVERIFY2(test::signal_eventually_emitted_once(threadFinished), "worker thread should be finished by now"); 0126 QVERIFY2(test::signal_eventually_emitted_once(threadCleaned), "thread should be disposed of by now"); 0127 0128 uut->deleteLater(); 0129 QVERIFY2(test::signal_eventually_emitted_once(dispatcherCleaned), "dispatcher should be disposed of by now"); 0130 } 0131 0132 QTEST_MAIN(DispatchTest) 0133 0134 #include "dispatcher-dispatch.moc"