Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
23.list.erase.cpp
Go to the documentation of this file.
1
27#include <list> // for list
28#include <cstddef> // for ptrdiff_t, size_t
29#include <stdexcept> // for out_of_range
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_char.h> // for rw_expand()
35#include <rw_new.h> // for bad_alloc, replacement operator new
36
37
39// for convenience and brevity
40#define Erase(sig) ListIds::erase_ ## sig
41
42static const char* const exceptions[] = {
43 "unknown exception", "exception"
44};
45
46
48// used to exercise
49// erase (iterator, iterator)
50static const ContainerTestCase
52
53#undef TEST
54#define TEST(str, off, size, res) { \
55 __LINE__, off, size, -1, -1, -1, str, sizeof str - 1, \
56 0, 0, res, sizeof res - 1, 0 }
57
58 // +----------------------------------------- controlled sequence
59 // | +--------------------- erase() pos argument
60 // | | +----------- erase() n argument
61 // | | | +------- expected result sequence
62 // | | | |
63 // | | | |
64 // | | | |
65 // | | | |
66 // | | | |
67 // V V V V
68 TEST ("", 0, 0, "" ),
69 TEST ("<U0>", 0, 1, "" ),
70 TEST ("<U0>", 0, 0, "<U0>" ),
71 TEST ("<U0>", 1, 1, "<U0>" ),
72 TEST ("<U0>@2", 1, 1, "<U0>" ),
73 TEST ("<U0>@2", 0, 1, "<U0>" ),
74
75 TEST ("a", 0, 1, "" ),
76 TEST ("a", 0, 0, "a" ),
77 TEST ("a", 1, 1, "a" ),
78
79 TEST ("abc", 0, 3, "" ),
80 TEST ("abc", 0, 2, "c" ),
81 TEST ("abc", 1, 2, "a" ),
82 TEST ("abc", 1, 1, "ac" ),
83 TEST ("abc", 2, 1, "ab" ),
84 TEST ("abc", 3, 0, "abc" ),
85
86 TEST ("t<U0> s", 0, 3, "s" ),
87 TEST ("t<U0> s", 0, 4, "" ),
88 TEST ("t<U0> s", 0, 1, "<U0> s" ),
89 TEST ("t<U0> s", 1, 3, "t" ),
90 TEST ("t<U0> s", 1, 2, "ts" ),
91 TEST ("t<U0> s", 2, 2, "t<U0>" ),
92 TEST ("t<U0> s", 2, 1, "t<U0>s" ),
93 TEST ("t<U0> s", 3, 2, "t<U0> " ),
94 TEST ("t<U0> s", 4, 0, "t<U0> s" ),
95
96 TEST ("a<U0>@3b", 2, 0, "a<U0>@3b" ),
97 TEST ("a<U0>@3b", 2, 3, "a<U0>" ),
98 TEST ("a<U0>@3b", 2, 2, "a<U0>b" ),
99 TEST ("a<U0>@3b", 1, 4, "a" ),
100 TEST ("a<U0>@3b", 0, 5, "" ),
101 TEST ("a<U0>@3b", 0, 2, "<U0>@2b" ),
102 TEST ("a<U0>b<U0>@2c", 0, 6, "" ),
103 TEST ("a<U0>b<U0>@2c", 4, 2, "a<U0>b<U0>" ),
104 TEST ("a<U0>b<U0>@2c", 4, 1, "a<U0>b<U0>c" ),
105 TEST ("<U0>ab<U0>@2c", 2, 5, "<U0>a" ),
106 TEST ("<U0>ab<U0>@2c", 0, 4, "<U0>c" ),
107 TEST ("ab<U0>c<U0>@2", 5, 1, "ab<U0>c<U0>" ),
108 TEST ("a", 0, 3, "" ),
109 TEST ("t<U0> s", 0, 9, "" ),
110 TEST ("ab<U0>c<U0>@2", 0, 10, "" ),
111 TEST ("x@4096", 0, 4105, "" ),
112 TEST ("a", 3, 1, "a" ),
113 TEST ("t<U0> s", 5, 1, "t<U0> s" ),
114 TEST ("ab<U0>c<U0>@2", 10, 1, "ab<U0>c<U0>@2" ),
115 TEST ("x@4096", 4106, 1, "x@4096" ),
116 TEST ("x@4096", 0, 4096, "" ),
117 TEST ("x@4096", 1, 4095, "x" ),
118 TEST ("x@4096", 4, 4092, "xxxx" ),
119 TEST ("x@4096", 4, 4090, "xxxxxx" ),
120 TEST ("x@4096", 4096, 4096, "x@4096" ),
121 TEST ("x@2048y@2048", 1, 4094, "xy" ),
122
123 TEST ("last test", 4, 1, "lasttest" )
124};
125
126
127
129// used to exercise
130// erase (iterator)
131static const ContainerTestCase
132iter_test_cases [] = {
133
134#undef TEST
135#define TEST(str, off, res) { \
136 __LINE__, off, -1, -1, -1, -1, str, sizeof str - 1, \
137 0, 0, res, sizeof res - 1, 0 }
138
139 // +-------------------------------------- controlled sequence
140 // | +------------------ iterator offset
141 // | | +------------- expected result sequence
142 // | | |
143 // V V V
144 TEST ("a", 0, ""),
145
146 TEST ("<U0>", 0, ""),
147 TEST ("<U0>@2", 0, "<U0>"),
148 TEST ("<U0>@2", 1, "<U0>"),
149
150 TEST ("abc", 0, "bc"),
151 TEST ("abc", 1, "ac"),
152 TEST ("abc", 2, "ab"),
153
154 TEST ("t<U0> s", 0, "<U0> s"),
155 TEST ("t<U0> s", 1, "t s"),
156 TEST ("t<U0> s", 2, "t<U0>s"),
157 TEST ("t<U0> s", 3, "t<U0> "),
158
159 TEST ("a<U0>@3b", 4, "a<U0>@3"),
160 TEST ("a<U0>@3b", 2, "a<U0>@2b"),
161 TEST ("a<U0>@3b", 1, "a<U0>@2b"),
162 TEST ("a<U0>@3b", 0, "<U0>@3b"),
163 TEST ("a<U0>b<U0>@2c", 4, "a<U0>b<U0>c"),
164 TEST ("<U0>ab<U0>@2c", 0, "ab<U0>@2c"),
165 TEST ("<U0>ab<U0>@2c", 2, "<U0>a<U0>@2c"),
166 TEST ("ab<U0>c<U0>@2", 5, "ab<U0>c<U0>"),
167
168 TEST ("x@4096y", 4096, "x@4096"),
169 TEST ("x@4096", 4088, "x@4095"),
170 TEST ("ax@4096", 0, "x@4096"),
171 TEST ("x@4096", 9, "x@4095"),
172
173 TEST ("last test", 4, "lasttest")
174};
175
176
178// used to exercise
179// pop_front ()
180static const ContainerTestCase
181pop_front_test_cases [] = {
182
183#undef TEST
184#define TEST(str, res) { \
185 __LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, \
186 0, 0, res, sizeof res - 1, 0 }
187
188 // +----------------------------------------- controlled sequence
189 // | +------------------------ expected result sequence
190 // | |
191 // | |
192 // | |
193 // | |
194 // | |
195 // V V
196 TEST ("<U0>", "" ),
197 TEST ("<U0>@2", "<U0>" ),
198 TEST ("a", "" ),
199 TEST ("abc", "bc" ),
200 TEST ("t<U0> s", "<U0> s" ),
201 TEST ("a<U0>@3b", "<U0>@3b" ),
202 TEST ("a<U0>b<U0>@2c", "<U0>b<U0>@2c" ),
203 TEST ("<U0>ab<U0>@2c", "ab<U0>@2c" ),
204 TEST ("ab<U0>c<U0>@2", "b<U0>c<U0>@2" ),
205 TEST ("x@4096", "x@4095" ),
206
207 TEST (" last test", "last test" )
208};
209
210
212// used to exercise
213// pop_back ()
214static const ContainerTestCase
215pop_back_test_cases [] = {
216
217#undef TEST
218#define TEST(str, res) { \
219 __LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, \
220 0, 0, res, sizeof res - 1, 0 }
221
222 // +----------------------------------------- controlled sequence
223 // | +------------------------ expected result sequence
224 // | |
225 // | |
226 // | |
227 // | |
228 // | |
229 // V V
230 TEST ("<U0>", "" ),
231 TEST ("<U0>@2", "<U0>" ),
232 TEST ("a", "" ),
233 TEST ("abc", "ab" ),
234 TEST ("t<U0> s", "t<U0> " ),
235 TEST ("a<U0>@3b", "a<U0>@3" ),
236 TEST ("a<U0>b<U0>@2c", "a<U0>b<U0>@2" ),
237 TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2" ),
238 TEST ("ab<U0>c<U0>@2", "ab<U0>c<U0>" ),
239 TEST ("x@4096", "x@4095" ),
240
241 TEST ("last test ", "last test" )
242};
243
244
246template <class InputIterator, class Distance>
247inline void
249
250 while (0 < dist) {
251 --dist;
252 ++it;
253 }
254}
255
256template<class InputIterator>
257inline std::size_t
259{
260 std::size_t dist = 0;
261
262 for (; first != last; ++first)
263 ++dist;
264
265 return dist;
266}
267
268template <class T, class Allocator>
270 const ContainerTestCaseData<T> &tdata)
271{
272 typedef std::list <T, Allocator> List;
273 typedef typename List::iterator ListIter;
274 typedef typename List::const_iterator ListCIter;
276
277 const ContainerFunc &func = tdata.func_;
278 const ContainerTestCase &tcase = tdata.tcase_;
279
280 // construct the list object to be modified
281 List lst (tdata.str_, tdata.str_ + tdata.strlen_);
282
283 // compute the offset and the extent (the number of elements)
284 // of the first range into the list object being modified
285 const std::size_t size1 = tdata.strlen_;
286 const std::size_t off1 =
287 std::size_t (tcase.off) < size1 ? std::size_t (tcase.off) : size1;
288 const std::size_t ext1 =
289 off1 + tcase.size < size1 ? tcase.size : size1 - off1;
290
291 // create a pair of iterators into the list object being modified
292 ListIter it_first (lst.begin ());
293 _rw_advance (it_first, off1);
294
295#ifndef _RWSTD_NO_EXCEPTIONS
296
297 // is some exception expected ?
298 const char* expected = 0;
299 const char* caught = 0;
300
301#else // if defined (_RWSTD_NO_EXCEPTIONS)
302
303 if (tcase.bthrow)
304 return;
305
306#endif // _RWSTD_NO_EXCEPTIONS
307
308 // start checking for memory leaks
309 rwt_check_leaks (0, 0);
310
311 ListIter res_iter;
312
313 const bool is_class = ListIds::UserClass == func.elem_id_;
314
315 const std::size_t x_count_save = UserClass::count_;
316
317 try {
318 // reset function call counters
319 if (is_class)
321
322 std::size_t delcnt = 0;
323
324 switch (func.which_) {
325
326 case Erase (iter):
327 res_iter = lst.erase (it_first);
328 delcnt = 1;
329 break;
330
331 case Erase (iter_iter): {
332 ListIter it_last (it_first);
333 _rw_advance (it_last, ext1);
334 res_iter = lst.erase (it_first, it_last);
335 delcnt = ext1;
336 break;
337 }
338
339 case ListIds::pop_front_void:
340 lst.pop_front ();
341 delcnt = 1;
342 break;
343
344 case ListIds::pop_back_void:
345 lst.pop_back ();
346 delcnt = 1;
347 break;
348
349 default:
350 RW_ASSERT (!"test logic error: unknown erase overload");
351 return;
352 }
353
354 if (is_class) {
355 // verify that the erase method calls only dtor
356 // of UserClass and only the given number of times each
357 bool success = UserClass::is_total (x_count_save - delcnt,
358 0, 0, 0, 0, 0)
359 && UserClass::n_total_dtor_ == delcnt;
360
361 rw_assert (success, 0, tcase.line,
362 "line %d. %{$FUNCALL} called default/copy ctor, "
363 "operator=() and dtor %zu, %zu, %zu, and %zu times, "
364 "respectively, 0, 0, 0, %zu expected",
365 __LINE__,
370 }
371
372 if (ListIds::pop_front_void != func.which_
373 && ListIds::pop_back_void != func.which_) {
374 // verify the returned value
375 std::size_t dist = _rw_distance (lst.begin (), res_iter);
376 rw_assert (dist <= lst.size(), 0, tcase.line,
377 "line %d. %{$FUNCALL} returned invalid iterator, "
378 "difference with begin is %zu",
379 __LINE__, dist);
380
381 if (std::size_t (tcase.off) >= tdata.reslen_) {
382 rw_assert (res_iter == lst.end (), 0, tcase.line,
383 "line %d. %{$FUNCALL} != end()", __LINE__);
384 }
385 else {
386
387 // assert precondition to silence a bogus HP cadvise
388 // warning #20200-D: Potential null pointer dereference
389 const T* pres_iter = &*res_iter;
390 RW_ASSERT (pres_iter != 0);
391
392 bool success =
393 tdata.res_ [tcase.off].data_.val_ == pres_iter->data_.val_;
394
395 rw_assert (success, 0, tcase.line,
396 "line %d. %{$FUNCALL} == %{#c}, got %{#c}",
397 __LINE__, char (tdata.res_ [tcase.off].data_.val_),
398 char (pres_iter->data_.val_));
399 }
400 }
401
402 // for convenience
403 static const int cwidth = sizeof (T);
404
405 const std::size_t got_size = lst.size ();
406 char* const got = new char [got_size + 1];
407
408 std::size_t index = 0;
409 for (ListCIter it = lst.begin (),
410 end = lst.end (); it != end; ++it) {
411 got [index++] = char (it->data_.val_);
412 }
413
414 got [got_size] = '\0';
415
416 // verify that strings length are equal
417 rw_assert (tdata.reslen_ == got_size, 0, tcase.line,
418 "line %d. %{$FUNCALL} expected \"%{X=*}\" with length "
419 "%zu, got %{/*.*Gs} with length %zu",
420 __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
421 tdata.reslen_, 1, int (got_size), got, got_size);
422
423 if (tdata.reslen_ == got_size) {
424 // if the result length matches the expected length
425 // (and only then), also verify that the modified
426 // list matches the expected result
427 const T* pmatch = T::mismatch (tdata.res_, got, got_size);
428
429 rw_assert (0 == pmatch, 0, tcase.line,
430 "line %d. %{$FUNCALL} expected \"%{X=*}\", "
431 "got %{/*.*Gs}, difference at offset %zu",
432 __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
433 1, int (got_size), got, pmatch - tdata.res_);
434 }
435
436 delete [] got;
437 }
438
439#ifndef _RWSTD_NO_EXCEPTIONS
440
441 catch (const std::exception &ex) {
442 caught = exceptions [1];
443 rw_assert (0, 0, tcase.line,
444 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
445 "unexpectedly%{;} caught std::%s(%#s)",
446 __LINE__, 0 != expected, expected, caught, ex.what ());
447 }
448 catch (...) {
449 caught = exceptions [0];
450 rw_assert (0, 0, tcase.line,
451 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
452 "unexpectedly%{;} caught %s",
453 __LINE__, 0 != expected, expected, caught);
454 }
455
456#endif // _RWSTD_NO_EXCEPTIONS
457
458 // FIXME: verify the number of blocks the function call
459 // is expected to allocate and detect any memory leaks
460 rw_check_leaks (lst.get_allocator (), tcase.line,
461 std::size_t (-1), std::size_t (-1));
462}
463
464
467
468int main (int argc, char** argv)
469{
470 static const ContainerTest
471 tests [] = {
472
473#undef TEST
474#define TEST(sig) { \
475 Erase (sig), sig ## _test_cases, \
476 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
477 }
478
479 TEST (iter),
480 TEST (iter_iter),
481
482#undef TEST
483#define TEST(sig) { \
484 ListIds::sig ## _void, sig ## _test_cases, \
485 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
486 }
487
488 TEST (pop_front),
489 TEST (pop_back)
490 };
491
492 const std::size_t test_count = sizeof tests / sizeof *tests;
493
494 return rw_run_cont_test (argc, argv, __FILE__,
495 "lib.list.erase",
497 test_erase_func_array, tests, test_count);
498}
#define T
Definition 17.names.cpp:163
#define Distance
Definition 17.names.cpp:466
#define last
Definition 17.names.cpp:487
#define dist
Definition 17.names.cpp:464
#define index
Definition 17.names.cpp:482
#define iter_iter_test_cases
void test_erase()
#define TEST(str, off, size, res)
#define Erase(sig)
std::size_t _rw_distance(InputIterator first, InputIterator last)
void _rw_advance(InputIterator &it, Distance dist)
const int end
#define main
int caught
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
_TEST_EXPORT _RWSTD_SIZE_T rwt_check_leaks(_RWSTD_SIZE_T *, const rwt_free_store *)
Definition new.cpp:684
#define RW_ASSERT(expr)
static _RWSTD_SIZE_T n_total_dtor_
Definition rw_value.h:126
static _RWSTD_SIZE_T n_total_op_assign_
Definition rw_value.h:127
static bool is_total(_RWSTD_SIZE_T count, _RWSTD_SIZE_T n_def_ctor, _RWSTD_SIZE_T n_copy_ctor, _RWSTD_SIZE_T n_op_assign, _RWSTD_SIZE_T n_op_eq, _RWSTD_SIZE_T n_op_lt)
Definition value.cpp:419
static _RWSTD_SIZE_T count_
Definition rw_value.h:120
static void reset_totals()
Definition value.cpp:452
static _RWSTD_SIZE_T n_total_def_ctor_
Definition rw_value.h:124
static _RWSTD_SIZE_T n_total_copy_ctor_
Definition rw_value.h:125