File indexing completed on 2024-04-14 14:19:44
0001 /* This file is part of the KDE libraries 0002 Copyright (c) 2006, 2011 David Faure <faure@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License version 2 as published by the Free Software Foundation. 0007 0008 This library is distributed in the hope that it will be useful, 0009 but WITHOUT ANY WARRANTY; without even the implied warranty of 0010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0011 Library General Public License for more details. 0012 0013 You should have received a copy of the GNU Library General Public License 0014 along with this library; see the file COPYING.LIB. If not, write to 0015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0016 Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "kstandarddirstest.h" 0020 #include "qstandardpaths.h" 0021 0022 #include "qtest.h" 0023 0024 QTEST_GUILESS_MAIN(KStandarddirsTest) 0025 0026 #include <config-kstandarddirs.h> 0027 #include <kdebug.h> 0028 #include <kstandarddirs.h> 0029 #include <kcomponentdata.h> 0030 #include <kconfig.h> 0031 #include <kglobal.h> 0032 #include <qtemporarydir.h> 0033 #include <QDebug> 0034 #include <QTest> 0035 #include <kconfiggroup.h> 0036 #include <QFile> 0037 0038 // we need case-insensitive comparison of file paths on windows 0039 #ifdef Q_OS_WIN 0040 #define QCOMPARE_PATHS(x,y) QCOMPARE(QString(x).toLower(), QString(y).toLower()) 0041 #define PATH_SENSITIVITY Qt::CaseInsensitive 0042 #define EXT ".exe" 0043 #else 0044 #define QCOMPARE_PATHS(x,y) QCOMPARE(QString(x), QString(y)) 0045 #define PATH_SENSITIVITY Qt::CaseSensitive 0046 #define EXT "" 0047 #endif 0048 0049 void KStandarddirsTest::initTestCase() 0050 { 0051 QString kconfig_compilerLocation = QStringLiteral(KCONFIG_COMPILER_LOCATION); 0052 if (kconfig_compilerLocation.startsWith(CMAKE_INSTALL_PREFIX)) { 0053 m_canFindKConfig = true; 0054 } else { 0055 // the user needs to set KDEDIRS properly! 0056 QStringList kdedirs = QFile::decodeName(qgetenv("KDEDIRS")).split(':'); 0057 m_canFindKConfig = false; 0058 foreach (QString dirName, kdedirs) { 0059 if (!dirName.isEmpty() && kconfig_compilerLocation.startsWith(dirName)) { 0060 m_canFindKConfig = true; 0061 } 0062 } 0063 } 0064 0065 // canonicalPath() to resolve symlinks (e.g. on FreeBSD where /home is a symlink to /usr/home), 0066 // this matches what KGlobal::dirs()->realPath() would do, but we can't use it before setting 0067 // the env vars, it would mess up the unit test 0068 const QString homePath = QDir::home().canonicalPath(); 0069 m_configHome = homePath + QLatin1String("/.kde-unit-test/xdg/config"); 0070 0071 qputenv("XDG_CONFIG_HOME", QFile::encodeName(m_configHome)); 0072 0073 m_dataHome = homePath + QLatin1String("/.kde-unit-test/xdg/local"); 0074 qputenv("XDG_DATA_HOME", QFile::encodeName(m_dataHome)); 0075 0076 const QString configDirs = QDir::currentPath() + "/xdg"; 0077 qputenv("XDG_CONFIG_DIRS", QFile::encodeName(configDirs)); 0078 0079 qunsetenv("XDG_DATA_DIRS"); 0080 0081 QFile::remove(KGlobal::dirs()->saveLocation("config") + "kstandarddirstestrc"); 0082 0083 // Create a main component data so that testAppData doesn't suddenly change the main component 0084 // data. 0085 KComponentData mainData("kstandarddirstest"); 0086 0087 // Must initialize KStandardDirs only after all the setenv() calls. 0088 QCOMPARE(KGlobal::dirs()->localxdgconfdir(), QString(m_configHome + '/')); 0089 } 0090 0091 void KStandarddirsTest::testSaveLocation() 0092 { 0093 const QString saveLocConfig = KGlobal::dirs()->saveLocation("config"); 0094 QCOMPARE_PATHS(saveLocConfig, KGlobal::dirs()->localxdgconfdir()); 0095 const QString saveLocXdgConfig = KGlobal::dirs()->saveLocation("xdgconf"); 0096 QCOMPARE_PATHS(saveLocConfig, saveLocXdgConfig); // same result 0097 0098 const QString saveLocAppData = KGlobal::dirs()->saveLocation("appdata"); 0099 QCOMPARE_PATHS(saveLocAppData, m_dataHome + "/kstandarddirstest/"); 0100 0101 const QString saveTmp = KGlobal::dirs()->saveLocation("tmp"); 0102 QCOMPARE_PATHS(saveTmp, QDir::tempPath() + '/'); 0103 } 0104 0105 void KStandarddirsTest::testLocateLocal() 0106 { 0107 const QString configLocal = KStandardDirs::locateLocal("config", "ksomethingrc"); 0108 // KStandardDirs resolves symlinks, so we must compare with canonicalPath() 0109 QCOMPARE_PATHS(configLocal, m_configHome + "/ksomethingrc"); 0110 } 0111 0112 void KStandarddirsTest::testResourceDirs() 0113 { 0114 const QStringList configDirs = KGlobal::dirs()->resourceDirs("config"); 0115 Q_FOREACH (const QString &dir, configDirs) { 0116 QVERIFY2(dir.endsWith("xdg/") 0117 || dir.endsWith("share/config/") // KDE4 compat path 0118 || dir.endsWith(".kde-unit-test/xdg/config/"), qPrintable(dir)); 0119 } 0120 } 0121 0122 void KStandarddirsTest::testAppData() 0123 { 0124 // This API is gone 0125 #if 0 0126 // In addition to testSaveLocation(), we want to also check other KComponentDatas 0127 KComponentData cData("foo"); 0128 const QString fooAppData = cData.dirs()->saveLocation("appdata"); 0129 QCOMPARE_PATHS(fooAppData, m_dataHome + "/foo/"); 0130 #endif 0131 } 0132 0133 void KStandarddirsTest::testChangeSaveLocation() 0134 { 0135 KStandardDirs cData; 0136 QCOMPARE_PATHS(cData.saveLocation("config"), m_configHome + "/"); 0137 // Can we change the save location? 0138 const QString newSaveLoc = m_configHome + "/newconfigdir/"; 0139 //cData.addResourceDir("config", newSaveLoc); // can't be done, absolute paths have less priority than relative paths 0140 cData.addResourceType("config", nullptr, "newconfigdir"); 0141 QCOMPARE_PATHS(KStandardDirs::realPath(cData.saveLocation("config")), newSaveLoc); 0142 } 0143 0144 static bool isKdeLibs4supportInstalled() 0145 { 0146 return QFile::exists(CMAKE_INSTALL_PREFIX "/bin/kf5-config"); 0147 } 0148 0149 void KStandarddirsTest::testFindResource() 0150 { 0151 if (!m_canFindKConfig) { 0152 QSKIP("KDEDIRS does not contain the KConfig prefix"); 0153 } 0154 0155 const QString bin = KGlobal::dirs()->findResource("exe", "kf5/kconf_update" EXT); 0156 QVERIFY(!bin.isEmpty()); 0157 #ifdef Q_OS_WIN 0158 QVERIFY(bin.endsWith("bin/kconf_update.exe")); 0159 #else 0160 QVERIFY(bin.endsWith("libexec/kf5/kconf_update")); 0161 #endif 0162 QVERIFY(!QDir::isRelativePath(bin)); 0163 0164 const QString data = KGlobal::dirs()->findResource("data", "dbus-1/interfaces/kf5_org.kde.JobView.xml"); 0165 QVERIFY(!data.isEmpty()); 0166 QVERIFY(data.endsWith(QLatin1String("dbus-1/interfaces/kf5_org.kde.JobView.xml"))); 0167 QVERIFY(!QDir::isRelativePath(data)); 0168 } 0169 0170 static bool oneEndsWith(const QStringList &lst, const QString &str) 0171 { 0172 for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) { 0173 if ((*it).endsWith(str)) { 0174 return true; 0175 } 0176 } 0177 return false; 0178 } 0179 0180 void KStandarddirsTest::testFindAllResources() 0181 { 0182 if (!isKdeLibs4supportInstalled()) { 0183 QSKIP("KDELibs4Support is not installed yet"); 0184 } 0185 0186 const QStringList dbusInterfaceFiles = KGlobal::dirs()->findAllResources("data", "dbus-1/interfaces/"); 0187 QVERIFY(!dbusInterfaceFiles.isEmpty()); 0188 QVERIFY(dbusInterfaceFiles.count() > 20); // I have 21 here, installed by kdelibs. 0189 0190 // Create a local config file, the file will be used as expected result 0191 const QString localConfigFile = m_configHome + "/foorc"; 0192 QFile::remove(localConfigFile); 0193 KConfig foorc("foorc"); 0194 KConfigGroup dummyGroup(&foorc, "Dummy"); 0195 dummyGroup.writeEntry("someEntry", true); 0196 dummyGroup.sync(); 0197 QVERIFY2(QFile::exists(localConfigFile), qPrintable(localConfigFile)); 0198 0199 const QStringList configFiles = KGlobal::dirs()->findAllResources("config"); 0200 QVERIFY(!configFiles.isEmpty()); 0201 //qDebug() << configFiles; 0202 QVERIFY(oneEndsWith(configFiles, "etc/xdg/kdebugrc")); 0203 QVERIFY(oneEndsWith(configFiles, "etc/xdg/kdebug.areas")); 0204 QVERIFY(oneEndsWith(configFiles, "kde-unit-test/xdg/config/foorc")); 0205 QVERIFY(!oneEndsWith(configFiles, "etc/xdg/colors/Web.colors")); // recursive was false 0206 0207 { 0208 const QStringList configFilesRecursive = KGlobal::dirs()->findAllResources("config", QString(), 0209 KStandardDirs::Recursive); 0210 QVERIFY(!configFilesRecursive.isEmpty()); 0211 QVERIFY(configFilesRecursive.count() > 5); // I have 15 here 0212 QVERIFY(oneEndsWith(configFilesRecursive, "etc/xdg/kdebugrc")); 0213 QVERIFY(oneEndsWith(configFilesRecursive, "etc/xdg/colors/Web.colors")); // proves that recursive worked 0214 } 0215 0216 { 0217 const QStringList configFilesRecursiveWithFilter = KGlobal::dirs()->findAllResources("config", "*rc", 0218 KStandardDirs::Recursive); 0219 QVERIFY(!configFilesRecursiveWithFilter.isEmpty()); 0220 //qDebug() << configFilesRecursiveWithFilter; 0221 QVERIFY(configFilesRecursiveWithFilter.count() >= 2); // foorc, kdebugrc 0222 QVERIFY(oneEndsWith(configFilesRecursiveWithFilter, "kde-unit-test/xdg/config/foorc")); 0223 QVERIFY(oneEndsWith(configFilesRecursiveWithFilter, "etc/xdg/kdebugrc")); 0224 QVERIFY(!oneEndsWith(configFilesRecursiveWithFilter, "etc/xdg/colors/Web.colors")); // didn't match the filter 0225 } 0226 0227 { 0228 QStringList fileNames; 0229 const QStringList configFilesWithFilter = KGlobal::dirs()->findAllResources("config", "*rc", KStandardDirs::NoDuplicates, fileNames); 0230 QVERIFY(!configFilesWithFilter.isEmpty()); 0231 QVERIFY2(configFilesWithFilter.count() >= 2, qPrintable(configFilesWithFilter.join(","))); 0232 QVERIFY(oneEndsWith(configFilesWithFilter, "kde-unit-test/xdg/config/foorc")); 0233 QVERIFY(oneEndsWith(configFilesWithFilter, "kdebugrc")); // either global (etc/xdg/) or local (XDG_HOME) 0234 QVERIFY(!oneEndsWith(configFilesWithFilter, "etc/xdg/ui/ui_standards.rc")); // recursive not set 0235 QVERIFY(!oneEndsWith(configFilesWithFilter, "etc/xdg/accept-languages.codes")); // didn't match the filter 0236 QCOMPARE(fileNames.count(), configFilesWithFilter.count()); 0237 QVERIFY(fileNames.contains("kdebugrc")); 0238 } 0239 0240 #if 0 0241 list = t.findAllResources("html", "en/*/index.html", false); 0242 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { 0243 kDebug() << "docs " << (*it).toLatin1().constData(); 0244 } 0245 0246 list = t.findAllResources("html", "*/*/*.html", false); 0247 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) { 0248 kDebug() << "docs " << (*it).toLatin1().constData(); 0249 } 0250 #endif 0251 } 0252 0253 void KStandarddirsTest::testFindAllResourcesNewDir() 0254 { 0255 const QString dir = m_dataHome + "/cmake/modules"; 0256 const QString fileName = dir + "/unittest.testfile"; 0257 QFile::remove(fileName); 0258 const QStringList origFiles = KGlobal::dirs()->findAllResources("data", "cmake/modules/"); 0259 const int origCount = origFiles.count(); 0260 0261 QDir().mkpath(dir); 0262 QFile file(fileName); 0263 QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text)); 0264 file.write("foo"); 0265 file.close(); 0266 0267 const int newCount = KGlobal::dirs()->findAllResources("data", "cmake/modules/").count(); 0268 QCOMPARE(newCount, origCount + 1); 0269 file.remove(); 0270 QDir().rmpath(dir); 0271 } 0272 0273 void KStandarddirsTest::testFindDirs() 0274 { 0275 if (!isKdeLibs4supportInstalled()) { 0276 QSKIP("KDELibs4Support is not installed yet"); 0277 } 0278 0279 const QString t = KStandardDirs::locateLocal("data", "locale/"); 0280 QCOMPARE(t, QString(m_dataHome + "/locale/")); 0281 const QStringList dirs = KGlobal::dirs()->findDirs("data", "locale"); 0282 QVERIFY(!dirs.isEmpty()); 0283 QVERIFY2(dirs.count() >= 2, qPrintable(dirs.join(","))); // at least local and global 0284 //qDebug() << dirs; 0285 } 0286 0287 void KStandarddirsTest::testFindResourceDir() 0288 { 0289 if (!isKdeLibs4supportInstalled()) { 0290 QSKIP("KDELibs4Support is not installed yet"); 0291 } 0292 0293 const QString configDir = KGlobal::dirs()->findResourceDir("config", "foorc"); 0294 QVERIFY(!configDir.isEmpty()); 0295 QVERIFY2(configDir.endsWith(QLatin1String("/xdg/config/")), qPrintable(configDir)); 0296 } 0297 0298 void KStandarddirsTest::testFindExeLibExec() 0299 { 0300 #ifndef Q_OS_UNIX 0301 QSKIP("non-UNIX system"); 0302 #endif 0303 if (!isKdeLibs4supportInstalled()) { 0304 // KStandardDirs::findExe only finds libexec executables in the installed location 0305 QSKIP("KDELibs4Support is not installed yet"); 0306 } 0307 0308 // findExe with a result in libexec 0309 const QString libexe = KGlobal::dirs()->findExe("kf5/fileshareset"); 0310 QVERIFY(!libexe.isEmpty()); 0311 QVERIFY(libexe.endsWith(LIB_INSTALL_DIR "/libexec/kf5/fileshareset" EXT, PATH_SENSITIVITY)); 0312 } 0313 0314 void KStandarddirsTest::testFindExe() 0315 { 0316 if (!m_canFindKConfig) { 0317 QSKIP("KDEDIRS does not contain the KConfig prefix"); 0318 } 0319 0320 const QString exeFileName = QStringLiteral("kreadconfig5"); 0321 0322 // findExe with a result in bin 0323 const QString binexe = KGlobal::dirs()->findExe(exeFileName); 0324 QVERIFY(!binexe.isEmpty()); 0325 QCOMPARE_PATHS(binexe, QStandardPaths::findExecutable(exeFileName)); 0326 0327 // Check the "exe" resource too 0328 QString binexePath1 = KStandardDirs::realFilePath(binexe); 0329 QString binexePath2 = KGlobal::dirs()->locate("exe", exeFileName); 0330 QCOMPARE_PATHS(binexePath1, binexePath2); 0331 0332 // Check realFilePath behavior with complete command lines, like KRun does 0333 const QString cmd = binexe + " -c foo -x bar"; 0334 const QString fromKStdDirs = KStandardDirs::realFilePath(cmd); 0335 QCOMPARE(fromKStdDirs, cmd); 0336 const QString fromQFileInfo = QFileInfo(cmd).canonicalFilePath(); 0337 QVERIFY2(fromQFileInfo.isEmpty(), qPrintable(QString("QFileInfo(\"" + cmd + "\").canonicalFilePath() returned \"" + fromQFileInfo + "\""))); // !! different result, since this doesn't exist as a file 0338 0339 #ifdef Q_OS_UNIX 0340 // findExe with relative path 0341 const QString pwd = QDir::currentPath(); 0342 QDir::setCurrent("/bin"); 0343 QStringList possibleResults; 0344 possibleResults << QString::fromLatin1("/bin/sh") << QString::fromLatin1("/usr/bin/sh"); 0345 const QString sh = KGlobal::dirs()->findExe("./sh"); 0346 if (!possibleResults.contains(sh)) { 0347 kDebug() << sh; 0348 } 0349 QVERIFY(possibleResults.contains(sh)); 0350 QDir::setCurrent(pwd); 0351 #endif 0352 0353 #if 0 // Broken test, findExe doesn't look in kdehome, but in kdehome/bin (in kde4) and in $PATH. 0354 #ifdef Q_OS_UNIX 0355 QFile home(m_kdehome); 0356 const QString target = m_kdehome + "/linktodir"; 0357 home.link(target); 0358 QVERIFY(KGlobal::dirs()->findExe(target).isEmpty()); 0359 #endif 0360 #endif 0361 0362 #ifdef Q_OS_UNIX 0363 // findExe for a binary not part of KDE 0364 const QString ls = KGlobal::dirs()->findExe("ls"); 0365 QVERIFY(!ls.isEmpty()); 0366 QVERIFY(ls.endsWith(QLatin1String("bin/ls"))); 0367 #endif 0368 0369 // findExe with no result 0370 const QString idontexist = KGlobal::dirs()->findExe("idontexist"); 0371 QVERIFY(idontexist.isEmpty()); 0372 0373 // findExe with empty string 0374 const QString empty = KGlobal::dirs()->findExe(""); 0375 QVERIFY(empty.isEmpty()); 0376 } 0377 0378 void KStandarddirsTest::testLocate() 0379 { 0380 QString textPlain = "text/x-patch.xml"; 0381 Q_FOREACH (const QString &path, KGlobal::dirs()->resourceDirs("xdgdata-mime")) { 0382 if (QFile::exists(path + textPlain)) { 0383 textPlain = path + textPlain; 0384 break; 0385 } 0386 } 0387 if (textPlain == "text/x-patch.xml") { 0388 QSKIP("xdg-share-mime not installed"); 0389 } 0390 0391 const QString res = KGlobal::dirs()->locate("xdgdata-mime", "text/x-patch.xml"); 0392 QCOMPARE_PATHS(res, textPlain); 0393 } 0394 0395 void KStandarddirsTest::testRelativeLocation() 0396 { 0397 if (!isKdeLibs4supportInstalled()) { 0398 QSKIP("KDELibs4Support is not installed yet"); 0399 } 0400 0401 const QString file = "kdebugrc"; 0402 QString located = KGlobal::dirs()->locate("config", file); 0403 QCOMPARE_PATHS(KGlobal::dirs()->relativeLocation("config", located), file); 0404 } 0405 0406 void KStandarddirsTest::testAddResourceType() 0407 { 0408 if (!isKdeLibs4supportInstalled()) { 0409 QSKIP("KDELibs4Support is not installed yet"); 0410 } 0411 0412 QString ret = KStandardDirs::locate("widgets", "pics/kdialog.png"); 0413 QCOMPARE(ret, QString()); // normal, there's no "widgets" resource in kstandarddirs by default 0414 0415 KGlobal::dirs()->addResourceType("widgets", "data", "kf5/widgets/"); 0416 ret = KStandardDirs::locate("widgets", "pics/kdialog.png"); 0417 QVERIFY(!ret.isEmpty()); 0418 0419 ret = KStandardDirs::locate("widgets", "pics/kdoublenuminput.png"); 0420 QVERIFY(!ret.isEmpty()); 0421 0422 const QStringList files = KGlobal::dirs()->findAllResources("widgets", "pics/*", KStandardDirs::NoDuplicates); 0423 QVERIFY(files.count() >= 10); 0424 0425 KGlobal::dirs()->addResourceType("xdgdata-ontology", nullptr, "ontology"); 0426 const QStringList ontologyDirs = KGlobal::dirs()->resourceDirs("xdgdata-ontology"); 0427 QCOMPARE(ontologyDirs.first(), KStandardDirs::realPath(QString(qgetenv("XDG_DATA_HOME")) + "/ontology/")); 0428 if (QFile::exists("/usr/share/ontology") && 0429 QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).contains("/usr/share")) { 0430 QVERIFY(ontologyDirs.contains("/usr/share/ontology/")); 0431 } 0432 } 0433 0434 void KStandarddirsTest::testAddResourceDir() 0435 { 0436 const QString dir = QFileInfo(QFINDTESTDATA("kstandarddirstest.cpp")).absolutePath(); 0437 const QString file = "kstandarddirstest.cpp"; 0438 QString ret = KStandardDirs::locate("here", file); 0439 QCOMPARE(ret, QString()); // not set up yet 0440 0441 KGlobal::dirs()->addResourceDir("here", dir); 0442 ret = KStandardDirs::locate("here", file); 0443 QCOMPARE_PATHS(ret, KStandardDirs::realPath(dir) + "kstandarddirstest.cpp"); 0444 } 0445 0446 void KStandarddirsTest::testSetXdgDataDirs() 0447 { 0448 // By default we should have KDEDIR/share/applications in `kf5-config --path xdgdata-apps` 0449 const QStringList dirs = KGlobal::dirs()->resourceDirs("xdgdata-apps"); 0450 const QString kdeDataApps = KStandardDirs::realPath(CMAKE_INSTALL_PREFIX "/share/applications/"); 0451 if (!dirs.contains(kdeDataApps)) { 0452 kDebug() << "ERROR:" << kdeDataApps << "not in" << dirs; 0453 kDebug() << "XDG_DATA_DIRS=" << qgetenv("XDG_DATA_DIRS"); 0454 kDebug() << "installprefix=" << KStandardDirs::installPath("kdedir"); 0455 kDebug() << "installdir=" << KStandardDirs::installPath("xdgdata-apps"); 0456 kDebug() << "GenericDataLocation=" << QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); 0457 } 0458 QVERIFY(dirs.contains(kdeDataApps, PATH_SENSITIVITY)); 0459 0460 // When setting XDG_DATA_DIRS this should still be true 0461 const QString localApps = m_dataHome + "/applications/"; 0462 QVERIFY(KStandardDirs::makeDir(localApps)); 0463 0464 // canonicalPath: see the comment in initTestCase 0465 const QString customDataDir = QDir::home().canonicalPath() + QLatin1String("/.kde-unit-test/xdg/global"); 0466 qputenv("XDG_DATA_DIRS", QFile::encodeName(customDataDir)); 0467 QVERIFY(QDir(customDataDir).mkpath("applications")); 0468 KStandardDirs newStdDirs; 0469 const QStringList newDirs = newStdDirs.resourceDirs("xdgdata-apps"); 0470 //qDebug() << newDirs; 0471 QVERIFY(newDirs.contains(kdeDataApps, PATH_SENSITIVITY)); 0472 QVERIFY(newDirs.contains(localApps, PATH_SENSITIVITY)); 0473 QVERIFY(newDirs.contains(customDataDir + "/applications/", PATH_SENSITIVITY)); 0474 } 0475 0476 void KStandarddirsTest::testRestrictedResources() 0477 { 0478 // Ensure we have a local xdgdata-apps dir 0479 QFile localFile(KStandardDirs::locateLocal("xdgdata-apps", "foo.desktop")); 0480 QVERIFY(localFile.open(QIODevice::WriteOnly | QIODevice::Text)); 0481 localFile.write("foo"); 0482 localFile.close(); 0483 const QString localAppsDir = KStandardDirs::realPath(QFileInfo(localFile).absolutePath() + '/'); 0484 QVERIFY(!localAppsDir.contains("foo.desktop")); 0485 // Ensure we have a local share/kstandarddirstest dir 0486 const QString localDataDir = KStandardDirs::locateLocal("data", "kstandarddirstest/"); 0487 QVERIFY(!localDataDir.isEmpty()); 0488 QVERIFY(QFile::exists(localDataDir)); 0489 const QString localOtherDataDir = KStandardDirs::locateLocal("data", "other/"); 0490 QVERIFY(!localOtherDataDir.isEmpty()); 0491 0492 // Check unrestricted results first 0493 const QStringList appsDirs = KGlobal::dirs()->resourceDirs("xdgdata-apps"); 0494 QCOMPARE_PATHS(appsDirs.first(), localAppsDir); 0495 const QString kdeDataApps = KStandardDirs::realPath(CMAKE_INSTALL_PREFIX "/share/applications/"); 0496 QVERIFY(appsDirs.contains(kdeDataApps, PATH_SENSITIVITY)); 0497 const QStringList dataDirs = KGlobal::dirs()->findDirs("data", "kstandarddirstest"); 0498 QCOMPARE_PATHS(dataDirs.first(), localDataDir); 0499 const QStringList otherDataDirs = KGlobal::dirs()->findDirs("data", "other"); 0500 QCOMPARE_PATHS(otherDataDirs.first(), localOtherDataDir); 0501 0502 // Initialize restrictions. 0503 // Need a new componentdata to trigger restricted-resource initialization 0504 // And we need to write the config _before_ creating the KStandardDirs. 0505 KConfig foorc("kstandarddirstestrc"); 0506 KConfigGroup restrictionsGroup(&foorc, "KDE Resource Restrictions"); 0507 restrictionsGroup.writeEntry("xdgdata-apps", false); 0508 restrictionsGroup.writeEntry("data_kstandarddirstest", false); 0509 restrictionsGroup.sync(); 0510 0511 // Check restrictions. 0512 //KComponentData cData("foo"); 0513 KStandardDirs *dirs = new KStandardDirs; 0514 dirs->addCustomized(&foorc); // like KGlobal::dirs() does 0515 QVERIFY(dirs->isRestrictedResource("xdgdata-apps")); 0516 QVERIFY(dirs->isRestrictedResource("data", "kstandarddirstest")); 0517 0518 const QStringList newAppsDirs = dirs->resourceDirs("xdgdata-apps"); 0519 QVERIFY(newAppsDirs.contains(kdeDataApps, PATH_SENSITIVITY)); 0520 QVERIFY(!newAppsDirs.contains(localAppsDir, PATH_SENSITIVITY)); // restricted! 0521 const QStringList newDataDirs = dirs->findDirs("data", "kstandarddirstest"); 0522 QVERIFY(!newDataDirs.contains(localDataDir, PATH_SENSITIVITY)); // restricted! 0523 const QStringList newOtherDataDirs = dirs->findDirs("data", "other"); 0524 QVERIFY(newOtherDataDirs.contains(localOtherDataDir, PATH_SENSITIVITY)); // not restricted! 0525 0526 restrictionsGroup.deleteGroup(); 0527 localFile.remove(); 0528 delete dirs; 0529 } 0530 0531 void KStandarddirsTest::testSymlinkResolution() 0532 { 0533 // On FreeBSD it is common to have a symlink /home -> /usr/home, 0534 // which messes with all the comparisons where **some** code paths 0535 // return a canonicalized path and some do not. 0536 if (QDir::homePath().compare(QFileInfo(QDir::homePath() + '/').canonicalFilePath(), PATH_SENSITIVITY) != 0) { 0537 QSKIP("HOME contains a symlink, not supported"); 0538 } 0539 #ifndef Q_OS_WIN 0540 // This makes the save location for the david resource, "<XDG_DATA_HOME>/symlink/test/" 0541 // where symlink points to "real", and the subdir test will be created later 0542 // This used to confuse KStandardDirs and make it return unresolved paths, 0543 // and thus making comparisons fail later on in KConfig. 0544 QString baseDir = m_dataHome; 0545 const QString symlink = baseDir + "/symlink"; 0546 const QString expected = baseDir + "/real/test/"; 0547 QDir d_(baseDir + "/real"); 0548 QVERIFY(d_.removeRecursively()); 0549 QVERIFY(QDir(baseDir).mkdir("real")); 0550 QFile::remove(symlink); 0551 QVERIFY(!QFile::exists(symlink)); 0552 QVERIFY(QFile::link("real", symlink)); 0553 QVERIFY(QFileInfo(symlink).isSymLink()); 0554 QVERIFY(!QFile::exists(expected)); 0555 KGlobal::dirs()->addResourceType("david", nullptr, "symlink/test"); 0556 QVERIFY(!QFile::exists(expected)); 0557 const QString saveLoc = KGlobal::dirs()->resourceDirs("david").first(); 0558 QVERIFY(!QFile::exists(expected)); 0559 // The issue at this point is that saveLoc does not actually exist yet. 0560 QVERIFY(QDir(saveLoc).canonicalPath().isEmpty()); // this is why we can't use canonicalPath 0561 QVERIFY(!QFile::exists(saveLoc)); 0562 QCOMPARE(saveLoc, KStandardDirs::realPath(saveLoc)); // must be resolved 0563 QCOMPARE(saveLoc, expected); 0564 QVERIFY(QDir(baseDir).mkpath("real/test")); // KConfig calls mkdir on its own, we simulate that here 0565 const QString sameSaveLoc = KGlobal::dirs()->resourceDirs("david").first(); 0566 QCOMPARE(sameSaveLoc, saveLoc); 0567 QCOMPARE(sameSaveLoc, KGlobal::dirs()->saveLocation("david")); 0568 0569 // While we're here... 0570 QCOMPARE(KStandardDirs::realPath(QString()), QString()); 0571 QCOMPARE(KStandardDirs::realPath(QString("/")), QString("/")); 0572 0573 QCOMPARE(KStandardDirs::realPath(QString("/does_not_exist/")), QString("/does_not_exist/")); 0574 #endif 0575 } 0576 0577 #include <QThreadPool> 0578 #include <QFutureSynchronizer> 0579 #include <qtconcurrentrun.h> 0580 0581 // To find multithreading bugs: valgrind --tool=helgrind ./kstandarddirstest testThreads 0582 void KStandarddirsTest::testThreads() 0583 { 0584 if (!isKdeLibs4supportInstalled()) { 0585 QSKIP("KDELibs4Support is not installed yet"); 0586 } 0587 if (!m_canFindKConfig) { 0588 QSKIP("KDEDIRS does not contain the KConfig prefix"); 0589 } 0590 0591 QThreadPool::globalInstance()->setMaxThreadCount(6); 0592 QFutureSynchronizer<void> sync; 0593 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testLocateLocal)); 0594 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testSaveLocation)); 0595 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testAppData)); 0596 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testFindResource)); 0597 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testFindAllResources)); 0598 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testLocate)); 0599 sync.addFuture(QtConcurrent::run(this, &KStandarddirsTest::testRelativeLocation)); 0600 sync.waitForFinished(); 0601 } 0602 0603 #include "moc_kstandarddirstest.cpp"