summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/io/qsettings/tst_qsettings.cpp')
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp571
1 files changed, 329 insertions, 242 deletions
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index 732d81d84a..f4d7f076ef 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -1,52 +1,23 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtCore/QSettings>
#include <private/qsettings_p.h>
+
+#include "tst_qmetatype_common.h"
+
#include <QtCore/QCoreApplication>
-#include <QtCore/QDateTime>
-#include <QtCore/QtGlobal>
-#include <QtCore/QMetaType>
-#include <QtCore/QString>
#include <QtCore/QDir>
+#include <QtCore/QEventLoop>
+#include <QtCore/QtGlobal>
#include <QtCore/QThread>
#include <QtCore/QSysInfo>
#if QT_CONFIG(shortcut)
# include <QtGui/QKeySequence>
#endif
-#include <QtCore>
-#include <QtGui>
-#include "tst_qmetatype_common.h"
-
#include <cctype>
#include <stdlib.h>
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
@@ -57,14 +28,27 @@
#if defined(Q_OS_WIN)
#include <QtCore/qt_windows.h>
#include <private/qwinregistry_p.h>
+#define QT_UNLINK _unlink
#else
#include <unistd.h>
+#define QT_UNLINK unlink
#endif
#if defined(Q_OS_DARWIN)
#include <CoreFoundation/CoreFoundation.h>
#endif
+#ifdef Q_OS_INTEGRITY
+#include "qplatformdefs.h"
+#endif
+
+#if defined(Q_OS_WASM)
+#include <QtCore/private/qstdweb_p.h>
+
+#include "emscripten/threading.h"
+#include "emscripten/val.h"
+#endif
+
Q_DECLARE_METATYPE(QSettings::Format)
#ifndef QSETTINGS_P_H_VERSION
@@ -102,6 +86,20 @@ static inline bool canWriteNativeSystemSettings()
static const char insufficientPermissionSkipMessage[] = "Insufficient permissions for this test.";
+static void populateWithFormats()
+{
+ QTest::addColumn<QSettings::Format>("format");
+
+ QTest::newRow("native") << QSettings::NativeFormat;
+#if defined(Q_OS_WASM)
+ if (qstdweb::haveJspi())
+ QTest::newRow("idb") << QSettings::WebIndexedDBFormat;
+#endif // defined(Q_OS_WASM)
+ QTest::newRow("ini") << QSettings::IniFormat;
+ QTest::newRow("custom1") << QSettings::CustomFormat1;
+ QTest::newRow("custom2") << QSettings::CustomFormat2;
+}
+
class tst_QSettings : public QObject
{
Q_OBJECT
@@ -114,8 +112,11 @@ public slots:
void cleanup() { cleanupTestFiles(); }
private slots:
void getSetCheck();
- void ctor_data();
+ void ctor_data() { populateWithFormats(); }
void ctor();
+#ifdef Q_OS_WASM
+ void idb();
+#endif
void beginGroup();
void setValue();
void remove();
@@ -126,16 +127,16 @@ private slots:
void syncAlternateDataStream();
#endif
void setFallbacksEnabled();
- void setFallbacksEnabled_data();
- void fromFile_data();
+ void setFallbacksEnabled_data() { populateWithFormats(); }
+ void fromFile_data() { populateWithFormats(); }
void fromFile();
- void testArrays_data();
+ void testArrays_data() { populateWithFormats(); }
void testArrays();
- void testCaseSensitivity_data();
+ void testCaseSensitivity_data() { populateWithFormats(); }
void testCaseSensitivity();
void testErrorHandling_data();
void testErrorHandling();
- void testChildKeysAndGroups_data();
+ void testChildKeysAndGroups_data() { populateWithFormats(); }
void testChildKeysAndGroups();
void testUpdateRequestEvent();
void testThreadSafety();
@@ -145,10 +146,10 @@ private slots:
void testRegistryShortRootNames();
void testRegistry32And64Bit();
void trailingWhitespace();
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
void fileName();
#endif
- void isWritable_data();
+ void isWritable_data() { populateWithFormats(); }
void isWritable();
void registerFormat();
void setPath();
@@ -162,23 +163,23 @@ private slots:
#endif
#ifdef QT_BUILD_INTERNAL
- void allKeys_data();
+ void allKeys_data() { populateWithFormats(); }
void allKeys();
- void childGroups_data();
+ void childGroups_data() { populateWithFormats(); }
void childGroups();
- void childKeys_data();
+ void childKeys_data() { populateWithFormats(); }
void childKeys();
void testIniParsing_data();
void testIniParsing();
void testEscapes();
void testNormalizedKey_data();
void testNormalizedKey();
- void testVariantTypes_data();
+ void testVariantTypes_data() { populateWithFormats(); }
void testVariantTypes();
void testMetaTypes_data();
void testMetaTypes();
#endif
- void rainersSyncBugOnMac_data();
+ void rainersSyncBugOnMac_data() { populateWithFormats(); }
void rainersSyncBugOnMac();
void recursionBug();
@@ -192,6 +193,10 @@ private slots:
void floatAsQVariant();
void testXdg();
+
+ void testReadKeys_data();
+ void testReadKeys();
+
private:
void cleanupTestFiles();
@@ -274,16 +279,6 @@ static bool writeCustom3File(QIODevice &device, const QSettings::SettingsMap &ma
return true;
}
-static void populateWithFormats()
-{
- QTest::addColumn<QSettings::Format>("format");
-
- QTest::newRow("native") << QSettings::NativeFormat;
- QTest::newRow("ini") << QSettings::IniFormat;
- QTest::newRow("custom1") << QSettings::CustomFormat1;
- QTest::newRow("custom2") << QSettings::CustomFormat2;
-}
-
tst_QSettings::tst_QSettings()
: m_canWriteNativeSystemSettings(canWriteNativeSystemSettings())
{
@@ -343,6 +338,32 @@ void tst_QSettings::cleanupTestFiles()
QSettings(QSettings::UserScope, "other.software.org").clear();
QSettings(QSettings::SystemScope, "other.software.org").clear();
#endif
+#if defined(Q_OS_WASM)
+ emscripten::val::global("window")["localStorage"].call<void>("clear");
+ if (qstdweb::haveJspi()) {
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::UserScope, "software.org",
+ "KillerAPP")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::SystemScope, "software.org",
+ "KillerAPP")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::UserScope, "other.software.org",
+ "KillerAPP")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::SystemScope,
+ "other.software.org", "KillerAPP")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::UserScope, "software.org")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::SystemScope, "software.org")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::UserScope, "other.software.org")
+ .clear();
+ QSettings(QSettings::Format::WebIndexedDBFormat, QSettings::SystemScope,
+ "other.software.org")
+ .clear();
+ }
+#endif
const QString foo(QLatin1String("foo"));
@@ -355,11 +376,6 @@ void tst_QSettings::cleanupTestFiles()
Test the constructors and the assignment operator.
*/
-void tst_QSettings::ctor_data()
-{
- populateWithFormats();
-}
-
void tst_QSettings::ctor()
{
QFETCH(QSettings::Format, format);
@@ -522,10 +538,10 @@ void tst_QSettings::ctor()
QSettings settings5(format, QSettings::UserScope, "SoftWare.ORG", "killerApp");
bool caseSensitive = true;
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
if (format == QSettings::NativeFormat) {
// more details in QMacSettingsPrivate::QMacSettingsPrivate(), organization was comify()-ed
- caseSensitive = settings5.fileName().contains("SoftWare.ORG");;
+ caseSensitive = settings5.fileName().contains("SoftWare.ORG");
} else {
caseSensitive = pathconf(settings5.fileName().toLatin1().constData(), _PC_CASE_SENSITIVE);
}
@@ -575,7 +591,7 @@ void tst_QSettings::ctor()
QCOMPARE(settings1.value("alpha/beta/geometry/width").toInt(), 3);
QCOMPARE(settings1.value("alpha/beta/geometry/height").toInt(), 4);
QCOMPARE(settings1.value("alpha/gamma/splitter").toInt(), 5);
- QCOMPARE(settings1.allKeys().count(), 6);
+ QCOMPARE(settings1.allKeys().size(), 6);
QCOMPARE(settings2.value("alpha/beta/geometry").toInt(), -7);
QCOMPARE(settings2.value("alpha/beta/geometry/x").toInt(), 1);
@@ -583,7 +599,7 @@ void tst_QSettings::ctor()
QCOMPARE(settings2.value("alpha/beta/geometry/width").toInt(), 3);
QCOMPARE(settings2.value("alpha/beta/geometry/height").toInt(), 4);
QCOMPARE(settings2.value("alpha/gamma/splitter").toInt(), 5);
- QCOMPARE(settings2.allKeys().count(), 6);
+ QCOMPARE(settings2.allKeys().size(), 6);
}
{
@@ -594,7 +610,7 @@ void tst_QSettings::ctor()
QCOMPARE(settings1.value("alpha/beta/geometry/width").toInt(), 3);
QCOMPARE(settings1.value("alpha/beta/geometry/height").toInt(), 4);
QCOMPARE(settings1.value("alpha/gamma/splitter").toInt(), 5);
- QCOMPARE(settings1.allKeys().count(), 6);
+ QCOMPARE(settings1.allKeys().size(), 6);
}
{
@@ -603,7 +619,7 @@ void tst_QSettings::ctor()
QCoreApplication::instance()->setOrganizationName("");
QCoreApplication::instance()->setApplicationName("");
QSettings settings;
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
QEXPECT_FAIL("native", "Default settings on Mac are valid, despite organization domain, name, and app name being null", Continue);
#endif
QCOMPARE(settings.status(), QSettings::AccessError);
@@ -618,7 +634,7 @@ void tst_QSettings::ctor()
}
QSettings settings(format, QSettings::UserScope, "", "");
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
QEXPECT_FAIL("native", "Default settings on Mac are valid, despite organization domain, name, and app name being null", Continue);
#endif
QCOMPARE(settings.status(), QSettings::AccessError);
@@ -643,6 +659,50 @@ void tst_QSettings::ctor()
}
}
+#if defined(Q_OS_WASM)
+void tst_QSettings::idb()
+{
+ if (!qstdweb::haveJspi())
+ QSKIP("JSPI needed for IndexedDB format");
+
+ QString systemScopeOrganizationWideFile;
+ {
+ QSettings settingsUserScopeAppSpecific(QSettings::Format::WebIndexedDBFormat,
+ QSettings::UserScope, "software.org", "KillerAPP");
+ QSettings settingsUserScopeOrganizationWide(QSettings::Format::WebIndexedDBFormat,
+ QSettings::UserScope, "software.org");
+ QSettings settingsSystemScopeAppSpecific(QSettings::Format::WebIndexedDBFormat,
+ QSettings::SystemScope, "software.org",
+ "KillerAPP");
+ QSettings settingsSystemScopeOrganizationWide(QSettings::Format::WebIndexedDBFormat,
+ QSettings::SystemScope, "software.org");
+
+ settingsSystemScopeOrganizationWide.setValue("testKey", 1);
+ systemScopeOrganizationWideFile = settingsSystemScopeOrganizationWide.fileName();
+ }
+
+ // Emscripten's memfs has a bug that makes a file appear twice in the hashmap.
+ while (QFile::exists(systemScopeOrganizationWideFile)) {
+ Q_ASSERT(QFile::remove(systemScopeOrganizationWideFile));
+ }
+
+ QEventLoop loop;
+ QTimer timer;
+ timer.setInterval(1);
+
+ connect(&timer, &QTimer::timeout, [&loop]() { loop.quit(); });
+ timer.start();
+
+ loop.exec();
+ {
+ QSettings settingsUserScopeAppSpecific(QSettings::Format::WebIndexedDBFormat,
+ QSettings::UserScope, "software.org", "KillerAPP");
+
+ QCOMPARE(settingsUserScopeAppSpecific.value("testKey").toInt(), 1);
+ }
+}
+#endif // Q_OS_WASM
+
void tst_QSettings::testByteArray_data()
{
QTest::addColumn<QByteArray>("data");
@@ -709,6 +769,10 @@ void tst_QSettings::embeddedZeroByte_data()
QTest::newRow("@bytearray\\0") << QVariant(bytes);
QTest::newRow("@string\\0") << QVariant(QString::fromLatin1(bytes.data(), bytes.size()));
+
+ bytes = QByteArray("@\xdd\x7d", 3);
+ QTest::newRow("@-prefixed data") << QVariant(bytes);
+ QTest::newRow("@-prefixed data as string") << QVariant(QString::fromLatin1(bytes.data(), bytes.size()));
}
void tst_QSettings::embeddedZeroByte()
@@ -945,7 +1009,7 @@ void tst_QSettings::testIniParsing()
if ( settings.status() == QSettings::NoError ) { // else no point proceeding
QVariant v = settings.value(key);
if (expect.isValid())
- QVERIFY(v.canConvert(expect.type()));
+ QVERIFY(v.canConvert(expect.metaType()));
// check some types so as to give prettier error messages
if ( v.typeId() == QMetaType::QString ) {
QCOMPARE(v.toString(), expect.toString());
@@ -1173,7 +1237,7 @@ template<int MetaTypeId>
static void testMetaTypesHelper(QSettings::Format format)
{
typedef typename MetaEnumToType<MetaTypeId>::Type Type;
- const char *key = QMetaType::typeName(MetaTypeId);
+ const char *key = QMetaType(MetaTypeId).name();
Type *value = TestValueFactory<MetaTypeId>::create();
QVariant inputVariant = QVariant::fromValue(*value);
@@ -1192,8 +1256,8 @@ static void testMetaTypesHelper(QSettings::Format format)
QSettings settings(format, scope, organization, applicationName);
QVariant outputVariant = settings.value(key);
if (MetaTypeId != QMetaType::QVariant)
- QVERIFY(outputVariant.canConvert(MetaTypeId));
- if (outputVariant.type() != inputVariant.type())
+ QVERIFY(outputVariant.canConvert(QMetaType(MetaTypeId)));
+ if (outputVariant.typeId() != inputVariant.typeId())
qWarning() << "type mismatch between" << inputVariant << "and" << outputVariant;
QCOMPARE(qvariant_cast<Type >(outputVariant), *value);
}
@@ -1232,7 +1296,7 @@ void tst_QSettings::testMetaTypes_data()
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
{ \
const char *formatName = QMetaEnum::fromType<QSettings::Format>().valueToKey(formats[i]); \
- const char *typeName = QMetaType::typeName(QMetaType::MetaTypeName); \
+ const char *typeName = QMetaType(QMetaType::MetaTypeName).name(); \
QTest::newRow(QString("%1:%2").arg(formatName).arg(typeName).toLatin1().constData()) \
<< QSettings::Format(formats[i]) << int(QMetaType::MetaTypeName); \
}
@@ -1267,106 +1331,102 @@ FOR_EACH_CORE_METATYPE(RETURN_CREATE_FUNCTION)
TypeTestFunctionGetter::get(type)(format);
}
-
-void tst_QSettings::testVariantTypes_data()
-{
- populateWithFormats();
-}
#endif
#ifdef QT_BUILD_INTERNAL
void tst_QSettings::testVariantTypes()
{
-#define testVal(key, val, tp, rtype) \
- { \
- QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP"); \
- settings1.setValue(key, QVariant::fromValue(val)); \
- } \
- QConfFile::clearCache(); \
- { \
- QSettings settings2(format, QSettings::UserScope, "software.org", "KillerAPP"); \
- QVariant v = settings2.value(key); \
- QVERIFY(qvariant_cast<tp >(v) == val); \
- QVERIFY(v.type() == QVariant::rtype); \
+ QFETCH(QSettings::Format, format);
+
+ {
+ QSettings settings(format, QSettings::UserScope, "software.org", "KillerAPP");
+ QVERIFY(!settings.contains("empty"));
+ QCOMPARE(settings.value("empty"), QVariant());
+
+ settings.setValue("empty", QVariant());
+ QVERIFY(settings.contains("empty"));
+ QCOMPARE(settings.value("empty"), QVariant());
+
+ settings.setValue("empty", QVariant(1));
+ QVERIFY(settings.contains("empty"));
+ QCOMPARE(settings.value("empty"), QVariant(1));
+
+ settings.setValue("empty", QVariant());
+ QVERIFY(settings.contains("empty"));
+ QCOMPARE(settings.value("empty"), QVariant());
+
+ settings.remove("empty");
+ QVERIFY(!settings.contains("empty"));
+ QCOMPARE(settings.value("empty"), QVariant());
}
- typedef QMap<QString, QVariant> TestVariantMap;
+ auto checker = [format](const char *key, auto value, QMetaType::Type expected) {
+ {
+ QSettings settings(format, QSettings::UserScope, "software.org", "KillerAPP");
+ settings.setValue(key, QVariant::fromValue(value));
+ }
+ QConfFile::clearCache();
+ {
+ QSettings settings(format, QSettings::UserScope, "software.org", "KillerAPP");
+ QVariant actual = settings.value(key);
+ QCOMPARE(actual.metaType().id(), expected);
+ QCOMPARE(qvariant_cast<decltype(value)>(actual), value);
+ }
+ };
+#define testValue(key, supplied, expected) do { \
+ checker(key, supplied, QMetaType::expected); \
+ if (QTest::currentTestFailed()) \
+ return; \
+ } while (0)
- QFETCH(QSettings::Format, format);
+ typedef QMap<QString, QVariant> TestVariantMap;
TestVariantMap m2;
m2.insert("ene", "due");
m2.insert("rike", "fake");
m2.insert("borba", "dorba");
- testVal("key2", m2, TestVariantMap, Map);
-
- QStringList l2;
+ testValue("customMap", m2, QVariantMap);
- l2 << "ene" << "due" << "@Point(1 2)" << "@fake";
- testVal("key3", l2, QStringList, StringList);
+ QStringList l2 { "ene", "due", "@Point(1 2)", "@fake" };
+ testValue("stringsAt", l2, QStringList);
- l2.clear();
- l2 << "ene" << "due" << "rike" << "fake";
- testVal("key3", l2, QStringList, StringList);
+ l2 = { "ene", "due", "rike", "fake" };
+ testValue("strings", l2, QStringList);
- QList<QVariant> l3;
QDate date = QDate::currentDate();
QTime time = QTime::currentTime();
- l3 << QString("ene") << 10 << QVariant::fromValue(QColor(1, 2, 3)) << QVariant(QRect(1, 2, 3, 4))
- << QVariant(QSize(4, 56)) << QVariant(QPoint(4, 2)) << true << false << date << time;
- testVal("key3", l3, QVariantList, List);
-
- testVal("key4", QString("hello"), QString, String);
- testVal("key5", QColor(1, 2, 3), QColor, Color);
- testVal("key6", QRect(1, 2, 3, 4), QRect, Rect);
- testVal("key7", QSize(4, 56), QSize, Size);
- testVal("key8", QPoint(4, 2), QPoint, Point);
- testVal("key10", date, QDate, Date);
- testVal("key11", time, QTime, Time);
- testVal("key12", QByteArray("foo bar"), QByteArray, ByteArray);
-
- {
- QSettings settings(format, QSettings::UserScope, "software.org", "KillerAPP");
- QVERIFY(!settings.contains("key99"));
- QCOMPARE(settings.value("key99"), QVariant());
+ QList<QVariant> l3 { QString("ene"), 10, QVariant::fromValue(QColor(1, 2, 3)),
+ QVariant(QRect(1, 2, 3, 4)), QVariant(QSize(4, 56)), QVariant(QPoint(4, 2)),
+ true, false, date, time };
+ testValue("mixedList", l3, QVariantList);
+
+ testValue("string", QString("hello"), QString);
+ testValue("color", QColor(1, 2, 3), QColor);
+ testValue("rect", QRect(1, 2, 3, 4), QRect);
+ testValue("size", QSize(4, 56), QSize);
+ testValue("point", QPoint(4, 2), QPoint);
+ testValue("date", date, QDate);
+ testValue("time", time, QTime);
+ testValue("byteArray", QByteArray("foo bar"), QByteArray);
+
+ QList<QVariant> l4 { QVariant(m2), QVariant(l2), QVariant(l3) };
+ testValue("collectList", l4, QVariantList);
- settings.setValue("key99", QVariant());
- QVERIFY(settings.contains("key99"));
- QCOMPARE(settings.value("key99"), QVariant());
-
- settings.setValue("key99", QVariant(1));
- QVERIFY(settings.contains("key99"));
- QCOMPARE(settings.value("key99"), QVariant(1));
-
- settings.setValue("key99", QVariant());
- QVERIFY(settings.contains("key99"));
- QCOMPARE(settings.value("key99"), QVariant());
-
- settings.remove("key99");
- QVERIFY(!settings.contains("key99"));
- QCOMPARE(settings.value("key99"), QVariant());
- }
-
- QList<QVariant> l4;
- l4 << QVariant(m2) << QVariant(l2) << QVariant(l3);
- testVal("key13", l4, QVariantList, List);
QDateTime dt = QDateTime::currentDateTime();
- dt.setOffsetFromUtc(3600);
- testVal("key14", dt, QDateTime, DateTime);
+ dt.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(3600));
+ testValue("dateTime", dt, QDateTime);
#if QT_CONFIG(shortcut)
// We store key sequences as strings instead of binary variant blob, for improved
// readability in the resulting format.
- if (format >= QSettings::InvalidFormat) {
- testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QKeySequence, KeySequence);
- } else {
- testVal("keysequence",
- QKeySequence(Qt::ControlModifier + Qt::Key_F1).toString(QKeySequence::NativeText),
- QString, String);
- }
+ QKeySequence seq(Qt::ControlModifier | Qt::Key_F1);
+ if (format >= QSettings::InvalidFormat)
+ testValue("keySequence", seq, QKeySequence);
+ else
+ testValue("keySequence", seq.toString(QKeySequence::NativeText), QString);
#endif // QT_CONFIG(shortcut)
-#undef testVal
+#undef testValue
}
#endif
@@ -1736,7 +1796,7 @@ void tst_QSettings::sync()
// Now "some other app" will change other.software.org.ini
QString userConfDir = settingsPath("__user__") + QDir::separator();
- unlink((userConfDir + "other.software.org.ini").toLatin1());
+ QT_UNLINK((userConfDir + "other.software.org.ini").toLatin1());
rename((userConfDir + "software.org.ini").toLatin1(),
(userConfDir + "other.software.org.ini").toLatin1());
@@ -1756,12 +1816,12 @@ void tst_QSettings::sync()
QCOMPARE(settings2.value("moo/beta/geometry/width").toInt(), 3);
QCOMPARE(settings2.value("moo/beta/geometry/height").toInt(), 4);
QCOMPARE(settings2.value("moo/gamma/splitter").toInt(), 5);
- QCOMPARE(settings2.allKeys().count(), 11);
+ QCOMPARE(settings2.allKeys().size(), 11);
// Now, software.org.ini no longer exists, this is same as another app
// clearing all settings.
settings1.sync();
- QCOMPARE(settings1.allKeys().count(), 0);
+ QCOMPARE(settings1.allKeys().size(), 0);
// Now "some other app" will change software.org.ini
QVERIFY(QFile::rename((userConfDir + "other.software.org.ini").toLatin1(),
@@ -1779,7 +1839,7 @@ void tst_QSettings::sync()
QCOMPARE(settings1.value("moo/beta/geometry/width").toInt(), 3);
QCOMPARE(settings1.value("moo/beta/geometry/height").toInt(), 4);
QCOMPARE(settings1.value("moo/gamma/splitter").toInt(), 5);
- QCOMPARE(settings1.allKeys().count(), 11);
+ QCOMPARE(settings1.allKeys().size(), 11);
}
void tst_QSettings::syncNonWriteableDir()
@@ -1854,11 +1914,6 @@ void tst_QSettings::syncAlternateDataStream()
}
#endif
-void tst_QSettings::setFallbacksEnabled_data()
-{
- populateWithFormats();
-}
-
void tst_QSettings::setFallbacksEnabled()
{
QFETCH(QSettings::Format, format);
@@ -1943,11 +1998,6 @@ void tst_QSettings::setFallbacksEnabled()
QVERIFY(!settings1.contains("key 5"));
}
-void tst_QSettings::testChildKeysAndGroups_data()
-{
- populateWithFormats();
-}
-
void tst_QSettings::testChildKeysAndGroups()
{
QFETCH(QSettings::Format, format);
@@ -2008,6 +2058,24 @@ void tst_QSettings::testChildKeysAndGroups()
l.sort();
QCOMPARE(l, QStringList() << "bar" << "foo");
}
+
+#if defined(Q_OS_WASM)
+ // WebIndexedDBFormat does not use the cached settings file on creation, but instead always uses
+ // the file from the indexed DB anew.
+ if (format == QSettings::Format::WebIndexedDBFormat)
+ settings1.sync();
+#endif
+
+ {
+ QSettings settings3(format, QSettings::UserScope, "software.org", "application");
+ settings3.setFallbacksEnabled(false);
+ settings3.beginGroup("alpha");
+ QCOMPARE(settings3.childGroups(), QStringList());
+ settings3.setFallbacksEnabled(true);
+ QStringList children = settings3.childGroups();
+ children.sort();
+ QCOMPARE(children, QStringList({"beta", "gamma"}));
+ }
}
void tst_QSettings::testUpdateRequestEvent()
@@ -2067,7 +2135,7 @@ void SettingsThread::run()
settings.setValue(QString::number((param * NumIterations) + i), param);
settings.sync();
if (settings.status() != QSettings::NoError) {
- QWARN(qPrintable(QString("Unexpected QSettings status %1").arg((int)settings.status())));
+ qWarning() << qPrintable(QString("Unexpected QSettings status %1").arg((int)settings.status()));
++numThreadSafetyFailures;
}
}
@@ -2075,6 +2143,16 @@ void SettingsThread::run()
void tst_QSettings::testThreadSafety()
{
+#if !QT_CONFIG(thread)
+ QSKIP("This test requires threads to be enabled.");
+#endif // !QT_CONFIG(thread)
+#if defined(Q_OS_WASM)
+ if (!qstdweb::haveJspi())
+ QSKIP("Test needs jspi on WASM. Calls are proxied to the main thread from SettingsThreads, "
+ "which necessitates the use of an event loop to yield to the main loop. Event loops "
+ "require jspi.");
+#endif
+
SettingsThread threads[NumThreads];
int i, j;
@@ -2082,6 +2160,19 @@ void tst_QSettings::testThreadSafety()
for (i = 0; i < NumThreads; ++i)
threads[i].start(i + 1);
+
+#if defined(Q_OS_WASM) && QT_CONFIG(thread)
+ QEventLoop loop;
+ int remaining = NumThreads;
+ for (int i = 0; i < NumThreads; ++i) {
+ QObject::connect(&threads[i], &QThread::finished, this, [&remaining, &loop]() {
+ if (!--remaining)
+ loop.quit();
+ });
+ }
+ loop.exec();
+#endif // defined(Q_OS_WASM) && QT_CONFIG(thread)
+
for (i = 0; i < NumThreads; ++i)
threads[i].wait();
@@ -2136,20 +2227,17 @@ void tst_QSettings::testNormalizedKey()
inKey.detach();
- QString result = QSettingsPrivate::normalizedKey(inKey);
- QCOMPARE(result, outKey);
-
- /*
- If the key is already normalized, we verify that outKey is
- just a shallow copy of the input string. This is an important
- optimization that shouldn't be removed accidentally.
- */
- if (inKey == outKey) {
- QVERIFY(!result.isDetached());
- } else {
- if (!result.isEmpty()) {
- QVERIFY(result.isDetached());
- }
+ {
+ auto result = QSettingsPrivate::normalizedKey(inKey);
+ QCOMPARE(result, outKey);
+ }
+ {
+ auto result = QSettingsPrivate::normalizedKey(QUtf8StringView{inKey.toUtf8()});
+ QCOMPARE(result, outKey);
+ }
+ {
+ auto result = QSettingsPrivate::normalizedKey(QLatin1String{inKey.toLatin1()});
+ QCOMPARE(result, outKey);
}
}
#endif
@@ -2175,6 +2263,8 @@ void tst_QSettings::testEmptyData()
vList2 << emptyString << nullString;
vList3 << QString("foo");
+ const auto rm = QScopeGuard([=] { QFile::remove(filename); });
+
{
QSettings settings(filename, QSettings::IniFormat);
settings.setValue("nullString", nullString);
@@ -2228,7 +2318,6 @@ void tst_QSettings::testEmptyData()
QCOMPARE(settings.value("vList3").toList(), vList3);
QCOMPARE(settings.status(), QSettings::NoError);
}
- QFile::remove(filename);
}
void tst_QSettings::testEmptyKey()
@@ -2334,11 +2423,6 @@ void tst_QSettings::trailingWhitespace()
}
}
-void tst_QSettings::fromFile_data()
-{
- populateWithFormats();
-}
-
void tst_QSettings::fromFile()
{
QFETCH(QSettings::Format, format);
@@ -2360,6 +2444,12 @@ void tst_QSettings::fromFile()
QStringList strList = QStringList() << "hope" << "destiny" << "chastity";
+#if !defined(Q_OS_WIN)
+ auto deleteFile = QScopeGuard([path, oldCur]() {
+ QFile::remove(path);
+ QDir::setCurrent(oldCur);
+ });
+#endif // !defined(Q_OS_WIN)
{
QSettings settings1(path, format);
QVERIFY(settings1.allKeys().isEmpty());
@@ -2395,8 +2485,6 @@ void tst_QSettings::fromFile()
QCOMPARE(settings1.value("gamma/foo.bar").toInt(), 4);
QCOMPARE(settings1.allKeys().size(), 3);
}
-
- QDir::setCurrent(oldCur);
}
static bool containsSubList(QStringList mom, QStringList son)
@@ -2408,11 +2496,6 @@ static bool containsSubList(QStringList mom, QStringList son)
return true;
}
-void tst_QSettings::testArrays_data()
-{
- populateWithFormats();
-}
-
/*
Tests beginReadArray(), beginWriteArray(), endArray(), and
setArrayIndex().
@@ -2478,17 +2561,17 @@ void tst_QSettings::testArrays()
QCOMPARE(settings1.value("ene").toInt(), 2);
QCOMPARE(settings1.value("due").toInt(), 3);
QCOMPARE(settings1.value("rike").toInt(), 4);
- QCOMPARE(settings1.allKeys().count(), 3);
+ QCOMPARE(settings1.allKeys().size(), 3);
settings1.setArrayIndex(1);
QCOMPARE(settings1.value("ene").toInt(), 5);
QCOMPARE(settings1.value("due").toInt(), 6);
QCOMPARE(settings1.value("rike").toInt(), 7);
- QCOMPARE(settings1.allKeys().count(), 3);
+ QCOMPARE(settings1.allKeys().size(), 3);
settings1.setArrayIndex(2);
QCOMPARE(settings1.value("ene").toInt(), 8);
QCOMPARE(settings1.value("due").toInt(), 9);
QCOMPARE(settings1.value("rike").toInt(), 10);
- QCOMPARE(settings1.allKeys().count(), 3);
+ QCOMPARE(settings1.allKeys().size(), 3);
settings1.endArray();
settings1.endGroup();
@@ -2538,17 +2621,17 @@ void tst_QSettings::testArrays()
QCOMPARE(settings1.value("ene").toInt(), 2);
QCOMPARE(settings1.value("due").toInt(), 3);
QCOMPARE(settings1.value("rike").toInt(), 4);
- QCOMPARE(settings1.allKeys().count(), 3);
+ QCOMPARE(settings1.allKeys().size(), 3);
settings1.setArrayIndex(1);
QCOMPARE(settings1.value("ene").toInt(), 5);
QCOMPARE(settings1.value("due").toInt(), 6);
QCOMPARE(settings1.value("rike").toInt(), 7);
- QCOMPARE(settings1.allKeys().count(), 3);
+ QCOMPARE(settings1.allKeys().size(), 3);
settings1.setArrayIndex(2);
QCOMPARE(settings1.value("ene").toInt(), 8);
QCOMPARE(settings1.value("due").toInt(), 9);
QCOMPARE(settings1.value("rike").toInt(), 10);
- QCOMPARE(settings1.allKeys().count(), 3);
+ QCOMPARE(settings1.allKeys().size(), 3);
settings1.endArray();
settings1.endGroup();
@@ -2693,7 +2776,7 @@ static QByteArray iniEscapedKey(const QString &str)
static QString iniUnescapedKey(const QByteArray &ba)
{
QString result;
- QSettingsPrivate::iniUnescapedKey(ba, 0, ba.size(), result);
+ QSettingsPrivate::iniUnescapedKey(ba, result);
return result;
}
@@ -2708,7 +2791,7 @@ static QStringList iniUnescapedStringList(const QByteArray &ba)
{
QStringList result;
QString str;
- bool isStringList = QSettingsPrivate::iniUnescapedStringList(ba, 0, ba.size(), str, result);
+ bool isStringList = QSettingsPrivate::iniUnescapedStringList(ba, str, result);
if (!isStringList)
result = QStringList(str);
return result;
@@ -2720,7 +2803,7 @@ QString escapeWeirdChars(const QString &s)
QString result;
bool escapeNextDigit = false;
- for (int i = 0; i < s.length(); ++i) {
+ for (int i = 0; i < s.size(); ++i) {
QChar c = s.at(i);
if (c.unicode() < ' ' || c.unicode() > '~'
|| (escapeNextDigit && c.unicode() >= '0' && c.unicode() <= 'f')) {
@@ -2860,11 +2943,6 @@ void tst_QSettings::testEscapes()
}
#endif
-void tst_QSettings::testCaseSensitivity_data()
-{
- populateWithFormats();
-}
-
void tst_QSettings::testCaseSensitivity()
{
QFETCH(QSettings::Format, format);
@@ -2944,7 +3022,7 @@ void tst_QSettings::testCaseSensitivity()
}
}
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
// Please write a fileName() test for the other platforms
void tst_QSettings::fileName()
{
@@ -3014,11 +3092,6 @@ void tst_QSettings::fileName()
}
#endif
-void tst_QSettings::isWritable_data()
-{
- populateWithFormats();
-}
-
void tst_QSettings::isWritable()
{
QFETCH(QSettings::Format, format);
@@ -3071,13 +3144,6 @@ void tst_QSettings::isWritable()
}
#ifdef QT_BUILD_INTERNAL
-void tst_QSettings::childGroups_data()
-{
- populateWithFormats();
-}
-#endif
-
-#ifdef QT_BUILD_INTERNAL
void tst_QSettings::childGroups()
{
QFETCH(QSettings::Format, format);
@@ -3147,13 +3213,6 @@ void tst_QSettings::childGroups()
#endif
#ifdef QT_BUILD_INTERNAL
-void tst_QSettings::childKeys_data()
-{
- populateWithFormats();
-}
-#endif
-
-#ifdef QT_BUILD_INTERNAL
void tst_QSettings::childKeys()
{
QFETCH(QSettings::Format, format);
@@ -3221,13 +3280,6 @@ void tst_QSettings::childKeys()
#endif
#ifdef QT_BUILD_INTERNAL
-void tst_QSettings::allKeys_data()
-{
- populateWithFormats();
-}
-#endif
-
-#ifdef QT_BUILD_INTERNAL
void tst_QSettings::allKeys()
{
QFETCH(QSettings::Format, format);
@@ -3378,7 +3430,7 @@ void tst_QSettings::setPath()
path checks that it has no bad side effects.
*/
for (int i = 0; i < 2; ++i) {
-#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
+#if !defined(Q_OS_WIN) && !defined(Q_OS_DARWIN) && !defined(Q_OS_WASM)
TEST_PATH(i == 0, "conf", NativeFormat, UserScope, "alpha")
TEST_PATH(i == 0, "conf", NativeFormat, SystemScope, "beta")
#endif
@@ -3487,11 +3539,6 @@ void tst_QSettings::dontReorderIniKeysNeedlessly()
}
#endif
-void tst_QSettings::rainersSyncBugOnMac_data()
-{
- ctor_data();
-}
-
void tst_QSettings::rainersSyncBugOnMac()
{
QFETCH(QSettings::Format, format);
@@ -3500,6 +3547,12 @@ void tst_QSettings::rainersSyncBugOnMac()
if (format == QSettings::NativeFormat)
QSKIP("Apple OSes do not support direct reads from and writes to .plist files, due to caching and background syncing. See QTBUG-34899.");
#endif
+#if defined(Q_OS_WASM)
+ if (format == QSettings::NativeFormat)
+ QSKIP("WASM's localStorage backend recognizes no concept of file");
+ if (format == QSettings::WebIndexedDBFormat)
+ QSKIP("WASM's indexedDB backend uses the virtual FS file only as a backing store");
+#endif // Q_OS_WASM
QString fileName;
@@ -3523,7 +3576,7 @@ void tst_QSettings::rainersSyncBugOnMac()
void tst_QSettings::recursionBug()
{
QPixmap pix(10,10);
- pix.fill("blue");
+ pix.fill(Qt::blue);
{
QSettings settings(settingsPath("starrunner.ini"), QSettings::IniFormat);
@@ -3570,14 +3623,14 @@ void tst_QSettings::consistentRegistryStorage()
}
#endif
-#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(QT_NO_STANDARDPATHS)
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WASM) && !defined(QT_NO_STANDARDPATHS)
QT_BEGIN_NAMESPACE
extern void clearDefaultPaths();
QT_END_NAMESPACE
#endif
void tst_QSettings::testXdg()
{
-#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(QT_NO_STANDARDPATHS)
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_WASM) && !defined(QT_NO_STANDARDPATHS)
// Note: The XDG_CONFIG_DIRS test must be done before overriding the system path
// by QSettings::setPath/setSystemIniPath (used in cleanupTestFiles()).
clearDefaultPaths();
@@ -3642,5 +3695,39 @@ void tst_QSettings::testXdg()
#endif
}
+void tst_QSettings::testReadKeys_data()
+{
+ QTest::addColumn<QString>("filepath");
+
+ QTest::newRow("escaped") << ":/qt5settings.ini";
+ QTest::newRow("utf-8") << ":/utf8settings.ini";
+}
+
+void tst_QSettings::testReadKeys()
+{
+ QFETCH(QString, filepath);
+
+ QSettings settings(filepath, QSettings::IniFormat);
+ QCOMPARE(settings.status(), QSettings::NoError);
+
+ QVariantMap expectedValues;
+ expectedValues.insert("Test/BAR", "BAR");
+ expectedValues.insert("Test/OST", "OST");
+ expectedValues.insert("Test/B\xC3\x84R", "B\xC3\x84R"); // BÄR
+ expectedValues.insert("Test/\xC3\x96SE", "\xC3\x96SE"); // ÖSE
+ expectedValues.insert(
+ "Test/\xD0\xAD\xD1\x82\xD0\xBE/\xD1\x82\xD0\xB5\xD1\x81\xD1\x82", // Это/тест
+ "\xD0\xAD\xD1\x82\xD0\xBE \xD1\x82\xD0\xB5\xD1\x81\xD1\x82"); // Это тест
+ expectedValues.insert(".,'%U\xD0\xB0\xD0\xB1\xD0\xB2\xD0\xB3\"\t", ".,'%!@#$");
+ expectedValues.insert("\xE2\x99\x9F", "\xE2\x99\x98\xE2\x99\x9A"); // ♟︎ ♘♚
+ expectedValues.insert("\xF0\x9F\x8C\x8D", "\xF0\x9F\x8C\x90"); // 🌍 🌐
+
+ QVariantMap readValues;
+ for (const auto &key : settings.allKeys())
+ readValues.insert(key, settings.value(key));
+
+ QCOMPARE(readValues, expectedValues);
+}
+
QTEST_MAIN(tst_QSettings)
#include "tst_qsettings.moc"