From a7555c33060a2f5e9d0d0f2220286c38f31d436f Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Thu, 20 Apr 2023 13:22:13 +0200 Subject: [PATCH] QStandardPaths/Unix: fix writableLocation() when test mode is enabled In commit 482a75fef9643 the code was changed to return early, but that missed appending the organization and app names while test mode is enabled. Issue spotted by Edward. Pick-to: 6.5 Change-Id: Ifd220f8990874a173413dcf71d105c04b605c800 Reviewed-by: David Faure --- src/corelib/io/qstandardpaths_unix.cpp | 58 +++++++++------- .../io/qstandardpaths/tst_qstandardpaths.cpp | 69 ++++++++++++++++++- 2 files changed, 98 insertions(+), 29 deletions(-) diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 55150f9e93..30c4c3ad55 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -180,16 +180,18 @@ QString QStandardPaths::writableLocation(StandardLocation type) case CacheLocation: case GenericCacheLocation: { - if (isTestModeEnabled()) - return QDir::homePath() + "/.qttest/cache"_L1; + QString xdgCacheHome; + if (isTestModeEnabled()) { + xdgCacheHome = QDir::homePath() + "/.qttest/cache"_L1; + } else { + // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html + xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); + if (!xdgCacheHome.startsWith(u'/')) + xdgCacheHome.clear(); // spec says relative paths should be ignored - // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html - QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); - if (!xdgCacheHome.startsWith(u'/')) - xdgCacheHome.clear(); // spec says relative paths should be ignored - - if (xdgCacheHome.isEmpty()) - xdgCacheHome = QDir::homePath() + "/.cache"_L1; + if (xdgCacheHome.isEmpty()) + xdgCacheHome = QDir::homePath() + "/.cache"_L1; + } if (type == QStandardPaths::CacheLocation) appendOrganizationAndApp(xdgCacheHome); return xdgCacheHome; @@ -198,15 +200,17 @@ QString QStandardPaths::writableLocation(StandardLocation type) case AppLocalDataLocation: case GenericDataLocation: { - if (isTestModeEnabled()) - return QDir::homePath() + "/.qttest/share"_L1; + QString xdgDataHome; + if (isTestModeEnabled()) { + xdgDataHome = QDir::homePath() + "/.qttest/share"_L1; + } else { + xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); + if (!xdgDataHome.startsWith(u'/')) + xdgDataHome.clear(); // spec says relative paths should be ignored - QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); - if (!xdgDataHome.startsWith(u'/')) - xdgDataHome.clear(); // spec says relative paths should be ignored - - if (xdgDataHome.isEmpty()) - xdgDataHome = QDir::homePath() + "/.local/share"_L1; + if (xdgDataHome.isEmpty()) + xdgDataHome = QDir::homePath() + "/.local/share"_L1; + } if (type == AppDataLocation || type == AppLocalDataLocation) appendOrganizationAndApp(xdgDataHome); return xdgDataHome; @@ -215,16 +219,18 @@ QString QStandardPaths::writableLocation(StandardLocation type) case GenericConfigLocation: case AppConfigLocation: { - if (isTestModeEnabled()) - return QDir::homePath() + "/.qttest/config"_L1; + QString xdgConfigHome; + if (isTestModeEnabled()) { + xdgConfigHome = QDir::homePath() + "/.qttest/config"_L1; + } else { + // http://standards.freedesktop.org/basedir-spec/latest/ + xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); + if (!xdgConfigHome.startsWith(u'/')) + xdgConfigHome.clear(); // spec says relative paths should be ignored - // http://standards.freedesktop.org/basedir-spec/latest/ - QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); - if (!xdgConfigHome.startsWith(u'/')) - xdgConfigHome.clear(); // spec says relative paths should be ignored - - if (xdgConfigHome.isEmpty()) - xdgConfigHome = QDir::homePath() + "/.config"_L1; + if (xdgConfigHome.isEmpty()) + xdgConfigHome = QDir::homePath() + "/.config"_L1; + } if (type == AppConfigLocation) appendOrganizationAndApp(xdgConfigHome); return xdgConfigHome; diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 3284b8479a..bd1babe7d6 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -29,6 +29,41 @@ using namespace Qt::StringLiterals; // Update this when adding new enum values; update enumNames too static const int MaxStandardLocation = QStandardPaths::AppConfigLocation; +static QString genericCacheLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); +} +static QString cacheLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); +} + +static QString genericDataLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); +} +static QString appDataLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); +} +static QString appLocalDataLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); +} + +static QString genericConfigLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); +} +static QString configLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); +} +static QString appConfigLoc() +{ + return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); +} + class tst_qstandardpaths : public QObject { Q_OBJECT @@ -221,24 +256,52 @@ void tst_qstandardpaths::enableTestMode() setCustomLocations(); // for the global config dir const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest"); - // ConfigLocation + // *Config*Location const QString configDir = qttestDir + QLatin1String("/config"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), configDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation), configDir); const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation); QCOMPARE(confDirs, QStringList() << configDir << m_globalConfigDir); + // AppConfigLocation should be "GenericConfigLocation/organization-name/app-name" + QCOMPARE(appConfigLoc(), configDir + "/tst_qstandardpaths"_L1); - // GenericDataLocation + // *Data*Location const QString dataDir = qttestDir + QLatin1String("/share"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), dataDir); const QStringList gdDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); QCOMPARE(gdDirs, QStringList() << dataDir << m_globalAppDir); + // AppDataLocation/AppLocalDataLocation should be + // "GenericDataLocation/organization-name/app-name" + QCOMPARE(appDataLoc(), dataDir + "/tst_qstandardpaths"_L1); + QCOMPARE(appLocalDataLoc(), dataDir + "/tst_qstandardpaths"_L1); - // GenericCacheLocation + // *CacheLocation const QString cacheDir = qttestDir + QLatin1String("/cache"); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation), cacheDir); const QStringList cacheDirs = QStandardPaths::standardLocations(QStandardPaths::GenericCacheLocation); QCOMPARE(cacheDirs, QStringList() << cacheDir); + // CacheLocation should be "GenericCacheLocation/organization-name/app-name" + QCOMPARE(cacheLoc(), cacheDir + "/tst_qstandardpaths"_L1); + + QCoreApplication::setOrganizationName("Qt"); + QCOMPARE(appConfigLoc(), configDir + "/Qt/tst_qstandardpaths"_L1); + QCOMPARE(appDataLoc(), dataDir + "/Qt/tst_qstandardpaths"_L1); + QCOMPARE(appLocalDataLoc(), dataDir + "/Qt/tst_qstandardpaths"_L1); + QCOMPARE(cacheLoc(), cacheDir + "/Qt/tst_qstandardpaths"_L1); + QCOMPARE(cacheLoc(), cacheDir + "/Qt/tst_qstandardpaths"_L1); + + QCoreApplication::setApplicationName("QtTest"); + QCOMPARE(appConfigLoc(), configDir + "/Qt/QtTest"_L1); + QCOMPARE(appDataLoc(), dataDir + "/Qt/QtTest"_L1); + QCOMPARE(appLocalDataLoc(), dataDir + "/Qt/QtTest"_L1); + QCoreApplication::setApplicationName("QtTest"); + QCOMPARE(cacheLoc(), cacheDir + "/Qt/QtTest"_L1); + + // Check these are unaffected by org/app names + QCOMPARE(genericConfigLoc(), configDir); + QCOMPARE(configLoc(), configDir); + QCOMPARE(genericDataLoc(), dataDir); + QCOMPARE(genericCacheLoc(), cacheDir); #endif // On all platforms, we want to ensure that the writableLocation is different in test mode and real mode.