diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2022-10-21 13:28:30 +0200 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2022-10-31 09:20:25 +0800 |
commit | 4e38a6a1948b69cab1cd434bee57d9aba88970aa (patch) | |
tree | 291d126cdacb7be8b6ed4b8c453465cdd307e4a0 /tests/auto/core | |
parent | 32b71a40cdbcd77956b309b032caafa02abcc13f (diff) |
QQmlStandardPaths: don't convert URLs to local files
Some of the paths return by QStandardPaths are not
local files, but URLs with a different scheme. In
particular, on iOS the QStandardPaths::PicturesLocation
will return "assets-library://". So be more
careful before converting a standard path to
a file system path, and check up-front if the
path is already a valid URL.
(\sa https://doc.qt.io/qt-6/qfiledialog.html#setDirectory)
Task-number: QTBUG-107844
Change-Id: Ic57e88833d519f5df484215360ee7e8d23c0106a
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'tests/auto/core')
-rw-r--r-- | tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp b/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp index 9c66bb25cf..b8f7878b41 100644 --- a/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp +++ b/tests/auto/core/qqmlstandardpaths/tst_qqmlstandardpaths.cpp @@ -3,6 +3,7 @@ #include <QQmlEngine> #include <QQmlComponent> +#include <QQmlExpression> #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtCore/qstandardpaths.h> @@ -15,6 +16,31 @@ public: private Q_SLOTS: void standardPaths(); + void standardLocations(); +}; + +static const QList<QStandardPaths::StandardLocation> allStandardLocations = { + QStandardPaths::DesktopLocation, + QStandardPaths::DocumentsLocation, + QStandardPaths::FontsLocation, + QStandardPaths::ApplicationsLocation, + QStandardPaths::MusicLocation, + QStandardPaths::MoviesLocation, + QStandardPaths::PicturesLocation, + QStandardPaths::TempLocation, + QStandardPaths::HomeLocation, + QStandardPaths::AppLocalDataLocation, + QStandardPaths::CacheLocation, + QStandardPaths::GenericDataLocation, + QStandardPaths::RuntimeLocation, + QStandardPaths::ConfigLocation, + QStandardPaths::DownloadLocation, + QStandardPaths::GenericCacheLocation, + QStandardPaths::GenericConfigLocation, + QStandardPaths::AppDataLocation, + QStandardPaths::AppConfigLocation, + QStandardPaths::PublicShareLocation, + QStandardPaths::TemplatesLocation }; void tst_qqmlstandardpaths::standardPaths() @@ -48,6 +74,67 @@ void tst_qqmlstandardpaths::standardPaths() QCOMPARE(object->property("locateDirectory").toInt(), QStandardPaths::LocateDirectory); } +/* + E.g. + + ENUM_VALUE_TO_STRING(QStandardPaths, StandardLocation, QStandardPaths::DesktopLocation) + + would result in "DesktopLocation". +*/ +#define ENUM_VALUE_TO_STRING(ClassType, UnqualifiedEnumType, enumValue) \ + ClassType::staticMetaObject.enumerator(ClassType::staticMetaObject.indexOfEnumerator( \ + #UnqualifiedEnumType)).valueToKey(enumValue) + +// Tests that the QML implementation of standardLocations() matches the C++ implementation. +void tst_qqmlstandardpaths::standardLocations() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("tst_standardpaths.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + for (const QStandardPaths::StandardLocation standardLocation : allStandardLocations) { + // First, check that the QStandardPaths doesn't give us any empty paths. + // While we're at it, convert the strings to URLs to allow us to compare later on. + const QString locationName = ENUM_VALUE_TO_STRING(QStandardPaths, StandardLocation, standardLocation); + const QList<QString> standardLocationPaths = QStandardPaths::standardLocations(standardLocation); + QList<QUrl> standardLocationUrls; + bool skipLocation = false; + for (const auto &path : standardLocationPaths) { +#ifdef Q_OS_ANDROID + // These paths are empty on Android (see QTBUG-108057 for related doc task). + if (standardLocation == QStandardPaths::ApplicationsLocation + || standardLocation == QStandardPaths::PublicShareLocation + || standardLocation == QStandardPaths::TemplatesLocation) { + skipLocation = true; + continue; + } +#endif + QVERIFY2(!path.isEmpty(), qPrintable(QString::fromLatin1( + "Path for %1 received from QStandardPaths::standardLocations is empty").arg(locationName))); + QUrl url = QUrl(path); + if (url.scheme().isEmpty()) + url = QUrl::fromLocalFile(path); + QVERIFY(!url.isEmpty()); + QVERIFY(url.isValid()); + standardLocationUrls.append(url); + } + if (skipLocation) + continue; + + const QString qml = QLatin1String("StandardPaths.standardLocations(StandardPaths.") + locationName + QLatin1Char(')'); + QQmlExpression qmlExpression(qmlContext(object.data()), object.data(), qml); + const QVariant evaluationResult = qmlExpression.evaluate(); + QVERIFY2(!qmlExpression.hasError(), qPrintable(qmlExpression.error().toString())); + const auto actualValue = evaluationResult.value<QList<QUrl>>(); + // Give some extra context to the failure message since we're not using data rows. + if (actualValue != standardLocationUrls) + qWarning() << "Comparison failed for" << locationName; + QCOMPARE(actualValue, standardLocationUrls); + } +} + QTEST_MAIN(tst_qqmlstandardpaths) #include "tst_qqmlstandardpaths.moc" |