diff --git a/src/utils/compositejob.cpp b/src/utils/compositejob.cpp index 79c92ca8..b970aba0 100644 --- a/src/utils/compositejob.cpp +++ b/src/utils/compositejob.cpp @@ -1,75 +1,78 @@ /* This file is part of Zanshin Copyright 2014 Mario Bensi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "compositejob.h" using namespace Utils; CompositeJob::CompositeJob(QObject *parent) : KCompositeJob(parent) { } void CompositeJob::start() { if (hasSubjobs()) { subjobs().first()->start(); } else { emitResult(); } } bool CompositeJob::install(KJob *job, const JobHandler::ResultHandlerWithJob &handler) { if (!addSubjob(job)) return false; JobHandler::install(job, handler); return true; } bool CompositeJob::install(KJob *job, const JobHandler::ResultHandler &handler) { JobHandler::install(job, handler); if (!addSubjob(job)) return false; return true; } void CompositeJob::emitError(const QString &errorText) { setError(KJob::UserDefinedError); setErrorText(errorText); emitResult(); } void CompositeJob::slotResult(KJob *job) { - KCompositeJob::slotResult(job); - - if (!hasSubjobs()) - emitResult(); + if (job->error()) { + KCompositeJob::slotResult(job); + } else { + removeSubjob(job); + if (!hasSubjobs()) + emitResult(); + } } diff --git a/tests/units/utils/compositejobtest.cpp b/tests/units/utils/compositejobtest.cpp index d94a1687..694dca98 100644 --- a/tests/units/utils/compositejobtest.cpp +++ b/tests/units/utils/compositejobtest.cpp @@ -1,156 +1,186 @@ /* This file is part of Zanshin Copyright 2014 Mario Bensi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "utils/compositejob.h" #include "testlib/fakejob.h" using namespace Utils; class CompositeJobTest : public QObject { Q_OBJECT public: explicit CompositeJobTest(QObject *parent = Q_NULLPTR) : QObject(parent) , m_callCount(0) { } private: int m_callCount; private slots: void shouldCallHandlers() { // GIVEN int callCount = 0; auto handler = [&]() { callCount++; }; FakeJob *job1 = new FakeJob(this); FakeJob *job2 = new FakeJob(this); CompositeJob *compositeJob = new CompositeJob(this); compositeJob->setAutoDelete(false); QVERIFY(compositeJob->install(job1, handler)); QVERIFY(compositeJob->install(job2, handler)); // WHEN compositeJob->start(); QTest::qWait(FakeJob::DURATION + 10); // THEN QCOMPARE(callCount, 2); QVERIFY(!compositeJob->error()); delete compositeJob; } void shouldCallHandlersWithJob() { // GIVEN int callCount = 0; QList seenJobs; auto handlerWithJob = [&](KJob *job) { callCount++; seenJobs << job; }; FakeJob *job1 = new FakeJob(this); FakeJob *job2 = new FakeJob(this); CompositeJob *compositeJob = new CompositeJob(this); compositeJob->setAutoDelete(false); QVERIFY(compositeJob->install(job1, handlerWithJob)); QVERIFY(compositeJob->install(job2, handlerWithJob)); // WHEN compositeJob->start(); QTest::qWait(FakeJob::DURATION + 10); // THEN QCOMPARE(callCount, 2); QCOMPARE(seenJobs.toSet(), QSet() << job1 << job2); QVERIFY(!compositeJob->error()); delete compositeJob; } void handleJobResult(KJob*) { m_callCount++; } void shouldCallJobInHandler() { // GIVEN CompositeJob *compositeJob = new CompositeJob(this); compositeJob->setAutoDelete(false); auto handler = [&]() { FakeJob *job2 = new FakeJob(this); QObject::connect(job2, &KJob::result, this, &CompositeJobTest::handleJobResult); compositeJob->addSubjob(job2); job2->start(); }; FakeJob *job1 = new FakeJob(this); QVERIFY(compositeJob->install(job1, handler)); // WHEN compositeJob->start(); QTest::qWait(FakeJob::DURATION*2 + 10); QCOMPARE(m_callCount, 1); QVERIFY(!compositeJob->error()); delete compositeJob; } void shouldEmitErrorFromHandler() { // GIVEN CompositeJob *compositeJob = new CompositeJob(this); compositeJob->setAutoDelete(false); auto handler = [&]() { compositeJob->emitError(QStringLiteral("Error reached")); }; FakeJob *job = new FakeJob(this); QVERIFY(compositeJob->install(job, handler)); // WHEN compositeJob->start(); QTest::qWait(FakeJob::DURATION*2 + 10); QCOMPARE(compositeJob->error(), static_cast(KJob::UserDefinedError)); QCOMPARE(compositeJob->errorText(), QStringLiteral("Error reached")); delete compositeJob; } + + void shouldNotEmitResultTwiceOnSecondSubJobError() + { + // GIVEN + int callCount = 0; + + auto handler = [&]() { + callCount++; + }; + + FakeJob *job1 = new FakeJob(this); + FakeJob *job2 = new FakeJob(this); + job2->setExpectedError(KJob::UserDefinedError, "Fake error"); + + CompositeJob *compositeJob = new CompositeJob(this); + compositeJob->setAutoDelete(false); + compositeJob->install(job1, handler); + compositeJob->install(job2, handler); + + QSignalSpy spy(compositeJob, &KJob::result); + + // WHEN + compositeJob->start(); + QTest::qWait(FakeJob::DURATION*2 + 10); + + // THEN + QCOMPARE(spy.count(), 1); + delete compositeJob; + + } }; ZANSHIN_TEST_MAIN(CompositeJobTest) #include "compositejobtest.moc"