forked from qt-creator/qt-creator
toString() is almost always the wrong conversion, but unfortunately too easy to find and often even working at least for local setup. This here raises the bar as the non-availability of the "obvious" toString() hopefully helps people to think about the semantics of the needed conversion and choose the right toXXX() function. The chosen new name is intentional ugly to reduce the likelihood that this (still almost always wrong) function is used out of convenience. Change-Id: I57f1618dd95ef2629d7d978688d130275e096c0f Reviewed-by: Eike Ziller <eike.ziller@qt.io>
734 lines
26 KiB
C++
734 lines
26 KiB
C++
// Copyright (C) 2017 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include <utils/algorithm.h>
|
|
#include <utils/settingsaccessor.h>
|
|
|
|
#include <QTemporaryDir>
|
|
|
|
#include <QtTest>
|
|
|
|
using namespace Utils;
|
|
|
|
const char TESTACCESSOR_APPLICATION_DN[] = "SettingsAccessor Test (Basic)";
|
|
const char TESTACCESSOR_DEFAULT_ID[] = "testId";
|
|
|
|
Store generateExtraData()
|
|
{
|
|
Store extra;
|
|
extra.insert("Foo", "Bar");
|
|
extra.insert("Int", 42);
|
|
return extra;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// TestVersionUpgrader:
|
|
// --------------------------------------------------------------------
|
|
|
|
class TestVersionUpgrader : public VersionUpgrader
|
|
{
|
|
public:
|
|
TestVersionUpgrader(int version)
|
|
: VersionUpgrader(version, "v" + QString::number(version))
|
|
{ }
|
|
|
|
Store upgrade(const Store &data) final
|
|
{
|
|
Store result = data;
|
|
result.insert(numberedKey("VERSION_", version()), version());
|
|
return result;
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
// BasicTestSettingsAccessor:
|
|
// --------------------------------------------------------------------
|
|
|
|
class BasicTestSettingsAccessor : public MergingSettingsAccessor
|
|
{
|
|
public:
|
|
BasicTestSettingsAccessor(const FilePath &baseName = "/foo/bar",
|
|
const QByteArray &id = QByteArray(TESTACCESSOR_DEFAULT_ID));
|
|
|
|
using MergingSettingsAccessor::addVersionUpgrader;
|
|
|
|
QHash<FilePath, Store> files() const { return m_files; }
|
|
void addFile(const FilePath &path, const Store &data) const { m_files.insert(path, data); }
|
|
FilePaths fileNames() const { return m_files.keys(); }
|
|
Store fileContents(const FilePath &path) const { return m_files.value(path); }
|
|
|
|
protected:
|
|
RestoreData readFile(const FilePath &path) const override
|
|
{
|
|
if (!m_files.contains(path))
|
|
return RestoreData("File not found.", "File not found.", Issue::Type::ERROR);
|
|
|
|
return RestoreData(path, m_files.value(path));
|
|
}
|
|
|
|
SettingsMergeResult merge(const SettingsMergeData &global,
|
|
const SettingsMergeData &local) const final
|
|
{
|
|
Q_UNUSED(global)
|
|
|
|
const Key key = local.key;
|
|
const QVariant main = local.main.value(key);
|
|
const QVariant secondary = local.secondary.value(key);
|
|
|
|
if (isHouseKeepingKey(key))
|
|
return qMakePair(key, main);
|
|
|
|
if (main.isNull() && secondary.isNull())
|
|
return std::nullopt;
|
|
if (!main.isNull())
|
|
return qMakePair(key, main);
|
|
return qMakePair(key, secondary);
|
|
}
|
|
|
|
std::optional<Issue> writeFile(const FilePath &path, const Store &data) const override
|
|
{
|
|
if (data.isEmpty()) {
|
|
return Issue("Failed to Write File", "There was nothing to write.",
|
|
Issue::Type::WARNING);
|
|
}
|
|
|
|
addFile(path, data);
|
|
return std::nullopt;
|
|
}
|
|
|
|
private:
|
|
mutable QHash<FilePath, Store> m_files;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
// TestBackUpStrategy:
|
|
// --------------------------------------------------------------------
|
|
|
|
class BasicTestSettingsAccessor;
|
|
|
|
class TestBackUpStrategy : public VersionedBackUpStrategy
|
|
{
|
|
public:
|
|
TestBackUpStrategy(BasicTestSettingsAccessor *accessor) :
|
|
VersionedBackUpStrategy(accessor)
|
|
{ }
|
|
|
|
FilePaths readFileCandidates(const FilePath &baseFileName) const override
|
|
{
|
|
return Utils::filtered(static_cast<const BasicTestSettingsAccessor *>(accessor())->fileNames(),
|
|
[&baseFileName](const FilePath &f) {
|
|
return f.parentDir() == baseFileName.parentDir() && f.toUrlishString().startsWith(baseFileName.toUrlishString());
|
|
});
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
// TestSettingsAccessor:
|
|
// --------------------------------------------------------------------
|
|
|
|
class TestSettingsAccessor : public BasicTestSettingsAccessor
|
|
{
|
|
public:
|
|
TestSettingsAccessor(const FilePath &baseName = "/foo/baz",
|
|
const QByteArray &id = QByteArray(TESTACCESSOR_DEFAULT_ID)) :
|
|
BasicTestSettingsAccessor(baseName, id)
|
|
{
|
|
addVersionUpgrader(std::make_unique<TestVersionUpgrader>(5));
|
|
addVersionUpgrader(std::make_unique<TestVersionUpgrader>(6));
|
|
addVersionUpgrader(std::make_unique<TestVersionUpgrader>(7));
|
|
}
|
|
|
|
// Make methods public for the tests:
|
|
using MergingSettingsAccessor::upgradeSettings;
|
|
};
|
|
|
|
BasicTestSettingsAccessor::BasicTestSettingsAccessor(const FilePath &baseName, const QByteArray &id)
|
|
{
|
|
setDocType("TestData");
|
|
setApplicationDisplayName(TESTACCESSOR_APPLICATION_DN);
|
|
setStrategy(std::make_unique<TestBackUpStrategy>(this));
|
|
setSettingsId(id);
|
|
setBaseFilePath(baseName);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// tst_SettingsAccessor:
|
|
// --------------------------------------------------------------------
|
|
|
|
class tst_SettingsAccessor : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
void addVersionUpgrader();
|
|
void addVersionUpgrader_negativeVersion();
|
|
void addVersionUpgrader_v3v2();
|
|
void addVersionUpgrader_v3v5();
|
|
void addVersionUpgrader_v3v4v5();
|
|
void addVersionUpgrader_v0v1();
|
|
|
|
void isValidVersionAndId();
|
|
|
|
void RestoreDataCompare();
|
|
void RestoreDataCompare_idMismatch();
|
|
void RestoreDataCompare_noId();
|
|
void RestoreDataCompare_sameVersion();
|
|
void RestoreDataCompare_emptyMap();
|
|
void RestoreDataCompare_twoEmptyMaps();
|
|
|
|
void upgradeSettings_noUpgradeNecessary();
|
|
void upgradeSettings_invalidId();
|
|
void upgradeSettings_tooOld();
|
|
void upgradeSettings_tooNew();
|
|
void upgradeSettings_oneStep();
|
|
void upgradeSettings_twoSteps();
|
|
void upgradeSettings_partialUpdate();
|
|
void upgradeSettings_targetVersionTooOld();
|
|
void upgradeSettings_targetVersionTooNew();
|
|
|
|
#if 0
|
|
void findIssues_ok();
|
|
void findIssues_emptyData();
|
|
void findIssues_tooNew();
|
|
void findIssues_tooOld();
|
|
void findIssues_wrongId();
|
|
void findIssues_nonDefaultPath();
|
|
#endif
|
|
|
|
void saveSettings();
|
|
void loadSettings();
|
|
void loadSettings_pickBest();
|
|
};
|
|
|
|
static Store versionedMap(int version, const QByteArray &id = {}, const Store &extra = {})
|
|
{
|
|
Store result;
|
|
result.insert("Version", version);
|
|
if (!id.isEmpty())
|
|
result.insert("EnvironmentId", id);
|
|
for (auto it = extra.cbegin(); it != extra.cend(); ++it)
|
|
result.insert(it.key(), it.value());
|
|
return result;
|
|
}
|
|
|
|
static SettingsAccessor::RestoreData restoreData(const FilePath &path,
|
|
const Store &data)
|
|
{
|
|
return SettingsAccessor::RestoreData(path, data);
|
|
}
|
|
|
|
//static SettingsAccessor::RestoreData restoreData(const QByteArray &path,
|
|
// const Store &data)
|
|
//{
|
|
// return restoreData(FilePath::fromUtf8(path), data);
|
|
//}
|
|
|
|
void tst_SettingsAccessor::addVersionUpgrader()
|
|
{
|
|
BasicTestSettingsAccessor accessor;
|
|
|
|
QCOMPARE(accessor.firstSupportedVersion(), -1);
|
|
QCOMPARE(accessor.currentVersion(), 0);
|
|
|
|
}
|
|
|
|
void tst_SettingsAccessor::addVersionUpgrader_negativeVersion()
|
|
{
|
|
BasicTestSettingsAccessor accessor;
|
|
|
|
QVERIFY(!accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(-1)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), -1);
|
|
QCOMPARE(accessor.currentVersion(), 0);
|
|
}
|
|
|
|
void tst_SettingsAccessor::addVersionUpgrader_v3v2()
|
|
{
|
|
BasicTestSettingsAccessor accessor;
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(3)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 4);
|
|
|
|
QVERIFY(!accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(2)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 4);
|
|
}
|
|
|
|
void tst_SettingsAccessor::addVersionUpgrader_v3v5()
|
|
{
|
|
BasicTestSettingsAccessor accessor;
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(3)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 4);
|
|
|
|
QVERIFY(!accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(5)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 4);
|
|
}
|
|
|
|
void tst_SettingsAccessor::addVersionUpgrader_v3v4v5()
|
|
{
|
|
BasicTestSettingsAccessor accessor;
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(3)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 4);
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(4)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 5);
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(5)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 3);
|
|
QCOMPARE(accessor.currentVersion(), 6);
|
|
}
|
|
|
|
void tst_SettingsAccessor::addVersionUpgrader_v0v1()
|
|
{
|
|
BasicTestSettingsAccessor accessor;
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(0)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 0);
|
|
QCOMPARE(accessor.currentVersion(), 1);
|
|
|
|
QVERIFY(accessor.addVersionUpgrader(std::make_unique<TestVersionUpgrader>(1)));
|
|
QCOMPARE(accessor.firstSupportedVersion(), 0);
|
|
QCOMPARE(accessor.currentVersion(), 2);
|
|
}
|
|
|
|
void tst_SettingsAccessor::isValidVersionAndId()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
|
|
QVERIFY(!accessor.isValidVersionAndId(4, TESTACCESSOR_DEFAULT_ID));
|
|
QVERIFY( accessor.isValidVersionAndId(5, TESTACCESSOR_DEFAULT_ID));
|
|
QVERIFY( accessor.isValidVersionAndId(6, TESTACCESSOR_DEFAULT_ID));
|
|
QVERIFY( accessor.isValidVersionAndId(7, TESTACCESSOR_DEFAULT_ID));
|
|
QVERIFY( accessor.isValidVersionAndId(8, TESTACCESSOR_DEFAULT_ID));
|
|
QVERIFY(!accessor.isValidVersionAndId(9, TESTACCESSOR_DEFAULT_ID));
|
|
|
|
QVERIFY(!accessor.isValidVersionAndId(4, "foo"));
|
|
QVERIFY(!accessor.isValidVersionAndId(5, "foo"));
|
|
QVERIFY(!accessor.isValidVersionAndId(6, "foo"));
|
|
QVERIFY(!accessor.isValidVersionAndId(7, "foo"));
|
|
QVERIFY(!accessor.isValidVersionAndId(8, "foo"));
|
|
QVERIFY(!accessor.isValidVersionAndId(9, "foo"));
|
|
}
|
|
|
|
void tst_SettingsAccessor::RestoreDataCompare()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
|
|
SettingsAccessor::RestoreData a = restoreData("/foo/bar", versionedMap(5, TESTACCESSOR_DEFAULT_ID));
|
|
SettingsAccessor::RestoreData b = restoreData("/foo/baz", versionedMap(6, TESTACCESSOR_DEFAULT_ID));
|
|
|
|
QCOMPARE(accessor.strategy()->compare(a, a), 0);
|
|
QCOMPARE(accessor.strategy()->compare(a, b), 1);
|
|
QCOMPARE(accessor.strategy()->compare(b, a), -1);
|
|
}
|
|
|
|
void tst_SettingsAccessor::RestoreDataCompare_idMismatch()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
|
|
SettingsAccessor::RestoreData a = restoreData("/foo/bar", versionedMap(5, TESTACCESSOR_DEFAULT_ID));
|
|
SettingsAccessor::RestoreData b = restoreData("/foo/baz", versionedMap(6, "foo"));
|
|
|
|
QCOMPARE(accessor.strategy()->compare(a, b), -1);
|
|
QCOMPARE(accessor.strategy()->compare(b, a), 1);
|
|
}
|
|
|
|
void tst_SettingsAccessor::RestoreDataCompare_noId()
|
|
{
|
|
const TestSettingsAccessor accessor("/foo/baz", QByteArray());
|
|
|
|
SettingsAccessor::RestoreData a = restoreData("/foo/bar", versionedMap(5, TESTACCESSOR_DEFAULT_ID));
|
|
SettingsAccessor::RestoreData b = restoreData("/foo/baz", versionedMap(6, "foo"));
|
|
|
|
QCOMPARE(accessor.strategy()->compare(a, b), 1);
|
|
QCOMPARE(accessor.strategy()->compare(b, a), -1);
|
|
}
|
|
|
|
void tst_SettingsAccessor::RestoreDataCompare_sameVersion()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
|
|
SettingsAccessor::RestoreData a = restoreData("/foo/bar", versionedMap(7, TESTACCESSOR_DEFAULT_ID));
|
|
SettingsAccessor::RestoreData b = restoreData("/foo/baz", versionedMap(7, TESTACCESSOR_DEFAULT_ID));
|
|
|
|
QCOMPARE(accessor.strategy()->compare(a, b), 0);
|
|
QCOMPARE(accessor.strategy()->compare(b, a), 0);
|
|
}
|
|
|
|
void tst_SettingsAccessor::RestoreDataCompare_emptyMap()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
|
|
SettingsAccessor::RestoreData a = restoreData("/foo/bar", Store());
|
|
SettingsAccessor::RestoreData b = restoreData("/foo/baz", versionedMap(7, TESTACCESSOR_DEFAULT_ID));
|
|
|
|
QCOMPARE(accessor.strategy()->compare(a, b), 1);
|
|
QCOMPARE(accessor.strategy()->compare(b, a), -1);
|
|
}
|
|
|
|
void tst_SettingsAccessor::RestoreDataCompare_twoEmptyMaps()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
|
|
SettingsAccessor::RestoreData a = restoreData("/foo/bar", Store());
|
|
SettingsAccessor::RestoreData b = restoreData("/foo/baz", Store());
|
|
|
|
QCOMPARE(accessor.strategy()->compare(a, b), 0);
|
|
QCOMPARE(accessor.strategy()->compare(b, a), 0);
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_noUpgradeNecessary()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 8;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, generateExtraData()));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 8);
|
|
|
|
QVERIFY(!result.hasIssue());
|
|
for (auto it = result.data.cbegin(); it != result.data.cend(); ++it) {
|
|
if (it.key() == "OriginalVersion")
|
|
QCOMPARE(it.value().toInt(), startVersion);
|
|
else if (input.data.contains(it.key())) // extra settings pass through unchanged!
|
|
QCOMPARE(it.value(), input.data.value(it.key()));
|
|
else
|
|
QVERIFY2(false, "Unexpected value found in upgraded result!");
|
|
}
|
|
QCOMPARE(result.data.size(), input.data.size() + 1); // OriginalVersion was added
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_invalidId()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 8;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, "foo", generateExtraData()));
|
|
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 8);
|
|
|
|
// Data is unchanged
|
|
QVERIFY(result.hasWarning());
|
|
for (auto it = result.data.cbegin(); it != result.data.cend(); ++it) {
|
|
if (it.key() == "OriginalVersion")
|
|
QCOMPARE(it.value().toInt(), startVersion);
|
|
else if (input.data.contains(it.key())) // extra settings pass through unchanged!
|
|
QCOMPARE(it.value(), input.data.value(it.key()));
|
|
else
|
|
QVERIFY2(false, "Unexpected value found in upgraded result!");
|
|
}
|
|
QCOMPARE(result.data.size(), input.data.size() + 1); // OriginalVersion was added
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_tooOld()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 1;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, generateExtraData()));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 8);
|
|
|
|
// Data is unchanged
|
|
QVERIFY(result.hasIssue());
|
|
QCOMPARE(result.data, input.data);
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_tooNew()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 42;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, generateExtraData()));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 8);
|
|
|
|
// Data is unchanged
|
|
QVERIFY(result.hasIssue());
|
|
QCOMPARE(result.data, input.data);
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_oneStep()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 7;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, generateExtraData()));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 8);
|
|
|
|
QVERIFY(!result.hasIssue());
|
|
for (auto it = result.data.cbegin(); it != result.data.cend(); ++it) {
|
|
if (it.key() == "OriginalVersion") // was added
|
|
QCOMPARE(it.value().toInt(), startVersion);
|
|
else if (it.key() == "Version") // was overridden
|
|
QCOMPARE(it.value().toInt(), 8);
|
|
else if (input.data.contains(it.key())) // extra settings pass through unchanged!
|
|
QCOMPARE(it.value(), input.data.value(it.key()));
|
|
else if (it.key() == "VERSION_7")
|
|
QCOMPARE(it.value().toInt(), 7);
|
|
else
|
|
QVERIFY2(false, "Unexpected value found in upgraded result!");
|
|
}
|
|
QCOMPARE(result.data.size(), input.data.size() + 2); // OriginalVersion + VERSION_7 was added
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_twoSteps()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 6;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, generateExtraData()));
|
|
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 8);
|
|
|
|
QVERIFY(!result.hasIssue());
|
|
for (auto it = result.data.cbegin(); it != result.data.cend(); ++it) {
|
|
if (it.key() == "OriginalVersion") // was added
|
|
QCOMPARE(it.value().toInt(), startVersion);
|
|
else if (it.key() == "Version") // was overridden
|
|
QCOMPARE(it.value().toInt(), 8);
|
|
else if (input.data.contains(it.key())) // extra settings pass through unchanged!
|
|
QCOMPARE(it.value(), input.data.value(it.key()));
|
|
else if (it.key() == "VERSION_6") // was added
|
|
QCOMPARE(it.value().toInt(), 6);
|
|
else if (it.key() == "VERSION_7") // was added
|
|
QCOMPARE(it.value().toInt(), 7);
|
|
else
|
|
QVERIFY2(false, "Unexpected value found in upgraded result!");
|
|
}
|
|
QCOMPARE(result.data.size(), input.data.size() + 3); // OriginalVersion + VERSION_6 + VERSION_7 was added
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_partialUpdate()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const int startVersion = 6;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, generateExtraData()));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 7);
|
|
|
|
QVERIFY(!result.hasIssue());
|
|
for (auto it = result.data.cbegin(); it != result.data.cend(); ++it) {
|
|
if (it.key() == "OriginalVersion") // was added
|
|
QCOMPARE(it.value().toInt(), startVersion);
|
|
else if (it.key() == "Version") // was overridden
|
|
QCOMPARE(it.value().toInt(), 7);
|
|
else if (input.data.contains(it.key())) // extra settings pass through unchanged!
|
|
QCOMPARE(it.value(), input.data.value(it.key()));
|
|
else if (it.key() == "VERSION_6")
|
|
QCOMPARE(it.value().toInt(), 6);
|
|
else
|
|
QVERIFY2(false, "Unexpected value found in upgraded result!");
|
|
}
|
|
QCOMPARE(result.data.size(), input.data.size() + 2); // OriginalVersion + VERSION_6 was added
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_targetVersionTooOld()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store extra = generateExtraData();
|
|
const int startVersion = 6;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, extra));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 2);
|
|
|
|
// result is unchanged!
|
|
QVERIFY(!result.hasIssue());
|
|
QCOMPARE(result.data, input.data);
|
|
}
|
|
|
|
void tst_SettingsAccessor::upgradeSettings_targetVersionTooNew()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store extra = generateExtraData();
|
|
const int startVersion = 6;
|
|
const SettingsAccessor::RestoreData input
|
|
= restoreData(accessor.baseFilePath(),
|
|
versionedMap(startVersion, TESTACCESSOR_DEFAULT_ID, extra));
|
|
|
|
const SettingsAccessor::RestoreData result = accessor.upgradeSettings(input, 42);
|
|
|
|
// result is unchanged!
|
|
QVERIFY(!result.hasIssue());
|
|
QCOMPARE(result.data, input.data);
|
|
}
|
|
|
|
#if 0
|
|
// FIXME: Test error conditions again.
|
|
void tst_SettingsAccessor::findIssues_ok()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store data = versionedMap(6, TESTACCESSOR_DEFAULT_ID);
|
|
const FilePath path = "/foo/baz.user";
|
|
|
|
const std::optional<SettingsAccessor::Issue> info = accessor.findIssues(data, path);
|
|
|
|
QVERIFY(!info);
|
|
}
|
|
|
|
void tst_SettingsAccessor::findIssues_emptyData()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store data;
|
|
const FilePath path = "/foo/bar.user";
|
|
|
|
const std::optional<SettingsAccessor::Issue> info = accessor.findIssues(data, path);
|
|
|
|
QVERIFY(bool(info));
|
|
}
|
|
|
|
void tst_SettingsAccessor::findIssues_tooNew()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store data = versionedMap(42, TESTACCESSOR_DEFAULT_ID);
|
|
const FilePath path = "/foo/bar.user";
|
|
|
|
const std::optional<SettingsAccessor::Issue> info = accessor.findIssues(data, path);
|
|
|
|
QVERIFY(bool(info));
|
|
}
|
|
|
|
void tst_SettingsAccessor::findIssues_tooOld()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store data = versionedMap(2, TESTACCESSOR_DEFAULT_ID);
|
|
const FilePath path = "/foo/bar.user";
|
|
|
|
const std::optional<SettingsAccessor::Issue> info = accessor.findIssues(data, path);
|
|
|
|
QVERIFY(bool(info));
|
|
}
|
|
|
|
void tst_SettingsAccessor::findIssues_wrongId()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store data = versionedMap(6, "foo");
|
|
const FilePath path = "/foo/bar.user";
|
|
|
|
const std::optional<SettingsAccessor::Issue> info = accessor.findIssues(data, path);
|
|
|
|
QVERIFY(bool(info));
|
|
}
|
|
|
|
void tst_SettingsAccessor::findIssues_nonDefaultPath()
|
|
{
|
|
const TestSettingsAccessor accessor;
|
|
const Store data = versionedMap(6, TESTACCESSOR_DEFAULT_ID);
|
|
const FilePath path = "/foo/bar.user.foobar";
|
|
|
|
const std::optional<SettingsAccessor::Issue> info = accessor.findIssues(data, path);
|
|
|
|
QVERIFY(bool(info));
|
|
}
|
|
#endif
|
|
|
|
void tst_SettingsAccessor::saveSettings()
|
|
{
|
|
const FilePath baseFile = "/tmp/foo/saveSettings";
|
|
const TestSettingsAccessor accessor(baseFile);
|
|
const Store data = versionedMap(6, TESTACCESSOR_DEFAULT_ID);
|
|
|
|
QVERIFY(accessor.saveSettings(data, nullptr));
|
|
|
|
QCOMPARE(accessor.files().count(), 1);
|
|
const Store read = accessor.fileContents(baseFile);
|
|
|
|
QVERIFY(!read.isEmpty());
|
|
for (auto it = read.cbegin(); it != read.cend(); ++it) {
|
|
if (it.key() == "Version") // Version is always overridden to the latest on save!
|
|
QCOMPARE(it.value().toInt(), 8);
|
|
else if (data.contains(it.key()))
|
|
QCOMPARE(it.value(), data.value(it.key()));
|
|
else
|
|
QVERIFY2(false, "Unexpected value!");
|
|
}
|
|
QCOMPARE(read.size(), data.size());
|
|
}
|
|
|
|
void tst_SettingsAccessor::loadSettings()
|
|
{
|
|
const Store data = versionedMap(6, "loadSettings", generateExtraData());
|
|
const FilePath path = "/tmp/foo/loadSettings";
|
|
const TestSettingsAccessor accessor(path, "loadSettings");
|
|
accessor.addFile(path, data);
|
|
QCOMPARE(accessor.files().count(), 1); // Catch changes early:-)
|
|
|
|
const Store read = accessor.restoreSettings(nullptr);
|
|
QCOMPARE(accessor.files().count(), 1); // no files were created
|
|
|
|
QVERIFY(!read.isEmpty());
|
|
for (auto it = read.cbegin(); it != read.cend(); ++it) {
|
|
if (it.key() == "Version") // was overridden
|
|
QCOMPARE(it.value().toInt(), 8);
|
|
else if (it.key() == "OriginalVersion") // was added
|
|
QCOMPARE(it.value().toInt(), 6);
|
|
else if (it.key() == "VERSION_6") // was added
|
|
QCOMPARE(it.value().toInt(), 6);
|
|
else if (it.key() == "VERSION_7") // was added
|
|
QCOMPARE(it.value().toInt(), 7);
|
|
else if (data.contains(it.key()))
|
|
QCOMPARE(it.value(), data.value(it.key()));
|
|
else
|
|
QVERIFY2(false, "Unexpected value!");
|
|
}
|
|
QCOMPARE(read.size(), data.size() + 3);
|
|
}
|
|
|
|
void tst_SettingsAccessor::loadSettings_pickBest()
|
|
{
|
|
const FilePath path = "/tmp/foo/loadSettings";
|
|
const TestSettingsAccessor accessor(path, "loadSettings");
|
|
|
|
accessor.addFile(path, versionedMap(10, "loadSettings", generateExtraData())); // too new
|
|
const Store data = versionedMap(7, "loadSettings", generateExtraData());
|
|
accessor.addFile("/tmp/foo/loadSettings.foo", data); // pick this!
|
|
accessor.addFile("/tmp/foo/loadSettings.foo1",
|
|
versionedMap(8, "fooSettings", generateExtraData())); // wrong environment
|
|
accessor.addFile("/tmp/foo/loadSettings.bar",
|
|
versionedMap(6, "loadSettings", generateExtraData())); // too old
|
|
accessor.addFile("/tmp/foo/loadSettings.baz",
|
|
versionedMap(1, "loadSettings", generateExtraData())); // much too old
|
|
QCOMPARE(accessor.files().count(), 5); // Catch changes early:-)
|
|
|
|
const Store read = accessor.restoreSettings(nullptr);
|
|
QCOMPARE(accessor.files().count(), 5); // no new files
|
|
|
|
QVERIFY(!read.isEmpty());
|
|
for (auto it = read.cbegin(); it != read.cend(); ++it) {
|
|
if (it.key() == "Version") // was overridden
|
|
QCOMPARE(it.value().toInt(), 8);
|
|
else if (it.key() == "OriginalVersion") // was added
|
|
QCOMPARE(it.value().toInt(), 7);
|
|
else if (it.key() == "VERSION_7") // was added
|
|
QCOMPARE(it.value().toInt(), 7);
|
|
else if (data.contains(it.key()))
|
|
QCOMPARE(it.value(), data.value(it.key()));
|
|
else
|
|
QVERIFY2(false, "Unexpected value!");
|
|
}
|
|
QCOMPARE(read.size(), data.size() + 2);
|
|
}
|
|
|
|
QTEST_GUILESS_MAIN(tst_SettingsAccessor)
|
|
|
|
#include "tst_settings.moc"
|