logic: Application settings migration system
* Added version number to ApplicationSettings * Added SettingsMigrator for defining migration rules for different ApplicationSettings versions * Migrate ApplicationSettings when loading
This commit is contained in:
@@ -1,14 +1,17 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<config>
|
<config>
|
||||||
<application>
|
<application>
|
||||||
<indexer_thread_count>4</indexer_thread_count>
|
<window_base_height>500</window_base_height>
|
||||||
<window_base_width>500</window_base_width>
|
<window_base_width>500</window_base_width>
|
||||||
<window_base_height>500</window_base_height>
|
</application>
|
||||||
</application>
|
<indexing>
|
||||||
<user>
|
<indexer_thread_count>4</indexer_thread_count>
|
||||||
<recent_projects>
|
</indexing>
|
||||||
<recent_project>./data/projects/tutorial/tutorial.coatiproject</recent_project>
|
<user>
|
||||||
<recent_project>./data/projects/tictactoe/tictactoe.coatiproject</recent_project>
|
<recent_projects>
|
||||||
</recent_projects>
|
<recent_project>./data/projects/tutorial/tutorial.coatiproject</recent_project>
|
||||||
</user>
|
<recent_project>./data/projects/tictactoe/tictactoe.coatiproject</recent_project>
|
||||||
|
</recent_projects>
|
||||||
|
</user>
|
||||||
|
<version>1</version>
|
||||||
</config>
|
</config>
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
<!-- COLOR: int int int int - rgba e.g. 125 125 125 255 -->
|
<!-- COLOR: int int int int - rgba e.g. 125 125 125 255 -->
|
||||||
|
|
||||||
<config>
|
<config>
|
||||||
|
<version><!-- INTEGER: Version number --></version>
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
<font_name><!-- STRING: font name --></font_name>
|
<font_name><!-- STRING: font name --></font_name>
|
||||||
<font_size><!-- INTEGER: font size in pt --></font_size>
|
<font_size><!-- INTEGER: font size in pt --></font_size>
|
||||||
|
|||||||
@@ -207,6 +207,8 @@ add_files(
|
|||||||
settings/ProjectSettings.h
|
settings/ProjectSettings.h
|
||||||
settings/Settings.cpp
|
settings/Settings.cpp
|
||||||
settings/Settings.h
|
settings/Settings.h
|
||||||
|
settings/SettingsMigrator.cpp
|
||||||
|
settings/SettingsMigrator.h
|
||||||
|
|
||||||
utility/file/FileInfo.cpp
|
utility/file/FileInfo.cpp
|
||||||
utility/file/FileInfo.h
|
utility/file/FileInfo.h
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "utility/ResourcePaths.h"
|
#include "utility/ResourcePaths.h"
|
||||||
#include "utility/utility.h"
|
#include "utility/utility.h"
|
||||||
|
|
||||||
|
const size_t ApplicationSettings::VERSION = 1;
|
||||||
|
|
||||||
std::shared_ptr<ApplicationSettings> ApplicationSettings::s_instance;
|
std::shared_ptr<ApplicationSettings> ApplicationSettings::s_instance;
|
||||||
|
|
||||||
std::shared_ptr<ApplicationSettings> ApplicationSettings::getInstance()
|
std::shared_ptr<ApplicationSettings> ApplicationSettings::getInstance()
|
||||||
@@ -23,6 +25,36 @@ ApplicationSettings::~ApplicationSettings()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ApplicationSettings::load(const FilePath& filePath)
|
||||||
|
{
|
||||||
|
bool loaded = Settings::load(filePath);
|
||||||
|
if (!loaded)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
|
||||||
|
migrator.addMigration(1,
|
||||||
|
"source/header_search_paths/header_search_path",
|
||||||
|
"indexing/cxx/header_search_paths/header_search_path");
|
||||||
|
migrator.addMigration(1,
|
||||||
|
"source/framework_search_paths/framework_search_path",
|
||||||
|
"indexing/cxx/framework_search_paths/framework_search_path");
|
||||||
|
migrator.addMigration(1,
|
||||||
|
"application/indexer_thread_count",
|
||||||
|
"indexing/indexer_thread_count");
|
||||||
|
|
||||||
|
bool migrated = migrator.migrate(this, ApplicationSettings::VERSION);
|
||||||
|
|
||||||
|
if (migrated)
|
||||||
|
{
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ApplicationSettings::operator==(const ApplicationSettings& other) const
|
bool ApplicationSettings::operator==(const ApplicationSettings& other) const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -10,9 +10,14 @@ class ApplicationSettings
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<ApplicationSettings> getInstance();
|
static std::shared_ptr<ApplicationSettings> getInstance();
|
||||||
|
|
||||||
|
static const size_t VERSION;
|
||||||
|
|
||||||
ApplicationSettings();
|
ApplicationSettings();
|
||||||
~ApplicationSettings();
|
~ApplicationSettings();
|
||||||
|
|
||||||
|
bool load(const FilePath& filePath);
|
||||||
|
|
||||||
bool operator==(const ApplicationSettings& other) const;
|
bool operator==(const ApplicationSettings& other) const;
|
||||||
|
|
||||||
int getMaxRecentProjectsCount() const;
|
int getMaxRecentProjectsCount() const;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ bool Settings::load(const FilePath& filePath)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
m_filePath = filePath;
|
||||||
LOG_WARNING("File for Settings not found: " + filePath.str());
|
LOG_WARNING("File for Settings not found: " + filePath.str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ bool Settings::load(const FilePath& filePath)
|
|||||||
|
|
||||||
void Settings::save()
|
void Settings::save()
|
||||||
{
|
{
|
||||||
if (m_config.get() && m_filePath.exists())
|
if (m_config.get() && !m_filePath.empty())
|
||||||
{
|
{
|
||||||
m_config->save(m_filePath.str());
|
m_config->save(m_filePath.str());
|
||||||
}
|
}
|
||||||
@@ -58,14 +59,7 @@ void Settings::save(const FilePath& filePath)
|
|||||||
{
|
{
|
||||||
setFilePath(filePath);
|
setFilePath(filePath);
|
||||||
|
|
||||||
if (m_config)
|
save();
|
||||||
{
|
|
||||||
m_config->save(filePath.str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARNING("Settings were not saved: " + filePath.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::clear()
|
void Settings::clear()
|
||||||
@@ -79,6 +73,33 @@ const FilePath& Settings::getFilePath() const
|
|||||||
return m_filePath;
|
return m_filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Settings::getVersion() const
|
||||||
|
{
|
||||||
|
return getValue<int>("version", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::setVersion(size_t version)
|
||||||
|
{
|
||||||
|
setValue<int>("version", version);
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings Settings::createFromText(const std::shared_ptr<TextAccess> textAccess)
|
||||||
|
{
|
||||||
|
Settings settings;
|
||||||
|
settings.m_config = ConfigManager::createAndLoad(textAccess);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Settings::getAsText() const
|
||||||
|
{
|
||||||
|
if (m_config)
|
||||||
|
{
|
||||||
|
return m_config->toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
Settings::Settings()
|
Settings::Settings()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
@@ -126,6 +147,11 @@ bool Settings::isValueDefined(const std::string& key) const
|
|||||||
return m_config->isValueDefined(key);
|
return m_config->isValueDefined(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Settings::removeValues(const std::string& key)
|
||||||
|
{
|
||||||
|
m_config->removeValues(key);
|
||||||
|
}
|
||||||
|
|
||||||
void Settings::enableWarnings() const
|
void Settings::enableWarnings() const
|
||||||
{
|
{
|
||||||
m_config->setWarnOnEmptyKey(true);
|
m_config->setWarnOnEmptyKey(true);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "utility/ConfigManager.h"
|
#include "utility/ConfigManager.h"
|
||||||
#include "utility/file/FilePath.h"
|
#include "utility/file/FilePath.h"
|
||||||
|
|
||||||
|
#include "settings/SettingsMigrator.h"
|
||||||
|
|
||||||
class Settings
|
class Settings
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -15,14 +17,20 @@ public:
|
|||||||
Settings& operator=(const Settings& other);
|
Settings& operator=(const Settings& other);
|
||||||
virtual ~Settings();
|
virtual ~Settings();
|
||||||
|
|
||||||
virtual bool load(const FilePath& filePath);
|
bool load(const FilePath& filePath);
|
||||||
virtual void save();
|
void save();
|
||||||
virtual void save(const FilePath& filePath);
|
void save(const FilePath& filePath);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
virtual const FilePath& getFilePath() const;
|
virtual const FilePath& getFilePath() const;
|
||||||
|
|
||||||
|
size_t getVersion() const;
|
||||||
|
void setVersion(size_t version);
|
||||||
|
|
||||||
|
static Settings createFromText(const std::shared_ptr<TextAccess> textAccess);
|
||||||
|
std::string getAsText() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Settings();
|
Settings();
|
||||||
|
|
||||||
@@ -47,9 +55,13 @@ protected:
|
|||||||
|
|
||||||
bool isValueDefined(const std::string& key) const;
|
bool isValueDefined(const std::string& key) const;
|
||||||
|
|
||||||
|
void removeValues(const std::string& key);
|
||||||
|
|
||||||
void enableWarnings() const;
|
void enableWarnings() const;
|
||||||
void disableWarnings() const;
|
void disableWarnings() const;
|
||||||
|
|
||||||
|
friend bool SettingsMigrator::migrate(Settings* settings, size_t targetVersion) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FilePath m_filePath;
|
FilePath m_filePath;
|
||||||
std::shared_ptr<ConfigManager> m_config;
|
std::shared_ptr<ConfigManager> m_config;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#include "settings/SettingsMigrator.h"
|
||||||
|
|
||||||
|
#include "settings/Settings.h"
|
||||||
|
|
||||||
|
SettingsMigrator::SettingsMigrator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsMigrator::~SettingsMigrator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMigrator::addMigration(size_t targetVersion, std::string oldKey, std::string newKey)
|
||||||
|
{
|
||||||
|
Migration migration;
|
||||||
|
migration.targetVersion = targetVersion;
|
||||||
|
migration.oldKey = oldKey;
|
||||||
|
migration.newKey = newKey;
|
||||||
|
|
||||||
|
m_migrations.emplace(targetVersion, migration);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsMigrator::migrate(Settings* settings, size_t targetVersion) const
|
||||||
|
{
|
||||||
|
size_t originVersion = settings->getVersion();
|
||||||
|
|
||||||
|
if (originVersion < targetVersion)
|
||||||
|
{
|
||||||
|
for (; originVersion <= targetVersion; originVersion++)
|
||||||
|
{
|
||||||
|
std::pair<std::multimap<size_t, Migration>::const_iterator, std::multimap<size_t, Migration>::const_iterator> ret;
|
||||||
|
ret = m_migrations.equal_range(originVersion);
|
||||||
|
|
||||||
|
for (std::multimap<size_t, Migration>::const_iterator it = ret.first; it != ret.second; it++)
|
||||||
|
{
|
||||||
|
const Migration& migration = it->second;
|
||||||
|
|
||||||
|
if (!settings->isValueDefined(migration.newKey))
|
||||||
|
{
|
||||||
|
settings->setValues<std::string>(
|
||||||
|
migration.newKey,
|
||||||
|
settings->getValues<std::string>(migration.oldKey, std::vector<std::string>())
|
||||||
|
);
|
||||||
|
settings->removeValues(migration.oldKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings->setVersion(targetVersion);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef SETTNGS_MIGRATOR_H
|
||||||
|
#define SETTNGS_MIGRATOR_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Settings;
|
||||||
|
|
||||||
|
class SettingsMigrator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static SettingsMigrator createApplicationSettingsMigrator();
|
||||||
|
|
||||||
|
SettingsMigrator();
|
||||||
|
virtual ~SettingsMigrator();
|
||||||
|
|
||||||
|
void addMigration(size_t targetVersion, std::string oldKey, std::string newKey);
|
||||||
|
|
||||||
|
bool migrate(Settings* settings, size_t targetVersion) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Migration
|
||||||
|
{
|
||||||
|
size_t targetVersion;
|
||||||
|
std::string oldKey;
|
||||||
|
std::string newKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::multimap<size_t, Migration> m_migrations;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SETTINGS_MIGRATOR_H
|
||||||
@@ -220,6 +220,11 @@ void ConfigManager::setValues(const std::string& key, const std::vector<bool>& v
|
|||||||
setValues(key, stringValues);
|
setValues(key, stringValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigManager::removeValues(const std::string& key)
|
||||||
|
{
|
||||||
|
m_values.erase(key);
|
||||||
|
}
|
||||||
|
|
||||||
bool ConfigManager::isValueDefined(const std::string& key) const
|
bool ConfigManager::isValueDefined(const std::string& key) const
|
||||||
{
|
{
|
||||||
std::multimap<std::string, std::string>::const_iterator it = m_values.find(key);
|
std::multimap<std::string, std::string>::const_iterator it = m_values.find(key);
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ public:
|
|||||||
void setValues(const std::string& key, const std::vector<float>& values);
|
void setValues(const std::string& key, const std::vector<float>& values);
|
||||||
void setValues(const std::string& key, const std::vector<bool>& values);
|
void setValues(const std::string& key, const std::vector<bool>& values);
|
||||||
|
|
||||||
|
void removeValues(const std::string& key);
|
||||||
|
|
||||||
bool isValueDefined(const std::string& key) const;
|
bool isValueDefined(const std::string& key) const;
|
||||||
|
|
||||||
bool load(const std::shared_ptr<TextAccess> textAccess);
|
bool load(const std::shared_ptr<TextAccess> textAccess);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ add_files(
|
|||||||
MessageQueueTestSuite.h
|
MessageQueueTestSuite.h
|
||||||
NetworkProtocolHelperTestSuite.h
|
NetworkProtocolHelperTestSuite.h
|
||||||
SettingsTestSuite.h
|
SettingsTestSuite.h
|
||||||
|
SettingsMigratorTestSuite.h
|
||||||
SearchIndexTestSuite.h
|
SearchIndexTestSuite.h
|
||||||
SqliteStorageTestSuite.h
|
SqliteStorageTestSuite.h
|
||||||
StorageTestSuite.h
|
StorageTestSuite.h
|
||||||
|
|||||||
@@ -0,0 +1,289 @@
|
|||||||
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
|
#include "settings/Settings.h"
|
||||||
|
#include "settings/SettingsMigrator.h"
|
||||||
|
|
||||||
|
class SettingsMigratorTestSuite : public CxxTest::TestSuite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void test_migrator_changes_nothing_without_migrations_except_version()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.migrate(&settingsBefore, 1);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_name()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <int>2</int>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "int");
|
||||||
|
migrator.migrate(&settingsBefore, 1);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_path()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <sub>\n"
|
||||||
|
" <int>2</int>\n"
|
||||||
|
" </sub>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "sub/int");
|
||||||
|
migrator.migrate(&settingsBefore, 1);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_group_name()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <values>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
" <value>3</value>\n"
|
||||||
|
" <value>4</value>\n"
|
||||||
|
" </values>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <vals>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
" <value>3</value>\n"
|
||||||
|
" <value>4</value>\n"
|
||||||
|
" </vals>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "values/value", "vals/value");
|
||||||
|
migrator.migrate(&settingsBefore, 1);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_group_element_name()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <values>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
" <value>3</value>\n"
|
||||||
|
" <value>4</value>\n"
|
||||||
|
" </values>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <values>\n"
|
||||||
|
" <val>2</val>\n"
|
||||||
|
" <val>3</val>\n"
|
||||||
|
" <val>4</val>\n"
|
||||||
|
" </values>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "values/value", "values/val");
|
||||||
|
migrator.migrate(&settingsBefore, 1);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_only_up_specified_version()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <int>2</int>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "int");
|
||||||
|
migrator.addMigration(2, "int", "val");
|
||||||
|
migrator.migrate(&settingsBefore, 1);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_only_from_specified_version()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <int>2</int>\n"
|
||||||
|
" <version>1</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <val>2</val>\n"
|
||||||
|
" <version>2</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "int");
|
||||||
|
migrator.addMigration(2, "int", "val");
|
||||||
|
migrator.migrate(&settingsBefore, 2);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_for_multiple_versions()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <val>2</val>\n"
|
||||||
|
" <version>2</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "int");
|
||||||
|
migrator.addMigration(2, "int", "val");
|
||||||
|
migrator.migrate(&settingsBefore, 2);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_for_multiple_migrations()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
" <element>hi there</element>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <val>2</val>\n"
|
||||||
|
" <ele>hi there</ele>\n"
|
||||||
|
" <version>2</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "val");
|
||||||
|
migrator.addMigration(1, "element", "ele");
|
||||||
|
migrator.migrate(&settingsBefore, 2);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_migrator_changes_for_multiple_versions_and_migrations()
|
||||||
|
{
|
||||||
|
Settings settingsBefore = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <value>2</value>\n"
|
||||||
|
" <element>two</element>\n"
|
||||||
|
" <element>three</element>\n"
|
||||||
|
" <element>four</element>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
Settings settingsAfter = createSettings(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
|
||||||
|
"<config>\n"
|
||||||
|
" <int>2</int>\n"
|
||||||
|
" <elements>\n"
|
||||||
|
" <element>two</element>\n"
|
||||||
|
" <element>three</element>\n"
|
||||||
|
" <element>four</element>\n"
|
||||||
|
" </elements>\n"
|
||||||
|
" <version>3</version>\n"
|
||||||
|
"</config>\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
SettingsMigrator migrator;
|
||||||
|
migrator.addMigration(1, "value", "int/val");
|
||||||
|
migrator.addMigration(1, "element", "ele");
|
||||||
|
migrator.addMigration(2, "int/val", "int");
|
||||||
|
migrator.addMigration(3, "ele", "elements/element");
|
||||||
|
migrator.migrate(&settingsBefore, 3);
|
||||||
|
|
||||||
|
TS_ASSERT_EQUALS(settingsBefore.getAsText(), settingsAfter.getAsText());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Settings createSettings(const std::string& text)
|
||||||
|
{
|
||||||
|
return Settings::createFromText(TextAccess::createFromString(text));
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user