File indexing completed on 2024-04-14 03:54:33

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