1 /* 2 SPDX-FileCopyrightText: 2012 Volker Krause <vkrause@kde.org> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5 */ 6 7 #include <qtest_akonadi.h> 8 9 #include "fakesession.h" 10 #include "job.h" 11 12 Q_DECLARE_METATYPE(KJob *) 13 Q_DECLARE_METATYPE(Akonadi::Job *) 14 15 using namespace Akonadi; 16 17 class FakeJob : public Job 18 { 19 Q_OBJECT 20 public: FakeJob(QObject * parent=nullptr)21 explicit FakeJob(QObject *parent = nullptr) 22 : Job(parent) 23 { 24 } done()25 void done() 26 { 27 emitResult(); 28 } 29 30 protected: doStart()31 void doStart() override 32 { 33 emitWriteFinished(); 34 } 35 }; 36 37 class JobTest : public QObject 38 { 39 Q_OBJECT 40 private Q_SLOTS: initTestCase()41 void initTestCase() 42 { 43 qRegisterMetaType<KJob *>(); 44 qRegisterMetaType<Akonadi::Job *>(); 45 } 46 testTopLevelJobExecution()47 void testTopLevelJobExecution() 48 { 49 FakeSession session("fakeSession", FakeSession::EndJobsManually); 50 51 QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded); 52 QVERIFY(sessionQueueSpy.isValid()); 53 54 auto job1 = new FakeJob(&session); 55 QSignalSpy job1DoneSpy(job1, &KJob::result); 56 QVERIFY(job1DoneSpy.isValid()); 57 58 auto job2 = new FakeJob(&session); 59 QSignalSpy job2DoneSpy(job2, &KJob::result); 60 QVERIFY(job2DoneSpy.isValid()); 61 62 QCOMPARE(sessionQueueSpy.size(), 2); 63 QCOMPARE(job1DoneSpy.size(), 0); 64 65 QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart); 66 QVERIFY(job1AboutToStartSpy.wait()); 67 68 QCOMPARE(job1DoneSpy.size(), 0); 69 70 job1->done(); 71 QCOMPARE(job1DoneSpy.size(), 1); 72 73 QSignalSpy job2AboutToStartSpy(job2, &Job::aboutToStart); 74 QVERIFY(job2AboutToStartSpy.wait()); 75 QCOMPARE(job2DoneSpy.size(), 0); 76 job2->done(); 77 78 QCOMPARE(job1DoneSpy.size(), 1); 79 QCOMPARE(job2DoneSpy.size(), 1); 80 } 81 testKillSession()82 void testKillSession() 83 { 84 FakeSession session("fakeSession", FakeSession::EndJobsManually); 85 86 QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded); 87 QVERIFY(sessionQueueSpy.isValid()); 88 QSignalSpy sessionReconnectSpy(&session, &Session::reconnected); 89 QVERIFY(sessionReconnectSpy.isValid()); 90 91 auto job1 = new FakeJob(&session); 92 QSignalSpy job1DoneSpy(job1, &KJob::result); 93 QVERIFY(job1DoneSpy.isValid()); 94 95 auto job2 = new FakeJob(&session); 96 QSignalSpy job2DoneSpy(job2, &KJob::result); 97 QVERIFY(job2DoneSpy.isValid()); 98 99 QCOMPARE(sessionQueueSpy.size(), 2); 100 QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart); 101 QVERIFY(job1AboutToStartSpy.wait()); 102 103 // one job running, one queued, now kill the session 104 session.clear(); 105 QVERIFY(sessionReconnectSpy.wait()); 106 107 QCOMPARE(job1DoneSpy.size(), 1); 108 QCOMPARE(job2DoneSpy.size(), 1); 109 QCOMPARE(sessionReconnectSpy.size(), 2); 110 } 111 testKillQueuedJob()112 void testKillQueuedJob() 113 { 114 FakeSession session("fakeSession", FakeSession::EndJobsManually); 115 116 QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded); 117 QVERIFY(sessionQueueSpy.isValid()); 118 QSignalSpy sessionReconnectSpy(&session, &Session::reconnected); 119 QVERIFY(sessionReconnectSpy.isValid()); 120 121 auto job1 = new FakeJob(&session); 122 QSignalSpy job1DoneSpy(job1, &KJob::result); 123 QVERIFY(job1DoneSpy.isValid()); 124 125 auto job2 = new FakeJob(&session); 126 QSignalSpy job2DoneSpy(job2, &KJob::result); 127 QVERIFY(job2DoneSpy.isValid()); 128 129 QCOMPARE(sessionQueueSpy.size(), 2); 130 QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart); 131 QVERIFY(job1AboutToStartSpy.wait()); 132 133 // one job running, one queued, now kill the waiting job 134 QVERIFY(job2->kill(KJob::EmitResult)); 135 136 QCOMPARE(job1DoneSpy.size(), 0); 137 QCOMPARE(job2DoneSpy.size(), 1); 138 139 job1->done(); 140 QCOMPARE(job1DoneSpy.size(), 1); 141 QCOMPARE(job2DoneSpy.size(), 1); 142 QCOMPARE(sessionReconnectSpy.size(), 1); 143 } 144 testKillRunningJob()145 void testKillRunningJob() 146 { 147 FakeSession session("fakeSession", FakeSession::EndJobsManually); 148 149 QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded); 150 QVERIFY(sessionQueueSpy.isValid()); 151 QSignalSpy sessionReconnectSpy(&session, &Session::reconnected); 152 QVERIFY(sessionReconnectSpy.isValid()); 153 154 auto job1 = new FakeJob(&session); 155 QSignalSpy job1DoneSpy(job1, &KJob::result); 156 QVERIFY(job1DoneSpy.isValid()); 157 158 auto job2 = new FakeJob(&session); 159 QSignalSpy job2DoneSpy(job2, &KJob::result); 160 QVERIFY(job2DoneSpy.isValid()); 161 162 QCOMPARE(sessionQueueSpy.size(), 2); 163 QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart); 164 QVERIFY(job1AboutToStartSpy.wait()); 165 166 // one job running, one queued, now kill the running one 167 QVERIFY(job1->kill(KJob::EmitResult)); 168 169 QCOMPARE(job1DoneSpy.size(), 1); 170 QCOMPARE(job2DoneSpy.size(), 0); 171 172 // session needs to reconnect, then execute the next job 173 QSignalSpy job2AboutToStartSpy(job2, &Job::aboutToStart); 174 QVERIFY(job2AboutToStartSpy.wait()); 175 QCOMPARE(sessionReconnectSpy.size(), 2); 176 job2->done(); 177 178 QCOMPARE(job1DoneSpy.size(), 1); 179 QCOMPARE(job2DoneSpy.size(), 1); 180 QCOMPARE(sessionReconnectSpy.size(), 2); 181 } 182 testKillRunningSubjob()183 void testKillRunningSubjob() 184 { 185 FakeSession session("fakeSession", FakeSession::EndJobsManually); 186 187 QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded); 188 QSignalSpy sessionReconnectSpy(&session, &Session::reconnected); 189 190 auto parentJob = new FakeJob(&session); 191 parentJob->setObjectName(QStringLiteral("parentJob")); 192 QSignalSpy parentJobDoneSpy(parentJob, &KJob::result); 193 194 auto subjob = new FakeJob(parentJob); 195 subjob->setObjectName(QStringLiteral("subjob")); 196 QSignalSpy subjobDoneSpy(subjob, &KJob::result); 197 198 auto subjob2 = new FakeJob(parentJob); 199 subjob2->setObjectName(QStringLiteral("subjob2")); 200 QSignalSpy subjob2DoneSpy(subjob2, &KJob::result); 201 202 auto nextJob = new FakeJob(&session); 203 nextJob->setObjectName(QStringLiteral("nextJob")); 204 QSignalSpy nextJobDoneSpy(nextJob, &KJob::result); 205 206 QCOMPARE(sessionQueueSpy.size(), 2); 207 QSignalSpy parentJobAboutToStart(parentJob, &Job::aboutToStart); 208 QVERIFY(parentJobAboutToStart.wait()); 209 210 QSignalSpy subjobAboutToStart(subjob, &Job::aboutToStart); 211 QVERIFY(subjobAboutToStart.wait()); 212 213 // one parent job, one subjob running (another one waiting), now kill the running subjob 214 QVERIFY(subjob->kill(KJob::EmitResult)); 215 216 QCOMPARE(subjobDoneSpy.size(), 1); 217 QCOMPARE(subjob2DoneSpy.size(), 0); 218 219 // Note that killing a subjob aborts the whole parent job 220 // Since the session only knows about the parent 221 QCOMPARE(parentJobDoneSpy.size(), 1); 222 223 // session needs to reconnect, then execute the next job 224 QSignalSpy nextJobAboutToStartSpy(nextJob, &Job::aboutToStart); 225 QVERIFY(nextJobAboutToStartSpy.wait()); 226 QCOMPARE(sessionReconnectSpy.size(), 2); 227 nextJob->done(); 228 229 QCOMPARE(subjob2DoneSpy.size(), 0); 230 QCOMPARE(nextJobDoneSpy.size(), 1); 231 } 232 }; 233 234 QTEST_AKONADIMAIN(JobTest) 235 236 #include "jobtest.moc" 237