File indexing completed on 2024-11-10 04:40:13

0001 /*
0002     SPDX-FileCopyrightText: 2012 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "qtest_akonadi.h"
0008 
0009 #include "fakesession.h"
0010 #include "job.h"
0011 
0012 Q_DECLARE_METATYPE(KJob *)
0013 Q_DECLARE_METATYPE(Akonadi::Job *)
0014 
0015 using namespace Akonadi;
0016 
0017 class FakeJob : public Job
0018 {
0019     Q_OBJECT
0020 public:
0021     explicit FakeJob(QObject *parent = nullptr)
0022         : Job(parent)
0023     {
0024     }
0025     void done()
0026     {
0027         emitResult();
0028     }
0029 
0030 protected:
0031     void doStart() override
0032     {
0033         emitWriteFinished();
0034     }
0035 };
0036 
0037 class JobTest : public QObject
0038 {
0039     Q_OBJECT
0040 private Q_SLOTS:
0041     void initTestCase()
0042     {
0043         qRegisterMetaType<KJob *>();
0044         qRegisterMetaType<Akonadi::Job *>();
0045     }
0046 
0047     void testTopLevelJobExecution()
0048     {
0049         FakeSession session("fakeSession", FakeSession::EndJobsManually);
0050 
0051         QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded);
0052         QVERIFY(sessionQueueSpy.isValid());
0053 
0054         auto job1 = new FakeJob(&session);
0055         QSignalSpy job1DoneSpy(job1, &KJob::result);
0056         QVERIFY(job1DoneSpy.isValid());
0057 
0058         auto job2 = new FakeJob(&session);
0059         QSignalSpy job2DoneSpy(job2, &KJob::result);
0060         QVERIFY(job2DoneSpy.isValid());
0061 
0062         QCOMPARE(sessionQueueSpy.size(), 2);
0063         QCOMPARE(job1DoneSpy.size(), 0);
0064 
0065         QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart);
0066         QVERIFY(job1AboutToStartSpy.wait());
0067 
0068         QCOMPARE(job1DoneSpy.size(), 0);
0069 
0070         job1->done();
0071         QCOMPARE(job1DoneSpy.size(), 1);
0072 
0073         QSignalSpy job2AboutToStartSpy(job2, &Job::aboutToStart);
0074         QVERIFY(job2AboutToStartSpy.wait());
0075         QCOMPARE(job2DoneSpy.size(), 0);
0076         job2->done();
0077 
0078         QCOMPARE(job1DoneSpy.size(), 1);
0079         QCOMPARE(job2DoneSpy.size(), 1);
0080     }
0081 
0082     void testKillSession()
0083     {
0084         FakeSession session("fakeSession", FakeSession::EndJobsManually);
0085 
0086         QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded);
0087         QVERIFY(sessionQueueSpy.isValid());
0088         QSignalSpy sessionReconnectSpy(&session, &Session::reconnected);
0089         QVERIFY(sessionReconnectSpy.isValid());
0090 
0091         auto job1 = new FakeJob(&session);
0092         QSignalSpy job1DoneSpy(job1, &KJob::result);
0093         QVERIFY(job1DoneSpy.isValid());
0094 
0095         auto job2 = new FakeJob(&session);
0096         QSignalSpy job2DoneSpy(job2, &KJob::result);
0097         QVERIFY(job2DoneSpy.isValid());
0098 
0099         auto job3 = new FakeJob(&session);
0100         QSignalSpy job3DoneSpy(job3, &KJob::result);
0101         QVERIFY(job3DoneSpy.isValid());
0102 
0103         auto job4 = new FakeJob(&session);
0104         QSignalSpy job4DoneSpy(job4, &KJob::result);
0105         QVERIFY(job4DoneSpy.isValid());
0106 
0107         QCOMPARE(sessionQueueSpy.size(), 4);
0108         QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart);
0109         QVERIFY(job1AboutToStartSpy.wait());
0110 
0111         // one job running, 3 queued, now kill the session
0112         session.clear();
0113         QVERIFY(sessionReconnectSpy.wait());
0114 
0115         QCOMPARE(job1DoneSpy.size(), 1);
0116         QCOMPARE(job2DoneSpy.size(), 1);
0117         QCOMPARE(job3DoneSpy.size(), 1);
0118         QCOMPARE(job4DoneSpy.size(), 1);
0119         QCOMPARE(sessionReconnectSpy.size(), 2);
0120     }
0121 
0122     void testKillQueuedJob()
0123     {
0124         FakeSession session("fakeSession", FakeSession::EndJobsManually);
0125 
0126         QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded);
0127         QVERIFY(sessionQueueSpy.isValid());
0128         QSignalSpy sessionReconnectSpy(&session, &Session::reconnected);
0129         QVERIFY(sessionReconnectSpy.isValid());
0130 
0131         auto job1 = new FakeJob(&session);
0132         QSignalSpy job1DoneSpy(job1, &KJob::result);
0133         QVERIFY(job1DoneSpy.isValid());
0134 
0135         auto job2 = new FakeJob(&session);
0136         QSignalSpy job2DoneSpy(job2, &KJob::result);
0137         QVERIFY(job2DoneSpy.isValid());
0138 
0139         QCOMPARE(sessionQueueSpy.size(), 2);
0140         QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart);
0141         QVERIFY(job1AboutToStartSpy.wait());
0142 
0143         // one job running, one queued, now kill the waiting job
0144         QVERIFY(job2->kill(KJob::EmitResult));
0145 
0146         QCOMPARE(job1DoneSpy.size(), 0);
0147         QCOMPARE(job2DoneSpy.size(), 1);
0148 
0149         job1->done();
0150         QCOMPARE(job1DoneSpy.size(), 1);
0151         QCOMPARE(job2DoneSpy.size(), 1);
0152         QCOMPARE(sessionReconnectSpy.size(), 1);
0153     }
0154 
0155     void testKillRunningJob()
0156     {
0157         FakeSession session("fakeSession", FakeSession::EndJobsManually);
0158 
0159         QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded);
0160         QVERIFY(sessionQueueSpy.isValid());
0161         QSignalSpy sessionReconnectSpy(&session, &Session::reconnected);
0162         QVERIFY(sessionReconnectSpy.isValid());
0163 
0164         auto job1 = new FakeJob(&session);
0165         QSignalSpy job1DoneSpy(job1, &KJob::result);
0166         QVERIFY(job1DoneSpy.isValid());
0167 
0168         auto job2 = new FakeJob(&session);
0169         QSignalSpy job2DoneSpy(job2, &KJob::result);
0170         QVERIFY(job2DoneSpy.isValid());
0171 
0172         QCOMPARE(sessionQueueSpy.size(), 2);
0173         QSignalSpy job1AboutToStartSpy(job1, &Job::aboutToStart);
0174         QVERIFY(job1AboutToStartSpy.wait());
0175 
0176         // one job running, one queued, now kill the running one
0177         QVERIFY(job1->kill(KJob::EmitResult));
0178 
0179         QCOMPARE(job1DoneSpy.size(), 1);
0180         QCOMPARE(job2DoneSpy.size(), 0);
0181 
0182         // session needs to reconnect, then execute the next job
0183         QSignalSpy job2AboutToStartSpy(job2, &Job::aboutToStart);
0184         QVERIFY(job2AboutToStartSpy.wait());
0185         QCOMPARE(sessionReconnectSpy.size(), 2);
0186         job2->done();
0187 
0188         QCOMPARE(job1DoneSpy.size(), 1);
0189         QCOMPARE(job2DoneSpy.size(), 1);
0190         QCOMPARE(sessionReconnectSpy.size(), 2);
0191     }
0192 
0193     void testKillRunningSubjob()
0194     {
0195         FakeSession session("fakeSession", FakeSession::EndJobsManually);
0196 
0197         QSignalSpy sessionQueueSpy(&session, &FakeSession::jobAdded);
0198         QSignalSpy sessionReconnectSpy(&session, &Session::reconnected);
0199 
0200         auto parentJob = new FakeJob(&session);
0201         parentJob->setObjectName(QLatin1StringView("parentJob"));
0202         QSignalSpy parentJobDoneSpy(parentJob, &KJob::result);
0203 
0204         auto subjob = new FakeJob(parentJob);
0205         subjob->setObjectName(QLatin1StringView("subjob"));
0206         QSignalSpy subjobDoneSpy(subjob, &KJob::result);
0207 
0208         auto subjob2 = new FakeJob(parentJob);
0209         subjob2->setObjectName(QLatin1StringView("subjob2"));
0210         QSignalSpy subjob2DoneSpy(subjob2, &KJob::result);
0211 
0212         auto nextJob = new FakeJob(&session);
0213         nextJob->setObjectName(QLatin1StringView("nextJob"));
0214         QSignalSpy nextJobDoneSpy(nextJob, &KJob::result);
0215 
0216         QCOMPARE(sessionQueueSpy.size(), 2);
0217         QSignalSpy parentJobAboutToStart(parentJob, &Job::aboutToStart);
0218         QVERIFY(parentJobAboutToStart.wait());
0219 
0220         QSignalSpy subjobAboutToStart(subjob, &Job::aboutToStart);
0221         QVERIFY(subjobAboutToStart.wait());
0222 
0223         // one parent job, one subjob running (another one waiting), now kill the running subjob
0224         QVERIFY(subjob->kill(KJob::EmitResult));
0225 
0226         QCOMPARE(subjobDoneSpy.size(), 1);
0227         QCOMPARE(subjob2DoneSpy.size(), 0);
0228 
0229         // Note that killing a subjob aborts the whole parent job
0230         // Since the session only knows about the parent
0231         QCOMPARE(parentJobDoneSpy.size(), 1);
0232 
0233         // session needs to reconnect, then execute the next job
0234         QSignalSpy nextJobAboutToStartSpy(nextJob, &Job::aboutToStart);
0235         QVERIFY(nextJobAboutToStartSpy.wait());
0236         QCOMPARE(sessionReconnectSpy.size(), 2);
0237         nextJob->done();
0238 
0239         QCOMPARE(subjob2DoneSpy.size(), 0);
0240         QCOMPARE(nextJobDoneSpy.size(), 1);
0241     }
0242 };
0243 
0244 QTEST_AKONADIMAIN(JobTest)
0245 
0246 #include "jobtest.moc"