The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
iterator.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2011 - 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#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
42static 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
75static 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
107static void add_widget(gui2::grid& grid
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
124template<class T>
125static 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
169static void test_control()
170{
171 /* Could add more widgets to the list. */
173
174}
175
176static 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
264BOOST_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}
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
Singleton class to manage game config file caching.
static config_cache & instance()
Get reference to the singleton object.
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
void set_child(std::unique_ptr< widget > widget, const unsigned row, const unsigned col, const unsigned flags, const unsigned border_size)
Sets a child in the grid.
Definition grid.cpp:71
The iterator class.
Definition iterator.hpp:37
Base class for all widgets.
Definition widget.hpp:55
void set_id(const std::string &id)
Definition widget.cpp:98
Helper class to redirect the output of the logger in a certain scope.
Definition log.hpp:98
Definitions for the interface to Wesnoth Markup Language (WML).
Contains the base iterator class for the gui2 widgets.
logger & debug()
Definition log.cpp:357
logger & warn()
Definition log.cpp:345
void timestamps(bool t)
Definition log.cpp:336
bool set_log_domain_severity(const std::string &name, severity severity)
Definition log.cpp:379
std::unordered_map< std::string, cache_item > cache
Definition sound.cpp:146
static std::string bottom_up_t_t_t_result()
Definition iterator.cpp:75
static void test_control()
Definition iterator.cpp:169
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
#define g