The Battle for Wesnoth  1.15.12+dev
test_mp_connect.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2018 by Andrius Silinskas <silinskas.andrius@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-test"
16 
17 #include <boost/test/unit_test.hpp>
18 
19 #include "game_config_manager.hpp"
20 #include "game_display.hpp"
23 #include "mt_rng.hpp"
24 #include "saved_game.hpp"
26 
27 #include <boost/assign.hpp>
28 
29 /* Definitions */
30 
32 public:
34  ng::connect_engine(gamestate, true, nullptr)
35  {}
36 };
37 
38 /* Variables */
39 
40 namespace {
41 
42 std::unique_ptr<saved_game> state;
43 std::unique_ptr<randomness::mt_rng> rng;
44 
45 }
46 
47 /* Global fixture */
48 
51  dummy_args({"wesnoth", "--noaddons"}),
52  cmdline_opts(dummy_args),
53  hotkey_manager(),
54  config_manager()
55  {
56  config_manager.reset(new game_config_manager(cmdline_opts));
57  config_manager->init_game_config(game_config_manager::NO_FORCE_RELOAD);
58 
59  state.reset(new saved_game());
60  state->classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;
61  state->classification().era_id = "era_default";
62  config_manager->load_game_config_for_game(state->classification(), state->get_scenario_id());
63 
64  state->mp_settings().name = "multiplayer_The_Freelands";
65  state->mp_settings().use_map_settings = true;
66  state->mp_settings().saved_game = mp_game_settings::SAVED_GAME_MODE::NONE;
67 
68  state->set_scenario(config_manager->
69  game_config().find_child("multiplayer", "id", state->mp_settings().name));
70 
71  state->mp_settings().num_turns = state->get_starting_point()["turns"];
72 
73  rng.reset(new randomness::mt_rng());
74  }
76  {
77  }
78  std::vector<std::string> dummy_args;
81  std::unique_ptr<game_config_manager> config_manager;
82 };
83 
84 
85 /* Test classes creation utilities */
86 
88 {
90  new test_connect_engine(*state);
91 
92  return connect_engine;
93 }
94 
95 static ng::side_engine* create_side_engine(const config& defaults,
97 {
98  config side_cfg = connect_engine->current_config()->child("side");
99  side_cfg.remove_attributes("faction");
100  side_cfg.clear_children("default_faction");
101  side_cfg.append(defaults);
102 
103  return new ng::side_engine(side_cfg, *connect_engine, 0);
104 }
105 
106 
107 /* Tests */
108 
110 BOOST_AUTO_TEST_SUITE( mp_connect )
111 
112 
113 BOOST_AUTO_TEST_CASE( flg_map_settings )
114 {
115  // Set up side_engine and its dependencies.
116  state->mp_settings().use_map_settings = true;
117  state->mp_settings().saved_game = mp_game_settings::SAVED_GAME_MODE::NONE;
118  std::unique_ptr<test_connect_engine>
121  config side;
122 
123  // Recruit list with no faction.
124  side.clear();
125  side["recruit"] = "Elvish Archer";
126  side_engine.reset(create_side_engine(side, connect_engine.get()));
127  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_factions().size(), 1 );
128  //BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Custom" );
129  BOOST_CHECK_EQUAL( side_engine->new_config()["recruit"], "Elvish Archer" );
130 
131  // Custom faction, no recruits.
132  side.clear();
133  side["faction"] = "Custom";
134  side_engine.reset(create_side_engine(side, connect_engine.get()));
135  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_factions().size(), 1 );
136  BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Custom" );
137  BOOST_CHECK_EQUAL( side_engine->new_config()["recruit"].empty(), true );
138 
139  // Random faction.
140  side.clear();
141  side["faction"] = "Random";
142  side_engine.reset(create_side_engine(side, connect_engine.get()));
143  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_factions().size(), 1 );
144  BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Random" );
145 
146  // Valid faction.
147  side.clear();
148  side["faction"] = "Rebels";
149  side_engine.reset(create_side_engine(side, connect_engine.get()));
150  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_factions().size(), 1 );
151  BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Rebels" );
152 
153  // Invalid faction.
154  side.clear();
155  side["faction"] = "ThisFactionDoesNotExist";
156  side_engine.reset(create_side_engine(side, connect_engine.get()));
157  BOOST_CHECK( side_engine->flg().choosable_factions().size() > 1 );
158  BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Random" );
159 
160  // Faction and recruit list.
161  side.clear();
162  side["recruit"] = "Elvish Archer";
163  side["faction"] = "Undead";
164  side_engine.reset(create_side_engine(side, connect_engine.get()));
165  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_factions().size(), 1 );
166  //BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Custom" );
167  //BOOST_CHECK_EQUAL( side_engine->new_config()["recruit"], "Elvish Archer" );
168 
169  // Carried over recruits.
170  side.clear();
171  side["previous_recruits"] = "Elvish Archer";
172  side_engine.reset(create_side_engine(side, connect_engine.get()));
173  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_factions().size(), 1 );
174  BOOST_CHECK_EQUAL( side_engine->new_config()["previous_recruits"],
175  "Elvish Archer" );
176 
177  // Valid leader unit.
178  side.clear();
179  side["type"] = "Shadow";
180  side_engine.reset(create_side_engine(side, connect_engine.get()));
181  BOOST_CHECK_EQUAL( side_engine->flg().choosable_leaders().size(), 1 );
182  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "Shadow" );
183  BOOST_CHECK_EQUAL( side_engine->new_config()["type"], "Shadow" );
184 
185  // Invalid leader unit.
186  side.clear();
187  side["type"] = "ThisUnitDoesNotExist";
188  side_engine.reset(create_side_engine(side, connect_engine.get()));
189  BOOST_CHECK_EQUAL( side_engine->flg().choosable_leaders().size(), 1 );
190  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "null" );
191 
192  // No leader, Custom faction.
193  side.clear();
194  side["faction"] = "Custom";
195  side_engine.reset(create_side_engine(side, connect_engine.get()));
196  BOOST_CHECK( side_engine->flg().choosable_leaders().size() > 1 );
197  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "random" );
198 
199  // No leader, Random faction.
200  side.clear();
201  side["faction"] = "Random";
202  side_engine.reset(create_side_engine(side, connect_engine.get()));
203  BOOST_CHECK_EQUAL( side_engine->flg().choosable_leaders().size(), 1 );
204  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "null" );
205 
206  // No leader, regular faction.
207  side.clear();
208  side["faction"] = "Undead";
209  side_engine.reset(create_side_engine(side, connect_engine.get()));
210  BOOST_CHECK( side_engine->flg().choosable_leaders().size() > 1 );
211  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "random" );
212 
213  // Carried over leader.
214  side.clear();
215  side["id"] = "LeaderID";
216  side["type"] = "Elvish Archer";
217  config& unit = side.add_child("unit");
218  unit["id"] = "LeaderID";
219  unit["type"] = "Elvish Ranger";
220  side_engine.reset(create_side_engine(side, connect_engine.get()));
221  BOOST_CHECK_EQUAL( side_engine->flg().choosable_leaders().size(), 1 );
222  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "Elvish Ranger" );
223 
224  // Random leader.
225  side.clear();
226  side["type"] = "random";
227  side_engine.reset(create_side_engine(side, connect_engine.get()));
228  BOOST_CHECK_EQUAL( side_engine->flg().choosable_leaders().size(), 1 );
229 
230  // Leader with both genders.
231  side.clear();
232  side["type"] = "Elvish Archer";
233  side_engine.reset(create_side_engine(side, connect_engine.get()));
234  BOOST_CHECK_EQUAL( side_engine->flg().choosable_genders().size(), 3 );
235  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "random" );
236 
237  // Leader with only male gender.
238  side.clear();
239  side["type"] = "Swordsman";
240  side_engine.reset(create_side_engine(side, connect_engine.get()));
241  BOOST_CHECK_EQUAL( side_engine->flg().choosable_genders().size(), 1 );
242  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "male" );
243 
244  // Leader with only female gender.
245  side.clear();
246  side["type"] = "Elvish Druid";
247  side_engine.reset(create_side_engine(side, connect_engine.get()));
248  BOOST_CHECK_EQUAL( side_engine->flg().choosable_genders().size(), 1 );
249  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "female" );
250 
251  // Valid leader with valid gender.
252  side.clear();
253  side["type"] = "White Mage";
254  side["gender"] = "female";
255  side_engine.reset(create_side_engine(side, connect_engine.get()));
256  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_genders().size(), 1 );
257  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "female" );
258 
259  // Valid leader with invalid gender.
260  side.clear();
261  side["type"] = "Troll";
262  side["gender"] = "female";
263  side_engine.reset(create_side_engine(side, connect_engine.get()));
264  BOOST_CHECK_EQUAL( side_engine->flg().choosable_genders().size(), 1 );
265  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "male" );
266 
267  // Leader with random gender.
268  side.clear();
269  side["type"] = "White Mage";
270  side["gender"] = "random";
271  side_engine.reset(create_side_engine(side, connect_engine.get()));
272  //BOOST_CHECK_EQUAL( side_engine->flg().choosable_genders().size(), 1 );
273  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "random" );
274 
275  // No leader.
276  side.clear();
277  side["leader_lock"] = true;
278  side_engine.reset(create_side_engine(side, connect_engine.get()));
279  BOOST_CHECK_EQUAL( side_engine->flg().choosable_leaders().size(), 1 );
280  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "null" );
281 
282  // Resolve random faction.
283  side.clear();
284  side["faction"] = "Random";
285  side_engine.reset(create_side_engine(side, connect_engine.get()));
286  side_engine->resolve_random(*rng);
287  BOOST_CHECK( side_engine->flg().current_faction()["id"] != "Random" );
288  BOOST_CHECK( side_engine->flg().current_leader() != "random" &&
289  side_engine->flg().current_leader() != "null");
290  BOOST_CHECK( side_engine->flg().current_gender() != "random" &&
291  side_engine->flg().current_gender() != "null");
292 
293  // Resolve random faction with default leader.
294  side.clear();
295  side["faction"] = "Random";
296  side["type"] = "Troll";
297  side_engine.reset(create_side_engine(side, connect_engine.get()));
298  side_engine->resolve_random(*rng);
299  BOOST_CHECK( side_engine->flg().current_faction()["id"] != "Random" );
300  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "Troll" );
301  BOOST_CHECK( side_engine->flg().current_gender() != "random" &&
302  side_engine->flg().current_gender() != "null" );
303 
304  // Resolve random faction with default leader and gender.
305  side.clear();
306  side["faction"] = "Random";
307  side["type"] = "White Mage";
308  side["gender"] = "male";
309  side_engine.reset(create_side_engine(side, connect_engine.get()));
310  side_engine->resolve_random(*rng);
311  BOOST_CHECK( side_engine->flg().current_faction()["id"] != "Random" );
312  BOOST_CHECK_EQUAL( side_engine->flg().current_leader(), "White Mage" );
313  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "male" );
314 
315  // Resolve random leader.
316  side.clear();
317  side["type"] = "random";
318  side_engine.reset(create_side_engine(side, connect_engine.get()));
319  side_engine->resolve_random(*rng);
320  BOOST_CHECK( side_engine->flg().current_leader() != "random" );
321 }
322 
323 BOOST_AUTO_TEST_CASE( flg_no_map_settings )
324 {
325  // Set up side_engine and its dependencies.
326  state->mp_settings().use_map_settings = false;
327  state->mp_settings().saved_game = mp_game_settings::SAVED_GAME_MODE::NONE;
328  const std::unique_ptr<test_connect_engine>
331  config side;
332 
333  // Recruit list with no faction.
334  side.clear();
335  side["recruit"] = "Elvish Archer";
336  side_engine.reset(create_side_engine(side, connect_engine.get()));
337  BOOST_CHECK( side_engine->flg().choosable_factions().size() > 1 );
338  //BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Custom" );
339 
340  // Custom faction, no recruits.
341  side.clear();
342  side["faction"] = "Custom";
343  side_engine.reset(create_side_engine(side, connect_engine.get()));
344  BOOST_CHECK( side_engine->flg().choosable_factions().size() > 1 );
345  BOOST_CHECK_EQUAL( side_engine->flg().current_faction()["id"], "Custom" );
346  BOOST_CHECK_EQUAL( side_engine->new_config()["recruit"].empty(), true );
347 
348  // Carried over recruits.
349  side.clear();
350  side["previous_recruits"] = "Elvish Archer";
351  side_engine.reset(create_side_engine(side, connect_engine.get()));
352  BOOST_CHECK( side_engine->flg().choosable_factions().size() > 1 );
353  BOOST_CHECK_EQUAL( side_engine->new_config()["previous_recruits"],
354  "Elvish Archer" );
355 
356  // Explicit leader for faction with multiple leaders.
357  side.clear();
358  side["type"] = "Goblin Impaler";
359  side_engine.reset(create_side_engine(side, connect_engine.get()));
360  side_engine->flg().set_current_faction("Rebels");
361  BOOST_CHECK( side_engine->flg().choosable_leaders().size() > 1 );
362 
363  // Duplicate leaders.
364  side.clear();
365  side["faction"] = "Custom";
366  side["type"] = "Swordsman";
367  side_engine.reset(create_side_engine(side, connect_engine.get()));
368  BOOST_CHECK( side_engine->flg().choosable_leaders().size() > 1 );
369  const std::vector<std::string>& leaders =
370  side_engine->flg().choosable_leaders();
371  BOOST_CHECK_EQUAL( std::count(leaders.begin(), leaders.end(), "Swordsman"),
372  1 );
373 
374  // Explicit gender for unit with both genders available.
375  side.clear();
376  side["gender"] = "female";
377  side_engine.reset(create_side_engine(side, connect_engine.get()));
378  side_engine->flg().set_current_faction("Rebels");
379  side_engine->flg().set_current_leader("Elvish Ranger");
380  BOOST_CHECK_EQUAL( side_engine->flg().current_gender(), "random" );
381 }
382 
383 BOOST_AUTO_TEST_CASE( flg_saved_game )
384 {
385  // TODO
386 }
387 
388 BOOST_AUTO_TEST_SUITE_END()
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:414
void clear_children(T... keys)
Definition: config.hpp:526
This class represents a single unit of a specific type.
Definition: unit.hpp:120
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:281
this class is initialized once at game start put all initialization and wipe code in the methods here...
void remove_attributes(T... keys)
Definition: config.hpp:491
BOOST_GLOBAL_FIXTURE(mp_connect_fixture)
Don&#39;t reload if the previous defines equal the new defines.
void clear()
Definition: config.cpp:895
static ng::side_engine * create_side_engine(const config &defaults, test_connect_engine *connect_engine)
BOOST_AUTO_TEST_CASE(flg_map_settings)
BOOST_AUTO_TEST_SUITE(filesystem)
Default, unset return value.
Definition: retval.hpp:31
Game configuration data as global variables.
Definition: build_info.cpp:58
std::unique_ptr< game_config_manager > config_manager
static test_connect_engine * create_test_connect_engine()
std::vector< std::string > dummy_args
std::shared_ptr< side_engine > side_engine_ptr
config & add_child(config_key_type key)
Definition: config.cpp:500
commandline_options cmdline_opts
hotkey::manager hotkey_manager
connect_engine(saved_game &state, const bool first_scenario, mp_game_metadata *metadata)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
friend class side_engine
test_connect_engine(saved_game &gamestate)