| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- /*
- SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
- SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
- */
- #include <QFileInfo>
- #include <QTest>
- #include "kcoreaddons_debug.h"
- #include <kpluginloader.h>
- #include <kpluginmetadata.h>
- class LibraryPathRestorer
- {
- public:
- explicit LibraryPathRestorer(const QStringList &paths)
- : mPaths(paths)
- {
- }
- ~LibraryPathRestorer()
- {
- QCoreApplication::setLibraryPaths(mPaths);
- }
- private:
- QStringList mPaths;
- };
- class KPluginLoaderTest : public QObject
- {
- Q_OBJECT
- #if KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 86)
- private Q_SLOTS:
- void testFindPlugin_missing()
- {
- const QString location = KPluginLoader::findPlugin(QStringLiteral("idonotexist"));
- QVERIFY2(location.isEmpty(), qPrintable(location));
- }
- void testFindPlugin()
- {
- const QString location = KPluginLoader::findPlugin(QStringLiteral("jsonplugin"));
- QVERIFY2(!location.isEmpty(), qPrintable(location));
- }
- #if KCOREADDONS_BUILD_DEPRECATED_SINCE(5, 84)
- void testPluginVersion()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QCOMPARE(vplugin.pluginVersion(), quint32(5));
- KPluginLoader vplugin2(QStringLiteral("versionedplugin"));
- QCOMPARE(vplugin2.pluginVersion(), quint32(5));
- KPluginLoader uplugin(QStringLiteral("unversionedplugin"));
- QCOMPARE(uplugin.pluginVersion(), quint32(-1));
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QCOMPARE(jplugin.pluginVersion(), quint32(-1));
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QCOMPARE(eplugin.pluginVersion(), quint32(-1));
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QCOMPARE(noplugin.pluginVersion(), quint32(-1));
- }
- #endif
- void testPluginName()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QCOMPARE(vplugin.pluginName(), QString::fromLatin1("versionedplugin"));
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QCOMPARE(jplugin.pluginName(), QString::fromLatin1("jsonplugin"));
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY2(eplugin.pluginName().isEmpty(), qPrintable(eplugin.pluginName()));
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QCOMPARE(noplugin.pluginName(), QString::fromLatin1("idonotexist"));
- }
- void testFactory()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QVERIFY(vplugin.factory());
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QVERIFY(jplugin.factory());
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY(!eplugin.factory());
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QVERIFY(!noplugin.factory());
- }
- void testErrorString()
- {
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QCOMPARE(eplugin.errorString(), QString::fromLatin1("there was an error"));
- }
- void testFileName()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QCOMPARE(QFileInfo(vplugin.fileName()).canonicalFilePath(), QFileInfo(QStringLiteral(VERSIONEDPLUGIN_FILE)).canonicalFilePath());
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QCOMPARE(QFileInfo(jplugin.fileName()).canonicalFilePath(), QFileInfo(QStringLiteral(JSONPLUGIN_FILE)).canonicalFilePath());
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY2(eplugin.fileName().isEmpty(), qPrintable(eplugin.fileName()));
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QVERIFY2(noplugin.fileName().isEmpty(), qPrintable(noplugin.fileName()));
- }
- void testInstance()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QVERIFY(vplugin.instance());
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QVERIFY(jplugin.instance());
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY(!eplugin.instance());
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QVERIFY(!noplugin.instance());
- }
- void testIsLoaded()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QVERIFY(!vplugin.isLoaded());
- QVERIFY(vplugin.load());
- QVERIFY(vplugin.isLoaded());
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QVERIFY(!jplugin.isLoaded());
- QVERIFY(jplugin.load());
- QVERIFY(jplugin.isLoaded());
- KPluginLoader aplugin(QStringLiteral("alwaysunloadplugin"));
- QVERIFY(!aplugin.isLoaded());
- QVERIFY(aplugin.load());
- QVERIFY(aplugin.isLoaded());
- if (aplugin.unload()) {
- QVERIFY(!aplugin.isLoaded());
- } else {
- qCDebug(KCOREADDONS_DEBUG) << "Could not unload alwaysunloadplugin:" << aplugin.errorString();
- }
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY(!eplugin.isLoaded());
- QVERIFY(!eplugin.load());
- QVERIFY(!eplugin.isLoaded());
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QVERIFY(!noplugin.isLoaded());
- QVERIFY(!noplugin.load());
- QVERIFY(!noplugin.isLoaded());
- }
- void testLoad()
- {
- KPluginLoader vplugin(QStringLiteral("versionedplugin"));
- QVERIFY(vplugin.load());
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QVERIFY(jplugin.load());
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY(!eplugin.load());
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QVERIFY(!noplugin.load());
- }
- void testLoadHints()
- {
- KPluginLoader aplugin(QStringLiteral("alwaysunloadplugin"));
- QCOMPARE(aplugin.loadHints(), QLibrary::PreventUnloadHint);
- aplugin.setLoadHints(QLibrary::ResolveAllSymbolsHint);
- // setLoadHints merges in this scenario in the patch collection [1] but not in raw Qt5
- // [1] https://invent.kde.org/qt/qt/qtbase/-/merge_requests/285
- QVERIFY(aplugin.loadHints() == (QLibrary::ResolveAllSymbolsHint | QLibrary::PreventUnloadHint)
- || aplugin.loadHints() == QLibrary::ResolveAllSymbolsHint);
- }
- void testMetaData()
- {
- KPluginLoader aplugin(QStringLiteral("alwaysunloadplugin"));
- QJsonObject ametadata = aplugin.metaData();
- QVERIFY(!ametadata.isEmpty());
- QVERIFY(ametadata.keys().contains(QLatin1String("IID")));
- QJsonValue ametadata_metadata = ametadata.value(QStringLiteral("MetaData"));
- QVERIFY(ametadata_metadata.toObject().isEmpty());
- QVERIFY(!aplugin.isLoaded()); // didn't load anything
- KPluginLoader jplugin(KPluginName(QStringLiteral("jsonplugin")));
- QJsonObject jmetadata = jplugin.metaData();
- QVERIFY(!jmetadata.isEmpty());
- QJsonValue jmetadata_metadata = jmetadata.value(QStringLiteral("MetaData"));
- QVERIFY(jmetadata_metadata.isObject());
- QJsonObject jmetadata_obj = jmetadata_metadata.toObject();
- QVERIFY(!jmetadata_obj.isEmpty());
- QJsonValue comment = jmetadata_obj.value(QStringLiteral("KPlugin")).toObject().value(QStringLiteral("Description"));
- QVERIFY(comment.isString());
- QCOMPARE(comment.toString(), QString::fromLatin1("This is a plugin"));
- KPluginLoader eplugin(KPluginName::fromErrorString(QStringLiteral("there was an error")));
- QVERIFY(eplugin.metaData().isEmpty());
- KPluginLoader noplugin(QStringLiteral("idonotexist"));
- QVERIFY(noplugin.metaData().isEmpty());
- }
- void testUnload()
- {
- KPluginLoader aplugin(QStringLiteral("alwaysunloadplugin"));
- QVERIFY(aplugin.load());
- // may need QEXPECT_FAIL on some platforms...
- QVERIFY(aplugin.unload());
- }
- void testInstantiatePlugins()
- {
- const QString plugin1Path = KPluginLoader::findPlugin(QStringLiteral("jsonplugin"));
- QVERIFY2(!plugin1Path.isEmpty(), qPrintable(plugin1Path));
- const QString plugin2Path = KPluginLoader::findPlugin(QStringLiteral("unversionedplugin"));
- QVERIFY2(!plugin2Path.isEmpty(), qPrintable(plugin2Path));
- const QString plugin3Path = KPluginLoader::findPlugin(QStringLiteral("jsonplugin2"));
- QVERIFY2(!plugin3Path.isEmpty(), qPrintable(plugin3Path));
- QTemporaryDir temp;
- QVERIFY(temp.isValid());
- QDir dir(temp.path());
- QVERIFY2(QFile::copy(plugin1Path, dir.absoluteFilePath(QFileInfo(plugin1Path).fileName())),
- qPrintable(dir.absoluteFilePath(QFileInfo(plugin1Path).fileName())));
- QVERIFY2(QFile::copy(plugin2Path, dir.absoluteFilePath(QFileInfo(plugin2Path).fileName())),
- qPrintable(dir.absoluteFilePath(QFileInfo(plugin2Path).fileName())));
- QVERIFY2(QFile::copy(plugin3Path, dir.absoluteFilePath(QFileInfo(plugin3Path).fileName())),
- qPrintable(dir.absoluteFilePath(QFileInfo(plugin3Path).fileName())));
- // only jsonplugin, since unversionedplugin has no json metadata
- QList<QObject *> plugins = KPluginLoader::instantiatePlugins(temp.path());
- QCOMPARE(plugins.size(), 2);
- QStringList classNames = QStringList() << QString::fromLatin1(plugins[0]->metaObject()->className())
- << QString::fromLatin1(plugins[1]->metaObject()->className());
- classNames.sort();
- QCOMPARE(classNames[0], QStringLiteral("jsonplugin2"));
- QCOMPARE(classNames[1], QStringLiteral("jsonpluginfa"));
- qDeleteAll(plugins);
- // try filter
- plugins = KPluginLoader::instantiatePlugins(temp.path(), [](const KPluginMetaData &md) {
- return md.pluginId() == QLatin1String("jsonplugin");
- });
- QCOMPARE(plugins.size(), 1);
- QCOMPARE(plugins[0]->metaObject()->className(), "jsonpluginfa");
- qDeleteAll(plugins);
- plugins = KPluginLoader::instantiatePlugins(temp.path(), [](const KPluginMetaData &md) {
- return md.pluginId() == QLatin1String("unversionedplugin");
- });
- QCOMPARE(plugins.size(), 0);
- plugins = KPluginLoader::instantiatePlugins(temp.path(), [](const KPluginMetaData &md) {
- return md.pluginId() == QLatin1String("foobar"); // ID does not match file name, is set in JSON
- });
- QCOMPARE(plugins.size(), 1);
- QCOMPARE(plugins[0]->metaObject()->className(), "jsonplugin2");
- qDeleteAll(plugins);
- // check that parent gets set
- plugins = KPluginLoader::instantiatePlugins(
- temp.path(),
- [](const KPluginMetaData &) {
- return true;
- },
- this);
- QCOMPARE(plugins.size(), 2);
- QCOMPARE(plugins[0]->parent(), this);
- QCOMPARE(plugins[1]->parent(), this);
- qDeleteAll(plugins);
- const QString subDirName = dir.dirName();
- QVERIFY(dir.cdUp()); // should now point to /tmp on Linux
- LibraryPathRestorer restorer(QCoreApplication::libraryPaths());
- // instantiate using relative path
- // make sure library path is set up correctly
- QCoreApplication::setLibraryPaths(QStringList() << dir.absolutePath());
- QVERIFY(!QDir::isAbsolutePath(subDirName));
- plugins = KPluginLoader::instantiatePlugins(subDirName);
- QCOMPARE(plugins.size(), 2);
- classNames = QStringList() << QString::fromLatin1(plugins[0]->metaObject()->className()) << QString::fromLatin1(plugins[1]->metaObject()->className());
- classNames.sort();
- QCOMPARE(classNames[0], QStringLiteral("jsonplugin2"));
- QCOMPARE(classNames[1], QStringLiteral("jsonpluginfa"));
- qDeleteAll(plugins);
- }
- void testForEachPlugin()
- {
- const QString jsonPluginSrc = KPluginLoader::findPlugin(QStringLiteral("jsonplugin"));
- QVERIFY2(!jsonPluginSrc.isEmpty(), qPrintable(jsonPluginSrc));
- const QString unversionedPluginSrc = KPluginLoader::findPlugin(QStringLiteral("unversionedplugin"));
- QVERIFY2(!unversionedPluginSrc.isEmpty(), qPrintable(unversionedPluginSrc));
- const QString jsonPlugin2Src = KPluginLoader::findPlugin(QStringLiteral("jsonplugin2"));
- QVERIFY2(!jsonPlugin2Src.isEmpty(), qPrintable(jsonPlugin2Src));
- QTemporaryDir temp;
- QVERIFY(temp.isValid());
- QDir dir(temp.path());
- QVERIFY(dir.mkdir(QStringLiteral("for-each-plugin")));
- QVERIFY(dir.cd(QStringLiteral("for-each-plugin")));
- const QString jsonPluginDest = dir.absoluteFilePath(QFileInfo(jsonPluginSrc).fileName());
- QVERIFY2(QFile::copy(jsonPluginSrc, jsonPluginDest), qPrintable(jsonPluginDest));
- const QString unversionedPluginDest = dir.absoluteFilePath(QFileInfo(unversionedPluginSrc).fileName());
- QVERIFY2(QFile::copy(unversionedPluginSrc, unversionedPluginDest), qPrintable(unversionedPluginDest));
- // copy jsonplugin2 to a "for-each-plugin" subdirectory in a different directory
- QTemporaryDir temp2;
- QVERIFY(temp2.isValid());
- QDir dir2(temp2.path());
- QVERIFY(dir2.mkdir(QStringLiteral("for-each-plugin")));
- QVERIFY(dir2.cd(QStringLiteral("for-each-plugin")));
- const QString jsonPlugin2Dest = dir2.absoluteFilePath(QFileInfo(jsonPlugin2Src).fileName());
- QVERIFY2(QFile::copy(jsonPlugin2Src, jsonPlugin2Dest), qPrintable(jsonPlugin2Dest));
- QStringList foundPlugins;
- QStringList expectedPlugins;
- const auto addToFoundPlugins = [&](const QString &path) {
- QVERIFY(!path.isEmpty());
- foundPlugins.append(path);
- };
- // test finding with absolute path
- expectedPlugins = QStringList() << jsonPluginDest << unversionedPluginDest;
- expectedPlugins.sort();
- KPluginLoader::forEachPlugin(dir.path(), addToFoundPlugins);
- foundPlugins.sort();
- QCOMPARE(foundPlugins, expectedPlugins);
- expectedPlugins = QStringList() << jsonPlugin2Dest;
- expectedPlugins.sort();
- foundPlugins.clear();
- KPluginLoader::forEachPlugin(dir2.path(), addToFoundPlugins);
- foundPlugins.sort();
- QCOMPARE(foundPlugins, expectedPlugins);
- // now test relative paths
- LibraryPathRestorer restorer(QCoreApplication::libraryPaths());
- QCoreApplication::setLibraryPaths(QStringList() << temp.path());
- expectedPlugins = QStringList() << jsonPluginDest << unversionedPluginDest;
- expectedPlugins.sort();
- foundPlugins.clear();
- KPluginLoader::forEachPlugin(QStringLiteral("for-each-plugin"), addToFoundPlugins);
- foundPlugins.sort();
- QCOMPARE(foundPlugins, expectedPlugins);
- QCoreApplication::setLibraryPaths(QStringList() << temp2.path());
- expectedPlugins = QStringList() << jsonPlugin2Dest;
- expectedPlugins.sort();
- foundPlugins.clear();
- KPluginLoader::forEachPlugin(QStringLiteral("for-each-plugin"), addToFoundPlugins);
- foundPlugins.sort();
- QCOMPARE(foundPlugins, expectedPlugins);
- QCoreApplication::setLibraryPaths(QStringList() << temp.path() << temp2.path());
- expectedPlugins = QStringList() << jsonPluginDest << unversionedPluginDest << jsonPlugin2Dest;
- expectedPlugins.sort();
- foundPlugins.clear();
- KPluginLoader::forEachPlugin(QStringLiteral("for-each-plugin"), addToFoundPlugins);
- foundPlugins.sort();
- QCOMPARE(foundPlugins, expectedPlugins);
- }
- #endif
- };
- QTEST_MAIN(KPluginLoaderTest)
- #include "kpluginloadertest.moc"
|