The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
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 target;
35
36#ifdef __APPLE__
37 target.try_emplace("APPLE");
38#endif
39
40#ifdef __ANDROID__
41 target.try_emplace("ANDROID");
42#endif
43
44// apparently defined now with the macos-15 github actions CI runner
45#if defined(MOUSE_TOUCH_EMULATION) || defined(TARGET_OS_IPHONE)
46 target.try_emplace("IPHONEOS");
47#endif
48
49 target.try_emplace("WESNOTH_VERSION", game_config::wesnoth_version.str());
50
51 target.try_emplace("WESNOTH_VERSION_MAJOR", std::to_string(game_config::wesnoth_version.major_version()));
52 target.try_emplace("WESNOTH_VERSION_MINOR", std::to_string(game_config::wesnoth_version.minor_version()));
53 target.try_emplace("WESNOTH_VERSION_REVISION", std::to_string(game_config::wesnoth_version.revision_level()));
54 target.try_emplace("WESNOTH_VERSION_SPECIAL", game_config::wesnoth_version.special_version());
55
56 return target;
57}
58
59/**
60 * Used to make distinct singleton for testing it
61 * because other tests will need original one to load data
62 **/
74
76 static test_config_cache * cache_ = new test_config_cache;
77 return *cache_;
78}
79
80/**
81 * Used to redirect defines settings to test cache
82 **/
84
98
99BOOST_AUTO_TEST_CASE( test_preproc_defines )
100{
102 const preproc_map& test_defines = cache.get_preproc_map();
103 preproc_map defines_map(setup_test_preproc_map());
104
105 // check initial state
106 BOOST_REQUIRE_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
107 defines_map.begin() ,defines_map.end());
108
109 // scoped
110 {
111 test_scoped_define test("TEST");
112 defines_map.try_emplace("TEST");;
113
114 BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
115 defines_map.begin() ,defines_map.end());
116 defines_map.erase("TEST");
117 }
118 // Check scoped remove
119
120 BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
121 defines_map.begin() ,defines_map.end());
122
123 // Manual add define
124 cache.add_define("TEST");
125 defines_map.try_emplace("TEST");;
126 BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
127 defines_map.begin() ,defines_map.end());
128
129 // Manual remove define
130 cache.remove_define("TEST");
131 defines_map.erase("TEST");
132 BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
133 defines_map.begin() ,defines_map.end());
134}
135
136BOOST_AUTO_TEST_CASE( test_config_cache_defaults )
137{
139 preproc_map defines_map(setup_test_preproc_map());
140
141 const preproc_map& test_defines = cache.get_preproc_map();
142 BOOST_CHECK_EQUAL_COLLECTIONS(test_defines.begin(),test_defines.end(),
143 defines_map.begin() ,defines_map.end());
144}
145
146
148
149 const std::string test_data_path("data/test/test/_main.cfg");
150
152{
153 config test_config;
154 config* child = &test_config.add_child("textdomain");
155 (*child)["name"] = GETTEXT_DOMAIN;
156
157 child = &test_config.add_child("test_key");
158 (*child)["define"] = "test";
159 return test_config;
160}
161
162
163BOOST_AUTO_TEST_CASE( test_load_config )
164{
165 config test_config = setup_test_config();
166 config cached_config = cache.get_config(test_data_path);
167 BOOST_CHECK_EQUAL(test_config, cached_config);
168
169 config &child = test_config.add_child("test_key2");
170 child["define"] = t_string("testing translation reset.", GETTEXT_DOMAIN);
171
172 test_scoped_define test_define_def("TEST_DEFINE");
173 cached_config = cache.get_config(test_data_path);
174 BOOST_CHECK_EQUAL(test_config, cached_config);
175
176 BOOST_CHECK_EQUAL(test_config.mandatory_child("test_key2")["define"].str(), cached_config.mandatory_child("test_key2")["define"].str());
177}
178
179BOOST_AUTO_TEST_CASE( test_macrosubstitution )
180{
181 config test_config = setup_test_config();
182
183 config &child = test_config.add_child("test_key3");
184 child["define"] = "transaction";
185 config &child2 = test_config.add_child("test_key4");
186 child2["defined"] = "parameter";
187
188 // test first that macro loading works
189 test_scoped_define macro("TEST_MACRO");
190
191 // Without cache
192 config cached_config = cache.get_config(test_data_path);
193 BOOST_CHECK_EQUAL(test_config, cached_config);
194
195 // With cache
196 cached_config = cache.get_config(test_data_path);
197 BOOST_CHECK_EQUAL(test_config, cached_config);
198}
199
200BOOST_AUTO_TEST_CASE( test_transaction )
201{
202 config test_config = setup_test_config();
203
204 config* child = &test_config.add_child("test_key3");
205 (*child)["define"] = "transaction";
206 child = &test_config.add_child("test_key4");
207 (*child)["defined"] = "parameter";
208
209 // test first that macro loading works
210 test_scoped_define macro("TEST_MACRO");
211
212 //Start transaction
213
215
216 config cached_config = cache.get_config(test_data_path);
217 BOOST_CHECK_EQUAL(test_config, cached_config);
218
219 transaction.lock();
220 config umc_config;
221 child = &umc_config.add_child("umc");
222 (*child)["test"] = "umc load";
223 child = &umc_config.add_child("test_key3");
224 (*child)["define"] = "transaction";
225 child = &umc_config.add_child("test_key4");
226 (*child)["defined"] = "parameter";
227 cached_config = cache.get_config("data/test/test/umc.cfg");
228 BOOST_CHECK_EQUAL(umc_config, cached_config);
229}
230
231BOOST_AUTO_TEST_CASE( test_define_loading )
232{
233 // try to load umc without valid cache
234 config test_config = setup_test_config();
235
236 config* child = &test_config.add_child("test_key3");
237 (*child)["define"] = "transaction";
238 child = &test_config.add_child("test_key4");
239 (*child)["defined"] = "parameter";
240
241 // test first that macro loading works
242 test_scoped_define macro("TEST_MACRO");
243
244 //Start transaction
245
247
248 config cached_config = cache.get_config(test_data_path);
249 BOOST_CHECK_EQUAL(test_config, cached_config);
250
251 transaction.lock();
252
253 cache.set_force_invalid_cache(true);
254 config umc_config;
255 child = &umc_config.add_child("umc");
256 (*child)["test"] = "umc load";
257 child = &umc_config.add_child("test_key3");
258 (*child)["define"] = "transaction";
259 child = &umc_config.add_child("test_key4");
260 (*child)["defined"] = "parameter";
261 cached_config = cache.get_config("data/test/test/umc.cfg");
262 BOOST_CHECK_EQUAL(umc_config, cached_config);
263 cache.set_force_invalid_cache(false);
264}
265
266BOOST_AUTO_TEST_CASE( test_lead_spaces_loading )
267{
268 config test_config;
269 test_config.add_child("test_lead_space")["space"] = "empty char in middle";
270 // Force reload of cache
271 cache.set_force_invalid_cache(true);
272 config cached_config = cache.get_config("data/test/test/leading_space.cfg");
273 BOOST_CHECK_EQUAL(test_config, cached_config);
274 cache.set_force_invalid_cache(false);
275 cached_config = cache.get_config("data/test/test/leading_space.cfg");
276 BOOST_CHECK_EQUAL(test_config, cached_config);
277}
278
279#if 0
280// for profiling cache speed
281BOOST_AUTO_TEST_CASE( test_performance )
282{
283 test_scoped_define mp("MULTIPLAYER");
284// cache.set_force_invalid_cache(true);
285 config cfg_ref = cache.get_config("data/");
286// cache.set_force_invalid_cache(false);
287 for (int i=0; i < 3; ++i)
288 {
289 cfg_ref = cache.get_config("data/");
290 }
291}
292#endif
293
294/* vim: set ts=4 sw=4: */
295BOOST_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.
Used to set and unset scoped defines to preproc_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
Interfaces for manipulating version numbers of engine, add-ons, etc.
const language_def & get_language()
Definition language.cpp:317
void set_language(const language_def &locale)
Definition language.cpp:259
Standard logging facilities (interface).
Game configuration data as global variables.
const version_info wesnoth_version(VERSION)
Main entry points of multiplayer mode.
STL namespace.
const config & get_test_config_ref()
std::string_view data
Definition picture.cpp:188
std::map< std::string, struct preproc_define > preproc_map
std::unordered_map< std::string, cache_item > cache
Definition sound.cpp:146
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)
#define i