You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1648 lines
60 KiB
1648 lines
60 KiB
/* This file is part of the KDE libraries |
|
Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) |
|
|
|
This library is free software; you can redistribute it and/or |
|
modify it under the terms of the GNU Library General Public |
|
License as published by the Free Software Foundation; either |
|
version 2 of the License, or (at your option) any later version. |
|
|
|
This library is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
Library General Public License for more details. |
|
|
|
You should have received a copy of the GNU Library General Public License |
|
along with this library; see the file COPYING.LIB. If not, write to |
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
Boston, MA 02110-1301, USA. |
|
*/ |
|
|
|
// Qt5 TODO: re-enable. No point in doing it before, it breaks on QString::fromUtf8(QByteArray), which exists in qt5. |
|
#undef QT_NO_CAST_FROM_BYTEARRAY |
|
|
|
#include "kconfigtest.h" |
|
|
|
#include <QtTest/QtTest> |
|
#include <qtemporarydir.h> |
|
#include <QStandardPaths> |
|
#include <kdesktopfile.h> |
|
|
|
#include <ksharedconfig.h> |
|
#include <kconfiggroup.h> |
|
|
|
#ifdef Q_OS_UNIX |
|
#include <utime.h> |
|
#endif |
|
#ifndef Q_OS_WIN |
|
#include <unistd.h> // gethostname |
|
#endif |
|
|
|
KCONFIGGROUP_DECLARE_ENUM_QOBJECT(KConfigTest, Testing) |
|
KCONFIGGROUP_DECLARE_FLAGS_QOBJECT(KConfigTest, Flags) |
|
|
|
QTEST_MAIN(KConfigTest) |
|
|
|
#define BOOLENTRY1 true |
|
#define BOOLENTRY2 false |
|
#define STRINGENTRY1 "hello" |
|
#define STRINGENTRY2 " hello" |
|
#define STRINGENTRY3 "hello " |
|
#define STRINGENTRY4 " hello " |
|
#define STRINGENTRY5 " " |
|
#define STRINGENTRY6 "" |
|
#define UTF8BITENTRY "Hello äöü" |
|
#define TRANSLATEDSTRINGENTRY1 "bonjour" |
|
#define BYTEARRAYENTRY QByteArray( "\x00\xff\x7f\x3c abc\x00\x00", 10 ) |
|
#define ESCAPEKEY " []\0017[]==]" |
|
#define ESCAPEENTRY "[]\170[]]=3=]\\] " |
|
#define DOUBLEENTRY 123456.78912345 |
|
#define FLOATENTRY 123.567f |
|
#define POINTENTRY QPoint( 4351, 1235 ) |
|
#define SIZEENTRY QSize( 10, 20 ) |
|
#define RECTENTRY QRect( 10, 23, 5321, 13 ) |
|
#define DATETIMEENTRY QDateTime( QDate( 2002, 06, 23 ), QTime( 12, 55, 40 ) ) |
|
#define STRINGLISTENTRY (QStringList( "Hello," ) << " World") |
|
#define STRINGLISTEMPTYENTRY QStringList() |
|
#define STRINGLISTJUSTEMPTYELEMENT QStringList(QString()) |
|
#define STRINGLISTEMPTYTRAINLINGELEMENT (QStringList( "Hi" ) << QString()) |
|
#define STRINGLISTESCAPEODDENTRY (QStringList( "Hello\\\\\\" ) << "World") |
|
#define STRINGLISTESCAPEEVENENTRY (QStringList( "Hello\\\\\\\\" ) << "World") |
|
#define STRINGLISTESCAPECOMMAENTRY (QStringList( "Hel\\\\\\,\\\\,\\,\\\\\\\\,lo" ) << "World") |
|
#define INTLISTENTRY1 QList<int>() << 1 << 2 << 3 << 4 |
|
#define BYTEARRAYLISTENTRY1 QList<QByteArray>() << "" << "1,2" << "end" |
|
#define VARIANTLISTENTRY (QVariantList() << true << false << QString("joe") << 10023) |
|
#define VARIANTLISTENTRY2 (QVariantList() << POINTENTRY << SIZEENTRY) |
|
#define HOMEPATH QString(QDir::homePath()+"/foo") |
|
#define HOMEPATHESCAPE QString(QDir::homePath()+"/foo/$HOME") |
|
#define DOLLARGROUP "$i" |
|
|
|
#define TEST_SUBDIR "kconfigtest_subdir/" |
|
|
|
static inline QString testConfigDir() { |
|
return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/" TEST_SUBDIR; |
|
} |
|
|
|
static inline QString kdeGlobalsPath() { |
|
return testConfigDir() + "../kdeglobals"; |
|
} |
|
|
|
void KConfigTest::initTestCase() |
|
{ |
|
// ensure we don't use files in the real config directory |
|
QStandardPaths::setTestModeEnabled(true); |
|
|
|
// to make sure all files from a previous failed run are deleted |
|
cleanupTestCase(); |
|
|
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
|
|
KConfigGroup cg(&sc, "AAA"); |
|
cg.writeEntry("stringEntry1", STRINGENTRY1, |
|
KConfig::Persistent | KConfig::Global); |
|
cg.deleteEntry("stringEntry2", KConfig::Global); |
|
|
|
cg = KConfigGroup(&sc, "Hello"); |
|
cg.writeEntry("boolEntry1", BOOLENTRY1); |
|
cg.writeEntry("boolEntry2", BOOLENTRY2); |
|
|
|
QByteArray data(UTF8BITENTRY); |
|
QCOMPARE(data.size(), 12); // the source file is in utf8 |
|
QCOMPARE(QString::fromUtf8(data).length(), 9); |
|
cg.writeEntry("Test", data); |
|
cg.writeEntry("bytearrayEntry", BYTEARRAYENTRY); |
|
cg.writeEntry(ESCAPEKEY, ESCAPEENTRY); |
|
cg.writeEntry("emptyEntry", ""); |
|
cg.writeEntry("stringEntry1", STRINGENTRY1); |
|
cg.writeEntry("stringEntry2", STRINGENTRY2); |
|
cg.writeEntry("stringEntry3", STRINGENTRY3); |
|
cg.writeEntry("stringEntry4", STRINGENTRY4); |
|
cg.writeEntry("stringEntry5", STRINGENTRY5); |
|
cg.writeEntry("urlEntry1", QUrl("http://qt-project.org")); |
|
cg.writeEntry("keywith=equalsign", STRINGENTRY1); |
|
cg.deleteEntry("stringEntry5"); |
|
cg.deleteEntry("stringEntry6"); // deleting a nonexistent entry |
|
cg.writeEntry("byteArrayEntry1", QByteArray(STRINGENTRY1), |
|
KConfig::Global | KConfig::Persistent); |
|
cg.writeEntry("doubleEntry1", DOUBLEENTRY); |
|
cg.writeEntry("floatEntry1", FLOATENTRY); |
|
|
|
sc.deleteGroup("deleteMe"); // deleting a nonexistent group |
|
|
|
cg = KConfigGroup(&sc, "Complex Types"); |
|
cg.writeEntry("rectEntry", RECTENTRY); |
|
cg.writeEntry("pointEntry", POINTENTRY); |
|
cg.writeEntry("sizeEntry", SIZEENTRY); |
|
cg.writeEntry("dateTimeEntry", DATETIMEENTRY); |
|
cg.writeEntry("dateEntry", DATETIMEENTRY.date()); |
|
|
|
KConfigGroup ct = cg; |
|
cg = KConfigGroup(&ct, "Nested Group 1"); |
|
cg.writeEntry("stringentry1", STRINGENTRY1); |
|
|
|
cg = KConfigGroup(&ct, "Nested Group 2"); |
|
cg.writeEntry("stringEntry2", STRINGENTRY2); |
|
|
|
cg = KConfigGroup(&cg, "Nested Group 2.1"); |
|
cg.writeEntry("stringEntry3", STRINGENTRY3); |
|
|
|
cg = KConfigGroup(&ct, "Nested Group 3"); |
|
cg.writeEntry("stringEntry3", STRINGENTRY3); |
|
|
|
cg = KConfigGroup(&sc, "List Types"); |
|
cg.writeEntry("listOfIntsEntry1", INTLISTENTRY1); |
|
cg.writeEntry("listOfByteArraysEntry1", BYTEARRAYLISTENTRY1); |
|
cg.writeEntry("stringListEntry", STRINGLISTENTRY); |
|
cg.writeEntry("stringListEmptyEntry", STRINGLISTEMPTYENTRY); |
|
cg.writeEntry("stringListJustEmptyElement", STRINGLISTJUSTEMPTYELEMENT); |
|
cg.writeEntry("stringListEmptyTrailingElement", STRINGLISTEMPTYTRAINLINGELEMENT); |
|
cg.writeEntry("stringListEscapeOddEntry", STRINGLISTESCAPEODDENTRY); |
|
cg.writeEntry("stringListEscapeEvenEntry", STRINGLISTESCAPEEVENENTRY); |
|
cg.writeEntry("stringListEscapeCommaEntry", STRINGLISTESCAPECOMMAENTRY); |
|
cg.writeEntry("variantListEntry", VARIANTLISTENTRY); |
|
|
|
cg = KConfigGroup(&sc, "Path Type"); |
|
cg.writePathEntry("homepath", HOMEPATH); |
|
cg.writePathEntry("homepathescape", HOMEPATHESCAPE); |
|
|
|
cg = KConfigGroup(&sc, "Enum Types"); |
|
writeEntry(cg, "enum-10", Tens); |
|
writeEntry(cg, "enum-100", Hundreds); |
|
writeEntry(cg, "flags-bit0", Flags(bit0)); |
|
writeEntry(cg, "flags-bit0-bit1", Flags(bit0 | bit1)); |
|
|
|
cg = KConfigGroup(&sc, "ParentGroup"); |
|
KConfigGroup cg1(&cg, "SubGroup1"); |
|
cg1.writeEntry("somestring", "somevalue"); |
|
cg.writeEntry("parentgrpstring", "somevalue"); |
|
KConfigGroup cg2(&cg, "SubGroup2"); |
|
cg2.writeEntry("substring", "somevalue"); |
|
KConfigGroup cg3(&cg, "SubGroup/3"); |
|
cg3.writeEntry("sub3string", "somevalue"); |
|
|
|
QVERIFY(sc.isDirty()); |
|
QVERIFY(sc.sync()); |
|
QVERIFY(!sc.isDirty()); |
|
|
|
QVERIFY2(QFile::exists(testConfigDir() + QStringLiteral("/kconfigtest")), |
|
qPrintable(testConfigDir() + QStringLiteral("/kconfigtest must exist"))); |
|
QVERIFY2(QFile::exists(kdeGlobalsPath()), |
|
qPrintable(kdeGlobalsPath() + QStringLiteral(" must exist"))); |
|
|
|
KConfig sc1(TEST_SUBDIR "kdebugrc", KConfig::SimpleConfig); |
|
KConfigGroup sg0(&sc1, "0"); |
|
sg0.writeEntry("AbortFatal", false); |
|
sg0.writeEntry("WarnOutput", 0); |
|
sg0.writeEntry("FatalOutput", 0); |
|
QVERIFY(sc1.sync()); |
|
|
|
//Setup stuff to test KConfig::addConfigSources() |
|
KConfig devcfg(TEST_SUBDIR "specificrc"); |
|
KConfigGroup devonlygrp(&devcfg, "Specific Only Group"); |
|
devonlygrp.writeEntry("ExistingEntry", "DevValue"); |
|
KConfigGroup devandbasegrp(&devcfg, "Shared Group"); |
|
devandbasegrp.writeEntry("SomeSharedEntry", "DevValue"); |
|
devandbasegrp.writeEntry("SomeSpecificOnlyEntry", "DevValue"); |
|
QVERIFY(devcfg.sync()); |
|
KConfig basecfg(TEST_SUBDIR "baserc"); |
|
KConfigGroup basegrp(&basecfg, "Base Only Group"); |
|
basegrp.writeEntry("ExistingEntry", "BaseValue"); |
|
KConfigGroup baseanddevgrp(&basecfg, "Shared Group"); |
|
baseanddevgrp.writeEntry("SomeSharedEntry", "BaseValue"); |
|
baseanddevgrp.writeEntry("SomeBaseOnlyEntry", "BaseValue"); |
|
QVERIFY(basecfg.sync()); |
|
|
|
KConfig gecfg(TEST_SUBDIR "groupescapetest", KConfig::SimpleConfig); |
|
cg = KConfigGroup(&gecfg, DOLLARGROUP); |
|
cg.writeEntry("entry", "doesntmatter"); |
|
|
|
} |
|
|
|
void KConfigTest::cleanupTestCase() |
|
{ |
|
//ensure we don't delete the real directory |
|
QDir localConfig(testConfigDir()); |
|
//qDebug() << "Erasing" << localConfig; |
|
if (localConfig.exists()) { |
|
QVERIFY(localConfig.removeRecursively()); |
|
} |
|
QVERIFY(!localConfig.exists()); |
|
if (QFile::exists(kdeGlobalsPath())) { |
|
QVERIFY(QFile::remove(kdeGlobalsPath())); |
|
} |
|
|
|
} |
|
|
|
static QList<QByteArray> readLinesFrom(const QString &path) |
|
{ |
|
QFile file(path); |
|
const bool opened = file.open(QIODevice::ReadOnly | QIODevice::Text); |
|
QList<QByteArray> lines; |
|
if (!opened) { |
|
QWARN(qPrintable(QLatin1String("Failed to open ") + path)); |
|
return lines; |
|
} |
|
QByteArray line; |
|
do { |
|
line = file.readLine(); |
|
if (!line.isEmpty()) { |
|
lines.append(line); |
|
} |
|
} while (!line.isEmpty()); |
|
return lines; |
|
} |
|
|
|
static QList<QByteArray> readLines(const char *fileName = TEST_SUBDIR "kconfigtest") |
|
{ |
|
const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); |
|
Q_ASSERT(!path.isEmpty()); |
|
return readLinesFrom(path + '/' + fileName); |
|
} |
|
|
|
// see also testDefaults, which tests reverting with a defaults (global) file available |
|
void KConfigTest::testDirtyAfterRevert() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest_revert"); |
|
|
|
KConfigGroup cg(&sc, "Hello"); |
|
cg.revertToDefault("does_not_exist"); |
|
QVERIFY(!sc.isDirty()); |
|
cg.writeEntry("Test", "Correct"); |
|
QVERIFY(sc.isDirty()); |
|
sc.sync(); |
|
QVERIFY(!sc.isDirty()); |
|
|
|
cg.revertToDefault("Test"); |
|
QVERIFY(sc.isDirty()); |
|
QVERIFY(sc.sync()); |
|
QVERIFY(!sc.isDirty()); |
|
|
|
cg.revertToDefault("Test"); |
|
QVERIFY(!sc.isDirty()); |
|
} |
|
|
|
void KConfigTest::testRevertAllEntries() |
|
{ |
|
// this tests the case were we revert (delete) all entries in a file, |
|
// leaving a blank file |
|
{ |
|
KConfig sc(TEST_SUBDIR "konfigtest2", KConfig::SimpleConfig); |
|
KConfigGroup cg(&sc, "Hello"); |
|
cg.writeEntry("Test", "Correct"); |
|
} |
|
|
|
{ |
|
KConfig sc(TEST_SUBDIR "konfigtest2", KConfig::SimpleConfig); |
|
KConfigGroup cg(&sc, "Hello"); |
|
QCOMPARE(cg.readEntry("Test", "Default"), QString("Correct")); |
|
cg.revertToDefault("Test"); |
|
} |
|
|
|
KConfig sc(TEST_SUBDIR "konfigtest2", KConfig::SimpleConfig); |
|
KConfigGroup cg(&sc, "Hello"); |
|
QCOMPARE(cg.readEntry("Test", "Default"), QString("Default")); |
|
} |
|
|
|
void KConfigTest::testSimple() |
|
{ |
|
// kdeglobals (which was created in initTestCase) must be found this way: |
|
const QStringList kdeglobals = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QLatin1String("kdeglobals")); |
|
QVERIFY(!kdeglobals.isEmpty()); |
|
|
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
QCOMPARE(sc2.name(), QString(TEST_SUBDIR "kconfigtest")); |
|
|
|
// make sure groupList() isn't returning something it shouldn't |
|
Q_FOREACH (const QString &group, sc2.groupList()) { |
|
QVERIFY(!group.isEmpty() && group != "<default>"); |
|
QVERIFY(!group.contains(QChar(0x1d))); |
|
} |
|
|
|
KConfigGroup sc3(&sc2, "AAA"); |
|
|
|
QVERIFY(sc3.hasKey("stringEntry1")); // from kdeglobals |
|
QVERIFY(!sc3.isEntryImmutable("stringEntry1")); |
|
QCOMPARE(sc3.readEntry("stringEntry1"), QString(STRINGENTRY1)); |
|
|
|
QVERIFY(!sc3.hasKey("stringEntry2")); |
|
QCOMPARE(sc3.readEntry("stringEntry2", QString("bla")), QString("bla")); |
|
|
|
QVERIFY(!sc3.hasDefault("stringEntry1")); |
|
|
|
sc3 = KConfigGroup(&sc2, "Hello"); |
|
QCOMPARE(sc3.readEntry("Test", QByteArray()), QByteArray(UTF8BITENTRY)); |
|
QCOMPARE(sc3.readEntry("bytearrayEntry", QByteArray()), BYTEARRAYENTRY); |
|
QCOMPARE(sc3.readEntry(ESCAPEKEY), QString(ESCAPEENTRY)); |
|
QCOMPARE(sc3.readEntry("Test", QString()), QString::fromUtf8(UTF8BITENTRY)); |
|
QCOMPARE(sc3.readEntry("emptyEntry"/*, QString("Fietsbel")*/), QString("")); |
|
QCOMPARE(sc3.readEntry("emptyEntry", QString("Fietsbel")).isEmpty(), true); |
|
QCOMPARE(sc3.readEntry("stringEntry1"), QString(STRINGENTRY1)); |
|
QCOMPARE(sc3.readEntry("stringEntry2"), QString(STRINGENTRY2)); |
|
QCOMPARE(sc3.readEntry("stringEntry3"), QString(STRINGENTRY3)); |
|
QCOMPARE(sc3.readEntry("stringEntry4"), QString(STRINGENTRY4)); |
|
QVERIFY(!sc3.hasKey("stringEntry5")); |
|
QCOMPARE(sc3.readEntry("stringEntry5", QString("test")), QString("test")); |
|
QVERIFY(!sc3.hasKey("stringEntry6")); |
|
QCOMPARE(sc3.readEntry("stringEntry6", QString("foo")), QString("foo")); |
|
QCOMPARE(sc3.readEntry("urlEntry1", QUrl()), QUrl("http://qt-project.org")); |
|
QCOMPARE(sc3.readEntry("boolEntry1", BOOLENTRY1), BOOLENTRY1); |
|
QCOMPARE(sc3.readEntry("boolEntry2", false), BOOLENTRY2); |
|
QCOMPARE(sc3.readEntry("keywith=equalsign", QString("wrong")), QString(STRINGENTRY1)); |
|
QCOMPARE(sc3.readEntry("byteArrayEntry1", QByteArray()), |
|
QByteArray(STRINGENTRY1)); |
|
QCOMPARE(sc3.readEntry("doubleEntry1", 0.0), DOUBLEENTRY); |
|
QCOMPARE(sc3.readEntry("floatEntry1", 0.0f), FLOATENTRY); |
|
} |
|
|
|
void KConfigTest::testDefaults() |
|
{ |
|
KConfig config(TEST_SUBDIR "defaulttest", KConfig::NoGlobals); |
|
const QString defaultsFile = TEST_SUBDIR "defaulttest.defaults"; |
|
KConfig defaults(defaultsFile, KConfig::SimpleConfig); |
|
|
|
const QString Default("Default"); |
|
const QString NotDefault("Not Default"); |
|
const QString Value1(STRINGENTRY1); |
|
const QString Value2(STRINGENTRY2); |
|
|
|
KConfigGroup group = defaults.group("any group"); |
|
group.writeEntry("entry1", Default); |
|
QVERIFY(group.sync()); |
|
|
|
group = config.group("any group"); |
|
group.writeEntry("entry1", Value1); |
|
group.writeEntry("entry2", Value2); |
|
QVERIFY(group.sync()); |
|
|
|
config.addConfigSources(QStringList() << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/' + defaultsFile); |
|
|
|
config.setReadDefaults(true); |
|
QCOMPARE(group.readEntry("entry1", QString()), Default); |
|
QCOMPARE(group.readEntry("entry2", NotDefault), NotDefault); // no default for entry2 |
|
|
|
config.setReadDefaults(false); |
|
QCOMPARE(group.readEntry("entry1", Default), Value1); |
|
QCOMPARE(group.readEntry("entry2", NotDefault), Value2); |
|
|
|
group.revertToDefault("entry1"); |
|
QCOMPARE(group.readEntry("entry1", QString()), Default); |
|
group.revertToDefault("entry2"); |
|
QCOMPARE(group.readEntry("entry2", QString()), QString()); |
|
|
|
// TODO test reverting localized entries |
|
|
|
Q_ASSERT(config.isDirty()); |
|
group.sync(); |
|
|
|
// Check that everything is OK on disk, too |
|
KConfig reader(TEST_SUBDIR "defaulttest", KConfig::NoGlobals); |
|
reader.addConfigSources(QStringList() << QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + '/' + defaultsFile); |
|
KConfigGroup readerGroup = reader.group("any group"); |
|
QCOMPARE(readerGroup.readEntry("entry1", QString()), Default); |
|
QCOMPARE(readerGroup.readEntry("entry2", QString()), QString()); |
|
} |
|
|
|
void KConfigTest::testLocale() |
|
{ |
|
KConfig config(TEST_SUBDIR "kconfigtest.locales", KConfig::SimpleConfig); |
|
const QString Translated(TRANSLATEDSTRINGENTRY1); |
|
const QString Untranslated(STRINGENTRY1); |
|
|
|
KConfigGroup group = config.group("Hello"); |
|
group.writeEntry("stringEntry1", Untranslated); |
|
config.setLocale("fr"); |
|
group.writeEntry("stringEntry1", Translated, KConfig::Localized | KConfig::Persistent); |
|
QVERIFY(config.sync()); |
|
|
|
QCOMPARE(group.readEntry("stringEntry1", QString()), Translated); |
|
QCOMPARE(group.readEntryUntranslated("stringEntry1"), Untranslated); |
|
|
|
config.setLocale("C"); // strings written in the "C" locale are written as nonlocalized |
|
group.writeEntry("stringEntry1", Untranslated, KConfig::Localized | KConfig::Persistent); |
|
QVERIFY(config.sync()); |
|
|
|
QCOMPARE(group.readEntry("stringEntry1", QString()), Untranslated); |
|
} |
|
|
|
void KConfigTest::testEncoding() |
|
{ |
|
QString groupstr = QString::fromUtf8("UTF-8:\xc3\xb6l"); |
|
|
|
KConfig c(TEST_SUBDIR "kconfigtestencodings"); |
|
KConfigGroup cg(&c, groupstr); |
|
cg.writeEntry("key", "value"); |
|
QVERIFY(c.sync()); |
|
|
|
QList<QByteArray> lines = readLines(TEST_SUBDIR "kconfigtestencodings"); |
|
QCOMPARE(lines.count(), 2); |
|
QCOMPARE(lines.first(), QByteArray("[UTF-8:\xc3\xb6l]\n")); |
|
|
|
KConfig c2(TEST_SUBDIR "kconfigtestencodings"); |
|
KConfigGroup cg2(&c2, groupstr); |
|
QVERIFY(cg2.readEntry("key") == QByteArray("value")); |
|
|
|
QVERIFY(c2.groupList().contains(groupstr)); |
|
} |
|
|
|
void KConfigTest::testLists() |
|
{ |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup sc3(&sc2, "List Types"); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListEntry"), QStringList()), |
|
STRINGLISTENTRY); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListEmptyEntry"), QStringList("wrong")), |
|
STRINGLISTEMPTYENTRY); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListJustEmptyElement"), QStringList()), |
|
STRINGLISTJUSTEMPTYELEMENT); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListEmptyTrailingElement"), QStringList()), |
|
STRINGLISTEMPTYTRAINLINGELEMENT); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListEscapeOddEntry"), QStringList()), |
|
STRINGLISTESCAPEODDENTRY); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListEscapeEvenEntry"), QStringList()), |
|
STRINGLISTESCAPEEVENENTRY); |
|
|
|
QCOMPARE(sc3.readEntry(QString("stringListEscapeCommaEntry"), QStringList()), |
|
STRINGLISTESCAPECOMMAENTRY); |
|
|
|
QCOMPARE(sc3.readEntry("listOfIntsEntry1"), QString::fromLatin1("1,2,3,4")); |
|
QList<int> expectedIntList = INTLISTENTRY1; |
|
QVERIFY(sc3.readEntry("listOfIntsEntry1", QList<int>()) == expectedIntList); |
|
|
|
QCOMPARE(QVariant(sc3.readEntry("variantListEntry", VARIANTLISTENTRY)).toStringList(), |
|
QVariant(VARIANTLISTENTRY).toStringList()); |
|
|
|
QCOMPARE(sc3.readEntry("listOfByteArraysEntry1", QList<QByteArray>()), BYTEARRAYLISTENTRY1); |
|
} |
|
|
|
void KConfigTest::testPath() |
|
{ |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup sc3(&sc2, "Path Type"); |
|
QCOMPARE(sc3.readPathEntry("homepath", QString()), HOMEPATH); |
|
QCOMPARE(sc3.readPathEntry("homepathescape", QString()), HOMEPATHESCAPE); |
|
QCOMPARE(sc3.entryMap()["homepath"], HOMEPATH); |
|
|
|
{ |
|
QFile file(testConfigDir() + "/pathtest"); |
|
file.open(QIODevice::WriteOnly | QIODevice::Text); |
|
QTextStream out(&file); |
|
out.setCodec("UTF-8"); |
|
out << "[Test Group]" << endl |
|
<< "homePath=$HOME/foo" << endl |
|
<< "homePath2=file://$HOME/foo" << endl |
|
<< "withBraces[$e]=file://${HOME}/foo" << endl |
|
<< "URL[$e]=file://${HOME}/foo" << endl |
|
<< "hostname[$e]=$(hostname)" << endl |
|
<< "noeol=foo"; // no EOL |
|
} |
|
KConfig cf2(TEST_SUBDIR "pathtest"); |
|
KConfigGroup group = cf2.group("Test Group"); |
|
QVERIFY(group.hasKey("homePath")); |
|
QCOMPARE(group.readPathEntry("homePath", QString()), HOMEPATH); |
|
QVERIFY(group.hasKey("homePath2")); |
|
QCOMPARE(group.readPathEntry("homePath2", QString()), QString("file://" + HOMEPATH)); |
|
QVERIFY(group.hasKey("withBraces")); |
|
QCOMPARE(group.readPathEntry("withBraces", QString()), QString("file://" + HOMEPATH)); |
|
QVERIFY(group.hasKey("URL")); |
|
QCOMPARE(group.readEntry("URL", QString()), QString("file://" + HOMEPATH)); |
|
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) |
|
// I don't know if this will work on windows |
|
// This test hangs on OS X |
|
QVERIFY(group.hasKey("hostname")); |
|
char hostname[256]; |
|
QVERIFY(::gethostname(hostname, sizeof(hostname)) == 0); |
|
QCOMPARE(group.readEntry("hostname", QString()), QString::fromLatin1(hostname)); |
|
#endif |
|
QVERIFY(group.hasKey("noeol")); |
|
QCOMPARE(group.readEntry("noeol", QString()), QString("foo")); |
|
} |
|
|
|
void KConfigTest::testPersistenceOfExpandFlagForPath() |
|
{ |
|
// This test checks that a path entry starting with $HOME is still flagged |
|
// with the expand flag after the config was altered without rewriting the |
|
// path entry. |
|
|
|
// 1st step: Open the config, add a new dummy entry and then sync the config |
|
// back to the storage. |
|
{ |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup sc3(&sc2, "Path Type"); |
|
sc3.writeEntry("dummy", "dummy"); |
|
QVERIFY(sc2.sync()); |
|
} |
|
|
|
// 2nd step: Call testPath() again. Rewriting the config must not break |
|
// the testPath() test. |
|
testPath(); |
|
} |
|
|
|
void KConfigTest::testComplex() |
|
{ |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup sc3(&sc2, "Complex Types"); |
|
|
|
QCOMPARE(sc3.readEntry("pointEntry", QPoint()), POINTENTRY); |
|
QCOMPARE(sc3.readEntry("sizeEntry", SIZEENTRY), SIZEENTRY); |
|
QCOMPARE(sc3.readEntry("rectEntry", QRect(1, 2, 3, 4)), RECTENTRY); |
|
QCOMPARE(sc3.readEntry("dateTimeEntry", QDateTime()).toString(Qt::ISODate), |
|
DATETIMEENTRY.toString(Qt::ISODate)); |
|
QCOMPARE(sc3.readEntry("dateEntry", QDate()).toString(Qt::ISODate), |
|
DATETIMEENTRY.date().toString(Qt::ISODate)); |
|
QCOMPARE(sc3.readEntry("dateTimeEntry", QDate()), DATETIMEENTRY.date()); |
|
} |
|
|
|
void KConfigTest::testEnums() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup sc3(&sc, "Enum Types"); |
|
|
|
QCOMPARE(sc3.readEntry("enum-10"), QString("Tens")); |
|
QVERIFY(readEntry(sc3, "enum-100", Ones) != Ones); |
|
QVERIFY(readEntry(sc3, "enum-100", Ones) != Tens); |
|
|
|
QCOMPARE(sc3.readEntry("flags-bit0"), QString("bit0")); |
|
QVERIFY(readEntry(sc3, "flags-bit0", Flags()) == bit0); |
|
|
|
int eid = staticMetaObject.indexOfEnumerator("Flags"); |
|
QVERIFY(eid != -1); |
|
QMetaEnum me = staticMetaObject.enumerator(eid); |
|
Flags bitfield = bit0 | bit1; |
|
|
|
QCOMPARE(sc3.readEntry("flags-bit0-bit1"), QString(me.valueToKeys(bitfield))); |
|
QVERIFY(readEntry(sc3, "flags-bit0-bit1", Flags()) == bitfield); |
|
} |
|
|
|
void KConfigTest::testEntryMap() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup cg(&sc, "Hello"); |
|
QMap<QString, QString> entryMap = cg.entryMap(); |
|
qDebug() << entryMap.keys(); |
|
QCOMPARE(entryMap.value("stringEntry1"), QString(STRINGENTRY1)); |
|
QCOMPARE(entryMap.value("stringEntry2"), QString(STRINGENTRY2)); |
|
QCOMPARE(entryMap.value("stringEntry3"), QString(STRINGENTRY3)); |
|
QCOMPARE(entryMap.value("stringEntry4"), QString(STRINGENTRY4)); |
|
QVERIFY(!entryMap.contains("stringEntry5")); |
|
QVERIFY(!entryMap.contains("stringEntry6")); |
|
QCOMPARE(entryMap.value("Test"), QString::fromUtf8(UTF8BITENTRY)); |
|
QCOMPARE(entryMap.value("bytearrayEntry"), QString::fromUtf8(BYTEARRAYENTRY)); |
|
QCOMPARE(entryMap.value("emptyEntry"), QString()); |
|
QVERIFY(entryMap.contains("emptyEntry")); |
|
QCOMPARE(entryMap.value("boolEntry1"), QString(BOOLENTRY1 ? "true" : "false")); |
|
QCOMPARE(entryMap.value("boolEntry2"), QString(BOOLENTRY2 ? "true" : "false")); |
|
QCOMPARE(entryMap.value("keywith=equalsign"), QString(STRINGENTRY1)); |
|
QCOMPARE(entryMap.value("byteArrayEntry1"), QString(STRINGENTRY1)); |
|
QCOMPARE(entryMap.value("doubleEntry1"), QString::number(DOUBLEENTRY, 'g', 15)); |
|
QCOMPARE(entryMap.value("floatEntry1"), QString::number(FLOATENTRY, 'g', 8)); |
|
} |
|
|
|
void KConfigTest::testInvalid() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
|
|
// all of these should print a message to the kdebug.dbg file |
|
KConfigGroup sc3(&sc, "Invalid Types"); |
|
sc3.writeEntry("badList", VARIANTLISTENTRY2); |
|
|
|
QList<int> list; |
|
|
|
// 1 element list |
|
list << 1; |
|
sc3.writeEntry(QString("badList"), list); |
|
|
|
QVERIFY(sc3.readEntry("badList", QPoint()) == QPoint()); |
|
QVERIFY(sc3.readEntry("badList", QRect()) == QRect()); |
|
QVERIFY(sc3.readEntry("badList", QSize()) == QSize()); |
|
QVERIFY(sc3.readEntry("badList", QDate()) == QDate()); |
|
QVERIFY(sc3.readEntry("badList", QDateTime()) == QDateTime()); |
|
|
|
// 2 element list |
|
list << 2; |
|
sc3.writeEntry("badList", list); |
|
|
|
QVERIFY(sc3.readEntry("badList", QRect()) == QRect()); |
|
QVERIFY(sc3.readEntry("badList", QDate()) == QDate()); |
|
QVERIFY(sc3.readEntry("badList", QDateTime()) == QDateTime()); |
|
|
|
// 3 element list |
|
list << 303; |
|
sc3.writeEntry("badList", list); |
|
|
|
QVERIFY(sc3.readEntry("badList", QPoint()) == QPoint()); |
|
QVERIFY(sc3.readEntry("badList", QRect()) == QRect()); |
|
QVERIFY(sc3.readEntry("badList", QSize()) == QSize()); |
|
QVERIFY(sc3.readEntry("badList", QDate()) == QDate()); // out of bounds |
|
QVERIFY(sc3.readEntry("badList", QDateTime()) == QDateTime()); |
|
|
|
// 4 element list |
|
list << 4; |
|
sc3.writeEntry("badList", list); |
|
|
|
QVERIFY(sc3.readEntry("badList", QPoint()) == QPoint()); |
|
QVERIFY(sc3.readEntry("badList", QSize()) == QSize()); |
|
QVERIFY(sc3.readEntry("badList", QDate()) == QDate()); |
|
QVERIFY(sc3.readEntry("badList", QDateTime()) == QDateTime()); |
|
|
|
// 5 element list |
|
list[2] = 3; |
|
list << 5; |
|
sc3.writeEntry("badList", list); |
|
|
|
QVERIFY(sc3.readEntry("badList", QPoint()) == QPoint()); |
|
QVERIFY(sc3.readEntry("badList", QRect()) == QRect()); |
|
QVERIFY(sc3.readEntry("badList", QSize()) == QSize()); |
|
QVERIFY(sc3.readEntry("badList", QDate()) == QDate()); |
|
QVERIFY(sc3.readEntry("badList", QDateTime()) == QDateTime()); |
|
|
|
// 6 element list |
|
list << 6; |
|
sc3.writeEntry("badList", list); |
|
|
|
QVERIFY(sc3.readEntry("badList", QPoint()) == QPoint()); |
|
QVERIFY(sc3.readEntry("badList", QRect()) == QRect()); |
|
QVERIFY(sc3.readEntry("badList", QSize()) == QSize()); |
|
} |
|
|
|
void KConfigTest::testChangeGroup() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup sc3(&sc, "Hello"); |
|
QCOMPARE(sc3.name(), QString("Hello")); |
|
KConfigGroup newGroup(sc3); |
|
#ifndef KDE_NO_DEPRECATED |
|
newGroup.changeGroup("FooBar"); // deprecated! |
|
QCOMPARE(newGroup.name(), QString("FooBar")); |
|
QCOMPARE(sc3.name(), QString("Hello")); // unchanged |
|
|
|
// Write into the "changed group" and check that it works |
|
newGroup.writeEntry("InFooBar", "FB"); |
|
QCOMPARE(KConfigGroup(&sc, "FooBar").entryMap().value("InFooBar"), QString("FB")); |
|
QCOMPARE(KConfigGroup(&sc, "Hello").entryMap().value("InFooBar"), QString()); |
|
#endif |
|
|
|
KConfigGroup rootGroup(sc.group("")); |
|
QCOMPARE(rootGroup.name(), QString("<default>")); |
|
KConfigGroup sc32(rootGroup.group("Hello")); |
|
QCOMPARE(sc32.name(), QString("Hello")); |
|
KConfigGroup newGroup2(sc32); |
|
#ifndef KDE_NO_DEPRECATED |
|
newGroup2.changeGroup("FooBar"); // deprecated! |
|
QCOMPARE(newGroup2.name(), QString("FooBar")); |
|
QCOMPARE(sc32.name(), QString("Hello")); // unchanged |
|
#endif |
|
} |
|
|
|
// Simple test for deleteEntry |
|
void KConfigTest::testDeleteEntry() |
|
{ |
|
const char *configFile = TEST_SUBDIR "kconfigdeletetest"; |
|
{ |
|
KConfig conf(configFile); |
|
conf.group("Hello").writeEntry("DelKey", "ToBeDeleted"); |
|
} |
|
const QList<QByteArray> lines = readLines(configFile); |
|
Q_ASSERT(lines.contains("[Hello]\n")); |
|
Q_ASSERT(lines.contains("DelKey=ToBeDeleted\n")); |
|
|
|
KConfig sc(configFile); |
|
KConfigGroup group(&sc, "Hello"); |
|
|
|
group.deleteEntry("DelKey"); |
|
QCOMPARE(group.readEntry("DelKey", QString("Fietsbel")), QString("Fietsbel")); |
|
|
|
QVERIFY(group.sync()); |
|
Q_ASSERT(!readLines(configFile).contains("DelKey=ToBeDeleted\n")); |
|
QCOMPARE(group.readEntry("DelKey", QString("still deleted")), QString("still deleted")); |
|
} |
|
|
|
void KConfigTest::testDelete() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
|
|
KConfigGroup ct(&sc, "Complex Types"); |
|
|
|
// First delete a nested group |
|
KConfigGroup delgr(&ct, "Nested Group 3"); |
|
QVERIFY(delgr.exists()); |
|
QVERIFY(ct.hasGroup("Nested Group 3")); |
|
delgr.deleteGroup(); |
|
QVERIFY(!delgr.exists()); |
|
QVERIFY(!ct.hasGroup("Nested Group 3")); |
|
QVERIFY(ct.groupList().contains("Nested Group 3")); |
|
|
|
KConfigGroup ng(&ct, "Nested Group 2"); |
|
QVERIFY(sc.hasGroup("Complex Types")); |
|
QVERIFY(!sc.hasGroup("Does not exist")); |
|
sc.deleteGroup("Complex Types"); |
|
QCOMPARE(sc.group("Complex Types").keyList().count(), 0); |
|
QVERIFY(!sc.hasGroup("Complex Types")); // #192266 |
|
QVERIFY(!sc.group("Complex Types").exists()); |
|
QVERIFY(!ct.hasGroup("Nested Group 1")); |
|
|
|
QCOMPARE(ct.group("Nested Group 1").keyList().count(), 0); |
|
QCOMPARE(ct.group("Nested Group 2").keyList().count(), 0); |
|
QCOMPARE(ng.group("Nested Group 2.1").keyList().count(), 0); |
|
|
|
KConfigGroup cg(&sc, "AAA"); |
|
cg.deleteGroup(); |
|
QVERIFY(sc.entryMap("Complex Types").isEmpty()); |
|
QVERIFY(sc.entryMap("AAA").isEmpty()); |
|
QVERIFY(!sc.entryMap("Hello").isEmpty()); //not deleted group |
|
QVERIFY(sc.entryMap("FooBar").isEmpty()); //inexistant group |
|
|
|
QVERIFY(cg.sync()); |
|
// Check what happens on disk |
|
const QList<QByteArray> lines = readLines(); |
|
//qDebug() << lines; |
|
QVERIFY(!lines.contains("[Complex Types]\n")); |
|
QVERIFY(!lines.contains("[Complex Types][Nested Group 1]\n")); |
|
QVERIFY(!lines.contains("[Complex Types][Nested Group 2]\n")); |
|
QVERIFY(!lines.contains("[Complex Types][Nested Group 2.1]\n")); |
|
QVERIFY(!lines.contains("[AAA]\n")); |
|
QVERIFY(lines.contains("[Hello]\n")); // a group that was not deleted |
|
|
|
// test for entries that are marked as deleted when there is no default |
|
KConfig cf(TEST_SUBDIR "kconfigtest", KConfig::SimpleConfig); // make sure there are no defaults |
|
cg = cf.group("Portable Devices"); |
|
cg.writeEntry("devices|manual|(null)", "whatever"); |
|
cg.writeEntry("devices|manual|/mnt/ipod", "/mnt/ipod"); |
|
QVERIFY(cf.sync()); |
|
|
|
int count = 0; |
|
Q_FOREACH (const QByteArray &item, readLines()) |
|
if (item.startsWith("devices|")) { // krazy:exclude=strings |
|
count++; |
|
} |
|
QCOMPARE(count, 2); |
|
cg.deleteEntry("devices|manual|/mnt/ipod"); |
|
QVERIFY(cf.sync()); |
|
Q_FOREACH (const QByteArray &item, readLines()) { |
|
QVERIFY(!item.contains("ipod")); |
|
} |
|
} |
|
|
|
void KConfigTest::testDefaultGroup() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup defaultGroup(&sc, "<default>"); |
|
QCOMPARE(defaultGroup.name(), QString("<default>")); |
|
QVERIFY(!defaultGroup.exists()); |
|
defaultGroup.writeEntry("TestKey", "defaultGroup"); |
|
QVERIFY(defaultGroup.exists()); |
|
QCOMPARE(defaultGroup.readEntry("TestKey", QString()), QString("defaultGroup")); |
|
QVERIFY(sc.sync()); |
|
|
|
{ |
|
// Test reading it |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup defaultGroup2(&sc2, "<default>"); |
|
QCOMPARE(defaultGroup2.name(), QString("<default>")); |
|
QVERIFY(defaultGroup2.exists()); |
|
QCOMPARE(defaultGroup2.readEntry("TestKey", QString()), QString("defaultGroup")); |
|
} |
|
{ |
|
// Test reading it |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup emptyGroup(&sc2, ""); |
|
QCOMPARE(emptyGroup.name(), QString("<default>")); |
|
QVERIFY(emptyGroup.exists()); |
|
QCOMPARE(emptyGroup.readEntry("TestKey", QString()), QString("defaultGroup")); |
|
} |
|
|
|
QList<QByteArray> lines = readLines(); |
|
QVERIFY(!lines.contains("[]\n")); |
|
QCOMPARE(lines.first(), QByteArray("TestKey=defaultGroup\n")); |
|
|
|
// Now that the group exists make sure it isn't returned from groupList() |
|
Q_FOREACH (const QString &group, sc.groupList()) { |
|
QVERIFY(!group.isEmpty() && group != "<default>"); |
|
} |
|
|
|
defaultGroup.deleteGroup(); |
|
QVERIFY(sc.sync()); |
|
|
|
// Test if deleteGroup worked |
|
lines = readLines(); |
|
QVERIFY(lines.first() != QByteArray("TestKey=defaultGroup\n")); |
|
} |
|
|
|
void KConfigTest::testEmptyGroup() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup emptyGroup(&sc, ""); |
|
QCOMPARE(emptyGroup.name(), QString("<default>")); // confusing, heh? |
|
QVERIFY(!emptyGroup.exists()); |
|
emptyGroup.writeEntry("TestKey", "emptyGroup"); |
|
QVERIFY(emptyGroup.exists()); |
|
QCOMPARE(emptyGroup.readEntry("TestKey", QString()), QString("emptyGroup")); |
|
QVERIFY(sc.sync()); |
|
|
|
{ |
|
// Test reading it |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup defaultGroup(&sc2, "<default>"); |
|
QCOMPARE(defaultGroup.name(), QString("<default>")); |
|
QVERIFY(defaultGroup.exists()); |
|
QCOMPARE(defaultGroup.readEntry("TestKey", QString()), QString("emptyGroup")); |
|
} |
|
{ |
|
// Test reading it |
|
KConfig sc2(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup emptyGroup2(&sc2, ""); |
|
QCOMPARE(emptyGroup2.name(), QString("<default>")); |
|
QVERIFY(emptyGroup2.exists()); |
|
QCOMPARE(emptyGroup2.readEntry("TestKey", QString()), QString("emptyGroup")); |
|
} |
|
|
|
QList<QByteArray> lines = readLines(); |
|
QVERIFY(!lines.contains("[]\n")); // there's no support for the [] group, in fact. |
|
QCOMPARE(lines.first(), QByteArray("TestKey=emptyGroup\n")); |
|
|
|
// Now that the group exists make sure it isn't returned from groupList() |
|
Q_FOREACH (const QString &group, sc.groupList()) { |
|
QVERIFY(!group.isEmpty() && group != "<default>"); |
|
} |
|
emptyGroup.deleteGroup(); |
|
QVERIFY(sc.sync()); |
|
|
|
// Test if deleteGroup worked |
|
lines = readLines(); |
|
QVERIFY(lines.first() != QByteArray("TestKey=defaultGroup\n")); |
|
} |
|
|
|
void KConfigTest::testCascadingWithLocale() |
|
{ |
|
// This test relies on XDG_CONFIG_DIRS, which only has effect on Unix. |
|
// Cascading (more than two levels) isn't available at all on Windows. |
|
#ifdef Q_OS_UNIX |
|
QTemporaryDir middleDir; |
|
QTemporaryDir globalDir; |
|
qputenv("XDG_CONFIG_DIRS", qPrintable(middleDir.path() + QString(":") + globalDir.path())); |
|
|
|
const QString globalConfigDir = globalDir.path() + "/" TEST_SUBDIR; |
|
QVERIFY(QDir().mkpath(globalConfigDir)); |
|
QFile global(globalConfigDir + "foo.desktop"); |
|
QVERIFY(global.open(QIODevice::WriteOnly | QIODevice::Text)); |
|
QTextStream globalOut(&global); |
|
globalOut << "[Group]" << endl |
|
<< "FromGlobal=true" << endl |
|
<< "FromGlobal[fr]=vrai" << endl |
|
<< "Name=Testing" << endl |
|
<< "Name[fr]=FR" << endl |
|
<< "Other=Global" << endl |
|
<< "Other[fr]=Global_FR" << endl; |
|
global.close(); |
|
|
|
const QString middleConfigDir = middleDir.path() + "/" TEST_SUBDIR; |
|
QVERIFY(QDir().mkpath(middleConfigDir)); |
|
QFile local(middleConfigDir + "foo.desktop"); |
|
QVERIFY(local.open(QIODevice::WriteOnly | QIODevice::Text)); |
|
QTextStream out(&local); |
|
out << "[Group]" << endl |
|
<< "FromLocal=true" << endl |
|
<< "FromLocal[fr]=vrai" << endl |
|
<< "Name=Local Testing" << endl |
|
<< "Name[fr]=FR" << endl |
|
<< "Other=English Only" << endl; |
|
local.close(); |
|
|
|
KConfig config(TEST_SUBDIR "foo.desktop"); |
|
KConfigGroup group = config.group("Group"); |
|
QCOMPARE(group.readEntry("FromGlobal"), QString("true")); |
|
QCOMPARE(group.readEntry("FromLocal"), QString("true")); |
|
QCOMPARE(group.readEntry("Name"), QString("Local Testing")); |
|
config.setLocale("fr"); |
|
QCOMPARE(group.readEntry("FromGlobal"), QString("vrai")); |
|
QCOMPARE(group.readEntry("FromLocal"), QString("vrai")); |
|
QCOMPARE(group.readEntry("Name"), QString("FR")); |
|
QCOMPARE(group.readEntry("Other"), QString("English Only")); // Global_FR is locally overriden |
|
#endif |
|
} |
|
|
|
void KConfigTest::testMerge() |
|
{ |
|
KConfig config(TEST_SUBDIR "mergetest", KConfig::SimpleConfig); |
|
|
|
KConfigGroup cg = config.group("some group"); |
|
cg.writeEntry("entry", " random entry"); |
|
cg.writeEntry("another entry", "blah blah blah"); |
|
|
|
{ |
|
// simulate writing by another process |
|
QFile file(testConfigDir() + "/mergetest"); |
|
file.open(QIODevice::WriteOnly | QIODevice::Text); |
|
QTextStream out(&file); |
|
out.setCodec("UTF-8"); |
|
out << "[Merged Group]" << endl |
|
<< "entry1=Testing" << endl |
|
<< "entry2=More Testing" << endl |
|
<< "[some group]" << endl |
|
<< "entry[fr]=French" << endl |
|
<< "entry[es]=Spanish" << endl |
|
<< "entry[de]=German" << endl; |
|
} |
|
QVERIFY(config.sync()); |
|
|
|
{ |
|
QList<QByteArray> lines; |
|
// this is what the file should look like |
|
lines << "[Merged Group]\n" |
|
<< "entry1=Testing\n" |
|
<< "entry2=More Testing\n" |
|
<< "\n" |
|
<< "[some group]\n" |
|
<< "another entry=blah blah blah\n" |
|
<< "entry=\\srandom entry\n" |
|
<< "entry[de]=German\n" |
|
<< "entry[es]=Spanish\n" |
|
<< "entry[fr]=French\n"; |
|
QFile file(testConfigDir() + "/mergetest"); |
|
file.open(QIODevice::ReadOnly | QIODevice::Text); |
|
Q_FOREACH (const QByteArray &line, lines) { |
|
QCOMPARE(line, file.readLine()); |
|
} |
|
} |
|
} |
|
|
|
void KConfigTest::testImmutable() |
|
{ |
|
{ |
|
QFile file(testConfigDir() + "/immutabletest"); |
|
file.open(QIODevice::WriteOnly | QIODevice::Text); |
|
QTextStream out(&file); |
|
out.setCodec("UTF-8"); |
|
out << "[$i]" << endl |
|
<< "entry1=Testing" << endl |
|
<< "[group][$i]" << endl |
|
<< "[group][subgroup][$i]" << endl; |
|
} |
|
|
|
KConfig config(TEST_SUBDIR "immutabletest", KConfig::SimpleConfig); |
|
QVERIFY(config.isGroupImmutable(QByteArray())); |
|
KConfigGroup cg = config.group(QByteArray()); |
|
QVERIFY(cg.isEntryImmutable("entry1")); |
|
KConfigGroup cg1 = config.group("group"); |
|
QVERIFY(cg1.isImmutable()); |
|
KConfigGroup cg1a = cg.group("group"); |
|
QVERIFY(cg1a.isImmutable()); |
|
KConfigGroup cg2 = cg1.group("subgroup"); |
|
QVERIFY(cg2.isImmutable()); |
|
} |
|
|
|
void KConfigTest::testOptionOrder() |
|
{ |
|
{ |
|
QFile file(testConfigDir() + "/doubleattrtest"); |
|
file.open(QIODevice::WriteOnly | QIODevice::Text); |
|
QTextStream out(&file); |
|
out.setCodec("UTF-8"); |
|
out << "[group3]" << endl |
|
<< "entry2=unlocalized" << endl |
|
<< "entry2[$i][de_DE]=t2" << endl; |
|
} |
|
KConfig config(TEST_SUBDIR "doubleattrtest", KConfig::SimpleConfig); |
|
config.setLocale("de_DE"); |
|
KConfigGroup cg3 = config.group("group3"); |
|
QVERIFY(!cg3.isImmutable()); |
|
QCOMPARE(cg3.readEntry("entry2", ""), QString("t2")); |
|
QVERIFY(cg3.isEntryImmutable("entry2")); |
|
config.setLocale("C"); |
|
QCOMPARE(cg3.readEntry("entry2", ""), QString("unlocalized")); |
|
QVERIFY(!cg3.isEntryImmutable("entry2")); |
|
cg3.writeEntry("entry2", "modified"); |
|
QVERIFY(config.sync()); |
|
|
|
{ |
|
QList<QByteArray> lines; |
|
// this is what the file should look like |
|
lines << "[group3]\n" |
|
<< "entry2=modified\n" |
|
<< "entry2[de_DE][$i]=t2\n"; |
|
|
|
QFile file(testConfigDir() + "/doubleattrtest"); |
|
file.open(QIODevice::ReadOnly | QIODevice::Text); |
|
Q_FOREACH (const QByteArray &line, lines) { |
|
QCOMPARE(line, file.readLine()); |
|
} |
|
} |
|
} |
|
|
|
void KConfigTest::testGroupEscape() |
|
{ |
|
KConfig config(TEST_SUBDIR "groupescapetest", KConfig::SimpleConfig); |
|
QVERIFY(config.group(DOLLARGROUP).exists()); |
|
} |
|
|
|
void KConfigTest::testSubGroup() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup cg(&sc, "ParentGroup"); |
|
QCOMPARE(cg.readEntry("parentgrpstring", ""), QString("somevalue")); |
|
KConfigGroup subcg1(&cg, "SubGroup1"); |
|
QCOMPARE(subcg1.name(), QString("SubGroup1")); |
|
QCOMPARE(subcg1.readEntry("somestring", ""), QString("somevalue")); |
|
KConfigGroup subcg2(&cg, "SubGroup2"); |
|
QCOMPARE(subcg2.name(), QString("SubGroup2")); |
|
QCOMPARE(subcg2.readEntry("substring", ""), QString("somevalue")); |
|
KConfigGroup subcg3(&cg, "SubGroup/3"); |
|
QCOMPARE(subcg3.readEntry("sub3string", ""), QString("somevalue")); |
|
QCOMPARE(subcg3.name(), QString("SubGroup/3")); |
|
KConfigGroup rcg(&sc, ""); |
|
KConfigGroup srcg(&rcg, "ParentGroup"); |
|
QCOMPARE(srcg.readEntry("parentgrpstring", ""), QString("somevalue")); |
|
|
|
QStringList groupList = cg.groupList(); |
|
groupList.sort(); // comes from QSet, so order is undefined |
|
QCOMPARE(groupList, (QStringList() << "SubGroup/3" << "SubGroup1" << "SubGroup2")); |
|
|
|
const QStringList expectedSubgroup3Keys = (QStringList() << "sub3string"); |
|
QCOMPARE(subcg3.keyList(), expectedSubgroup3Keys); |
|
const QStringList expectedParentGroupKeys(QStringList() << "parentgrpstring"); |
|
|
|
QCOMPARE(cg.keyList(), expectedParentGroupKeys); |
|
|
|
QCOMPARE(QStringList(cg.entryMap().keys()), expectedParentGroupKeys); |
|
QCOMPARE(QStringList(subcg3.entryMap().keys()), expectedSubgroup3Keys); |
|
|
|
// Create A group containing only other groups. We want to make sure it |
|
// shows up in groupList of sc |
|
KConfigGroup neg(&sc, "NoEntryGroup"); |
|
KConfigGroup negsub1(&neg, "NEG Child1"); |
|
negsub1.writeEntry("entry", "somevalue"); |
|
KConfigGroup negsub2(&neg, "NEG Child2"); |
|
KConfigGroup negsub3(&neg, "NEG Child3"); |
|
KConfigGroup negsub31(&negsub3, "NEG Child3-1"); |
|
KConfigGroup negsub4(&neg, "NEG Child4"); |
|
KConfigGroup negsub41(&negsub4, "NEG Child4-1"); |
|
negsub41.writeEntry("entry", "somevalue"); |
|
|
|
// A group exists if it has content |
|
QVERIFY(negsub1.exists()); |
|
|
|
// But it doesn't exist if it has no content |
|
// Ossi and David say: this is how it's supposed to work. |
|
// However you could add a dummy entry for now, or we could add a "Persist" feature to kconfig groups |
|
// which would make it written out, much like "immutable" already makes them persistent. |
|
QVERIFY(!negsub2.exists()); |
|
|
|
// A subgroup does not qualify as content if it is also empty |
|
QVERIFY(!negsub3.exists()); |
|
|
|
// A subgroup with content is ok |
|
QVERIFY(negsub4.exists()); |
|
|
|
// Only subgroups with content show up in groupList() |
|
//QEXPECT_FAIL("", "Empty subgroups do not show up in groupList()", Continue); |
|
//QCOMPARE(neg.groupList(), QStringList() << "NEG Child1" << "NEG Child2" << "NEG Child3" << "NEG Child4"); |
|
// This is what happens |
|
QStringList groups = neg.groupList(); |
|
groups.sort(); // Qt5 made the ordering unreliable, due to QHash |
|
QCOMPARE(groups, QStringList() << "NEG Child1" << "NEG Child4"); |
|
|
|
// make sure groupList() isn't returning something it shouldn't |
|
Q_FOREACH (const QString &group, sc.groupList()) { |
|
QVERIFY(!group.isEmpty() && group != "<default>"); |
|
QVERIFY(!group.contains(QChar(0x1d))); |
|
QVERIFY(!group.contains("subgroup")); |
|
QVERIFY(!group.contains("SubGroup")); |
|
} |
|
|
|
QVERIFY(sc.sync()); |
|
|
|
// Check that the empty groups are not written out. |
|
const QList<QByteArray> lines = readLines(); |
|
QVERIFY(lines.contains("[NoEntryGroup][NEG Child1]\n")); |
|
QVERIFY(!lines.contains("[NoEntryGroup][NEG Child2]\n")); |
|
QVERIFY(!lines.contains("[NoEntryGroup][NEG Child3]\n")); |
|
QVERIFY(!lines.contains("[NoEntryGroup][NEG Child4]\n")); // implicit group, not written out |
|
QVERIFY(lines.contains("[NoEntryGroup][NEG Child4][NEG Child4-1]\n")); |
|
} |
|
|
|
void KConfigTest::testAddConfigSources() |
|
{ |
|
KConfig cf(TEST_SUBDIR "specificrc"); |
|
|
|
cf.addConfigSources(QStringList() << testConfigDir() + "/baserc"); |
|
cf.reparseConfiguration(); |
|
|
|
KConfigGroup specificgrp(&cf, "Specific Only Group"); |
|
QCOMPARE(specificgrp.readEntry("ExistingEntry", ""), QString("DevValue")); |
|
|
|
KConfigGroup sharedgrp(&cf, "Shared Group"); |
|
QCOMPARE(sharedgrp.readEntry("SomeSpecificOnlyEntry", ""), QString("DevValue")); |
|
QCOMPARE(sharedgrp.readEntry("SomeBaseOnlyEntry", ""), QString("BaseValue")); |
|
QCOMPARE(sharedgrp.readEntry("SomeSharedEntry", ""), QString("DevValue")); |
|
|
|
KConfigGroup basegrp(&cf, "Base Only Group"); |
|
QCOMPARE(basegrp.readEntry("ExistingEntry", ""), QString("BaseValue")); |
|
basegrp.writeEntry("New Entry Base Only", "SomeValue"); |
|
|
|
KConfigGroup newgrp(&cf, "New Group"); |
|
newgrp.writeEntry("New Entry", "SomeValue"); |
|
|
|
QVERIFY(cf.sync()); |
|
|
|
KConfig plaincfg(TEST_SUBDIR "specificrc"); |
|
|
|
KConfigGroup newgrp2(&plaincfg, "New Group"); |
|
QCOMPARE(newgrp2.readEntry("New Entry", ""), QString("SomeValue")); |
|
|
|
KConfigGroup basegrp2(&plaincfg, "Base Only Group"); |
|
QCOMPARE(basegrp2.readEntry("New Entry Base Only", ""), QString("SomeValue")); |
|
} |
|
|
|
void KConfigTest::testGroupCopyTo() |
|
{ |
|
KConfig cf1(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup original = cf1.group("Enum Types"); |
|
|
|
KConfigGroup copy = cf1.group("Enum Types Copy"); |
|
original.copyTo(©); // copy from one group to another |
|
QCOMPARE(copy.entryMap(), original.entryMap()); |
|
|
|
KConfig cf2(TEST_SUBDIR "copy_of_kconfigtest", KConfig::SimpleConfig); |
|
QVERIFY(!cf2.hasGroup(original.name())); |
|
QVERIFY(!cf2.hasGroup(copy.name())); |
|
|
|
KConfigGroup newGroup = cf2.group(original.name()); |
|
original.copyTo(&newGroup); // copy from one file to another |
|
QVERIFY(cf2.hasGroup(original.name())); |
|
QVERIFY(!cf2.hasGroup(copy.name())); // make sure we didn't copy more than we wanted |
|
QCOMPARE(newGroup.entryMap(), original.entryMap()); |
|
} |
|
|
|
void KConfigTest::testConfigCopyToSync() |
|
{ |
|
KConfig cf1(TEST_SUBDIR "kconfigtest"); |
|
// Prepare source file |
|
KConfigGroup group(&cf1, "CopyToTest"); |
|
group.writeEntry("Type", "Test"); |
|
QVERIFY(cf1.sync()); |
|
|
|
// Copy to "destination" |
|
const QString destination = testConfigDir() + "/kconfigcopytotest"; |
|
QFile::remove(destination); |
|
|
|
KConfig cf2(TEST_SUBDIR "kconfigcopytotest"); |
|
KConfigGroup group2(&cf2, "CopyToTest"); |
|
|
|
group.copyTo(&group2); |
|
|
|
QString testVal = group2.readEntry("Type"); |
|
QCOMPARE(testVal, QString("Test")); |
|
// should write to disk the copied data from group |
|
QVERIFY(cf2.sync()); |
|
QVERIFY(QFile::exists(destination)); |
|
} |
|
|
|
void KConfigTest::testConfigCopyTo() |
|
{ |
|
KConfig cf1(TEST_SUBDIR "kconfigtest"); |
|
{ |
|
// Prepare source file |
|
KConfigGroup group(&cf1, "CopyToTest"); |
|
group.writeEntry("Type", "Test"); |
|
QVERIFY(cf1.sync()); |
|
} |
|
|
|
{ |
|
// Copy to "destination" |
|
const QString destination = testConfigDir() + "/kconfigcopytotest"; |
|
QFile::remove(destination); |
|
KConfig cf2; |
|
cf1.copyTo(destination, &cf2); |
|
KConfigGroup group2(&cf2, "CopyToTest"); |
|
QString testVal = group2.readEntry("Type"); |
|
QCOMPARE(testVal, QString("Test")); |
|
QVERIFY(cf2.sync()); |
|
QVERIFY(QFile::exists(destination)); |
|
} |
|
|
|
// Check copied config file on disk |
|
KConfig cf3(TEST_SUBDIR "kconfigcopytotest"); |
|
KConfigGroup group3(&cf3, "CopyToTest"); |
|
QString testVal = group3.readEntry("Type"); |
|
QCOMPARE(testVal, QString("Test")); |
|
} |
|
|
|
void KConfigTest::testReparent() |
|
{ |
|
KConfig cf(TEST_SUBDIR "kconfigtest"); |
|
const QString name("Enum Types"); |
|
KConfigGroup group = cf.group(name); |
|
const QMap<QString, QString> originalMap = group.entryMap(); |
|
KConfigGroup parent = cf.group("Parent Group"); |
|
|
|
QVERIFY(!parent.hasGroup(name)); |
|
|
|
QVERIFY(group.entryMap() == originalMap); |
|
|
|
group.reparent(&parent); // see if it can be made a sub-group of another group |
|
QVERIFY(parent.hasGroup(name)); |
|
QCOMPARE(group.entryMap(), originalMap); |
|
|
|
group.reparent(&cf); // see if it can make it a top-level group again |
|
// QVERIFY(!parent.hasGroup(name)); |
|
QCOMPARE(group.entryMap(), originalMap); |
|
} |
|
|
|
static void ageTimeStamp(const QString &path, int nsec) |
|
{ |
|
#ifdef Q_OS_UNIX |
|
QDateTime mtime = QFileInfo(path).lastModified().addSecs(-nsec); |
|
struct utimbuf utbuf; |
|
utbuf.actime = mtime.toTime_t(); |
|
utbuf.modtime = utbuf.actime; |
|
utime(QFile::encodeName(path), &utbuf); |
|
#else |
|
QTest::qSleep(nsec * 1000); |
|
#endif |
|
} |
|
|
|
void KConfigTest::testWriteOnSync() |
|
{ |
|
QDateTime oldStamp, newStamp; |
|
KConfig sc(TEST_SUBDIR "kconfigtest", KConfig::IncludeGlobals); |
|
|
|
// Age the timestamp of global config file a few sec, and collect it. |
|
QString globFile = kdeGlobalsPath(); |
|
ageTimeStamp(globFile, 2); // age 2 sec |
|
oldStamp = QFileInfo(globFile).lastModified(); |
|
|
|
// Add a local entry and sync the config. |
|
// Should not rewrite the global config file. |
|
KConfigGroup cgLocal(&sc, "Locals"); |
|
cgLocal.writeEntry("someLocalString", "whatever"); |
|
QVERIFY(sc.sync()); |
|
|
|
// Verify that the timestamp of global config file didn't change. |
|
newStamp = QFileInfo(globFile).lastModified(); |
|
QCOMPARE(newStamp, oldStamp); |
|
|
|
// Age the timestamp of local config file a few sec, and collect it. |
|
QString locFile = testConfigDir() + "/kconfigtest"; |
|
ageTimeStamp(locFile, 2); // age 2 sec |
|
oldStamp = QFileInfo(locFile).lastModified(); |
|
|
|
// Add a global entry and sync the config. |
|
// Should not rewrite the local config file. |
|
KConfigGroup cgGlobal(&sc, "Globals"); |
|
cgGlobal.writeEntry("someGlobalString", "whatever", |
|
KConfig::Persistent | KConfig::Global); |
|
QVERIFY(sc.sync()); |
|
|
|
// Verify that the timestamp of local config file didn't change. |
|
newStamp = QFileInfo(locFile).lastModified(); |
|
QCOMPARE(newStamp, oldStamp); |
|
} |
|
|
|
void KConfigTest::testFailOnReadOnlyFileSync() |
|
{ |
|
KConfig sc(TEST_SUBDIR "kconfigfailonreadonlytest"); |
|
KConfigGroup cgLocal(&sc, "Locals"); |
|
|
|
cgLocal.writeEntry("someLocalString", "whatever"); |
|
QVERIFY(cgLocal.sync()); |
|
|
|
QFile f(testConfigDir() + "kconfigfailonreadonlytest"); |
|
QVERIFY(f.exists()); |
|
QVERIFY(f.setPermissions(QFileDevice::ReadOwner)); |
|
|
|
cgLocal.writeEntry("someLocalString", "whatever2"); |
|
QVERIFY(!cgLocal.sync()); |
|
|
|
QVERIFY(f.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner)); |
|
QVERIFY(f.remove()); |
|
} |
|
|
|
void KConfigTest::testDirtyOnEqual() |
|
{ |
|
QDateTime oldStamp, newStamp; |
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
|
|
// Initialize value |
|
KConfigGroup cgLocal(&sc, "random"); |
|
cgLocal.writeEntry("theKey", "whatever"); |
|
QVERIFY(sc.sync()); |
|
|
|
// Age the timestamp of local config file a few sec, and collect it. |
|
QString locFile = testConfigDir() + "/kconfigtest"; |
|
ageTimeStamp(locFile, 2); // age 2 sec |
|
oldStamp = QFileInfo(locFile).lastModified(); |
|
|
|
// Write exactly the same again |
|
cgLocal.writeEntry("theKey", "whatever"); |
|
// This should be a no-op |
|
QVERIFY(sc.sync()); |
|
|
|
// Verify that the timestamp of local config file didn't change. |
|
newStamp = QFileInfo(locFile).lastModified(); |
|
QCOMPARE(newStamp, oldStamp); |
|
} |
|
|
|
void KConfigTest::testDirtyOnEqualOverdo() |
|
{ |
|
QByteArray val1("\0""one", 4); |
|
QByteArray val2("\0""two", 4); |
|
QByteArray defvalr; |
|
|
|
KConfig sc(TEST_SUBDIR "kconfigtest"); |
|
KConfigGroup cgLocal(&sc, "random"); |
|
cgLocal.writeEntry("someKey", val1); |
|
QCOMPARE(cgLocal.readEntry("someKey", defvalr), val1); |
|
cgLocal.writeEntry("someKey", val2); |
|
QCOMPARE(cgLocal.readEntry("someKey", defvalr), val2); |
|
} |
|
|
|
void KConfigTest::testCreateDir() |
|
{ |
|
// Test auto-creating the parent directory when needed (KConfigIniBackend::createEnclosing) |
|
QString kdehome = QDir::home().canonicalPath() + "/.kde-unit-test"; |
|
QString subdir = kdehome + "/newsubdir"; |
|
QString file = subdir + "/foo.desktop"; |
|
QFile::remove(file); |
|
QDir().rmdir(subdir); |
|
QVERIFY(!QDir().exists(subdir)); |
|
KDesktopFile desktopFile(file); |
|
desktopFile.desktopGroup().writeEntry("key", "value"); |
|
QVERIFY(desktopFile.sync()); |
|
QVERIFY(QFile::exists(file)); |
|
|
|
// Cleanup |
|
QFile::remove(file); |
|
QDir().rmdir(subdir); |
|
} |
|
|
|
void KConfigTest::testSyncOnExit() |
|
{ |
|
// Often, the KGlobalPrivate global static's destructor ends up calling ~KConfig -> |
|
// KConfig::sync ... and if that code triggers KGlobal code again then things could crash. |
|
// So here's a test for modifying KSharedConfig::openConfig() and not syncing, the process exit will sync. |
|
KConfigGroup grp(KSharedConfig::openConfig(TEST_SUBDIR "syncOnExitRc"), "syncOnExit"); |
|
grp.writeEntry("key", "value"); |
|
} |
|
|
|
void KConfigTest::testSharedConfig() |
|
{ |
|
// Can I use a KConfigGroup even after the KSharedConfigPtr goes out of scope? |
|
KConfigGroup myConfigGroup; |
|
{ |
|
KSharedConfigPtr config = KSharedConfig::openConfig(TEST_SUBDIR "kconfigtest"); |
|
myConfigGroup = KConfigGroup(config, "Hello"); |
|
} |
|
QCOMPARE(myConfigGroup.readEntry("stringEntry1"), QString(STRINGENTRY1)); |
|
} |
|
|
|
void KConfigTest::testLocaleConfig() |
|
{ |
|
// Initialize the testdata |
|
QDir dir; |
|
QString subdir = testConfigDir(); |
|
dir.mkpath(subdir); |
|
QString file = subdir + "/localized.test"; |
|
QFile::remove(file); |
|
QFile f(file); |
|
QVERIFY(f.open(QIODevice::WriteOnly)); |
|
QTextStream ts(&f); |
|
ts << "[Test_Wrong]\n"; |
|
ts << "foo[ca]=5\n"; |
|
ts << "foostring[ca]=nice\n"; |
|
ts << "foobool[ca]=true\n"; |
|
ts << "[Test_Right]\n"; |
|
ts << "foo=5\n"; |
|
ts << "foo[ca]=5\n"; |
|
ts << "foostring=primary\n"; |
|
ts << "foostring[ca]=nice\n"; |
|
ts << "foobool=primary\n"; |
|
ts << "foobool[ca]=true\n"; |
|
f.close(); |
|
|
|
// Load the testdata |
|
QVERIFY(QFile::exists(file)); |
|
KConfig config(file); |
|
config.setLocale("ca"); |
|
|
|
// This group has only localized values. That is not supported. The values |
|
// should be dropped on loading. |
|
KConfigGroup cg(&config, "Test_Wrong"); |
|
QEXPECT_FAIL("", "The localized values are not dropped", Continue); |
|
QVERIFY(!cg.hasKey("foo")); |
|
QEXPECT_FAIL("", "The localized values are not dropped", Continue); |
|
QVERIFY(!cg.hasKey("foostring")); |
|
QEXPECT_FAIL("", "The localized values are not dropped", Continue); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
|
|
// Now check the correct config group |
|
KConfigGroup cg2(&config, "Test_Right"); |
|
QCOMPARE(cg2.readEntry("foo"), QString("5")); |
|
QCOMPARE(cg2.readEntry("foo", 3), 5); |
|
QCOMPARE(cg2.readEntry("foostring"), QString("nice")); |
|
QCOMPARE(cg2.readEntry("foostring", "ugly"), QString("nice")); |
|
QCOMPARE(cg2.readEntry("foobool"), QString("true")); |
|
QCOMPARE(cg2.readEntry("foobool", false), true); |
|
|
|
// Clean up after the testcase |
|
QFile::remove(file); |
|
} |
|
|
|
void KConfigTest::testDeleteWhenLocalized() |
|
{ |
|
// Initialize the testdata |
|
QDir dir; |
|
QString subdir = QDir::home().canonicalPath() + "/.kde-unit-test/"; |
|
dir.mkpath(subdir); |
|
QString file = subdir + "/localized_delete.test"; |
|
QFile::remove(file); |
|
QFile f(file); |
|
QVERIFY(f.open(QIODevice::WriteOnly)); |
|
QTextStream ts(&f); |
|
ts << "[Test4711]\n"; |
|
ts << "foo=3\n"; |
|
ts << "foo[ca]=5\n"; |
|
ts << "foo[de]=7\n"; |
|
ts << "foostring=ugly\n"; |
|
ts << "foostring[ca]=nice\n"; |
|
ts << "foostring[de]=schoen\n"; |
|
ts << "foobool=false\n"; |
|
ts << "foobool[ca]=true\n"; |
|
ts << "foobool[de]=true\n"; |
|
f.close(); |
|
|
|
// Load the testdata. We start in locale "ca". |
|
QVERIFY(QFile::exists(file)); |
|
KConfig config(file); |
|
config.setLocale("ca"); |
|
KConfigGroup cg(&config, "Test4711"); |
|
|
|
// Delete a value. Once with localized, once with Normal |
|
cg.deleteEntry("foostring", KConfigBase::Persistent | KConfigBase::Localized); |
|
cg.deleteEntry("foobool"); |
|
QVERIFY(config.sync()); |
|
|
|
// The value is now gone. The others are still there. Everything correct |
|
// here. |
|
QVERIFY(!cg.hasKey("foostring")); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
QVERIFY(cg.hasKey("foo")); |
|
|
|
// The current state is: (Just return before this comment.) |
|
// [...] |
|
// foobool[ca]=true |
|
// foobool[de]=wahr |
|
// foostring=ugly |
|
// foostring[de]=schoen |
|
|
|
// Now switch the locale to "de" and repeat the checks. Results should be |
|
// the same. But they currently are not. The localized value are |
|
// independent of each other. All values are still there in "de". |
|
config.setLocale("de"); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foostring")); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
QVERIFY(cg.hasKey("foo")); |
|
// Check where the wrong values come from. |
|
// We get the "de" value. |
|
QCOMPARE(cg.readEntry("foostring", "nothing"), QString("schoen")); |
|
// We get the "de" value. |
|
QCOMPARE(cg.readEntry("foobool", false), true); |
|
|
|
// Now switch the locale back "ca" and repeat the checks. Results are |
|
// again different. |
|
config.setLocale("ca"); |
|
// This line worked above. But now it fails. |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foostring")); |
|
// This line worked above too. |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
QVERIFY(cg.hasKey("foo")); |
|
// Check where the wrong values come from. |
|
// We get the primary value because the "ca" value was deleted. |
|
QCOMPARE(cg.readEntry("foostring", "nothing"), QString("ugly")); |
|
// We get the "ca" value. |
|
QCOMPARE(cg.readEntry("foobool", false), true); |
|
|
|
// Now test the deletion of a group. |
|
cg.deleteGroup(); |
|
QVERIFY(config.sync()); |
|
|
|
// Current state: [ca] and [de] entries left... oops. |
|
//qDebug() << readLinesFrom(file); |
|
|
|
// Bug: The group still exists [because of the localized entries]... |
|
QVERIFY(cg.exists()); |
|
QVERIFY(!cg.hasKey("foo")); |
|
QVERIFY(!cg.hasKey("foostring")); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
|
|
// Now switch the locale to "de" and repeat the checks. All values |
|
// still here because only the primary values are deleted. |
|
config.setLocale("de"); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foo")); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foostring")); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
// Check where the wrong values come from. |
|
// We get the "de" value. |
|
QCOMPARE(cg.readEntry("foostring", "nothing"), QString("schoen")); |
|
// We get the "de" value. |
|
QCOMPARE(cg.readEntry("foobool", false), true); |
|
// We get the "de" value. |
|
QCOMPARE(cg.readEntry("foo", 0), 7); |
|
|
|
// Now switch the locale to "ca" and repeat the checks |
|
// "foostring" is now really gone because both the primary value and the |
|
// "ca" value are deleted. |
|
config.setLocale("ca"); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foo")); |
|
QVERIFY(!cg.hasKey("foostring")); |
|
QEXPECT_FAIL("", "Currently localized values are not deleted correctly", Continue); |
|
QVERIFY(!cg.hasKey("foobool")); |
|
// Check where the wrong values come from. |
|
// We get the "ca" value. |
|
QCOMPARE(cg.readEntry("foobool", false), true); |
|
// We get the "ca" value. |
|
QCOMPARE(cg.readEntry("foo", 0), 5); |
|
|
|
// Cleanup |
|
QFile::remove(file); |
|
} |
|
|
|
void KConfigTest::testKdeGlobals() |
|
{ |
|
{ |
|
KConfig glob("kdeglobals"); |
|
KConfigGroup general(&glob, "General"); |
|
general.writeEntry("testKG", "1"); |
|
QVERIFY(glob.sync()); |
|
} |
|
|
|
KConfig globRead("kdeglobals"); |
|
const KConfigGroup general(&globRead, "General"); |
|
QCOMPARE(general.readEntry("testKG"), QString("1")); |
|
|
|
// Check we wrote into kdeglobals |
|
const QList<QByteArray> lines = readLines("kdeglobals"); |
|
QVERIFY(lines.contains("[General]\n")); |
|
QVERIFY(lines.contains("testKG=1\n")); |
|
|
|
// Writing using NoGlobals |
|
{ |
|
KConfig glob("kdeglobals", KConfig::NoGlobals); |
|
KConfigGroup general(&glob, "General"); |
|
general.writeEntry("testKG", "2"); |
|
QVERIFY(glob.sync()); |
|
} |
|
globRead.reparseConfiguration(); |
|
QCOMPARE(general.readEntry("testKG"), QString("2")); |
|
|
|
// Reading using NoGlobals |
|
{ |
|
KConfig globReadNoGlob("kdeglobals", KConfig::NoGlobals); |
|
const KConfigGroup generalNoGlob(&globReadNoGlob, "General"); |
|
QCOMPARE(generalNoGlob.readEntry("testKG"), QString("2")); |
|
} |
|
|
|
// TODO now use kconfigtest and writeEntry(,Global) -> should go into kdeglobals |
|
} |
|
|
|
void KConfigTest::testAnonymousConfig() |
|
{ |
|
KConfig anonConfig(QString(), KConfig::SimpleConfig); |
|
KConfigGroup general(&anonConfig, "General"); |
|
QCOMPARE(general.readEntry("testKG"), QString()); // no kdeglobals merging |
|
general.writeEntry("Foo", "Bar"); |
|
QCOMPARE(general.readEntry("Foo"), QString("Bar")); |
|
} |
|
|
|
#include <QThreadPool> |
|
#include <qtconcurrentrun.h> |
|
|
|
// To find multithreading bugs: valgrind --tool=helgrind --track-lockorders=no ./kconfigtest testThreads |
|
void KConfigTest::testThreads() |
|
{ |
|
QThreadPool::globalInstance()->setMaxThreadCount(6); |
|
QList<QFuture<void> > futures; |
|
// Run in parallel some tests that work on different config files, |
|
// otherwise unexpected things might indeed happen. |
|
futures << QtConcurrent::run(this, &KConfigTest::testAddConfigSources); |
|
futures << QtConcurrent::run(this, &KConfigTest::testSimple); |
|
futures << QtConcurrent::run(this, &KConfigTest::testDefaults); |
|
// QEXPECT_FAIL triggers race conditions, it should be fixed to use QThreadStorage... |
|
//futures << QtConcurrent::run(this, &KConfigTest::testDeleteWhenLocalized); |
|
//futures << QtConcurrent::run(this, &KConfigTest::testEntryMap); |
|
Q_FOREACH (QFuture<void> f, futures) { // krazy:exclude=foreach |
|
f.waitForFinished(); |
|
} |
|
}
|
|
|