QStandardPaths/Unix: fix writableLocation() when test mode is enabled

In commit 482a75fef9 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 <david.faure@kdab.com>
This commit is contained in:
Ahmad Samir 2023-04-20 13:22:13 +02:00
parent e320280f61
commit a7555c3306
2 changed files with 98 additions and 29 deletions

View File

@ -180,16 +180,18 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case CacheLocation: case CacheLocation:
case GenericCacheLocation: case GenericCacheLocation:
{ {
if (isTestModeEnabled()) QString xdgCacheHome;
return QDir::homePath() + "/.qttest/cache"_L1; 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 if (xdgCacheHome.isEmpty())
QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); xdgCacheHome = QDir::homePath() + "/.cache"_L1;
if (!xdgCacheHome.startsWith(u'/')) }
xdgCacheHome.clear(); // spec says relative paths should be ignored
if (xdgCacheHome.isEmpty())
xdgCacheHome = QDir::homePath() + "/.cache"_L1;
if (type == QStandardPaths::CacheLocation) if (type == QStandardPaths::CacheLocation)
appendOrganizationAndApp(xdgCacheHome); appendOrganizationAndApp(xdgCacheHome);
return xdgCacheHome; return xdgCacheHome;
@ -198,15 +200,17 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case AppLocalDataLocation: case AppLocalDataLocation:
case GenericDataLocation: case GenericDataLocation:
{ {
if (isTestModeEnabled()) QString xdgDataHome;
return QDir::homePath() + "/.qttest/share"_L1; 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.isEmpty())
if (!xdgDataHome.startsWith(u'/')) xdgDataHome = QDir::homePath() + "/.local/share"_L1;
xdgDataHome.clear(); // spec says relative paths should be ignored }
if (xdgDataHome.isEmpty())
xdgDataHome = QDir::homePath() + "/.local/share"_L1;
if (type == AppDataLocation || type == AppLocalDataLocation) if (type == AppDataLocation || type == AppLocalDataLocation)
appendOrganizationAndApp(xdgDataHome); appendOrganizationAndApp(xdgDataHome);
return xdgDataHome; return xdgDataHome;
@ -215,16 +219,18 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case GenericConfigLocation: case GenericConfigLocation:
case AppConfigLocation: case AppConfigLocation:
{ {
if (isTestModeEnabled()) QString xdgConfigHome;
return QDir::homePath() + "/.qttest/config"_L1; 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/ if (xdgConfigHome.isEmpty())
QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); xdgConfigHome = QDir::homePath() + "/.config"_L1;
if (!xdgConfigHome.startsWith(u'/')) }
xdgConfigHome.clear(); // spec says relative paths should be ignored
if (xdgConfigHome.isEmpty())
xdgConfigHome = QDir::homePath() + "/.config"_L1;
if (type == AppConfigLocation) if (type == AppConfigLocation)
appendOrganizationAndApp(xdgConfigHome); appendOrganizationAndApp(xdgConfigHome);
return xdgConfigHome; return xdgConfigHome;

View File

@ -29,6 +29,41 @@ using namespace Qt::StringLiterals;
// Update this when adding new enum values; update enumNames too // Update this when adding new enum values; update enumNames too
static const int MaxStandardLocation = QStandardPaths::AppConfigLocation; 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 class tst_qstandardpaths : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -221,24 +256,52 @@ void tst_qstandardpaths::enableTestMode()
setCustomLocations(); // for the global config dir setCustomLocations(); // for the global config dir
const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest"); const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest");
// ConfigLocation // *Config*Location
const QString configDir = qttestDir + QLatin1String("/config"); const QString configDir = qttestDir + QLatin1String("/config");
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), configDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), configDir);
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation), configDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation), configDir);
const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation); const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation);
QCOMPARE(confDirs, QStringList() << configDir << m_globalConfigDir); 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"); const QString dataDir = qttestDir + QLatin1String("/share");
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), dataDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation), dataDir);
const QStringList gdDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); const QStringList gdDirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
QCOMPARE(gdDirs, QStringList() << dataDir << m_globalAppDir); 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"); const QString cacheDir = qttestDir + QLatin1String("/cache");
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation), cacheDir); QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation), cacheDir);
const QStringList cacheDirs = QStandardPaths::standardLocations(QStandardPaths::GenericCacheLocation); const QStringList cacheDirs = QStandardPaths::standardLocations(QStandardPaths::GenericCacheLocation);
QCOMPARE(cacheDirs, QStringList() << cacheDir); 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 #endif
// On all platforms, we want to ensure that the writableLocation is different in test mode and real mode. // On all platforms, we want to ensure that the writableLocation is different in test mode and real mode.