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