The Battle for Wesnoth  1.19.0-dev
test_gui2.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2024
3  by Mark de Wever <koraq@xs4all.nl>
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 // In this domain since it compares a shared string from this domain.
17 #define GETTEXT_DOMAIN "wesnoth-lib"
18 
19 #include "addon/client.hpp"
20 #include "addon/info.hpp"
21 #include "config_cache.hpp"
22 #include "filesystem.hpp"
23 #include "formula/debugger.hpp"
24 #include "game_config.hpp"
25 #include "game_config_manager.hpp"
26 #include "game_config_view.hpp"
27 #include "game_display.hpp"
28 #include "game_events/manager.hpp"
32 #include "game_launcher.hpp"
34 #include "gettext.hpp"
45 #include "gui/dialogs/chat_log.hpp"
83 #include "gui/dialogs/message.hpp"
98 #include "gui/dialogs/outro.hpp"
99 #include "gui/dialogs/prompt.hpp"
110 #include "gui/dialogs/tooltip.hpp"
115 #include "gui/dialogs/unit_list.hpp"
118 #include "gui/dialogs/wml_error.hpp"
120 #include "gui/widgets/settings.hpp"
121 #include "gui/widgets/window.hpp"
122 #include "language.hpp"
123 #include "map/map.hpp"
124 #include "replay.hpp"
125 #include "save_index.hpp"
126 #include "saved_game.hpp"
128 #include "terrain/type_data.hpp"
130 #include "utils/general.hpp"
131 #include "wesnothd_connection.hpp"
132 #include "wml_exception.hpp"
133 
134 #include <boost/test/unit_test.hpp>
135 
136 #include <functional>
137 #include <memory>
138 
139 using namespace gui2::dialogs;
140 
143  : config_manager()
144  , dummy_args({"wesnoth", "--noaddons"})
145  {
146  /** The main config, which contains the entire WML tree. */
147  game_config_view game_config_view_ = game_config_view::wrap(main_config);
148  config_manager.reset(new game_config_manager(dummy_args));
149 
151 
152  cache.clear_defines();
153  cache.add_define("EDITOR");
154  cache.add_define("MULTIPLAYER");
155  cache.get_config(game_config::path +"/data", main_config);
156 
157  const filesystem::binary_paths_manager bin_paths_manager(game_config_view_);
158 
160  game_config::load_config(main_config.mandatory_child("game_config"));
161  }
163  {
164  }
166  static const std::string widgets_file;
167  std::unique_ptr<game_config_manager> config_manager;
168  std::vector<std::string> dummy_args;
169 };
171 const std::string test_gui2_fixture::widgets_file = "widgets_tested.log";
172 
173 namespace gui2 {
174 
175 namespace dialogs {
176 
177 std::string get_modal_dialog_id(const modal_dialog& dialog)
178 {
179  return dialog.window_id();
180 }
181 
182 std::string get_modeless_dialog_id(const modeless_dialog& dialog)
183 {
184  return dialog.window_id();
185 }
186 
187 } // namespace dialogs
188 } // namespace gui2
189 
190 namespace {
191 
192  /**
193  * Helper class to generate a dialog.
194  *
195  * This class makes sure the dialog is properly created and initialized.
196  * The specialized versions are at the end of this file.
197  */
198  template<class T>
199  struct dialog_tester
200  {
201  T* create() { return new T(); }
202  };
203 
204  typedef std::pair<unsigned, unsigned> resolution;
205  typedef std::vector<std::pair<unsigned, unsigned>> resolution_list;
206 
207  template<class T>
208  void test_resolutions(const resolution_list& resolutions)
209  {
210  for(const resolution& resolution : resolutions) {
212 
213  dialog_tester<T> ctor;
214  const std::unique_ptr<modal_dialog> dlg(ctor.create());
215  BOOST_REQUIRE_MESSAGE(dlg.get(), "Failed to create a dialog.");
216 
217  std::string id = get_modal_dialog_id(*dlg.get());
218  filesystem::write_file(test_gui2_fixture::widgets_file, ","+id, std::ios_base::app);
219 
220  std::string exception;
221  try {
222  dlg->show(1);
223  } catch(const gui2::layout_exception_width_modified&) {
224  exception = "gui2::layout_exception_width_modified";
226  exception = "gui2::layout_exception_width_resize_failed";
228  exception = "gui2::layout_exception_height_resize_failed";
229  } catch(const wml_exception& e) {
230  exception = e.dev_message;
231  } catch(const std::exception& e) {
232  exception = e.what();
233  } catch(...) {
234  exception = utils::get_unknown_exception_type();
235  }
236  BOOST_CHECK_MESSAGE(exception.empty(),
237  "Test for '" << id
238  << "' Failed\nnew widgets = " << gui2::new_widgets
239  << " resolution = " << resolution.first
240  << 'x' << resolution.second
241  << "\nException caught: " << exception << '.');
242  }
243  }
244 
245  template<class T>
246  void test_popup_resolutions(const resolution_list& resolutions)
247  {
248  bool interact = false;
249  for(int i = 0; i < 2; ++i) {
250  for(const resolution& resolution : resolutions) {
251  // debug clock doesn't work at 800x600
252  if(resolution.first == 800 && resolution.second == 600) {
253  continue;
254  }
256 
257  dialog_tester<T> ctor;
258  const std::unique_ptr<modeless_dialog> dlg(ctor.create());
259  BOOST_REQUIRE_MESSAGE(dlg.get(), "Failed to create a dialog.");
260 
261  std::string id = get_modeless_dialog_id(*dlg.get());
262  filesystem::write_file(test_gui2_fixture::widgets_file, ","+id, std::ios_base::app);
263 
264  std::string exception;
265  try {
266  dlg->show(interact);
267  gui2::window* window = dlg.get();
268  BOOST_REQUIRE_NE(window, static_cast<void*>(nullptr));
269  window->draw();
270  } catch(const gui2::layout_exception_width_modified&) {
271  exception = "gui2::layout_exception_width_modified";
273  exception = "gui2::layout_exception_width_resize_failed";
275  exception = "gui2::layout_exception_height_resize_failed";
276  } catch(const wml_exception& e) {
277  exception = e.dev_message;
278  } catch(const std::exception& e) {
279  exception = e.what();
280  } catch(...) {
281  exception = utils::get_unknown_exception_type();
282  }
283  BOOST_CHECK_MESSAGE(exception.empty(),
284  "Test for '" << id
285  << "' Failed\nnew widgets = " << gui2::new_widgets
286  << " resolution = " << resolution.first
287  << 'x' << resolution.second
288  << "\nException caught: " << exception << '.');
289  }
290 
291  interact = true;
292  }
293  }
294 
295 #ifdef _MSC_VER
296 #pragma warning(push)
297 #pragma warning(disable: 4702)
298 #endif
299  void test_tip_resolutions(const resolution_list& resolutions
300  , const std::string& id)
301  {
302  for(const auto& resolution : resolutions) {
304 
305  filesystem::write_file(test_gui2_fixture::widgets_file, ","+id, std::ios_base::app);
306 
307  std::string exception;
308  try {
309  tip::show(id
310  , "Test message for a tooltip."
311  , point(0, 0)
312  , {0,0,0,0});
313  tip::remove();
314  } catch(const gui2::layout_exception_width_modified&) {
315  exception = "gui2::layout_exception_width_modified";
317  exception = "gui2::layout_exception_width_resize_failed";
319  exception = "gui2::layout_exception_height_resize_failed";
320  } catch(const wml_exception& e) {
321  exception = e.dev_message;
322  } catch(const std::exception& e) {
323  exception = e.what();
324  } catch(...) {
325  exception = utils::get_unknown_exception_type();
326  }
327  BOOST_CHECK_MESSAGE(exception.empty(),
328  "Test for tip '" << id
329  << "' Failed\nnew widgets = " << gui2::new_widgets
330  << " resolution = " << resolution.first
331  << 'x' << resolution.second
332  << "\nException caught: " << exception << '.');
333  }
334  }
335 #ifdef _MSC_VER
336 #pragma warning(pop)
337 #endif
338 
339 const resolution_list& get_gui_resolutions()
340 {
341  static resolution_list result {
342  {800, 600},
343  {1024, 768},
344  {1280, 1024},
345  {1680, 1050},
346  };
347 
348  return result;
349 }
350 
351 template<class T>
352 void test()
353 {
354  gui2::new_widgets = false;
355 
356 // for(std::size_t i = 0; i < 2; ++i) {
357 
358  test_resolutions<T>(get_gui_resolutions());
359 
360 // break; // FIXME: New widgets break
361 // gui2::new_widgets = true;
362 // }
363 }
364 
365 template<class T>
366 void test_popup()
367 {
368  gui2::new_widgets = false;
369 
370  for(std::size_t i = 0; i < 2; ++i) {
371 
372  test_popup_resolutions<T>(get_gui_resolutions());
373 
374  gui2::new_widgets = true;
375  }
376 }
377 
378 void test_tip(const std::string& id)
379 {
380  gui2::new_widgets = false;
381 
382  for(std::size_t i = 0; i < 2; ++i) {
383 
384  test_tip_resolutions(get_gui_resolutions(), id);
385 
386  gui2::new_widgets = true;
387  }
388 }
389 
390 } // namespace
391 
393 
394 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_auth)
395 {
396  test<addon_auth>();
397 }
398 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_connect)
399 {
400  test<addon_connect>();
401 }
402 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_license_prompt)
403 {
404  test<addon_license_prompt>();
405 }
406 BOOST_AUTO_TEST_CASE(modal_dialog_test_campaign_difficulty)
407 {
408  test<campaign_difficulty>();
409 }
410 BOOST_AUTO_TEST_CASE(modal_dialog_test_chat_log)
411 {
412  test<chat_log>();
413 }
414 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_choose_addon)
415 {
416  test<editor_choose_addon>();
417 }
418 BOOST_AUTO_TEST_CASE(modal_dialog_test_prompt)
419 {
420  test<prompt>();
421 }
422 BOOST_AUTO_TEST_CASE(modal_dialog_test_core_selection)
423 {
424  test<core_selection>();
425 }
426 BOOST_AUTO_TEST_CASE(modal_dialog_test_custom_tod)
427 {
428  test<custom_tod>();
429 }
430 BOOST_AUTO_TEST_CASE(modal_dialog_test_depcheck_confirm_change)
431 {
432  test<depcheck_confirm_change>();
433 }
434 BOOST_AUTO_TEST_CASE(modal_dialog_test_depcheck_select_new)
435 {
436  test<depcheck_select_new>();
437 }
438 BOOST_AUTO_TEST_CASE(modal_dialog_test_edit_label)
439 {
440  test<edit_label>();
441 }
442 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_pbl)
443 {
444  test<editor_edit_pbl>();
445 }
446 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_pbl_translation)
447 {
448  test<editor_edit_pbl_translation>();
449 }
450 BOOST_AUTO_TEST_CASE(modal_dialog_test_edit_text)
451 {
452  test<edit_text>();
453 }
454 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_label)
455 {
456  test<editor_edit_label>();
457 }
458 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_side)
459 {
460  test<editor_edit_side>();
461 }
462 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_scenario)
463 {
464  test<editor_edit_scenario>();
465 }
466 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_generate_map)
467 {
468  test<editor_generate_map>();
469 }
470 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_new_map)
471 {
472  test<editor_new_map>();
473 }
474 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_resize_map)
475 {
476  test<editor_resize_map>();
477 }
478 BOOST_AUTO_TEST_CASE(modal_dialog_test_faction_select)
479 {
480  test<faction_select>();
481 }
482 BOOST_AUTO_TEST_CASE(modal_dialog_test_file_dialog)
483 {
484  test<file_dialog>();
485 }
486 BOOST_AUTO_TEST_CASE(modal_dialog_test_folder_create)
487 {
488  test<folder_create>();
489 }
490 BOOST_AUTO_TEST_CASE(modal_dialog_test_formula_debugger)
491 {
492  test<formula_debugger>();
493 }
494 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_cache_options)
495 {
496  test<game_cache_options>();
497 }
498 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_delete)
499 {
500  test<game_delete>();
501 }
502 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_version)
503 {
504  test<game_version>();
505 }
506 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_save)
507 {
508  test<game_save>();
509 }
510 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_save_message)
511 {
512  test<game_save_message>();
513 }
514 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_save_oos)
515 {
516  test<game_save_oos>();
517 }
518 BOOST_AUTO_TEST_CASE(modal_dialog_test_generator_settings)
519 {
520  test<generator_settings>();
521 }
522 BOOST_AUTO_TEST_CASE(modal_dialog_test_hotkey_bind)
523 {
524  test<hotkey_bind>();
525 }
526 BOOST_AUTO_TEST_CASE(modal_dialog_test_install_dependencies)
527 {
528  test<install_dependencies>();
529 }
530 BOOST_AUTO_TEST_CASE(modal_dialog_test_language_selection)
531 {
532  test<language_selection>();
533 }
534 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_lobby)
535 {
536  test<mp_lobby>();
537 }
538 BOOST_AUTO_TEST_CASE(modal_dialog_test_lobby_player_info)
539 {
540  test<lobby_player_info>();
541 }
542 BOOST_AUTO_TEST_CASE(modal_dialog_test_log_settings)
543 {
544  test<log_settings>();
545 }
546 BOOST_AUTO_TEST_CASE(modal_dialog_test_message)
547 {
548  test<message>();
549 }
550 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_alerts_options)
551 {
552  test<mp_alerts_options>();
553 }
554 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_connect)
555 {
556  test<mp_connect>();
557 }
558 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_join_game_password_prompt)
559 {
560  test<mp_join_game_password_prompt>();
561 }
562 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_login)
563 {
564  test<mp_login>();
565 }
566 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_method_selection)
567 {
568  test<mp_method_selection>();
569 }
570 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_report)
571 {
572  test<mp_report>();
573 }
574 BOOST_AUTO_TEST_CASE(modal_dialog_test_simple_item_selector)
575 {
576  test<simple_item_selector>();
577 }
578 BOOST_AUTO_TEST_CASE(modal_dialog_test_screenshot_notification)
579 {
580  test<screenshot_notification>();
581 }
582 BOOST_AUTO_TEST_CASE(modal_dialog_test_select_orb_colors)
583 {
584  test<select_orb_colors>();
585 }
586 BOOST_AUTO_TEST_CASE(modal_dialog_test_statistics_dialog)
587 {
588  test<statistics_dialog>();
589 }
590 BOOST_AUTO_TEST_CASE(modal_dialog_test_surrender_quit)
591 {
592  test<surrender_quit>();
593 }
594 BOOST_AUTO_TEST_CASE(modal_dialog_test_theme_list)
595 {
596  test<theme_list>();
597 }
598 BOOST_AUTO_TEST_CASE(modal_dialog_test_transient_message)
599 {
600  test<transient_message>();
601 }
602 BOOST_AUTO_TEST_CASE(modal_dialog_test_unit_create)
603 {
604  test<unit_create>();
605 }
606 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_error)
607 {
608  test<wml_error>();
609 }
610 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_message_left)
611 {
612  test<wml_message_left>();
613 }
614 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_message_right)
615 {
616  test<wml_message_right>();
617 }
618 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_message_double)
619 {
620  test<wml_message_double>();
621 }
622 BOOST_AUTO_TEST_CASE(modal_dialog_test_achievements_dialog)
623 {
624  test<achievements_dialog>();
625 }
626 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_match_history_dialog)
627 {
628  test<mp_match_history>();
629 }
630 BOOST_AUTO_TEST_CASE(modeless_dialog_test_debug_clock)
631 {
632  test_popup<debug_clock>();
633 }
634 BOOST_AUTO_TEST_CASE(tooltip_test_tooltip_large)
635 {
636  test_tip("tooltip_large");
637 }
638 BOOST_AUTO_TEST_CASE(tooltip_test_tooltip)
639 {
640  test_tip("tooltip");
641 }
642 BOOST_AUTO_TEST_CASE(modal_dialog_test_tod_new_schedule)
643 {
644  test<tod_new_schedule>();
645 }
646 
647 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_unit)
648 {
649  test<editor_edit_unit>();
650 }
651 
652 // execute last - checks that there aren't any unaccounted for GUIs
654 {
655  std::set<std::string> widget_list = gui2::registered_window_types();
656  std::vector<std::string> widgets_tested = utils::split(filesystem::read_file(test_gui2_fixture::widgets_file));
657  std::set<std::string> omitted {
658  /*
659  * The unit attack unit test are disabled for now, they calling parameters
660  * don't allow 'nullptr's needs to be fixed.
661  */
662  "unit_attack",
663  // No test for this right now, not sure how to use the test system
664  // for dialog with no default constructor
665  "lua_interpreter",
666  /*
667  * Disable label settings dialog test because we need a display_context
668  * object, which we don't have, and it's a lot of work to produce a dummy
669  * one.
670  */
671  "label_settings",
672  "addon_uninstall_list",
673  "addon_manager",
674  "loading_screen",
675  "network_transmission",
676  "synched_choice_wait",
677  "drop_down_menu",
678  "preferences_dialog",
679  "unit_recruit",
680  "unit_recall",
681  "unit_list",
682  "unit_advance",
683  "mp_host_game_prompt",
684  "mp_create_game",
685  // The title screen appears to be throwing a bad_alloc on Travis, so disable it for now
686  "title_screen",
687  "end_credits",
688  "mp_staging",
689  "mp_join_game",
690  "terrain_layers",
691  "attack_predictions",
692  "help_browser",
693  "story_viewer",
694  "outro",
695  "mp_change_control", // Basically useless without a game_board object, so disabling
696  "game_stats", // segfault with LTO
697  "gamestate_inspector", // segfault with LTO
698  "server_info",
699  "sp_options_configure",// segfault with LTO
700  "campaign_selection",// segfault with LTO
701  "game_load",// segfault after disabling the above tests
702  "file_progress",
703  };
705 
706  for(const std::string& item : widgets_tested)
707  {
708  widget_list.erase(item);
709  PLAIN_LOG << "Checking widget " << item;
710  BOOST_CHECK_EQUAL(omitted.count(item), 0);
711  }
712  for(const std::string& item : omitted)
713  {
714  widget_list.erase(item);
715  }
716 
717  // Test size() instead of empty() to get the number of offenders
718  BOOST_CHECK_EQUAL(widget_list.size(), 0);
719  for(const std::string& id : widget_list) {
720  PLAIN_LOG << "Window '" << id << "' registered but not tested.";
721  }
722 }
723 
724 BOOST_AUTO_TEST_CASE(test_make_test_fake)
725 {
727 
728  try {
729  message dlg("title", "message", true, false, false);
730  dlg.show(1);
731  } catch(const wml_exception& e) {
732  BOOST_CHECK(e.user_message == _("Failed to show a dialog, which doesn't fit on the screen."));
733  return;
734  } catch(...) {
735  BOOST_ERROR("Didn't catch the wanted exception, instead caught " << utils::get_unknown_exception_type() << ".");
736  }
737  BOOST_ERROR("Didn't catch the wanted exception, instead caught nothing.");
738 }
739 
740 BOOST_AUTO_TEST_SUITE_END()
741 
742 namespace {
743 
744 template<>
745 struct dialog_tester<addon_auth>
746 {
747  config cfg;
748  addon_auth* create()
749  {
750  return new addon_auth(cfg);
751  }
752 };
753 
754 template<>
755 struct dialog_tester<addon_connect>
756 {
757  std::string host_name = "host_name";
758  addon_connect* create()
759  {
760  return new addon_connect(host_name, true);
761  }
762 };
763 
764 template<>
765 struct dialog_tester<addon_license_prompt>
766 {
767  std::string license_terms = R"(Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis ante nibh, dignissim ullamcorper tristique eget, condimentum sit amet enim. Aenean dictum pulvinar lacinia. Etiam eleifend, leo sed efficitur consectetur, augue nulla ornare lectus, vitae molestie lacus risus vitae libero. Quisque odio nunc, porttitor eget fermentum sit amet, faucibus eu risus. Praesent sit amet lacus tortor. Suspendisse volutpat quam vitae ipsum fermentum, in vulputate metus egestas. Nulla id consequat ex. Nulla ac dignissim nisl, nec euismod lectus. Duis vitae dolor ornare, convallis justo in, porta dui.
768 
769 Sed faucibus nibh sit amet ligula porta, non malesuada nibh tristique. Maecenas aliquam diam non eros convallis mattis. Proin rhoncus condimentum leo, sed condimentum magna. Phasellus cursus condimentum lacus, sed sodales lacus. Sed pharetra dictum metus, eget dictum nibh lobortis imperdiet. Nunc tempus sollicitudin bibendum. In porttitor interdum orci. Curabitur vitae nibh vestibulum, condimentum lectus quis, condimentum dui. In quis cursus nisl. Maecenas semper neque eu ipsum aliquam, id porta ligula lacinia. Integer sed blandit ex, eu accumsan magna.)";
770  addon_license_prompt* create()
771  {
772  return new addon_license_prompt(license_terms);
773  }
774 };
775 
776 template<>
777 struct dialog_tester<addon_manager>
778 {
779  dialog_tester()
780  {
782  }
783  addon_manager* create()
784  {
785  addons_client client("localhost:15999");
786  return new addon_manager(client);
787  }
788 };
789 
790 template<>
791 struct dialog_tester<campaign_difficulty>
792 {
793  campaign_difficulty* create()
794  {
795  const config items("difficulty");
796 
797  return new campaign_difficulty(items);
798  }
799 };
800 
801 template<>
802 struct dialog_tester<campaign_selection>
803 {
804  saved_game state;
806  dialog_tester() : state(config {"campaign_type", "scenario"}), ng(state)
807  {
808  }
809  campaign_selection* create()
810  {
811  return new campaign_selection(ng);
812  }
813 };
814 
815 template<>
816 struct dialog_tester<chat_log>
817 {
818  config cfg;
819  vconfig vcfg;
820  replay_recorder_base rbase;
821  replay r;
822  dialog_tester() : vcfg(cfg), r(rbase) {}
823  chat_log* create()
824  {
825  return new chat_log(vcfg, r);
826  }
827 };
828 
829 template<>
830 struct dialog_tester<editor_choose_addon>
831 {
832  std::string temp;
833  editor_choose_addon* create()
834  {
835  return new editor_choose_addon(temp);
836  }
837 };
838 
839 template<>
840 struct dialog_tester<prompt>
841 {
842  std::string temp;
843  prompt* create()
844  {
845  return new prompt(temp);
846  }
847 };
848 
849 template<>
850 struct dialog_tester<core_selection>
851 {
852  std::vector<config> cores;
853  dialog_tester()
854  {
855  cores.resize(1);
856  }
857  core_selection* create()
858  {
859  return new core_selection(cores, 0);
860  }
861 };
862 
863 template<>
864 struct dialog_tester<custom_tod>
865 {
866  std::vector<time_of_day> times;
867  int current_tod = 0;
868  dialog_tester()
869  {
870  times.resize(1);
871  }
872  custom_tod* create()
873  {
874  return new custom_tod(times, current_tod);
875  }
876 };
877 
878 template<>
879 struct dialog_tester<edit_label>
880 {
881  std::string label = "Label text to modify";
882  bool team_only = false;
883  edit_label* create()
884  {
885  return new edit_label(label, team_only);
886  }
887 };
888 
889 template<>
890 struct dialog_tester<edit_text>
891 {
892  std::string text = "text to modify";
893  edit_text* create()
894  {
895  return new edit_text("title", "label", text);
896  }
897 };
898 
899 template<>
900 struct dialog_tester<editor_edit_label>
901 {
902  std::string label = "Label text to modify";
903  std::string category = "test";
904  bool immutable = false, fog = false, shroud = false;
905  color_t color;
906  editor_edit_label* create()
907  {
908  return new editor_edit_label(label, immutable, fog, shroud, color, category);
909  }
910 };
911 
912 template<>
913 struct dialog_tester<editor_edit_pbl>
914 {
915  std::string temp;
916  std::string temp1;
917  editor_edit_pbl* create()
918  {
919  return new editor_edit_pbl(temp, temp1);
920  }
921 };
922 
923 template<>
924 struct dialog_tester<editor_edit_pbl_translation>
925 {
926  std::string temp1;
927  std::string temp2;
928  std::string temp3;
930  {
931  return new editor_edit_pbl_translation(temp1, temp2, temp3);
932  }
933 };
934 
935 template<>
936 struct dialog_tester<editor_edit_scenario>
937 {
938  std::string id, name, descr;
939  int turns = 0, xp_mod = 50;
940  bool defeat_enemies = false, random_start = false;
941  editor_edit_scenario* create()
942  {
943  return new editor_edit_scenario(id, name, descr, turns, xp_mod, defeat_enemies, random_start);
944  }
945 };
946 
947 template<>
948 struct dialog_tester<editor_edit_side>
949 {
950  team t;
952  dialog_tester() : info(t) {}
953  editor_edit_side* create()
954  {
955  return new editor_edit_side(info);
956  }
957 };
958 
959 template<>
960 struct dialog_tester<formula_debugger>
961 {
962  wfl::formula_debugger debugger;
963  formula_debugger* create()
964  {
965  return new formula_debugger(debugger);
966  }
967 };
968 
969 template<>
970 struct dialog_tester<game_load>
971 {
972  config cfg;
973  game_config_view view;
974  // It would be good to have a test directory instead of using the same directory as the player,
975  // however this code will support that - default_saves_dir() will respect --userdata-dir.
977  dialog_tester()
978  {
979  /** @todo Would be nice to add real data to the config. */
980  }
981  game_load* create()
982  {
983  view = game_config_view::wrap(cfg);
984  return new game_load(view, data);
985  }
986 
987 };
988 
989 template<>
990 struct dialog_tester<game_save>
991 {
992  std::string title = "Title";
993  std::string filename = "filename";
994  game_save* create()
995  {
996  return new game_save(title, filename);
997  }
998 
999 };
1000 
1001 template<>
1002 struct dialog_tester<game_save_message>
1003 {
1004  std::string title = "Title";
1005  std::string filename = "filename";
1006  std::string message = "message";
1007  game_save_message* create()
1008  {
1009  return new game_save_message(title, filename, message);
1010  }
1011 
1012 };
1013 
1014 template<>
1015 struct dialog_tester<game_save_oos>
1016 {
1017  bool ignore_all = false;
1018  std::string title = "Title";
1019  std::string filename = "filename";
1020  std::string message = "message";
1021  game_save_oos* create()
1022  {
1023  return new game_save_oos(ignore_all, title, filename, message);
1024  }
1025 
1026 };
1027 
1028 template<>
1029 struct dialog_tester<install_dependencies>
1030 {
1031  addons_list addons;
1032  install_dependencies* create()
1033  {
1034  return new install_dependencies(addons);
1035  }
1036 };
1037 
1038 template<>
1039 struct dialog_tester<hotkey_bind>
1040 {
1041  std::string id = "";
1042 
1043  hotkey_bind* create()
1044  {
1045  return new hotkey_bind(id);
1046  }
1047 };
1048 
1049 template<>
1050 struct dialog_tester<mp_lobby>
1051 {
1053  wesnothd_connection connection;
1054  mp::lobby_info li;
1055  int selected_game;
1056  dialog_tester() : connection("", ""), li()
1057  {
1058  }
1059  mp_lobby* create()
1060  {
1061  return new mp_lobby(li, connection, selected_game);
1062  }
1063 };
1064 
1065 template<>
1066 struct dialog_tester<mp_match_history>
1067 {
1068  wesnothd_connection connection;
1069  dialog_tester() : connection("", "")
1070  {
1071  }
1072  mp_match_history* create()
1073  {
1074  return new mp_match_history("", connection, false);
1075  }
1076 };
1077 
1078 class fake_chat_handler : public events::chat_handler {
1079  void add_chat_message(const std::time_t&,
1080  const std::string&, int, const std::string&,
1081  MESSAGE_TYPE) {}
1082  void send_chat_message(const std::string&, bool) {}
1083  void send_to_server(const config&) {}
1084  void clear_messages() {}
1085 };
1086 
1087 template<>
1088 struct dialog_tester<lobby_player_info>
1089 {
1090  config c;
1091  fake_chat_handler ch;
1092  wesnothd_connection connection;
1093  mp::user_info ui;
1094  mp::lobby_info li;
1095  dialog_tester()
1096  : connection("", "")
1097  , ui(c), li()
1098  {
1099  }
1100  lobby_player_info* create()
1101  {
1102  return new lobby_player_info(ch, ui, li);
1103  }
1104 };
1105 
1106 template<>
1107 struct dialog_tester<log_settings>
1108 {
1109  log_settings* create()
1110  {
1111  return new log_settings();
1112  }
1113 };
1114 
1115 template<>
1116 struct dialog_tester<message>
1117 {
1118  message* create()
1119  {
1120  return new message("Title", "Message", false, false, false);
1121  }
1122 };
1123 
1124 template<>
1125 struct dialog_tester<mp_create_game>
1126 {
1127  saved_game state;
1128  dialog_tester() : state(config {"campaign_type", "multiplayer"})
1129  {
1130  }
1131  mp_create_game* create()
1132  {
1133  return new mp_create_game(state, true);
1134  }
1135 };
1136 
1137 template<>
1138 struct dialog_tester<mp_join_game_password_prompt>
1139 {
1140  std::string password;
1142  {
1144  }
1145 };
1146 
1147 template<>
1148 struct dialog_tester<mp_report>
1149 {
1150  std::string report_text;
1151  mp_report* create()
1152  {
1153  return new mp_report(report_text);
1154  }
1155 };
1156 
1157 static std::vector<std::string> depcheck_mods {"mod_one", "some other", "more"};
1158 
1159 template<>
1160 struct dialog_tester<depcheck_confirm_change>
1161 {
1162  depcheck_confirm_change* create()
1163  {
1164  return new depcheck_confirm_change(true, depcheck_mods, "requester");
1165  }
1166 };
1167 
1168 template<>
1169 struct dialog_tester<depcheck_select_new>
1170 {
1171  depcheck_select_new* create()
1172  {
1173  return new depcheck_select_new(ng::depcheck::MODIFICATION, depcheck_mods);
1174  }
1175 };
1176 
1177 template<>
1178 struct dialog_tester<mp_login>
1179 {
1180  mp_login* create()
1181  {
1182  return new mp_login("wesnoth.org", "label", true);
1183  }
1184 };
1185 
1186 template<>
1187 struct dialog_tester<simple_item_selector>
1188 {
1189  simple_item_selector* create()
1190  {
1191  return new simple_item_selector("title", "message", std::vector<std::string>(), false, false);
1192  }
1193 };
1194 
1195 template<>
1196 struct dialog_tester<screenshot_notification>
1197 {
1198  screenshot_notification* create()
1199  {
1200  return new screenshot_notification("path", nullptr);
1201  }
1202 };
1203 
1204 template<>
1205 struct dialog_tester<theme_list>
1206 {
1207  static theme_info make_theme(const std::string& name)
1208  {
1209  theme_info ti;
1210  ti.id = name;
1211  ti.name = name;
1212  ti.description = name + " this is a description";
1213  return ti;
1214  }
1215  static std::vector<theme_info> themes;
1216  theme_list* create()
1217  {
1218  return new theme_list(themes, 0);
1219  }
1220 };
1221 std::vector<theme_info> dialog_tester<theme_list>::themes {make_theme("classic"), make_theme("new"), make_theme("more"), make_theme("themes")};
1222 
1223 template<>
1224 struct dialog_tester<editor_generate_map>
1225 {
1226  std::vector<std::unique_ptr<map_generator>> map_generators;
1227  editor_generate_map* create()
1228  {
1229  for(const config &i : test_gui2_fixture::main_config.child_range("multiplayer")) {
1230  if(i["scenario_generation"] == "default") {
1231  auto generator_cfg = i.optional_child("generator");
1232  if (generator_cfg) {
1233  map_generators.emplace_back(create_map_generator("", *generator_cfg));
1234  }
1235  }
1236  }
1237 
1238  editor_generate_map* result = new editor_generate_map(map_generators);
1239  BOOST_REQUIRE_MESSAGE(result, "Failed to create a dialog.");
1240 
1241  return result;
1242  }
1243 };
1244 
1245 template<>
1246 struct dialog_tester<editor_new_map>
1247 {
1248  int width = 10;
1249  int height = 10;
1250  editor_new_map* create()
1251  {
1252  return new editor_new_map("Test", width, height);
1253  }
1254 };
1255 
1256 template<>
1257 struct dialog_tester<editor_resize_map>
1258 {
1259  int width = 0;
1260  int height = 0;
1262  bool copy = false;
1263  editor_resize_map* create()
1264  {
1265  return new editor_resize_map(width, height, expand_direction, copy);
1266  }
1267 };
1268 
1269 template<>
1270 struct dialog_tester<file_dialog>
1271 {
1272  file_dialog* create()
1273  {
1274  return new file_dialog();
1275  }
1276 };
1277 
1278 template<>
1279 struct dialog_tester<folder_create>
1280 {
1281  std::string folder_name;
1282  folder_create* create()
1283  {
1284  return new folder_create(folder_name);
1285  }
1286 };
1287 
1288 template<>
1289 struct dialog_tester<transient_message>
1290 {
1291  transient_message* create()
1292  {
1293  return new transient_message("Title", false, "Message", false, "");
1294  }
1295 };
1296 
1297 template<>
1298 struct dialog_tester<title_screen>
1299 {
1300  std::vector<std::string> args;
1301  commandline_options opts;
1303  dialog_tester() : opts(args), game(opts) {}
1304  title_screen* create()
1305  {
1306  return new title_screen(game);
1307  }
1308 };
1309 
1310 template<>
1311 struct dialog_tester<wml_error>
1312 {
1313  static std::vector<std::string> files;
1314  wml_error* create()
1315  {
1316  return new wml_error("Summary", "Post summary", files, "Details");
1317  }
1318 };
1319 std::vector<std::string> dialog_tester<wml_error>::files {"some", "files", "here"};
1320 
1321 template<>
1322 struct dialog_tester<wml_message_left>
1323 {
1324  wml_message_left* create()
1325  {
1326  return new wml_message_left("Title", "Message", "", false);
1327  }
1328 };
1329 
1330 template<>
1331 struct dialog_tester<wml_message_right>
1332 {
1333  wml_message_right* create()
1334  {
1335  return new wml_message_right("Title", "Message", "", false);
1336  }
1337 };
1338 
1339 template<>
1340 struct dialog_tester<wml_message_double>
1341 {
1342  wml_message_double* create()
1343  {
1344  return new wml_message_double("Title", "Message", "", false, "", true);
1345  }
1346 };
1347 
1348 template<>
1349 struct dialog_tester<faction_select>
1350 {
1351  config era_cfg, side_cfg;
1352  std::vector<const config*> eras;
1353  ng::flg_manager flg;
1354  std::string color;
1355  dialog_tester()
1356  : era_cfg(), side_cfg(), eras(1, &era_cfg) // TODO: Add an actual era definition
1357  , flg(eras, side_cfg, false, false, false)
1358  , color("teal")
1359  {}
1360  faction_select* create() {
1361  return new faction_select(flg, color, 1);
1362  }
1363 };
1364 
1365 template<>
1366 struct dialog_tester<generator_settings>
1367 {
1368  config cfg;
1370  dialog_tester() : data(cfg) {}
1371  generator_settings* create()
1372  {
1373  return new generator_settings(data);
1374  }
1375 };
1376 
1377 template<>
1378 struct dialog_tester<sp_options_configure>
1379 {
1380  saved_game state;
1381  ng::create_engine create_eng;
1382  ng::configure_engine config_eng;
1383  dialog_tester() : create_eng(state)
1384  , config_eng(create_eng.get_state()) {}
1385  sp_options_configure* create()
1386  {
1387  return new sp_options_configure(create_eng, config_eng);
1388  }
1389 };
1390 
1391 template<>
1392 struct dialog_tester<statistics_dialog>
1393 {
1394  team t;
1396  statistics_t stats;
1397  dialog_tester() : t() , stats_record(), stats(stats_record) {}
1398  statistics_dialog* create()
1399  {
1400  return new statistics_dialog(stats, t);
1401  }
1402 };
1403 
1404 template<>
1405 struct dialog_tester<surrender_quit>
1406 {
1407  dialog_tester() {}
1408  surrender_quit* create()
1409  {
1410  return new surrender_quit();
1411  }
1412 };
1413 
1414 template<>
1415 struct dialog_tester<tod_new_schedule>
1416 {
1417  std::string id = "id";
1418  std::string name = "name";
1419  dialog_tester() {}
1420  tod_new_schedule* create()
1421  {
1422  return new tod_new_schedule(id, name);
1423  }
1424 };
1425 
1426 template<>
1427 struct dialog_tester<editor_edit_unit>
1428 {
1429  config cfg;
1430  game_config_view view;
1431 
1432  dialog_tester() {}
1433  editor_edit_unit* create()
1434  {
1435  config& units = cfg.add_child("units");
1436  cfg.add_child("race");
1437  config& movetype = units.add_child("movetype");
1438  movetype["name"] = "Test Movetype";
1439  movetype.add_child("defense");
1440  movetype.add_child("resistance");
1441  movetype.add_child("movement_costs");
1442  view = game_config_view::wrap(cfg);
1443  return new editor_edit_unit(view, "test_addon");
1444  }
1445 };
1446 
1447 } // namespace
double t
Definition: astarsearch.cpp:63
Add-ons (campaignd) client class.
Definition: client.hpp:41
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
config & add_child(config_key_type key)
Definition: config.cpp:441
Singleton class to manage game config file caching.
void add_define(const std::string &define)
Add a entry to preproc defines map.
static config_cache & instance()
Get reference to the singleton object.
void clear_defines()
Clear stored defines map to default values.
void get_config(const std::string &path, config &cfg, abstract_validator *validator=nullptr)
Gets a config object from given path.
A class grating read only view to a vector of config objects, viewed as one config with all children ...
static game_config_view wrap(const config &cfg)
This shows the dialog to provide a password when uploading an add-on.
Definition: addon_auth.hpp:32
This shows the dialog for managing addons and connecting to the addon server.
Definition: connect.hpp:34
Shows the list of addons on the server available for installation.
Definition: manager.hpp:50
The campaign mode difficulty menu.
This shows the dialog which allows the user to choose which campaign to play.
This shows the dialog which allows the user to choose which core to play.
This shows the dialog to modify tod schedules.
Definition: custom_tod.hpp:49
Asks the user to confirm a change required to proceed.
Offers a list of compatible items if a currently selected one is incompatible.
Dialog for editing gamemap labels.
Definition: edit_label.hpp:34
Dialog for renaming units in-game.
Definition: edit_text.hpp:32
Dialog for adding a translation while editing an add-on's _server.pbl.
Dialog for editing gamemap labels.
Definition: edit_label.hpp:34
Dialog for adding a translation while editing an add-on's _server.pbl.
Dialog for editing an add-on's _server.pbl.
Definition: edit_pbl.hpp:46
Dialog for editing gamemap scenarios.
Dialog for editing gamemap sides.
Definition: edit_side.hpp:40
Dialog that allows user to create custom unit types.
Definition: edit_unit.hpp:40
The dialog for selecting which random generator to use in the editor.
This shows the dialog to resize the current map.
Definition: resize_map.hpp:50
Dialog for providing the name of a new folder to create.
This shows the debugger for the formulas.
This shows the dialog to select and load a savegame file.
Definition: game_load.hpp:48
This shows the dialog to create a savegame file.
Definition: game_save.hpp:33
Main class to show messages to the user.
Definition: message.hpp:36
Abstract base class for all modal dialogs.
virtual const std::string & window_id() const =0
The ID of the window to build.
bool show(const unsigned auto_close_time=0)
Shows the window.
The popup class shows windows that are shown non-modal.
virtual const std::string & window_id() const
The ID of the window to build.
Dialog for entering a password for joining a password-protected MP game.
This shows the dialog to log in to the MP server.
Definition: mp_login.hpp:41
This shows a dialog to report players on the multiplayer server.
Definition: mp_report.hpp:35
Dialog for getting a single text value from the player.
Definition: prompt.hpp:34
Notification dialog used after saving a game or map screenshot to display information about it for th...
A simple one-column listbox with OK and Cancel buttons.
This shows the dialog to confirm surrender and/or quitting the game.
Dialog for selecting a GUI theme.
Definition: theme_list.hpp:36
This class implements the title screen.
Dialog that takes new schedule ID and name from the player.
Shows a transient message.
WML preprocessor/parser error report dialog.
Definition: wml_error.hpp:36
Shows a dialog with two portraits, one on each side.
Shows a dialog with the portrait on the left side.
Shows a dialog with the portrait on the right side.
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:63
void draw()
Draws the window.
Definition: window.cpp:606
The basic "size" of the unit - flying, small land, large land, etc.
Definition: movetype.hpp:45
This class represents the collective information the client has about the players and games on the se...
Definition: lobby_info.hpp:31
FLG stands for faction, leader and gender.
Definition: flg_manager.hpp:30
static std::shared_ptr< save_index_class > default_saves_dir()
Returns an instance for managing saves in filesystem::get_saves_dir()
Definition: save_index.cpp:208
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:74
A variable-expanding proxy for the config class.
Definition: variable.hpp:45
A class that represents a TCP/IP connection to the wesnothd server.
Networked add-ons (campaignd) client interface.
Formula AI debugger.
Declarations for File-IO.
std::size_t i
Definition: function.cpp:968
static std::string _(const char *str)
Definition: gettext.hpp:93
std::string label
What to show in the filter's drop-down list.
Definition: manager.cpp:209
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:207
This file contains the window object, this object is a top level container which has the event manage...
std::map< std::string, addon_info > addons_list
Definition: info.hpp:27
bool load_language_list()
Definition: language.cpp:103
Defines the exception classes for the layout algorithm.
#define PLAIN_LOG
Definition: log.hpp:295
map_generator * create_map_generator(const std::string &name, const config &cfg, const config *vars)
Definition: map_create.cpp:28
Various uncategorised dialogs.
void point(int x, int y)
Draw a single point.
Definition: draw.cpp:202
bool delete_file(const std::string &filename)
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
void write_file(const std::string &fname, const std::string &data, std::ios_base::openmode mode)
Throws io_exception if an error occurs.
Game configuration data as global variables.
Definition: build_info.cpp:60
std::string path
Definition: filesystem.cpp:83
void load_config(const config &v)
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
Definition: tooltip.cpp:79
void remove()
Removes a tip.
Definition: tooltip.cpp:109
std::string get_modal_dialog_id(const modal_dialog &dialog)
Definition: test_gui2.cpp:177
std::string get_modeless_dialog_id(const modeless_dialog &dialog)
Definition: test_gui2.cpp:182
Generic file dialog.
std::set< std::string > & registered_window_types()
Returns the list of registered windows.
bool new_widgets
Do we wish to use the new library or not.
Definition: settings.cpp:23
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:412
logger & info()
Definition: log.cpp:314
const std::vector< std::string > items
void send_to_server(const config &data)
Attempts to send given data to server if a connection is open.
bool fog()
Definition: game.cpp:522
bool shroud()
Definition: game.cpp:532
std::string password(const std::string &server, const std::string &login)
point resolution()
Definition: general.cpp:392
int turns()
Definition: game.cpp:542
game_display & get_fake_display(const int width, const int height)
Gets a fake test display.
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
Definition: general.cpp:23
std::vector< std::string > split(const config_attribute_value &val)
std::string_view data
Definition: picture.cpp:194
Replay control code.
This file contains the settings handling of the widget library.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
The paths manager is responsible for recording the various paths that binary files may be located at.
Definition: filesystem.hpp:398
Exception thrown when the height resizing has failed.
Exception thrown when the width has been modified during resizing.
Exception thrown when the width resizing has failed.
This class represents the information a client has about another player.
Definition: lobby_data.hpp:30
static config main_config
Definition: test_gui2.cpp:165
std::unique_ptr< game_config_manager > config_manager
Definition: test_gui2.cpp:167
std::vector< std::string > dummy_args
Definition: test_gui2.cpp:168
static const std::string widgets_file
Definition: test_gui2.cpp:166
t_string name
Definition: theme.hpp:38
t_string description
Definition: theme.hpp:39
std::string id
Definition: theme.hpp:37
Helper class, don't construct this directly.
mock_char c
BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_auth)
Definition: test_gui2.cpp:394
BOOST_FIXTURE_TEST_SUITE(test_map_location, MLFixture)
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define e