File indexing completed on 2024-05-19 04:39:58
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2014 Milian Wolff <mail@milianw.de> 0004 SPDX-FileCopyrightText: 2023 Igor Kushnir <igorkuo@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "ksequentialcompoundjobtest.h" 0010 0011 #include "ksimplesequentialcompoundjob.h" 0012 0013 #include <QSignalSpy> 0014 #include <QStandardPaths> 0015 #include <QTest> 0016 0017 #include <memory> 0018 #include <vector> 0019 0020 using namespace KDevCoreAddons; 0021 0022 class PublicSequentialCompoundJob : public KSequentialCompoundJob 0023 { 0024 public: 0025 using KSequentialCompoundJob::addSubjob; 0026 using KSequentialCompoundJob::clearSubjobs; 0027 using KSequentialCompoundJob::removeSubjob; 0028 using KSequentialCompoundJob::subjobs; 0029 }; 0030 0031 struct JobSpy { 0032 explicit JobSpy(const KJob *job) 0033 : infoMessage(job, &KJob::infoMessage) 0034 , percentChanged(job, &KJob::percentChanged) 0035 , finished(job, &KJob::finished) 0036 , result(job, &KJob::result) 0037 { 0038 } 0039 0040 QSignalSpy infoMessage; 0041 QSignalSpy percentChanged; 0042 QSignalSpy finished; 0043 QSignalSpy result; 0044 }; 0045 0046 struct KillableTestJobSpy : public JobSpy { 0047 explicit KillableTestJobSpy(KillableTestJob *job) 0048 : JobSpy(job) 0049 , started(job, &KillableTestJob::started) 0050 , killed(job, &KillableTestJob::killed) 0051 , job(job) 0052 { 0053 } 0054 0055 QSignalSpy started; 0056 QSignalSpy killed; 0057 QPointer<KillableTestJob> job; 0058 }; 0059 0060 std::vector<std::unique_ptr<KillableTestJobSpy>> generateKillableTestJobSpies(int subjobCount) 0061 { 0062 std::vector<std::unique_ptr<KillableTestJobSpy>> jobSpies; 0063 for (int j = 0; j < subjobCount; ++j) { 0064 jobSpies.push_back(std::make_unique<KillableTestJobSpy>(new KillableTestJob)); 0065 } 0066 return jobSpies; 0067 } 0068 0069 void KSequentialCompoundJobTest::initTestCase() 0070 { 0071 QStandardPaths::setTestModeEnabled(true); 0072 } 0073 0074 void KSequentialCompoundJobTest::runZeroJobs() 0075 { 0076 QPointer master(new KSimpleSequentialCompoundJob); 0077 JobSpy masterSpy(master); 0078 0079 QCOMPARE(masterSpy.finished.count(), 0); 0080 QCOMPARE(masterSpy.result.count(), 0); 0081 master->start(); 0082 QCOMPARE(masterSpy.finished.count(), 1); 0083 QCOMPARE(masterSpy.result.count(), 1); 0084 0085 QTest::qWait(1); 0086 QVERIFY(!master); 0087 } 0088 0089 void KSequentialCompoundJobTest::runOneJob() 0090 { 0091 QPointer slave(new TestJob); 0092 0093 QPointer master(new KSimpleSequentialCompoundJob); 0094 QVERIFY(master->addSubjob(slave)); 0095 JobSpy masterSpy(master); 0096 0097 QSignalSpy startedSpy(slave, &TestJob::started); 0098 JobSpy slaveSpy(slave); 0099 0100 master->start(); 0101 QCOMPARE(startedSpy.count(), 1); 0102 QCOMPARE(slaveSpy.finished.count(), 0); 0103 QCOMPARE(masterSpy.finished.count(), 0); 0104 0105 QCOMPARE(masterSpy.percentChanged.count(), 0); 0106 QCOMPARE(master->percent(), 0); 0107 0108 slave->emitResult(); 0109 0110 QCOMPARE(masterSpy.percentChanged.count(), 1); 0111 QCOMPARE(master->percent(), 100); 0112 0113 QCOMPARE(masterSpy.finished.count(), 1); 0114 QCOMPARE(masterSpy.result.count(), 1); 0115 0116 QCOMPARE(startedSpy.count(), 1); 0117 QCOMPARE(slaveSpy.finished.count(), 1); 0118 QCOMPARE(slaveSpy.result.count(), 1); 0119 0120 QTest::qWait(1); 0121 0122 QVERIFY(!slave); 0123 QVERIFY(!master); 0124 0125 QCOMPARE(slaveSpy.percentChanged.count(), 0); 0126 QCOMPARE(masterSpy.percentChanged.count(), 1); 0127 } 0128 0129 void KSequentialCompoundJobTest::runTwoJobs() 0130 { 0131 QPointer slave1(new TestJob); 0132 QPointer slave2(new TestJob); 0133 0134 QPointer master(new KSimpleSequentialCompoundJob); 0135 QVERIFY(master->addSubjob(slave1)); 0136 QVERIFY(master->addSubjob(slave2)); 0137 JobSpy masterSpy(master); 0138 0139 QSignalSpy started1Spy(slave1, &TestJob::started); 0140 QSignalSpy started2Spy(slave2, &TestJob::started); 0141 JobSpy slave1Spy(slave1); 0142 JobSpy slave2Spy(slave2); 0143 0144 master->start(); 0145 QCOMPARE(started1Spy.count(), 1); 0146 QCOMPARE(slave1Spy.finished.count(), 0); 0147 QCOMPARE(started2Spy.count(), 0); 0148 QCOMPARE(slave2Spy.finished.count(), 0); 0149 QCOMPARE(masterSpy.finished.count(), 0); 0150 0151 QCOMPARE(masterSpy.percentChanged.count(), 0); 0152 QCOMPARE(master->percent(), 0); 0153 0154 slave1->emitResult(); 0155 0156 QCOMPARE(masterSpy.percentChanged.count(), 1); 0157 QCOMPARE(master->percent(), 50); 0158 0159 QCOMPARE(started1Spy.count(), 1); 0160 QCOMPARE(slave1Spy.finished.count(), 1); 0161 QCOMPARE(started2Spy.count(), 1); 0162 QCOMPARE(slave2Spy.finished.count(), 0); 0163 QCOMPARE(masterSpy.finished.count(), 0); 0164 0165 slave2->emitResult(); 0166 0167 QCOMPARE(masterSpy.percentChanged.count(), 2); 0168 QCOMPARE(master->percent(), 100); 0169 0170 QCOMPARE(masterSpy.finished.count(), 1); 0171 QCOMPARE(masterSpy.result.count(), 1); 0172 0173 QCOMPARE(started1Spy.count(), 1); 0174 QCOMPARE(slave1Spy.finished.count(), 1); 0175 QCOMPARE(slave1Spy.result.count(), 1); 0176 0177 QCOMPARE(started2Spy.count(), 1); 0178 QCOMPARE(slave2Spy.finished.count(), 1); 0179 QCOMPARE(slave2Spy.result.count(), 1); 0180 0181 QTest::qWait(1); 0182 0183 QVERIFY(!slave1); 0184 QVERIFY(!slave2); 0185 QVERIFY(!master); 0186 0187 QCOMPARE(slave1Spy.percentChanged.count(), 0); 0188 QCOMPARE(slave2Spy.percentChanged.count(), 0); 0189 QCOMPARE(masterSpy.percentChanged.count(), 2); 0190 } 0191 0192 void KSequentialCompoundJobTest::addRemoveClearSubjob_data() 0193 { 0194 QTest::addColumn<bool>("shouldClearSubjobs"); 0195 QTest::newRow("removeSubjob") << false; 0196 QTest::newRow("clearSubjobs") << true; 0197 } 0198 0199 void KSequentialCompoundJobTest::addRemoveClearSubjob() 0200 { 0201 QPointer compoundJob(new PublicSequentialCompoundJob); 0202 JobSpy compoundSpy(compoundJob); 0203 QVERIFY(!compoundJob->addSubjob(nullptr)); 0204 QVERIFY(!compoundJob->removeSubjob(nullptr)); 0205 0206 QPointer subjob(new TestJob); 0207 JobSpy subjobSpy(subjob); 0208 QCOMPARE(subjob->parent(), nullptr); 0209 QVERIFY(!compoundJob->removeSubjob(subjob)); 0210 0211 subjob->emitInfoMessage("hi"); 0212 QCOMPARE(subjobSpy.infoMessage.count(), 1); 0213 subjob->setPercent(10); 0214 QCOMPARE(subjobSpy.percentChanged.count(), 1); 0215 0216 QCOMPARE(compoundJob->subjobs(), {}); 0217 QVERIFY(compoundJob->addSubjob(subjob)); 0218 QCOMPARE(compoundJob->subjobs(), {subjob}); 0219 0220 QCOMPARE(subjob->parent(), compoundJob); 0221 QVERIFY(!compoundJob->addSubjob(subjob)); 0222 QCOMPARE(subjob->parent(), compoundJob); 0223 0224 QCOMPARE(compoundSpy.infoMessage.count(), 0); 0225 QCOMPARE(compoundSpy.percentChanged.count(), 0); 0226 0227 subjob->emitInfoMessage("there"); 0228 QCOMPARE(subjobSpy.infoMessage.count(), 2); 0229 QCOMPARE(compoundSpy.infoMessage.count(), 1); 0230 QCOMPARE(compoundSpy.infoMessage.constLast().at(0).value<KJob *>(), subjob); 0231 QCOMPARE(compoundSpy.infoMessage.constLast().at(1), "there"); 0232 0233 subjob->setPercent(25); 0234 QCOMPARE(subjobSpy.percentChanged.count(), 2); 0235 QCOMPARE(compoundSpy.percentChanged.count(), 0); // the subjob is not started, its percent changes are ignored 0236 0237 compoundJob->start(); 0238 subjob->setPercent(45); 0239 QCOMPARE(subjobSpy.percentChanged.count(), 3); 0240 QCOMPARE(compoundSpy.percentChanged.count(), 1); 0241 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0242 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 45); 0243 QCOMPARE(compoundJob->percent(), 45); 0244 0245 QVERIFY(!compoundJob->removeSubjob(nullptr)); 0246 QCOMPARE(compoundJob->subjobs(), {subjob}); 0247 QCOMPARE(subjob->parent(), compoundJob); 0248 0249 QFETCH(const bool, shouldClearSubjobs); 0250 if (shouldClearSubjobs) { 0251 compoundJob->clearSubjobs(); 0252 } else { 0253 QVERIFY(compoundJob->removeSubjob(subjob)); 0254 } 0255 QCOMPARE(compoundJob->subjobs(), {}); 0256 QCOMPARE(subjob->parent(), nullptr); 0257 QVERIFY(!compoundJob->removeSubjob(subjob)); 0258 0259 subjob->emitInfoMessage("!"); 0260 QCOMPARE(subjobSpy.infoMessage.count(), 3); 0261 subjob->setPercent(91); 0262 QCOMPARE(subjobSpy.percentChanged.count(), 4); 0263 0264 QCOMPARE(subjobSpy.finished.count(), 0); 0265 QCOMPARE(subjobSpy.result.count(), 0); 0266 subjob->emitResult(); 0267 QCOMPARE(subjobSpy.finished.count(), 1); 0268 QCOMPARE(subjobSpy.result.count(), 1); 0269 0270 QVERIFY(subjob); 0271 QTest::qWait(1); 0272 QVERIFY(!subjob); 0273 0274 QVERIFY(compoundJob); 0275 QCOMPARE(compoundSpy.finished.count(), 0); 0276 delete compoundJob; 0277 QCOMPARE(compoundSpy.finished.count(), 1); 0278 0279 QCOMPARE(compoundSpy.infoMessage.count(), 1); 0280 QCOMPARE(compoundSpy.percentChanged.count(), 1); 0281 QCOMPARE(compoundSpy.result.count(), 0); 0282 } 0283 0284 void KSequentialCompoundJobTest::addClearSubjobs() 0285 { 0286 QPointer compoundJob(new PublicSequentialCompoundJob); 0287 JobSpy compoundSpy(compoundJob); 0288 0289 QPointer subjob1(new TestJob); 0290 JobSpy subjob1Spy(subjob1); 0291 QSignalSpy started1Spy(subjob1, &TestJob::started); 0292 QPointer subjob2(new TestJob); 0293 JobSpy subjob2Spy(subjob2); 0294 QSignalSpy started2Spy(subjob2, &TestJob::started); 0295 0296 QVERIFY(compoundJob->addSubjob(subjob1)); 0297 QVERIFY(!compoundJob->removeSubjob(subjob2)); 0298 QVERIFY(compoundJob->addSubjob(subjob2)); 0299 const QList<KJob *> expectedSubjobList{subjob1, subjob2}; 0300 QCOMPARE(compoundJob->subjobs(), expectedSubjobList); 0301 QCOMPARE(subjob1->parent(), compoundJob); 0302 QCOMPARE(subjob2->parent(), compoundJob); 0303 0304 QVERIFY(!compoundJob->addSubjob(subjob2)); 0305 QVERIFY(!compoundJob->addSubjob(subjob1)); 0306 QCOMPARE(compoundJob->subjobs(), expectedSubjobList); 0307 0308 subjob1->emitInfoMessage("take"); 0309 QCOMPARE(subjob1Spy.infoMessage.count(), 1); 0310 QCOMPARE(compoundSpy.infoMessage.count(), 1); 0311 QCOMPARE(compoundSpy.infoMessage.constLast().at(0).value<KJob *>(), subjob1); 0312 QCOMPARE(compoundSpy.infoMessage.constLast().at(1), "take"); 0313 0314 subjob2->emitInfoMessage("that"); 0315 QCOMPARE(subjob2Spy.infoMessage.count(), 1); 0316 QCOMPARE(compoundSpy.infoMessage.count(), 2); 0317 QCOMPARE(compoundSpy.infoMessage.constLast().at(0).value<KJob *>(), subjob2); 0318 QCOMPARE(compoundSpy.infoMessage.constLast().at(1), "that"); 0319 0320 subjob1->setPercent(31); 0321 QCOMPARE(subjob1Spy.percentChanged.count(), 1); 0322 subjob2->setPercent(12); 0323 QCOMPARE(subjob2Spy.percentChanged.count(), 1); 0324 QCOMPARE(compoundSpy.percentChanged.count(), 0); // the subjobs are not started, their percent changes are ignored 0325 0326 QCOMPARE(started1Spy.count(), 0); 0327 compoundJob->start(); 0328 QCOMPARE(started1Spy.count(), 1); 0329 QCOMPARE(started2Spy.count(), 0); 0330 0331 subjob1->setPercent(52); 0332 QCOMPARE(subjob1Spy.percentChanged.count(), 2); 0333 QCOMPARE(compoundSpy.percentChanged.count(), 1); 0334 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0335 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 26); 0336 QCOMPARE(compoundJob->percent(), 26); 0337 0338 subjob2->setPercent(95); 0339 QCOMPARE(subjob2Spy.percentChanged.count(), 2); 0340 QCOMPARE(compoundSpy.percentChanged.count(), 1); // the 2nd subjob is not started, its percent changes are ignored 0341 QCOMPARE(compoundJob->percent(), 26); 0342 0343 subjob1->setPercent(83); 0344 QCOMPARE(subjob1Spy.percentChanged.count(), 3); 0345 QCOMPARE(compoundSpy.percentChanged.count(), 2); 0346 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0347 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 41); 0348 QCOMPARE(compoundJob->percent(), 41); 0349 0350 QVERIFY(!compoundJob->removeSubjob(nullptr)); 0351 QCOMPARE(compoundJob->subjobs(), expectedSubjobList); 0352 compoundJob->clearSubjobs(); 0353 QCOMPARE(compoundJob->subjobs(), {}); 0354 QCOMPARE(subjob1->parent(), nullptr); 0355 QCOMPARE(subjob2->parent(), nullptr); 0356 QVERIFY(!compoundJob->removeSubjob(nullptr)); 0357 QVERIFY(!compoundJob->removeSubjob(subjob2)); 0358 QVERIFY(!compoundJob->removeSubjob(subjob1)); 0359 QCOMPARE(compoundJob->subjobs(), {}); 0360 0361 subjob1->emitInfoMessage("lost"); 0362 subjob2->emitInfoMessage("too"); 0363 subjob1->setPercent(99); 0364 subjob2->setPercent(100); 0365 QCOMPARE(compoundSpy.infoMessage.count(), 2); 0366 QCOMPARE(compoundSpy.percentChanged.count(), 2); 0367 QCOMPARE(compoundJob->percent(), 41); 0368 0369 delete subjob1; 0370 delete subjob2; 0371 QTest::qWait(1); 0372 QVERIFY(compoundJob); 0373 0374 QCOMPARE(compoundSpy.finished.count(), 0); 0375 QVERIFY(compoundJob->kill()); 0376 QCOMPARE(compoundSpy.finished.count(), 1); 0377 0378 QVERIFY(compoundJob); 0379 QTest::qWait(1); 0380 QVERIFY(!compoundJob); 0381 0382 QCOMPARE(compoundSpy.infoMessage.count(), 2); 0383 QCOMPARE(compoundSpy.percentChanged.count(), 2); 0384 QCOMPARE(compoundSpy.finished.count(), 1); 0385 QCOMPARE(compoundSpy.result.count(), 0); 0386 } 0387 0388 void KSequentialCompoundJobTest::subjobPercentChanged() 0389 { 0390 QPointer compoundJob(new KSimpleSequentialCompoundJob); 0391 JobSpy compoundSpy(compoundJob); 0392 0393 QPointer subjob1(new TestJob); 0394 JobSpy subjob1Spy(subjob1); 0395 QSignalSpy started1Spy(subjob1, &TestJob::started); 0396 QPointer subjob2(new TestJob); 0397 JobSpy subjob2Spy(subjob2); 0398 QSignalSpy started2Spy(subjob2, &TestJob::started); 0399 QPointer subjob3(new TestJob); 0400 JobSpy subjob3Spy(subjob3); 0401 QSignalSpy started3Spy(subjob3, &TestJob::started); 0402 0403 QVERIFY(compoundJob->addSubjob(subjob1)); 0404 QVERIFY(compoundJob->addSubjob(subjob2)); 0405 QVERIFY(compoundJob->addSubjob(subjob3)); 0406 0407 QCOMPARE(started1Spy.count(), 0); 0408 compoundJob->start(); 0409 QCOMPARE(started1Spy.count(), 1); 0410 QCOMPARE(started2Spy.count(), 0); 0411 0412 subjob1->setPercent(33); 0413 QCOMPARE(subjob1Spy.percentChanged.count(), 1); 0414 QCOMPARE(compoundSpy.percentChanged.count(), 1); 0415 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0416 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 33 / 3); 0417 QCOMPARE(compoundJob->percent(), 11); 0418 0419 subjob1->setPercent(88); 0420 QCOMPARE(subjob1Spy.percentChanged.count(), 2); 0421 QCOMPARE(compoundSpy.percentChanged.count(), 2); 0422 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0423 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 88 / 3); 0424 QCOMPARE(compoundJob->percent(), 29); 0425 0426 subjob1->emitResult(); 0427 QCOMPARE(subjob1Spy.percentChanged.count(), 2); 0428 QCOMPARE(compoundSpy.percentChanged.count(), 3); 0429 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0430 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 100 / 3); 0431 QCOMPARE(compoundJob->percent(), 33); 0432 0433 QCOMPARE(started1Spy.count(), 1); 0434 QCOMPARE(subjob1Spy.finished.count(), 1); 0435 QCOMPARE(started2Spy.count(), 1); 0436 QCOMPARE(started3Spy.count(), 0); 0437 0438 subjob2->setPercent(4); 0439 QCOMPARE(subjob2Spy.percentChanged.count(), 1); 0440 QCOMPARE(compoundSpy.percentChanged.count(), 4); 0441 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0442 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), (100 + 4) / 3); 0443 QCOMPARE(compoundJob->percent(), 34); 0444 0445 subjob2->setPercent(5); 0446 QCOMPARE(subjob2Spy.percentChanged.count(), 2); 0447 QCOMPARE(compoundSpy.percentChanged.count(), 5); 0448 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0449 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), (100 + 5) / 3); 0450 QCOMPARE(compoundJob->percent(), 35); 0451 0452 subjob2->setPercent(7); 0453 QCOMPARE(subjob2Spy.percentChanged.count(), 3); 0454 QCOMPARE(compoundSpy.percentChanged.count(), 5); // the total percent value hasn't changed 0455 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0456 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), (100 + 7) / 3); 0457 QCOMPARE(compoundJob->percent(), 35); 0458 0459 subjob2->setPercent(99); 0460 QCOMPARE(subjob2Spy.percentChanged.count(), 4); 0461 QCOMPARE(compoundSpy.percentChanged.count(), 6); 0462 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0463 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), (100 + 99) / 3); 0464 QCOMPARE(compoundJob->percent(), 66); 0465 0466 subjob2->emitResult(); 0467 QCOMPARE(subjob2Spy.percentChanged.count(), 4); 0468 QCOMPARE(compoundSpy.percentChanged.count(), 6); // the total percent value hasn't changed 0469 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0470 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 2 * 100 / 3); 0471 QCOMPARE(compoundJob->percent(), 66); 0472 0473 QCOMPARE(started2Spy.count(), 1); 0474 QCOMPARE(subjob2Spy.finished.count(), 1); 0475 QCOMPARE(started3Spy.count(), 1); 0476 0477 subjob3->setPercent(50); 0478 QCOMPARE(subjob3Spy.percentChanged.count(), 1); 0479 QCOMPARE(compoundSpy.percentChanged.count(), 7); 0480 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0481 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), (200 + 50) / 3); 0482 QCOMPARE(compoundJob->percent(), 83); 0483 0484 delete subjob3; 0485 QCOMPARE(subjob3Spy.percentChanged.count(), 1); 0486 QCOMPARE(compoundSpy.percentChanged.count(), 8); 0487 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0488 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 3 * 100 / 3); 0489 QCOMPARE(compoundJob->percent(), 100); 0490 0491 QCOMPARE(started3Spy.count(), 1); 0492 QCOMPARE(subjob3Spy.finished.count(), 1); 0493 0494 QTest::qWait(1); 0495 QVERIFY(!subjob1); 0496 QVERIFY(!subjob2); 0497 QVERIFY(!subjob3); 0498 QVERIFY(!compoundJob); 0499 0500 QCOMPARE(compoundSpy.percentChanged.count(), 8); 0501 QCOMPARE(compoundSpy.finished.count(), 1); 0502 QCOMPARE(compoundSpy.result.count(), 1); 0503 } 0504 0505 void KSequentialCompoundJobTest::abortOnSubjobError() 0506 { 0507 QPointer compoundJob(new PublicSequentialCompoundJob); 0508 JobSpy compoundSpy(compoundJob); 0509 0510 QPointer subjob1(new TestJob); 0511 QPointer subjob2(new TestJob); 0512 JobSpy subjob2Spy(subjob2); 0513 QSignalSpy started2Spy(subjob2, &TestJob::started); 0514 0515 QVERIFY(compoundJob->addSubjob(subjob1)); 0516 QVERIFY(compoundJob->addSubjob(subjob2)); 0517 const QList<KJob *> expectedSubjobList{subjob1, subjob2}; 0518 QCOMPARE(compoundJob->subjobs(), expectedSubjobList); 0519 0520 compoundJob->start(); 0521 0522 QCOMPARE(started2Spy.count(), 0); 0523 subjob1->setError(244); 0524 subjob1->setErrorText("Crashed"); 0525 subjob1->emitResult(); 0526 QCOMPARE(compoundJob->error(), 244); 0527 QCOMPARE(compoundJob->errorText(), "Crashed"); 0528 QCOMPARE(compoundSpy.finished.count(), 1); 0529 QCOMPARE(compoundSpy.result.count(), 1); 0530 0531 QTest::qWait(1); 0532 QVERIFY(!subjob1); 0533 QVERIFY(!subjob2); 0534 QVERIFY(!compoundJob); 0535 0536 QCOMPARE(started2Spy.count(), 0); 0537 QCOMPARE(subjob2Spy.finished.count(), 1); 0538 QCOMPARE(subjob2Spy.result.count(), 0); 0539 } 0540 0541 void KSequentialCompoundJobTest::disableAbortOnSubjobError_data() 0542 { 0543 QTest::addColumn<bool>("lastSubjobError"); 0544 QTest::newRow("last-subjob-no-error") << false; 0545 QTest::newRow("last-subjob-error") << true; 0546 } 0547 0548 void KSequentialCompoundJobTest::disableAbortOnSubjobError() 0549 { 0550 QPointer compoundJob(new PublicSequentialCompoundJob); 0551 JobSpy compoundSpy(compoundJob); 0552 compoundJob->setAbortOnSubjobError(false); 0553 0554 QPointer subjob1(new TestJob); 0555 QPointer subjob2(new TestJob); 0556 JobSpy subjob2Spy(subjob2); 0557 QSignalSpy started2Spy(subjob2, &TestJob::started); 0558 0559 QVERIFY(compoundJob->addSubjob(subjob1)); 0560 QVERIFY(compoundJob->addSubjob(subjob2)); 0561 const QList<KJob *> expectedSubjobList{subjob1, subjob2}; 0562 QCOMPARE(compoundJob->subjobs(), expectedSubjobList); 0563 0564 compoundJob->start(); 0565 0566 QCOMPARE(started2Spy.count(), 0); 0567 subjob1->setError(105); 0568 subjob1->setErrorText("Failed"); 0569 subjob1->emitResult(); 0570 QCOMPARE(started2Spy.count(), 1); 0571 QCOMPARE(subjob1->parent(), nullptr); 0572 QCOMPARE(subjob2->parent(), compoundJob); 0573 QCOMPARE(compoundJob->subjobs(), {subjob2}); 0574 0575 QTest::qWait(1); 0576 QVERIFY(!subjob1); 0577 0578 QCOMPARE(subjob2Spy.finished.count(), 0); 0579 QCOMPARE(subjob2Spy.result.count(), 0); 0580 QCOMPARE(compoundSpy.percentChanged.count(), 1); 0581 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0582 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 50); 0583 QCOMPARE(compoundJob->percent(), 50); 0584 QCOMPARE(compoundJob->error(), 0); 0585 QCOMPARE(compoundJob->errorText(), ""); 0586 QCOMPARE(compoundSpy.finished.count(), 0); 0587 QCOMPARE(compoundSpy.result.count(), 0); 0588 0589 QFETCH(const bool, lastSubjobError); 0590 const int errorCode = lastSubjobError ? 902 : 0; 0591 const QString errorText = lastSubjobError ? "broken pipe" : ""; 0592 if (lastSubjobError) { 0593 subjob2->setError(errorCode); 0594 subjob2->setErrorText(errorText); 0595 } 0596 subjob2->emitResult(); 0597 QCOMPARE(compoundSpy.percentChanged.count(), 2); 0598 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0599 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 100); 0600 QCOMPARE(compoundJob->percent(), 100); 0601 QCOMPARE(compoundJob->error(), errorCode); 0602 QCOMPARE(compoundJob->errorText(), errorText); 0603 QCOMPARE(compoundSpy.finished.count(), 1); 0604 QCOMPARE(compoundSpy.result.count(), 1); 0605 0606 QTest::qWait(1); 0607 QVERIFY(!subjob2); 0608 QVERIFY(!compoundJob); 0609 } 0610 0611 void KSequentialCompoundJobTest::finishWrongSubjob_data() 0612 { 0613 QTest::addColumn<bool>("abortOnSubjobError"); 0614 QTest::newRow("abort-on-subjob-error") << true; 0615 QTest::newRow("no-abort-on-subjob-error") << false; 0616 } 0617 0618 void KSequentialCompoundJobTest::finishWrongSubjob() 0619 { 0620 QPointer compoundJob(new PublicSequentialCompoundJob); 0621 JobSpy compoundSpy(compoundJob); 0622 0623 QFETCH(const bool, abortOnSubjobError); 0624 compoundJob->setAbortOnSubjobError(abortOnSubjobError); 0625 0626 QPointer subjob1(new TestJob); 0627 QPointer subjob2(new TestJob); 0628 JobSpy subjob2Spy(subjob2); 0629 QSignalSpy started2Spy(subjob2, &TestJob::started); 0630 0631 QVERIFY(compoundJob->addSubjob(subjob1)); 0632 QVERIFY(compoundJob->addSubjob(subjob2)); 0633 const QList<KJob *> expectedSubjobList{subjob1, subjob2}; 0634 QCOMPARE(compoundJob->subjobs(), expectedSubjobList); 0635 0636 compoundJob->start(); 0637 0638 subjob2->setError(543); 0639 subjob2->setErrorText("Canceled"); 0640 subjob2->emitResult(); 0641 QCOMPARE(subjob2->error(), 543); 0642 QCOMPARE(subjob2->errorText(), "Canceled"); 0643 QCOMPARE(started2Spy.count(), 0); 0644 QCOMPARE(subjob2Spy.finished.count(), 1); 0645 QCOMPARE(subjob2Spy.result.count(), 1); 0646 // when an unstarted job finishes, sequential compound job simply removes it 0647 QCOMPARE(subjob2->parent(), nullptr); 0648 QCOMPARE(compoundJob->subjobs(), {subjob1}); 0649 0650 QTest::qWait(1); 0651 QVERIFY(!subjob2); 0652 0653 QCOMPARE(compoundJob->error(), 0); 0654 QCOMPARE(compoundJob->errorText(), ""); 0655 QCOMPARE(compoundSpy.finished.count(), 0); 0656 QCOMPARE(compoundSpy.result.count(), 0); 0657 0658 subjob1->emitResult(); 0659 QCOMPARE(subjob1->parent(), nullptr); 0660 QCOMPARE(compoundJob->subjobs(), {}); 0661 QCOMPARE(compoundJob->error(), 0); 0662 QCOMPARE(compoundJob->errorText(), ""); 0663 QCOMPARE(compoundSpy.finished.count(), 1); 0664 QCOMPARE(compoundSpy.result.count(), 1); 0665 0666 // These percent checks do not test expected behavior, but demonstrate what the current behavior is. 0667 // compoundSpy.percentChanged.count() == 2 and compoundJob->percent() == 100 may be more correct/useful. 0668 QCOMPARE(compoundSpy.percentChanged.count(), 1); 0669 QCOMPARE(compoundSpy.percentChanged.constLast().at(0).value<KJob *>(), compoundJob); 0670 QCOMPARE(compoundSpy.percentChanged.constLast().at(1), 50); 0671 QCOMPARE(compoundJob->percent(), 50); 0672 0673 QTest::qWait(1); 0674 QVERIFY(!subjob1); 0675 QVERIFY(!compoundJob); 0676 } 0677 0678 void KSequentialCompoundJobTest::killUnstartedCompoundJob_data() 0679 { 0680 QTest::addColumn<int>("subjobCount"); 0681 QTest::addColumn<KJob::KillVerbosity>("killVerbosity"); 0682 for (int subjobCount : {0, 1, 4}) { 0683 QTest::addRow("kill-quietly-%d-subjobs", subjobCount) << subjobCount << KJob::Quietly; 0684 QTest::addRow("emit-result-%d-subjobs", subjobCount) << subjobCount << KJob::EmitResult; 0685 } 0686 } 0687 0688 void KSequentialCompoundJobTest::killUnstartedCompoundJob() 0689 { 0690 QPointer compoundJob(new KSimpleSequentialCompoundJob); 0691 JobSpy compoundSpy(compoundJob); 0692 QVERIFY(compoundJob->capabilities() & KJob::Killable); 0693 0694 QFETCH(const int, subjobCount); 0695 auto subjobSpies = generateKillableTestJobSpies(subjobCount); 0696 for (const auto &spy : subjobSpies) { 0697 QVERIFY(compoundJob->addSubjob(spy->job)); 0698 } 0699 0700 QCOMPARE(compoundSpy.finished.count(), 0); 0701 QFETCH(const KJob::KillVerbosity, killVerbosity); 0702 QVERIFY(compoundJob->kill(killVerbosity)); 0703 QCOMPARE(compoundSpy.finished.count(), 1); 0704 QCOMPARE(compoundSpy.result.count(), killVerbosity == KJob::EmitResult); 0705 QCOMPARE(compoundJob->error(), KJob::KilledJobError); 0706 0707 QVERIFY(compoundJob); 0708 for (const auto &spy : subjobSpies) { 0709 QVERIFY(spy->job); 0710 // no need to kill unstarted subjobs, just destroy them 0711 QCOMPARE(spy->job->error(), 0); 0712 QCOMPARE(spy->job->errorText(), ""); 0713 } 0714 QTest::qWait(1); 0715 QVERIFY(!compoundJob); 0716 for (const auto &spy : subjobSpies) { 0717 QVERIFY(!spy->job); 0718 QCOMPARE(spy->started.count(), 0); 0719 QCOMPARE(spy->killed.count(), 0); // no need to kill unstarted subjobs, just destroy them 0720 QCOMPARE(spy->finished.count(), 1); 0721 QCOMPARE(spy->result.count(), 0); 0722 } 0723 } 0724 0725 void KSequentialCompoundJobTest::killFinishedCompoundJob_data() 0726 { 0727 killUnstartedCompoundJob_data(); 0728 } 0729 0730 void KSequentialCompoundJobTest::killFinishedCompoundJob() 0731 { 0732 QPointer compoundJob(new KSimpleSequentialCompoundJob); 0733 JobSpy compoundSpy(compoundJob); 0734 QVERIFY(compoundJob->capabilities() & KJob::Killable); 0735 0736 QFETCH(const int, subjobCount); 0737 auto subjobSpies = generateKillableTestJobSpies(subjobCount); 0738 for (const auto &spy : subjobSpies) { 0739 QVERIFY(compoundJob->addSubjob(spy->job)); 0740 } 0741 0742 compoundJob->start(); 0743 for (std::size_t i = 0; i < subjobSpies.size(); ++i) { 0744 QCOMPARE(compoundSpy.finished.count(), 0); 0745 auto &spy = subjobSpies[i]; 0746 QCOMPARE(spy->started.count(), 1); 0747 QCOMPARE(spy->finished.count(), 0); 0748 QCOMPARE(spy->result.count(), 0); 0749 spy->job->emitResult(); 0750 QCOMPARE(spy->started.count(), 1); 0751 QCOMPARE(spy->finished.count(), 1); 0752 QCOMPARE(spy->result.count(), 1); 0753 } 0754 QCOMPARE(compoundSpy.finished.count(), 1); 0755 QCOMPARE(compoundSpy.result.count(), 1); 0756 0757 QFETCH(const KJob::KillVerbosity, killVerbosity); 0758 QVERIFY(compoundJob->kill(killVerbosity)); 0759 QCOMPARE(compoundSpy.finished.count(), 1); 0760 QCOMPARE(compoundSpy.result.count(), 1); 0761 QCOMPARE(compoundJob->error(), 0); 0762 QCOMPARE(compoundJob->errorText(), ""); 0763 0764 QVERIFY(compoundJob); 0765 for (const auto &spy : subjobSpies) { 0766 QVERIFY(spy->job); 0767 QCOMPARE(spy->job->error(), 0); 0768 QCOMPARE(spy->job->errorText(), ""); 0769 } 0770 QTest::qWait(1); 0771 QVERIFY(!compoundJob); 0772 for (const auto &spy : subjobSpies) { 0773 QVERIFY(!spy->job); 0774 QCOMPARE(spy->started.count(), 1); 0775 QCOMPARE(spy->killed.count(), 0); 0776 QCOMPARE(spy->finished.count(), 1); 0777 QCOMPARE(spy->result.count(), 1); 0778 } 0779 } 0780 0781 void KSequentialCompoundJobTest::killRunningCompoundJob() 0782 { 0783 QPointer compoundJob(new KSimpleSequentialCompoundJob); 0784 JobSpy compoundSpy(compoundJob); 0785 QVERIFY(compoundJob->capabilities() & KJob::Killable); 0786 0787 auto subjobSpies = generateKillableTestJobSpies(3); 0788 QCOMPARE(subjobSpies.size(), 3); 0789 for (const auto &spy : subjobSpies) { 0790 QVERIFY(compoundJob->addSubjob(spy->job)); 0791 } 0792 const auto &firstSubjobSpy = *subjobSpies.front(); 0793 0794 compoundJob->start(); 0795 QCOMPARE(firstSubjobSpy.started.count(), 1); 0796 QCOMPARE(firstSubjobSpy.finished.count(), 0); 0797 QCOMPARE(compoundSpy.finished.count(), 0); 0798 0799 QVERIFY(compoundJob->kill()); 0800 QCOMPARE(firstSubjobSpy.started.count(), 1); 0801 QCOMPARE(firstSubjobSpy.killed.count(), 1); 0802 QCOMPARE(firstSubjobSpy.killed.constLast().constFirst(), true); 0803 QCOMPARE(firstSubjobSpy.finished.count(), 1); 0804 QCOMPARE(firstSubjobSpy.result.count(), 0); // kill the running subjob quietly 0805 QCOMPARE(compoundSpy.finished.count(), 1); 0806 QCOMPARE(compoundSpy.result.count(), 0); 0807 0808 QCOMPARE(firstSubjobSpy.job->error(), KJob::KilledJobError); 0809 QCOMPARE(compoundJob->error(), KJob::KilledJobError); 0810 QCOMPARE(compoundJob->errorText(), firstSubjobSpy.job->errorText()); 0811 0812 QVERIFY(compoundJob); 0813 for (const auto &spy : subjobSpies) { 0814 QVERIFY(spy->job); 0815 if (spy.get() != &firstSubjobSpy) { 0816 QCOMPARE(spy->job->error(), 0); 0817 QCOMPARE(spy->job->errorText(), ""); 0818 } 0819 } 0820 QTest::qWait(1); 0821 QVERIFY(!compoundJob); 0822 for (const auto &spy : subjobSpies) { 0823 QVERIFY(!spy->job); 0824 const bool isFirstSubjob = spy.get() == &firstSubjobSpy; 0825 QCOMPARE(spy->started.count(), isFirstSubjob); // don't start subjobs once killed 0826 QCOMPARE(spy->killed.count(), isFirstSubjob); // no need to kill unstarted subjobs, just destroy them 0827 QCOMPARE(spy->finished.count(), 1); 0828 QCOMPARE(spy->result.count(), 0); 0829 } 0830 } 0831 0832 void KSequentialCompoundJobTest::killingSubjobFails() 0833 { 0834 QPointer compoundJob(new PublicSequentialCompoundJob); 0835 JobSpy compoundSpy(compoundJob); 0836 QVERIFY(compoundJob->capabilities() & KJob::Killable); 0837 0838 auto subjobSpies = generateKillableTestJobSpies(7); 0839 QCOMPARE(subjobSpies.size(), 7); 0840 for (const auto &spy : subjobSpies) { 0841 QVERIFY(compoundJob->addSubjob(spy->job)); 0842 } 0843 const auto &firstSubjobSpy = *subjobSpies.front(); 0844 firstSubjobSpy.job->setKillingSucceeds(false); 0845 0846 compoundJob->start(); 0847 QCOMPARE(firstSubjobSpy.started.count(), 1); 0848 QCOMPARE(firstSubjobSpy.finished.count(), 0); 0849 QCOMPARE(compoundSpy.finished.count(), 0); 0850 0851 QVERIFY(!compoundJob->kill()); 0852 QCOMPARE(firstSubjobSpy.started.count(), 1); 0853 QCOMPARE(firstSubjobSpy.killed.count(), 1); 0854 QCOMPARE(firstSubjobSpy.killed.constLast().constFirst(), false); 0855 QCOMPARE(firstSubjobSpy.finished.count(), 0); 0856 QCOMPARE(firstSubjobSpy.result.count(), 0); 0857 QCOMPARE(compoundSpy.finished.count(), 0); 0858 QCOMPARE(compoundJob->subjobs().count(), subjobSpies.size()); 0859 0860 QCOMPARE(firstSubjobSpy.job->error(), 0); 0861 QCOMPARE(firstSubjobSpy.job->errorText(), ""); 0862 QCOMPARE(compoundJob->error(), 0); 0863 QCOMPARE(compoundJob->errorText(), ""); 0864 0865 // unstarted subjobs are simply removed when finished, their errors are ignored 0866 0867 const auto &finishedSubjobSpy = *subjobSpies[3]; 0868 finishedSubjobSpy.job->emitResult(); 0869 QCOMPARE(finishedSubjobSpy.started.count(), 0); 0870 QCOMPARE(finishedSubjobSpy.finished.count(), 1); 0871 QCOMPARE(compoundSpy.finished.count(), 0); 0872 QCOMPARE(compoundJob->subjobs().count(), subjobSpies.size() - 1); 0873 QVERIFY(!compoundJob->subjobs().contains(finishedSubjobSpy.job)); 0874 0875 const auto &errorSubjobSpy = *subjobSpies[1]; 0876 errorSubjobSpy.job->setError(142); 0877 errorSubjobSpy.job->emitResult(); 0878 QCOMPARE(errorSubjobSpy.started.count(), 0); 0879 QCOMPARE(errorSubjobSpy.finished.count(), 1); 0880 QCOMPARE(compoundSpy.finished.count(), 0); 0881 QCOMPARE(compoundJob->subjobs().count(), subjobSpies.size() - 2); 0882 QVERIFY(!compoundJob->subjobs().contains(errorSubjobSpy.job)); 0883 0884 const auto &killedSubjobSpy = *subjobSpies[4]; 0885 QVERIFY(killedSubjobSpy.job->kill()); 0886 QCOMPARE(killedSubjobSpy.started.count(), 0); 0887 QCOMPARE(killedSubjobSpy.finished.count(), 1); 0888 QCOMPARE(killedSubjobSpy.result.count(), 0); 0889 QCOMPARE(compoundSpy.finished.count(), 0); 0890 QCOMPARE(compoundJob->subjobs().count(), subjobSpies.size() - 3); 0891 QVERIFY(!compoundJob->subjobs().contains(killedSubjobSpy.job)); 0892 0893 QCOMPARE(compoundJob->error(), 0); 0894 QCOMPARE(compoundJob->errorText(), ""); 0895 0896 firstSubjobSpy.job->emitResult(); 0897 QCOMPARE(firstSubjobSpy.started.count(), 1); 0898 QCOMPARE(firstSubjobSpy.killed.count(), 1); 0899 QCOMPARE(firstSubjobSpy.finished.count(), 1); 0900 QCOMPARE(firstSubjobSpy.result.count(), 1); 0901 QCOMPARE(compoundSpy.finished.count(), 1); 0902 QCOMPARE(compoundSpy.result.count(), 1); 0903 0904 QCOMPARE(firstSubjobSpy.job->error(), 0); 0905 // the compound job was killed, so it should report KilledJobError, even if the killed subjob does not 0906 QCOMPARE(compoundJob->error(), KJob::KilledJobError); 0907 QCOMPARE(compoundJob->errorText(), firstSubjobSpy.job->errorText()); 0908 0909 QVERIFY(compoundJob); 0910 for (const auto &spy : subjobSpies) { 0911 QVERIFY(spy->job); 0912 } 0913 QTest::qWait(1); 0914 QVERIFY(!compoundJob); 0915 for (const auto &spy : subjobSpies) { 0916 QVERIFY(!spy->job); 0917 const bool isFirstSubjob = spy.get() == &firstSubjobSpy; 0918 QCOMPARE(spy->started.count(), isFirstSubjob); // don't start subjobs once killed 0919 QCOMPARE(spy->killed.count(), isFirstSubjob || spy.get() == &killedSubjobSpy); 0920 QCOMPARE(spy->finished.count(), 1); 0921 QCOMPARE(spy->result.count(), isFirstSubjob || spy.get() == &finishedSubjobSpy || spy.get() == &errorSubjobSpy); 0922 } 0923 } 0924 0925 void KSequentialCompoundJobTest::killRunningCompoundJobRepeatedly_data() 0926 { 0927 QTest::addColumn<int>("killAttempts"); 0928 QTest::addColumn<int>("successfulKillAttempts"); 0929 QTest::addColumn<bool>("destroyKilledSubjob"); 0930 for (int killAttempts = 1; killAttempts <= 3; ++killAttempts) { 0931 for (int successfulKillAttempts = 0; successfulKillAttempts <= killAttempts; ++successfulKillAttempts) { 0932 QTest::addRow("attempts-%d-successful-%d", killAttempts, successfulKillAttempts) << killAttempts << successfulKillAttempts << false; 0933 if (successfulKillAttempts == 0) { 0934 QTest::addRow("attempts-%d-successful-%d-destroy-killed-subjob", killAttempts, successfulKillAttempts) 0935 << killAttempts << successfulKillAttempts << true; 0936 } 0937 } 0938 } 0939 } 0940 0941 void KSequentialCompoundJobTest::killRunningCompoundJobRepeatedly() 0942 { 0943 QPointer compoundJob(new KSimpleSequentialCompoundJob); 0944 JobSpy compoundSpy(compoundJob); 0945 QVERIFY(compoundJob->capabilities() & KJob::Killable); 0946 0947 // The number of subjobs is independent from and unrelated to the number of kill attempts. 0948 auto subjobSpies = generateKillableTestJobSpies(3); 0949 QCOMPARE(subjobSpies.size(), 3); 0950 for (const auto &spy : subjobSpies) { 0951 QVERIFY(compoundJob->addSubjob(spy->job)); 0952 } 0953 const auto &firstSubjobSpy = *subjobSpies.front(); 0954 0955 compoundJob->start(); 0956 QCOMPARE(firstSubjobSpy.started.count(), 1); 0957 QCOMPARE(firstSubjobSpy.finished.count(), 0); 0958 QCOMPARE(compoundSpy.finished.count(), 0); 0959 0960 QFETCH(const int, killAttempts); 0961 QFETCH(const int, successfulKillAttempts); 0962 for (int attempt = 0; attempt < killAttempts; ++attempt) { 0963 const bool killingSucceeds = attempt >= killAttempts - successfulKillAttempts; 0964 firstSubjobSpy.job->setKillingSucceeds(killingSucceeds); 0965 QCOMPARE(compoundJob->kill(), killingSucceeds); 0966 // KJob::kill() calls KSequentialCompoundJob::doKill() only if the job has not finished, 0967 // i.e. if the previous killing failed. 0968 const int subjobKillCount = std::min(attempt, killAttempts - successfulKillAttempts) + 1; 0969 0970 QCOMPARE(firstSubjobSpy.started.count(), 1); 0971 QCOMPARE(firstSubjobSpy.killed.count(), subjobKillCount); 0972 if (attempt < subjobKillCount) { 0973 QCOMPARE(firstSubjobSpy.killed.at(attempt).constFirst(), killingSucceeds); 0974 } 0975 QCOMPARE(firstSubjobSpy.finished.count(), killingSucceeds); 0976 QCOMPARE(firstSubjobSpy.result.count(), 0); // kill the running subjob quietly 0977 QCOMPARE(compoundSpy.finished.count(), killingSucceeds); 0978 QCOMPARE(compoundSpy.result.count(), 0); 0979 0980 const auto error = killingSucceeds ? KJob::KilledJobError : KJob::NoError; 0981 QCOMPARE(firstSubjobSpy.job->error(), error); 0982 QCOMPARE(compoundJob->error(), error); 0983 } 0984 0985 QFETCH(const bool, destroyKilledSubjob); 0986 if (destroyKilledSubjob) { 0987 delete firstSubjobSpy.job; 0988 QVERIFY(compoundJob); 0989 QCOMPARE(compoundSpy.result.count(), 1); 0990 } else if (successfulKillAttempts == 0) { 0991 delete compoundJob; 0992 QVERIFY(!compoundJob); 0993 QCOMPARE(compoundSpy.result.count(), 0); 0994 } else { 0995 QVERIFY(compoundJob); 0996 QCOMPARE(compoundSpy.result.count(), 0); // killed quietly in the loop above 0997 } 0998 0999 QCOMPARE(compoundSpy.finished.count(), 1); 1000 QTest::qWait(1); 1001 QVERIFY(!compoundJob); 1002 for (const auto &spy : subjobSpies) { 1003 QVERIFY(!spy->job); 1004 const bool isFirstSubjob = spy.get() == &firstSubjobSpy; 1005 QCOMPARE(spy->started.count(), isFirstSubjob); // don't start subjobs once killed 1006 if (isFirstSubjob) { 1007 QVERIFY(spy->killed.count() <= killAttempts); 1008 } else { 1009 QCOMPARE(spy->killed.count(), 0); 1010 } 1011 QCOMPARE(spy->finished.count(), 1); 1012 QCOMPARE(spy->result.count(), 0); 1013 } 1014 } 1015 1016 QTEST_GUILESS_MAIN(KSequentialCompoundJobTest)