File indexing completed on 2024-04-14 03:54:30
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 <QCoreApplication> 0010 #include <QObject> 0011 #include <QProcess> 0012 #include <QStandardPaths> 0013 #include <QTest> 0014 0015 #include "abstractrunnertest.h" 0016 #include "kpluginmetadata_utils_p.h" 0017 0018 Q_DECLARE_METATYPE(KRunner::QueryMatch) 0019 Q_DECLARE_METATYPE(QList<KRunner::QueryMatch>) 0020 0021 using namespace KRunner; 0022 namespace KRunner 0023 { 0024 extern int __changeCountBeforeSaving; 0025 } 0026 0027 class RunnerManagerTest : public AbstractRunnerTest 0028 { 0029 Q_OBJECT 0030 private Q_SLOTS: 0031 void initTestCase() 0032 { 0033 __changeCountBeforeSaving = 1; 0034 startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")}); 0035 qputenv("XDG_DATA_DIRS", QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation).toLocal8Bit()); 0036 QCoreApplication::setLibraryPaths(QStringList()); 0037 initProperties(); 0038 qRegisterMetaType<QList<KRunner::QueryMatch>>(); 0039 } 0040 0041 void cleanupTestCase() 0042 { 0043 killRunningDBusProcesses(); 0044 } 0045 0046 /** 0047 * This will test the mechanismm that stalls for 250ms before emiting any result in RunnerManager::scheduleMatchesChanged() 0048 * and the mechanism that anticipates the last results emission in RunnerManager::jobDone(). 0049 */ 0050 void testScheduleMatchesChanged() 0051 { 0052 QSignalSpy spyQueryFinished(manager.get(), &KRunner::RunnerManager::queryFinished); 0053 QSignalSpy spyMatchesChanged(manager.get(), &KRunner::RunnerManager::matchesChanged); 0054 0055 QVERIFY(spyQueryFinished.isValid()); 0056 QVERIFY(spyMatchesChanged.isValid()); 0057 0058 QCOMPARE(spyQueryFinished.count(), 0); 0059 0060 // This will track the total execution time 0061 QElapsedTimer timer; 0062 timer.start(); 0063 0064 // This special string will simulate a 300ms delay 0065 manager->launchQuery("fooDelay300"); 0066 0067 // However not yet a matcheschanged, it should be stalled for 250ms 0068 QCOMPARE(spyMatchesChanged.count(), 0); 0069 0070 // After 250ms it will emit with empty matches, we wait for that. 0071 // We can't put a low upper limit on these wait() calls because the CI environment can be slow. 0072 QVERIFY(spyMatchesChanged.wait()); // This should take just a tad longer than 250ms. 0073 0074 // This should have taken no less than 250ms. It waits for 250s before "giving up" and emitting an empty matches list. 0075 QVERIFY(timer.elapsed() >= 250); 0076 QCOMPARE(spyMatchesChanged.count(), 1); 0077 QCOMPARE(manager->matches().count(), 0); // This is the empty matches "reset" emission, result is not ready yet 0078 QCOMPARE(spyQueryFinished.count(), 0); // Still the same, query is not done 0079 0080 // We programmed it to emit the result after 300ms, so we need to wait 50ms more for the next emission 0081 QVERIFY(spyQueryFinished.wait()); 0082 0083 // This should have taken at least 300ms total, as we requested via the special query string 0084 QVERIFY(timer.elapsed() >= 300); 0085 0086 // At this point RunnerManager::jobDone() should have anticipated the final emission. 0087 QCOMPARE(manager->matches().count(), 1); // The result is here 0088 QCOMPARE(spyQueryFinished.count(), 1); // Will have emited queryFinished, job is done 0089 QCOMPARE(spyMatchesChanged.count(), 2); // We had the second matchesChanged emission, now with the query result 0090 0091 // Now we will make sure that RunnerManager::scheduleMatchesChanged() emits matchesChanged instantly 0092 // if we start a query with an empty string. It will never produce results, stalling is meaningless 0093 manager->launchQuery(""); 0094 QCOMPARE(spyMatchesChanged.count(), 3); // One more, instantly, without stall 0095 QCOMPARE(manager->matches().count(), 0); // Empty results for empty query string 0096 QVERIFY(spyQueryFinished.wait()); 0097 } 0098 0099 /** 0100 * This will test queryFinished signal from reset() is emitted when the previous runners are 0101 * still running. 0102 */ 0103 void testQueryFinishedFromReset() 0104 { 0105 QSignalSpy spyQueryFinished(manager.get(), &KRunner::RunnerManager::queryFinished); 0106 0107 manager->launchQuery("fooDelay1000"); 0108 QTest::qSleep(500); 0109 QCOMPARE(spyQueryFinished.size(), 0); 0110 0111 manager->launchQuery("fooDelay300"); 0112 QCOMPARE(spyQueryFinished.size(), 1); // From reset() 0113 0114 QVERIFY(spyQueryFinished.wait()); 0115 QCOMPARE(spyQueryFinished.size(), 2); 0116 } 0117 0118 /** 0119 * When we delete the RunnerManager while a job is still running, we should not crash 0120 */ 0121 void testNotCrashWhenDeletingRunnerManager() 0122 { 0123 RunnerManager manager; 0124 manager.setAllowedRunners({QStringLiteral("fakerunnerplugin")}); 0125 manager.loadRunner(KPluginMetaData::findPluginById(QStringLiteral("krunnertest"), QStringLiteral("fakerunnerplugin"))); 0126 0127 QCOMPARE(manager.runners().size(), 1); 0128 0129 manager.launchQuery("somequery"); 0130 } 0131 0132 void testRunnerManagerStateGroups() 0133 { 0134 auto stateGrp = KSharedConfig::openConfig(QString(), KConfig::NoGlobals)->group("Testme"); 0135 auto configGrp = KSharedConfig::openConfig(QString(), KConfig::NoGlobals)->group("Plugins"); 0136 stateGrp.deleteGroup(); 0137 RunnerManager manager(configGrp, stateGrp, this); 0138 manager.setAllowedRunners({QStringLiteral("fakerunnerplugin")}); 0139 manager.loadRunner(KPluginMetaData::findPluginById(QStringLiteral("krunnertest"), QStringLiteral("fakerunnerplugin"))); 0140 QSignalSpy spyQueryFinished(&manager, &KRunner::RunnerManager::queryFinished); 0141 0142 manager.launchQuery("foo"); 0143 spyQueryFinished.wait(); 0144 manager.run(manager.matches().constFirst()); 0145 manager.matchSessionComplete(); 0146 QCOMPARE(stateGrp.readEntry("LaunchCounts"), "1 foo"); 0147 QCOMPARE(stateGrp.config()->groupList().size(), 1); 0148 } 0149 0150 void testRunnerSuspendWhileReloadingConfig() 0151 { 0152 RunnerManager manager; 0153 manager.loadRunner(KPluginMetaData::findPluginById(QStringLiteral("krunnertest2"), QStringLiteral("suspendedrunnerplugin"))); 0154 QCOMPARE(manager.runners().size(), 1); 0155 0156 AbstractRunner *runner = manager.runners().constFirst(); 0157 QVERIFY(runner->isMatchingSuspended()); 0158 0159 QSignalSpy spy(&manager, &KRunner::RunnerManager::queryFinished); 0160 manager.launchQuery("foo"); 0161 QVERIFY2(spy.wait(), "RunnerManager did not emit the queryFinished signal"); 0162 0163 QCOMPARE(manager.matches().size(), 1); 0164 0165 QVERIFY(!runner->isMatchingSuspended()); 0166 } 0167 0168 void testAbstractRunnerTestTimeout() 0169 { 0170 QEXPECT_FAIL("", "This test is expected to fail", Continue); 0171 const auto matches = launchQuery("fooDelay6000"); 0172 QVERIFY(matches.isEmpty()); 0173 } 0174 }; 0175 0176 QTEST_MAIN(RunnerManagerTest) 0177 0178 #include "runnermanagertest.moc"