mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-14 20:41:21 +00:00
Refactored config_cache to support loading multiple cached items...
...using path as key
This commit is contained in:
parent
4d39fc6474
commit
99305160ae
@ -30,6 +30,8 @@
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
@ -41,6 +43,10 @@
|
||||
|
||||
typedef std::map<std::string,t_string> string_map;
|
||||
|
||||
class config;
|
||||
|
||||
typedef boost::shared_ptr<config> config_ptr;
|
||||
|
||||
/** A config object defines a single node in a WML file, with access to child nodes. */
|
||||
class config
|
||||
{
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "show_dialog.hpp"
|
||||
#include "sha1.hpp"
|
||||
#include "serialization/binary_wml.hpp"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
|
||||
#define ERR_CONFIG LOG_STREAM(err, config)
|
||||
@ -41,44 +42,14 @@ namespace game_config {
|
||||
}
|
||||
|
||||
config_cache::config_cache() :
|
||||
game_config_(),
|
||||
force_valid_cache_(false),
|
||||
use_cache_(true),
|
||||
dirty_(true),
|
||||
config_root_("data/"),
|
||||
user_config_root_(get_addon_campaigns_dir()),
|
||||
defines_map_()
|
||||
{
|
||||
// To settup initial defines map correctly
|
||||
clear_defines();
|
||||
}
|
||||
|
||||
std::string config_cache::get_config_root() const
|
||||
{
|
||||
return config_root_;
|
||||
}
|
||||
|
||||
void config_cache::set_config_root(const std::string& path)
|
||||
{
|
||||
if (path == config_root_)
|
||||
return;
|
||||
dirty_ = true;
|
||||
config_root_ = path;
|
||||
}
|
||||
|
||||
std::string config_cache::get_user_config_root() const
|
||||
{
|
||||
return user_config_root_;
|
||||
}
|
||||
|
||||
void config_cache::set_user_config_root(const std::string& path)
|
||||
{
|
||||
if (path == user_config_root_)
|
||||
return;
|
||||
dirty_ = true;
|
||||
user_config_root_ = path;
|
||||
}
|
||||
|
||||
const preproc_map& config_cache::get_preproc_map() const
|
||||
{
|
||||
return defines_map_;
|
||||
@ -106,35 +77,59 @@ namespace game_config {
|
||||
|
||||
}
|
||||
|
||||
void config_cache::reload_translations()
|
||||
config_ptr config_cache::get_config(const std::string& path)
|
||||
{
|
||||
if (dirty_)
|
||||
config_ptr ret(new config());
|
||||
load_configs(path, *ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void config_cache::write_file(std::string path, const config& cfg)
|
||||
{
|
||||
bool gzip = false;
|
||||
switch(game_config::cache_type)
|
||||
{
|
||||
load_configs(game_config_, false);
|
||||
} else {
|
||||
game_config_.reset_translation();
|
||||
game_config::load_config(game_config_.child("game_config"));
|
||||
case GZIP:
|
||||
gzip = true;
|
||||
path += ".gz";
|
||||
case BWML:
|
||||
{
|
||||
scoped_ostream stream = ostream_file(path);
|
||||
config_writer writer(*stream,gzip,"",game_config::cache_compression_level);
|
||||
writer.write(cfg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
config& config_cache::get_config(bool recheck_cache)
|
||||
void config_cache::read_file(const std::string& path, config& cfg)
|
||||
{
|
||||
if (!dirty_)
|
||||
return game_config_;
|
||||
|
||||
load_configs(game_config_, recheck_cache);
|
||||
dirty_ = false;
|
||||
|
||||
return game_config_;
|
||||
std::string error_log;
|
||||
switch(game_config::cache_type)
|
||||
{
|
||||
case BWML:
|
||||
{
|
||||
scoped_istream stream = istream_file(path);
|
||||
read(cfg, *stream);
|
||||
}
|
||||
break;
|
||||
case GZIP:
|
||||
{
|
||||
scoped_istream stream = istream_file(path + ".gz");
|
||||
read_gz(cfg, *stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void config_cache::read_configs(config& cfg, std::string& error_log)
|
||||
void config_cache::read_configs(const std::string& path, config& cfg)
|
||||
{
|
||||
preproc_map defines_map(defines_map_);
|
||||
|
||||
std::string user_error_log;
|
||||
std::string error_log;
|
||||
//read the file and then write to the cache
|
||||
scoped_istream stream = preprocess_file(config_root_, &defines_map, &error_log);
|
||||
scoped_istream stream = preprocess_file(path, &defines_map, &error_log);
|
||||
|
||||
//reset the parse counter before reading the game files
|
||||
if (loadscreen::global_loadscreen) {
|
||||
@ -142,87 +137,17 @@ namespace game_config {
|
||||
}
|
||||
|
||||
read(cfg, *stream, &error_log);
|
||||
// clone and put the gfx rules aside so that we can prepend the add-on
|
||||
// rules to them.
|
||||
config core_terrain_rules;
|
||||
// FIXME: there should be a canned algorithm for cloning child_list objects,
|
||||
// along with the memory their elements point to... little implementation detail.
|
||||
foreach(config const* p_cfg, game_config_.get_children("terrain_graphics")) {
|
||||
core_terrain_rules.add_child("terrain_graphics", *p_cfg);
|
||||
if (!error_log.empty())
|
||||
{
|
||||
throw config::error(error_log);
|
||||
}
|
||||
game_config_.clear_children("terrain_graphics");
|
||||
|
||||
// load usermade add-ons
|
||||
// const std::string user_campaign_dir = get_addon_campaigns_dir();
|
||||
std::vector< std::string > error_addons;
|
||||
// Scan addon directories
|
||||
std::vector<std::string> user_addons;
|
||||
|
||||
get_files_in_dir(user_config_root_,NULL,&user_addons,ENTIRE_FILE_PATH);
|
||||
|
||||
// Load the addons
|
||||
for(std::vector<std::string>::const_iterator uc = user_addons.begin(); uc != user_addons.end(); ++uc) {
|
||||
std::string oldstyle_cfg = *uc + ".cfg";
|
||||
std::string main_cfg = *uc + "/_main.cfg";
|
||||
std::string toplevel;
|
||||
if (file_exists(oldstyle_cfg))
|
||||
toplevel = oldstyle_cfg;
|
||||
else if (file_exists(main_cfg))
|
||||
toplevel = main_cfg;
|
||||
else
|
||||
continue;
|
||||
|
||||
try {
|
||||
preproc_map addon_defines_map(defines_map);
|
||||
scoped_istream stream = preprocess_file(toplevel, &addon_defines_map);
|
||||
|
||||
std::string addon_error_log;
|
||||
|
||||
config umc_cfg;
|
||||
read(umc_cfg, *stream, &addon_error_log);
|
||||
|
||||
if (addon_error_log.empty()) {
|
||||
game_config_.append(umc_cfg);
|
||||
} else {
|
||||
user_error_log += addon_error_log;
|
||||
error_addons.push_back(*uc);
|
||||
}
|
||||
} catch(config::error& err) {
|
||||
ERR_CONFIG << "error reading usermade add-on '" << *uc << "'\n";
|
||||
error_addons.push_back(*uc);
|
||||
user_error_log += err.message + "\n";
|
||||
} catch(preproc_config::error&) {
|
||||
ERR_CONFIG << "error reading usermade add-on '" << *uc << "'\n";
|
||||
error_addons.push_back(*uc);
|
||||
//no need to modify the error log here, already done by the preprocessor
|
||||
} catch(io_exception&) {
|
||||
ERR_CONFIG << "error reading usermade add-on '" << *uc << "'\n";
|
||||
error_addons.push_back(*uc);
|
||||
}
|
||||
if(error_addons.empty() == false) {
|
||||
std::stringstream msg;
|
||||
msg << _n("The following add-on had errors and could not be loaded:",
|
||||
"The following add-ons had errors and could not be loaded:",
|
||||
error_addons.size());
|
||||
for(std::vector<std::string>::const_iterator i = error_addons.begin(); i != error_addons.end(); ++i) {
|
||||
msg << "\n" << *i;
|
||||
}
|
||||
|
||||
msg << "\n" << _("ERROR DETAILS:") << "\n" << font::nullify_markup(user_error_log);
|
||||
|
||||
gui::show_error_message(*game_display::get_singleton(),msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
cfg.merge_children("units");
|
||||
cfg.append(core_terrain_rules);
|
||||
|
||||
}
|
||||
|
||||
void config_cache::load_configs(config& cfg, bool recheck_cache)
|
||||
void config_cache::read_cache(const std::string& path, config& cfg)
|
||||
{
|
||||
bool is_valid = true;
|
||||
std::stringstream defines_string;
|
||||
defines_string << path;
|
||||
for(preproc_map::const_iterator i = defines_map_.begin(); i != defines_map_.end(); ++i) {
|
||||
if(i->second.value != "" || i->second.arguments.empty() == false) {
|
||||
is_valid = false;
|
||||
@ -232,10 +157,10 @@ namespace game_config {
|
||||
|
||||
defines_string << " " << i->first;
|
||||
}
|
||||
//std::string localename = get_locale().localename;
|
||||
//str << "-lang_" << (localename.empty() ? "default" : localename);
|
||||
|
||||
if(is_valid && use_cache_) {
|
||||
// Do cache check only if define map is valid and
|
||||
// caching is allowed
|
||||
if(is_valid) {
|
||||
const std::string& cache = get_cache_dir();
|
||||
if(cache != "") {
|
||||
sha1_hash sha(defines_string.str()); // use a hash for a shorter display of the defines
|
||||
@ -248,8 +173,7 @@ namespace game_config {
|
||||
try {
|
||||
if(file_exists(fname_checksum)) {
|
||||
config checksum_cfg;
|
||||
scoped_istream stream = istream_file(fname_checksum);
|
||||
read(checksum_cfg, *stream);
|
||||
read_file(fname_checksum, checksum_cfg);
|
||||
dir_checksum = file_tree_checksum(checksum_cfg);
|
||||
}
|
||||
} catch(config::error&) {
|
||||
@ -263,12 +187,11 @@ namespace game_config {
|
||||
LOG_CONFIG << "skipping cache validation (forced)\n";
|
||||
}
|
||||
|
||||
if(file_exists(fname) && (force_valid_cache_ || (dir_checksum == data_tree_checksum(recheck_cache)))) {
|
||||
if(file_exists(fname) && (force_valid_cache_ || (dir_checksum == data_tree_checksum()))) {
|
||||
LOG_CONFIG << "found valid cache at '" << fname << "' using it\n";
|
||||
log_scope("read cache");
|
||||
try {
|
||||
scoped_istream stream = istream_file(fname);
|
||||
read_compressed(cfg, *stream);
|
||||
read_file(fname,cfg);
|
||||
return;
|
||||
} catch(config::error&) {
|
||||
ERR_CONFIG << "cache is corrupt. Loading from files\n";
|
||||
@ -278,34 +201,34 @@ namespace game_config {
|
||||
}
|
||||
|
||||
LOG_CONFIG << "no valid cache found. Writing cache to '" << fname << " with defines_map "<< defines_string.str() << "'\n";
|
||||
DBG_CONFIG << ((use_cache_ && file_exists(fname)) ? "yes":"no ") << " " << dir_checksum.modified << "==" << data_tree_checksum().modified << " " << dir_checksum.nfiles << "==" << data_tree_checksum().nfiles << " " << dir_checksum.sum_size << "==" << data_tree_checksum().sum_size << "\n";
|
||||
|
||||
std::string error_log;
|
||||
read_configs(path, cfg);
|
||||
|
||||
read_configs(cfg, error_log);
|
||||
|
||||
if(!error_log.empty()) {
|
||||
gui::show_error_message(*game_display::get_singleton(),
|
||||
_("Warning: Errors occurred while loading game configuration files: '") +
|
||||
font::nullify_markup(error_log));
|
||||
|
||||
} else {
|
||||
try {
|
||||
scoped_ostream cache = ostream_file(fname);
|
||||
write_compressed(*cache, cfg);
|
||||
config checksum_cfg;
|
||||
data_tree_checksum().write(checksum_cfg);
|
||||
scoped_ostream checksum = ostream_file(fname_checksum);
|
||||
write(*checksum, checksum_cfg);
|
||||
} catch(io_exception&) {
|
||||
ERR_FS << "could not write to cache '" << fname << "'\n";
|
||||
}
|
||||
try {
|
||||
write_file(fname, cfg);
|
||||
config checksum_cfg;
|
||||
data_tree_checksum().write(checksum_cfg);
|
||||
write_file(fname_checksum, checksum_cfg);
|
||||
} catch(io_exception&) {
|
||||
ERR_FS << "could not write to cache '" << fname << "'\n";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_CONFIG << "Loading plain config instead of cache\n";
|
||||
load_configs(path, cfg);
|
||||
}
|
||||
|
||||
void config_cache::load_configs(const std::string& path, config& cfg)
|
||||
{
|
||||
if (use_cache_)
|
||||
{
|
||||
read_cache(path, cfg);
|
||||
} else {
|
||||
read_configs(path, cfg);
|
||||
}
|
||||
|
||||
return;
|
||||
ERR_CONFIG << "caching cannot be done. Reading file\n";
|
||||
|
||||
std::string error_log;
|
||||
@ -324,9 +247,23 @@ namespace game_config {
|
||||
use_cache_ = use;
|
||||
}
|
||||
|
||||
void config_cache::set_force_valid_cache(bool force)
|
||||
{
|
||||
force_valid_cache_ = force;
|
||||
}
|
||||
|
||||
void config_cache::recheck_filetree_checksum()
|
||||
{
|
||||
data_tree_checksum(true);
|
||||
}
|
||||
|
||||
void config_cache::add_define(const std::string& define)
|
||||
{
|
||||
dirty_ = true;
|
||||
defines_map_[define] = preproc_define();
|
||||
}
|
||||
|
||||
void config_cache::remove_define(const std::string& define)
|
||||
{
|
||||
defines_map_.erase(define);
|
||||
}
|
||||
}
|
||||
|
@ -22,44 +22,96 @@
|
||||
namespace game_config {
|
||||
|
||||
|
||||
/**
|
||||
* Singleton object to manage game configs
|
||||
* and cache reading.
|
||||
**/
|
||||
/**
|
||||
* Singleton object to manage game configs
|
||||
* and cache reading.
|
||||
* @TODO: Make smarter filetree checksum caching so only required parts
|
||||
* of tree are checked at startup. Trees are overlapping so have
|
||||
* to split trees to subtrees to only do check once per file.
|
||||
**/
|
||||
class config_cache : private boost::noncopyable {
|
||||
static config_cache cache_;
|
||||
|
||||
config game_config_;
|
||||
bool force_valid_cache_, use_cache_, dirty_;
|
||||
std::string config_root_, user_config_root_;
|
||||
bool force_valid_cache_, use_cache_;
|
||||
preproc_map defines_map_;
|
||||
|
||||
void read_configs(config&, std::string&);
|
||||
|
||||
void read_file(const std::string& file, config& cfg);
|
||||
void write_file(std::string file, const config& cfg);
|
||||
|
||||
void read_cache(const std::string& path, config& cfg);
|
||||
|
||||
void read_configs(const std::string& path, config& cfg);
|
||||
|
||||
// Protected to let test code access
|
||||
protected:
|
||||
config_cache();
|
||||
|
||||
|
||||
std::string get_config_root() const;
|
||||
std::string get_user_config_root() const;
|
||||
const preproc_map& get_preproc_map() const;
|
||||
void load_configs(config& cfg, bool recheck_cache);
|
||||
void load_configs(const std::string& path, config& cfg);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get reference to the singleton object
|
||||
**/
|
||||
static config_cache& instance();
|
||||
|
||||
void set_config_root(const std::string&);
|
||||
void set_user_config_root(const std::string&);
|
||||
|
||||
config& get_config(bool recheck_cache = false);
|
||||
/**
|
||||
* get config object from given path
|
||||
* @param path which to load. Should be _main.cfg.
|
||||
* @return shread_ptr config object
|
||||
**/
|
||||
config_ptr get_config(const std::string& path);
|
||||
|
||||
/**
|
||||
* Clear stored defines map to default values
|
||||
**/
|
||||
void clear_defines();
|
||||
/**
|
||||
* Add a entry to preproc defines map
|
||||
**/
|
||||
void add_define(const std::string& define);
|
||||
/**
|
||||
* Remove a entry to preproc defines map
|
||||
**/
|
||||
void remove_define(const std::string& define);
|
||||
|
||||
void reload_translations();
|
||||
|
||||
/**
|
||||
* Enable/disable caching
|
||||
**/
|
||||
void set_use_cache(bool use);
|
||||
/**
|
||||
* Enable/disable cache validation
|
||||
**/
|
||||
void set_force_valid_cache(bool force);
|
||||
/**
|
||||
* Force cache checksum validation.
|
||||
**/
|
||||
void recheck_filetree_checksum();
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to set and unset scoped defines to preproc_map
|
||||
* This is prefered form to set defines that aren't global
|
||||
**/
|
||||
template <class T>
|
||||
class scoped_preproc_define_internal : private boost::noncopyable {
|
||||
// Protected to let test code access
|
||||
protected:
|
||||
std::string name_;
|
||||
public:
|
||||
scoped_preproc_define_internal(const std::string& name) : name_(name)
|
||||
{
|
||||
T::instance().add_define(name_);
|
||||
}
|
||||
~scoped_preproc_define_internal()
|
||||
{
|
||||
T::instance().remove_define(name_);
|
||||
}
|
||||
};
|
||||
typedef scoped_preproc_define_internal<config_cache> scoped_preproc_define;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -59,6 +59,9 @@ namespace game_config
|
||||
bool use_dummylocales = false;
|
||||
#endif
|
||||
|
||||
cache_types cache_type = BWML;
|
||||
int cache_compression_level = 5;
|
||||
|
||||
std::string game_icon = "wesnoth-icon.png", game_title, game_logo, title_music, lobby_music;
|
||||
int title_logo_x = 0, title_logo_y = 0, title_buttons_x = 0, title_buttons_y = 0, title_buttons_padding = 0,
|
||||
title_tip_x = 0, title_tip_width = 0, title_tip_padding = 0;
|
||||
|
@ -50,6 +50,13 @@ namespace game_config
|
||||
|
||||
extern bool use_dummylocales;
|
||||
|
||||
extern enum cache_types {
|
||||
BWML,
|
||||
GZIP
|
||||
} cache_type;
|
||||
|
||||
extern int cache_compression_level;
|
||||
|
||||
extern std::string path;
|
||||
|
||||
struct server_info {
|
||||
|
@ -63,7 +63,7 @@ struct wesnoth_global_fixture {
|
||||
game_config::path = get_cwd();
|
||||
|
||||
load_language_list();
|
||||
::init_textdomains(game_config::config_cache::instance().get_config());
|
||||
::init_textdomains(*game_config::config_cache::instance().get_config(game_config::path + "/data/_main.cfg"));
|
||||
const std::vector<language_def>& languages = get_languages();
|
||||
std::vector<language_def>::const_iterator English = std::find_if(languages.begin(),
|
||||
languages.end(),
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( config_cache )
|
||||
|
||||
const std::string test_data_path("data/test/test/_main.cfg");
|
||||
/**
|
||||
* Used to make distinct singleton for testing it
|
||||
* because other tests will need original one to load data
|
||||
@ -41,18 +42,16 @@ BOOST_AUTO_TEST_SUITE( config_cache )
|
||||
return cache_;
|
||||
}
|
||||
|
||||
std::string get_config_root() const {
|
||||
return game_config::config_cache::get_config_root();
|
||||
}
|
||||
std::string get_user_config_root() const {
|
||||
return game_config::config_cache::get_user_config_root();
|
||||
}
|
||||
|
||||
const preproc_map& get_preproc_map() const {
|
||||
return game_config::config_cache::get_preproc_map();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to redirect defines settings to test cache
|
||||
**/
|
||||
typedef game_config::scoped_preproc_define_internal<test_config_cache> test_scoped_define;
|
||||
|
||||
test_config_cache test_config_cache::cache_;
|
||||
|
||||
static preproc_map settup_test_preproc_map()
|
||||
@ -84,9 +83,6 @@ BOOST_AUTO_TEST_CASE( test_config_cache_defaults )
|
||||
preproc_map defines_map(settup_test_preproc_map());
|
||||
test_config_cache& cache = test_config_cache::instance();
|
||||
|
||||
BOOST_CHECK_EQUAL("data/", cache.get_config_root());
|
||||
BOOST_CHECK_EQUAL(get_addon_campaigns_dir(), cache.get_user_config_root());
|
||||
|
||||
const preproc_map& test_defines = cache.get_preproc_map();
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
@ -95,7 +91,7 @@ BOOST_AUTO_TEST_CASE( test_config_cache_defaults )
|
||||
BOOST_AUTO_TEST_CASE( test_load_config )
|
||||
{
|
||||
test_config_cache& cache = test_config_cache::instance();
|
||||
cache.add_define("TEST");
|
||||
test_scoped_define test_def("TEST");
|
||||
|
||||
preproc_map defines_map(settup_test_preproc_map());
|
||||
defines_map["TEST"] = preproc_define();
|
||||
@ -103,12 +99,6 @@ BOOST_AUTO_TEST_CASE( test_load_config )
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
|
||||
std::string test_data_path("data/test/test/");
|
||||
cache.set_config_root(test_data_path);
|
||||
BOOST_CHECK_EQUAL(test_data_path, cache.get_config_root());
|
||||
test_data_path = "invalid";
|
||||
cache.set_user_config_root(test_data_path);
|
||||
BOOST_CHECK_EQUAL(test_data_path, cache.get_user_config_root());
|
||||
|
||||
config test_config;
|
||||
config* child = &test_config.add_child("textdomain");
|
||||
@ -118,59 +108,55 @@ BOOST_AUTO_TEST_CASE( test_load_config )
|
||||
(*child)["define"] = "test";
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(test_config, cache.get_config());
|
||||
BOOST_CHECK_EQUAL(test_config, *cache.get_config(test_data_path));
|
||||
|
||||
cache.add_define("TEST_DEFINE");
|
||||
test_scoped_define test_define_def("TEST_DEFINE");
|
||||
|
||||
child = &test_config.add_child("test_key2");
|
||||
(*child)["define"] = t_string("testing translation reset.", GETTEXT_DOMAIN);
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(test_config, cache.get_config());
|
||||
BOOST_CHECK_EQUAL(test_config, *cache.get_config(test_data_path));
|
||||
|
||||
BOOST_CHECK_EQUAL((*test_config.child("test_key2"))["define"].str(), (*cache.get_config().child("test_key2"))["define"].str());
|
||||
BOOST_CHECK_EQUAL((*test_config.child("test_key2"))["define"].str(), (*cache.get_config(test_data_path)->child("test_key2"))["define"].str());
|
||||
}
|
||||
|
||||
static bool match_german(const language_def& def)
|
||||
{
|
||||
return def.localename == "de_DE";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_translation_reload )
|
||||
BOOST_AUTO_TEST_CASE( test_preproc_defines )
|
||||
{
|
||||
test_config_cache& cache = test_config_cache::instance();
|
||||
config test_config;
|
||||
config* child = &test_config.add_child("textdomain");
|
||||
(*child)["name"] = "wesnoth";
|
||||
const preproc_map& test_defines = cache.get_preproc_map();
|
||||
preproc_map defines_map(settup_test_preproc_map());
|
||||
|
||||
child = &test_config.add_child("test_key");
|
||||
(*child)["define"] = "test";
|
||||
// check initial state
|
||||
BOOST_REQUIRE_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
|
||||
child = &test_config.add_child("test_key2");
|
||||
(*child)["define"] = t_string("testing translation reset.", GETTEXT_DOMAIN);
|
||||
// scoped
|
||||
{
|
||||
test_scoped_define test("TEST");
|
||||
defines_map["TEST"] = preproc_define();
|
||||
|
||||
BOOST_CHECK_EQUAL((*test_config.child("test_key2"))["define"].str(), (*cache.get_config().child("test_key2"))["define"].str());
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
defines_map.erase("TEST");
|
||||
}
|
||||
// Check scoped remove
|
||||
|
||||
// Change language
|
||||
const language_def& original_lang = get_language();
|
||||
const std::vector<language_def>& languages = get_languages();
|
||||
BOOST_CHECK_MESSAGE(languages.size()>0, "No languages found!");
|
||||
std::vector<language_def>::const_iterator German = std::find_if(languages.begin(),
|
||||
languages.end(),
|
||||
match_german); // Using German because the most active translation
|
||||
BOOST_REQUIRE_MESSAGE(German != languages.end() && German->available(), "German translation not found");
|
||||
::set_language(*German);
|
||||
cache.reload_translations();
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
|
||||
BOOST_CHECK_MESSAGE((*test_config.child("test_key2"))["define"].str() != (*cache.get_config().child("test_key2"))["define"].str(), "Translation reset failed to make test string different!");
|
||||
|
||||
(*child)["define"].reset_translation();
|
||||
// Manual add define
|
||||
cache.add_define("TEST");
|
||||
defines_map["TEST"] = preproc_define();
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
|
||||
BOOST_CHECK_EQUAL(test_config, cache.get_config());
|
||||
BOOST_CHECK_EQUAL((*test_config.child("test_key2"))["define"].str(), (*cache.get_config().child("test_key2"))["define"].str());
|
||||
set_language(original_lang);
|
||||
// Manual remove define
|
||||
cache.remove_define("TEST");
|
||||
defines_map.erase("TEST");
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
|
||||
defines_map.begin() ,defines_map.end());
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4: */
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user