Allow auto tests to stay away from the user's configuration.
QStandardPaths now knows a "test mode" which changes writable locations to point to test directories, in order to prevent auto tests from reading from or writing to the current user's configuration. This affects the locations into which test programs might write files: GenericDataLocation, DataLocation, ConfigLocation, GenericCacheLocation, CacheLocation. Other locations are not affected. Change-Id: I29606c2e74714360edd871a8c387a5c1ef7d1f54 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Jason McDonald <jason.mcdonald@nokia.com>
This commit is contained in:
parent
99e7ad660f
commit
a5a80da223
@ -309,6 +309,27 @@ QString QStandardPaths::displayName(StandardLocation type)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\fn void QStandardPaths::enableTestMode(bool testMode)
|
||||
|
||||
Enables "test mode" in QStandardPaths, which changes writable locations
|
||||
to point to test directories, in order to prevent auto tests from reading from
|
||||
or writing to the current user's configuration.
|
||||
|
||||
This affects the locations into which test programs might write files:
|
||||
GenericDataLocation, DataLocation, ConfigLocation,
|
||||
GenericCacheLocation, CacheLocation.
|
||||
Other locations are not affected.
|
||||
|
||||
On Unix, XDG_DATA_HOME is set to ~/.qttest/share, XDG_CONFIG_HOME is
|
||||
set to ~/.qttest/config, and XDG_CACHE_HOME is set to ~/.qttest/cache.
|
||||
|
||||
On Mac, data goes to "~/.qttest/Application Support", cache goes to
|
||||
~/.qttest/Cache, and config goes to ~/.qttest/Preferences.
|
||||
|
||||
On Windows, everything goes to a "qttest" directory under Application Data.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_STANDARDPATHS
|
||||
|
@ -91,6 +91,8 @@ public:
|
||||
|
||||
static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList());
|
||||
|
||||
static void enableTestMode(bool testMode);
|
||||
|
||||
private:
|
||||
// prevent construction
|
||||
QStandardPaths();
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QAtomicPointer>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#ifndef QT_NO_STANDARDPATHS
|
||||
|
||||
@ -62,6 +63,23 @@ public:
|
||||
|
||||
Q_GLOBAL_STATIC(QStandardPathsPrivate, configCache);
|
||||
|
||||
static bool qsp_testMode = false;
|
||||
|
||||
void QStandardPaths::enableTestMode(bool testMode)
|
||||
{
|
||||
qsp_testMode = testMode;
|
||||
}
|
||||
|
||||
static void appendOrganizationAndApp(QString &path)
|
||||
{
|
||||
const QString org = QCoreApplication::organizationName();
|
||||
if (!org.isEmpty())
|
||||
path += QLatin1Char('/') + org;
|
||||
const QString appName = QCoreApplication::applicationName();
|
||||
if (!appName.isEmpty())
|
||||
path += QLatin1Char('/') + appName;
|
||||
}
|
||||
|
||||
QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
{
|
||||
switch (type) {
|
||||
@ -73,6 +91,30 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
break;
|
||||
}
|
||||
|
||||
if (qsp_testMode) {
|
||||
const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest");
|
||||
QString path;
|
||||
switch (type) {
|
||||
case GenericDataLocation:
|
||||
case DataLocation:
|
||||
path = qttestDir + QLatin1String("/share");
|
||||
if (type == DataLocation)
|
||||
appendOrganizationAndApp(path);
|
||||
return path;
|
||||
case GenericCacheLocation:
|
||||
case CacheLocation:
|
||||
path = qttestDir + QLatin1String("/cache");
|
||||
if (type == CacheLocation)
|
||||
appendOrganizationAndApp(path);
|
||||
return path;
|
||||
case ConfigLocation:
|
||||
return qttestDir + QLatin1String("/config");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QJsonObject * localConfigObject = configCache()->object.loadAcquire();
|
||||
if (localConfigObject == 0) {
|
||||
QString configHome = QFile::decodeName(qgetenv("PATH_CONFIG_HOME"));
|
||||
|
@ -90,6 +90,13 @@ OSType translateLocation(QStandardPaths::StandardLocation type)
|
||||
}
|
||||
}
|
||||
|
||||
static bool qsp_testMode = false;
|
||||
|
||||
void QStandardPaths::enableTestMode(bool testMode)
|
||||
{
|
||||
qsp_testMode = testMode;
|
||||
}
|
||||
|
||||
/*
|
||||
Constructs a full unicode path from a FSRef.
|
||||
*/
|
||||
@ -101,6 +108,16 @@ static QString getFullPath(const FSRef &ref)
|
||||
return QString();
|
||||
}
|
||||
|
||||
static void appendOrganizationAndApp(QString &path)
|
||||
{
|
||||
const QString org = QCoreApplication::organizationName();
|
||||
if (!org.isEmpty())
|
||||
path += QLatin1Char('/') + org;
|
||||
const QString appName = QCoreApplication::applicationName();
|
||||
if (!appName.isEmpty())
|
||||
path += QLatin1Char('/') + appName;
|
||||
}
|
||||
|
||||
static QString macLocation(QStandardPaths::StandardLocation type, short domain)
|
||||
{
|
||||
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
|
||||
@ -111,17 +128,36 @@ static QString macLocation(QStandardPaths::StandardLocation type, short domain)
|
||||
|
||||
QString path = getFullPath(ref);
|
||||
|
||||
if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation) {
|
||||
if (!QCoreApplication::organizationName().isEmpty())
|
||||
path += QLatin1Char('/') + QCoreApplication::organizationName();
|
||||
if (!QCoreApplication::applicationName().isEmpty())
|
||||
path += QLatin1Char('/') + QCoreApplication::applicationName();
|
||||
}
|
||||
return path;
|
||||
if (type == QStandardPaths::DataLocation || type == QStandardPaths::CacheLocation)
|
||||
appendOrganizationAndApp(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
{
|
||||
if (qsp_testMode) {
|
||||
const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest");
|
||||
QString path;
|
||||
switch (type) {
|
||||
case GenericDataLocation:
|
||||
case DataLocation:
|
||||
path = qttestDir + QLatin1String("/Application Support");
|
||||
if (type == DataLocation)
|
||||
appendOrganizationAndApp(path);
|
||||
return path;
|
||||
case GenericCacheLocation:
|
||||
case CacheLocation:
|
||||
path = qttestDir + QLatin1String("/Cache");
|
||||
if (type == CacheLocation)
|
||||
appendOrganizationAndApp(path);
|
||||
return path;
|
||||
case ConfigLocation:
|
||||
return qttestDir + QLatin1String("/Preferences");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case HomeLocation:
|
||||
return QDir::homePath();
|
||||
|
@ -63,6 +63,13 @@ static void appendOrganizationAndApp(QString &path)
|
||||
path += QLatin1Char('/') + appName;
|
||||
}
|
||||
|
||||
static bool qsp_testMode = false;
|
||||
|
||||
void QStandardPaths::enableTestMode(bool testMode)
|
||||
{
|
||||
qsp_testMode = testMode;
|
||||
}
|
||||
|
||||
QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
{
|
||||
switch (type) {
|
||||
@ -75,6 +82,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
{
|
||||
// http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
|
||||
QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
|
||||
if (qsp_testMode)
|
||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.qttest/cache");
|
||||
if (xdgCacheHome.isEmpty())
|
||||
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
|
||||
if (type == QStandardPaths::CacheLocation)
|
||||
@ -85,6 +94,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
case GenericDataLocation:
|
||||
{
|
||||
QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
|
||||
if (qsp_testMode)
|
||||
xdgDataHome = QDir::homePath() + QLatin1String("/.qttest/share");
|
||||
if (xdgDataHome.isEmpty())
|
||||
xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
|
||||
if (type == QStandardPaths::DataLocation)
|
||||
@ -95,6 +106,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
{
|
||||
// http://standards.freedesktop.org/basedir-spec/latest/
|
||||
QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME"));
|
||||
if (qsp_testMode)
|
||||
xdgConfigHome = QDir::homePath() + QLatin1String("/.qttest/config");
|
||||
if (xdgConfigHome.isEmpty())
|
||||
xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
|
||||
return xdgConfigHome;
|
||||
@ -140,7 +153,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
if (xdgConfigHome.isEmpty())
|
||||
xdgConfigHome = QDir::homePath() + QLatin1String("/.config");
|
||||
QFile file(xdgConfigHome + QLatin1String("/user-dirs.dirs"));
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
if (!qsp_testMode && file.open(QIODevice::ReadOnly)) {
|
||||
QHash<QString, QString> lines;
|
||||
QTextStream stream(&file);
|
||||
// Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop"
|
||||
|
@ -85,6 +85,13 @@ static QString convertCharArray(const wchar_t *path)
|
||||
return QDir::fromNativeSeparators(QString::fromWCharArray(path));
|
||||
}
|
||||
|
||||
static bool qsp_testMode = false;
|
||||
|
||||
void QStandardPaths::enableTestMode(bool testMode)
|
||||
{
|
||||
qsp_testMode = testMode;
|
||||
}
|
||||
|
||||
QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
{
|
||||
QString result;
|
||||
@ -105,6 +112,8 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE))
|
||||
#endif
|
||||
result = convertCharArray(path);
|
||||
if (qsp_testMode)
|
||||
result += QLatin1String("/qttest");
|
||||
if (type != GenericDataLocation) {
|
||||
if (!QCoreApplication::organizationName().isEmpty())
|
||||
result += QLatin1Char('/') + QCoreApplication::organizationName();
|
||||
|
@ -60,6 +60,7 @@ class tst_qstandardpaths : public QObject
|
||||
private slots:
|
||||
void testDefaultLocations();
|
||||
void testCustomLocations();
|
||||
void enableTestMode();
|
||||
void testLocateAll();
|
||||
void testDataLocation();
|
||||
void testFindExecutable();
|
||||
@ -69,6 +70,7 @@ private slots:
|
||||
void testAllWritableLocations();
|
||||
|
||||
private:
|
||||
#ifdef Q_XDG_PLATFORM
|
||||
void setCustomLocations() {
|
||||
m_localConfigDir = m_localConfigTempDir.path();
|
||||
m_globalConfigDir = m_globalConfigTempDir.path();
|
||||
@ -80,13 +82,12 @@ private:
|
||||
qputenv("XDG_DATA_DIRS", QFile::encodeName(m_globalAppDir));
|
||||
}
|
||||
void setDefaultLocations() {
|
||||
#ifdef Q_XDG_PLATFORM
|
||||
qputenv("XDG_CONFIG_HOME", QByteArray());
|
||||
qputenv("XDG_CONFIG_DIRS", QByteArray());
|
||||
qputenv("XDG_DATA_HOME", QByteArray());
|
||||
qputenv("XDG_DATA_DIRS", QByteArray());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Config dirs
|
||||
QString m_localConfigDir;
|
||||
@ -156,6 +157,58 @@ void tst_qstandardpaths::testCustomLocations()
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_qstandardpaths::enableTestMode()
|
||||
{
|
||||
QStandardPaths::enableTestMode(true);
|
||||
|
||||
#ifdef Q_XDG_PLATFORM
|
||||
setCustomLocations(); // for the global config dir
|
||||
const QString qttestDir = QDir::homePath() + QLatin1String("/.qttest");
|
||||
|
||||
// ConfigLocation
|
||||
const QString configDir = qttestDir + QLatin1String("/config");
|
||||
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), configDir);
|
||||
const QStringList confDirs = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation);
|
||||
QCOMPARE(confDirs, QStringList() << configDir << m_globalConfigDir);
|
||||
|
||||
// GenericDataLocation
|
||||
const QString dataDir = qttestDir + QLatin1String("/share");
|
||||
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::DataLocation), dataDir);
|
||||
const QStringList gdDirs = QStandardPaths::standardLocations(QStandardPaths::DataLocation);
|
||||
QCOMPARE(gdDirs, QStringList() << dataDir << m_globalAppDir);
|
||||
|
||||
// CacheLocation
|
||||
const QString cacheDir = qttestDir + QLatin1String("/cache");
|
||||
QCOMPARE(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), cacheDir);
|
||||
const QStringList cacheDirs = QStandardPaths::standardLocations(QStandardPaths::CacheLocation);
|
||||
QCOMPARE(cacheDirs, QStringList() << cacheDir);
|
||||
#endif
|
||||
|
||||
// On all platforms, we want to ensure that the writableLocation is different in test mode and real mode.
|
||||
// Check this for locations where test programs typically write. Not desktop, download, music etc...
|
||||
typedef QHash<QStandardPaths::StandardLocation, QString> LocationHash;
|
||||
LocationHash testLocations;
|
||||
testLocations.insert(QStandardPaths::DataLocation, QStandardPaths::writableLocation(QStandardPaths::DataLocation));
|
||||
testLocations.insert(QStandardPaths::GenericDataLocation, QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
|
||||
testLocations.insert(QStandardPaths::ConfigLocation, QStandardPaths::writableLocation(QStandardPaths::ConfigLocation));
|
||||
testLocations.insert(QStandardPaths::CacheLocation, QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
||||
testLocations.insert(QStandardPaths::GenericCacheLocation, QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation));
|
||||
// On Windows, what should "Program Files" become, in test mode?
|
||||
//testLocations.insert(QStandardPaths::ApplicationsLocation, QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation));
|
||||
|
||||
QStandardPaths::enableTestMode(false);
|
||||
|
||||
for (LocationHash::const_iterator it = testLocations.constBegin(); it != testLocations.constEnd(); ++it)
|
||||
QVERIFY2(QStandardPaths::writableLocation(it.key()) != it.value(), qPrintable(it.value()));
|
||||
|
||||
// Check that this is also true with no env vars set
|
||||
#ifdef Q_XDG_PLATFORM
|
||||
setDefaultLocations();
|
||||
for (LocationHash::const_iterator it = testLocations.constBegin(); it != testLocations.constEnd(); ++it)
|
||||
QVERIFY2(QStandardPaths::writableLocation(it.key()) != it.value(), qPrintable(it.value()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_qstandardpaths::testLocateAll()
|
||||
{
|
||||
#ifdef Q_XDG_PLATFORM
|
||||
|
Loading…
Reference in New Issue
Block a user