The Battle for Wesnoth  1.19.14+dev
test_config_cache.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2025
3  by Pauli Nieminen <paniemin@cc.hut.fi>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include <boost/test/unit_test.hpp>
17 
18 #define GETTEXT_DOMAIN "wesnoth-test"
19 
20 
21 #include "config_cache.hpp"
22 #include "config.hpp"
23 #include "game_config.hpp"
24 #include "language.hpp"
25 #include "log.hpp"
26 #include "game_version.hpp"
27 
29 
30 #include <functional>
31 
33 {
34  preproc_map defines_map;
35 
36 #if defined(__APPLE__)
37  defines_map.try_emplace("APPLE");
38 #endif
39 
40  defines_map.try_emplace("WESNOTH_VERSION", game_config::wesnoth_version.str());
41  return defines_map;
42 }
43 
44 /**
45  * Used to make distinct singleton for testing it
46  * because other tests will need original one to load data
47  **/
50 
51  public:
52  static test_config_cache& instance() ;
53 
54  void set_force_invalid_cache(bool force)
55  {
57  }
58 };
59 
61  static test_config_cache * cache_ = new test_config_cache;
62  return *cache_;
63 }
64 
65 /**
66  * Used to redirect defines settings to test cache
67  **/
69 
72  {
74  }
76  {
78  }
82 };
83 
84 BOOST_AUTO_TEST_CASE( test_preproc_defines )
85 {
87  const preproc_map& test_defines = cache.get_preproc_map();
88  preproc_map defines_map(setup_test_preproc_map());
89 
90  // check initial state
91  BOOST_REQUIRE_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
92  defines_map.begin() ,defines_map.end());
93 
94  // scoped
95  {
96  test_scoped_define test("TEST");
97  defines_map.try_emplace("TEST");;
98 
99  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
100  defines_map.begin() ,defines_map.end());
101  defines_map.erase("TEST");
102  }
103  // Check scoped remove
104 
105  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
106  defines_map.begin() ,defines_map.end());
107 
108  // Manual add define
109  cache.add_define("TEST");
110  defines_map.try_emplace("TEST");;
111  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
112  defines_map.begin() ,defines_map.end());
113 
114  // Manual remove define
115  cache.remove_define("TEST");
116  defines_map.erase("TEST");
117  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
118  defines_map.begin() ,defines_map.end());
119 }
120 
121 BOOST_AUTO_TEST_CASE( test_config_cache_defaults )
122 {
124  preproc_map defines_map(setup_test_preproc_map());
125 
126  const preproc_map& test_defines = cache.get_preproc_map();
127  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
128  defines_map.begin() ,defines_map.end());
129 }
130 
131 
133 
134  const std::string test_data_path("data/test/test/_main.cfg");
135 
137 {
138  config test_config;
139  config* child = &test_config.add_child("textdomain");
140  (*child)["name"] = GETTEXT_DOMAIN;
141 
142  child = &test_config.add_child("test_key");
143  (*child)["define"] = "test";
144  return test_config;
145 }
146 
147 
148 BOOST_AUTO_TEST_CASE( test_load_config )
149 {
150  config test_config = setup_test_config();
151  config cached_config = cache.get_config(test_data_path);
152  BOOST_CHECK_EQUAL(test_config, cached_config);
153 
154  config &child = test_config.add_child("test_key2");
155  child["define"] = t_string("testing translation reset.", GETTEXT_DOMAIN);
156 
157  test_scoped_define test_define_def("TEST_DEFINE");
158  cached_config = cache.get_config(test_data_path);
159  BOOST_CHECK_EQUAL(test_config, cached_config);
160 
161  BOOST_CHECK_EQUAL(test_config.mandatory_child("test_key2")["define"].str(), cached_config.mandatory_child("test_key2")["define"].str());
162 }
163 
164 BOOST_AUTO_TEST_CASE( test_macrosubstitution )
165 {
166  config test_config = setup_test_config();
167 
168  config &child = test_config.add_child("test_key3");
169  child["define"] = "transaction";
170  config &child2 = test_config.add_child("test_key4");
171  child2["defined"] = "parameter";
172 
173  // test first that macro loading works
174  test_scoped_define macro("TEST_MACRO");
175 
176  // Without cache
177  config cached_config = cache.get_config(test_data_path);
178  BOOST_CHECK_EQUAL(test_config, cached_config);
179 
180  // With cache
181  cached_config = cache.get_config(test_data_path);
182  BOOST_CHECK_EQUAL(test_config, cached_config);
183 }
184 
185 BOOST_AUTO_TEST_CASE( test_transaction )
186 {
187  config test_config = setup_test_config();
188 
189  config* child = &test_config.add_child("test_key3");
190  (*child)["define"] = "transaction";
191  child = &test_config.add_child("test_key4");
192  (*child)["defined"] = "parameter";
193 
194  // test first that macro loading works
195  test_scoped_define macro("TEST_MACRO");
196 
197  //Start transaction
198 
200 
201  config cached_config = cache.get_config(test_data_path);
202  BOOST_CHECK_EQUAL(test_config, cached_config);
203 
204  transaction.lock();
205  config umc_config;
206  child = &umc_config.add_child("umc");
207  (*child)["test"] = "umc load";
208  child = &umc_config.add_child("test_key3");
209  (*child)["define"] = "transaction";
210  child = &umc_config.add_child("test_key4");
211  (*child)["defined"] = "parameter";
212  cached_config = cache.get_config("data/test/test/umc.cfg");
213  BOOST_CHECK_EQUAL(umc_config, cached_config);
214 }
215 
216 BOOST_AUTO_TEST_CASE( test_define_loading )
217 {
218  // try to load umc without valid cache
219  config test_config = setup_test_config();
220 
221  config* child = &test_config.add_child("test_key3");
222  (*child)["define"] = "transaction";
223  child = &test_config.add_child("test_key4");
224  (*child)["defined"] = "parameter";
225 
226  // test first that macro loading works
227  test_scoped_define macro("TEST_MACRO");
228 
229  //Start transaction
230 
232 
233  config cached_config = cache.get_config(test_data_path);
234  BOOST_CHECK_EQUAL(test_config, cached_config);
235 
236  transaction.lock();
237 
238  cache.set_force_invalid_cache(true);
239  config umc_config;
240  child = &umc_config.add_child("umc");
241  (*child)["test"] = "umc load";
242  child = &umc_config.add_child("test_key3");
243  (*child)["define"] = "transaction";
244  child = &umc_config.add_child("test_key4");
245  (*child)["defined"] = "parameter";
246  cached_config = cache.get_config("data/test/test/umc.cfg");
247  BOOST_CHECK_EQUAL(umc_config, cached_config);
248  cache.set_force_invalid_cache(false);
249 }
250 
251 BOOST_AUTO_TEST_CASE( test_lead_spaces_loading )
252 {
253  config test_config;
254  test_config.add_child("test_lead_space")["space"] = "empty char in middle";
255  // Force reload of cache
256  cache.set_force_invalid_cache(true);
257  config cached_config = cache.get_config("data/test/test/leading_space.cfg");
258  BOOST_CHECK_EQUAL(test_config, cached_config);
259  cache.set_force_invalid_cache(false);
260  cached_config = cache.get_config("data/test/test/leading_space.cfg");
261  BOOST_CHECK_EQUAL(test_config, cached_config);
262 }
263 
264 #if 0
265 // for profiling cache speed
266 BOOST_AUTO_TEST_CASE( test_performance )
267 {
268  test_scoped_define mp("MULTIPLAYER");
269 // cache.set_force_invalid_cache(true);
270  config cfg_ref = cache.get_config("data/");
271 // cache.set_force_invalid_cache(false);
272  for (int i=0; i < 3; ++i)
273  {
274  cfg_ref = cache.get_config("data/");
275  }
276 }
277 #endif
278 
279 /* vim: set ts=4 sw=4: */
280 BOOST_AUTO_TEST_SUITE_END()
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
Definition: config.cpp:362
config & add_child(config_key_type key)
Definition: config.cpp:436
Used to share macros between cache objects You have to create transaction object to load all macros t...
void lock()
Lock the transaction so no more macros are added.
Singleton class to manage game config file caching.
void add_define(const std::string &define)
Add a entry to preproc defines map.
const preproc_map & get_preproc_map() const
void remove_define(const std::string &define)
Remove a entry to preproc defines map.
Used to make distinct singleton for testing it because other tests will need original one to load dat...
static test_config_cache & instance()
void set_force_invalid_cache(bool force)
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
std::size_t i
Definition: function.cpp:1032
Interfaces for manipulating version numbers of engine, add-ons, etc.
const language_def & get_language()
Definition: language.cpp:327
Standard logging facilities (interface).
Game configuration data as global variables.
Definition: build_info.cpp:61
const version_info wesnoth_version(VERSION)
Main entry points of multiplayer mode.
Definition: lobby_data.cpp:49
const config & get_test_config_ref()
void set_language(const std::string &language, const std::vector< std::string > *)
Definition: gettext.cpp:494
std::string_view data
Definition: picture.cpp:188
std::map< std::string, struct preproc_define > preproc_map
test_config_cache & cache
test_scoped_define test_def
static config setup_test_config()
static preproc_map setup_test_preproc_map()
BOOST_AUTO_TEST_CASE(test_preproc_defines)
#define GETTEXT_DOMAIN
const std::string test_data_path("data/test/test/_main.cfg")
game_config::scoped_preproc_define_internal< test_config_cache > test_scoped_define
Used to redirect defines settings to test cache.
BOOST_FIXTURE_TEST_SUITE(test_map_location, MLFixture)