File indexing completed on 2024-04-14 14:27:17

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include <KConfigGroup>
0009 #include <KDesktopFile>
0010 #include <QDebug>
0011 #include <QSignalSpy>
0012 #include <QTest>
0013 #include <kbuildsycoca_p.h>
0014 #include <kservicetype.h>
0015 #include <ksycoca.h>
0016 #include <ksycocadict_p.h>
0017 
0018 class KSycocaDictTest : public QObject
0019 {
0020     Q_OBJECT
0021 
0022 private Q_SLOTS:
0023     void initTestCase()
0024     {
0025         QStandardPaths::setTestModeEnabled(true);
0026 
0027         // dicttestplugintype: a servicetype
0028         const QString dictTestPluginType = serviceTypesDir() + QLatin1String{"/dicttestplugintype.desktop"};
0029         if (!QFile::exists(dictTestPluginType)) {
0030             KDesktopFile file(dictTestPluginType);
0031             KConfigGroup group = file.desktopGroup();
0032             group.writeEntry("Comment", "Fake Text Plugin");
0033             group.writeEntry("Type", "ServiceType");
0034             group.writeEntry("X-KDE-ServiceType", "DictTestPluginType");
0035             file.group("PropertyDef::X-KDE-Version").writeEntry("Type", "double"); // like in ktexteditorplugin.desktop
0036             qDebug() << "Just created" << dictTestPluginType;
0037         }
0038         runKBuildSycoca();
0039     }
0040     void testStandardDict();
0041 
0042 private:
0043     QString serviceTypesDir()
0044     {
0045         return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String{"/kservicetypes5"};
0046     }
0047 
0048     void add(KSycocaDict &dict, const QString &key, const QString &name)
0049     {
0050         KServiceType::Ptr ptr = KServiceType::serviceType(name);
0051         if (!ptr) {
0052             qWarning() << "serviceType not found" << name;
0053         }
0054         dict.add(key, KSycocaEntry::Ptr(ptr));
0055     }
0056     static void runKBuildSycoca();
0057 };
0058 
0059 QTEST_MAIN(KSycocaDictTest)
0060 
0061 void KSycocaDictTest::runKBuildSycoca()
0062 {
0063 #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 80)
0064     QSignalSpy spy(KSycoca::self(), qOverload<const QStringList &>(&KSycoca::databaseChanged));
0065 #else
0066     QSignalSpy spy(KSycoca::self(), &KSycoca::databaseChanged);
0067 #endif
0068 
0069     KBuildSycoca builder;
0070     QVERIFY(builder.recreate());
0071     if (spy.isEmpty()) {
0072         qDebug() << "waiting for signal";
0073         QVERIFY(spy.wait(10000));
0074         qDebug() << "got signal";
0075     }
0076 }
0077 
0078 // Standard use of KSycocaDict: mapping entry name to entry
0079 void KSycocaDictTest::testStandardDict()
0080 {
0081     QVERIFY(KSycoca::isAvailable());
0082 
0083     QStringList serviceTypes;
0084     // clang-format off
0085     serviceTypes << QStringLiteral("DictTestPluginType")
0086                  << QStringLiteral("KUriFilter/Plugin")
0087                  << QStringLiteral("KDataTool")
0088                  << QStringLiteral("KCModule")
0089                  << QStringLiteral("KScan/KScanDialog")
0090                  << QStringLiteral("Browser/View")
0091                  << QStringLiteral("Plasma/Applet")
0092                  << QStringLiteral("Plasma/Runner");
0093     // clang-format on
0094 
0095     // Skip servicetypes that are not installed
0096     auto it = std::remove_if(serviceTypes.begin(), serviceTypes.end(), [](const QString &s) {
0097         return !KServiceType::serviceType(s);
0098     });
0099     serviceTypes.erase(it, serviceTypes.end());
0100 
0101     qDebug() << serviceTypes;
0102 
0103     QBENCHMARK {
0104         QByteArray buffer;
0105         {
0106             KSycocaDict dict;
0107             for (const QString &str : std::as_const(serviceTypes)) {
0108                 add(dict, str, str);
0109             }
0110             dict.remove(QStringLiteral("DictTestPluginType")); // just to test remove
0111             add(dict, QStringLiteral("DictTestPluginType"), QStringLiteral("DictTestPluginType"));
0112             QCOMPARE(int(dict.count()), serviceTypes.count());
0113             QDataStream saveStream(&buffer, QIODevice::WriteOnly);
0114             dict.save(saveStream);
0115         }
0116 
0117         QDataStream stream(buffer);
0118         KSycocaDict loadingDict(&stream, 0);
0119         int offset = loadingDict.find_string(QStringLiteral("DictTestPluginType"));
0120         QVERIFY(offset > 0);
0121         QCOMPARE(offset, KServiceType::serviceType(QStringLiteral("DictTestPluginType"))->offset());
0122         for (const QString &str : std::as_const(serviceTypes)) {
0123             int offset = loadingDict.find_string(str);
0124             QVERIFY(offset > 0);
0125             QCOMPARE(offset, KServiceType::serviceType(str)->offset());
0126         }
0127         offset = loadingDict.find_string(QStringLiteral("doesnotexist"));
0128         // TODO QCOMPARE(offset, 0); // could be non 0 according to the docs, too; if non 0, we should check that the pointed mimetype doesn't have this name.
0129     }
0130 }
0131 
0132 #include "ksycocadicttest.moc"