diff options
Diffstat (limited to 'tests/auto/corelib/io/qsettings')
-rw-r--r-- | tests/auto/corelib/io/qsettings/.gitattributes | 2 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/CMakeLists.txt | 51 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/float.ini | 3 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/qsettings.pro | 11 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/qsettings.qrc | 12 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/qt5settings.ini | 11 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/resourcefile4.ini | 2 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/resourcefile5.ini | 2 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/tst_qsettings.cpp | 774 | ||||
-rw-r--r-- | tests/auto/corelib/io/qsettings/utf8settings.ini | 11 |
10 files changed, 458 insertions, 421 deletions
diff --git a/tests/auto/corelib/io/qsettings/.gitattributes b/tests/auto/corelib/io/qsettings/.gitattributes index a4ad8d7644..920df33b54 100644 --- a/tests/auto/corelib/io/qsettings/.gitattributes +++ b/tests/auto/corelib/io/qsettings/.gitattributes @@ -1,5 +1,3 @@ resourcefile.ini -crlf resourcefile2.ini -crlf resourcefile3.ini -crlf -resourcefile4.ini -crlf -resourcefile5.ini -crlf diff --git a/tests/auto/corelib/io/qsettings/CMakeLists.txt b/tests/auto/corelib/io/qsettings/CMakeLists.txt new file mode 100644 index 0000000000..e68b2644af --- /dev/null +++ b/tests/auto/corelib/io/qsettings/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qsettings Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsettings LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +# Test: +set(qsettings_resource_files + "bom.ini" + "resourcefile.ini" + "resourcefile2.ini" + "resourcefile3.ini" + "resourcefile6.plist" + "withcomments.ini" + "float.ini" + "qt5settings.ini" + "utf8settings.ini" +) + +qt_internal_add_test(tst_qsettings + SOURCES + tst_qsettings.cpp + INCLUDE_DIRECTORIES + ../../kernel/qmetatype + LIBRARIES + Qt::CorePrivate + Qt::Gui + TESTDATA ${qsettings_resource_files} + BUILTIN_TESTDATA +) + + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_qsettings CONDITION MSVC + LIBRARIES + advapi32 +) + +qt_internal_extend_target(tst_qsettings CONDITION APPLE + LIBRARIES + ${FWCoreFoundation} +) diff --git a/tests/auto/corelib/io/qsettings/float.ini b/tests/auto/corelib/io/qsettings/float.ini new file mode 100644 index 0000000000..bf9312c14c --- /dev/null +++ b/tests/auto/corelib/io/qsettings/float.ini @@ -0,0 +1,3 @@ +[test] +float=0.5 +float_qvariant=@Variant(\0\0\0\x87?\0\0\0) diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro deleted file mode 100644 index 98ea337e7f..0000000000 --- a/tests/auto/corelib/io/qsettings/qsettings.pro +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG += testcase -TARGET = tst_qsettings -QT = core-private gui testlib -SOURCES = tst_qsettings.cpp -RESOURCES += qsettings.qrc -INCLUDEPATH += $$PWD/../../kernel/qmetatype - -msvc: QMAKE_USE += advapi32 -darwin: LIBS += -framework CoreFoundation - -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/io/qsettings/qsettings.qrc b/tests/auto/corelib/io/qsettings/qsettings.qrc deleted file mode 100644 index db1d8c663f..0000000000 --- a/tests/auto/corelib/io/qsettings/qsettings.qrc +++ /dev/null @@ -1,12 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>resourcefile.ini</file> - <file>resourcefile2.ini</file> - <file>resourcefile3.ini</file> - <file>resourcefile4.ini</file> - <file>resourcefile5.ini</file> - <file>resourcefile6.plist</file> - <file>bom.ini</file> - <file>withcomments.ini</file> - </qresource> -</RCC> diff --git a/tests/auto/corelib/io/qsettings/qt5settings.ini b/tests/auto/corelib/io/qsettings/qt5settings.ini new file mode 100644 index 0000000000..59239d29f3 --- /dev/null +++ b/tests/auto/corelib/io/qsettings/qt5settings.ini @@ -0,0 +1,11 @@ +[General] +.%2C%27%25U%U0430%U0431%U0432%U0433%22%09=".,'%!@#$" +%U265F=\x2658\x265a +%UD83C%UDF0D=\xd83c\xdf10 + +[Test] +BAR=BAR +B%C4R=B\xc4R +OST=OST +%D6SE=\xd6SE +%U042D%U0442%U043E\%U0442%U0435%U0441%U0442=\x42d\x442\x43e \x442\x435\x441\x442 diff --git a/tests/auto/corelib/io/qsettings/resourcefile4.ini b/tests/auto/corelib/io/qsettings/resourcefile4.ini deleted file mode 100644 index 09c21b1591..0000000000 --- a/tests/auto/corelib/io/qsettings/resourcefile4.ini +++ /dev/null @@ -1,2 +0,0 @@ -[Fa%E7ade] -QU%C9BEC=Façade/QUÉBEC diff --git a/tests/auto/corelib/io/qsettings/resourcefile5.ini b/tests/auto/corelib/io/qsettings/resourcefile5.ini deleted file mode 100644 index d2d2103560..0000000000 --- a/tests/auto/corelib/io/qsettings/resourcefile5.ini +++ /dev/null @@ -1,2 +0,0 @@ -[Fa%E7ade] -QU%C9BEC=Faade/QUBEC diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index c969e72c18..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$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// 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.h" - #include <cctype> #include <stdlib.h> #if defined(Q_OS_WIN) && defined(Q_CC_GNU) @@ -56,17 +27,28 @@ #if defined(Q_OS_WIN) #include <QtCore/qt_windows.h> -#ifndef Q_OS_WINRT -# include <private/qwinregistry_p.h> -#endif +#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 @@ -77,7 +59,7 @@ QT_FORWARD_DECLARE_CLASS(QSettings) static inline bool canWriteNativeSystemSettings() { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) HKEY key; const LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software", 0, KEY_WRITE, &key); if (result == ERROR_SUCCESS) @@ -104,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 @@ -116,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(); @@ -128,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(); @@ -147,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(); @@ -159,42 +158,45 @@ private slots: #if !defined(Q_OS_WIN) && !defined(QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER) void dontReorderIniKeysNeedlessly(); #endif -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) void consistentRegistryStorage(); #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 setIniCodec(); 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(); void testByteArray_data(); void testByteArray(); void testByteArrayNativeFormat(); - void iniCodec(); void bom(); void embeddedZeroByte_data(); void embeddedZeroByte(); void spaceAfterComment(); + void floatAsQVariant(); void testXdg(); + + void testReadKeys_data(); + void testReadKeys(); + private: void cleanupTestFiles(); @@ -216,12 +218,7 @@ void tst_QSettings::getSetCheck() static QString settingsPath(const char *path = nullptr) { // Temporary path for files that are specified explicitly in the constructor. -#ifndef Q_OS_WINRT static const QString tempPath = QDir::tempPath() + QLatin1String("/tst_QSettings"); -#else - static const QString tempPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) - + QLatin1String("/tst_QSettings"); -#endif return path && *path ? tempPath + QLatin1Char('/') + QLatin1String(path) : tempPath; } @@ -282,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()) { @@ -326,7 +313,7 @@ void tst_QSettings::cleanupTestFiles() if (settingsDir.exists()) QVERIFY(settingsDir.removeRecursively()); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) QSettings("HKEY_CURRENT_USER\\Software\\software.org", QSettings::NativeFormat).clear(); QSettings("HKEY_CURRENT_USER\\Software\\other.software.org", QSettings::NativeFormat).clear(); QSettings("HKEY_CURRENT_USER\\Software\\foo", QSettings::NativeFormat).clear(); @@ -341,7 +328,7 @@ void tst_QSettings::cleanupTestFiles() QSettings("HKEY_LOCAL_MACHINE\\Software\\bat", QSettings::NativeFormat).clear(); QSettings("HKEY_LOCAL_MACHINE\\Software\\baz", QSettings::NativeFormat).clear(); } -#elif defined(Q_OS_DARWIN) || defined(Q_OS_WINRT) +#elif defined(Q_OS_DARWIN) QSettings(QSettings::UserScope, "software.org", "KillerAPP").clear(); QSettings(QSettings::SystemScope, "software.org", "KillerAPP").clear(); QSettings(QSettings::UserScope, "other.software.org", "KillerAPP").clear(); @@ -351,15 +338,36 @@ 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")); -#if defined(Q_OS_WINRT) - QSettings(foo, QSettings::NativeFormat).clear(); - QFile fooFile(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1Char('/') + foo); -#else QFile fooFile(foo); -#endif if (fooFile.exists()) QVERIFY2(fooFile.remove(), qPrintable(fooFile.errorString())); } @@ -368,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); @@ -535,14 +538,14 @@ 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); } -#elif defined(Q_OS_WIN32) || defined(Q_OS_WINRT) +#elif defined(Q_OS_WIN32) caseSensitive = false; #endif if (caseSensitive) @@ -588,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); @@ -596,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); } { @@ -607,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); } { @@ -616,8 +619,8 @@ void tst_QSettings::ctor() QCoreApplication::instance()->setOrganizationName(""); QCoreApplication::instance()->setApplicationName(""); QSettings settings; -#if defined(Q_OS_MAC) || defined(Q_OS_WINRT) - QEXPECT_FAIL("native", "Default settings on Mac/WinRT are valid, despite organization domain, name, and app name being null", Continue); +#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); QCoreApplication::instance()->setOrganizationName("software.org"); @@ -631,8 +634,8 @@ void tst_QSettings::ctor() } QSettings settings(format, QSettings::UserScope, "", ""); -#if defined(Q_OS_MAC) || defined(Q_OS_WINRT) - QEXPECT_FAIL("native", "Default settings on Mac/WinRT are valid, despite organization domain, name, and app name being null", Continue); +#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); QSettings settings2(format, QSettings::UserScope, "software.org", "KillerAPP"); @@ -656,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"); @@ -695,28 +742,6 @@ void tst_QSettings::testByteArrayNativeFormat() #endif } -void tst_QSettings::iniCodec() -{ - { - QSettings settings("QtProject", "tst_qsettings"); - settings.setIniCodec("cp1251"); - QByteArray ba; - ba.resize(256); - for (int i = 0; i < ba.size(); i++) - ba[i] = i; - settings.setValue("array",ba); - } - { - QSettings settings("QtProject", "tst_qsettings"); - settings.setIniCodec("cp1251"); - QByteArray ba = settings.value("array").toByteArray(); - QCOMPARE(ba.size(), 256); - for (int i = 0; i < ba.size(); i++) - QCOMPARE((uchar)ba.at(i), (uchar)i); - } - -} - void tst_QSettings::bom() { QSettings s(":/bom.ini", QSettings::IniFormat); @@ -744,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() @@ -757,11 +786,11 @@ void tst_QSettings::embeddedZeroByte() QSettings settings("QtProject", "tst_qsettings"); QVariant outValue = settings.value(QTest::currentDataTag()); - switch (value.type()) { - case QVariant::ByteArray: + switch (value.typeId()) { + case QMetaType::QByteArray: QCOMPARE(outValue.toByteArray(), value.toByteArray()); break; - case QVariant::String: + case QMetaType::QString: QCOMPARE(outValue.toString(), value.toString()); break; default: @@ -801,6 +830,20 @@ void tst_QSettings::spaceAfterComment() settings.endGroup(); } +// test if a qvariant-encoded float can be read +void tst_QSettings::floatAsQVariant() +{ + QVERIFY(QFile::exists(":/float.ini")); + QSettings s(":/float.ini", QSettings::IniFormat); + + s.beginGroup("test"); + QCOMPARE(s.value("float").toDouble(), 0.5); + QCOMPARE(s.value("float_qvariant").toDouble(), 0.5); + + QCOMPARE(s.value("float").toFloat(), 0.5); + QCOMPARE(s.value("float_qvariant").toFloat(), 0.5); +} + void tst_QSettings::testErrorHandling_data() { QTest::addColumn<int>("filePerms"); // -1 means file should not exist @@ -965,11 +1008,12 @@ void tst_QSettings::testIniParsing() if ( settings.status() == QSettings::NoError ) { // else no point proceeding QVariant v = settings.value(key); - QVERIFY(v.canConvert(expect.type())); + if (expect.isValid()) + QVERIFY(v.canConvert(expect.metaType())); // check some types so as to give prettier error messages - if ( v.type() == QVariant::String ) { + if ( v.typeId() == QMetaType::QString ) { QCOMPARE(v.toString(), expect.toString()); - } else if ( v.type() == QVariant::Int ) { + } else if ( v.typeId() == QMetaType::Int ) { QCOMPARE(v.toInt(), expect.toInt()); } else { QCOMPARE(v, expect); @@ -1125,6 +1169,14 @@ void tst_QSettings::setValue() settings.setValue("key 2", QString("false")); QCOMPARE(settings.value("key 2", true).toBool(), false); + settings.setValue("key 2", double(1234.56)); + QCOMPARE(settings.value("key 2").toDouble(), double(1234.56)); + QCOMPARE(settings.value("key 2").toString().left(7), QString::number(double(1234.56))); + + settings.setValue("key 2", float(1234.56)); + QCOMPARE(settings.value("key 2").toFloat(), float(1234.56)); + QCOMPARE(settings.value("key 2").toString().left(7), QString::number(float(1234.56))); + // The following block should not compile. /* settings.setValue("key 2", "true"); @@ -1151,7 +1203,7 @@ void tst_QSettings::setValue() QCOMPARE(settings.value("key 2").toStringList(), QStringList() << "" << "a" << "" << "bc" << ""); settings.setValue("key 3", QList<QVariant>()); - QCOMPARE(settings.value("key 3").toList(), QList<QVariant>()); + QVERIFY(settings.value("key 3").toList().isEmpty()); settings.setValue("key 3", QList<QVariant>() << 1 << QString("a")); QCOMPARE(settings.value("key 3").toList(), QList<QVariant>() << 1 << QString("a")); @@ -1185,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); @@ -1204,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); } @@ -1244,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); \ } @@ -1279,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); + testValue("customMap", m2, QVariantMap); - QStringList l2; + QStringList l2 { "ene", "due", "@Point(1 2)", "@fake" }; + testValue("stringsAt", l2, QStringList); - l2 << "ene" << "due" << "@Point(1 2)" << "@fake"; - testVal("key3", l2, QStringList, StringList); + l2 = { "ene", "due", "rike", "fake" }; + testValue("strings", l2, QStringList); - l2.clear(); - l2 << "ene" << "due" << "rike" << "fake"; - testVal("key3", l2, QStringList, StringList); - - 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()); - - 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)); + 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.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 @@ -1748,14 +1796,9 @@ void tst_QSettings::sync() // Now "some other app" will change other.software.org.ini QString userConfDir = settingsPath("__user__") + QDir::separator(); -#if !defined(Q_OS_WINRT) - 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()); -#else - QFile::remove(userConfDir + "other.software.org.ini"); - QFile::rename(userConfDir + "software.org.ini" , userConfDir + "other.software.org.ini"); -#endif settings2.sync(); @@ -1773,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(), @@ -1796,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() @@ -1871,11 +1914,6 @@ void tst_QSettings::syncAlternateDataStream() } #endif -void tst_QSettings::setFallbacksEnabled_data() -{ - populateWithFormats(); -} - void tst_QSettings::setFallbacksEnabled() { QFETCH(QSettings::Format, format); @@ -1960,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); @@ -2025,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() @@ -2070,7 +2121,7 @@ int numThreadSafetyFailures; class SettingsThread : public QThread { public: - void run(); + void run() override; void start(int n) { param = n; QThread::start(); } private: @@ -2084,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; } } @@ -2092,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; @@ -2099,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(); @@ -2153,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 @@ -2192,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); @@ -2245,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() @@ -2289,7 +2361,7 @@ void tst_QSettings::testRegistryShortRootNames() void tst_QSettings::testRegistry32And64Bit() { -#if !defined (Q_OS_WIN) || defined(Q_OS_WINRT) +#if !defined (Q_OS_WIN) QSKIP("This test is specific to the Windows registry.", SkipAll); #else @@ -2335,14 +2407,15 @@ void tst_QSettings::testRegistry32And64Bit() void tst_QSettings::trailingWhitespace() { + const QString path = settingsPath("trailingWhitespace"); { - QSettings s("tst_QSettings_trailingWhitespace"); + QSettings s(path, QSettings::IniFormat); s.setValue("trailingSpace", "x "); s.setValue("trailingTab", "x\t"); s.setValue("trailingNewline", "x\n"); } { - QSettings s("tst_QSettings_trailingWhitespace"); + QSettings s(path, QSettings::IniFormat); QCOMPARE(s.value("trailingSpace").toString(), QLatin1String("x ")); QCOMPARE(s.value("trailingTab").toString(), QLatin1String("x\t")); QCOMPARE(s.value("trailingNewline").toString(), QLatin1String("x\n")); @@ -2350,11 +2423,6 @@ void tst_QSettings::trailingWhitespace() } } -void tst_QSettings::fromFile_data() -{ - populateWithFormats(); -} - void tst_QSettings::fromFile() { QFETCH(QSettings::Format, format); @@ -2369,13 +2437,19 @@ void tst_QSettings::fromFile() QString path = "foo"; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) if (format == QSettings::NativeFormat) path = "\\HKEY_CURRENT_USER\\Software\\foo"; #endif 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()); @@ -2411,75 +2485,8 @@ void tst_QSettings::fromFile() QCOMPARE(settings1.value("gamma/foo.bar").toInt(), 4); QCOMPARE(settings1.allKeys().size(), 3); } - - QDir::setCurrent(oldCur); } -#ifdef QT_BUILD_INTERNAL -void tst_QSettings::setIniCodec() -{ - QByteArray expeContents4, expeContents5; - QByteArray actualContents4, actualContents5; - - { - QFile inFile(":/resourcefile4.ini"); - inFile.open(QIODevice::ReadOnly); - expeContents4 = inFile.readAll(); - inFile.close(); - } - - { - QFile inFile(":/resourcefile5.ini"); - inFile.open(QIODevice::ReadOnly); - expeContents5 = inFile.readAll(); - inFile.close(); - } - - { - QSettings settings4(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP"); - settings4.setIniCodec("UTF-8"); - settings4.setValue(QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC"), QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC")); - settings4.sync(); - - QSettings settings5(QSettings::IniFormat, QSettings::UserScope, "other.software.org", "KillerAPP"); - settings5.setIniCodec("ISO 8859-1"); - settings5.setValue(QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC"), QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC")); - settings5.sync(); - - { - QFile inFile(settings4.fileName()); - inFile.open(QIODevice::ReadOnly | QIODevice::Text); - actualContents4 = inFile.readAll(); - inFile.close(); - } - - { - QFile inFile(settings5.fileName()); - inFile.open(QIODevice::ReadOnly | QIODevice::Text); - actualContents5 = inFile.readAll(); - inFile.close(); - } - } - - QConfFile::clearCache(); - - QCOMPARE(actualContents4, expeContents4); - QCOMPARE(actualContents5, expeContents5); - - QSettings settings4(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP"); - settings4.setIniCodec("UTF-8"); - QSettings settings5(QSettings::IniFormat, QSettings::UserScope, "other.software.org", "KillerAPP"); - settings5.setIniCodec("Latin-1"); - - QCOMPARE(settings4.allKeys().count(), 1); - QCOMPARE(settings5.allKeys().count(), 1); - - QCOMPARE(settings4.allKeys().first(), settings5.allKeys().first()); - QCOMPARE(settings4.value(settings4.allKeys().first()).toString(), - settings5.value(settings5.allKeys().first()).toString()); -} -#endif - static bool containsSubList(QStringList mom, QStringList son) { for (int i = 0; i < son.size(); ++i) { @@ -2489,11 +2496,6 @@ static bool containsSubList(QStringList mom, QStringList son) return true; } -void tst_QSettings::testArrays_data() -{ - populateWithFormats(); -} - /* Tests beginReadArray(), beginWriteArray(), endArray(), and setArrayIndex(). @@ -2559,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(); @@ -2619,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(); @@ -2774,14 +2776,14 @@ 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; } static QByteArray iniEscapedStringList(const QStringList &strList) { QByteArray result; - QSettingsPrivate::iniEscapedStringList(strList, result, 0); + QSettingsPrivate::iniEscapedStringList(strList, result); return result; } @@ -2789,23 +2791,9 @@ static QStringList iniUnescapedStringList(const QByteArray &ba) { QStringList result; QString str; -#if QSETTINGS_P_H_VERSION >= 2 - bool isStringList = QSettingsPrivate::iniUnescapedStringList(ba, 0, ba.size(), str, result -#if QSETTINGS_P_H_VERSION >= 3 - , 0 -#endif - ); + bool isStringList = QSettingsPrivate::iniUnescapedStringList(ba, str, result); if (!isStringList) result = QStringList(str); -#else - QStringList *strList = QSettingsPrivate::iniUnescapedStringList(ba, 0, ba.size(), str); - if (strList) { - result = *strList; - delete strList; - } else { - result = QStringList(str); - } -#endif return result; } #endif @@ -2815,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')) { @@ -2904,8 +2892,8 @@ void tst_QSettings::testEscapes() testEscapedStringList(QChar(0) + QString("0"), "\\0\\x30"); testEscapedStringList("~!@#$%^&*()_+.-/\\=", "\"~!@#$%^&*()_+.-/\\\\=\""); testEscapedStringList("~!@#$%^&*()_+.-/\\", "~!@#$%^&*()_+.-/\\\\"); - testEscapedStringList(QString("\x7F") + "12aFz", "\\x7f\\x31\\x32\\x61\\x46z"); - testEscapedStringList(QString(" \t\n\\n") + QChar(0x123) + QChar(0x4567), "\" \\t\\n\\\\n\\x123\\x4567\""); + testEscapedStringList(QString("\x7F") + "12aFz", QByteArray("\x7f") + "12aFz"); + testEscapedStringList(QString(" \t\n\\n") + QChar(0x123) + QChar(0x4567), "\" \\t\\n\\\\n\xC4\xA3\xE4\x95\xA7\""); testEscapedStringList(QString("\a\b\f\n\r\t\v'\"?\001\002\x03\x04"), "\\a\\b\\f\\n\\r\\t\\v'\\\"?\\x1\\x2\\x3\\x4"); testEscapedStringList(QStringList() << "," << ";" << "a" << "ab, \tc, d ", "\",\", \";\", a, \"ab, \\tc, d \""); @@ -2920,7 +2908,7 @@ void tst_QSettings::testEscapes() QString() + QChar(0) + QChar(0) + QChar(0) + QChar(0) + QChar(1) + QChar(0111) + QChar(011111) + QChar(0) + QChar(0xCDEF) + "GH" + QChar(0x3456), - "\\0\\0\\0\\0\\x1I\\x1249\\0\\xcdefGH\\x3456"); + "\\0\\0\\0\\0\\x1I\xE1\x89\x89\\0\xEC\xB7\xAFGH\xE3\x91\x96"); testUnescapedStringList(QByteArray("\\c\\d\\e\\f\\g\\$\\*\\\0", 16), "\f", "\\f"); testUnescapedStringList("\"a\", \t\"bc \", \" d\" , \"ef \" ,,g, hi i,,, ,", QStringList() << "a" << "bc " << " d" << "ef " << "" << "g" << "hi i" @@ -2935,8 +2923,6 @@ void tst_QSettings::testEscapes() testVariant(QString("Hello, World!"), QString("Hello, World!"), toString); testVariant(QString("@Hello World!"), QString("@@Hello World!"), toString); testVariant(QString("@@Hello World!"), QString("@@@Hello World!"), toString); - testVariant(QByteArray("Hello World!"), QString("@ByteArray(Hello World!)"), toString); - testVariant(QByteArray("@Hello World!"), QString("@ByteArray(@Hello World!)"), toString); testVariant(QVariant(100), QString("100"), toString); testVariant(QStringList() << "ene" << "due" << "rike", QString::fromLatin1("@Variant(\x0\x0\x0\xb\x0\x0\x0\x3\x0\x0\x0\x6\x0\x65\x0n\x0\x65\x0\x0\x0\x6\x0\x64\x0u\x0\x65\x0\x0\x0\x8\x0r\x0i\x0k\x0\x65)", 50), toStringList); testVariant(QRect(1, 2, 3, 4), QString("@Rect(1 2 3 4)"), toRect); @@ -2957,11 +2943,6 @@ void tst_QSettings::testEscapes() } #endif -void tst_QSettings::testCaseSensitivity_data() -{ - populateWithFormats(); -} - void tst_QSettings::testCaseSensitivity() { QFETCH(QSettings::Format, format); @@ -3041,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() { @@ -3111,11 +3092,6 @@ void tst_QSettings::fileName() } #endif -void tst_QSettings::isWritable_data() -{ - populateWithFormats(); -} - void tst_QSettings::isWritable() { QFETCH(QSettings::Format, format); @@ -3145,7 +3121,7 @@ void tst_QSettings::isWritable() QSettings s3(format, QSettings::SystemScope, "foo.org", "Something Different"); if (s1.status() == QSettings::NoError && s1.contains("foo")) { -#if defined(Q_OS_MACX) +#if defined(Q_OS_MACOS) QVERIFY(s1.isWritable()); if (format == QSettings::NativeFormat) { QVERIFY(!s2.isWritable()); @@ -3168,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); @@ -3244,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); @@ -3318,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); @@ -3475,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 @@ -3584,19 +3539,20 @@ void tst_QSettings::dontReorderIniKeysNeedlessly() } #endif -void tst_QSettings::rainersSyncBugOnMac_data() -{ - ctor_data(); -} - void tst_QSettings::rainersSyncBugOnMac() { QFETCH(QSettings::Format, format); -#if defined(Q_OS_DARWIN) || defined(Q_OS_WINRT) +#if defined(Q_OS_DARWIN) 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; @@ -3620,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); @@ -3628,7 +3584,7 @@ void tst_QSettings::recursionBug() } } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) static DWORD readKeyType(HKEY handle, QStringView rSubKey) { @@ -3667,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(); @@ -3739,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" diff --git a/tests/auto/corelib/io/qsettings/utf8settings.ini b/tests/auto/corelib/io/qsettings/utf8settings.ini new file mode 100644 index 0000000000..bac010254f --- /dev/null +++ b/tests/auto/corelib/io/qsettings/utf8settings.ini @@ -0,0 +1,11 @@ +[General] +.%2C%27%25Uабвг%22%09=".,'%!@#$" +♟=♘♚ +🌍=🌐 + +[Test] +BAR=BAR +BÄR=BÄR +OST=OST +ÖSE=ÖSE +Это\тест=Это тест |