You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
9.9 KiB
290 lines
9.9 KiB
/* |
|
SPDX-FileCopyrightText: 2016-2021 Harald Sitter <sitter@kde.org> |
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
|
*/ |
|
|
|
#include <QDebug> |
|
#include <QDir> |
|
#include <QFile> |
|
#include <QObject> |
|
#include <QStandardPaths> |
|
#include <QTest> |
|
#include <QThread> |
|
|
|
#include <KSycoca> |
|
|
|
#include "../servicerunner.h" |
|
|
|
#include <clocale> |
|
#include <optional> |
|
#include <sys/types.h> |
|
#include <unistd.h> |
|
|
|
class ServiceRunnerTest : public QObject |
|
{ |
|
Q_OBJECT |
|
private Q_SLOTS: |
|
void initTestCase(); |
|
void cleanupTestCase(); |
|
|
|
void testExcutableExactMatch(); |
|
void testChromeAppsRelevance(); |
|
void testKonsoleVsYakuakeComment(); |
|
void testSystemSettings(); |
|
void testSystemSettings2(); |
|
void testCategories(); |
|
void testJumpListActions(); |
|
void testINotifyUsage(); |
|
}; |
|
|
|
void ServiceRunnerTest::initTestCase() |
|
{ |
|
QStandardPaths::setTestModeEnabled(true); |
|
|
|
auto appsPath = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation); |
|
QDir(appsPath).removeRecursively(); |
|
QVERIFY(QDir().mkpath(appsPath)); |
|
auto fixtureDir = QDir(QFINDTESTDATA("fixtures")); |
|
const auto infoList = fixtureDir.entryInfoList(QDir::Files); |
|
for (const auto &fileInfo : infoList) { |
|
auto source = fileInfo.absoluteFilePath(); |
|
auto target = appsPath + QDir::separator() + fileInfo.fileName(); |
|
QVERIFY2(QFile::copy(fileInfo.absoluteFilePath(), target), qPrintable(QStringLiteral("can't copy %1 => %2").arg(source, target))); |
|
} |
|
|
|
setlocale(LC_ALL, "C.utf8"); |
|
|
|
KSycoca::self()->ensureCacheValid(); |
|
|
|
// Make sure noDisplay behaves consistently WRT OnlyShowIn etc. |
|
QVERIFY(setenv("XDG_CURRENT_DESKTOP", "KDE", 1) == 0); |
|
// NOTE: noDisplay also includes X-KDE-OnlyShowOnQtPlatforms which is a bit harder to fake |
|
// and not currently under testing anyway. |
|
} |
|
|
|
void ServiceRunnerTest::cleanupTestCase() |
|
{ |
|
} |
|
|
|
void ServiceRunnerTest::testExcutableExactMatch() |
|
{ |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
context.setQuery(QStringLiteral("Virtual Machine Manager ServiceRunnerTest")); // virt-manager.desktop |
|
|
|
runner.match(context); |
|
auto matches = context.matches(); |
|
QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Virtual Machine Manager ServiceRunnerTest") && match.relevance() == 1; |
|
})); |
|
} |
|
|
|
void ServiceRunnerTest::testChromeAppsRelevance() |
|
{ |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
context.setQuery(QStringLiteral("chrome")); |
|
|
|
runner.match(context); |
|
|
|
bool chromeFound = false; |
|
bool signalFound = false; |
|
const auto matches = context.matches(); |
|
for (const auto &match : matches) { |
|
qDebug() << "matched" << match.text(); |
|
if (!match.text().contains(QLatin1String("ServiceRunnerTest"))) { |
|
continue; |
|
} |
|
|
|
if (match.text() == QLatin1String("Google Chrome ServiceRunnerTest")) { |
|
QCOMPARE(match.relevance(), 0.8); |
|
chromeFound = true; |
|
} else if (match.text() == QLatin1String("Signal ServiceRunnerTest")) { |
|
// Rates lower because it doesn't have it in the name. |
|
QCOMPARE(match.relevance(), 0.7); |
|
signalFound = true; |
|
} |
|
} |
|
QVERIFY(chromeFound); |
|
QVERIFY(signalFound); |
|
} |
|
|
|
void ServiceRunnerTest::testKonsoleVsYakuakeComment() |
|
{ |
|
// Yakuake has konsole mentioned in comment, should be rated lower. |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
context.setQuery(QStringLiteral("kons")); |
|
|
|
runner.match(context); |
|
|
|
bool konsoleFound = false; |
|
bool yakuakeFound = false; |
|
const auto matches = context.matches(); |
|
for (const auto &match : matches) { |
|
qDebug() << "matched" << match.text(); |
|
if (!match.text().contains(QLatin1String("ServiceRunnerTest"))) { |
|
continue; |
|
} |
|
|
|
if (match.text() == QLatin1String("Konsole ServiceRunnerTest")) { |
|
QCOMPARE(match.relevance(), 0.99); |
|
konsoleFound = true; |
|
} else if (match.text() == QLatin1String("Yakuake ServiceRunnerTest")) { |
|
// Rates lower because it doesn't have it in the name. |
|
QCOMPARE(match.relevance(), 0.59); |
|
yakuakeFound = true; |
|
} |
|
} |
|
QVERIFY(konsoleFound); |
|
QVERIFY(yakuakeFound); |
|
} |
|
|
|
void ServiceRunnerTest::testSystemSettings() |
|
{ |
|
// In 5.9.0 'System Settings' suddenly didn't come back as a match for 'settings' anymore. |
|
// System Settings has a noKDE version and a KDE version, if the noKDE version is encountered |
|
// first it will be added to the seen cache, however disqualification of already seen items |
|
// may then also disqualify the KDE version of system settings on account of having already |
|
// seen it. This test makes sure we find the right version. |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
context.setQuery(QStringLiteral("settings")); |
|
|
|
runner.match(context); |
|
|
|
bool systemSettingsFound = false; |
|
bool foreignSystemSettingsFound = false; |
|
const auto matches = context.matches(); |
|
for (const auto &match : matches) { |
|
qDebug() << "matched" << match.text(); |
|
if (match.text() == QLatin1String("System Settings ServiceRunnerTest")) { |
|
systemSettingsFound = true; |
|
} |
|
if (match.text() == QLatin1String("KDE System Settings ServiceRunnerTest")) { |
|
foreignSystemSettingsFound = true; |
|
} |
|
} |
|
QVERIFY(systemSettingsFound); |
|
QVERIFY(!foreignSystemSettingsFound); |
|
} |
|
|
|
void ServiceRunnerTest::testSystemSettings2() |
|
{ |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
context.setQuery(QStringLiteral("sy")); |
|
|
|
runner.match(context); |
|
|
|
bool systemSettingsFound = false; |
|
bool foreignSystemSettingsFound = false; |
|
const auto matches = context.matches(); |
|
for (const auto &match : matches) { |
|
qDebug() << "matched" << match.text(); |
|
if (match.text() == QLatin1String("System Settings ServiceRunnerTest")) { |
|
systemSettingsFound = true; |
|
} |
|
if (match.text() == QLatin1String("KDE System Settings ServiceRunnerTest")) { |
|
foreignSystemSettingsFound = true; |
|
} |
|
} |
|
QVERIFY(systemSettingsFound); |
|
QVERIFY(!foreignSystemSettingsFound); |
|
} |
|
|
|
void ServiceRunnerTest::testCategories() |
|
{ |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
|
|
context.setQuery(QStringLiteral("System")); |
|
runner.match(context); |
|
auto matches = context.matches(); |
|
QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Konsole ServiceRunnerTest") && match.relevance() == 0.64; |
|
})); |
|
|
|
// Multiple categories |
|
context.setQuery(QStringLiteral("System KDE TerminalEmulator")); |
|
runner.match(context); |
|
matches = context.matches(); |
|
QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Konsole ServiceRunnerTest") && match.relevance() == 0.64; |
|
})); |
|
|
|
// Multiple categories but at least one doesn't match |
|
context.setQuery(QStringLiteral("System KDE Office")); |
|
runner.match(context); |
|
matches = context.matches(); |
|
QVERIFY(std::none_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Konsole ServiceRunnerTest"); |
|
})); |
|
} |
|
|
|
void ServiceRunnerTest::testJumpListActions() |
|
{ |
|
ServiceRunner runner(this, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
|
|
context.setQuery(QStringLiteral("open a new window")); // org.kde.konsole.desktop |
|
runner.match(context); |
|
auto matches = context.matches(); |
|
QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Open a New Window - Konsole ServiceRunnerTest") && match.relevance() == 0.55; |
|
})); |
|
|
|
context.setQuery(QStringLiteral("new window")); |
|
runner.match(context); |
|
matches = context.matches(); |
|
QVERIFY(std::any_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Open a New Window - Konsole ServiceRunnerTest") && match.relevance() == 0.5; |
|
})); |
|
|
|
context.setQuery(QStringLiteral("new windows")); |
|
runner.match(context); |
|
matches = context.matches(); |
|
QVERIFY(std::none_of(matches.cbegin(), matches.cend(), [](const Plasma::QueryMatch &match) { |
|
return match.text() == QLatin1String("Open a New Window - Konsole ServiceRunnerTest"); |
|
})); |
|
} |
|
|
|
void ServiceRunnerTest::testINotifyUsage() |
|
{ |
|
auto inotifyCount = []() -> uint { |
|
uint count = 0; |
|
const QDir procDir(QStringLiteral("/proc/%1/fd").arg(getpid())); |
|
for (const auto &fileInfo : procDir.entryInfoList()) { |
|
if (fileInfo.symLinkTarget().endsWith(QStringLiteral("anon_inode:inotify"))) { |
|
++count; |
|
} |
|
} |
|
return count; |
|
}; |
|
|
|
const uint originalCount = inotifyCount(); |
|
|
|
// We'll run this in a new thread so KDirWatch would be led to create a new thread-local watch instance. |
|
// The expectation here is that this KDW instance is not persistently claiming an inotify instance. |
|
bool inotifyCountCool = false; |
|
auto thread = QThread::create([&] { |
|
ServiceRunner runner(nullptr, KPluginMetaData(), QVariantList()); |
|
Plasma::RunnerContext context; |
|
context.setQuery(QStringLiteral("settings")); |
|
|
|
runner.match(context); |
|
|
|
QCOMPARE(inotifyCount(), originalCount); |
|
inotifyCountCool = true; |
|
}); |
|
thread->start(); |
|
thread->wait(); |
|
thread->deleteLater(); |
|
|
|
QVERIFY(inotifyCountCool); |
|
} |
|
|
|
QTEST_MAIN(ServiceRunnerTest) |
|
|
|
#include "servicerunnertest.moc"
|
|
|