The Battle for Wesnoth  1.19.0-dev
iterator.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011 - 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 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
18 #include <boost/test/unit_test.hpp>
19 
20 #include "config.hpp"
21 #include "config_cache.hpp"
23 #include "gui/widgets/label.hpp"
24 #include "gui/widgets/grid.hpp"
25 
26 #include <sstream>
27 #include <typeinfo>
28 
29 /*
30  * In the unit tests we use a widget tree that looks like:
31  *
32  * [0]
33  * \
34  * [1|2|3|4]
35  * \
36  * [5|6|7|8]
37  *
38  * Where widgets 0 and 1 are a grid and the rest of the widgets a label.
39  * The unit tests traverse the tree.
40  */
41 
42 static std::string top_down_t_t_t_result()
43 {
44  static const std::string result =
45  "At '0'. Iterate widget: reached the end. Iterate grid: failed. "
46  "Iterate child: proceed. Down and visit '1'.\n"
47  "At '1'. Iterate widget: reached the end. Iterate grid: failed. "
48  "Iterate child: proceed. Down and visit '5'.\n"
49  "At '5'. Iterate widget: reached the end. Iterate grid: failed. "
50  "Iterate child: reached the end. Up widget '5'. "
51  "Iterate: reached '6'. Down and visit '6'.\n"
52  "At '6'. Iterate widget: reached the end. Iterate grid: failed. "
53  "Iterate child: reached the end. Up widget '6'. "
54  "Iterate: reached '7'. Down and visit '7'.\n"
55  "At '7'. Iterate widget: reached the end. Iterate grid: failed. "
56  "Iterate child: reached the end. Up widget '7'. "
57  "Iterate: reached '8'. Down and visit '8'.\n"
58  "At '8'. Iterate widget: reached the end. Iterate grid: failed. "
59  "Iterate child: reached the end. Up widget '8'. "
60  "Iterate: failed. Up widget '1'. "
61  "Iterate: reached '2'. Down and visit '2'.\n"
62  "At '2'. Iterate widget: reached the end. Iterate grid: failed. "
63  "Iterate child: reached the end. Up widget '2'. "
64  "Iterate: reached '3'. Down and visit '3'.\n"
65  "At '3'. Iterate widget: reached the end. Iterate grid: failed. "
66  "Iterate child: reached the end. Up widget '3'. "
67  "Iterate: reached '4'. Down and visit '4'.\n"
68  "At '4'. Iterate widget: reached the end. Iterate grid: failed. "
69  "Iterate child: reached the end. Up widget '4'. "
70  "Iterate: failed. Finished iteration.\n";
71 
72  return result;
73 }
74 
75 static std::string bottom_up_t_t_t_result()
76 {
77  static const std::string result =
78  "Constructor: Down widget '1'. Down widget '5'. Finished at '5'.\n"
79  "At '5'. Iterate widget: reached the end. Iterate grid: failed. "
80  "Iterate child: Up '1'. Iterate child: visit '1'. "
81  "Down widget '6'. Visit '6'.\n"
82  "At '6'. Iterate widget: reached the end. Iterate grid: failed. "
83  "Iterate child: Up '1'. Iterate child: visit '1'. "
84  "Down widget '7'. Visit '7'.\n"
85  "At '7'. Iterate widget: reached the end. Iterate grid: failed. "
86  "Iterate child: Up '1'. Iterate child: visit '1'. "
87  "Down widget '8'. Visit '8'.\n"
88  "At '8'. Iterate widget: reached the end. Iterate grid: failed. "
89  "Iterate child: Up '1'. Iterate child: reached the end. Visit '1'.\n"
90  "At '1'. Iterate widget: reached the end. Iterate grid: failed. "
91  "Iterate child: Up '0'. Iterate child: visit '0'. "
92  "Down widget '2'. Visit '2'.\n"
93  "At '2'. Iterate widget: reached the end. Iterate grid: failed. "
94  "Iterate child: Up '0'. Iterate child: visit '0'. "
95  "Down widget '3'. Visit '3'.\n"
96  "At '3'. Iterate widget: reached the end. Iterate grid: failed. "
97  "Iterate child: Up '0'. Iterate child: visit '0'. "
98  "Down widget '4'. Visit '4'.\n"
99  "At '4'. Iterate widget: reached the end. Iterate grid: failed. "
100  "Iterate child: Up '0'. Iterate child: reached the end. Visit '0'.\n"
101  "At '0'. Iterate widget: reached the end. Iterate grid: failed. "
102  "Iterate child: Finished iteration.\n";
103 
104  return result;
105 }
106 
108  , std::unique_ptr<gui2::widget> widget
109  , const std::string& id
110  , const unsigned row
111  , const unsigned column)
112 {
113  BOOST_REQUIRE_NE(widget.get(), static_cast<gui2::widget*>(nullptr));
114 
115  widget->set_id(id);
116  grid.set_child(std::move(widget)
117  , row
118  , column
121  , 0);
122 }
123 
124 template<class T>
125 static void test_control(T&& control)
126 {
127  {
129  true
130  , true
131  , true>>
132  iterator(control);
133 
134  /***** INITIAL STATE *****/
135 
136  BOOST_CHECK_EQUAL(iterator.at_end(), false);
137 
138  BOOST_CHECK_EQUAL(&*iterator, &control);
139 
140  /***** POST END *****/
141 
142  BOOST_CHECK_EQUAL(iterator.next(), false);
143 
144  BOOST_CHECK_EQUAL(iterator.at_end(), true);
145 
146  }
147  {
149  false
150  , true
151  , true>>
152  iterator(control);
153 
154  /***** INITIAL STATE *****/
155 
156  BOOST_CHECK_EQUAL(iterator.at_end(), true);
157  }
158 
159  {
161  BOOST_CHECK_EQUAL(iterator.at_end(), false);
162  }
163  {
165  BOOST_CHECK_EQUAL(iterator.at_end(), true);
166  }
167 }
168 
169 static void test_control()
170 {
171  /* Could add more widgets to the list. */
173 
174 }
175 
176 static void test_grid()
177 {
178  /* An empty grid behaves the same as a control so test here. */
180 
181  /* Test the child part here. */
182  gui2::grid grid(2 ,2);
183  grid.set_id("0");
184 
185  auto g = std::make_unique<gui2::grid>(2, 2);
186  gui2::grid* gptr = g.get();
187 
188  add_widget(grid, std::move(g), "1", 0, 0);
189  add_widget(grid, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "2", 1, 0);
190  add_widget(grid, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "3", 0, 1);
191  add_widget(grid, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "4", 1, 1);
192 
193  add_widget(*gptr, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "5", 0, 0);
194  add_widget(*gptr, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "6", 1, 0);
195  add_widget(*gptr, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "7", 0, 1);
196  add_widget(*gptr, std::make_unique<gui2::label>(gui2::implementation::builder_label(config())), "8", 1, 1);
197 
198  {
199  std::stringstream sstr;
200  lg::redirect_output_setter redirect_output(sstr);
201 
203  true
204  , true
205  , true>>
206  iterator(grid);
207 
208  while(iterator.next()) {
209  /* DO NOTHING */
210  }
211 
212  BOOST_CHECK_EQUAL(top_down_t_t_t_result(), sstr.str());
213  }
214  {
215  std::stringstream sstr;
216  lg::redirect_output_setter redirect_output(sstr);
217 
219  true
220  , true
221  , true>>
222  iterator(grid);
223 
224  for( ; !iterator.at_end(); ++iterator) {
225  /* DO NOTHING */
226  }
227 
228  BOOST_CHECK_EQUAL(top_down_t_t_t_result(), sstr.str());
229  }
230  {
231  std::stringstream sstr;
232  lg::redirect_output_setter redirect_output(sstr);
233 
235  true
236  , true
237  , true>>
238  iterator(grid);
239 
240  while(iterator.next()) {
241  /* DO NOTHING */
242  }
243 
244  BOOST_CHECK_EQUAL(bottom_up_t_t_t_result(), sstr.str());
245  }
246  {
247  std::stringstream sstr;
248  lg::redirect_output_setter redirect_output(sstr);
249 
251  true
252  , true
253  , true>>
254  iterator(grid);
255 
256  for( ; !iterator.at_end(); ++iterator) {
257  /* DO NOTHING */
258  }
259 
260  BOOST_CHECK_EQUAL(bottom_up_t_t_t_result(), sstr.str());
261  }
262 }
263 
264 BOOST_AUTO_TEST_CASE(test_gui2_iterator)
265 {
266  /**** Initialize the environment. *****/
268 
269  cache.clear_defines();
270  cache.add_define("EDITOR");
271  cache.add_define("MULTIPLAYER");
272 
273  lg::set_log_domain_severity("gui/iterator", lg::debug());
274  lg::timestamps(false);
275 
276  std::stringstream sstr;
277  lg::redirect_output_setter redirect_output(sstr);
278 
279  test_control();
280  test_grid();
281 
283 }
double g
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
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.
Base container class.
Definition: grid.hpp:32
static const unsigned HORIZONTAL_GROW_SEND_TO_CLIENT
Definition: grid.hpp:56
static const unsigned VERTICAL_GROW_SEND_TO_CLIENT
Definition: grid.hpp:49
The iterator class.
Definition: iterator.hpp:37
A label displays text that can be wrapped but no scrollbars are provided.
Definition: label.hpp:56
Base class for all widgets.
Definition: widget.hpp:53
Helper class to redirect the output of the logger in a certain scope.
Definition: log.hpp:98
Contains the base iterator class for the gui2 widgets.
logger & debug()
Definition: log.cpp:320
logger & warn()
Definition: log.cpp:308
void timestamps(bool t)
Definition: log.cpp:299
bool set_log_domain_severity(const std::string &name, severity severity)
Definition: log.cpp:342
bool grid()
Definition: general.cpp:565
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
static std::string bottom_up_t_t_t_result()
Definition: iterator.cpp:75
static void test_control(T &&control)
Definition: iterator.cpp:125
static void add_widget(gui2::grid &grid, std::unique_ptr< gui2::widget > widget, const std::string &id, const unsigned row, const unsigned column)
Definition: iterator.cpp:107
static void test_grid()
Definition: iterator.cpp:176
static std::string top_down_t_t_t_result()
Definition: iterator.cpp:42
BOOST_AUTO_TEST_CASE(test_gui2_iterator)
Definition: iterator.cpp:264