File indexing completed on 2024-04-21 03:56:46
0001 /* 0002 SPDX-FileCopyrightText: 2017 David Edmundson <davidedmundson@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include <KRunner/Action> 0008 #include <KRunner/RunnerManager> 0009 #include <QObject> 0010 #include <QProcess> 0011 #include <QSignalSpy> 0012 #include <QStandardPaths> 0013 #include <QTest> 0014 #include <QTime> 0015 #include <QTimer> 0016 0017 #include "abstractrunnertest.h" 0018 #include "kpluginmetadata_utils_p.h" 0019 0020 using namespace KRunner; 0021 0022 Q_DECLARE_METATYPE(KRunner::QueryMatch) 0023 Q_DECLARE_METATYPE(QList<KRunner::QueryMatch>) 0024 0025 class DBusRunnerTest : public AbstractRunnerTest 0026 { 0027 Q_OBJECT 0028 public: 0029 DBusRunnerTest(); 0030 ~DBusRunnerTest() override; 0031 0032 private Q_SLOTS: 0033 void cleanup(); 0034 void testMatch(); 0035 void testMulti(); 0036 void testFilterProperties(); 0037 void testFilterProperties_data(); 0038 void testRequestActionsOnce(); 0039 void testDBusRunnerSyntaxIntegration(); 0040 void testIconData(); 0041 void testLifecycleMethods(); 0042 void testRequestActionsWildcards(); 0043 }; 0044 0045 DBusRunnerTest::DBusRunnerTest() 0046 : AbstractRunnerTest() 0047 { 0048 qRegisterMetaType<QList<KRunner::QueryMatch>>(); 0049 QStandardPaths::setTestModeEnabled(true); 0050 } 0051 0052 DBusRunnerTest::~DBusRunnerTest() 0053 { 0054 } 0055 0056 void DBusRunnerTest::cleanup() 0057 { 0058 // Make sure kill the running processes after each test 0059 killRunningDBusProcesses(); 0060 } 0061 0062 void DBusRunnerTest::testMatch() 0063 { 0064 QProcess *process = startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")}); 0065 initProperties(); 0066 const auto matches = launchQuery(QStringLiteral("foo")); 0067 0068 // verify matches 0069 QCOMPARE(matches.count(), 1); 0070 auto result = matches.first(); 0071 0072 // see testremoterunner.cpp 0073 QCOMPARE(result.id(), QStringLiteral("dbusrunnertest_id1")); // note the runner name is prepended 0074 QCOMPARE(result.text(), QStringLiteral("Match 1")); 0075 QCOMPARE(result.iconName(), QStringLiteral("icon1")); 0076 QCOMPARE(result.categoryRelevance(), qToUnderlying(KRunner::QueryMatch::CategoryRelevance::Highest)); 0077 QCOMPARE(result.isMultiLine(), true); 0078 // relevance can't be compared easily because RunnerContext meddles with it 0079 0080 // verify actions 0081 QCOMPARE(result.actions().size(), 1); 0082 auto action = result.actions().constFirst(); 0083 0084 QCOMPARE(action.text(), QStringLiteral("Action 1")); 0085 0086 QSignalSpy processSpy(process, &QProcess::readyRead); 0087 manager->run(result); 0088 processSpy.wait(); 0089 QCOMPARE(process->readAllStandardOutput().trimmed().split('\n').constLast(), QByteArray("Running:id1:")); 0090 0091 manager->run(result, action); 0092 processSpy.wait(); 0093 QCOMPARE(process->readAllStandardOutput().trimmed().split('\n').constLast(), QByteArray("Running:id1:action1")); 0094 } 0095 0096 void DBusRunnerTest::testMulti() 0097 { 0098 startDBusRunnerProcess({QStringLiteral("net.krunnertests.multi.a1")}, QStringLiteral("net.krunnertests.multi.a1")); 0099 startDBusRunnerProcess({QStringLiteral("net.krunnertests.multi.a2")}, QStringLiteral("net.krunnertests.multi.a2")); 0100 manager.reset(new RunnerManager()); // This case is special, because we want to load the runners manually 0101 0102 auto md = parseMetaDataFromDesktopFile(QFINDTESTDATA("plugins/dbusrunnertestmulti.desktop")); 0103 QVERIFY(md.isValid()); 0104 manager->loadRunner(md); 0105 const auto matches = launchQuery(QStringLiteral("foo")); 0106 0107 // verify matches, must be one from each 0108 QCOMPARE(matches.count(), 2); 0109 0110 const QString first = matches.at(0).data().toList().constFirst().toString(); 0111 const QString second = matches.at(1).data().toList().constFirst().toString(); 0112 QVERIFY(first != second); 0113 QVERIFY(first == QLatin1String("net.krunnertests.multi.a1") || first == QStringLiteral("net.krunnertests.multi.a2")); 0114 QVERIFY(second == QLatin1String("net.krunnertests.multi.a1") || second == QStringLiteral("net.krunnertests.multi.a2")); 0115 } 0116 0117 void DBusRunnerTest::testRequestActionsOnce() 0118 { 0119 QProcess *process = startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")}); 0120 initProperties(); 0121 0122 launchQuery(QStringLiteral("foo")); 0123 QVERIFY(!manager->matches().constFirst().actions().isEmpty()); 0124 manager->matchSessionComplete(); 0125 launchQuery(QStringLiteral("fooo")); 0126 const QString processOutput(process->readAllStandardOutput()); 0127 QCOMPARE(processOutput.count("Matching"), 2); 0128 QCOMPARE(processOutput.count("Actions"), 1); 0129 QVERIFY(!manager->matches().constFirst().actions().isEmpty()); 0130 } 0131 0132 void DBusRunnerTest::testFilterProperties_data() 0133 { 0134 QTest::addColumn<QString>("rejectedQuery"); 0135 QTest::addColumn<QString>("acceptedQuery"); 0136 0137 QTest::newRow("min-letter-count") << "fo" 0138 << "foo"; 0139 QTest::newRow("match-regex") << "barfoo" 0140 << "foobar"; 0141 } 0142 0143 void DBusRunnerTest::testFilterProperties() 0144 { 0145 QFETCH(QString, rejectedQuery); 0146 QFETCH(QString, acceptedQuery); 0147 QProcess *process = startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")}); 0148 initProperties(); 0149 0150 launchQuery(rejectedQuery); 0151 // Match method was not called, because of the min letter count or match regex property 0152 QVERIFY(process->readAllStandardOutput().isEmpty()); 0153 // accepted query fits those constraints 0154 launchQuery(acceptedQuery); 0155 QCOMPARE(QString(process->readAllStandardOutput()).remove("Actions").trimmed(), QStringLiteral("Matching:") + acceptedQuery); 0156 } 0157 0158 void DBusRunnerTest::testDBusRunnerSyntaxIntegration() 0159 { 0160 startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")}); 0161 initProperties(); 0162 const QList<RunnerSyntax> syntaxes = runner->syntaxes(); 0163 QCOMPARE(syntaxes.size(), 2); 0164 0165 QCOMPARE(syntaxes.at(0).exampleQueries().size(), 1); 0166 QCOMPARE(syntaxes.at(0).exampleQueries().constFirst(), QStringLiteral("syntax1")); 0167 QCOMPARE(syntaxes.at(0).description(), QStringLiteral("description1")); 0168 QCOMPARE(syntaxes.at(1).exampleQueries().size(), 1); 0169 QCOMPARE(syntaxes.at(1).exampleQueries().constFirst(), QStringLiteral("syntax2")); 0170 QCOMPARE(syntaxes.at(1).description(), QStringLiteral("description2")); 0171 } 0172 0173 void DBusRunnerTest::testIconData() 0174 { 0175 startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave")}); 0176 initProperties(); 0177 0178 const auto matches = launchQuery(QStringLiteral("fooCostomIcon")); 0179 QCOMPARE(matches.count(), 1); 0180 auto result = matches.first(); 0181 0182 QImage expectedIcon(10, 10, QImage::Format_RGBA8888); 0183 expectedIcon.fill(Qt::blue); 0184 0185 QCOMPARE(result.icon().availableSizes().first(), QSize(10, 10)); 0186 QCOMPARE(result.icon().pixmap(QSize(10, 10)), QPixmap::fromImage(expectedIcon)); 0187 } 0188 0189 void DBusRunnerTest::testLifecycleMethods() 0190 { 0191 QProcess *process = startDBusRunnerProcess({QStringLiteral("net.krunnertests.dave"), QString()}); 0192 manager.reset(new RunnerManager()); // This case is special, because we want to load the runners manually 0193 auto md = parseMetaDataFromDesktopFile(QFINDTESTDATA("plugins/dbusrunnertestruntimeconfig.desktop")); 0194 manager->loadRunner(md); 0195 QCOMPARE(manager->runners().count(), 1); 0196 // Match session should be set up automatically 0197 launchQuery(QStringLiteral("fooo")); 0198 0199 // Make sure we got our match, end the match session and give the process a bit of time to get the DBus signal 0200 QTRY_COMPARE_WITH_TIMEOUT(manager->matches().count(), 1, 2000); 0201 manager->matchSessionComplete(); 0202 QTest::qWait(500); 0203 0204 const QStringList lifeCycleSteps = QString::fromLocal8Bit(process->readAllStandardOutput()).split(QLatin1Char('\n'), Qt::SkipEmptyParts); 0205 const QStringList expectedLifeCycleSteps = { 0206 QStringLiteral("Config"), 0207 QStringLiteral("Actions"), 0208 QStringLiteral("Matching:fooo"), 0209 QStringLiteral("Teardown"), 0210 }; 0211 QCOMPARE(lifeCycleSteps, expectedLifeCycleSteps); 0212 0213 // The query does not match our min letter count we set at runtime 0214 launchQuery(QStringLiteral("foo")); 0215 QVERIFY(manager->matches().isEmpty()); 0216 // The query does not match our match regex we set at runtime 0217 launchQuery(QStringLiteral("barfoo")); 0218 QVERIFY(manager->matches().isEmpty()); 0219 } 0220 0221 void DBusRunnerTest::testRequestActionsWildcards() 0222 { 0223 initProperties(); 0224 manager.reset(new RunnerManager()); // This case is special, because we want to load the runners manually 0225 auto md = parseMetaDataFromDesktopFile(QFINDTESTDATA("plugins/dbusrunnertestmulti.desktop")); 0226 QVERIFY(md.isValid()); 0227 manager->loadRunner(md); 0228 QCOMPARE(manager->runners().count(), 1); 0229 0230 startDBusRunnerProcess({QStringLiteral("net.krunnertests.multi.a1")}, QStringLiteral("net.krunnertests.multi.a1")); 0231 startDBusRunnerProcess({QStringLiteral("net.krunnertests.multi.a2")}, QStringLiteral("net.krunnertests.multi.a2")); 0232 const auto matches = launchQuery("foo"); 0233 QCOMPARE(matches.count(), 2); 0234 0235 QCOMPARE(matches.at(0).actions().count(), 1); 0236 QCOMPARE(matches.at(0).actions(), matches.at(1).actions()); 0237 } 0238 0239 QTEST_MAIN(DBusRunnerTest) 0240 0241 #include "dbusrunnertest.moc"