File indexing completed on 2024-04-21 15:03:01

0001 /*
0002     SPDX-FileCopyrightText: 2022 Eduardo Cruz <eduardo.cruz@kdemail.net>
0003     SPDX-License-Identifier: LGPL-2.1-or-later
0004 */
0005 
0006 #include "runnermanager.h"
0007 
0008 #include <KSharedConfig>
0009 #include <QAction>
0010 #include <QCoreApplication>
0011 #include <QObject>
0012 #include <QProcess>
0013 #include <QStandardPaths>
0014 #include <QTest>
0015 
0016 #include "abstractrunnertest.h"
0017 #include "kpluginmetadata_utils_p.h"
0018 
0019 Q_DECLARE_METATYPE(Plasma::QueryMatch)
0020 Q_DECLARE_METATYPE(QList<Plasma::QueryMatch>)
0021 
0022 using namespace Plasma;
0023 
0024 class RunnerManagerTest : public AbstractRunnerTest
0025 {
0026     Q_OBJECT
0027 private Q_SLOTS:
0028     void initTestCase()
0029     {
0030         startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")});
0031         qputenv("XDG_DATA_DIRS", QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation).toLocal8Bit());
0032         QCoreApplication::setLibraryPaths(QStringList());
0033         initProperties();
0034         auto md = parseMetaDataFromDesktopFile(QFINDTESTDATA("dbusrunnertestmulti.desktop"));
0035         QVERIFY(md.isValid());
0036         manager->loadRunner(md);
0037         qRegisterMetaType<QList<Plasma::QueryMatch>>();
0038     }
0039 
0040     void cleanupTestCase()
0041     {
0042         killRunningDBusProcesses();
0043     }
0044 
0045     /**
0046      * This will test the mechanismm that stalls for 250ms before emiting any result in RunnerManager::scheduleMatchesChanged()
0047      * and the mechanism that anticipates the last results emission in RunnerManager::jobDone().
0048      */
0049     void testScheduleMatchesChanged()
0050     {
0051         QSignalSpy spyQueryFinished(manager.get(), &Plasma::RunnerManager::queryFinished);
0052         QSignalSpy spyMatchesChanged(manager.get(), &Plasma::RunnerManager::matchesChanged);
0053 
0054         QVERIFY(spyQueryFinished.isValid());
0055         QVERIFY(spyMatchesChanged.isValid());
0056 
0057         QCOMPARE(spyQueryFinished.count(), 0);
0058 
0059         // This will track the total execution time
0060         QElapsedTimer timer;
0061         timer.start();
0062 
0063         // This special string will simulate a 300ms delay
0064         manager->launchQuery("fooDelay300");
0065 
0066         // However not yet a matcheschanged, it should be stalled for 250ms
0067         QCOMPARE(spyMatchesChanged.count(), 0);
0068 
0069         // After 250ms it will emit with empty matches, we wait for that.
0070         // We can't put a low upper limit on these wait() calls because the CI environment can be slow.
0071         QVERIFY(spyMatchesChanged.wait()); // This should take just a tad longer than 250ms.
0072 
0073         // This should have taken no less than 250ms. It waits for 250s before "giving up" and emitting an empty matches list.
0074         QVERIFY(timer.elapsed() >= 250);
0075         QCOMPARE(spyMatchesChanged.count(), 1);
0076         QCOMPARE(manager->matches().count(), 0); // This is the empty matches "reset" emission, result is not ready yet
0077         QCOMPARE(spyQueryFinished.count(), 0); // Still the same, query is not done
0078 
0079         // We programmed it to emit the result after 300ms, so we need to wait 50ms more for the next emission
0080         QVERIFY(spyQueryFinished.wait());
0081 
0082         // This should have taken at least 300ms total, as we requested via the special query string
0083         QVERIFY(timer.elapsed() >= 300);
0084 
0085         // At this point RunnerManager::jobDone() should have anticipated the final emission.
0086         QCOMPARE(spyMatchesChanged.count(), 2); // We had the second matchesChanged emission, now with the query result
0087         QCOMPARE(manager->matches().count(), 1); // The result is here
0088         QCOMPARE(spyQueryFinished.count(), 1); // Will have emited queryFinished, job is done
0089 
0090         // Now we will make sure that RunnerManager::scheduleMatchesChanged() emits matchesChanged instantly
0091         // if we start a query with an empty string. It will never produce results, stalling is meaningless
0092         manager->launchQuery("");
0093         QCOMPARE(spyMatchesChanged.count(), 3); // One more, instantly, without stall
0094         QCOMPARE(manager->matches().count(), 0); // Empty results for empty query string
0095         QVERIFY(spyQueryFinished.wait());
0096     }
0097 
0098     /**
0099      * This will test queryFinished signal from reset() is emitted when the previous runners are
0100      * still running.
0101      */
0102     void testQueryFinishedFromReset()
0103     {
0104         QSignalSpy spyQueryFinished(manager.get(), &Plasma::RunnerManager::queryFinished);
0105 
0106         manager->launchQuery("fooDelay1000");
0107         QCOMPARE(spyQueryFinished.size(), 0);
0108 
0109         manager->launchQuery("fooDelay300");
0110         QCOMPARE(spyQueryFinished.size(), 1); // From reset()
0111 
0112         QVERIFY(spyQueryFinished.wait());
0113         QCOMPARE(spyQueryFinished.size(), 2);
0114     }
0115 
0116     /**
0117      * When we delete the RunnerManager while a job is still running, we should not crash
0118      */
0119     void testNotCrashWhenDeletingRunnerManager()
0120     {
0121         RunnerManager manager;
0122         manager.setAllowedRunners({QStringLiteral("fakerunnerplugin")});
0123         manager.loadRunner(KPluginMetaData::findPluginById(QStringLiteral("krunnertest"), QStringLiteral("fakerunnerplugin")));
0124 
0125         QCOMPARE(manager.runners().size(), 1);
0126 
0127         manager.launchQuery("somequery");
0128     }
0129 };
0130 
0131 QTEST_MAIN(RunnerManagerTest)
0132 
0133 #include "runnermanagertest.moc"