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

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2015 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 <QProcess>
0012 #include <QTemporaryDir>
0013 #include <QTest>
0014 #include <kservice.h>
0015 #include <kservicefactory_p.h>
0016 #include <kservicetype.h>
0017 #include <kservicetypefactory_p.h>
0018 #include <ksycoca.h>
0019 #include <ksycoca_p.h>
0020 
0021 // taken from tst_qstandardpaths
0022 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID)
0023 #define Q_XDG_PLATFORM
0024 #endif
0025 
0026 class KSycocaXdgDirsTest : public QObject
0027 {
0028     Q_OBJECT
0029 
0030 private Q_SLOTS:
0031     void initTestCase()
0032     {
0033         QStandardPaths::setTestModeEnabled(true);
0034 
0035         QVERIFY(m_tempDir.isValid());
0036     }
0037     void cleanupTestCase()
0038     {
0039         QFile::remove(KSycoca::absoluteFilePath());
0040     }
0041     void testOtherAppDir();
0042 
0043 private:
0044     static void runKBuildSycoca(const QProcessEnvironment &environment);
0045 
0046     QTemporaryDir m_tempDir;
0047 };
0048 
0049 QTEST_MAIN(KSycocaXdgDirsTest)
0050 
0051 void KSycocaXdgDirsTest::runKBuildSycoca(const QProcessEnvironment &environment)
0052 {
0053     QProcess proc;
0054     const QString kbuildsycoca = QStringLiteral(KBUILDSYCOCAEXE);
0055     QVERIFY(!kbuildsycoca.isEmpty());
0056     QStringList args;
0057     args << QStringLiteral("--testmode");
0058     // proc.setProcessChannelMode(QProcess::ForwardedChannels);
0059     proc.start(kbuildsycoca, args);
0060     proc.setProcessEnvironment(environment);
0061 
0062     proc.waitForFinished();
0063     QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
0064 }
0065 
0066 // Ensure two apps with different XDG_DATA_DIRS/XDG_DATA_HOME don't use the same sycoca.
0067 void KSycocaXdgDirsTest::testOtherAppDir()
0068 {
0069 #ifndef Q_XDG_PLATFORM
0070     QSKIP("This test requires XDG_DATA_DIRS");
0071 #endif
0072 
0073     // KSycoca::self() represents application 1, running with one set of dirs
0074     KSycoca::self()->ensureCacheValid();
0075 
0076     // Create another xdg data dir
0077     const QString dataDir = m_tempDir.path();
0078     qputenv("XDG_DATA_DIRS", QFile::encodeName(dataDir));
0079     QCOMPARE(dataDir, QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).constLast());
0080     QVERIFY(!KService::serviceByDesktopPath(QStringLiteral("test_app_other.desktop")));
0081 
0082     const QString appDir = dataDir + QLatin1String{"/applications"};
0083 
0084     // The buildsystem copied applications.menus into bin/data/menus, so we don't rely on /etc/xdg
0085     const QByteArray modifiedConfigDirs = QFile::encodeName(QCoreApplication::applicationDirPath()) + "/data";
0086     qputenv("XDG_CONFIG_DIRS", modifiedConfigDirs);
0087 
0088     // test_app_other: live in a different application directory
0089     const QString testAppOther = appDir + QLatin1String{"/test_app_other.desktop"};
0090     KDesktopFile file(testAppOther);
0091     KConfigGroup group = file.desktopGroup();
0092     group.writeEntry("Type", "Application");
0093     group.writeEntry("Exec", "kded5");
0094     group.writeEntry("Name", "Test App Other");
0095     qDebug() << "Just created" << testAppOther;
0096     file.sync();
0097 
0098     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
0099     env.insert(QStringLiteral("XDG_DATA_DIRS"), dataDir);
0100     runKBuildSycoca(env);
0101 
0102 #if 0 // for debugging
0103     const KService::List lst = KService::allServices();
0104     QVERIFY(!lst.isEmpty());
0105     for (const KService::Ptr &serv : lst) {
0106         qDebug() << serv->entryPath() << serv->storageId() /*<< serv->desktopEntryName()*/;
0107     }
0108 #endif
0109 
0110     // This is still NOT available to application 1.
0111     // kbuildsycoca created a different DB file, the one we read from hasn't changed.
0112     // Changing XDG_DATA_DIRS at runtime isn't supported, so this test isn't doing what apps would do.
0113     // The point however is that another app using different dirs cannot mess up our DB.
0114     QVERIFY(!KService::serviceByStorageId(QStringLiteral("test_app_other.desktop")));
0115 
0116     // Check here what the application 2 would see, by creating another sycoca instance.
0117     KSycoca otherAppSycoca;
0118     // do what serviceByStorageId does:
0119     otherAppSycoca.ensureCacheValid();
0120     QVERIFY(otherAppSycoca.d->serviceFactory()->findServiceByStorageId(QStringLiteral("test_app_other.desktop")));
0121     QVERIFY(otherAppSycoca.d->m_databasePath != KSycoca::self()->d->m_databasePath); // check that they use a different filename
0122     // check that the timestamp code works
0123     QVERIFY(!otherAppSycoca.d->needsRebuild());
0124 }
0125 
0126 #include "ksycoca_xdgdirstest.moc"