The Battle for Wesnoth  1.19.18+dev
test_gui2.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
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"
46 #include "gui/dialogs/chat_log.hpp"
85 #include "gui/dialogs/message.hpp"
101 #include "gui/dialogs/outro.hpp"
102 #include "gui/dialogs/prompt.hpp"
114 #include "gui/dialogs/tooltip.hpp"
119 #include "gui/dialogs/wml_error.hpp"
121 #include "gui/widgets/settings.hpp"
122 #include "gui/widgets/window.hpp"
123 #include "language.hpp"
124 #include "map/map.hpp"
125 #include "replay.hpp"
126 #include "save_index.hpp"
127 #include "saved_game.hpp"
129 #include "terrain/type_data.hpp"
131 #include "utils/general.hpp"
132 #include "wesnothd_connection.hpp"
133 #include "wml_exception.hpp"
134 
135 #include <boost/test/unit_test.hpp>
136 
137 #include <functional>
138 #include <memory>
139 
140 using namespace gui2::dialogs;
141 
144  : config_manager()
145  , dummy_args({"wesnoth", "--noaddons"})
146  {
147  config_manager.reset(new game_config_manager(dummy_args));
149 
150  cache.clear_defines();
151  cache.add_define("EDITOR");
152  cache.add_define("MULTIPLAYER");
153 
154  /** The main config, which contains the entire WML tree. */
155  main_config = cache.get_config(game_config::path +"/data");
156  game_config_view game_config_view_ = game_config_view::wrap(main_config);
157 
158  const filesystem::binary_paths_manager bin_paths_manager(game_config_view_);
159 
161  game_config::load_config(main_config.mandatory_child("game_config"));
162  }
164  {
165  }
167  static const std::string widgets_file;
168  std::unique_ptr<game_config_manager> config_manager;
169  std::vector<std::string> dummy_args;
170 };
172 const std::string test_gui2_fixture::widgets_file = "widgets_tested.log";
173 
174 namespace gui2 {
175 
176 namespace dialogs {
177 
178 std::string get_modal_dialog_id(const modal_dialog& dialog)
179 {
180  return dialog.window_id();
181 }
182 
183 std::string get_modeless_dialog_id(const modeless_dialog& dialog)
184 {
185  return dialog.window_id();
186 }
187 
188 } // namespace dialogs
189 } // namespace gui2
190 
191 namespace {
192 
193  /**
194  * Helper class to generate a dialog.
195  *
196  * This class makes sure the dialog is properly created and initialized.
197  * The specialized versions are at the end of this file.
198  */
199  template<class T>
200  struct dialog_tester
201  {
202  T* create() { return new T(); }
203  };
204 
205  typedef std::pair<unsigned, unsigned> resolution;
206  typedef std::vector<std::pair<unsigned, unsigned>> resolution_list;
207 
208  template<class T>
209  void test_resolutions(const resolution_list& resolutions)
210  {
211  for(const resolution& resolution : resolutions) {
212  test_utils::set_test_resolution(resolution.first, resolution.second);
213 
214  dialog_tester<T> ctor;
215  const std::unique_ptr<modal_dialog> dlg(ctor.create());
216  BOOST_REQUIRE_MESSAGE(dlg.get(), "Failed to create a dialog.");
217 
218  std::string id = get_modal_dialog_id(*dlg.get());
219  filesystem::write_file(test_gui2_fixture::widgets_file, ","+id, std::ios_base::app);
220 
221  std::string exception;
222  try {
223  dlg->show(1);
224  } catch(const gui2::layout_exception_width_modified&) {
225  exception = "gui2::layout_exception_width_modified";
227  exception = "gui2::layout_exception_width_resize_failed";
229  exception = "gui2::layout_exception_height_resize_failed";
230  } catch(const wml_exception& e) {
231  exception = e.dev_message;
232  } catch(const std::exception& e) {
233  exception = e.what();
234  } catch(...) {
235  exception = utils::get_unknown_exception_type();
236  }
237  BOOST_CHECK_MESSAGE(exception.empty(),
238  "Test for '" << id
239  << "' Failed\nnew widgets = " << gui2::new_widgets
240  << " resolution = " << resolution.first
241  << 'x' << resolution.second
242  << "\nException caught: " << exception << '.');
243  }
244  }
245 
246  template<class T>
247  void test_popup_resolutions(const resolution_list& resolutions)
248  {
249  bool interact = false;
250  for(int i = 0; i < 2; ++i) {
251  for(const resolution& resolution : resolutions) {
252  test_utils::set_test_resolution(resolution.first, resolution.second);
253 
254  dialog_tester<T> ctor;
255  const std::unique_ptr<modeless_dialog> dlg(ctor.create());
256  BOOST_REQUIRE_MESSAGE(dlg.get(), "Failed to create a dialog.");
257 
258  std::string id = get_modeless_dialog_id(*dlg.get());
259  filesystem::write_file(test_gui2_fixture::widgets_file, ","+id, std::ios_base::app);
260 
261  std::string exception;
262  try {
263  dlg->show(interact);
264  gui2::window* window = dlg.get();
265  BOOST_REQUIRE_NE(window, static_cast<void*>(nullptr));
266  window->draw();
267  } catch(const gui2::layout_exception_width_modified&) {
268  exception = "gui2::layout_exception_width_modified";
270  exception = "gui2::layout_exception_width_resize_failed";
272  exception = "gui2::layout_exception_height_resize_failed";
273  } catch(const wml_exception& e) {
274  exception = e.dev_message;
275  } catch(const std::exception& e) {
276  exception = e.what();
277  } catch(...) {
278  exception = utils::get_unknown_exception_type();
279  }
280  BOOST_CHECK_MESSAGE(exception.empty(),
281  "Test for '" << id
282  << "' Failed\nnew widgets = " << gui2::new_widgets
283  << " resolution = " << resolution.first
284  << 'x' << resolution.second
285  << "\nException caught: " << exception << '.');
286  }
287 
288  interact = true;
289  }
290  }
291 
292 #ifdef _MSC_VER
293 #pragma warning(push)
294 #pragma warning(disable: 4702)
295 #endif
296  void test_tip_resolutions(const resolution_list& resolutions
297  , const std::string& id)
298  {
299  for(const auto& resolution : resolutions) {
300  test_utils::set_test_resolution(resolution.first, resolution.second);
301 
302  filesystem::write_file(test_gui2_fixture::widgets_file, ","+id, std::ios_base::app);
303 
304  std::string exception;
305  try {
306  tip::show(id
307  , "Test message for a tooltip."
308  , point(0, 0)
309  , {0,0,0,0});
310  tip::remove();
311  } catch(const gui2::layout_exception_width_modified&) {
312  exception = "gui2::layout_exception_width_modified";
314  exception = "gui2::layout_exception_width_resize_failed";
316  exception = "gui2::layout_exception_height_resize_failed";
317  } catch(const wml_exception& e) {
318  exception = e.dev_message;
319  } catch(const std::exception& e) {
320  exception = e.what();
321  } catch(...) {
322  exception = utils::get_unknown_exception_type();
323  }
324  BOOST_CHECK_MESSAGE(exception.empty(),
325  "Test for tip '" << id
326  << "' Failed\nnew widgets = " << gui2::new_widgets
327  << " resolution = " << resolution.first
328  << 'x' << resolution.second
329  << "\nException caught: " << exception << '.');
330  }
331  }
332 #ifdef _MSC_VER
333 #pragma warning(pop)
334 #endif
335 
336 const resolution_list& get_gui_resolutions()
337 {
338  static resolution_list result {
339  {1024, 768},
340  {1280, 1024},
341  {1680, 1050},
342  };
343 
344  return result;
345 }
346 
347 template<class T>
348 void test()
349 {
350  gui2::new_widgets = false;
351 
352 // for(std::size_t i = 0; i < 2; ++i) {
353 
354  test_resolutions<T>(get_gui_resolutions());
355 
356 // break; // FIXME: New widgets break
357 // gui2::new_widgets = true;
358 // }
359 }
360 
361 template<class T>
362 void test_popup()
363 {
364  gui2::new_widgets = false;
365 
366  for(std::size_t i = 0; i < 2; ++i) {
367 
368  test_popup_resolutions<T>(get_gui_resolutions());
369 
370  gui2::new_widgets = true;
371  }
372 }
373 
374 void test_tip(const std::string& id)
375 {
376  gui2::new_widgets = false;
377 
378  for(std::size_t i = 0; i < 2; ++i) {
379 
380  test_tip_resolutions(get_gui_resolutions(), id);
381 
382  gui2::new_widgets = true;
383  }
384 }
385 
386 } // namespace
387 
389 
390 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_auth)
391 {
392  test<addon_auth>();
393 }
394 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_connect)
395 {
396  test<addon_connect>();
397 }
398 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_license_prompt)
399 {
400  test<addon_license_prompt>();
401 }
402 BOOST_AUTO_TEST_CASE(modal_dialog_test_campaign_difficulty)
403 {
404  test<campaign_difficulty>();
405 }
406 BOOST_AUTO_TEST_CASE(modal_dialog_test_chat_log)
407 {
408  test<chat_log>();
409 }
410 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_choose_addon)
411 {
412  test<editor_choose_addon>();
413 }
414 BOOST_AUTO_TEST_CASE(modal_dialog_test_prompt)
415 {
416  test<prompt>();
417 }
418 BOOST_AUTO_TEST_CASE(modal_dialog_test_core_selection)
419 {
420  test<core_selection>();
421 }
422 BOOST_AUTO_TEST_CASE(modal_dialog_test_depcheck_confirm_change)
423 {
424  test<depcheck_confirm_change>();
425 }
426 BOOST_AUTO_TEST_CASE(modal_dialog_test_depcheck_select_new)
427 {
428  test<depcheck_select_new>();
429 }
430 BOOST_AUTO_TEST_CASE(modal_dialog_test_edit_label)
431 {
432  test<edit_label>();
433 }
434 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_pbl)
435 {
436  test<editor_edit_pbl>();
437 }
438 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_pbl_translation)
439 {
440  test<editor_edit_pbl_translation>();
441 }
442 BOOST_AUTO_TEST_CASE(modal_dialog_test_edit_text)
443 {
444  test<edit_text>();
445 }
446 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_label)
447 {
448  test<editor_edit_label>();
449 }
450 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_side)
451 {
452  test<editor_edit_side>();
453 }
454 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_scenario)
455 {
456  test<editor_edit_scenario>();
457 }
458 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_generate_map)
459 {
460  test<editor_generate_map>();
461 }
462 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_new_map)
463 {
464  test<editor_new_map>();
465 }
466 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_resize_map)
467 {
468  test<editor_resize_map>();
469 }
470 BOOST_AUTO_TEST_CASE(modal_dialog_test_faction_select)
471 {
472  test<faction_select>();
473 }
474 BOOST_AUTO_TEST_CASE(modal_dialog_test_file_dialog)
475 {
476  test<file_dialog>();
477 }
478 BOOST_AUTO_TEST_CASE(modal_dialog_test_folder_create)
479 {
480  test<folder_create>();
481 }
482 BOOST_AUTO_TEST_CASE(modal_dialog_test_formula_debugger)
483 {
484  test<formula_debugger>();
485 }
486 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_cache_options)
487 {
488  test<game_cache_options>();
489 }
490 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_delete)
491 {
492  test<game_delete>();
493 }
494 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_version)
495 {
496  test<game_version>();
497 }
498 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_save)
499 {
500  test<game_save>();
501 }
502 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_save_message)
503 {
504  test<game_save_message>();
505 }
506 BOOST_AUTO_TEST_CASE(modal_dialog_test_game_save_oos)
507 {
508  test<game_save_oos>();
509 }
510 BOOST_AUTO_TEST_CASE(modal_dialog_test_generator_settings)
511 {
512  test<generator_settings>();
513 }
514 BOOST_AUTO_TEST_CASE(modal_dialog_test_gui_test_dialog)
515 {
516  test<gui_test_dialog>();
517 }
518 BOOST_AUTO_TEST_CASE(modal_dialog_test_hotkey_bind)
519 {
520  test<hotkey_bind>();
521 }
522 BOOST_AUTO_TEST_CASE(modal_dialog_test_install_dependencies)
523 {
524  test<install_dependencies>();
525 }
526 BOOST_AUTO_TEST_CASE(modal_dialog_test_language_selection)
527 {
528  test<language_selection>();
529 }
530 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_lobby)
531 {
532  test<mp_lobby>();
533 }
534 BOOST_AUTO_TEST_CASE(modal_dialog_test_lobby_player_info)
535 {
536  test<lobby_player_info>();
537 }
538 BOOST_AUTO_TEST_CASE(modal_dialog_test_log_settings)
539 {
540  test<log_settings>();
541 }
542 BOOST_AUTO_TEST_CASE(modal_dialog_test_message)
543 {
544  test<message>();
545 }
546 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_alerts_options)
547 {
548  test<mp_alerts_options>();
549 }
550 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_connect)
551 {
552  test<mp_connect>();
553 }
554 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_join_game_password_prompt)
555 {
556  test<mp_join_game_password_prompt>();
557 }
558 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_login)
559 {
560  test<mp_login>();
561 }
562 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_method_selection)
563 {
564  test<mp_method_selection>();
565 }
566 BOOST_AUTO_TEST_CASE(modal_dialog_test_mp_report)
567 {
568  test<mp_report>();
569 }
570 BOOST_AUTO_TEST_CASE(modal_dialog_test_simple_item_selector)
571 {
572  test<simple_item_selector>();
573 }
574 BOOST_AUTO_TEST_CASE(modal_dialog_test_screenshot_notification)
575 {
576  test<screenshot_notification>();
577 }
578 BOOST_AUTO_TEST_CASE(modal_dialog_test_select_orb_colors)
579 {
580  test<select_orb_colors>();
581 }
582 BOOST_AUTO_TEST_CASE(modal_dialog_test_reachmap_options)
583 {
584  test<reachmap_options>();
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_wml_error)
603 {
604  test<wml_error>();
605 }
606 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_message_left)
607 {
608  test<wml_message_left>();
609 }
610 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_message_right)
611 {
612  test<wml_message_right>();
613 }
614 BOOST_AUTO_TEST_CASE(modal_dialog_test_wml_message_double)
615 {
616  test<wml_message_double>();
617 }
618 BOOST_AUTO_TEST_CASE(modal_dialog_test_achievements_dialog)
619 {
620  test<achievements_dialog>();
621 }
622 BOOST_AUTO_TEST_CASE(modal_dialog_test_addon_server_info)
623 {
624  test<addon_server_info>();
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(modal_dialog_test_migrate_version_selection_dialog)
631 {
632  test<gui2::dialogs::migrate_version_selection>();
633 }
634 BOOST_AUTO_TEST_CASE(modeless_dialog_test_debug_clock)
635 {
636  test_popup<debug_clock>();
637 }
638 BOOST_AUTO_TEST_CASE(tooltip_test_tooltip_large)
639 {
640  test_tip("tooltip_large");
641 }
642 BOOST_AUTO_TEST_CASE(tooltip_test_tooltip)
643 {
644  test_tip("tooltip");
645 }
646 BOOST_AUTO_TEST_CASE(modal_dialog_test_tod_new_schedule)
647 {
648  test<tod_new_schedule>();
649 }
650 
651 BOOST_AUTO_TEST_CASE(modal_dialog_test_editor_edit_unit)
652 {
653  test<editor_edit_unit>();
654 }
655 
656 // execute last - checks that there aren't any unaccounted for GUIs
658 {
659  std::set<std::string> widget_list = gui2::registered_window_types();
660  std::vector<std::string> widgets_tested = utils::split(filesystem::read_file(test_gui2_fixture::widgets_file));
661  std::set<std::string> omitted {
662  /*
663  * The unit attack unit test are disabled for now, they calling parameters
664  * don't allow 'nullptr's needs to be fixed.
665  */
666  "unit_attack",
667  // No test for this right now, not sure how to use the test system
668  // for dialog with no default constructor
669  "lua_interpreter",
670  /*
671  * Disable label settings dialog test because we need a display_context
672  * object, which we don't have, and it's a lot of work to produce a dummy
673  * one.
674  */
675  "label_settings",
676  "addon_uninstall_list",
677  "addon_manager",
678  "loading_screen",
679  "network_transmission",
680  "synched_choice_wait",
681  "drop_down_menu",
682  "preferences_dialog",
683  "units_dialog",
684  "unit_advance",
685  "mp_host_game_prompt",
686  "mp_create_game",
687  // The title screen appears to be throwing a bad_alloc on Travis, so disable it for now
688  "title_screen",
689  "end_credits",
690  "mp_staging",
691  "mp_join_game",
692  "terrain_layers",
693  "attack_predictions",
694  "help_browser",
695  "story_viewer",
696  "outro",
697  "mp_change_control", // Basically useless without a game_board object, so disabling
698  "game_stats", // segfault with LTO
699  "gamestate_inspector", // segfault with LTO
700  "server_info",
701  "sp_options_configure",// segfault with LTO
702  "campaign_selection",// segfault with LTO
703  "game_load",// segfault after disabling the above tests
704  "file_progress",
705  "fps_report", // needs something to report...
706  "custom_tod", // needs to be adapted to handle a null display
707  };
709 
710  for(const std::string& item : widgets_tested)
711  {
712  widget_list.erase(item);
713  PLAIN_LOG << "Checking widget " << item;
714  BOOST_CHECK_EQUAL(omitted.count(item), 0);
715  }
716  for(const std::string& item : omitted)
717  {
718  widget_list.erase(item);
719  }
720 
721  // Test size() instead of empty() to get the number of offenders
722  BOOST_CHECK_EQUAL(widget_list.size(), 0);
723  for(const std::string& id : widget_list) {
724  PLAIN_LOG << "Window '" << id << "' registered but not tested.";
725  }
726 }
727 
728 BOOST_AUTO_TEST_CASE(test_make_test_fake)
729 {
731 
732  try {
733  message dlg("title", "message", true, false, false);
734  dlg.show(1);
735  } catch(const wml_exception& e) {
737  return;
738  } catch(...) {
739  BOOST_ERROR("Didn't catch the wanted exception, instead caught " << utils::get_unknown_exception_type() << ".");
740  }
741  BOOST_ERROR("Didn't catch the wanted exception, instead caught nothing.");
742 }
743 
744 BOOST_AUTO_TEST_SUITE_END()
745 
746 namespace {
747 
748 template<>
749 struct dialog_tester<addon_server_info>
750 {
751  std::string s = "";
752  bool b = false;
753  addon_server_info* create()
754  {
755  addons_client client("localhost:15999");
756  return new addon_server_info(client, s, b);
757  }
758 };
759 
760 template<>
761 struct dialog_tester<addon_auth>
762 {
763  config cfg;
764  addon_auth* create()
765  {
766  return new addon_auth(cfg);
767  }
768 };
769 
770 template<>
771 struct dialog_tester<addon_connect>
772 {
773  std::string host_name = "host_name";
774  addon_connect* create()
775  {
776  return new addon_connect(host_name, true);
777  }
778 };
779 
780 template<>
781 struct dialog_tester<addon_license_prompt>
782 {
783  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.
784 
785 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.)";
786  addon_license_prompt* create()
787  {
788  return new addon_license_prompt(license_terms);
789  }
790 };
791 
792 template<>
793 struct dialog_tester<addon_manager>
794 {
795  dialog_tester()
796  {
798  }
799  addon_manager* create()
800  {
801  addons_client client("localhost:15999");
802  return new addon_manager(client);
803  }
804 };
805 
806 template<>
807 struct dialog_tester<campaign_difficulty>
808 {
809  campaign_difficulty* create()
810  {
811  const config items("difficulty");
812 
813  return new campaign_difficulty(items);
814  }
815 };
816 
817 template<>
818 struct dialog_tester<campaign_selection>
819 {
820  saved_game state;
822  dialog_tester() : state(config {"campaign_type", "scenario"}), ng(state)
823  {
824  }
825  campaign_selection* create()
826  {
827  return new campaign_selection(ng);
828  }
829 };
830 
831 template<>
832 struct dialog_tester<chat_log>
833 {
834  config cfg;
835  vconfig vcfg;
836  replay_recorder_base rbase;
837  replay r;
838  dialog_tester() : vcfg(cfg), r(rbase) {}
839  chat_log* create()
840  {
841  return new chat_log(vcfg, r);
842  }
843 };
844 
845 template<>
846 struct dialog_tester<editor_choose_addon>
847 {
848  std::string temp;
849  editor_choose_addon* create()
850  {
851  return new editor_choose_addon(temp);
852  }
853 };
854 
855 template<>
856 struct dialog_tester<prompt>
857 {
858  std::string temp;
859  prompt* create()
860  {
861  return new prompt(temp);
862  }
863 };
864 
865 template<>
866 struct dialog_tester<core_selection>
867 {
868  std::vector<config> cores;
869  dialog_tester()
870  {
871  cores.resize(1);
872  }
873  core_selection* create()
874  {
875  return new core_selection(cores, 0);
876  }
877 };
878 
879 template<>
880 struct dialog_tester<custom_tod>
881 {
882  std::vector<time_of_day> times;
883  int current_tod = 0;
884  dialog_tester()
885  {
886  times.resize(1);
887  }
888  custom_tod* create()
889  {
890  return new custom_tod(times, current_tod);
891  }
892 };
893 
894 template<>
895 struct dialog_tester<edit_label>
896 {
897  std::string label = "Label text to modify";
898  bool team_only = false;
899  edit_label* create()
900  {
901  return new edit_label(label, team_only);
902  }
903 };
904 
905 template<>
906 struct dialog_tester<edit_text>
907 {
908  std::string text = "text to modify";
909  edit_text* create()
910  {
911  return new edit_text("title", "label", text);
912  }
913 };
914 
915 template<>
916 struct dialog_tester<editor_edit_label>
917 {
918  std::string label = "Label text to modify";
919  std::string category = "test";
920  bool immutable = false, fog = false, shroud = false;
921  color_t color;
922  editor_edit_label* create()
923  {
924  return new editor_edit_label(label, immutable, fog, shroud, color, category);
925  }
926 };
927 
928 template<>
929 struct dialog_tester<editor_edit_pbl>
930 {
931  std::string temp;
932  std::string temp1;
933  editor_edit_pbl* create()
934  {
935  return new editor_edit_pbl(temp, temp1);
936  }
937 };
938 
939 template<>
940 struct dialog_tester<editor_edit_pbl_translation>
941 {
942  std::string temp1;
943  std::string temp2;
944  std::string temp3;
946  {
947  return new editor_edit_pbl_translation(temp1, temp2, temp3);
948  }
949 };
950 
951 template<>
952 struct dialog_tester<editor_edit_scenario>
953 {
954  std::string id, name, descr;
955  int turns = 0, xp_mod = 50;
956  bool defeat_enemies = false, random_start = false;
957  editor_edit_scenario* create()
958  {
959  return new editor_edit_scenario(id, name, descr, turns, xp_mod, defeat_enemies, random_start);
960  }
961 };
962 
963 template<>
964 struct dialog_tester<editor_edit_side>
965 {
966  team t;
968  dialog_tester() : info(t) {}
969  editor_edit_side* create()
970  {
971  return new editor_edit_side(info);
972  }
973 };
974 
975 template<>
976 struct dialog_tester<formula_debugger>
977 {
978  wfl::formula_debugger debugger;
979  formula_debugger* create()
980  {
981  return new formula_debugger(debugger);
982  }
983 };
984 
985 template<>
986 struct dialog_tester<game_load>
987 {
988  config cfg;
989  // It would be good to have a test directory instead of using the same directory as the player,
990  // however this code will support that - default_saves_dir() will respect --userdata-dir.
992  dialog_tester()
993  {
994  /** @todo Would be nice to add real data to the config. */
995  }
996  game_load* create()
997  {
998  return new game_load(data);
999  }
1000 };
1001 
1002 template<>
1003 struct dialog_tester<game_save>
1004 {
1005  std::string title = "Title";
1006  std::string filename = "filename";
1007  game_save* create()
1008  {
1009  return new game_save(title, filename);
1010  }
1011 
1012 };
1013 
1014 template<>
1015 struct dialog_tester<game_save_message>
1016 {
1017  std::string title = "Title";
1018  std::string filename = "filename";
1019  std::string message = "message";
1020  game_save_message* create()
1021  {
1022  return new game_save_message(title, filename, message);
1023  }
1024 
1025 };
1026 
1027 template<>
1028 struct dialog_tester<game_save_oos>
1029 {
1030  bool ignore_all = false;
1031  std::string title = "Title";
1032  std::string filename = "filename";
1033  std::string message = "message";
1034  game_save_oos* create()
1035  {
1036  return new game_save_oos(ignore_all, title, filename, message);
1037  }
1038 
1039 };
1040 
1041 template<>
1042 struct dialog_tester<install_dependencies>
1043 {
1044  addons_list addons;
1045  install_dependencies* create()
1046  {
1047  return new install_dependencies(addons);
1048  }
1049 };
1050 
1051 template<>
1052 struct dialog_tester<hotkey_bind>
1053 {
1054  std::string id = "";
1055 
1056  hotkey_bind* create()
1057  {
1058  return new hotkey_bind(id);
1059  }
1060 };
1061 
1062 template<>
1063 struct dialog_tester<mp_lobby>
1064 {
1066  wesnothd_connection connection;
1067  mp::lobby_info li;
1068  int selected_game;
1069  dialog_tester() : connection("", ""), li()
1070  {
1071  }
1072  mp_lobby* create()
1073  {
1074  return new mp_lobby(li, connection, selected_game);
1075  }
1076 };
1077 
1078 template<>
1079 struct dialog_tester<mp_match_history>
1080 {
1081  wesnothd_connection connection;
1082  dialog_tester() : connection("", "")
1083  {
1084  }
1085  mp_match_history* create()
1086  {
1087  return new mp_match_history("", connection, false);
1088  }
1089 };
1090 
1091 template<>
1092 struct dialog_tester<gui2::dialogs::migrate_version_selection>
1093 {
1095  {
1097  }
1098 };
1099 
1100 class fake_chat_handler : public events::chat_handler {
1101  void add_chat_message(const std::chrono::system_clock::time_point&,
1102  const std::string&, int, const std::string&,
1103  MESSAGE_TYPE) {}
1104  void send_chat_message(const std::string&, bool) {}
1105  void send_to_server(const config&) {}
1106  void clear_messages() {}
1107 };
1108 
1109 template<>
1110 struct dialog_tester<lobby_player_info>
1111 {
1112  config c;
1113  fake_chat_handler ch;
1114  wesnothd_connection connection;
1115  mp::user_info ui;
1116  mp::lobby_info li;
1117  dialog_tester()
1118  : connection("", "")
1119  , ui(c), li()
1120  {
1121  }
1122  lobby_player_info* create()
1123  {
1124  return new lobby_player_info(ch, ui, li);
1125  }
1126 };
1127 
1128 template<>
1129 struct dialog_tester<log_settings>
1130 {
1131  log_settings* create()
1132  {
1133  return new log_settings();
1134  }
1135 };
1136 
1137 template<>
1138 struct dialog_tester<message>
1139 {
1140  message* create()
1141  {
1142  return new message("Title", "Message", false, false, false);
1143  }
1144 };
1145 
1146 template<>
1147 struct dialog_tester<mp_create_game>
1148 {
1149  saved_game state;
1150  dialog_tester() : state(config {"campaign_type", "multiplayer"})
1151  {
1152  }
1153  mp_create_game* create()
1154  {
1155  return new mp_create_game(state, true);
1156  }
1157 };
1158 
1159 template<>
1160 struct dialog_tester<mp_join_game_password_prompt>
1161 {
1162  std::string password;
1164  {
1165  return new mp_join_game_password_prompt(password);
1166  }
1167 };
1168 
1169 template<>
1170 struct dialog_tester<mp_report>
1171 {
1172  std::string report_text;
1173  mp_report* create()
1174  {
1175  return new mp_report(report_text);
1176  }
1177 };
1178 
1179 static std::vector<std::string> depcheck_mods {"mod_one", "some other", "more"};
1180 
1181 template<>
1182 struct dialog_tester<depcheck_confirm_change>
1183 {
1184  depcheck_confirm_change* create()
1185  {
1186  return new depcheck_confirm_change(true, depcheck_mods, "requester");
1187  }
1188 };
1189 
1190 template<>
1191 struct dialog_tester<depcheck_select_new>
1192 {
1193  depcheck_select_new* create()
1194  {
1195  return new depcheck_select_new(ng::depcheck::MODIFICATION, depcheck_mods);
1196  }
1197 };
1198 
1199 template<>
1200 struct dialog_tester<mp_login>
1201 {
1202  mp_login* create()
1203  {
1204  return new mp_login("wesnoth.org", "label", true);
1205  }
1206 };
1207 
1208 template<>
1209 struct dialog_tester<simple_item_selector>
1210 {
1211  simple_item_selector* create()
1212  {
1213  return new simple_item_selector("title", "message", std::vector<std::string>(), false, false);
1214  }
1215 };
1216 
1217 template<>
1218 struct dialog_tester<screenshot_notification>
1219 {
1220  screenshot_notification* create()
1221  {
1222  return new screenshot_notification("path", nullptr);
1223  }
1224 };
1225 
1226 template<>
1227 struct dialog_tester<theme_list>
1228 {
1229  static theme_info make_theme(const std::string& name)
1230  {
1231  theme_info ti;
1232  ti.id = name;
1233  ti.name = name;
1234  ti.description = name + " this is a description";
1235  return ti;
1236  }
1237  static std::vector<theme_info> themes;
1238  theme_list* create()
1239  {
1240  return new theme_list(themes, 0);
1241  }
1242 };
1243 std::vector<theme_info> dialog_tester<theme_list>::themes {make_theme("classic"), make_theme("new"), make_theme("more"), make_theme("themes")};
1244 
1245 template<>
1246 struct dialog_tester<editor_generate_map>
1247 {
1248  std::vector<std::unique_ptr<map_generator>> map_generators;
1249  editor_generate_map* create()
1250  {
1251  for(const config &i : test_gui2_fixture::main_config.child_range("multiplayer")) {
1252  if(i["scenario_generation"] == "default") {
1253  auto generator_cfg = i.optional_child("generator");
1254  if (generator_cfg) {
1255  map_generators.emplace_back(create_map_generator("", *generator_cfg));
1256  }
1257  }
1258  }
1259 
1260  editor_generate_map* result = new editor_generate_map(map_generators);
1261  BOOST_REQUIRE_MESSAGE(result, "Failed to create a dialog.");
1262 
1263  return result;
1264  }
1265 };
1266 
1267 template<>
1268 struct dialog_tester<editor_new_map>
1269 {
1270  int width = 10;
1271  int height = 10;
1272  editor_new_map* create()
1273  {
1274  return new editor_new_map("Test", width, height);
1275  }
1276 };
1277 
1278 template<>
1279 struct dialog_tester<editor_resize_map>
1280 {
1281  int width = 0;
1282  int height = 0;
1284  bool copy = false;
1285  editor_resize_map* create()
1286  {
1287  return new editor_resize_map(width, height, expand_direction, copy);
1288  }
1289 };
1290 
1291 template<>
1292 struct dialog_tester<file_dialog>
1293 {
1294  file_dialog* create()
1295  {
1296  return new file_dialog();
1297  }
1298 };
1299 
1300 template<>
1301 struct dialog_tester<folder_create>
1302 {
1303  std::string folder_name;
1304  folder_create* create()
1305  {
1306  return new folder_create(folder_name);
1307  }
1308 };
1309 
1310 template<>
1311 struct dialog_tester<transient_message>
1312 {
1313  transient_message* create()
1314  {
1315  return new transient_message("Title", false, "Message", false, "");
1316  }
1317 };
1318 
1319 template<>
1320 struct dialog_tester<title_screen>
1321 {
1322  std::vector<std::string> args;
1323  commandline_options opts;
1325  dialog_tester() : opts(args), game(opts) {}
1326  title_screen* create()
1327  {
1328  return new title_screen(game);
1329  }
1330 };
1331 
1332 template<>
1333 struct dialog_tester<wml_error>
1334 {
1335  static std::vector<std::string> files;
1336  wml_error* create()
1337  {
1338  return new wml_error("Summary", "Post summary", files, "Details");
1339  }
1340 };
1341 std::vector<std::string> dialog_tester<wml_error>::files {"some", "files", "here"};
1342 
1343 template<>
1344 struct dialog_tester<wml_message_left>
1345 {
1346  wml_message_left* create()
1347  {
1348  return new wml_message_left("Title", "Message", "", false);
1349  }
1350 };
1351 
1352 template<>
1353 struct dialog_tester<wml_message_right>
1354 {
1355  wml_message_right* create()
1356  {
1357  return new wml_message_right("Title", "Message", "", false);
1358  }
1359 };
1360 
1361 template<>
1362 struct dialog_tester<wml_message_double>
1363 {
1364  wml_message_double* create()
1365  {
1366  return new wml_message_double("Title", "Message", "", false, "", true);
1367  }
1368 };
1369 
1370 template<>
1371 struct dialog_tester<faction_select>
1372 {
1373  config era_cfg, side_cfg;
1374  std::vector<const config*> eras;
1375  ng::era_metadata era;
1376  ng::flg_manager flg;
1377  std::string color;
1378  dialog_tester()
1379  : era_cfg(), side_cfg(), eras(1, &era_cfg), era(era_cfg) // TODO: Add an actual era definition
1380  , flg(era, eras, side_cfg, false, false, false)
1381  , color("teal")
1382  {}
1383  faction_select* create() {
1384  return new faction_select(flg, color, 1);
1385  }
1386 };
1387 
1388 template<>
1389 struct dialog_tester<generator_settings>
1390 {
1391  config cfg;
1393  dialog_tester() : data(cfg) {}
1394  generator_settings* create()
1395  {
1396  return new generator_settings(data);
1397  }
1398 };
1399 
1400 template<>
1401 struct dialog_tester<sp_options_configure>
1402 {
1403  saved_game state;
1404  ng::create_engine create_eng;
1405  dialog_tester() : create_eng(state) {}
1406  sp_options_configure* create()
1407  {
1408  return new sp_options_configure(create_eng);
1409  }
1410 };
1411 
1412 template<>
1413 struct dialog_tester<statistics_dialog>
1414 {
1415  team t;
1417  statistics_t stats;
1418  dialog_tester() : t() , stats_record(), stats(stats_record) {}
1419  statistics_dialog* create()
1420  {
1421  return new statistics_dialog(stats, t);
1422  }
1423 };
1424 
1425 template<>
1426 struct dialog_tester<surrender_quit>
1427 {
1428  dialog_tester() {}
1429  surrender_quit* create()
1430  {
1431  return new surrender_quit();
1432  }
1433 };
1434 
1435 template<>
1436 struct dialog_tester<tod_new_schedule>
1437 {
1438  std::string id = "id";
1439  t_string name = "name";
1440  dialog_tester() {}
1441  tod_new_schedule* create()
1442  {
1443  return new tod_new_schedule(id, name);
1444  }
1445 };
1446 
1447 template<>
1448 struct dialog_tester<editor_edit_unit>
1449 {
1450  config cfg;
1451  game_config_view view;
1452 
1453  dialog_tester() {}
1454  editor_edit_unit* create()
1455  {
1456  config& units = cfg.add_child("units");
1457  cfg.add_child("race");
1458  config& movetype = units.add_child("movetype");
1459  movetype["name"] = "Test Movetype";
1460  movetype.add_child("defense");
1461  movetype.add_child("resistance");
1462  movetype.add_child("movement_costs");
1463  view = game_config_view::wrap(cfg);
1464  return new editor_edit_unit(view, "test_addon");
1465  }
1466 };
1467 
1468 template<>
1469 struct dialog_tester<gui_test_dialog>
1470 {
1471  dialog_tester() {}
1472  gui_test_dialog* create()
1473  {
1474  return new gui_test_dialog();
1475  }
1476 };
1477 
1478 } // 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:157
config & add_child(std::string_view key)
Definition: config.cpp:436
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.
config get_config(const std::string &path, 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)
Dialog that allows user to create custom unit types.
Definition: edit_unit.hpp:33
A test dialog for testing various gui2 features.
Main class to show messages to the user.
Definition: message.hpp:36
This shows the dialog to select a previous version of Wesnoth to migrate preferences from and redownl...
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.
This shows the dialog to confirm surrender and/or quitting the game.
This class implements the title screen.
Dialog that takes new schedule ID and name from the player.
Shows a transient message.
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:59
void draw()
Draws the window.
Definition: window.cpp:593
The basic "size" of the unit - flying, small land, large land, etc.
Definition: movetype.hpp:44
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:43
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:202
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.
const config * cfg
Declarations for File-IO.
std::size_t i
Definition: function.cpp:1032
std::string label
What to show in the filter's drop-down list.
Definition: manager.cpp:201
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:199
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:111
Defines the exception classes for the layout algorithm.
#define PLAIN_LOG
Definition: log.hpp:296
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:214
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:61
std::string path
Definition: filesystem.cpp:106
bool addon_server_info
Definition: game_config.cpp:79
void load_config(const config &v)
void remove()
Removes a tip.
Definition: tooltip.cpp:94
void show(const std::string &window_id, const t_string &message, const point &mouse, const rect &source_rect)
Shows a tip.
Definition: tooltip.cpp:64
std::string get_modal_dialog_id(const modal_dialog &dialog)
Definition: test_gui2.cpp:178
std::string get_modeless_dialog_id(const modeless_dialog &dialog)
Definition: test_gui2.cpp:183
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
logger & info()
Definition: log.cpp:351
void send_to_server(const config &data)
Attempts to send given data to server if a connection is open.
void set_test_resolution(const int width, const int height)
Sets the dummy display resolution for use by the tests.
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:188
Replay control code.
This file contains the settings handling of the widget library.
std::string filename
Filename.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:61
The paths manager is responsible for recording the various paths that binary files may be located at.
Definition: filesystem.hpp:439
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:29
static config main_config
Definition: test_gui2.cpp:166
std::unique_ptr< game_config_manager > config_manager
Definition: test_gui2.cpp:168
std::vector< std::string > dummy_args
Definition: test_gui2.cpp:169
static const std::string widgets_file
Definition: test_gui2.cpp:167
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:390
BOOST_FIXTURE_TEST_SUITE(test_map_location, MLFixture)
static map_location::direction s
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define e
#define b