File indexing completed on 2024-05-05 12:21:33

0001 /*
0002     SPDX-FileCopyrightText: 2020 Alexander Lohnau <alexander.lohnau@gmx.de>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #ifndef PLASMA_ABSTRACTRUNNERTEST_H
0007 #define PLASMA_ABSTRACTRUNNERTEST_H
0008 
0009 #include <KPluginMetaData>
0010 #include <KRunner/AbstractRunner>
0011 #include <KRunner/RunnerManager>
0012 #include <QStandardPaths>
0013 
0014 #include <QSignalSpy>
0015 #include <QTest>
0016 #if KRUNNER_DBUS_RUNNER_TESTING
0017 #include <QDBusConnection>
0018 #include <QDBusServiceWatcher>
0019 #endif
0020 
0021 namespace
0022 {
0023 /**
0024  * This class provides a basic structure for a runner test.
0025  * The compile definitions should be configured using the `add_krunner_test` cmake macro
0026  * @since 5.80
0027  */
0028 class AbstractRunnerTest : public QObject
0029 {
0030 public:
0031     using QObject::QObject;
0032     std::unique_ptr<Plasma::RunnerManager> manager = nullptr;
0033     Plasma::AbstractRunner *runner = nullptr;
0034 
0035     /**
0036      * Load the runner and set the manager and runner properties.
0037      */
0038     void initProperties()
0039     {
0040         qputenv("LC_ALL", "C.utf-8");
0041         manager.reset(new Plasma::RunnerManager());
0042 
0043 #if KRUNNER_DBUS_RUNNER_TESTING
0044         auto md = manager->convertDBusRunnerToJson(QStringLiteral(KRUNNER_TEST_DESKTOP_FILE));
0045         QVERIFY(md.isValid());
0046         manager->loadRunner(md);
0047 #else
0048         const QString pluginId = QFileInfo(QStringLiteral(KRUNNER_TEST_RUNNER_PLUGIN_NAME)).completeBaseName();
0049         auto metaData = KPluginMetaData::findPluginById(QStringLiteral(KRUNNER_TEST_RUNNER_PLUGIN_DIR), pluginId);
0050         QVERIFY2(metaData.isValid(), qPrintable("Could not find plugin " + pluginId + " in folder " + KRUNNER_TEST_RUNNER_PLUGIN_DIR));
0051 
0052         // Set internal variables
0053         manager->loadRunner(metaData);
0054 #endif
0055         QCOMPARE(manager->runners().count(), 1);
0056         runner = manager->runners().constFirst();
0057 
0058         // Just make sure all went well
0059         QVERIFY(runner);
0060     }
0061 
0062     /**
0063      * Launch a query and wait for the RunnerManager to finish
0064      * @param query
0065      * @param runnerName
0066      */
0067     void launchQuery(const QString &query, const QString &runnerName = QString())
0068     {
0069         QSignalSpy spy(manager.get(), &Plasma::RunnerManager::queryFinished);
0070         manager->launchQuery(query, runnerName);
0071         QVERIFY2(spy.wait(), "RunnerManager did not emit the queryFinished signal");
0072     }
0073 #if KRUNNER_DBUS_RUNNER_TESTING
0074     /**
0075      * Launch the configured DBus executable with the given arguments and wait for the process to be started.
0076      * @param args
0077      * @param waitForService Wait for this service to be registered, this will default to the service from the metadata
0078      * @return Process that was successfully started
0079      */
0080     QProcess *startDBusRunnerProcess(const QStringList &args = {}, const QString waitForService = QString())
0081     {
0082         qputenv("LC_ALL", "C.utf-8");
0083         QProcess *process = new QProcess();
0084         auto md = manager->convertDBusRunnerToJson(QStringLiteral(KRUNNER_TEST_DESKTOP_FILE));
0085         QString serviceToWatch = waitForService;
0086         if (serviceToWatch.isEmpty()) {
0087             serviceToWatch = md.value(QStringLiteral("X-Plasma-DBusRunner-Service"));
0088         }
0089         QDBusServiceWatcher watcher(serviceToWatch, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration);
0090 
0091         QEventLoop loop;
0092         connect(&watcher, &QDBusServiceWatcher::serviceRegistered, &loop, &QEventLoop::quit);
0093         process->start(QStringLiteral(KRUNNER_TEST_DBUS_EXECUTABLE), args);
0094         loop.exec();
0095 
0096         Q_ASSERT(process->state() == QProcess::ProcessState::Running);
0097         m_runningProcesses << process;
0098         return process;
0099     }
0100 
0101     /**
0102      * Kill all processes that got started with the startDBusRunnerProcess
0103      */
0104     void killRunningDBusProcesses()
0105     {
0106         for (auto &process : std::as_const(m_runningProcesses)) {
0107             process->kill();
0108             QVERIFY(process->waitForFinished());
0109         }
0110         qDeleteAll(m_runningProcesses);
0111         m_runningProcesses.clear();
0112     }
0113 
0114 private:
0115     QList<QProcess *> m_runningProcesses;
0116 #endif
0117 };
0118 }
0119 
0120 #endif