1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 
43 #include <qdebug.h>
44 #include <QtTest/QtTest>
45 
46 #include <QtCore/QSettings>
47 #include <private/qsettings_p.h>
48 //#include <QtGui/QApplication>
49 #include <QtCore/QCoreApplication>
50 #include <QtCore/QtGlobal>
51 #include <QtCore/QMetaType>
52 #include <QtCore/QtDebug>
53 #include <QtCore/QString>
54 #include "../../shared/util.h"
55 
56 #if !defined(Q_OS_SYMBIAN)
57 # include <cctype>
58 #endif
59 #if defined(Q_OS_WIN) && defined(Q_CC_GNU)
60 // need for unlink on mingw
61 #include <io.h>
62 #endif
63 
64 #if defined(Q_OS_WIN)
65 #include <QtCore/qt_windows.h>
66 #endif
67 
68 #ifndef QSETTINGS_P_H_VERSION
69 #define QSETTINGS_P_H_VERSION 1
70 #endif
71 
72 //TESTED_FILES=
73 
74 QT_FORWARD_DECLARE_CLASS(QSettings)
75 QT_FORWARD_DECLARE_CLASS(QSettings)
76 
77 class tst_QSettings : public QObject
78 {
79     Q_OBJECT
80 
81 public:
82     tst_QSettings();
83 
84 public slots:
85     void init();
86     void cleanup();
87 private slots:
88     void getSetCheck();
89     void ctor_data();
90     void ctor();
91     void beginGroup();
92     void setValue();
93     void remove();
94     void contains();
95     void sync();
96     void setFallbacksEnabled();
97     void setFallbacksEnabled_data();
98     void fromFile_data();
99     void fromFile();
100     void setIniCodec();
101     void testArrays_data();
102     void testArrays();
103     void testEscapes();
104     void testCompatFunctions();
105     void testCaseSensitivity_data();
106     void testCaseSensitivity();
107     void testErrorHandling_data();
108     void testErrorHandling();
109     void testIniParsing_data();
110     void testIniParsing();
111     void testChildKeysAndGroups_data();
112     void testChildKeysAndGroups();
113     void testUpdateRequestEvent();
114     void testThreadSafety();
115     void testNormalizedKey_data();
116     void testNormalizedKey();
117     void testEmptyData();
118     void testResourceFiles();
119     void fileName();
120     void isWritable_data();
121     void isWritable();
122     void childGroups_data();
123     void childGroups();
124     void childKeys_data();
125     void childKeys();
126     void allKeys_data();
127     void allKeys();
128     void registerFormat();
129     void setPath();
130     void setDefaultFormat();
131     void dontCreateNeedlessPaths();
132 #if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
133     void dontReorderIniKeysNeedlessly();
134 #endif
135 #if defined(Q_OS_WIN)
136     void qtbug_13249();
137 #endif
138 
139     /*
140         These tests were developed for the Qt 3 QSettings class.
141     */
142 #ifdef QT3_SUPPORT
143     void oldWriteEntryIni_data();
144     void oldWriteEntryIni();
145     void oldReadEntryIni_data();
146     void oldReadEntryIni();
147     void oldBeginGroup_data();
148     void oldBeginGroup();
149     void oldEndGroup_data();
150     void oldEndGroup();
151     void oldResetGroup_data();
152     void oldResetGroup();
153     void oldEntryList_data();
154     void oldEntryList();
155     void oldWriteEntry_QString_bool_data();
156     void oldWriteEntry_QString_bool();
157     void oldWriteEntry_QString_double_data();
158     void oldWriteEntry_QString_double();
159     void oldWriteEntry_QString_int_data();
160     void oldWriteEntry_QString_int();
161     void oldWriteEntry_QString_QString_data();
162     void oldWriteEntry_QString_QString();
163     void oldWriteEntry_QString_QStringList_data();
164     void oldWriteEntry_QString_QStringList();
165     void oldWriteEntry_QString_QStringList_QChar_data();
166     void oldWriteEntry_QString_QStringList_QChar();
167     void oldReadListEntry_QString();
168     void oldReadListEntry_QString_QChar();
169     void oldReadEntry();
170     void oldReadNumEntry();
171     void oldReadDoubleEntry();
172     void oldReadBoolEntry();
173     void oldGlobalVersusLocal();
174     void oldRemoveEntry();
175 #endif
176 
177     void testVariantTypes_data();
178     void testVariantTypes();
179     void rainersSyncBugOnMac_data();
180     void rainersSyncBugOnMac();
181     void recursionBug();
182 #ifdef QT3_SUPPORT
183     void setPathBug();
184 #endif
185 
186     void testByteArray_data();
187     void testByteArray();
188     void iniCodec();
189 
190 private:
191     void oldWriteEntry_data();
192     void oldReadEntry_data();
193     void oldWriteEntryHelper(QSettings &settings);
194     void oldReadEntryHelper(QSettings &settings);
195 };
196 
197 // Testing get/set functions
getSetCheck()198 void tst_QSettings::getSetCheck()
199 {
200     QSettings obj1;
201     // bool QSettings::fallbacksEnabled()
202     // void QSettings::setFallbacksEnabled(bool)
203     obj1.setFallbacksEnabled(false);
204     QCOMPARE(false, obj1.fallbacksEnabled());
205     obj1.setFallbacksEnabled(true);
206     QCOMPARE(true, obj1.fallbacksEnabled());
207 }
208 
209 //using namespace std;
210 
211 //#include <qapplication.h>
212 #include <qcoreapplication.h>
213 #include <qdir.h>
214 #include <qregexp.h>
215 #include <qthread.h>
216 #include <stdlib.h>
217 #ifndef Q_OS_WIN
218 #include <unistd.h>
219 #endif
220 
Q_DECLARE_METATYPE(QSettings::Format)221 Q_DECLARE_METATYPE(QSettings::Format)
222 
223 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
224 static void removePath(const QString& _path)
225 {
226     QString path = _path;
227     QDir dir(path);
228     if (!dir.exists())
229         return;
230     QStringList entries = dir.entryList();
231     foreach(QString name, entries) {
232         QString absolute = path + name;
233         if (QFileInfo(absolute).isDir())
234             removePath(absolute+"\\");
235         else
236             QFile::remove(absolute);
237     }
238     dir.cdUp();
239     if (path[path.size()-1] == '\\')
240         path = path.left(path.size()-1);
241     dir.rmdir(path.mid(path.lastIndexOf('\\')+1));
242 }
243 #endif
244 
settingsPath(const char * path="")245 static QString settingsPath(const char *path = "")
246 {
247     // Temporary path for files that are specified explictly in the constructor.
248     QString tempPath = QDir::tempPath();
249     if (tempPath.endsWith("/"))
250 	tempPath.truncate(tempPath.size() - 1);
251     return QDir::toNativeSeparators(tempPath + "/tst_QSettings/" + QLatin1String(path));
252 }
253 
readCustom1File(QIODevice & device,QSettings::SettingsMap & map)254 static bool readCustom1File(QIODevice &device, QSettings::SettingsMap &map)
255 {
256     QDataStream in(&device);
257     quint32 magic;
258     in >> magic;
259     in >> map;
260     return (magic == 0x01010101 && in.status() == QDataStream::Ok);
261 }
262 
writeCustom1File(QIODevice & device,const QSettings::SettingsMap & map)263 static bool writeCustom1File(QIODevice &device, const QSettings::SettingsMap &map)
264 {
265     QDataStream out(&device);
266     out << quint32(0x01010101);
267     out << map;
268     return out.status() == QDataStream::Ok;
269 }
270 
readCustom2File(QIODevice & device,QSettings::SettingsMap & map)271 static bool readCustom2File(QIODevice &device, QSettings::SettingsMap &map)
272 {
273     QDataStream in(&device);
274     quint64 magic;
275     in >> magic;
276     in >> map;
277     return (magic == Q_UINT64_C(0x0202020202020202) && in.status() == QDataStream::Ok);
278 }
279 
writeCustom2File(QIODevice & device,const QSettings::SettingsMap & map)280 static bool writeCustom2File(QIODevice &device, const QSettings::SettingsMap &map)
281 {
282     QDataStream out(&device);
283     out << Q_UINT64_C(0x0202020202020202);
284     out << map;
285     return out.status() == QDataStream::Ok;
286 }
287 
readCustom3File(QIODevice & device,QSettings::SettingsMap & map)288 static bool readCustom3File(QIODevice &device, QSettings::SettingsMap &map)
289 {
290     QTextStream in(&device);
291     QString tag;
292     in >> tag;
293     if (tag == "OK") {
294         map.insert("retval", "OK");
295         return true;
296     } else {
297         return false;
298     }
299 }
300 
writeCustom3File(QIODevice & device,const QSettings::SettingsMap & map)301 static bool writeCustom3File(QIODevice &device, const QSettings::SettingsMap &map)
302 {
303     QTextStream out(&device);
304     if (map.value("retval") != "OK")
305         return false;
306 
307     out << "OK";
308     return true;
309 }
310 
populateWithFormats()311 static void populateWithFormats()
312 {
313     QTest::addColumn<QSettings::Format>("format");
314 
315     QTest::newRow("native") << QSettings::NativeFormat;
316     QTest::newRow("ini") << QSettings::IniFormat;
317     QTest::newRow("custom1") << QSettings::CustomFormat1;
318     QTest::newRow("custom2") << QSettings::CustomFormat2;
319 }
320 
tst_QSettings()321 tst_QSettings::tst_QSettings()
322 {
323     QSettings::Format custom1 = QSettings::registerFormat("custom1", readCustom1File, writeCustom1File);
324     QSettings::Format custom2 = QSettings::registerFormat("custom2", readCustom2File, writeCustom2File
325 #ifndef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
326                                                           , Qt::CaseInsensitive
327 #endif
328                                                           );
329     QVERIFY(custom1 == QSettings::CustomFormat1);
330     QVERIFY(custom2 == QSettings::CustomFormat2);
331 }
332 
init()333 void tst_QSettings::init()
334 {
335     QSettings::setSystemIniPath(settingsPath("__system__"));
336     QSettings::setUserIniPath(settingsPath("__user__"));
337 
338 #if defined(Q_OS_WIN)
339     QSettings("HKEY_CURRENT_USER\\Software\\software.org", QSettings::NativeFormat).clear();
340     QSettings("HKEY_LOCAL_MACHINE\\Software\\software.org", QSettings::NativeFormat).clear();
341     QSettings("HKEY_CURRENT_USER\\Software\\other.software.org", QSettings::NativeFormat).clear();
342     QSettings("HKEY_LOCAL_MACHINE\\Software\\other.software.org", QSettings::NativeFormat).clear();
343     QSettings("HKEY_CURRENT_USER\\Software\\foo", QSettings::NativeFormat).clear();
344     QSettings("HKEY_CURRENT_USER\\Software\\bar", QSettings::NativeFormat).clear();
345     QSettings("HKEY_CURRENT_USER\\Software\\bat", QSettings::NativeFormat).clear();
346     QSettings("HKEY_CURRENT_USER\\Software\\baz", QSettings::NativeFormat).clear();
347     QSettings("HKEY_LOCAL_MACHINE\\Software\\foo", QSettings::NativeFormat).clear();
348     QSettings("HKEY_LOCAL_MACHINE\\Software\\bar", QSettings::NativeFormat).clear();
349     QSettings("HKEY_LOCAL_MACHINE\\Software\\bat", QSettings::NativeFormat).clear();
350     QSettings("HKEY_LOCAL_MACHINE\\Software\\baz", QSettings::NativeFormat).clear();
351     if (QDir(settingsPath()).exists()) {
352 #if defined(Q_OS_WINCE)
353         removePath(settingsPath());
354 #else
355         if (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based)
356 	    system(QString("rmdir /Q /S %1").arg(settingsPath()).toLatin1());
357 	else
358 	    system(QString("deltree /Y %1").arg(settingsPath()).toLatin1());
359 #endif
360     }
361 #elif defined(Q_OS_DARWIN)
362     QSettings(QSettings::UserScope, "software.org", "KillerAPP").clear();
363     QSettings(QSettings::SystemScope, "software.org", "KillerAPP").clear();
364     QSettings(QSettings::UserScope, "other.software.org", "KillerAPP").clear();
365     QSettings(QSettings::SystemScope, "other.software.org", "KillerAPP").clear();
366     QSettings(QSettings::UserScope, "software.org").clear();
367     QSettings(QSettings::SystemScope, "software.org").clear();
368     QSettings(QSettings::UserScope, "other.software.org").clear();
369     QSettings(QSettings::SystemScope, "other.software.org").clear();
370 #elif defined(Q_OS_SYMBIAN)
371     removePath(settingsPath());
372 #endif
373 
374 #if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
375     system(QString("chmod -R u+rw %1 2> /dev/null").arg(settingsPath()).toLatin1());
376     system(QString("rm -fr %1 2> /dev/null").arg(settingsPath()).toLatin1());
377 #endif
378 
379     QFile::remove("foo");
380 }
381 
cleanup()382 void tst_QSettings::cleanup()
383 {
384     init();
385 }
386 
387 /*
388     Test the constructors and the assignment operator.
389 */
390 
ctor_data()391 void tst_QSettings::ctor_data()
392 {
393     populateWithFormats();
394 }
395 
ctor()396 void tst_QSettings::ctor()
397 {
398     QFETCH(QSettings::Format, format);
399 
400     {
401         QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP");
402         QSettings settings2(format, QSettings::UserScope, "software.org");
403         QSettings settings3(format, QSettings::SystemScope, "software.org", "KillerAPP");
404         QSettings settings4(format, QSettings::SystemScope, "software.org");
405 
406         QSettings settings5(format, QSettings::UserScope, "software.org", "KillerAPP");
407         QSettings settings6(format, QSettings::UserScope, "software.org");
408         QSettings settings7(format, QSettings::SystemScope, "software.org", "KillerAPP");
409         QSettings settings8(format, QSettings::SystemScope, "software.org");
410 
411         // test QSettings::format() while we're at it
412         QVERIFY(settings1.format() == format);
413         QVERIFY(settings2.format() == format);
414         QVERIFY(settings3.format() == format);
415         QVERIFY(settings4.format() == format);
416 
417         // test QSettings::scope() while we're at it
418         QVERIFY(settings1.scope() == QSettings::UserScope);
419         QVERIFY(settings2.scope() == QSettings::UserScope);
420         QVERIFY(settings3.scope() == QSettings::SystemScope);
421         QVERIFY(settings4.scope() == QSettings::SystemScope);
422 
423         // test QSettings::organizationName() while we're at it
424         QVERIFY(settings1.organizationName() == "software.org");
425         QVERIFY(settings2.organizationName() == "software.org");
426         QVERIFY(settings3.organizationName() == "software.org");
427         QVERIFY(settings4.organizationName() == "software.org");
428 
429         // test QSettings::applicationName() while we're at it
430         QCOMPARE(settings1.applicationName(), QString("KillerAPP"));
431         QVERIFY(settings2.applicationName().isEmpty());
432         QVERIFY(settings3.applicationName() == "KillerAPP");
433         QVERIFY(settings4.applicationName().isEmpty());
434 
435 #if !defined(Q_OS_BLACKBERRY)
436         /*
437             Go forwards.
438         */
439         settings4.setValue("key 1", QString("doodah"));
440         QCOMPARE(settings1.value("key 1").toString(), QString("doodah"));
441         QCOMPARE(settings2.value("key 1").toString(), QString("doodah"));
442         QCOMPARE(settings3.value("key 1").toString(), QString("doodah"));
443         QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
444 
445         settings3.setValue("key 1", QString("blah"));
446         QCOMPARE(settings1.value("key 1").toString(), QString("blah"));
447         QCOMPARE(settings2.value("key 1").toString(), QString("doodah"));
448         QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
449         QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
450 
451         settings2.setValue("key 1", QString("whoa"));
452         QCOMPARE(settings1.value("key 1").toString(), QString("whoa"));
453         QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
454         QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
455         QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
456 
457         settings1.setValue("key 1", QString("gurgle"));
458         QCOMPARE(settings1.value("key 1").toString(), QString("gurgle"));
459         QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
460         QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
461         QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
462 
463         /*
464             Test the copies.
465         */
466         QCOMPARE(settings5.value("key 1").toString(), settings1.value("key 1").toString());
467         QCOMPARE(settings6.value("key 1").toString(), settings2.value("key 1").toString());
468         QCOMPARE(settings7.value("key 1").toString(), settings3.value("key 1").toString());
469         QCOMPARE(settings8.value("key 1").toString(), settings4.value("key 1").toString());
470 
471         /*
472             Go backwards.
473         */
474 
475         settings2.setValue("key 1", QString("bilboh"));
476         QCOMPARE(settings1.value("key 1").toString(), QString("gurgle"));
477         QCOMPARE(settings2.value("key 1").toString(), QString("bilboh"));
478         QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
479         QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
480 
481         settings3.setValue("key 1", QString("catha"));
482         QCOMPARE(settings1.value("key 1").toString(), QString("gurgle"));
483         QCOMPARE(settings2.value("key 1").toString(), QString("bilboh"));
484         QCOMPARE(settings3.value("key 1").toString(), QString("catha"));
485         QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
486 
487         settings4.setValue("key 1", QString("quirko"));
488         QCOMPARE(settings1.value("key 1").toString(), QString("gurgle"));
489         QCOMPARE(settings2.value("key 1").toString(), QString("bilboh"));
490         QCOMPARE(settings3.value("key 1").toString(), QString("catha"));
491         QCOMPARE(settings4.value("key 1").toString(), QString("quirko"));
492 #else
493         /*
494             No fallback mechanism and a single scope on Blackberry OS
495         */
496         settings2.setValue("key 1", QString("whoa"));
497         QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
498         QCOMPARE(settings4.value("key 1").toString(), QString("whoa"));
499         QVERIFY(!settings1.contains("key 1"));
500         QVERIFY(!settings3.contains("key 1"));
501 
502         settings1.setValue("key 1", QString("blah"));
503         QCOMPARE(settings1.value("key 1").toString(), QString("blah"));
504         QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
505         QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
506         QCOMPARE(settings4.value("key 1").toString(), QString("whoa"));
507 #endif
508 
509         /*
510             Test the copies again.
511         */
512         QCOMPARE(settings5.value("key 1").toString(), settings1.value("key 1").toString());
513         QCOMPARE(settings6.value("key 1").toString(), settings2.value("key 1").toString());
514         QCOMPARE(settings7.value("key 1").toString(), settings3.value("key 1").toString());
515         QCOMPARE(settings8.value("key 1").toString(), settings4.value("key 1").toString());
516 
517         /*
518             "General" is a problem key for .ini files.
519         */
520         settings1.setValue("General", 1);
521         settings1.setValue("%General", 2);
522         settings1.setValue("alpha", 3);
523         settings1.setValue("General/alpha", 4);
524         settings1.setValue("%General/alpha", 5);
525         settings1.setValue("alpha/General", 6);
526         settings1.setValue("alpha/%General", 7);
527         settings1.setValue("General/General", 8);
528         settings1.setValue("General/%General", 9);
529         settings1.setValue("%General/General", 10);
530         settings1.setValue("%General/%General", 11);
531     }
532 
533     {
534         /*
535             Test that the data was stored on disk after all instances
536             of QSettings are destroyed.
537         */
538 
539         QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP");
540         QSettings settings2(format, QSettings::UserScope, "software.org");
541         QSettings settings3(format, QSettings::SystemScope, "software.org", "KillerAPP");
542         QSettings settings4(format, QSettings::SystemScope, "software.org");
543 
544 #if !defined(Q_OS_BLACKBERRY)
545         QCOMPARE(settings1.value("key 1").toString(), QString("gurgle"));
546         QCOMPARE(settings2.value("key 1").toString(), QString("bilboh"));
547         QCOMPARE(settings3.value("key 1").toString(), QString("catha"));
548         QCOMPARE(settings4.value("key 1").toString(), QString("quirko"));
549 #else
550         QCOMPARE(settings1.value("key 1").toString(), QString("blah"));
551         QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
552         QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
553         QCOMPARE(settings4.value("key 1").toString(), QString("whoa"));
554 #endif
555 
556         /*
557             Test problem keys.
558         */
559 
560         QCOMPARE(settings1.value("General").toInt(), 1);
561         QCOMPARE(settings1.value("%General").toInt(), 2);
562         QCOMPARE(settings1.value("alpha").toInt(), 3);
563         QCOMPARE(settings1.value("General/alpha").toInt(), 4);
564         QCOMPARE(settings1.value("%General/alpha").toInt(), 5);
565         QCOMPARE(settings1.value("alpha/General").toInt(), 6);
566         QCOMPARE(settings1.value("alpha/%General").toInt(), 7);
567         QCOMPARE(settings1.value("General/General").toInt(), 8);
568         QCOMPARE(settings1.value("General/%General").toInt(), 9);
569         QCOMPARE(settings1.value("%General/General").toInt(), 10);
570         QCOMPARE(settings1.value("%General/%General").toInt(), 11);
571 
572         /*
573             Test that the organization and product parameters is
574             case-insensitive on Windows and Mac, case-sensitive on
575             Unix.
576         */
577         QSettings settings5(format, QSettings::UserScope, "SoftWare.ORG", "killerApp");
578         if (format == QSettings::NativeFormat) {
579 #if defined(Q_OS_WIN) || defined(Q_OS_DARWIN) || defined(Q_OS_SYMBIAN)
580             QCOMPARE(settings5.value("key 1").toString(), QString("gurgle"));
581 #else
582             QVERIFY(!settings5.contains("key 1"));
583 #endif
584         } else {
585 #if defined(Q_OS_WIN) || defined(Q_OS_DARWIN) || defined(Q_OS_SYMBIAN)
586             QCOMPARE(settings5.value("key 1").toString(), QString("gurgle"));
587 #else
588             QVERIFY(!settings5.contains("key 1"));
589 #endif
590         }
591     }
592 
593     {
594         QSettings settings1(settingsPath("custom/custom.conf"), QSettings::IniFormat);
595         settings1.beginGroup("alpha/beta");
596         settings1.setValue("geometry", -7);
597         settings1.setValue("geometry/x", 1);
598         settings1.setValue("geometry/y", 2);
599         QSettings settings2(settingsPath("custom/custom.conf"), QSettings::IniFormat);
600         settings1.setValue("geometry/width", 3);
601         settings2.setValue("alpha/beta/geometry/height", 4);
602         settings2.setValue("alpha/gamma/splitter", 5);
603         settings1.endGroup();
604 
605         // test QSettings::scope() while we're at it
606         QVERIFY(settings1.scope() == QSettings::UserScope);
607 
608         // test QSettings::organizationName() while we're at it
609         QVERIFY(settings1.organizationName().isEmpty());
610 
611         // test QSettings::applicationName() while we're at it
612         QVERIFY(settings1.organizationName().isEmpty());
613 
614         QSettings settings3(settingsPath("custom/custom2.conf"), QSettings::IniFormat);
615         settings3.beginGroup("doodley/beta");
616         settings3.setValue("geometry", -7);
617         settings3.setValue("geometry/x", 1);
618         settings3.setValue("geometry/y", 2);
619         settings3.setValue("geometry/width", 3);
620         settings3.setValue("geometry/height", 4);
621         settings3.endGroup();
622         settings3.setValue("alpha/gamma/splitter", 5);
623 
624         QCOMPARE(settings1.value("alpha/beta/geometry").toInt(), -7);
625         QCOMPARE(settings1.value("alpha/beta/geometry/x").toInt(), 1);
626         QCOMPARE(settings1.value("alpha/beta/geometry/y").toInt(), 2);
627         QCOMPARE(settings1.value("alpha/beta/geometry/width").toInt(), 3);
628         QCOMPARE(settings1.value("alpha/beta/geometry/height").toInt(), 4);
629         QCOMPARE(settings1.value("alpha/gamma/splitter").toInt(), 5);
630         QCOMPARE(settings1.allKeys().count(), 6);
631 
632         QCOMPARE(settings2.value("alpha/beta/geometry").toInt(), -7);
633         QCOMPARE(settings2.value("alpha/beta/geometry/x").toInt(), 1);
634         QCOMPARE(settings2.value("alpha/beta/geometry/y").toInt(), 2);
635         QCOMPARE(settings2.value("alpha/beta/geometry/width").toInt(), 3);
636         QCOMPARE(settings2.value("alpha/beta/geometry/height").toInt(), 4);
637         QCOMPARE(settings2.value("alpha/gamma/splitter").toInt(), 5);
638         QCOMPARE(settings2.allKeys().count(), 6);
639     }
640 
641     {
642         QSettings settings1(settingsPath("custom/custom.conf"), QSettings::IniFormat);
643         QCOMPARE(settings1.value("alpha/beta/geometry").toInt(), -7);
644         QCOMPARE(settings1.value("alpha/beta/geometry/x").toInt(), 1);
645         QCOMPARE(settings1.value("alpha/beta/geometry/y").toInt(), 2);
646         QCOMPARE(settings1.value("alpha/beta/geometry/width").toInt(), 3);
647         QCOMPARE(settings1.value("alpha/beta/geometry/height").toInt(), 4);
648         QCOMPARE(settings1.value("alpha/gamma/splitter").toInt(), 5);
649         QCOMPARE(settings1.allKeys().count(), 6);
650     }
651 
652     {
653         // QSettings's default constructor is native by default
654         if (format == QSettings::NativeFormat) {
655             QCoreApplication::instance()->setOrganizationName("");
656             QCoreApplication::instance()->setApplicationName("");
657             QSettings settings;
658             QCOMPARE(settings.status(), QSettings::AccessError);
659             QCoreApplication::instance()->setOrganizationName("software.org");
660             QCoreApplication::instance()->setApplicationName("KillerAPP");
661             QSettings settings2;
662             QCOMPARE(settings2.status(), QSettings::NoError);
663             QSettings settings3("software.org", "KillerAPP");
664             QCOMPARE(settings2.fileName(), settings3.fileName());
665             QCoreApplication::instance()->setOrganizationName("");
666             QCoreApplication::instance()->setApplicationName("");
667         }
668 
669         QSettings settings(format, QSettings::UserScope, "", "");
670         QCOMPARE(settings.status(), QSettings::AccessError);
671         QSettings settings2(format, QSettings::UserScope, "software.org", "KillerAPP");
672         QCOMPARE(settings2.status(), QSettings::NoError);
673 
674         // test QSettings::format() while we're at it
675         QVERIFY(settings.format() == format);
676         QVERIFY(settings2.format() == format);
677 
678         // test QSettings::scope() while we're at it
679         QVERIFY(settings.scope() == QSettings::UserScope);
680         QVERIFY(settings2.scope() == QSettings::UserScope);
681 
682         // test QSettings::organizationName() while we're at it
683         QVERIFY(settings.organizationName().isEmpty());
684         QVERIFY(settings2.organizationName() == "software.org");
685 
686         // test QSettings::applicationName() while we're at it
687         QVERIFY(settings.applicationName().isEmpty());
688         QVERIFY(settings2.applicationName() == "KillerAPP");
689     }
690 }
691 
testByteArray_data()692 void tst_QSettings::testByteArray_data()
693 {
694     QTest::addColumn<QByteArray>("data");
695 
696     QByteArray bytes("Hello world!");
697 
698     QTest::newRow("latin1") << bytes;
699 #ifndef QT_NO_COMPRESS
700     QTest::newRow("compressed") << qCompress(bytes);
701 #endif
702     QTest::newRow("with \\0") << bytes + '\0' + bytes;
703 }
704 
testByteArray()705 void tst_QSettings::testByteArray()
706 {
707     QFETCH(QByteArray, data);
708 
709     // write
710     {
711         QSettings settings("Trolltech", "tst_qsettings");
712         settings.setValue("byteArray", data);
713     }
714     // read
715     {
716         QSettings settings("Trolltech", "tst_qsettings");
717         QByteArray ret = settings.value("byteArray", data).toByteArray();
718         QCOMPARE(ret, data);
719     }
720 }
721 
iniCodec()722 void tst_QSettings::iniCodec()
723 {
724     {
725         QSettings settings("QtProject", "tst_qsettings");
726         settings.setIniCodec("cp1251");
727         QByteArray ba;
728         ba.resize(256);
729         for (int i = 0; i < ba.size(); i++)
730             ba[i] = i;
731         settings.setValue("array",ba);
732     }
733     {
734         QSettings settings("QtProject", "tst_qsettings");
735         settings.setIniCodec("cp1251");
736         QByteArray ba = settings.value("array").toByteArray();
737         QCOMPARE(ba.size(), 256);
738         for (int i = 0; i < ba.size(); i++)
739             QCOMPARE((uchar)ba.at(i), (uchar)i);
740     }
741 
742 }
743 
testErrorHandling_data()744 void tst_QSettings::testErrorHandling_data()
745 {
746     QTest::addColumn<int>("filePerms"); // -1 means file should not exist
747     QTest::addColumn<int>("dirPerms");
748     QTest::addColumn<int>("statusAfterCtor");
749     QTest::addColumn<bool>("shouldBeEmpty");
750     QTest::addColumn<int>("statusAfterGet");
751     QTest::addColumn<int>("statusAfterSetAndSync");
752 
753     //                         file    dir     afterCtor                      empty     afterGet                      afterSetAndSync
754     QTest::newRow("0600 0700") << 0600 << 0700 << (int)QSettings::NoError     << false << (int)QSettings::NoError     << (int)QSettings::NoError;
755 
756     QTest::newRow("0400 0700") << 0400 << 0700 << (int)QSettings::NoError
757         << false << (int)QSettings::NoError     << (int)QSettings::AccessError;
758     QTest::newRow("0200 0700") << 0200 << 0700 << (int)QSettings::AccessError
759         << true  << (int)QSettings::AccessError << (int)QSettings::AccessError;
760 
761     QTest::newRow("  -1 0700") <<   -1 << 0700 << (int)QSettings::NoError     << true  << (int)QSettings::NoError     << (int)QSettings::NoError;
762 
763     QTest::newRow("  -1 0000") <<   -1 << 0000 << (int)QSettings::NoError     << true  << (int)QSettings::NoError     << (int)QSettings::AccessError;
764     QTest::newRow("  -1 0100") <<   -1 << 0100 << (int)QSettings::NoError     << true  << (int)QSettings::NoError     << (int)QSettings::AccessError;
765     QTest::newRow("0600 0100") << 0600 << 0100 << (int)QSettings::NoError     << false << (int)QSettings::NoError     << (int)QSettings::NoError;
766     QTest::newRow("  -1 0300") <<   -1 << 0300 << (int)QSettings::NoError     << true  << (int)QSettings::NoError     << (int)QSettings::NoError;
767     QTest::newRow("0600 0300") << 0600 << 0300 << (int)QSettings::NoError     << false << (int)QSettings::NoError     << (int)QSettings::NoError;
768     QTest::newRow("  -1 0500") <<   -1 << 0500 << (int)QSettings::NoError     << true  << (int)QSettings::NoError     << (int)QSettings::AccessError;
769     QTest::newRow("0600 0500") << 0600 << 0500 << (int)QSettings::NoError     << false << (int)QSettings::NoError     << (int)QSettings::NoError;
770 }
771 
testErrorHandling()772 void tst_QSettings::testErrorHandling()
773 {
774 #ifdef QT_BUILD_INTERNAL
775 #ifdef Q_OS_WIN
776     QSKIP("Windows doesn't support most file modes, including read-only directories, so this test is moot.", SkipAll);
777 #elif defined(Q_OS_SYMBIAN)
778     QSKIP("Symbian/Open C doesn't support execute or write only file modes, or directory permissions, so this test is mostly moot.", SkipAll);
779 #elif defined(Q_OS_UNIX)
780     if (::getuid() == 0)
781         QSKIP("Running this test as root doesn't work, since file perms do not bother him", SkipAll);
782 #else
783     QFETCH(int, filePerms);
784     QFETCH(int, dirPerms);
785     QFETCH(int, statusAfterCtor);
786     QFETCH(bool, shouldBeEmpty);
787     QFETCH(int, statusAfterGet);
788     QFETCH(int, statusAfterSetAndSync);
789 
790     system(QString("chmod 700 %1 2>/dev/null").arg(settingsPath("someDir")).toLatin1());
791     system(QString("chmod -R u+rwx %1 2>/dev/null").arg(settingsPath("someDir")).toLatin1());
792     system(QString("rm -fr %1").arg(settingsPath("someDir")).toLatin1());
793 
794     // prepare a file with some settings
795     if (filePerms != -1) {
796         QSettings settings(settingsPath("someDir/someSettings.ini"), QSettings::IniFormat);
797         QCOMPARE((int) settings.status(), (int) QSettings::NoError);
798 
799         settings.beginGroup("alpha/beta");
800         settings.setValue("geometry", -7);
801         settings.setValue("geometry/x", 1);
802         settings.setValue("geometry/y", 2);
803         settings.setValue("geometry/width", 3);
804         settings.setValue("geometry/height", 4);
805         settings.endGroup();
806         settings.setValue("alpha/gamma/splitter", 5);
807     } else {
808         system(QString("mkdir -p %1").arg(settingsPath("someDir")).toLatin1());
809     }
810 
811     if (filePerms != -1) {
812         system(QString("chmod %1 %2")
813                     .arg(QString::number(filePerms, 8))
814                     .arg(settingsPath("someDir/someSettings.ini"))
815                     .toLatin1());
816     }
817     system(QString("chmod %1 %2")
818                 .arg(QString::number(dirPerms, 8))
819                 .arg(settingsPath("someDir"))
820                 .toLatin1());
821 
822     // the test
823     {
824         QConfFile::clearCache();
825         QSettings settings(settingsPath("someDir/someSettings.ini"), QSettings::IniFormat);
826         QCOMPARE((int)settings.status(), statusAfterCtor);
827         if (shouldBeEmpty) {
828             QCOMPARE(settings.allKeys().count(), 0);
829         } else {
830             QVERIFY(settings.allKeys().count() > 0);
831         }
832         settings.value("alpha/beta/geometry");
833         QCOMPARE((int)settings.status(), statusAfterGet);
834         settings.setValue("alpha/beta/geometry", 100);
835         QCOMPARE((int)settings.status(), statusAfterGet);
836         QCOMPARE(settings.value("alpha/beta/geometry").toInt(), 100);
837         settings.sync();
838         QCOMPARE(settings.value("alpha/beta/geometry").toInt(), 100);
839         QCOMPARE((int)settings.status(), statusAfterSetAndSync);
840     }
841 #endif // !Q_OS_WIN
842 #endif
843 }
844 
845 Q_DECLARE_METATYPE(QVariant)
Q_DECLARE_METATYPE(QSettings::Status)846 Q_DECLARE_METATYPE(QSettings::Status)
847 
848 void tst_QSettings::testIniParsing_data()
849 {
850     QTest::addColumn<QByteArray>("inicontent");
851     QTest::addColumn<QString>("key");
852     QTest::addColumn<QVariant>("expect");
853     QTest::addColumn<QSettings::Status>("status");
854 
855     // Test "forgiving" parsing of entries not terminated with newline or unterminated strings
856     QTest::newRow("good1")    << QByteArray("v=1\n")          << "v" << QVariant(1) << QSettings::NoError;
857     QTest::newRow("good2")    << QByteArray("v=1\\\n2")       << "v" << QVariant(12) << QSettings::NoError;
858     QTest::newRow("good3")    << QByteArray("v=1\\\r2")       << "v" << QVariant(12) << QSettings::NoError;
859     QTest::newRow("good4")    << QByteArray("v=1\\\n\r2")     << "v" << QVariant(12) << QSettings::NoError;
860     QTest::newRow("good5")    << QByteArray("v=1\\\r\n2")     << "v" << QVariant(12) << QSettings::NoError;
861     QTest::newRow("good6")    << QByteArray("v  \t = \t 1\\\r\n2")     << "v" << QVariant(12) << QSettings::NoError;
862     QTest::newRow("garbage1") << QByteArray("v")              << "v" << QVariant() << QSettings::FormatError;
863     QTest::newRow("nonterm1") << QByteArray("v=str")          << "v" << QVariant("str") << QSettings::NoError;
864     QTest::newRow("nonterm2") << QByteArray("v=\"str\"")      << "v" << QVariant("str") << QSettings::NoError;
865     QTest::newRow("nonterm3") << QByteArray("v=\"str")        << "v" << QVariant("str") << QSettings::NoError;
866     QTest::newRow("nonterm4") << QByteArray("v=\\")           << "v" << QVariant("") << QSettings::NoError;
867     QTest::newRow("nonterm5") << QByteArray("u=s\nv=\"str")   << "v" << QVariant("str") << QSettings::NoError;
868     QTest::newRow("nonterm6") << QByteArray("v=\"str\nw=ok")  << "v" << QVariant("str\nw=ok") << QSettings::NoError;
869     QTest::newRow("nonterm7") << QByteArray("v=")             << "v" << QVariant("") << QSettings::NoError;
870     QTest::newRow("nonterm8") << QByteArray("v=\"str\njnk")   << "v" << QVariant("str\njnk") << QSettings::NoError;
871     QTest::newRow("nonterm9") << QByteArray("v=1\\")          << "v" << QVariant(1) << QSettings::NoError;
872     QTest::newRow("nonterm10") << QByteArray("v=1\\\n")       << "v" << QVariant(1) << QSettings::NoError;
873     QTest::newRow("nonterm11") << QByteArray("v=1\\\r")       << "v" << QVariant(1) << QSettings::NoError;
874     QTest::newRow("nonterm12") << QByteArray("v=1\\\n\r")     << "v" << QVariant(1) << QSettings::NoError;
875     QTest::newRow("nonterm13") << QByteArray("v=1\\\r\n")     << "v" << QVariant(1) << QSettings::NoError;
876     QTest::newRow("nonterm14") << QByteArray("v=1\\\n\nx=2")  << "v" << QVariant(1) << QSettings::NoError;
877     QTest::newRow("nonterm15") << QByteArray("v=1\\\r\rx=2")  << "v" << QVariant(1) << QSettings::NoError;
878     QTest::newRow("nonterm16") << QByteArray("v=1\\\n\n\nx=2") << "v" << QVariant(1) << QSettings::NoError;
879     QTest::newRow("nonterm17") << QByteArray("; foo\nv=1") << "v" << QVariant(1) << QSettings::NoError;
880     QTest::newRow("nonterm18") << QByteArray("; foo\n\nv=1") << "v" << QVariant(1) << QSettings::NoError;
881     QTest::newRow("nonterm19") << QByteArray("\nv=1;foo") << "v" << QVariant(1) << QSettings::NoError;
882     QTest::newRow("nonterm20") << QByteArray("v=x ") << "v" << QVariant("x") << QSettings::NoError;
883     QTest::newRow("nonterm21") << QByteArray("v=x ;") << "v" << QVariant("x") << QSettings::NoError;
884 }
885 
testIniParsing()886 void tst_QSettings::testIniParsing()
887 {
888 #ifdef QT_BUILD_INTERNAL
889     qRegisterMetaType<QVariant>("QVariant");
890     qRegisterMetaType<QSettings::Status>("QSettings::Status");
891 
892     QDir dir(settingsPath());
893     QVERIFY(dir.mkpath("someDir"));
894     QFile f(dir.path()+"/someDir/someSettings.ini");
895 
896     QFETCH(QByteArray, inicontent);
897     QFETCH(QString, key);
898     QFETCH(QVariant, expect);
899     QFETCH(QSettings::Status, status);
900 
901     QVERIFY(f.open(QFile::WriteOnly));
902     f.write(inicontent);
903     f.close();
904 
905     QConfFile::clearCache();
906     QSettings settings(settingsPath("someDir/someSettings.ini"), QSettings::IniFormat);
907 
908     if ( settings.status() == QSettings::NoError ) { // else no point proceeding
909 	QVariant v = settings.value(key);
910 	QVERIFY(v.canConvert(expect.type()));
911 	// check some types so as to give prettier error messages
912 	if ( v.type() == QVariant::String ) {
913 	    QCOMPARE(v.toString(), expect.toString());
914 	} else if ( v.type() == QVariant::Int ) {
915 	    QCOMPARE(v.toInt(), expect.toInt());
916 	} else {
917 	    QCOMPARE(v, expect);
918 	}
919     }
920 
921     QCOMPARE(settings.status(), status);
922 #endif
923 }
924 
925 /*
926     Tests beginGroup(), endGroup(), and group().
927 */
beginGroup()928 void tst_QSettings::beginGroup()
929 {
930     QSettings settings1(QSettings::UserScope, "software.org", "KillerAPP");
931     QSettings settings2(QSettings::UserScope, "software.org", "KillerAPP");
932 
933     /*
934       Let's start with some back and forthing.
935     */
936 
937     settings1.beginGroup("alpha");
938     QCOMPARE(settings1.group(), QString("alpha"));
939     settings1.endGroup();
940     QCOMPARE(settings1.group(), QString());
941     settings1.beginGroup("/beta");
942     QCOMPARE(settings1.group(), QString("beta"));
943     settings1.endGroup();
944     QCOMPARE(settings1.group(), QString());
945 
946     settings1.beginGroup("///gamma//");
947     QCOMPARE(settings1.group(), QString("gamma"));
948     settings1.endGroup();
949     QCOMPARE(settings1.group(), QString());
950 
951     settings1.setValue("geometry", 5);
952     QCOMPARE(settings1.value("geometry").toInt(), 5);
953     QCOMPARE(settings1.value("/geometry///").toInt(), 5);
954     QCOMPARE(settings2.value("geometry").toInt(), 5);
955     QCOMPARE(settings2.value("/geometry///").toInt(), 5);
956 
957     /*
958       OK, now start for real.
959     */
960 
961     settings1.beginGroup("alpha");
962     QCOMPARE(settings1.group(), QString("alpha"));
963     settings1.setValue("geometry", 66);
964     QCOMPARE(settings1.value("geometry").toInt(), 66);
965     QCOMPARE(settings2.value("geometry").toInt(), 5);
966     QCOMPARE(settings2.value("alpha/geometry").toInt(), 66);
967 
968     QSettings settings3(QSettings::UserScope, "software.org", "KillerAPP");
969     settings3.beginGroup("alpha");
970     QCOMPARE(settings3.value("geometry").toInt(), 66);
971 
972     settings1.beginGroup("/beta///");
973     QCOMPARE(settings1.group(), QString("alpha/beta"));
974     settings1.setValue("geometry", 777);
975     QCOMPARE(settings1.value("geometry").toInt(), 777);
976     QCOMPARE(settings2.value("geometry").toInt(), 5);
977     QCOMPARE(settings2.value("alpha/geometry").toInt(), 66);
978     QCOMPARE(settings2.value("alpha/beta/geometry").toInt(), 777);
979     QCOMPARE(settings3.value("geometry").toInt(), 66);
980     QCOMPARE(settings3.value("beta/geometry").toInt(), 777);
981 
982     settings3.beginGroup("gamma");
983     settings3.setValue("geometry", 8888);
984     QCOMPARE(settings3.value("geometry").toInt(), 8888);
985     QCOMPARE(settings2.value("geometry").toInt(), 5);
986     QCOMPARE(settings2.value("alpha/geometry").toInt(), 66);
987     QCOMPARE(settings2.value("alpha/beta/geometry").toInt(), 777);
988     QCOMPARE(settings2.value("alpha/gamma/geometry").toInt(), 8888);
989     QCOMPARE(settings1.value("geometry").toInt(), 777);
990 
991     // endGroup() should do nothing if group() is empty
992     for (int i = 0; i < 10; ++i)
993         settings2.endGroup();
994     QCOMPARE(settings2.value("geometry").toInt(), 5);
995     QCOMPARE(settings2.value("alpha/geometry").toInt(), 66);
996     QCOMPARE(settings2.value("alpha/beta/geometry").toInt(), 777);
997     QCOMPARE(settings2.value("alpha/gamma/geometry").toInt(), 8888);
998 
999     QCOMPARE(settings1.group(), QString("alpha/beta"));
1000     settings1.endGroup();
1001     QCOMPARE(settings1.group(), QString("alpha"));
1002     settings1.endGroup();
1003     QCOMPARE(settings1.group(), QString());
1004     QCOMPARE(settings1.value("geometry").toInt(), 5);
1005     QCOMPARE(settings1.value("alpha/geometry").toInt(), 66);
1006     QCOMPARE(settings1.value("alpha/beta/geometry").toInt(), 777);
1007     QCOMPARE(settings1.value("alpha/gamma/geometry").toInt(), 8888);
1008 
1009     settings1.beginGroup("delta");
1010     QCOMPARE(settings1.group(), QString("delta"));
1011     settings1.beginGroup("");
1012     QCOMPARE(settings1.group(), QString("delta"));
1013     settings1.beginGroup("/");
1014     QCOMPARE(settings1.group(), QString("delta"));
1015     settings1.beginGroup("////");
1016     QCOMPARE(settings1.group(), QString("delta"));
1017     settings1.beginGroup("////omega///epsilon zeta eta  theta/ / /");
1018     QCOMPARE(settings1.group(), QString("delta/omega/epsilon zeta eta  theta/ / "));
1019     settings1.endGroup();
1020     QCOMPARE(settings1.group(), QString("delta"));
1021     settings1.endGroup();
1022     QCOMPARE(settings1.group(), QString("delta"));
1023     settings1.endGroup();
1024     QCOMPARE(settings1.group(), QString("delta"));
1025     settings1.endGroup();
1026     QCOMPARE(settings1.group(), QString("delta"));
1027     settings1.endGroup();
1028     QCOMPARE(settings1.group(), QString());
1029 }
1030 
1031 /*
1032     Tests setValue() and getXxx().
1033 */
setValue()1034 void tst_QSettings::setValue()
1035 {
1036     QSettings settings(QSettings::UserScope, "software.org", "KillerAPP");
1037 
1038     settings.setValue("key 2", (int)0x7fffffff);
1039     QCOMPARE(settings.value("key 2").toInt(), (int)0x7fffffff);
1040     QCOMPARE(settings.value("key 2").toString(), QString::number((int)0x7fffffff));
1041     settings.setValue("key 2", -1);
1042     QCOMPARE(settings.value("key 2").toInt(), -1);
1043     QCOMPARE(settings.value("key 2").toString(), QString("-1"));
1044     settings.setValue("key 2", (int)0x80000000);
1045     QCOMPARE(settings.value("key 2").toInt(), (int)0x80000000);
1046     settings.setValue("key 2", (int)0);
1047     QCOMPARE(settings.value("key 2", 123).toInt(), (int)0);
1048     settings.setValue("key 2", (int)12345);
1049     QCOMPARE(settings.value("key 2").toInt(), (int)12345);
1050     QCOMPARE(settings.value("no such key", 1234).toInt(), (int)1234);
1051     QCOMPARE(settings.value("no such key").toInt(), (int)0);
1052 
1053     settings.setValue("key 2", true);
1054     QCOMPARE(settings.value("key 2").toBool(), true);
1055     settings.setValue("key 2", false);
1056     QCOMPARE(settings.value("key 2", true).toBool(), false);
1057     settings.setValue("key 2", (int)1);
1058     QCOMPARE(settings.value("key 2").toBool(), true);
1059     settings.setValue("key 2", (int)-1);
1060     QCOMPARE(settings.value("key 2").toBool(), true);
1061     settings.setValue("key 2", (int)0);
1062     QCOMPARE(settings.value("key 2", true).toBool(), false);
1063     settings.setValue("key 2", QString("true"));
1064     QCOMPARE(settings.value("key 2").toBool(), true);
1065     settings.setValue("key 2", QString("false"));
1066     QCOMPARE(settings.value("key 2", true).toBool(), false);
1067 /*
1068     settings.setValue("key 2", "true");
1069     QCOMPARE(settings.value("key 2").toBool(), true);
1070     settings.setValue("key 2", "false");
1071     QCOMPARE(settings.value("key 2", true).toBool(), false);
1072     settings.setValue("key 2", "");
1073     QCOMPARE(settings.value("key 2", true).toBool(), true);
1074     settings.setValue("key 2", "");
1075     QCOMPARE(settings.value("key 2", false).toBool(), false);
1076     settings.setValue("key 2", "0.000e-00"); // cannot convert double to a bool
1077     QCOMPARE(settings.value("key 2", true).toBool(), true);
1078     settings.setValue("key 2", "0.000e-00");
1079     QCOMPARE(settings.value("key 2", false).toBool(), false);
1080 
1081 */
1082     settings.setValue("key 2", QStringList());
1083     QCOMPARE(settings.value("key 2").toStringList(), QStringList());
1084     settings.setValue("key 2", QStringList(""));
1085     QCOMPARE(settings.value("key 2").toStringList(), QStringList(""));
1086     settings.setValue("key 2", QStringList() << "" << "");
1087     QCOMPARE(settings.value("key 2").toStringList(), QStringList() << "" << "");
1088     settings.setValue("key 2", QStringList() << "" << "a" << "" << "bc" << "");
1089     QCOMPARE(settings.value("key 2").toStringList(), QStringList() << "" << "a" << "" << "bc" << "");
1090 
1091     settings.setValue("key 3", QList<QVariant>());
1092     QCOMPARE(settings.value("key 3").toList(), QList<QVariant>());
1093     settings.setValue("key 3", QList<QVariant>() << 1 << QString("a"));
1094     QCOMPARE(settings.value("key 3").toList(), QList<QVariant>() << 1 << QString("a"));
1095 
1096     QList<QVariant> outerList;
1097     outerList << 1 << QString("b");
1098     QList<QVariant> innerList = outerList;
1099     outerList.append(QVariant(innerList));
1100     outerList.append(QVariant(innerList));
1101     outerList << 2 << QString("c");
1102     innerList = outerList;
1103     outerList.append(QVariant(innerList));
1104     // outerList: [1, "b", [1, "b"], [1, "b"], 2, "c", [1, "b", [1, "b"], [1, "b"], 2, "c"]]
1105 
1106     settings.setValue("key 3", outerList);
1107     QCOMPARE(settings.value("key 3").toList(), outerList);
1108     QCOMPARE(settings.value("key 3").toList().size(), 7);
1109 
1110     QMap<QString, QVariant> map;
1111     map.insert("1", "one");
1112     map.insert("2", "two");
1113     map.insert("3", outerList);
1114     map.insert("5", "cinco");
1115     map.insert("10", "zehn");
1116     settings.setValue("key 4", map);
1117     QCOMPARE(settings.value("key 4").toMap(), map);
1118 }
1119 
testVariantTypes_data()1120 void tst_QSettings::testVariantTypes_data()
1121 {
1122     populateWithFormats();
1123 }
1124 
testVariantTypes()1125 void tst_QSettings::testVariantTypes()
1126 {
1127 #ifdef QT_BUILD_INTERNAL
1128 #define testVal(key, val, tp, rtype) \
1129     { \
1130         QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP"); \
1131         settings1.setValue(key, qVariantFromValue(val)); \
1132     } \
1133     QConfFile::clearCache(); \
1134     { \
1135         QSettings settings2(format, QSettings::UserScope, "software.org", "KillerAPP"); \
1136         QVariant v = settings2.value(key); \
1137         QVERIFY(qvariant_cast<tp >(v) == val); \
1138         QVERIFY(v.type() == QVariant::rtype); \
1139     }
1140 
1141     typedef QMap<QString, QVariant> TestVariantMap;
1142 
1143     QFETCH(QSettings::Format, format);
1144 
1145     TestVariantMap m2;
1146     m2.insert("ene", "due");
1147     m2.insert("rike", "fake");
1148     m2.insert("borba", "dorba");
1149     testVal("key2", m2, TestVariantMap, Map);
1150 
1151     QStringList l2;
1152 
1153     l2 << "ene" << "due" << "@Point(1 2)" << "@fake";
1154     testVal("key3", l2, QStringList, StringList);
1155 
1156     l2.clear();
1157     l2 << "ene" << "due" << "rike" << "fake";
1158     testVal("key3", l2, QStringList, StringList);
1159 
1160     QList<QVariant> l3;
1161     QDate date = QDate::currentDate();
1162     QTime time = QTime::currentTime();
1163     l3 << QString("ene") << 10 << qVariantFromValue(QColor(1, 2, 3)) << QVariant(QRect(1, 2, 3, 4))
1164         << QVariant(QSize(4, 56)) << QVariant(QPoint(4, 2)) << true << false << date << time;
1165     testVal("key3", l3, QVariantList, List);
1166 
1167     testVal("key4", QString("hello"), QString, String);
1168     testVal("key5", QColor(1, 2, 3), QColor, Color);
1169     testVal("key6", QRect(1, 2, 3, 4), QRect, Rect);
1170     testVal("key7", QSize(4, 56), QSize, Size);
1171     testVal("key8", QPoint(4, 2), QPoint, Point);
1172     testVal("key10", date, QDate, Date);
1173     testVal("key11", time, QTime, Time);
1174     testVal("key12", QByteArray("foo bar"), QByteArray, ByteArray);
1175 
1176     {
1177         QSettings settings(format, QSettings::UserScope, "software.org", "KillerAPP");
1178         QVERIFY(!settings.contains("key99"));
1179         QCOMPARE(settings.value("key99"), QVariant());
1180 
1181         settings.setValue("key99", QVariant());
1182         QVERIFY(settings.contains("key99"));
1183         QCOMPARE(settings.value("key99"), QVariant());
1184 
1185         settings.setValue("key99", QVariant(1));
1186         QVERIFY(settings.contains("key99"));
1187         QCOMPARE(settings.value("key99"), QVariant(1));
1188 
1189         settings.setValue("key99", QVariant());
1190         QVERIFY(settings.contains("key99"));
1191         QCOMPARE(settings.value("key99"), QVariant());
1192 
1193         settings.remove("key99");
1194         QVERIFY(!settings.contains("key99"));
1195         QCOMPARE(settings.value("key99"), QVariant());
1196     }
1197 
1198     QList<QVariant> l4;
1199     l4 << QVariant(m2) << QVariant(l2) << QVariant(l3);
1200     testVal("key13", l4, QVariantList, List);
1201 
1202     // We store key sequences as strings instead of binary variant blob, for improved
1203     // readability in the resulting format.
1204     if (format >= QSettings::InvalidFormat) {
1205         testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QKeySequence, KeySequence);
1206     } else {
1207         testVal("keysequence", QKeySequence(Qt::ControlModifier + Qt::Key_F1), QString, String);
1208     }
1209 
1210 #undef testVal
1211 #endif
1212 }
1213 
remove()1214 void tst_QSettings::remove()
1215 {
1216     QSettings settings0(QSettings::UserScope, "software.org", "KillerAPP");
1217     int initialNumKeys = settings0.allKeys().size();
1218     QCOMPARE(settings0.value("key 1", "123").toString(), QString("123"));
1219     settings0.remove("key 1");
1220     QCOMPARE(settings0.value("key 1", "456").toString(), QString("456"));
1221 
1222     settings0.setValue("key 1", "bubloo");
1223     QCOMPARE(settings0.value("key 1").toString(), QString("bubloo"));
1224     settings0.remove("key 2");
1225     QCOMPARE(settings0.value("key 1").toString(), QString("bubloo"));
1226     settings0.remove("key 1");
1227     QCOMPARE(settings0.value("key 1", "789").toString(), QString("789"));
1228 
1229     /*
1230       Make sure that removing a key removes all the subkeys.
1231     */
1232     settings0.setValue("alpha/beta/geometry", -7);
1233     settings0.setValue("alpha/beta/geometry/x", 1);
1234     settings0.setValue("alpha/beta/geometry/y", 2);
1235     settings0.setValue("alpha/beta/geometry/width", 3);
1236     settings0.setValue("alpha/beta/geometry/height", 4);
1237     settings0.setValue("alpha/gamma/splitter", 5);
1238 
1239     settings0.remove("alpha/beta/geometry/x");
1240     QCOMPARE(settings0.value("alpha/beta/geometry").toInt(), -7);
1241     QCOMPARE(settings0.value("alpha/beta/geometry/x", 999).toInt(), 999);
1242     QCOMPARE(settings0.value("alpha/beta/geometry/y").toInt(), 2);
1243     QCOMPARE(settings0.value("alpha/beta/geometry/width").toInt(), 3);
1244     QCOMPARE(settings0.value("alpha/beta/geometry/height").toInt(), 4);
1245     QCOMPARE(settings0.value("alpha/gamma/splitter").toInt(), 5);
1246 
1247     settings0.remove("alpha/beta/geometry");
1248     QCOMPARE(settings0.value("alpha/beta/geometry", 777).toInt(), 777);
1249     QCOMPARE(settings0.value("alpha/beta/geometry/x", 111).toInt(), 111);
1250     QCOMPARE(settings0.value("alpha/beta/geometry/y", 222).toInt(), 222);
1251     QCOMPARE(settings0.value("alpha/beta/geometry/width", 333).toInt(), 333);
1252     QCOMPARE(settings0.value("alpha/beta/geometry/height", 444).toInt(), 444);
1253     QCOMPARE(settings0.value("alpha/gamma/splitter").toInt(), 5);
1254 
1255     settings0.setValue("alpha/beta/geometry", -7);
1256     settings0.setValue("alpha/beta/geometry/x", 1);
1257     settings0.setValue("alpha/beta/geometry/y", 2);
1258     settings0.setValue("alpha/beta/geometry/width", 3);
1259     settings0.setValue("alpha/beta/geometry/height", 4);
1260     settings0.setValue("alpha/gamma/splitter", 5);
1261     QCOMPARE(settings0.allKeys().size(), initialNumKeys + 6);
1262 
1263     settings0.beginGroup("alpha/beta/geometry");
1264     settings0.remove("");
1265     settings0.endGroup();
1266     QVERIFY(!settings0.contains("alpha/beta/geometry"));
1267     QVERIFY(!settings0.contains("alpha/beta/geometry/x"));
1268     QVERIFY(!settings0.contains("alpha/beta/geometry/y"));
1269     QVERIFY(!settings0.contains("alpha/beta/geometry/width"));
1270     QVERIFY(!settings0.contains("alpha/beta/geometry/height"));
1271     QVERIFY(settings0.contains("alpha/gamma/splitter"));
1272     QCOMPARE(settings0.allKeys().size(), initialNumKeys + 1);
1273 
1274     settings0.beginGroup("alpha/beta");
1275     settings0.remove("");
1276     settings0.endGroup();
1277     QVERIFY(!settings0.contains("alpha/beta/geometry"));
1278     QVERIFY(!settings0.contains("alpha/beta/geometry/x"));
1279     QVERIFY(!settings0.contains("alpha/beta/geometry/y"));
1280     QVERIFY(!settings0.contains("alpha/beta/geometry/width"));
1281     QVERIFY(!settings0.contains("alpha/beta/geometry/height"));
1282     QVERIFY(settings0.contains("alpha/gamma/splitter"));
1283     QCOMPARE(settings0.allKeys().size(), initialNumKeys + 1);
1284 
1285     settings0.remove("");
1286     QVERIFY(!settings0.contains("alpha/gamma/splitter"));
1287     QCOMPARE(settings0.allKeys().size(), initialNumKeys);
1288 
1289     /*
1290       Do it again, but this time let's use setGroup().
1291     */
1292 
1293     settings0.setValue("alpha/beta/geometry", -7);
1294     settings0.setValue("alpha/beta/geometry/x", 1);
1295     settings0.setValue("alpha/beta/geometry/y", 2);
1296     settings0.setValue("alpha/beta/geometry/width", 3);
1297     settings0.setValue("alpha/beta/geometry/height", 4);
1298     settings0.setValue("alpha/gamma/splitter", 5);
1299 
1300     settings0.beginGroup("foo/bar/baz/doesn't");
1301     settings0.remove("exist");
1302     settings0.endGroup();
1303     QCOMPARE(settings0.value("alpha/beta/geometry").toInt(), -7);
1304     QCOMPARE(settings0.value("alpha/beta/geometry/x").toInt(), 1);
1305     QCOMPARE(settings0.value("alpha/beta/geometry/y").toInt(), 2);
1306     QCOMPARE(settings0.value("alpha/beta/geometry/width").toInt(), 3);
1307     QCOMPARE(settings0.value("alpha/beta/geometry/height").toInt(), 4);
1308     QCOMPARE(settings0.value("alpha/gamma/splitter").toInt(), 5);
1309 
1310     settings0.beginGroup("alpha/beta/geometry");
1311     settings0.remove("x");
1312     settings0.endGroup();
1313     QCOMPARE(settings0.value("alpha/beta/geometry").toInt(), -7);
1314     QCOMPARE(settings0.value("alpha/beta/geometry/x", 999).toInt(), 999);
1315     QCOMPARE(settings0.value("alpha/beta/geometry/y").toInt(), 2);
1316     QCOMPARE(settings0.value("alpha/beta/geometry/width").toInt(), 3);
1317     QCOMPARE(settings0.value("alpha/beta/geometry/height").toInt(), 4);
1318     QCOMPARE(settings0.value("alpha/gamma/splitter").toInt(), 5);
1319 
1320     settings0.remove("alpha/beta");
1321     QCOMPARE(settings0.value("alpha/beta/geometry", 777).toInt(), 777);
1322     QCOMPARE(settings0.value("alpha/beta/geometry/x", 111).toInt(), 111);
1323     QCOMPARE(settings0.value("alpha/beta/geometry/y", 222).toInt(), 222);
1324     QCOMPARE(settings0.value("alpha/beta/geometry/width", 333).toInt(), 333);
1325     QCOMPARE(settings0.value("alpha/beta/geometry/height", 444).toInt(), 444);
1326     QCOMPARE(settings0.value("alpha/gamma/splitter").toInt(), 5);
1327 
1328     settings0.clear();
1329     QCOMPARE(settings0.value("alpha/gamma/splitter", 888).toInt(), 888);
1330 
1331     /*
1332       OK, now let's check what happens if settings are spread across
1333       multiple files (user vs. global, product-specific vs.
1334       company-wide).
1335     */
1336 
1337     QSettings settings1(QSettings::UserScope, "software.org", "KillerAPP");
1338     QSettings settings2(QSettings::UserScope, "software.org");
1339     QSettings settings3(QSettings::SystemScope, "software.org", "KillerAPP");
1340     QSettings settings4(QSettings::SystemScope, "software.org");
1341 
1342     settings4.setValue("key 1", "doodah");
1343     settings3.setValue("key 1", "blah");
1344     settings2.setValue("key 1", "whoa");
1345     settings1.setValue("key 1", "gurgle");
1346     QCOMPARE(settings1.value("key 1").toString(), QString("gurgle"));
1347     QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
1348 
1349 #if !defined(Q_OS_BLACKBERRY)
1350     QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
1351     QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
1352 
1353     settings1.remove("key 1");
1354     QCOMPARE(settings1.value("key 1").toString(), QString("whoa"));
1355     QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
1356     QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
1357     QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
1358 
1359     settings2.remove("key 1");
1360     QCOMPARE(settings1.value("key 1").toString(), QString("blah"));
1361     QCOMPARE(settings2.value("key 1").toString(), QString("doodah"));
1362     QCOMPARE(settings3.value("key 1").toString(), QString("blah"));
1363     QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
1364 
1365     settings3.remove("key 1");
1366     QCOMPARE(settings1.value("key 1").toString(), QString("doodah"));
1367     QCOMPARE(settings2.value("key 1").toString(), QString("doodah"));
1368     QCOMPARE(settings3.value("key 1").toString(), QString("doodah"));
1369     QCOMPARE(settings4.value("key 1").toString(), QString("doodah"));
1370 
1371     settings4.remove("key 1");
1372     QVERIFY(!settings1.contains("key 1"));
1373     QVERIFY(!settings2.contains("key 1"));
1374     QVERIFY(!settings3.contains("key 1"));
1375     QVERIFY(!settings4.contains("key 1"));
1376 #else
1377     settings1.remove("key 1");
1378     QCOMPARE(settings2.value("key 1").toString(), QString("whoa"));
1379 
1380     settings2.remove("key 1");
1381     QVERIFY(!settings1.contains("key 1"));
1382     QVERIFY(!settings2.contains("key 1"));
1383 #endif
1384 
1385     /*
1386       Get ready for the next part of the test.
1387     */
1388 
1389     settings1.clear();
1390     settings2.clear();
1391     settings3.clear();
1392     settings4.clear();
1393 
1394     settings1.sync();
1395     settings2.sync();
1396     settings3.sync();
1397     settings4.sync();
1398 
1399     /*
1400       Check that recursive removes work correctly when some of the
1401       keys are loaded from the file and others have been modified in
1402       memory (corresponds to originalKeys vs. addedKeys in the
1403       QSettingsFile code).
1404     */
1405 
1406     settings1.setValue("alpha/beta/geometry", -7);
1407     settings1.setValue("alpha/beta/geometry/x", 1);
1408     settings1.setValue("alpha/beta/geometry/y", 2);
1409     settings1.setValue("alpha/gamma/splitter", 5);
1410     settings1.sync();
1411 
1412     settings1.setValue("alpha/beta/geometry/width", 3);
1413     settings1.setValue("alpha/beta/geometry/height", 4);
1414 
1415     settings1.remove("alpha/beta/geometry/y");
1416     QVERIFY(settings1.contains("alpha/beta/geometry"));
1417     QVERIFY(settings1.contains("alpha/beta/geometry/x"));
1418     QVERIFY(!settings1.contains("alpha/beta/geometry/y"));
1419     QVERIFY(settings1.contains("alpha/beta/geometry/width"));
1420     QVERIFY(settings1.contains("alpha/beta/geometry/height"));
1421     QCOMPARE(settings1.allKeys().size(), initialNumKeys + 5);
1422 
1423     settings1.remove("alpha/beta/geometry/y");
1424     QCOMPARE(settings1.allKeys().size(), initialNumKeys + 5);
1425 
1426     settings1.remove("alpha/beta/geometry/height");
1427     QVERIFY(settings1.contains("alpha/beta/geometry"));
1428     QVERIFY(settings1.contains("alpha/beta/geometry/x"));
1429     QVERIFY(!settings1.contains("alpha/beta/geometry/y"));
1430     QVERIFY(settings1.contains("alpha/beta/geometry/width"));
1431     QVERIFY(!settings1.contains("alpha/beta/geometry/height"));
1432     QCOMPARE(settings1.allKeys().size(), initialNumKeys + 4);
1433 
1434     settings1.remove("alpha/beta/geometry");
1435     QVERIFY(!settings1.contains("alpha/beta/geometry"));
1436     QVERIFY(!settings1.contains("alpha/beta/geometry/x"));
1437     QVERIFY(!settings1.contains("alpha/beta/geometry/y"));
1438     QVERIFY(!settings1.contains("alpha/beta/geometry/width"));
1439     QVERIFY(!settings1.contains("alpha/beta/geometry/height"));
1440     QVERIFY(settings1.contains("alpha/gamma/splitter"));
1441     QCOMPARE(settings1.allKeys().size(), initialNumKeys + 1);
1442 
1443     settings1.sync();
1444     QVERIFY(!settings1.contains("alpha/beta/geometry"));
1445     QVERIFY(!settings1.contains("alpha/beta/geometry/x"));
1446     QVERIFY(!settings1.contains("alpha/beta/geometry/y"));
1447     QVERIFY(!settings1.contains("alpha/beta/geometry/width"));
1448     QVERIFY(!settings1.contains("alpha/beta/geometry/height"));
1449     QVERIFY(settings1.contains("alpha/gamma/splitter"));
1450     QCOMPARE(settings1.allKeys().size(), initialNumKeys + 1);
1451 }
1452 
1453 /*
1454     Tests contains() and keys().
1455 */
contains()1456 void tst_QSettings::contains()
1457 {
1458     QSettings settings1(QSettings::UserScope, "software.org", "KillerAPP");
1459     int initialNumKeys = settings1.allKeys().size(); // 0 on all platforms but Mac OS X.
1460     settings1.setValue("alpha/beta/geometry", -7);
1461     settings1.setValue("alpha/beta/geometry/x", 1);
1462     settings1.setValue("alpha/beta/geometry/y", 2);
1463     settings1.setValue("alpha/beta/geometry/width", 3);
1464     settings1.setValue("alpha/beta/geometry/height", 4);
1465     settings1.setValue("alpha/gamma/splitter", 5);
1466     settings1.setValue("alpha/gamma/splitter/ /", 5);
1467 
1468     QVERIFY(!settings1.contains("alpha"));
1469     QVERIFY(!settings1.contains("alpha/beta"));
1470     QVERIFY(!settings1.contains("///alpha///beta///"));
1471     QVERIFY(settings1.contains("alpha/beta/geometry"));
1472     QVERIFY(settings1.contains("///alpha///beta//geometry//"));
1473     QVERIFY(settings1.contains("alpha/beta/geometry/x"));
1474     QVERIFY(settings1.contains("alpha/beta/geometry/y"));
1475     QVERIFY(settings1.contains("alpha/beta/geometry/width"));
1476     QVERIFY(settings1.contains("alpha/beta/geometry/height"));
1477     QVERIFY(!settings1.contains("alpha/beta/geometry/height/foo/bar/doesn't/exist"));
1478     QVERIFY(!settings1.contains("alpha/gamma"));
1479     QVERIFY(settings1.contains("alpha/gamma/splitter"));
1480     QVERIFY(settings1.contains("alpha/gamma/splitter/ "));
1481     QVERIFY(settings1.contains("////alpha/gamma/splitter// ////"));
1482 
1483     settings1.beginGroup("alpha");
1484     QVERIFY(!settings1.contains("beta"));
1485     QVERIFY(!settings1.contains("/////beta///"));
1486     QVERIFY(settings1.contains("beta/geometry"));
1487     QVERIFY(settings1.contains("/////beta//geometry//"));
1488     QVERIFY(settings1.contains("beta/geometry/x"));
1489     QVERIFY(settings1.contains("beta/geometry/y"));
1490     QVERIFY(settings1.contains("beta/geometry/width"));
1491     QVERIFY(settings1.contains("beta/geometry/height"));
1492     QVERIFY(!settings1.contains("beta/geometry/height/foo/bar/doesn't/exist"));
1493     QVERIFY(!settings1.contains("gamma"));
1494     QVERIFY(settings1.contains("gamma/splitter"));
1495     QVERIFY(settings1.contains("gamma/splitter/ "));
1496     QVERIFY(settings1.contains("////gamma/splitter// ////"));
1497 
1498     settings1.beginGroup("beta/geometry");
1499     QVERIFY(settings1.contains("x"));
1500     QVERIFY(settings1.contains("y"));
1501     QVERIFY(settings1.contains("width"));
1502     QVERIFY(settings1.contains("height"));
1503     QVERIFY(!settings1.contains("height/foo/bar/doesn't/exist"));
1504 
1505     QStringList keys = settings1.allKeys();
1506     QStringList expectedResult = QStringList() << "x" << "y" << "width" << "height";
1507     keys.sort();
1508     expectedResult.sort();
1509     int i;
1510     QCOMPARE(keys, expectedResult);
1511     for (i = 0; i < keys.size(); ++i) {
1512         QVERIFY(settings1.contains(keys.at(i)));
1513     }
1514 
1515     settings1.endGroup();
1516     QVERIFY(settings1.group() == "alpha");
1517     keys = settings1.allKeys();
1518     QCOMPARE(keys.size(), expectedResult.size() + 3);
1519     for (i = 0; i < keys.size(); ++i) {
1520         QVERIFY(settings1.contains(keys.at(i)));
1521     }
1522 
1523     settings1.endGroup();
1524     QVERIFY(settings1.group().isEmpty());
1525     keys = settings1.allKeys();
1526 
1527     QCOMPARE(keys.size(), initialNumKeys + 7);
1528     for (i = 0; i < keys.size(); ++i) {
1529         QVERIFY(settings1.contains(keys.at(i)));
1530     }
1531 }
1532 
sync()1533 void tst_QSettings::sync()
1534 {
1535     /*
1536         What we're trying to test here is the case where two
1537         instances of the same application access the same preference
1538         files. We want to make sure that the results are 'merged',
1539         rather than having the last application overwrite settings
1540         set by the first application (like in Qt 3).
1541 
1542         This is only applicable to the INI format. The Windows
1543         registry and Mac's CFPreferences API should take care of this
1544         by themselves.
1545     */
1546 
1547     QSettings settings1(QSettings::IniFormat, QSettings::UserScope, "software.org");
1548     settings1.setValue("alpha/beta/geometry", -7);
1549     settings1.setValue("alpha/beta/geometry/x", 1);
1550     settings1.setValue("alpha/beta/geometry/y", 2);
1551     settings1.setValue("alpha/beta/geometry/width", 3);
1552     settings1.setValue("alpha/beta/geometry/height", 4);
1553     settings1.setValue("alpha/gamma/splitter", 5);
1554     settings1.sync(); // and it all goes into the file
1555 
1556     QSettings settings2(QSettings::IniFormat, QSettings::UserScope, "other.software.org");
1557     settings2.setValue("alpha/beta/geometry/x", 8);
1558     settings2.sync();
1559 
1560     settings2.setValue("moo/beta/geometry", -7);
1561     settings2.setValue("moo/beta/geometry/x", 1);
1562     settings2.setValue("moo/beta/geometry/y", 2);
1563     settings2.setValue("moo/beta/geometry/width", 3);
1564     settings2.setValue("moo/beta/geometry/height", 4);
1565     settings2.setValue("moo/gamma/splitter", 5);
1566     settings2.setValue("alpha/gamma/splitter", 15);
1567     settings2.remove("alpha/beta/geometry/x");
1568     settings2.remove("alpha/beta/geometry/y"); // should do nothing
1569 
1570     // Now "some other app" will change other.software.org.ini
1571     QString userConfDir = settingsPath("__user__") + QDir::separator();
1572 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
1573     unlink((userConfDir + "other.software.org.ini").toLatin1());
1574     rename((userConfDir + "software.org.ini").toLatin1(),
1575            (userConfDir + "other.software.org.ini").toLatin1());
1576 #else
1577     QFile::remove(userConfDir + "other.software.org.ini");
1578     QFile::rename(userConfDir + "software.org.ini" , userConfDir + "other.software.org.ini");
1579 #endif
1580 
1581     settings2.sync();
1582 
1583     // And voila, we should be merged
1584 
1585     QCOMPARE(settings2.value("alpha/beta/geometry").toInt(), -7);
1586     QVERIFY(!settings2.contains("alpha/beta/geometry/x")); // <----- removed by settings2
1587     QCOMPARE(settings2.value("alpha/beta/geometry/y").toInt(), 2);
1588     QCOMPARE(settings2.value("alpha/beta/geometry/width").toInt(), 3);
1589     QCOMPARE(settings2.value("alpha/beta/geometry/height").toInt(), 4);
1590     QCOMPARE(settings2.value("alpha/gamma/splitter").toInt(), 15); // <---- set by settings2
1591     QCOMPARE(settings2.value("moo/beta/geometry").toInt(), -7);
1592     QCOMPARE(settings2.value("moo/beta/geometry/x").toInt(), 1);
1593     QCOMPARE(settings2.value("moo/beta/geometry/y").toInt(), 2);
1594     QCOMPARE(settings2.value("moo/beta/geometry/width").toInt(), 3);
1595     QCOMPARE(settings2.value("moo/beta/geometry/height").toInt(), 4);
1596     QCOMPARE(settings2.value("moo/gamma/splitter").toInt(), 5);
1597     QCOMPARE(settings2.allKeys().count(), 11);
1598 
1599     // Now, software.org.ini no longer exists, this is same as another app
1600     // clearing all settings.
1601     settings1.sync();
1602     QCOMPARE(settings1.allKeys().count(), 0);
1603 
1604 /*
1605     // Now "some other app" will change software.org.conf
1606     unlink((userConfDir + "software.org.ini").toLatin1());
1607     rename((userConfDir + "other.software.org.ini").toLatin1(),
1608             (userConfDir + "software.org.ini").toLatin1());
1609 
1610     settings1.sync();
1611     QCOMPARE(settings1.value("alpha/beta/geometry").toInt(), -7);
1612     QCOMPARE(settings1.value("alpha/beta/geometry/y").toInt(), 2);
1613     QCOMPARE(settings1.value("alpha/beta/geometry/width").toInt(), 3);
1614     QCOMPARE(settings1.value("alpha/beta/geometry/height").toInt(), 4);
1615     QCOMPARE(settings1.value("alpha/gamma/splitter").toInt(), 15);
1616     QCOMPARE(settings1.value("moo/beta/geometry").toInt(), -7);
1617     QCOMPARE(settings1.value("moo/beta/geometry/x").toInt(), 1);
1618     QCOMPARE(settings1.value("moo/beta/geometry/y").toInt(), 2);
1619     QCOMPARE(settings1.value("moo/beta/geometry/width").toInt(), 3);
1620     QCOMPARE(settings1.value("moo/beta/geometry/height").toInt(), 4);
1621     QCOMPARE(settings1.value("moo/gamma/splitter").toInt(), 5);
1622     QCOMPARE(settings1.allKeys().count(), 11);
1623 */
1624 }
1625 
setFallbacksEnabled_data()1626 void tst_QSettings::setFallbacksEnabled_data()
1627 {
1628     populateWithFormats();
1629 }
1630 
setFallbacksEnabled()1631 void tst_QSettings::setFallbacksEnabled()
1632 {
1633     QFETCH(QSettings::Format, format);
1634 
1635     QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP");
1636     QSettings settings2(format, QSettings::UserScope, "software.org");
1637     QSettings settings3(format, QSettings::SystemScope, "software.org", "KillerAPP");
1638     QSettings settings4(format, QSettings::SystemScope, "software.org");
1639 
1640     settings1.setValue("key 1", "alpha");
1641     settings2.setValue("key 1", "beta");
1642     settings3.setValue("key 1", "gamma");
1643     settings4.setValue("key 1", "delta");
1644 
1645     settings1.setValue("key 2", "alpha");
1646     settings2.setValue("key 2", "beta");
1647     settings3.setValue("key 2", "gamma");
1648 
1649     settings1.setValue("key 3", "alpha");
1650     settings3.setValue("key 3", "gamma");
1651     settings4.setValue("key 3", "delta");
1652 
1653     settings1.setValue("key 4", "alpha");
1654     settings2.setValue("key 4", "beta");
1655     settings4.setValue("key 4", "delta");
1656 
1657     settings2.setValue("key 5", "beta");
1658     settings3.setValue("key 5", "gamma");
1659     settings4.setValue("key 5", "delta");
1660 
1661     QVERIFY(settings1.fallbacksEnabled());
1662     QVERIFY(settings2.fallbacksEnabled());
1663     QVERIFY(settings3.fallbacksEnabled());
1664     QVERIFY(settings4.fallbacksEnabled());
1665 
1666     settings1.setFallbacksEnabled(false);
1667     settings2.setFallbacksEnabled(false);
1668     settings3.setFallbacksEnabled(false);
1669     settings4.setFallbacksEnabled(false);
1670 
1671     QVERIFY(!settings1.fallbacksEnabled());
1672     QVERIFY(!settings2.fallbacksEnabled());
1673     QVERIFY(!settings3.fallbacksEnabled());
1674     QVERIFY(!settings4.fallbacksEnabled());
1675 
1676     /*
1677         Make sure that the QSettings objects can still access their
1678         main associated file when fallbacks are turned off.
1679     */
1680 
1681 #if !defined(Q_OS_BLACKBERRY)
1682     QCOMPARE(settings1.value("key 1").toString(), QString("alpha"));
1683     QCOMPARE(settings2.value("key 1").toString(), QString("beta"));
1684     QCOMPARE(settings3.value("key 1").toString(), QString("gamma"));
1685     QCOMPARE(settings4.value("key 1").toString(), QString("delta"));
1686 
1687     QCOMPARE(settings1.value("key 2").toString(), QString("alpha"));
1688     QCOMPARE(settings2.value("key 2").toString(), QString("beta"));
1689     QCOMPARE(settings3.value("key 2").toString(), QString("gamma"));
1690     QVERIFY(!settings4.contains("key 2"));
1691 
1692     QCOMPARE(settings1.value("key 3").toString(), QString("alpha"));
1693     QCOMPARE(settings3.value("key 3").toString(), QString("gamma"));
1694     QCOMPARE(settings4.value("key 3").toString(), QString("delta"));
1695     QVERIFY(!settings2.contains("key 3"));
1696 
1697     QCOMPARE(settings1.value("key 4").toString(), QString("alpha"));
1698     QCOMPARE(settings2.value("key 4").toString(), QString("beta"));
1699     QCOMPARE(settings4.value("key 4").toString(), QString("delta"));
1700     QVERIFY(!settings3.contains("key 4"));
1701 
1702     QCOMPARE(settings2.value("key 5").toString(), QString("beta"));
1703     QCOMPARE(settings3.value("key 5").toString(), QString("gamma"));
1704     QCOMPARE(settings4.value("key 5").toString(), QString("delta"));
1705     QVERIFY(!settings1.contains("key 5"));
1706 
1707     QCOMPARE(settings1.value("key 1").toString(), QString("alpha"));
1708     QCOMPARE(settings1.value("key 5").toString(), QString(""));
1709     QVERIFY(settings1.contains("key 1"));
1710     QVERIFY(!settings1.contains("key 5"));
1711 #else
1712     QCOMPARE(settings1.value("key 1").toString(), QString("gamma"));
1713     QCOMPARE(settings2.value("key 1").toString(), QString("delta"));
1714     QCOMPARE(settings3.value("key 1").toString(), QString("gamma"));
1715     QCOMPARE(settings4.value("key 1").toString(), QString("delta"));
1716 
1717     QCOMPARE(settings1.value("key 2").toString(), QString("gamma"));
1718     QCOMPARE(settings2.value("key 2").toString(), QString("beta"));
1719     QCOMPARE(settings3.value("key 2").toString(), QString("gamma"));
1720     QCOMPARE(settings4.value("key 2").toString(), QString("beta"));
1721 
1722     QCOMPARE(settings1.value("key 3").toString(), QString("gamma"));
1723     QCOMPARE(settings2.value("key 3").toString(), QString("delta"));
1724     QCOMPARE(settings3.value("key 3").toString(), QString("gamma"));
1725     QCOMPARE(settings4.value("key 3").toString(), QString("delta"));
1726 #endif
1727 }
1728 
testChildKeysAndGroups_data()1729 void tst_QSettings::testChildKeysAndGroups_data()
1730 {
1731     populateWithFormats();
1732 }
1733 
testChildKeysAndGroups()1734 void tst_QSettings::testChildKeysAndGroups()
1735 {
1736     QFETCH(QSettings::Format, format);
1737 
1738     QSettings settings1(format, QSettings::UserScope, "software.org");
1739     settings1.setFallbacksEnabled(false);
1740     settings1.setValue("alpha/beta/geometry", -7);
1741     settings1.setValue("alpha/beta/geometry/x", 1);
1742     settings1.setValue("alpha/beta/geometry/y", 2);
1743     settings1.setValue("alpha/beta/geometry/width", 3);
1744     settings1.setValue("alpha/beta/geometry/height", 4);
1745     settings1.setValue("alpha/gamma/splitter", 5);
1746 
1747     QCOMPARE(settings1.childKeys(), QStringList());
1748     QCOMPARE(settings1.childGroups(), QStringList() << "alpha");
1749 
1750     settings1.beginGroup("/alpha");
1751     QCOMPARE(settings1.childKeys(), QStringList());
1752     QCOMPARE(settings1.childGroups(), QStringList() << "beta" << "gamma");
1753 
1754     settings1.beginGroup("/beta");
1755     QCOMPARE(settings1.childKeys(), QStringList() << "geometry");
1756     QCOMPARE(settings1.childGroups(), QStringList() << "geometry");
1757 
1758     settings1.beginGroup("/geometry");
1759     QCOMPARE(settings1.childKeys(), QStringList()  << "height" << "width" << "x" << "y");
1760     QCOMPARE(settings1.childGroups(), QStringList());
1761 
1762     settings1.beginGroup("/width");
1763     QCOMPARE(settings1.childKeys(), QStringList());
1764     QCOMPARE(settings1.childGroups(), QStringList());
1765 
1766     settings1.endGroup();
1767     settings1.endGroup();
1768     settings1.endGroup();
1769     settings1.endGroup();
1770 
1771     { // task 53792
1772         QSettings settings2("other.software.org");
1773         settings2.setValue("viewbar/foo/test1", "1");
1774         settings2.setValue("viewbar/foo/test2", "2");
1775         settings2.setValue("viewbar/foo/test3", "3");
1776         settings2.setValue("viewbar/foo/test4", "4");
1777         settings2.setValue("viewbar/foo/test5", "5");
1778         settings2.setValue("viewbar/bar/test1", "1");
1779         settings2.setValue("viewbar/bar/test2", "2");
1780         settings2.setValue("viewbar/bar/test3", "3");
1781         settings2.setValue("viewbar/bar/test4", "4");
1782         settings2.setValue("viewbar/bar/test5", "5");
1783 
1784         settings2.beginGroup("viewbar");
1785         QStringList l = settings2.childGroups();
1786         settings2.endGroup();
1787         l.sort();
1788         QCOMPARE(l, QStringList() << "bar" << "foo");
1789     }
1790 }
1791 
testUpdateRequestEvent()1792 void tst_QSettings::testUpdateRequestEvent()
1793 {
1794     QFile::remove("foo");
1795     QVERIFY(!QFile::exists("foo"));
1796 
1797     QSettings settings1("foo", QSettings::IniFormat);
1798     QVERIFY(!QFile::exists("foo"));
1799     QVERIFY(QFileInfo("foo").size() == 0);
1800     settings1.setValue("key1", 1);
1801     QVERIFY(QFileInfo("foo").size() == 0);
1802 
1803     QTRY_VERIFY(QFileInfo("foo").size() > 0);
1804 
1805     settings1.remove("key1");
1806     QVERIFY(QFileInfo("foo").size() > 0);
1807 
1808     QTRY_VERIFY(QFileInfo("foo").size() == 0);
1809 
1810     settings1.setValue("key2", 2);
1811     QVERIFY(QFileInfo("foo").size() == 0);
1812 
1813     QTRY_VERIFY(QFileInfo("foo").size() > 0);
1814 
1815     settings1.clear();
1816     QVERIFY(QFileInfo("foo").size() > 0);
1817 
1818     QTRY_VERIFY(QFileInfo("foo").size() == 0);
1819 }
1820 
1821 const int NumIterations = 5;
1822 const int NumThreads = 4;
1823 
1824 class SettingsThread : public QThread
1825 {
1826 public:
1827     void run();
start(int n)1828     void start(int n) { param = n; QThread::start(); }
1829 
1830 private:
1831     int param;
1832 };
1833 
run()1834 void SettingsThread::run()
1835 {
1836     for (int i = 0; i < NumIterations; ++i) {
1837         QSettings settings("software.org", "KillerAPP");
1838         settings.setValue(QString::number((param * NumIterations) + i), param);
1839         settings.sync();
1840         QCOMPARE((int)settings.status(), (int)QSettings::NoError);
1841     }
1842 }
1843 
testThreadSafety()1844 void tst_QSettings::testThreadSafety()
1845 {
1846     SettingsThread threads[NumThreads];
1847     int i, j;
1848 
1849     for (i = 0; i < NumThreads; ++i)
1850         threads[i].start(i + 1);
1851     for (i = 0; i < NumThreads; ++i)
1852         threads[i].wait();
1853 
1854     QSettings settings("software.org", "KillerAPP");
1855     for (i = 0; i < NumThreads; ++i) {
1856         int param = i + 1;
1857         for (j = 0; j < NumIterations; ++j) {
1858             QCOMPARE(settings.value(QString::number((param * NumIterations) + j)).toInt(), param);
1859         }
1860     }
1861 }
1862 
testNormalizedKey_data()1863 void tst_QSettings::testNormalizedKey_data()
1864 {
1865     QTest::addColumn<QString>("inKey");
1866     QTest::addColumn<QString>("outKey");
1867 
1868     QTest::newRow("empty1") << "" << "";
1869     QTest::newRow("empty2") << "/" << "";
1870     QTest::newRow("empty3") << "//" << "";
1871     QTest::newRow("empty4") << "///" << "";
1872 
1873     QTest::newRow("a1") << "a" << "a";
1874     QTest::newRow("a2") << "/a" << "a";
1875     QTest::newRow("a3") << "a/" << "a";
1876     QTest::newRow("a4") << "//a" << "a";
1877     QTest::newRow("a5") << "a//" << "a";
1878     QTest::newRow("a6") << "///a" << "a";
1879     QTest::newRow("a7") << "a///" << "a";
1880     QTest::newRow("a8") << "///a/" << "a";
1881     QTest::newRow("a9") << "/a///" << "a";
1882 
1883     QTest::newRow("ab1") << "aaa/bbb" << "aaa/bbb";
1884     QTest::newRow("ab2") << "/aaa/bbb" << "aaa/bbb";
1885     QTest::newRow("ab3") << "aaa/bbb/" << "aaa/bbb";
1886     QTest::newRow("ab4") << "/aaa/bbb/" << "aaa/bbb";
1887     QTest::newRow("ab5") << "aaa///bbb" << "aaa/bbb";
1888     QTest::newRow("ab6") << "aaa///bbb/" << "aaa/bbb";
1889     QTest::newRow("ab7") << "/aaa///bbb/" << "aaa/bbb";
1890     QTest::newRow("ab8") << "////aaa///bbb////" << "aaa/bbb";
1891 }
1892 
testNormalizedKey()1893 void tst_QSettings::testNormalizedKey()
1894 {
1895 #ifdef QT_BUILD_INTERNAL
1896     QFETCH(QString, inKey);
1897     QFETCH(QString, outKey);
1898 
1899     inKey.detach();
1900 
1901     QString result = QSettingsPrivate::normalizedKey(inKey);
1902     QCOMPARE(result, outKey);
1903 
1904     /*
1905         If the key is already normalized, we verify that outKey is
1906         just a shallow copy of the input string. This is an important
1907         optimization that shouldn't be removed accidentally.
1908     */
1909     if (inKey == outKey) {
1910         QVERIFY(!result.isDetached());
1911     } else {
1912         if (!result.isEmpty()) {
1913             QVERIFY(result.isDetached());
1914         }
1915     }
1916 #endif
1917 }
1918 
testEmptyData()1919 void tst_QSettings::testEmptyData()
1920 {
1921     QString filename(QDir::tempPath() + "/empty.ini");
1922     QFile::remove(filename);
1923     QVERIFY(!QFile::exists(filename));
1924 
1925     QString nullString;
1926     QString emptyString("");
1927     QStringList emptyList;
1928     QStringList list;
1929     QStringList list2;
1930 
1931     QVariantList emptyVList;
1932     QVariantList vList, vList2, vList3;
1933 
1934     list << emptyString << nullString;
1935     list2 << emptyString;
1936     vList << emptyString;
1937     vList2 << emptyString << nullString;
1938     vList3 << QString("foo");
1939 
1940     {
1941         QSettings settings(filename, QSettings::IniFormat);
1942         settings.setValue("nullString", nullString);
1943         settings.setValue("emptyString", emptyString);
1944         settings.setValue("emptyList", emptyList);
1945         settings.setValue("list", list);
1946         settings.setValue("list2", list2);
1947         settings.setValue("emptyVList", emptyVList);
1948         settings.setValue("vList", vList);
1949         settings.setValue("vList2", vList2);
1950         settings.setValue("vList3", vList3);
1951         QVERIFY(settings.status() == QSettings::NoError);
1952     }
1953     {
1954         QSettings settings(filename, QSettings::IniFormat);
1955         QCOMPARE(settings.value("nullString").toString(), nullString);
1956         QCOMPARE(settings.value("emptyString").toString(), emptyString);
1957         QCOMPARE(settings.value("emptyList").toStringList(), emptyList);
1958         QCOMPARE(settings.value("list").toStringList(), list);
1959         QCOMPARE(settings.value("list2").toStringList(), list2);
1960         QCOMPARE(settings.value("emptyVList").toList(), emptyVList);
1961         QCOMPARE(settings.value("vList").toList(), vList);
1962         QCOMPARE(settings.value("vList2").toList(), vList2);
1963         QCOMPARE(settings.value("vList3").toList(), vList3);
1964         QVERIFY(settings.status() == QSettings::NoError);
1965     }
1966 
1967     {
1968         QSettings settings("Trolltech", "tst_qsettings");
1969         settings.setValue("nullString", nullString);
1970         settings.setValue("emptyString", emptyString);
1971         settings.setValue("emptyList", emptyList);
1972         settings.setValue("list", list);
1973         settings.setValue("list2", list2);
1974         settings.setValue("emptyVList", emptyVList);
1975         settings.setValue("vList", vList);
1976         settings.setValue("vList2", vList2);
1977         settings.setValue("vList3", vList3);
1978         QVERIFY(settings.status() == QSettings::NoError);
1979     }
1980     {
1981         QSettings settings("Trolltech", "tst_qsettings");
1982         QCOMPARE(settings.value("nullString").toString(), nullString);
1983         QCOMPARE(settings.value("emptyString").toString(), emptyString);
1984         QCOMPARE(settings.value("emptyList").toStringList(), emptyList);
1985         QCOMPARE(settings.value("list").toStringList(), list);
1986         QCOMPARE(settings.value("list2").toStringList(), list2);
1987         QCOMPARE(settings.value("emptyVList").toList(), emptyVList);
1988         QCOMPARE(settings.value("vList").toList(), vList);
1989         QCOMPARE(settings.value("vList2").toList(), vList2);
1990         QCOMPARE(settings.value("vList3").toList(), vList3);
1991         QVERIFY(settings.status() == QSettings::NoError);
1992     }
1993     QFile::remove(filename);
1994 }
1995 
testResourceFiles()1996 void tst_QSettings::testResourceFiles()
1997 {
1998     QSettings settings(":/resourcefile.ini", QSettings::IniFormat);
1999     QVERIFY(settings.status() == QSettings::NoError);
2000     QVERIFY(!settings.isWritable());
2001     QCOMPARE(settings.value("Field 1/Bottom").toInt(), 89);
2002     settings.setValue("Field 1/Bottom", 90);
2003 
2004     // the next two lines check the statu quo; another behavior would be possible
2005     QVERIFY(settings.status() == QSettings::NoError);
2006     QCOMPARE(settings.value("Field 1/Bottom").toInt(), 90);
2007 
2008     settings.sync();
2009     QVERIFY(settings.status() == QSettings::AccessError);
2010     QCOMPARE(settings.value("Field 1/Bottom").toInt(), 90);
2011 }
2012 
fromFile_data()2013 void tst_QSettings::fromFile_data()
2014 {
2015     populateWithFormats();
2016 }
2017 
fromFile()2018 void tst_QSettings::fromFile()
2019 {
2020     QFETCH(QSettings::Format, format);
2021 
2022     QFile::remove("foo");
2023     QVERIFY(!QFile::exists("foo"));
2024 
2025     QString path = "foo";
2026 
2027 #ifdef Q_OS_WIN
2028     if (format == QSettings::NativeFormat)
2029         path = "\\HKEY_CURRENT_USER\\Software\\foo";
2030 #endif
2031 
2032     QStringList strList = QStringList() << "hope" << "destiny" << "chastity";
2033 
2034     {
2035         QSettings settings1(path, format);
2036         QVERIFY(settings1.allKeys().isEmpty());
2037 
2038         settings1.setValue("alpha", 1);
2039         settings1.setValue("alpha", 2);
2040         settings1.setValue("beta", strList);
2041 
2042         QSettings settings2(path, format);
2043         QCOMPARE(settings2.value("alpha").toInt(), 2);
2044 
2045         settings1.sync();
2046 #ifndef Q_OS_WIN
2047         QVERIFY(QFile::exists("foo"));
2048 #endif
2049         QCOMPARE(settings1.value("alpha").toInt(), 2);
2050         QCOMPARE(settings2.value("alpha").toInt(), 2);
2051 
2052         settings2.setValue("alpha", 3);
2053         settings2.setValue("gamma/foo.bar", 4);
2054         QCOMPARE(settings1.value("alpha").toInt(), 3);
2055         QCOMPARE(settings2.value("alpha").toInt(), 3);
2056         QCOMPARE(settings1.value("beta").toStringList(), strList);
2057         QCOMPARE(settings2.value("beta").toStringList(), strList);
2058         QCOMPARE(settings1.value("gamma/foo.bar").toInt(), 4);
2059         QCOMPARE(settings2.value("gamma/foo.bar").toInt(), 4);
2060     }
2061 
2062     {
2063         QSettings settings1(path, format);
2064         QCOMPARE(settings1.value("alpha").toInt(), 3);
2065         QCOMPARE(settings1.value("beta").toStringList(), strList);
2066         QCOMPARE(settings1.value("gamma/foo.bar").toInt(), 4);
2067         QCOMPARE(settings1.allKeys().size(), 3);
2068     }
2069 }
2070 
setIniCodec()2071 void tst_QSettings::setIniCodec()
2072 {
2073 #ifdef QT_BUILD_INTERNAL
2074     QByteArray expeContents4, expeContents5;
2075     QByteArray actualContents4, actualContents5;
2076 
2077     {
2078     QFile inFile(":/resourcefile4.ini");
2079     inFile.open(QIODevice::ReadOnly);
2080     expeContents4 = inFile.readAll();
2081     inFile.close();
2082     }
2083 
2084     {
2085     QFile inFile(":/resourcefile5.ini");
2086     inFile.open(QIODevice::ReadOnly);
2087     expeContents5 = inFile.readAll();
2088     inFile.close();
2089     }
2090 
2091     {
2092     QSettings settings4(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP");
2093     settings4.setIniCodec("UTF-8");
2094     settings4.setValue(QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC"), QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC"));
2095     settings4.sync();
2096 
2097     QSettings settings5(QSettings::IniFormat, QSettings::UserScope, "other.software.org", "KillerAPP");
2098     settings5.setIniCodec("ISO 8859-1");
2099     settings5.setValue(QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC"), QLatin1String("Fa\xe7" "ade/QU\xc9" "BEC"));
2100     settings5.sync();
2101 
2102     {
2103     QFile inFile(settings4.fileName());
2104     inFile.open(QIODevice::ReadOnly);
2105     actualContents4 = inFile.readAll();
2106     inFile.close();
2107     }
2108 
2109     {
2110     QFile inFile(settings5.fileName());
2111     inFile.open(QIODevice::ReadOnly);
2112     actualContents5 = inFile.readAll();
2113     inFile.close();
2114     }
2115     }
2116 
2117     QConfFile::clearCache();
2118 
2119     QCOMPARE(actualContents4, expeContents4);
2120     QCOMPARE(actualContents5, expeContents5);
2121 
2122     QSettings settings4(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP");
2123     settings4.setIniCodec("UTF-8");
2124     QSettings settings5(QSettings::IniFormat, QSettings::UserScope, "other.software.org", "KillerAPP");
2125     settings5.setIniCodec("Latin-1");
2126 
2127     QCOMPARE(settings4.allKeys().count(), 1);
2128     QCOMPARE(settings5.allKeys().count(), 1);
2129 
2130     QCOMPARE(settings4.allKeys().first(), settings5.allKeys().first());
2131     QCOMPARE(settings4.value(settings4.allKeys().first()).toString(),
2132              settings5.value(settings5.allKeys().first()).toString());
2133 #endif
2134 }
2135 
containsSubList(QStringList mom,QStringList son)2136 static bool containsSubList(QStringList mom, QStringList son)
2137 {
2138     for (int i = 0; i < son.size(); ++i) {
2139         if (!mom.contains(son.at(i)))
2140             return false;
2141     }
2142     return true;
2143 }
2144 
testArrays_data()2145 void tst_QSettings::testArrays_data()
2146 {
2147     populateWithFormats();
2148 }
2149 
2150 /*
2151     Tests beginReadArray(), beginWriteArray(), endArray(), and
2152     setArrayIndex().
2153 */
testArrays()2154 void tst_QSettings::testArrays()
2155 {
2156     QFETCH(QSettings::Format, format);
2157 
2158     {
2159         QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP");
2160 
2161         settings1.beginWriteArray("foo/bar", 3);
2162         settings1.setValue("bip", 1);
2163         settings1.setArrayIndex(0);
2164         settings1.setValue("ene", 2);
2165         settings1.setValue("due", 3);
2166         settings1.setValue("rike", 4);
2167         settings1.setArrayIndex(1);
2168         settings1.setValue("ene", 5);
2169         settings1.setValue("due", 6);
2170         settings1.setValue("rike", 7);
2171         settings1.setArrayIndex(2);
2172         settings1.setValue("ene", 8);
2173         settings1.setValue("due", 9);
2174         settings1.setValue("rike", 10);
2175         settings1.endArray();
2176 
2177         QStringList expectedList;
2178         expectedList
2179             << "foo/bar/bip"
2180             << "foo/bar/size"
2181             << "foo/bar/1/ene"
2182             << "foo/bar/1/due"
2183             << "foo/bar/1/rike"
2184             << "foo/bar/2/ene"
2185             << "foo/bar/2/due"
2186             << "foo/bar/2/rike"
2187             << "foo/bar/3/ene"
2188             << "foo/bar/3/due"
2189             << "foo/bar/3/rike";
2190         expectedList.sort();
2191 
2192         QStringList actualList = settings1.allKeys();
2193         actualList.sort();
2194         QVERIFY(containsSubList(actualList, expectedList));
2195 
2196         QCOMPARE(settings1.value("/foo/bar/bip").toInt(), 1);
2197         QCOMPARE(settings1.value("/foo/bar/1/ene").toInt(), 2);
2198         QCOMPARE(settings1.value("/foo/bar/1/due").toInt(), 3);
2199         QCOMPARE(settings1.value("/foo/bar/1/rike").toInt(), 4);
2200         QCOMPARE(settings1.value("/foo/bar/2/ene").toInt(), 5);
2201         QCOMPARE(settings1.value("/foo/bar/2/due").toInt(), 6);
2202         QCOMPARE(settings1.value("/foo/bar/2/rike").toInt(), 7);
2203         QCOMPARE(settings1.value("/foo/bar/3/ene").toInt(), 8);
2204         QCOMPARE(settings1.value("/foo/bar/3/due").toInt(), 9);
2205         QCOMPARE(settings1.value("/foo/bar/3/rike").toInt(), 10);
2206 
2207         settings1.beginGroup("/foo");
2208         int count = settings1.beginReadArray("bar");
2209         QCOMPARE(count, 3);
2210         QCOMPARE(settings1.value("bip").toInt(), 1);
2211         settings1.setArrayIndex(0);
2212         QCOMPARE(settings1.value("ene").toInt(), 2);
2213         QCOMPARE(settings1.value("due").toInt(), 3);
2214         QCOMPARE(settings1.value("rike").toInt(), 4);
2215         QCOMPARE(settings1.allKeys().count(), 3);
2216         settings1.setArrayIndex(1);
2217         QCOMPARE(settings1.value("ene").toInt(), 5);
2218         QCOMPARE(settings1.value("due").toInt(), 6);
2219         QCOMPARE(settings1.value("rike").toInt(), 7);
2220         QCOMPARE(settings1.allKeys().count(), 3);
2221         settings1.setArrayIndex(2);
2222         QCOMPARE(settings1.value("ene").toInt(), 8);
2223         QCOMPARE(settings1.value("due").toInt(), 9);
2224         QCOMPARE(settings1.value("rike").toInt(), 10);
2225         QCOMPARE(settings1.allKeys().count(), 3);
2226 
2227         settings1.endArray();
2228         settings1.endGroup();
2229     }
2230     /*
2231         Check that we get the arrays right when we load them again
2232     */
2233 
2234     {
2235         QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP");
2236 
2237         QStringList expectedList;
2238         expectedList
2239             << "foo/bar/bip"
2240             << "foo/bar/size"
2241             << "foo/bar/1/ene"
2242             << "foo/bar/1/due"
2243             << "foo/bar/1/rike"
2244             << "foo/bar/2/ene"
2245             << "foo/bar/2/due"
2246             << "foo/bar/2/rike"
2247             << "foo/bar/3/ene"
2248             << "foo/bar/3/due"
2249             << "foo/bar/3/rike";
2250         expectedList.sort();
2251 
2252         QStringList actualList = settings1.allKeys();
2253         actualList.sort();
2254         QVERIFY(containsSubList(actualList, expectedList));
2255 
2256         QCOMPARE(settings1.value("/foo/bar/bip").toInt(), 1);
2257         QCOMPARE(settings1.value("/foo/bar/1/ene").toInt(), 2);
2258         QCOMPARE(settings1.value("/foo/bar/1/due").toInt(), 3);
2259         QCOMPARE(settings1.value("/foo/bar/1/rike").toInt(), 4);
2260         QCOMPARE(settings1.value("/foo/bar/2/ene").toInt(), 5);
2261         QCOMPARE(settings1.value("/foo/bar/2/due").toInt(), 6);
2262         QCOMPARE(settings1.value("/foo/bar/2/rike").toInt(), 7);
2263         QCOMPARE(settings1.value("/foo/bar/3/ene").toInt(), 8);
2264         QCOMPARE(settings1.value("/foo/bar/3/due").toInt(), 9);
2265         QCOMPARE(settings1.value("/foo/bar/3/rike").toInt(), 10);
2266 
2267         settings1.beginGroup("/foo");
2268         int count = settings1.beginReadArray("bar");
2269         QCOMPARE(count, 3);
2270         QCOMPARE(settings1.value("bip").toInt(), 1);
2271         settings1.setArrayIndex(0);
2272         QCOMPARE(settings1.value("ene").toInt(), 2);
2273         QCOMPARE(settings1.value("due").toInt(), 3);
2274         QCOMPARE(settings1.value("rike").toInt(), 4);
2275         QCOMPARE(settings1.allKeys().count(), 3);
2276         settings1.setArrayIndex(1);
2277         QCOMPARE(settings1.value("ene").toInt(), 5);
2278         QCOMPARE(settings1.value("due").toInt(), 6);
2279         QCOMPARE(settings1.value("rike").toInt(), 7);
2280         QCOMPARE(settings1.allKeys().count(), 3);
2281         settings1.setArrayIndex(2);
2282         QCOMPARE(settings1.value("ene").toInt(), 8);
2283         QCOMPARE(settings1.value("due").toInt(), 9);
2284         QCOMPARE(settings1.value("rike").toInt(), 10);
2285         QCOMPARE(settings1.allKeys().count(), 3);
2286 
2287         settings1.endArray();
2288         settings1.endGroup();
2289     }
2290     /*
2291         This code generates lots of warnings, but that's on purpose.
2292         Basically, we check that endGroup() can be used instead of
2293         endArray() and vice versa. This is not documented, but this
2294         is the behavior that we have chosen.
2295     */
2296     QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP");
2297     settings1.clear();
2298     settings1.beginGroup("/alpha");
2299     QCOMPARE(settings1.group(), QString("alpha"));
2300     settings1.setArrayIndex(0);
2301     QCOMPARE(settings1.group(), QString("alpha"));
2302     settings1.setArrayIndex(1);
2303     QCOMPARE(settings1.group(), QString("alpha"));
2304     settings1.setArrayIndex(2);
2305     QCOMPARE(settings1.group(), QString("alpha"));
2306     settings1.beginGroup("/beta");
2307     QCOMPARE(settings1.group(), QString("alpha/beta"));
2308     settings1.beginGroup("");
2309     QCOMPARE(settings1.group(), QString("alpha/beta"));
2310     settings1.beginWriteArray("DO", 4);
2311     QCOMPARE(settings1.value("size").toInt(), 4);
2312     QCOMPARE(settings1.group(), QString("alpha/beta/DO"));
2313     settings1.setArrayIndex(0);
2314     QCOMPARE(settings1.group(), QString("alpha/beta/DO/1"));
2315     settings1.setArrayIndex(1);
2316     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2"));
2317     settings1.beginGroup("1");
2318     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1"));
2319     settings1.setArrayIndex(3);
2320     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1"));
2321     settings1.setArrayIndex(4);
2322     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1"));
2323     settings1.beginWriteArray("RE");
2324     QVERIFY(!settings1.contains("size"));
2325     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1/RE"));
2326     settings1.setArrayIndex(0);
2327     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1/RE/1"));
2328     settings1.setArrayIndex(1);
2329     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1/RE/2"));
2330     settings1.endArray();
2331     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2/1"));
2332     settings1.endArray();
2333     QCOMPARE(settings1.group(), QString("alpha/beta/DO/2"));
2334     settings1.setArrayIndex(2);
2335     QCOMPARE(settings1.group(), QString("alpha/beta/DO/3"));
2336     settings1.endGroup();
2337     QCOMPARE(settings1.group(), QString("alpha/beta"));
2338     settings1.endGroup();
2339     QCOMPARE(settings1.group(), QString("alpha/beta"));
2340     settings1.endGroup();
2341     QCOMPARE(settings1.group(), QString("alpha"));
2342     settings1.endArray();
2343     QCOMPARE(settings1.group(), QString());
2344     settings1.endGroup();
2345     QCOMPARE(settings1.group(), QString());
2346 
2347     /*
2348         Now, let's make sure that things work well if an array
2349         is spread across multiple files.
2350     */
2351     int i;
2352 
2353     settings1.clear();
2354     QSettings settings2(format, QSettings::UserScope, "software.org");
2355 
2356     QStringList threeStrings;
2357     threeStrings << "Uno" << "Dos" << "Tres";
2358 
2359     QStringList fiveStrings;
2360     fiveStrings << "alpha" << "beta" << "gamma" << "delta" << "epsilon";
2361 
2362     settings1.beginWriteArray("strings");
2363     for (i = threeStrings.size() - 1; i >= 0; --i) {
2364         settings1.setArrayIndex(i);
2365         settings1.setValue("fileName", threeStrings.at(i));
2366     }
2367     settings1.endArray();
2368 
2369     settings2.beginWriteArray("strings");
2370     for (i = fiveStrings.size() - 1; i >= 0; --i) {
2371         settings2.setArrayIndex(i);
2372         settings2.setValue("fileName", fiveStrings.at(i));
2373     }
2374     settings2.endArray();
2375 
2376     int size1 = settings1.beginReadArray("strings");
2377     QCOMPARE(size1, 3);
2378     QCOMPARE(settings1.value("size").toInt(), 3);
2379 
2380     for (i = 0; i < size1; ++i) {
2381         settings1.setArrayIndex(i);
2382         QString str = settings1.value("fileName").toString();
2383         QCOMPARE(str, threeStrings.at(i));
2384     }
2385     settings1.endArray();
2386 
2387     int size2 = settings2.beginReadArray("strings");
2388     QCOMPARE(size2, 5);
2389     QCOMPARE(settings2.value("size").toInt(), 5);
2390 
2391     for (i = 0; i < size2; ++i) {
2392         settings2.setArrayIndex(i);
2393         QString str = settings2.value("fileName").toString();
2394         QCOMPARE(str, fiveStrings.at(i));
2395     }
2396     settings2.endArray();
2397 
2398 #if !defined (Q_OS_BLACKBERRY)
2399     size1 = settings1.beginReadArray("strings");
2400     QCOMPARE(size1, 3);
2401 
2402     // accessing entries beyond the end of settings1 goes to settings2
2403     for (i = size1; i < size2; ++i) {
2404         settings1.setArrayIndex(i);
2405         QString str = settings1.value("fileName").toString();
2406         QCOMPARE(str, fiveStrings.at(i));
2407     }
2408     settings1.endArray();
2409 #endif
2410 }
2411 
2412 #ifdef QT_BUILD_INTERNAL
iniEscapedKey(const QString & str)2413 static QByteArray iniEscapedKey(const QString &str)
2414 {
2415     QByteArray result;
2416     QSettingsPrivate::iniEscapedKey(str, result);
2417     return result;
2418 }
2419 
iniUnescapedKey(const QByteArray & ba)2420 static QString iniUnescapedKey(const QByteArray &ba)
2421 {
2422     QString result;
2423     QSettingsPrivate::iniUnescapedKey(ba, 0, ba.size(), result);
2424     return result;
2425 }
2426 
iniEscapedStringList(const QStringList & strList)2427 static QByteArray iniEscapedStringList(const QStringList &strList)
2428 {
2429     QByteArray result;
2430     QSettingsPrivate::iniEscapedStringList(strList, result, 0);
2431     return result;
2432 }
2433 
iniUnescapedStringList(const QByteArray & ba)2434 static QStringList iniUnescapedStringList(const QByteArray &ba)
2435 {
2436     QStringList result;
2437     QString str;
2438 #if QSETTINGS_P_H_VERSION >= 2
2439     bool isStringList = QSettingsPrivate::iniUnescapedStringList(ba, 0, ba.size(), str, result
2440 #if QSETTINGS_P_H_VERSION >= 3
2441                                                                  , 0
2442 #endif
2443                                                                     );
2444     if (!isStringList)
2445         result = QStringList(str);
2446 #else
2447     QStringList *strList = QSettingsPrivate::iniUnescapedStringList(ba, 0, ba.size(), str);
2448     if (strList) {
2449         result = *strList;
2450         delete strList;
2451     } else {
2452         result = QStringList(str);
2453     }
2454 #endif
2455     return result;
2456 }
2457 #endif
2458 
escapeWeirdChars(const QString & s)2459 QString escapeWeirdChars(const QString &s)
2460 {
2461     QString result;
2462     bool escapeNextDigit = false;
2463 
2464     for (int i = 0; i < s.length(); ++i) {
2465         QChar c = s.at(i);
2466         if (c.unicode() < ' ' || c.unicode() > '~'
2467             || (escapeNextDigit && c.unicode() >= '0' && c.unicode() <= 'f')) {
2468             result += QString("\\x%1").arg(c.unicode(), 0, 16);
2469             escapeNextDigit = true;
2470         } else {
2471             result += c;
2472             escapeNextDigit = false;
2473         }
2474     }
2475 
2476     return result;
2477 }
2478 
testEscapes()2479 void tst_QSettings::testEscapes()
2480 {
2481 #ifdef QT_BUILD_INTERNAL
2482     QSettings settings(QSettings::UserScope, "software.org", "KillerAPP");
2483 
2484 #define testEscapedKey(plainKey, escKey) \
2485     QCOMPARE(iniEscapedKey(plainKey), QByteArray(escKey)); \
2486     QCOMPARE(iniUnescapedKey(escKey), QString(plainKey));
2487 
2488 #define testUnescapedKey(escKey, plainKey, reescKey) \
2489     QCOMPARE(iniUnescapedKey(escKey), QString(plainKey)); \
2490     QCOMPARE(iniEscapedKey(plainKey), QByteArray(reescKey)); \
2491     QCOMPARE(iniUnescapedKey(reescKey), QString(plainKey));
2492 
2493 #define testEscapedStringList(plainStrList, escStrList) \
2494     { \
2495         QStringList plainList(plainStrList); \
2496         QByteArray escList(escStrList); \
2497         QCOMPARE(iniEscapedStringList(plainList), escList); \
2498         QCOMPARE(iniUnescapedStringList(escList), plainList); \
2499     } \
2500 
2501 
2502 #define testUnescapedStringList(escStrList, plainStrList, reescStrList) \
2503     { \
2504         QStringList plainList(plainStrList); \
2505         QByteArray escList(escStrList); \
2506         QByteArray reescList(reescStrList); \
2507         QCOMPARE(iniUnescapedStringList(escList), plainList); \
2508         QCOMPARE(iniEscapedStringList(plainList), reescList); \
2509         QCOMPARE(iniUnescapedStringList(reescList), plainList); \
2510     } \
2511 
2512 
2513 #define testVariant(val, escStr, func) \
2514     { \
2515         QVariant v(val); \
2516         QString s = QSettingsPrivate::variantToString(v); \
2517         /*qDebug() << QString("testVariant(): reference=\"%1\" result=\"%2\"").arg(escStr).arg(s); */\
2518         QCOMPARE(s, escStr); \
2519         QCOMPARE(QVariant(QSettingsPrivate::stringToVariant(escStr)), v); \
2520         QVERIFY(val == v.func()); \
2521     }
2522 
2523 #define testBadEscape(escStr, vStr) \
2524     { \
2525         QVariant v = QSettingsPrivate::stringToVariant(QString(escStr)); \
2526         QCOMPARE(v.toString(), QString(vStr)); \
2527     }
2528 
2529     testEscapedKey("", "");
2530     testEscapedKey(" ", "%20");
2531     testEscapedKey(" 0123 abcd ", "%200123%20abcd%20");
2532     testEscapedKey("~!@#$%^&*()_+.-/\\=", "%7E%21%40%23%24%25%5E%26%2A%28%29_%2B.-\\%5C%3D");
2533     testEscapedKey(QString() + QChar(0xabcd) + QChar(0x1234) + QChar(0x0081), "%UABCD%U1234%81");
2534     testEscapedKey(QString() + QChar(0xFE) + QChar(0xFF) + QChar(0x100) + QChar(0x101), "%FE%FF%U0100%U0101");
2535 
2536     testUnescapedKey("", "", "");
2537     testUnescapedKey("%20", " ", "%20");
2538     testUnescapedKey("/alpha/beta", "/alpha/beta", "\\alpha\\beta");
2539     testUnescapedKey("\\alpha\\beta", "/alpha/beta", "\\alpha\\beta");
2540     testUnescapedKey("%5Calpha%5Cbeta", "\\alpha\\beta", "%5Calpha%5Cbeta");
2541     testUnescapedKey("%", "%", "%25");
2542     testUnescapedKey("%f%!%%%%1x%x1%U%Uz%U123%U1234%1234%", QString("%f%!%%%%1x%x1%U%Uz%U123") + QChar(0x1234) + "\x12" + "34%",
2543                      "%25f%25%21%25%25%25%251x%25x1%25U%25Uz%25U123%U1234%1234%25");
2544 
2545     testEscapedStringList("", "");
2546     testEscapedStringList(" ", "\" \"");
2547     testEscapedStringList(";", "\";\"");
2548     testEscapedStringList(",", "\",\"");
2549     testEscapedStringList("=", "\"=\"");
2550     testEscapedStringList("abc-def", "abc-def");
2551     testEscapedStringList(QChar(0) + QString("0"), "\\0\\x30");
2552     testEscapedStringList("~!@#$%^&*()_+.-/\\=", "\"~!@#$%^&*()_+.-/\\\\=\"");
2553     testEscapedStringList("~!@#$%^&*()_+.-/\\", "~!@#$%^&*()_+.-/\\\\");
2554     testEscapedStringList(QString("\x7F") + "12aFz", "\\x7f\\x31\\x32\\x61\\x46z");
2555     testEscapedStringList(QString("   \t\n\\n") + QChar(0x123) + QChar(0x4567), "\"   \\t\\n\\\\n\\x123\\x4567\"");
2556     testEscapedStringList(QString("\a\b\f\n\r\t\v'\"?\001\002\x03\x04"), "\\a\\b\\f\\n\\r\\t\\v'\\\"?\\x1\\x2\\x3\\x4");
2557     testEscapedStringList(QStringList() << "," << ";" << "a" << "ab,  \tc, d ", "\",\", \";\", a, \"ab,  \\tc, d \"");
2558 
2559     /*
2560       Test .ini syntax that cannot be generated by QSettings (but can be entered by users).
2561     */
2562     testUnescapedStringList("", "", "");
2563     testUnescapedStringList("\"\"", "", "");
2564     testUnescapedStringList("\"abcdef\"", "abcdef", "abcdef");
2565     testUnescapedStringList("\"\\?\\'\\\"\"", "?'\"", "?'\\\"");
2566     testUnescapedStringList("\\0\\00\\000\\0000000\\1\\111\\11111\\x\\x0\\xABCDEFGH\\x0123456\\",
2567                             QString() + QChar(0) + QChar(0) + QChar(0) + QChar(0) + QChar(1)
2568                             + QChar(0111) + QChar(011111) + QChar(0) + QChar(0xCDEF) + "GH"
2569                             + QChar(0x3456),
2570                             "\\0\\0\\0\\0\\x1I\\x1249\\0\\xcdefGH\\x3456");
2571     testUnescapedStringList(QByteArray("\\c\\d\\e\\f\\g\\$\\*\\\0", 16), "\f", "\\f");
2572     testUnescapedStringList("\"a\",  \t\"bc \", \"  d\" , \"ef  \" ,,g,   hi  i,,, ,",
2573                             QStringList() << "a" << "bc " << "  d" << "ef  " << "" << "g" << "hi  i"
2574                                           << "" << "" << "" << "",
2575                             "a, \"bc \", \"  d\", \"ef  \", , g, hi  i, , , , ");
2576     testUnescapedStringList("a ,  b   ,   c   d   , efg   ",
2577                             QStringList() << "a" << "b" << "c   d" << "efg",
2578                             "a, b, c   d, efg");
2579 
2580     // streaming qvariant into a string
2581     testVariant(QString("Hello World!"), QString("Hello World!"), toString);
2582     testVariant(QString("Hello, World!"), QString("Hello, World!"), toString);
2583     testVariant(QString("@Hello World!"), QString("@@Hello World!"), toString);
2584     testVariant(QString("@@Hello World!"), QString("@@@Hello World!"), toString);
2585     testVariant(QByteArray("Hello World!"), QString("@ByteArray(Hello World!)"), toString);
2586     testVariant(QByteArray("@Hello World!"), QString("@ByteArray(@Hello World!)"), toString);
2587     testVariant(QVariant(100), QString("100"), toString);
2588     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);
2589     testVariant(QRect(1, 2, 3, 4), QString("@Rect(1 2 3 4)"), toRect);
2590     testVariant(QSize(5, 6), QString("@Size(5 6)"), toSize);
2591     testVariant(QPoint(7, 8), QString("@Point(7 8)"), toPoint);
2592 
2593     testBadEscape("", "");
2594     testBadEscape("@", "@");
2595     testBadEscape("@@", "@");
2596     testBadEscape("@@@", "@@");
2597     testBadEscape(" ", " ");
2598     testBadEscape("@Rect", "@Rect");
2599     testBadEscape("@Rect(", "@Rect(");
2600     testBadEscape("@Rect()", "@Rect()");
2601     testBadEscape("@Rect)", "@Rect)");
2602     testBadEscape("@Rect(1 2 3)", "@Rect(1 2 3)");
2603     testBadEscape("@@Rect(1 2 3)", "@Rect(1 2 3)");
2604 #endif
2605 }
2606 
testCompatFunctions()2607 void tst_QSettings::testCompatFunctions()
2608 {
2609 #ifdef QT3_SUPPORT
2610     QSettings settings1("software.org", "KillerAPP");
2611 
2612     bool ok;
2613     ok = settings1.writeEntry("/root/bool", true);
2614     QVERIFY(ok);
2615     ok = settings1.writeEntry("/root/double", 1.4);
2616     QVERIFY(ok);
2617     ok = settings1.writeEntry("/root/int", 66666);
2618     QVERIFY(ok);
2619     ok = settings1.writeEntry("/root/const char */1", "Hello");
2620     QVERIFY(ok);
2621     ok = settings1.writeEntry("/root/const char */2", "");
2622     QVERIFY(ok);
2623     ok = settings1.writeEntry("/root/const char */3", (const char *)0);
2624     QVERIFY(ok);
2625     ok = settings1.writeEntry("/root/QString/1", QString("Hello"));
2626     QVERIFY(ok);
2627     ok = settings1.writeEntry("/root/QString/2", QString(""));
2628     QVERIFY(ok);
2629     ok = settings1.writeEntry("/root/QString/3", QString());
2630     QVERIFY(ok);
2631     ok = settings1.writeEntry("/root/QStringList/1", QStringList());
2632     QVERIFY(ok);
2633     ok = settings1.writeEntry("/root/QStringList/2", QStringList() << "");
2634     QVERIFY(ok);
2635     ok = settings1.writeEntry("/root/QStringList/3", QStringList() << "a" << "" << "b");
2636     QVERIFY(ok);
2637     ok = settings1.writeEntry("/root/QStringList/4", QStringList() << "a" << "" << "b", ':');
2638     QVERIFY(ok);
2639 
2640     QCOMPARE(settings1.readBoolEntry("/root/bool"), true);
2641     QCOMPARE(settings1.readDoubleEntry("/root/double"), 1.4);
2642     QCOMPARE(settings1.readNumEntry("/root/int"), 66666);
2643     QCOMPARE(settings1.readEntry("/root/const char */1"), QString("Hello"));
2644     QCOMPARE(settings1.readEntry("/root/const char */2"), QString(""));
2645     QCOMPARE(settings1.readEntry("/root/const char */3"), QString());
2646     QCOMPARE(settings1.readEntry("/root/QString/1"), QString("Hello"));
2647     QCOMPARE(settings1.readEntry("/root/QString/2"), QString(""));
2648     QCOMPARE(settings1.readEntry("/root/QString/3"), QString());
2649     QCOMPARE(settings1.readListEntry("/root/QStringList/1"), QStringList());
2650     QCOMPARE(settings1.readListEntry("/root/QStringList/2"), QStringList() << "");
2651     QCOMPARE(settings1.readListEntry("/root/QStringList/3"), QStringList() << "a" << "" << "b");
2652     QCOMPARE(settings1.readListEntry("/root/QStringList/4", ':'), QStringList() << "a" << "" << "b");
2653     QCOMPARE(settings1.readEntry("/root/QStringList/4"), QString("a::b"));
2654 
2655     QStringList actual, expectedSubKey, expectedEntry;
2656 
2657     settings1.clear();
2658     QStringList initialKeys = settings1.allKeys();
2659     settings1.setValue("/alpha/beta", 5);
2660     settings1.setValue("/alpha/beta/gamma", 5);
2661     settings1.setValue("/alpha/beta/delta", 5);
2662     settings1.setValue("/alpha/epsilon/zeta/eta", 5);
2663     settings1.setValue("/alpha/theta", 5);
2664 
2665     settings1.beginGroup("/alpha");
2666     QCOMPARE(settings1.group(), QString("alpha"));
2667 
2668     actual = settings1.entryList("");
2669     actual.sort();
2670     expectedEntry = QStringList() << "beta" << "theta";
2671     QCOMPARE(actual, expectedEntry);
2672 
2673     actual = settings1.subkeyList("");
2674     actual.sort();
2675     expectedSubKey = QStringList() << "beta" << "epsilon";
2676     QCOMPARE(actual, expectedSubKey);
2677 
2678     settings1.endGroup();
2679 
2680     actual = settings1.entryList("alpha");
2681     actual.sort();
2682     QCOMPARE(actual, expectedEntry);
2683 
2684     actual = settings1.subkeyList("alpha");
2685     actual.sort();
2686     QCOMPARE(actual, expectedSubKey);
2687 
2688     actual = settings1.entryList("");
2689     QVERIFY(containsSubList(initialKeys, actual));
2690 
2691     actual = settings1.subkeyList("");
2692     QVERIFY(actual.contains("alpha"));
2693 
2694     actual = settings1.subkeyList("foo/bar/baz");
2695     QVERIFY(actual.isEmpty());
2696 
2697     actual = settings1.subkeyList("alpha/epsilon");
2698     expectedSubKey = QStringList() << "zeta";
2699     QCOMPARE(actual, expectedSubKey);
2700 #else
2701     QSKIP("Compiled without Qt3Support", SkipAll);
2702 #endif
2703 }
2704 
testCaseSensitivity_data()2705 void tst_QSettings::testCaseSensitivity_data()
2706 {
2707     populateWithFormats();
2708 }
2709 
testCaseSensitivity()2710 void tst_QSettings::testCaseSensitivity()
2711 {
2712     QFETCH(QSettings::Format, format);
2713 
2714     for (int pass = 0; pass < 2; ++pass) {
2715         QSettings settings(format, QSettings::UserScope, "software.org", "KillerAPP");
2716         settings.beginGroup("caseSensitivity");
2717 
2718         bool cs = true;
2719 #ifndef QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
2720         switch (format) {
2721         case QSettings::NativeFormat:
2722 #ifdef Q_OS_DARWIN
2723             cs = true;
2724 #else
2725             cs = false;
2726 #endif
2727             break;
2728         case QSettings::IniFormat:
2729             cs = false;
2730             break;
2731         case QSettings::CustomFormat1:
2732             cs = true;
2733             break;
2734         case QSettings::CustomFormat2:
2735             cs = false;
2736             break;
2737         default:
2738             ;
2739         }
2740 #endif
2741 
2742         if (pass == 0) {
2743             settings.setValue("key 1", 1);
2744             settings.setValue("KEY 1", 2);
2745             settings.setValue("key 2", 3);
2746         }
2747 
2748         for (int i = 0; i < 2; ++i) {
2749             QVERIFY(settings.contains("key 1"));
2750             QVERIFY(settings.contains("KEY 1"));
2751             QCOMPARE(settings.value("KEY 1").toInt(), 2);
2752 /*            QVERIFY(settings.allKeys().contains("/KEY 1"));
2753             QVERIFY(settings.allKeys().contains("/key 2")); */
2754 
2755             if (cs) {
2756                 QVERIFY(!settings.contains("kEy 1"));
2757                 QCOMPARE(settings.value("key 1").toInt(), 1);
2758                 QCOMPARE(settings.allKeys().size(), 3);
2759                 QVERIFY(settings.allKeys().contains("key 1"));
2760             } else {
2761                 QVERIFY(settings.contains("kEy 1"));
2762                 QCOMPARE(settings.value("kEy 1").toInt(), 2);
2763                 QCOMPARE(settings.value("key 1").toInt(), 2);
2764                 QCOMPARE(settings.allKeys().size(), 2);
2765             }
2766 
2767             settings.sync();
2768         }
2769 
2770         settings.remove("KeY 1");
2771 
2772         if (cs) {
2773             QVERIFY(!settings.contains("KeY 1"));
2774             QVERIFY(settings.contains("key 1"));
2775             QVERIFY(settings.contains("KEY 1"));
2776             QCOMPARE(settings.value("key 1").toInt(), 1);
2777             QCOMPARE(settings.value("KEY 1").toInt(), 2);
2778             QCOMPARE(settings.allKeys().size(), 3);
2779         } else {
2780             QVERIFY(!settings.contains("KeY 1"));
2781             QVERIFY(!settings.contains("key 1"));
2782             QVERIFY(!settings.contains("KEY 1"));
2783             QCOMPARE(settings.allKeys().size(), 1);
2784         }
2785         settings.setValue("KEY 1", 2);
2786     }
2787 }
2788 
2789 #ifdef QT3_SUPPORT
oldEntryList_data()2790 void tst_QSettings::oldEntryList_data()
2791 {
2792     oldWriteEntry_data();
2793 }
2794 
oldReadEntryIni_data()2795 void tst_QSettings::oldReadEntryIni_data()
2796 {
2797     oldWriteEntry_data();
2798 }
2799 
oldWriteEntryIni_data()2800 void tst_QSettings::oldWriteEntryIni_data()
2801 {
2802     oldWriteEntry_data();
2803 }
2804 
oldReadEntry_data()2805 void tst_QSettings::oldReadEntry_data()
2806 {
2807     oldWriteEntry_data();
2808 }
2809 
oldWriteEntry_data()2810 void tst_QSettings::oldWriteEntry_data()
2811 {
2812     // define the test elements we're going to use
2813     QTest::addColumn<QString>("string");
2814     QTest::addColumn<QString>("empty");
2815     QTest::addColumn<QString>("unicode");
2816     QTest::addColumn<int>("integer");
2817     QTest::addColumn<bool>("boolean");
2818     QTest::addColumn<double>("floating");
2819     QTest::addColumn<QStringList>("list");
2820 
2821     QStringList list0;
2822     list0 << "elem1";
2823     list0 << "elem2";
2824     list0 << "elem3";
2825     list0 << "elem4";
2826 
2827     QTest::newRow( "data0") << QString("blah") << QString("") << QString( QChar(0x0E12) ) << 99 << TRUE << 3.1415 << list0;
2828 
2829     QStringList list1;
2830     list1 << " elem1";
2831     list1 << "elem2 ";
2832     list1 << QString();
2833     list1 << "";
2834     list1 << "elem3";
2835     QTest::newRow( "data1") << QString("foo") << QString("") << QString( QChar(0xFEFC) ) << -150 << FALSE << 0.0 << list1;
2836 }
2837 
oldWriteEntryHelper(QSettings & settings)2838 void tst_QSettings::oldWriteEntryHelper( QSettings &settings )
2839 {
2840     QFETCH( QString, string );
2841     QFETCH( QString, empty );
2842     QFETCH( QString, unicode );
2843     QFETCH( int, integer );
2844     QFETCH( bool, boolean );
2845     QFETCH( double, floating );
2846     QFETCH( QStringList, list );
2847 
2848     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting", string ) );
2849     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/String", string ) );
2850     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/Empty", empty ) );
2851     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/Unicode", unicode ) );
2852     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/Integer", integer ) );
2853     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/Boolean", boolean ) );
2854     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/Floating", floating ) );
2855     QVERIFY( settings.writeEntry( "/Trolltech/QSettingsTesting/List", list ) );
2856 }
2857 
oldReadEntryHelper(QSettings & settings)2858 void tst_QSettings::oldReadEntryHelper( QSettings &settings )
2859 {
2860     bool ok;
2861 
2862     QFETCH( QString, string );
2863     QFETCH( QString, empty );
2864     QFETCH( QString, unicode );
2865     QFETCH( int, integer );
2866     QFETCH( bool, boolean );
2867     QFETCH( double, floating );
2868     QFETCH( QStringList, list );
2869 
2870     QCOMPARE( settings.readEntry( "/Trolltech/QSettingsTesting", QString::null, &ok ), string );
2871     QVERIFY( ok );
2872     QCOMPARE( settings.readEntry( "/Trolltech/QSettingsTesting/String", QString::null, &ok ), string );
2873     QVERIFY( ok );
2874     QCOMPARE( settings.readEntry( "/Trolltech/QSettingsTesting/Empty", QString::null, &ok ), empty );
2875     QVERIFY( ok );
2876     QCOMPARE( settings.readEntry( "/Trolltech/QSettingsTesting/Unicode", QString::null, &ok ), unicode );
2877     QVERIFY( ok );
2878     QCOMPARE( settings.readNumEntry( "/Trolltech/QSettingsTesting/Integer", 0, &ok ), integer );
2879     QVERIFY( ok );
2880     QCOMPARE( settings.readBoolEntry( "/Trolltech/QSettingsTesting/Boolean", 0, &ok ), boolean );
2881     QVERIFY( ok );
2882     QCOMPARE( settings.readDoubleEntry( "/Trolltech/QSettingsTesting/Floating", 0, &ok ), floating );
2883     QVERIFY( ok );
2884     QCOMPARE( settings.readListEntry( "/Trolltech/QSettingsTesting/List", &ok ), list );
2885     QVERIFY( ok );
2886 
2887     settings.readListEntry( "/Trolltech/QSettingsTesting/NonExistingValue", &ok );
2888     QVERIFY( !ok );
2889 }
2890 
oldWriteEntryIni()2891 void tst_QSettings::oldWriteEntryIni()
2892 {
2893     QSettings settings(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP");
2894     oldWriteEntryHelper(settings);
2895 }
2896 
oldReadEntryIni()2897 void tst_QSettings::oldReadEntryIni()
2898 {
2899     {
2900 	QSettings writeSettings(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP");
2901 	oldWriteEntryHelper( writeSettings );
2902     }
2903     {
2904 	QSettings readSettings(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP");
2905 	oldReadEntryHelper( readSettings );
2906     }
2907 }
2908 
2909 
oldEndGroup_data()2910 void tst_QSettings::oldEndGroup_data()
2911 {
2912     oldBeginGroup_data();
2913 }
2914 
oldResetGroup_data()2915 void tst_QSettings::oldResetGroup_data()
2916 {
2917     oldBeginGroup_data();
2918 }
2919 
oldBeginGroup_data()2920 void tst_QSettings::oldBeginGroup_data()
2921 {
2922     // define the test elements we're going to use
2923     QTest::addColumn<QString>("group");
2924     QTest::addColumn<QString>("value");
2925 
2926     QTest::newRow( "data0") << QString("blah") << "value";
2927     QTest::newRow( "data1") << QString("") << "first/value";
2928     QTest::newRow( "data2") << QString("first/second") << "value";
2929     QTest::newRow( "data3") << QString("first/second/third") << "value";
2930     QTest::newRow( "data4") << QString("first/second/third") << "value";
2931 }
2932 
oldBeginGroup()2933 void tst_QSettings::oldBeginGroup()
2934 {
2935     bool ok;
2936 
2937     QFETCH( QString, group );
2938     QFETCH( QString, value );
2939 
2940     QSettings settings("software.org", "KillerAPP");
2941 
2942     QCOMPARE(settings.group(), QString());
2943     settings.beginGroup( group );
2944     QCOMPARE(settings.group(), group);
2945 
2946     QVERIFY( settings.writeEntry( "/" + value, value ) );
2947     QCOMPARE( settings.readEntry( "/" + value ), value );
2948     settings.endGroup();
2949     QCOMPARE( settings.readEntry( group + "/" + value, QString::null, &ok ), value );
2950     QVERIFY( ok );
2951 }
2952 
oldEndGroup()2953 void tst_QSettings::oldEndGroup()
2954 {
2955     QFETCH( QString, group );
2956 
2957     QSettings settings("software.org", "KillerAPP");
2958     QCOMPARE( settings.group(), QString() );
2959 
2960     settings.beginGroup( group );
2961     settings.endGroup();
2962     QCOMPARE( settings.group(), QString() );
2963 
2964     settings.beginGroup( group );
2965     settings.beginGroup( group );
2966     settings.endGroup();
2967     QCOMPARE( settings.group(), group );
2968     settings.endGroup();
2969     QCOMPARE( settings.group(), QString() );
2970 
2971     QTest::ignoreMessage(QtWarningMsg, "QSettings::endGroup: No matching beginGroup()");
2972     settings.endGroup();
2973     QCOMPARE( settings.group(), QString() );
2974 }
2975 
oldResetGroup()2976 void tst_QSettings::oldResetGroup()
2977 {
2978     QFETCH( QString, group );
2979 
2980     QSettings settings("software.org", "KillerAPP");
2981     settings.beginGroup( group );
2982 
2983     settings.resetGroup();
2984     QCOMPARE( settings.group(), QString() );
2985 }
2986 
oldEntryList()2987 void tst_QSettings::oldEntryList()
2988 {
2989     {
2990 	QSettings writeSettings("software.org", "KillerAPP");
2991 	oldWriteEntryHelper( writeSettings );
2992     }
2993 
2994     QStringList entryKeys;
2995     entryKeys << "String" << "Empty" << "Unicode" << "Integer" << "Boolean" << "Floating" << "List";
2996 
2997     QSettings readSettings("software.org", "KillerAPP");
2998     QStringList entryList = readSettings.entryList( "/Trolltech/QSettingsTesting/" );
2999     entryKeys.sort();
3000     entryList.sort();
3001     QCOMPARE( entryKeys, entryList );
3002 }
3003 
oldWriteEntry_QString_bool_data()3004 void tst_QSettings::oldWriteEntry_QString_bool_data()
3005 {
3006     QTest::addColumn<bool>("b");
3007     QTest::newRow( "false" ) << bool(FALSE);
3008     QTest::newRow( "true" ) << bool(TRUE);
3009 }
3010 
oldWriteEntry_QString_bool()3011 void tst_QSettings::oldWriteEntry_QString_bool()
3012 {
3013     {
3014 	QSettings writeSettings("software.org", "KillerAPP");
3015 	QFETCH( bool, b );
3016 	QVERIFY( writeSettings.writeEntry( "/Trolltech/QSettingsTesting/Boolean", b ) );
3017     }
3018 
3019     {
3020 	QSettings readSettings("software.org", "KillerAPP");
3021 	QFETCH( bool, b );
3022 	bool ok = FALSE;
3023 	QCOMPARE( readSettings.readBoolEntry( "/Trolltech/QSettingsTesting/Boolean", 0, &ok ), b );
3024 	QVERIFY( ok );
3025     }
3026 }
3027 
oldWriteEntry_QString_double_data()3028 void tst_QSettings::oldWriteEntry_QString_double_data()
3029 {
3030     QTest::addColumn<double>("f");
3031     QTest::newRow( "data0" ) << 3.1415;
3032     QTest::newRow( "data1" ) << 0.0;
3033     QTest::newRow( "data2" ) << 0.0000000000000000000000000001;
3034 }
3035 
oldWriteEntry_QString_double()3036 void tst_QSettings::oldWriteEntry_QString_double()
3037 {
3038     {
3039 	QSettings writeSettings("software.org", "KillerAPP");
3040 	QFETCH( double, f );
3041 	QVERIFY( writeSettings.writeEntry( "/Trolltech/QSettingsTesting/Floating", f ) );
3042     }
3043     {
3044 	QSettings readSettings("software.org", "KillerAPP");
3045 	QFETCH( double, f );
3046 	bool ok = FALSE;
3047 	QCOMPARE( readSettings.readDoubleEntry( "/Trolltech/QSettingsTesting/Floating", 0, &ok ), f );
3048 	QVERIFY( ok );
3049     }
3050 }
3051 
oldWriteEntry_QString_int_data()3052 void tst_QSettings::oldWriteEntry_QString_int_data()
3053 {
3054     QTest::addColumn<int>("i");
3055     QTest::newRow( "data0" ) << int(0);
3056     QTest::newRow( "data1" ) << int(1);
3057     QTest::newRow( "data2" ) << int(11);
3058     QTest::newRow( "data3" ) << int(111);
3059     QTest::newRow( "data4" ) << int(1111);
3060     QTest::newRow( "data5" ) << int(11111);
3061     QTest::newRow( "data6" ) << int(-1);
3062     QTest::newRow( "data7" ) << int(-11);
3063     QTest::newRow( "data8" ) << int(-111);
3064     QTest::newRow( "data9" ) << int(-1111);
3065     QTest::newRow( "data10" ) << int(-11111);
3066 }
3067 
oldWriteEntry_QString_int()3068 void tst_QSettings::oldWriteEntry_QString_int()
3069 {
3070     {
3071 	QSettings writeSettings("software.org", "KillerAPP");
3072 	QFETCH( int, i );
3073 	QVERIFY( writeSettings.writeEntry( "/Trolltech/QSettingsTesting/Integer", i ) );
3074     }
3075     {
3076 	QSettings readSettings("software.org", "KillerAPP");
3077 	QFETCH( int, i );
3078 	bool ok = FALSE;
3079 	QCOMPARE( readSettings.readNumEntry( "/Trolltech/QSettingsTesting/Integer", 0, &ok ), i );
3080 	QVERIFY( ok );
3081     }
3082 }
3083 
oldWriteEntry_QString_QString_data()3084 void tst_QSettings::oldWriteEntry_QString_QString_data()
3085 {
3086     QTest::addColumn<QString>("s");
3087     QTest::newRow( "data0" ) << QString( "blah" );
3088     QTest::newRow( "data1" ) << QString( "" );
3089     QTest::newRow( "data2" ) << QString( QChar(0x0E12) ); // unicode
3090     QTest::newRow( "data3" ) << QString("foo");
3091 //    QTest::newRow( "data4" ) << QString::null;	       // nul string (not supported on Windows!)
3092     QTest::newRow( "data5" ) << QString( QChar(0xFEFC) ); // more unicode
3093     QTest::newRow( "data6" ) << QString( "This is s short string" );
3094     QTest::newRow( "data7" ) << QString( "This is a string with a cr\nand some text on the second line" );
3095     QTest::newRow( "data8" ) << QString( "\n" );
3096     QTest::newRow( "data9" ) << QString( "01234567890, abcdefghijklmnopqrestuvxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_+=-[{]}\\|'\":;/?.>,<" );
3097 }
3098 
oldWriteEntry_QString_QString()3099 void tst_QSettings::oldWriteEntry_QString_QString()
3100 {
3101     {
3102 	QSettings writeSettings("software.org", "KillerAPP");
3103 	QFETCH( QString, s );
3104 	QVERIFY( writeSettings.writeEntry( "/Trolltech/QSettingsTesting/String", s ) );
3105     }
3106     {
3107 	QSettings readSettings("software.org", "KillerAPP");
3108 	QFETCH( QString, s );
3109 	bool ok = FALSE;
3110 	QCOMPARE( readSettings.readEntry( "/Trolltech/QSettingsTesting/String", QString::null, &ok ), s );
3111 	QVERIFY( ok );
3112     }
3113 }
3114 
oldWriteEntry_QString_QStringList_data()3115 void tst_QSettings::oldWriteEntry_QString_QStringList_data()
3116 {
3117     QTest::addColumn<QStringList>("l");
3118     QStringList list0;
3119     list0 << "elem1";
3120     list0 << "elem2";
3121     list0 << "elem3";
3122     list0 << "elem4";
3123 
3124     QTest::newRow( "data0") << list0;
3125 
3126     QStringList list1;
3127     list1 << " elem1";
3128     list1 << "elem2 ";
3129     list1 << QString();
3130     list1 << "";
3131     list1 << "elem3";
3132     QTest::newRow( "data1") << list1;
3133 
3134     QStringList list2;
3135     list2 << " elem1";
3136     list2 << "elem2 bla bla bla, yada yada, 01234567890, abcdefghijklmnopqrestuvxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_+=-[{]}\\|'\":;/?.>,<";
3137     list1 << QString();
3138     list2 << "\n";
3139     list2 << "elem3\nand another line";
3140     QTest::newRow( "data2") << list2;
3141 }
3142 
oldWriteEntry_QString_QStringList()3143 void tst_QSettings::oldWriteEntry_QString_QStringList()
3144 {
3145     {
3146 	QSettings writeSettings("software.org", "KillerAPP");
3147 	QFETCH( QStringList, l );
3148 	QVERIFY( writeSettings.writeEntry( "/Trolltech/QSettingsTesting/List", l ) );
3149     }
3150     {
3151 	QSettings readSettings("software.org", "KillerAPP");
3152 	QFETCH( QStringList, l );
3153 	bool ok = FALSE;
3154 	QCOMPARE( readSettings.readListEntry( "/Trolltech/QSettingsTesting/List", &ok ), l );
3155 	QVERIFY( ok );
3156     }
3157 }
3158 
oldWriteEntry_QString_QStringList_QChar_data()3159 void tst_QSettings::oldWriteEntry_QString_QStringList_QChar_data()
3160 {
3161     QTest::addColumn<QStringList>("l");
3162     QTest::addColumn<QString>("sep");
3163 
3164     QStringList list0;
3165     list0 << "elem1";
3166     list0 << "elem2";
3167     list0 << "elem3";
3168     list0 << "elem4";
3169 
3170     QTest::newRow( "data00") << list0 << "\\";
3171     QTest::newRow( "data01") << list0 << "/";
3172     QTest::newRow( "data02") << list0 << " ";
3173 
3174     QStringList list1;
3175     list1 << " elem1";
3176     list1 << "elem2 ";
3177     list1 << "elem3";
3178     QTest::newRow( "data10") << list1 << "\\";
3179     QTest::newRow( "data11") << list1 << "/";
3180     QTest::newRow( "data12") << list1 << "&";
3181 
3182     QStringList list2;
3183     list2 << " elem1";
3184     list2 << "elem2 bla bla bla, yada yada, 01234567890, abcdefghijklmnopqrestuvxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^*()_+=-[{]}\\|/'\":;?.>,<";
3185     list2 << "\n";
3186     list2 << "elem3\nand another line";
3187     QTest::newRow( "data20") << list2 << "&";
3188 
3189     // an empty stringlist should be stored as an empty string (and return an empty stringlist?)
3190     QStringList list3;
3191     QTest::newRow( "data30") << list3 << "/";
3192 }
3193 
oldWriteEntry_QString_QStringList_QChar()3194 void tst_QSettings::oldWriteEntry_QString_QStringList_QChar()
3195 {
3196     // edba:
3197     // data10, data11, data12, data20, data21 and data22 currently fail.
3198     // This is because the list DOES contain the separator which is a fail IMO, so i
3199     // expect the writeEntry to return FALSE (but it doesn't).
3200     // If my interpretation of the doc is wrong, then the separators should be deleted from
3201     // data10 .. data22.
3202     {
3203 	QSettings writeSettings("software.org", "KillerAPP");
3204 	QFETCH( QStringList, l );
3205 	QFETCH( QString, sep );
3206 	QVERIFY( writeSettings.writeEntry( "/Trolltech/QSettingsTesting/List", l, QChar(sep[0]) ) );
3207     }
3208     {
3209 	QSettings readSettings("software.org", "KillerAPP");
3210 	QFETCH( QStringList, l );
3211 	QFETCH( QString, sep );
3212 	bool ok = FALSE;
3213 	QStringList actual;
3214 	actual = readSettings.readListEntry( "/Trolltech/QSettingsTesting/List", QChar(sep[0]), &ok );
3215 	QVERIFY2( ok, "Read the stringlist from the settings" );
3216 	QCOMPARE( actual, l );
3217     }
3218 }
3219 
oldReadListEntry_QString()3220 void tst_QSettings::oldReadListEntry_QString()
3221 {
3222     DEPENDS_ON( "writeEntry_QString_QStringList" );
3223 }
3224 
oldReadListEntry_QString_QChar()3225 void tst_QSettings::oldReadListEntry_QString_QChar()
3226 {
3227     DEPENDS_ON( "writeEntry_QString_QStringList_QChar" );
3228 }
3229 
oldReadEntry()3230 void tst_QSettings::oldReadEntry()
3231 {
3232     DEPENDS_ON( "writeEntry_QString_QString" );
3233 }
3234 
oldReadNumEntry()3235 void tst_QSettings::oldReadNumEntry()
3236 {
3237     DEPENDS_ON( "writeEntry_QString_int" );
3238 }
3239 
oldReadDoubleEntry()3240 void tst_QSettings::oldReadDoubleEntry()
3241 {
3242     DEPENDS_ON( "writeEntry_QString_double" );
3243 }
3244 
oldReadBoolEntry()3245 void tst_QSettings::oldReadBoolEntry()
3246 {
3247     DEPENDS_ON( "writeEntry_QString_bool" );
3248 }
3249 
oldRemoveEntry()3250 void tst_QSettings::oldRemoveEntry()
3251 {
3252     // we'll use this one later
3253     QSettings firstSettings("software.org", "KillerAPP");
3254 
3255     // first write a key
3256     {
3257 	QSettings writeSettings("software.org", "KillerAPP");
3258 	writeSettings.writeEntry( "/Trolltech/QSettingsTesting/removeEntry", "foobar" );
3259     }
3260 
3261     // check that the key exists
3262     {
3263 	QSettings readSettings("software.org", "KillerAPP");
3264 	bool ok = FALSE;
3265 	QString foo = readSettings.readEntry( "/Trolltech/QSettingsTesting/removeEntry", QString::null, &ok  );
3266 	QVERIFY( ok );
3267 	QVERIFY( foo == "foobar" );
3268 
3269 	// and remove it
3270 	QVERIFY( readSettings.removeEntry( "/Trolltech/QSettingsTesting/removeEntry") );
3271 
3272 	// check that it is gone
3273 	QString foo2 = readSettings.readEntry( "/Trolltech/QSettingsTesting/removeEntry", QString::null, &ok  );
3274 	QVERIFY( ok == FALSE );
3275 	QVERIFY( foo2 == "" );
3276     }
3277 
3278     // Take another chance with a fresh instance
3279     {
3280 	QSettings readSettings("software.org", "KillerAPP");
3281 	bool ok = FALSE;
3282 	QString foo = readSettings.readEntry( "/Trolltech/QSettingsTesting/removeEntry", QString::null, &ok  );
3283 	QVERIFY( ok == FALSE );
3284 	QVERIFY( foo == "" );
3285     }
3286 
3287     // and another chance with an instance that existed already
3288     {
3289 	bool ok = FALSE;
3290 	QString foo = firstSettings.readEntry( "/Trolltech/QSettingsTesting/removeEntry", QString::null, &ok  );
3291 	QVERIFY( ok == FALSE );
3292 	QVERIFY( foo == "" );
3293     }
3294 }
3295 
oldGlobalVersusLocal()3296 void tst_QSettings::oldGlobalVersusLocal()
3297 {
3298     { //write global
3299         QSettings settings("foo");
3300         settings.setPath("software.org", "KillerAPP", QSettings::Global);
3301         settings.writeEntry("/vs/just_global/", "from Global");
3302         settings.writeEntry("/vs/local_and_global/", "from Global");
3303     }
3304     { //write local
3305         QSettings settings("bar");
3306         settings.setPath("software.org", "KillerAPP", QSettings::User);
3307         settings.writeEntry("/vs/local_and_global/", "from User");
3308     }
3309     bool ok;
3310     {
3311         QSettings settings("baz");
3312         settings.setPath("software.org", "KillerAPP", QSettings::User);
3313         QString just_global = settings.readEntry("/vs/just_global/", "not_available", &ok);
3314 	    QVERIFY(ok);
3315         QCOMPARE(just_global, QString("from Global"));
3316         QString local_and_global = settings.readEntry("/vs/local_and_global/", "not_available", &ok);
3317 	    QVERIFY(ok);
3318         QCOMPARE(local_and_global, QString("from User"));
3319     }
3320     {
3321         QSettings settings("bat");
3322         settings.setPath("software.org", "KillerAPP", QSettings::Global);
3323         QString just_global = settings.readEntry("/vs/just_global/", "not_available", &ok);
3324         QVERIFY(ok);
3325         QCOMPARE(just_global, QString("from Global"));
3326         QString local_and_global = settings.readEntry("/vs/local_and_global/", "not_available", &ok);
3327         QVERIFY(ok);
3328         QCOMPARE(local_and_global, QString("from Global"));
3329     }
3330 }
3331 #endif // QT3_SUPPORT
3332 
fileName()3333 void tst_QSettings::fileName()
3334 {
3335 #ifdef Q_OS_MAC
3336     QSettings s1(QSettings::UserScope, "Apple", "Console");
3337     QSettings s2(QSettings::UserScope, "Apple");
3338     QSettings s3(QSettings::SystemScope, "Apple", "Console");
3339     QSettings s4(QSettings::SystemScope, "Apple");
3340 
3341     QCOMPARE(s1.fileName(), QDir::homePath() + "/Library/Preferences/com.apple.Console.plist");
3342     QCOMPARE(s2.fileName(), QDir::homePath() + "/Library/Preferences/com.apple.plist");
3343     QCOMPARE(s3.fileName(), QString("/Library/Preferences/com.apple.Console.plist"));
3344     QCOMPARE(s4.fileName(), QString("/Library/Preferences/com.apple.plist"));
3345 
3346     QSettings s5(QSettings::SystemScope, "Apple.com", "Console");
3347     QCOMPARE(s5.fileName(), QString("/Library/Preferences/com.apple.Console.plist"));
3348 
3349     QSettings s6(QSettings::SystemScope, "apple.com", "Console");
3350     QCOMPARE(s6.fileName(), QString("/Library/Preferences/com.apple.Console.plist"));
3351 
3352     QSettings s7(QSettings::SystemScope, "apple.Com", "Console");
3353     QCOMPARE(s7.fileName(), QString("/Library/Preferences/com.apple.Console.plist"));
3354 
3355     QSettings s8(QSettings::SystemScope, "apple.fr", "Console");
3356     QCOMPARE(s8.fileName(), QString("/Library/Preferences/fr.apple.Console.plist"));
3357 
3358     QSettings s9(QSettings::SystemScope, "apple.co.jp", "Console");
3359     QCOMPARE(s9.fileName(), QString("/Library/Preferences/jp.co.apple.Console.plist"));
3360 
3361     QSettings s10(QSettings::SystemScope, "apple.org", "Console");
3362     QCOMPARE(s10.fileName(), QString("/Library/Preferences/org.apple.Console.plist"));
3363 
3364     QSettings s11(QSettings::SystemScope, "apple.net", "Console");
3365     QCOMPARE(s11.fileName(), QString("/Library/Preferences/net.apple.Console.plist"));
3366 
3367     QSettings s12(QSettings::SystemScope, "apple.museum", "Console");
3368     QCOMPARE(s12.fileName(), QString("/Library/Preferences/museum.apple.Console.plist"));
3369 
3370     QSettings s13(QSettings::SystemScope, "apple.FR", "Console");
3371     QCOMPARE(s13.fileName(), QString("/Library/Preferences/fr.apple.Console.plist"));
3372 
3373     QSettings s14(QSettings::SystemScope, "apple.mUseum", "Console");
3374     QCOMPARE(s14.fileName(), QString("/Library/Preferences/museum.apple.Console.plist"));
3375 
3376     QSettings s15(QSettings::SystemScope, "apple.zz", "Console");
3377     QCOMPARE(s15.fileName(), QString("/Library/Preferences/zz.apple.Console.plist"));
3378 
3379     QSettings s15_prime(QSettings::SystemScope, "apple.foo", "Console");
3380     QCOMPARE(s15_prime.fileName(), QString("/Library/Preferences/com.apple-foo.Console.plist"));
3381 
3382     QSettings s16(QSettings::SystemScope, "apple.f", "Console");
3383     QCOMPARE(s16.fileName(), QString("/Library/Preferences/com.apple-f.Console.plist"));
3384 
3385     QSettings s17(QSettings::SystemScope, "apple.", "Console");
3386     QCOMPARE(s17.fileName(), QString("/Library/Preferences/com.apple.Console.plist"));
3387 
3388     QSettings s18(QSettings::SystemScope, "Foo, Inc.", "Console");
3389     QCOMPARE(s18.fileName(), QString("/Library/Preferences/com.foo-inc.Console.plist"));
3390 
3391     QSettings s19(QSettings::SystemScope, "Foo, Inc.com", "Console");
3392     QCOMPARE(s19.fileName(), QString("/Library/Preferences/com.foo, inc.Console.plist"));
3393 
3394     QSettings s20(QSettings::SystemScope, QLatin1String("   ") + QChar(0xbd) + QLatin1String("Foo//:/Barxxx  Baz!()#@.com"), "Console");
3395     QCOMPARE(s20.fileName(), QLatin1String("/Library/Preferences/com.   ") + QChar(0xbd) + QLatin1String("foo  : barxxx  baz!()#@.Console.plist"));
3396 
3397     QSettings s21(QSettings::SystemScope, QLatin1String("   ") + QChar(0xbd) + QLatin1String("Foo//:/Bar,,,  Baz!()#"), "Console");
3398     QCOMPARE(s21.fileName(), QString("/Library/Preferences/com.foo-bar-baz.Console.plist"));
3399 #else
3400     QSKIP("Please write a fileName() test for the other platforms", SkipAll);
3401 #endif
3402 }
3403 
isWritable_data()3404 void tst_QSettings::isWritable_data()
3405 {
3406     populateWithFormats();
3407 }
3408 
isWritable()3409 void tst_QSettings::isWritable()
3410 {
3411     QFETCH(QSettings::Format, format);
3412 
3413     {
3414         QSettings s1(format, QSettings::UserScope, "software.org", "KillerAPP");
3415         s1.setValue("foo", 1);
3416         s1.sync();
3417         // that should create the file
3418     }
3419 
3420     {
3421         QSettings s1(format, QSettings::UserScope, "software.org", "KillerAPP");
3422         QVERIFY(s1.isWritable());
3423     }
3424 
3425     {
3426         QSettings s1(format, QSettings::SystemScope, "software.org", "KillerAPP");
3427         s1.setValue("foo", 1);
3428         s1.sync();
3429         // that should create the file, *if* we have the permissions
3430     }
3431 
3432     {
3433         QSettings s1(format, QSettings::SystemScope, "software.org", "KillerAPP");
3434         QSettings s2(format, QSettings::SystemScope, "software.org", "Something Different");
3435         QSettings s3(format, QSettings::SystemScope, "foo.org", "Something Different");
3436         if (s1.contains("foo")) {
3437             QVERIFY(s1.isWritable());
3438             QVERIFY(s2.isWritable());
3439             QVERIFY(s3.isWritable());
3440         } else {
3441             QVERIFY(!s1.isWritable());
3442             QVERIFY(!s2.isWritable());
3443             QVERIFY(!s3.isWritable());
3444         }
3445     }
3446 }
3447 
childGroups_data()3448 void tst_QSettings::childGroups_data()
3449 {
3450     populateWithFormats();
3451 }
3452 
childGroups()3453 void tst_QSettings::childGroups()
3454 {
3455 #ifdef QT_BUILD_INTERNAL
3456     QFETCH(QSettings::Format, format);
3457 
3458     {
3459         QSettings settings(format, QSettings::SystemScope, "software.org");
3460         settings.setValue("alpha", "1");
3461         settings.setValue("alpha/a", "2");
3462         settings.setValue("alpha/b", "3");
3463         settings.setValue("alpha/c", "4");
3464         settings.setValue("beta", "5");
3465         settings.setValue("gamma", "6");
3466         settings.setValue("gamma/d", "7");
3467         settings.setValue("gamma/d/e", "8");
3468         settings.setValue("gamma/f/g", "9");
3469         settings.setValue("omicron/h/i/j/x", "10");
3470         settings.setValue("omicron/h/i/k/y", "11");
3471         settings.setValue("zeta/z", "12");
3472     }
3473 
3474     for (int pass = 0; pass < 3; ++pass) {
3475         QConfFile::clearCache();
3476         QSettings settings(format, QSettings::SystemScope, "software.org");
3477         settings.setFallbacksEnabled(false);
3478         if (pass == 1) {
3479             settings.value("gamma/d");
3480         } else if (pass == 2) {
3481             settings.value("gamma");
3482         }
3483 
3484         settings.beginGroup("gamma");
3485         QCOMPARE(settings.childGroups(), QStringList() << "d" << "f");
3486         settings.beginGroup("d");
3487         QCOMPARE(settings.childGroups(), QStringList());
3488         settings.endGroup();
3489         settings.endGroup();
3490 
3491         settings.beginGroup("alpha");
3492         QCOMPARE(settings.childGroups(), QStringList());
3493         settings.endGroup();
3494 
3495         settings.beginGroup("d");
3496         QCOMPARE(settings.childGroups(), QStringList());
3497         settings.endGroup();
3498 
3499         settings.beginGroup("/omicron///h/i///");
3500         QCOMPARE(settings.childGroups(), QStringList() << "j" << "k");
3501         settings.endGroup();
3502 
3503         settings.beginGroup("////");
3504         QCOMPARE(settings.childGroups(), QStringList() << "alpha" << "gamma" << "omicron" << "zeta");
3505         settings.endGroup();
3506 
3507         QCOMPARE(settings.childGroups(), QStringList() << "alpha" << "gamma" << "omicron" << "zeta");
3508     }
3509 #endif
3510 }
3511 
childKeys_data()3512 void tst_QSettings::childKeys_data()
3513 {
3514     populateWithFormats();
3515 }
3516 
childKeys()3517 void tst_QSettings::childKeys()
3518 {
3519 #ifdef QT_BUILD_INTERNAL
3520     QFETCH(QSettings::Format, format);
3521 
3522     {
3523         QSettings settings(format, QSettings::SystemScope, "software.org");
3524         settings.setValue("alpha", "1");
3525         settings.setValue("alpha/a", "2");
3526         settings.setValue("alpha/b", "3");
3527         settings.setValue("alpha/c", "4");
3528         settings.setValue("beta", "5");
3529         settings.setValue("gamma", "6");
3530         settings.setValue("gamma/d", "7");
3531         settings.setValue("gamma/d/e", "8");
3532         settings.setValue("gamma/f/g", "9");
3533         settings.setValue("omicron/h/i/j/x", "10");
3534         settings.setValue("omicron/h/i/k/y", "11");
3535         settings.setValue("zeta/z", "12");
3536     }
3537 
3538     for (int pass = 0; pass < 3; ++pass) {
3539         QConfFile::clearCache();
3540         QSettings settings(format, QSettings::SystemScope, "software.org");
3541         settings.setFallbacksEnabled(false);
3542         if (pass == 1) {
3543             settings.value("gamma/d");
3544         } else if (pass == 2) {
3545             settings.value("gamma");
3546         }
3547 
3548         settings.beginGroup("gamma");
3549         QCOMPARE(settings.childKeys(), QStringList() << "d");
3550         settings.beginGroup("d");
3551         QCOMPARE(settings.childKeys(), QStringList() << "e");
3552         settings.endGroup();
3553         settings.endGroup();
3554 
3555         settings.beginGroup("alpha");
3556         QCOMPARE(settings.childKeys(), QStringList() << "a" << "b" << "c");
3557         settings.endGroup();
3558 
3559         settings.beginGroup("d");
3560         QCOMPARE(settings.childKeys(), QStringList());
3561         settings.endGroup();
3562 
3563         settings.beginGroup("/omicron///h/i///");
3564         QCOMPARE(settings.childKeys(), QStringList());
3565         settings.endGroup();
3566 
3567         settings.beginGroup("////");
3568         QCOMPARE(settings.childKeys(), QStringList() << "alpha" << "beta" << "gamma");
3569         settings.endGroup();
3570 
3571         QCOMPARE(settings.childKeys(), QStringList() << "alpha" << "beta" << "gamma");
3572     }
3573 #endif
3574 }
3575 
allKeys_data()3576 void tst_QSettings::allKeys_data()
3577 {
3578     populateWithFormats();
3579 }
3580 
allKeys()3581 void tst_QSettings::allKeys()
3582 {
3583 #ifdef QT_BUILD_INTERNAL
3584     QFETCH(QSettings::Format, format);
3585 
3586     QStringList allKeys;
3587     allKeys << "alpha" << "alpha/a" << "alpha/b" << "alpha/c" << "beta" << "gamma" << "gamma/d"
3588             << "gamma/d/e" << "gamma/f/g" << "omicron/h/i/j/x" << "omicron/h/i/k/y" << "zeta/z";
3589 
3590     {
3591         QSettings settings(format, QSettings::SystemScope, "software.org");
3592         for (int i = 0; i < allKeys.size(); ++i)
3593             settings.setValue(allKeys.at(i), QString::number(i + 1));
3594     }
3595 
3596     for (int pass = 0; pass < 3; ++pass) {
3597         QConfFile::clearCache();
3598         QSettings settings(format, QSettings::SystemScope, "software.org");
3599         settings.setFallbacksEnabled(false);
3600 
3601         if (pass == 1) {
3602             settings.value("gamma/d");
3603         } else if (pass == 2) {
3604             settings.value("gamma");
3605         }
3606 
3607         settings.beginGroup("gamma");
3608         QCOMPARE(settings.allKeys(), QStringList() << "d" << "d/e" << "f/g");
3609         settings.beginGroup("d");
3610         QCOMPARE(settings.allKeys(), QStringList() << "e");
3611         settings.endGroup();
3612         settings.endGroup();
3613 
3614         settings.beginGroup("alpha");
3615         QCOMPARE(settings.allKeys(), QStringList() << "a" << "b" << "c");
3616         settings.endGroup();
3617 
3618         settings.beginGroup("d");
3619         QCOMPARE(settings.allKeys(), QStringList());
3620         settings.endGroup();
3621 
3622         settings.beginGroup("/omicron///h/i///");
3623         QCOMPARE(settings.allKeys(), QStringList() << "j/x" << "k/y");
3624         settings.endGroup();
3625 
3626         settings.beginGroup("////");
3627         QCOMPARE(settings.allKeys(), allKeys);
3628         settings.endGroup();
3629 
3630         QCOMPARE(settings.allKeys(), allKeys);
3631     }
3632 #endif
3633 }
3634 
registerFormat()3635 void tst_QSettings::registerFormat()
3636 {
3637     QSettings settings1(QSettings::IniFormat, QSettings::UserScope, "software.org", "KillerAPP");
3638     QSettings settings2(QSettings::CustomFormat1, QSettings::UserScope, "software.org", "KillerAPP");
3639 
3640     QString fileName = settings1.fileName();
3641     fileName.chop(3); // "ini";
3642     fileName.append("custom1");
3643     QCOMPARE(settings2.fileName(), fileName);
3644 
3645     // OK, let's see if it can read a generated file of a custom type
3646     // Beware: readCustom3File() and writeCustom3File() have unintuitive behavior
3647     // so we can test error handling
3648 
3649     QSettings::Format custom3 = QSettings::registerFormat("custom3", readCustom3File, writeCustom3File);
3650     QVERIFY(custom3 == QSettings::CustomFormat3);
3651 
3652     QDir dir(settingsPath());
3653     QVERIFY(dir.mkpath("someDir"));
3654     QFile f(dir.path()+"/someDir/someSettings.custom3");
3655 
3656     QVERIFY(f.open(QFile::WriteOnly));
3657     f.write("OK");
3658     f.close();
3659 
3660     {
3661     QSettings settings(settingsPath("someDir/someSettings.custom3"), QSettings::CustomFormat3);
3662     QCOMPARE(settings.status(), QSettings::NoError);
3663     QCOMPARE(settings.value("retval").toString(), QString("OK"));
3664     QVERIFY(settings.isWritable());
3665     }
3666 
3667     QVERIFY(f.open(QFile::WriteOnly));
3668     f.write("NotOK");
3669     f.close();
3670 
3671     {
3672     QSettings settings(settingsPath("someDir/someSettings.custom3"), QSettings::CustomFormat3);
3673     QCOMPARE(settings.status(), QSettings::FormatError);
3674     QCOMPARE(settings.value("retval").toString(), QString());
3675     QVERIFY(settings.isWritable());
3676     }
3677 
3678     QVERIFY(f.open(QFile::WriteOnly));
3679     f.write("OK");
3680     f.close();
3681 
3682     {
3683     QSettings settings(settingsPath("someDir/someSettings.custom3"), QSettings::CustomFormat3);
3684     QCOMPARE(settings.status(), QSettings::NoError);
3685     settings.setValue("zzz", "bar");
3686     settings.sync();
3687     QCOMPARE(settings.status(), QSettings::NoError);
3688 
3689     settings.setValue("retval", "NotOK");
3690     settings.sync();
3691     QCOMPARE(settings.status(), QSettings::AccessError);
3692 
3693     QCOMPARE(settings.value("retval").toString(), QString("NotOK"));
3694     QVERIFY(settings.isWritable());
3695     }
3696 
3697     {
3698     QSettings settings(settingsPath("someDir/someSettings.custom3"), QSettings::CustomFormat4);
3699     QCOMPARE(settings.status(), QSettings::AccessError);
3700     QVERIFY(!settings.isWritable());
3701     }
3702 }
3703 
setPath()3704 void tst_QSettings::setPath()
3705 {
3706 #define TEST_PATH(doSet, ext, format, scope, path) \
3707     { \
3708     if (doSet) \
3709         QSettings::setPath(QSettings::format, QSettings::scope, settingsPath(path)); \
3710     QSettings settings1(QSettings::format, QSettings::scope, "software.org", "KillerAPP"); \
3711     QCOMPARE(QDir(settings1.fileName()), QDir(settingsPath(path) + QDir::separator() + "software.org" \
3712                                   + QDir::separator() + "KillerAPP." + ext)); \
3713     }
3714 
3715     /*
3716         The first pass checks that setPath() works; the second
3717         path checks that it has no bad side effects.
3718     */
3719     for (int i = 0; i < 2; ++i) {
3720 #if !defined(Q_OS_BLACKBERRY)
3721 #if !defined(Q_OS_WIN) && !defined(Q_OS_MAC)
3722         TEST_PATH(i == 0, "conf", NativeFormat, UserScope, "alpha")
3723         TEST_PATH(i == 0, "conf", NativeFormat, SystemScope, "beta")
3724 #endif
3725         TEST_PATH(i == 0, "ini", IniFormat, UserScope, "gamma")
3726         TEST_PATH(i == 0, "ini", IniFormat, SystemScope, "omicron")
3727         TEST_PATH(i == 0, "custom1", CustomFormat1, UserScope, "epsilon")
3728         TEST_PATH(i == 0, "custom1", CustomFormat1, SystemScope, "zeta")
3729         TEST_PATH(i == 0, "custom2", CustomFormat2, UserScope, "eta")
3730         TEST_PATH(i == 0, "custom2", CustomFormat2, SystemScope, "iota")
3731 #else // Q_OS_BLACKBERRY: no system scope
3732         TEST_PATH(i == 0, "conf", NativeFormat, UserScope, "alpha")
3733         TEST_PATH(i == 0, "ini", IniFormat, UserScope, "gamma")
3734         TEST_PATH(i == 0, "custom1", CustomFormat1, UserScope, "epsilon")
3735         TEST_PATH(i == 0, "custom2", CustomFormat2, UserScope, "eta")
3736 #endif
3737     }
3738 }
3739 
setDefaultFormat()3740 void tst_QSettings::setDefaultFormat()
3741 {
3742     QVERIFY(QSettings::defaultFormat() == QSettings::NativeFormat);
3743 
3744     QSettings::setDefaultFormat(QSettings::CustomFormat1);
3745     QSettings settings1("org", "app");
3746     QSettings settings2(QSettings::SystemScope, "org", "app");
3747     QSettings settings3;
3748 
3749     QVERIFY(settings1.format() == QSettings::NativeFormat);
3750     QVERIFY(settings2.format() == QSettings::NativeFormat);
3751     QVERIFY(settings3.format() == QSettings::CustomFormat1);
3752 
3753     QSettings::setDefaultFormat(QSettings::NativeFormat);
3754     QVERIFY(QSettings::defaultFormat() == QSettings::NativeFormat);
3755 
3756     QVERIFY(settings1.format() == QSettings::NativeFormat);
3757     QVERIFY(settings2.format() == QSettings::NativeFormat);
3758     QVERIFY(settings3.format() == QSettings::CustomFormat1);
3759 }
3760 
dontCreateNeedlessPaths()3761 void tst_QSettings::dontCreateNeedlessPaths()
3762 {
3763     QString path;
3764     {
3765         QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Hello", "Test");
3766         QVariant val = settings.value("foo", "bar");
3767         path = settings.fileName();
3768     }
3769 
3770     QFileInfo fileInfo(path);
3771     QVERIFY(!fileInfo.dir().exists());
3772 }
3773 
3774 #if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
dontReorderIniKeysNeedlessly()3775 void tst_QSettings::dontReorderIniKeysNeedlessly()
3776 {
3777 #ifdef  QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER
3778     QSKIP("This Qt build does not preserve ordering, as a code size optimization.", SkipAll);
3779 #endif
3780 
3781     /*
3782         This is a very strong test. It asserts that modifying
3783         resourcefile2.ini will lead to the exact contents of
3784         resourcefile3.ini. Right now it's run only on Unix
3785         systems, but that should be enough since the INI
3786         code (unlike this test) is platform-agnostic.
3787 
3788         Things that are tested:
3789 
3790             * keys are written in the same order that they were
3791               read in
3792 
3793             * new keys are put at the end of their respective
3794               sections
3795     */
3796 
3797     QFile inFile(":/resourcefile2.ini");
3798     inFile.open(QIODevice::ReadOnly);
3799     QByteArray contentsBefore = inFile.readAll();
3800     inFile.close();
3801 
3802     QByteArray expectedContentsAfter;
3803 
3804     {
3805         QFile inFile(":/resourcefile3.ini");
3806         inFile.open(QIODevice::ReadOnly);
3807         expectedContentsAfter = inFile.readAll();
3808         inFile.close();
3809     }
3810 
3811     QString outFileName;
3812     QString outFileName2;
3813 
3814     QTemporaryFile outFile;
3815     outFile.open();
3816     outFile.write(contentsBefore);
3817     outFileName = outFile.fileName();
3818     outFile.close();
3819 
3820     QSettings settings(outFileName, QSettings::IniFormat);
3821     QVERIFY(settings.status() == QSettings::NoError);
3822     QVERIFY(settings.isWritable());
3823 
3824     settings.setValue("Field 1/Bottom", 90);
3825     settings.setValue("Field 1/x", 1);
3826     settings.setValue("Field 1/y", 1);
3827     settings.setValue("Field 1/width", 1);
3828     settings.setValue("Field 1/height", 1);
3829     settings.sync();
3830 
3831     QFile outFile2(outFileName);
3832     QVERIFY(outFile2.open(QIODevice::ReadOnly));
3833     QCOMPARE(outFile2.readAll(), expectedContentsAfter);
3834     outFile2.close();
3835 }
3836 #endif
3837 
rainersSyncBugOnMac_data()3838 void tst_QSettings::rainersSyncBugOnMac_data()
3839 {
3840     ctor_data();
3841 }
3842 
rainersSyncBugOnMac()3843 void tst_QSettings::rainersSyncBugOnMac()
3844 {
3845     QFETCH(QSettings::Format, format);
3846 
3847     QString fileName;
3848 
3849     {
3850         QSettings s1(format, QSettings::UserScope, "software.org", "KillerAPP");
3851         QCOMPARE(s1.value("key1", 5).toInt(), 5);
3852         fileName = s1.fileName();
3853     }
3854 
3855     {
3856         QSettings s2(fileName, format);
3857         s2.setValue("key1", 25);
3858     }
3859 
3860     {
3861         QSettings s3(format, QSettings::UserScope, "software.org", "KillerAPP");
3862         QCOMPARE(s3.value("key1", 30).toInt(), 25);
3863     }
3864 }
3865 
recursionBug()3866 void tst_QSettings::recursionBug()
3867 {
3868     QPixmap pix(10,10);
3869     pix.fill("blue");
3870 
3871     {
3872         QSettings settings(settingsPath("starrunner.ini"), QSettings::IniFormat);
3873         settings.setValue("General/Pixmap", pix );
3874     }
3875 }
3876 
3877 #ifdef QT3_SUPPORT
setPathBug()3878 void tst_QSettings::setPathBug()
3879 {
3880     QSettings settings("software.org", "KillerAPP", this);
3881     settings.setPath("foo.org", "Bar", QSettings::User);
3882     QVERIFY(settings.parent() == this);
3883     settings.setValue("blah", "BAZ");
3884     settings.setPath("bar.org", "Baz", QSettings::User);
3885     settings.setValue("blah", "BAZ");
3886     QVERIFY(settings.parent() == this);
3887 }
3888 #endif
3889 
3890 #if defined(Q_OS_WIN)
3891 
readKeyType(HKEY handle,const QString & rSubKey)3892 static DWORD readKeyType(HKEY handle, const QString &rSubKey)
3893 {
3894     DWORD dataType;
3895     DWORD dataSize;
3896     LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, &dataType, 0, &dataSize);
3897 
3898     if (res == ERROR_SUCCESS)
3899         return dataType;
3900 
3901     return 0;
3902 }
3903 
qtbug_13249()3904 void tst_QSettings::qtbug_13249()
3905 {
3906     QSettings settings1(QSettings::UserScope, "software.org", "KillerAPP");
3907 
3908     qint32 x = 1024;
3909     settings1.setValue("qtbug_13249_a", (qint32)x);
3910     QCOMPARE(settings1.value("qtbug_13249_a").toInt(), (qint32)1024);
3911     settings1.setValue("qtbug_13249_b", (quint32)x);
3912     QCOMPARE(settings1.value("qtbug_13249_b").toUInt(), (quint32)1024);
3913     settings1.setValue("qtbug_13249_c", (qint64)x);
3914     QCOMPARE(settings1.value("qtbug_13249_c").toLongLong(), (qint64)1024);
3915     settings1.setValue("qtbug_13249_d", (quint64)x);
3916     QCOMPARE(settings1.value("qtbug_13249_d").toULongLong(), (quint64)1024);
3917     settings1.sync();
3918 
3919     HKEY handle;
3920     LONG res;
3921     QString keyName = "Software\\software.org\\KillerAPP";
3922     res = RegOpenKeyEx(HKEY_CURRENT_USER, reinterpret_cast<const wchar_t *>(keyName.utf16()), 0, KEY_READ, &handle);
3923     if (res == ERROR_SUCCESS)
3924     {
3925         DWORD dataType;
3926         dataType = readKeyType(handle, QString("qtbug_13249_a"));
3927         if (dataType != 0) {
3928             QCOMPARE((int)REG_DWORD, (int)dataType);
3929         }
3930         dataType = readKeyType(handle, QString("qtbug_13249_b"));
3931         if (dataType != 0) {
3932             QCOMPARE((int)REG_DWORD, (int)dataType);
3933         }
3934         dataType = readKeyType(handle, QString("qtbug_13249_c"));
3935         if (dataType != 0) {
3936             QCOMPARE((int)REG_QWORD, (int)dataType);
3937         }
3938         dataType = readKeyType(handle, QString("qtbug_13249_d"));
3939         if (dataType != 0) {
3940             QCOMPARE((int)REG_QWORD, (int)dataType);
3941         }
3942         RegCloseKey(handle);
3943     }
3944 }
3945 #endif
3946 /*
3947 // Not tested at the moment.
3948 void tst_QSettings::oldSubkeyList()
3949 {
3950     QVERIFY( TRUE );
3951 }
3952 */
3953 
3954 QTEST_MAIN(tst_QSettings)
3955 #include "tst_qsettings.moc"
3956 
3957 
3958 // foo
3959