The Battle for Wesnoth  1.19.24+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  defines_map.try_emplace("WESNOTH_VERSION_MAJOR", std::to_string(game_config::wesnoth_version.major_version()));
42  defines_map.try_emplace("WESNOTH_VERSION_MINOR", std::to_string(game_config::wesnoth_version.minor_version()));
43  defines_map.try_emplace("WESNOTH_VERSION_REVISION", std::to_string(game_config::wesnoth_version.revision_level()));
44  defines_map.try_emplace("WESNOTH_VERSION_SPECIAL", game_config::wesnoth_version.special_version());
45  return defines_map;
46 }
47 
48 /**
49  * Used to make distinct singleton for testing it
50  * because other tests will need original one to load data
51  **/
54 
55  public:
56  static test_config_cache& instance() ;
57 
58  void set_force_invalid_cache(bool force)
59  {
61  }
62 };
63 
65  static test_config_cache * cache_ = new test_config_cache;
66  return *cache_;
67 }
68 
69 /**
70  * Used to redirect defines settings to test cache
71  **/
73 
76  {
78  }
80  {
82  }
86 };
87 
88 BOOST_AUTO_TEST_CASE( test_preproc_defines )
89 {
91  const preproc_map& test_defines = cache.get_preproc_map();
92  preproc_map defines_map(setup_test_preproc_map());
93 
94  // check initial state
95  BOOST_REQUIRE_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
96  defines_map.begin() ,defines_map.end());
97 
98  // scoped
99  {
100  test_scoped_define test("TEST");
101  defines_map.try_emplace("TEST");;
102 
103  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
104  defines_map.begin() ,defines_map.end());
105  defines_map.erase("TEST");
106  }
107  // Check scoped remove
108 
109  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
110  defines_map.begin() ,defines_map.end());
111 
112  // Manual add define
113  cache.add_define("TEST");
114  defines_map.try_emplace("TEST");;
115  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
116  defines_map.begin() ,defines_map.end());
117 
118  // Manual remove define
119  cache.remove_define("TEST");
120  defines_map.erase("TEST");
121  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
122  defines_map.begin() ,defines_map.end());
123 }
124 
125 BOOST_AUTO_TEST_CASE( test_config_cache_defaults )
126 {
128  preproc_map defines_map(setup_test_preproc_map());
129 
130  const preproc_map& test_defines = cache.get_preproc_map();
131  BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
132  defines_map.begin() ,defines_map.end());
133 }
134 
135 
137 
138  const std::string test_data_path("data/test/test/_main.cfg");
139 
141 {
142  config test_config;
143  config* child = &test_config.add_child("textdomain");
144  (*child)["name"] = GETTEXT_DOMAIN;
145 
146  child = &test_config.add_child("test_key");
147  (*child)["define"] = "test";
148  return test_config;
149 }
150 
151 
152 BOOST_AUTO_TEST_CASE( test_load_config )
153 {
154  config test_config = setup_test_config();
155  config cached_config = cache.get_config(test_data_path);
156  BOOST_CHECK_EQUAL(test_config, cached_config);
157 
158  config &child = test_config.add_child("test_key2");
159  child["define"] = t_string("testing translation reset.", GETTEXT_DOMAIN);
160 
161  test_scoped_define test_define_def("TEST_DEFINE");
162  cached_config = cache.get_config(test_data_path);
163  BOOST_CHECK_EQUAL(test_config, cached_config);
164 
165  BOOST_CHECK_EQUAL(test_config.mandatory_child("test_key2")["define"].str(), cached_config.mandatory_child("test_key2")["define"].str());
166 }
167 
168 BOOST_AUTO_TEST_CASE( test_macrosubstitution )
169 {
170  config test_config = setup_test_config();
171 
172  config &child = test_config.add_child("test_key3");
173  child["define"] = "transaction";
174  config &child2 = test_config.add_child("test_key4");
175  child2["defined"] = "parameter";
176 
177  // test first that macro loading works
178  test_scoped_define macro("TEST_MACRO");
179 
180  // Without cache
181  config cached_config = cache.get_config(test_data_path);
182  BOOST_CHECK_EQUAL(test_config, cached_config);
183 
184  // With cache
185  cached_config = cache.get_config(test_data_path);
186  BOOST_CHECK_EQUAL(test_config, cached_config);
187 }
188 
189 BOOST_AUTO_TEST_CASE( test_transaction )
190 {
191  config test_config = setup_test_config();
192 
193  config* child = &test_config.add_child("test_key3");
194  (*child)["define"] = "transaction";
195  child = &test_config.add_child("test_key4");
196  (*child)["defined"] = "parameter";
197 
198  // test first that macro loading works
199  test_scoped_define macro("TEST_MACRO");
200 
201  //Start transaction
202 
204 
205  config cached_config = cache.get_config(test_data_path);
206  BOOST_CHECK_EQUAL(test_config, cached_config);
207 
208  transaction.lock();
209  config umc_config;
210  child = &umc_config.add_child("umc");
211  (*child)["test"] = "umc load";
212  child = &umc_config.add_child("test_key3");
213  (*child)["define"] = "transaction";
214  child = &umc_config.add_child("test_key4");
215  (*child)["defined"] = "parameter";
216  cached_config = cache.get_config("data/test/test/umc.cfg");
217  BOOST_CHECK_EQUAL(umc_config, cached_config);
218 }
219 
220 BOOST_AUTO_TEST_CASE( test_define_loading )
221 {
222  // try to load umc without valid cache
223  config test_config = setup_test_config();
224 
225  config* child = &test_config.add_child("test_key3");
226  (*child)["define"] = "transaction";
227  child = &test_config.add_child("test_key4");
228  (*child)["defined"] = "parameter";
229 
230  // test first that macro loading works
231  test_scoped_define macro("TEST_MACRO");
232 
233  //Start transaction
234 
236 
237  config cached_config = cache.get_config(test_data_path);
238  BOOST_CHECK_EQUAL(test_config, cached_config);
239 
240  transaction.lock();
241 
242  cache.set_force_invalid_cache(true);
243  config umc_config;
244  child = &umc_config.add_child("umc");
245  (*child)["test"] = "umc load";
246  child = &umc_config.add_child("test_key3");
247  (*child)["define"] = "transaction";
248  child = &umc_config.add_child("test_key4");
249  (*child)["defined"] = "parameter";
250  cached_config = cache.get_config("data/test/test/umc.cfg");
251  BOOST_CHECK_EQUAL(umc_config, cached_config);
252  cache.set_force_invalid_cache(false);
253 }
254 
255 BOOST_AUTO_TEST_CASE( test_lead_spaces_loading )
256 {
257  config test_config;
258  test_config.add_child("test_lead_space")["space"] = "empty char in middle";
259  // Force reload of cache
260  cache.set_force_invalid_cache(true);
261  config cached_config = cache.get_config("data/test/test/leading_space.cfg");
262  BOOST_CHECK_EQUAL(test_config, cached_config);
263  cache.set_force_invalid_cache(false);
264  cached_config = cache.get_config("data/test/test/leading_space.cfg");
265  BOOST_CHECK_EQUAL(test_config, cached_config);
266 }
267 
268 #if 0
269 // for profiling cache speed
270 BOOST_AUTO_TEST_CASE( test_performance )
271 {
272  test_scoped_define mp("MULTIPLAYER");
273 // cache.set_force_invalid_cache(true);
274  config cfg_ref = cache.get_config("data/");
275 // cache.set_force_invalid_cache(false);
276  for (int i=0; i < 3; ++i)
277  {
278  cfg_ref = cache.get_config("data/");
279  }
280 }
281 #endif
282 
283 /* vim: set ts=4 sw=4: */
284 BOOST_AUTO_TEST_SUITE_END()
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:157
config & add_child(std::string_view key)
Definition: config.cpp:436
config & mandatory_child(std::string_view key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
Definition: config.cpp:362
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:1031
Interfaces for manipulating version numbers of engine, add-ons, etc.
const language_def & get_language()
Definition: language.cpp:311
Standard logging facilities (interface).
Game configuration data as global variables.
Definition: build_info.cpp:68
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 to_string(const Range &range, const Func &op)
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)