Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
23.list.iterators.cpp
Go to the documentation of this file.
1
27#include <list> // for list
28#include <stdexcept> // for out_of_range, length_error
29#include <cstddef> // for size_t
30
31#include <rw_lists.h> // for ListMembers
32#include <rw_driver.h> // for rw_test()
33#include <rw_allocator.h> // for UserAlloc
34#include <rw_new.h> // for bad_alloc, replacement operator new
35
36
38static const char* const exceptions[] = {
39 "unknown exception", "bad_alloc", "exception"
40};
41
42
44// used to exercise
45// begin () and rend () and front ()
46static const ContainerTestCase
47begin_void_test_cases [] = {
48
49#undef TEST
50#define TEST(lst, res) { \
51 __LINE__, -1, -1, -1, -1, -1, \
52 lst, sizeof (lst) - 1, \
53 0, 0, 0, res, 0 \
54}
55
56 // +--------------------------------- controlled sequence
57 // | +---------------- expected result
58 // | |
59 // V V
60 TEST ("", _RWSTD_SIZE_MAX),
61 TEST ("a", 'a' ),
62 TEST ("<U0>", '\0'),
63 TEST ("abc", 'a' ),
64 TEST ("<U0>ab<U0>@2c", '\0'),
65 TEST ("a<U0>b<U0>@2c", 'a' ),
66 TEST ("a<U0>bc<U0>@2", 'a' ),
67 TEST ("x@4096", 'x' ),
68 TEST ("last", 'l' )
69};
70
71
73// used to exercise
74// end () and rbegin () and back ()
75static const ContainerTestCase
76end_void_test_cases [] = {
77
78#undef TEST
79#define TEST(lst, res) { \
80 __LINE__, -1, -1, -1, -1, -1, \
81 lst, sizeof (lst) - 1, \
82 0, 0, 0, res, 0 \
83}
84
85 // +--------------------------------- controlled sequence
86 // | +---------------- expected result
87 // | |
88 // V V
89 TEST ("", _RWSTD_SIZE_MAX),
90 TEST ("a", 'a' ),
91 TEST ("<U0>", '\0'),
92 TEST ("abc", 'c' ),
93 TEST ("<U0>ab<U0>@2c", 'c' ),
94 TEST ("a<U0>b<U0>@2c", 'c' ),
95 TEST ("a<U0>bc<U0>@2", '\0'),
96 TEST ("x@4096", 'x' ),
97 TEST ("last", 't' )
98};
99
100
102// exercises:
103// get_allocator ()
104static const ContainerTestCase
105get_allocator_void_test_cases [] = {
106
107#undef TEST
108#define TEST(lst) { \
109 __LINE__, -1, -1, -1, -1, -1, \
110 lst, sizeof (lst) - 1, \
111 0, 0, 0, 0, 0 \
112}
113
114 // +------------------------------------------ controlled sequence
115 // |
116 // |
117 // |
118 // |
119 // |
120 // |
121 // |
122 // V
123 TEST ("" ),
124 TEST ("ab" ),
125 TEST ("<U0>" ),
126 TEST ("x@4096" ),
127 TEST ("a<U0>b" ),
128 TEST ("a@2048cb@2047" ),
129 TEST ("last" )
130};
131
132
133
135template <class T, class Allocator>
137 const ContainerTestCaseData<T> &tdata)
138{
139 typedef std::list <T, Allocator> List;
140 typedef typename List::iterator ListIter;
141 typedef typename List::const_iterator ListCIter;
142 typedef typename List::reverse_iterator ListRIter;
143 typedef typename List::const_reverse_iterator ListCRIter;
145
146 const ContainerFunc &func = tdata.func_;
147 const ContainerTestCase &tcase = tdata.tcase_;
148
149 const bool test_iters =
150 func.which_ == ListIds::begin_void
151 || func.which_ == ListIds::begin_const_void
152 || func.which_ == ListIds::end_void
153 || func.which_ == ListIds::end_const_void
154 || func.which_ == ListIds::rbegin_void
155 || func.which_ == ListIds::rbegin_const_void
156 || func.which_ == ListIds::rend_void
157 || func.which_ == ListIds::rend_const_void
158 || func.which_ == ListIds::front_void
159 || func.which_ == ListIds::front_const_void
160 || func.which_ == ListIds::back_void
161 || func.which_ == ListIds::back_const_void;
162
163 const bool test_const_list =
164 func.which_ == ListIds::begin_const_void
165 || func.which_ == ListIds::end_const_void
166 || func.which_ == ListIds::rbegin_const_void
167 || func.which_ == ListIds::rend_const_void
168 || func.which_ == ListIds::front_const_void
169 || func.which_ == ListIds::back_const_void;
170
171 const bool test_end_iters =
172 func.which_ == ListIds::end_void
173 || func.which_ == ListIds::end_const_void
174 || func.which_ == ListIds::rend_void
175 || func.which_ == ListIds::rend_const_void;
176
177 // allocator object for test get_allocator
179
180 // construct the list object
181 List lst (tdata.str_, tdata.str_ + tdata.strlen_, alloc);
182 // construct the constant list object
183 const List clst (tdata.str_, tdata.str_ + tdata.strlen_, alloc);
184
185 const std::size_t s_size = test_const_list ? clst.size () : lst.size ();
186
187 // save the state of the list object before the call
188 // to detect exception safety violations (changes to
189 // the state of the object after an exception)
190 const ListState lst_state (lst);
191
192 // start checking for memory leaks
193 rw_check_leaks (lst.get_allocator ());
194
195 try {
196
197 // methods result
198 const T* res_ptr = 0;
199
200 // for begin () and end ()
201 ListIter it;
202 // for begin () const and end () const
203 ListCIter cit;
204 // for rbegin () and rend ()
205 ListRIter rit;
206 // for rbegin () const and rend () const
207 ListCRIter crit;
208
209 // for get_allocator ()
210 Allocator resalloc;
211
212 bool it_relations = true;
213
214 switch (func.which_) {
215
216 case ListIds::begin_void:
217 it = lst.begin();
218 it_relations = it == lst.rend ().base ();
219 if (s_size) res_ptr = &*it;
220 break;
221
222 case ListIds::begin_const_void:
223 cit = clst.begin();
224 it_relations = cit == clst.rend ().base ();
225 if (s_size) res_ptr = &*cit;
226 break;
227
228 case ListIds::end_void:
229 it = lst.end();
230 it_relations = it == lst.rbegin ().base ();
231 if (s_size) res_ptr = &*--it;
232 break;
233
234 case ListIds::end_const_void:
235 cit = clst.end();
236 it_relations = cit == clst.rbegin ().base ();
237 if (s_size) res_ptr = &*--cit;
238 break;
239
240 case ListIds::rbegin_void:
241 rit = lst.rbegin();
242 it_relations = rit.base () == lst.end ();
243 if (s_size) res_ptr = &*rit;
244 break;
245
246 case ListIds::rbegin_const_void:
247 crit = clst.rbegin();
248 it_relations = crit.base () == clst.end ();
249 if (s_size) res_ptr = &*crit;
250 break;
251
252 case ListIds::rend_void:
253 rit = lst.rend();
254 it_relations = rit.base () == lst.begin ();
255 if (s_size) res_ptr = &*--rit;
256 break;
257
258 case ListIds::rend_const_void:
259 crit = clst.rend();
260 it_relations = crit.base () == clst.begin ();
261 if (s_size) res_ptr = &*--crit;
262 break;
263
264 case ListIds::front_void:
265 if (s_size) {
266 res_ptr = &lst.front ();
267 it_relations = res_ptr == &*lst.begin ();
268 }
269 break;
270
271 case ListIds::front_const_void:
272 if (s_size) {
273 res_ptr = &clst.front ();
274 it_relations = res_ptr == &*clst.begin ();
275 }
276 break;
277
278 case ListIds::back_void:
279 if (s_size) {
280 res_ptr = &lst.back ();
281 it_relations = res_ptr == &*--lst.end ();
282 }
283 break;
284
285 case ListIds::back_const_void:
286 if (s_size) {
287 res_ptr = &clst.back ();
288 it_relations = res_ptr == &*--clst.end ();
289 }
290 break;
291
292 case ListIds::get_allocator_void:
293 resalloc = clst.get_allocator ();
294 break;
295
296 default:
297 RW_ASSERT (!"test logic error: unknown iterators overload");
298 return;
299 }
300
301 if (res_ptr) {
302
303 const char exp_res =
304 (_RWSTD_SIZE_MAX != tcase.nres ? char (tcase.nres) : char ());
305
306 const bool success = 0 == T::mismatch (res_ptr, &exp_res, 1);
307
308 rw_assert (success, 0, tcase.line,
309 "line %d. %{$FUNCALL}%{?} - 1%{;} expected "
310 "%{#c}, got %{#c}", __LINE__,
311 test_end_iters, exp_res, char (res_ptr->data_.val_));
312 }
313
314 if (test_iters) {
315
316 if (0 == s_size) {
317
318 bool success = true;
319
320 if ( func.which_ == ListIds::begin_void
321 || func.which_ == ListIds::end_void)
322 success = it == lst.begin () && it == lst.end ();
323
324 if ( func.which_ == ListIds::begin_const_void
325 || func.which_ == ListIds::end_const_void)
326 success = cit == clst.begin () && cit == clst.end ();
327
328 if ( func.which_ == ListIds::rbegin_void
329 || func.which_ == ListIds::rend_void)
330 success = rit == lst.rbegin () && rit == lst.rend ();
331
332 if ( func.which_ == ListIds::rbegin_const_void
333 || func.which_ == ListIds::rend_const_void)
334 success = crit == clst.rbegin () && crit == clst.rend ();
335
336 // check the begin () == end (), rbegin () == rend ()
337 rw_assert(success, 0, tcase.line,
338 "line %d. %{$FUNCALL} returned iterator is not "
339 "equal to begin and end for an empty list",
340 __LINE__);
341 }
342
343 // check the iterators relationship
344 rw_assert(it_relations, 0, tcase.line,
345 "line %d. %{$FUNCALL} iterators "
346 "relationship is broken", __LINE__);
347 }
348
349 if (func.which_ == ListIds::get_allocator_void) {
350
351 // verify that the allocator returned from the function
352 // equal to allocator passed to the ctor
353 const bool success = (alloc == resalloc);
354
355 rw_assert(success, 0, tcase.line,
356 "line %d. %{$FUNCALL} expected equal to allocator "
357 "passed to the ctor", __LINE__);
358 }
359 }
360
361#ifndef _RWSTD_NO_EXCEPTIONS
362
363 catch (const std::bad_alloc &ex) {
364 rw_assert (0, 0, tcase.line,
365 "line %d. %{$FUNCALL} unexpectedly caught std::%s(%#s)",
366 __LINE__, exceptions [1], ex.what ());
367 }
368 catch (const std::exception &ex) {
369 rw_assert (0, 0, tcase.line,
370 "line %d. %{$FUNCALL} unexpectedly caught std::%s(%#s)",
371 __LINE__, exceptions [2], ex.what ());
372 }
373 catch (...) {
374 rw_assert (0, 0, tcase.line,
375 "line %d. %{$FUNCALL} unexpectedly caught %s",
376 __LINE__, exceptions [0]);
377 }
378
379#endif // _RWSTD_NO_EXCEPTIONS
380
381 // FIXME: verify the number of blocks the function call
382 // is expected to allocate and detect any memory leaks
383 rw_check_leaks (lst.get_allocator (), tcase.line,
384 std::size_t (-1), std::size_t (-1));
385
386 // verify that state of the object didn't changed
387 lst_state.assert_equal (ListState (lst),
388 __LINE__, tcase.line, "call");
389}
390
391
394
395int main (int argc, char** argv)
396{
397 static const ContainerTest
398 tests [] = {
399
400#undef TEST
401#define TEST(gsig, sig) { \
402 gsig, sig ## _test_cases, \
403 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
404}
405
406 TEST (ListIds::begin_void, begin_void),
407 TEST (ListIds::begin_const_void, begin_void),
408 TEST (ListIds::end_void, end_void),
409 TEST (ListIds::end_const_void, end_void),
410 TEST (ListIds::rbegin_void, end_void),
411 TEST (ListIds::rbegin_const_void, end_void),
412 TEST (ListIds::rend_void, begin_void),
413 TEST (ListIds::rend_const_void, begin_void),
414 TEST (ListIds::front_void, begin_void),
415 TEST (ListIds::front_const_void, begin_void),
416 TEST (ListIds::back_void, end_void),
417 TEST (ListIds::back_const_void, end_void),
418 TEST (ListIds::get_allocator_void, get_allocator_void)
419 };
420
421 const std::size_t test_count = sizeof tests / sizeof *tests;
422
423 return rw_run_cont_test (argc, argv, __FILE__,
424 "lib.list.iterators", ContainerIds::List,
425 test_iterators_func_array, tests, test_count);
426}
#define T
Definition 17.names.cpp:163
#define alloc
Definition 17.names.cpp:441
#define TEST(lst, res)
void test_iterators(T *, Allocator *, const ContainerTestCaseData< T > &tdata)
#define main
const ContainerFunc & func_
const ContainerTestCase & tcase_
_TEST_EXPORT void rw_check_leaks(const SharedAlloc *=0, int=0, _RWSTD_SIZE_T=0, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX)
_TEST_EXPORT int rw_run_cont_test(int, char **, const char *, const char *, ContainerIds::ContainerId, ContainerTestFunc *, const ContainerTest *, _RWSTD_SIZE_T)
#define DEFINE_CONTAINER_TEST_FUNCTIONS(fname)
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
#define RW_ASSERT(expr)
_RWSTD_SIZE_T nres
void assert_equal(const ListState &state, int line, int case_line, const char *when) const
Definition rw_lists.h:267