Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
23.list.capacity.cpp
Go to the documentation of this file.
1
27#include <list> // for list
28#include <cstddef> // for size_t
29#include <stdexcept> // for exception
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 Size(sig) ListIds::size_ ## sig
41#define MaxSize(sig) ListIds::max_size_ ## sig
42#define Resize(sig) ListIds::resize_ ## sig
43#define Clear(sig) ListIds::clear_ ## sig
44#define Empty(sig) ListIds::empty_ ## sig
45
46static const char* const exceptions[] = {
47 "unknown exception", "bad_alloc", "exception"
48};
49
50
52// used to exercise
53// size ()
54static const ContainerTestCase
55size_void_test_cases [] = {
56
57#undef TEST
58#define TEST(str, res) { \
59 __LINE__, -1, -1, -1, -1, -1, \
60 str, sizeof str - 1, 0, 0, \
61 0, res, -1 \
62 }
63
64 // +--------------------------------------- controlled sequence
65 // | +------------------ expected result
66 // | |
67 // | |
68 // V V
69 TEST (0, 0),
70 TEST ("", 0),
71
72 TEST ("<U0>", 1),
73 TEST ("a", 1),
74 TEST (" ", 1),
75 TEST ("ab", 2),
76 TEST ("bc", 2),
77
78 TEST ("test string", 11),
79 TEST ("Test String", 11),
80
81 TEST ("t<U0> s", 4),
82 TEST ("Test<U0>string", 11),
83
84 TEST ("<U0>a<U0>b", 4),
85 TEST ("a<U0>@2b", 4),
86 TEST ("a<U0>@3b", 5),
87 TEST ("a<U0>@2b<U0>", 5),
88 TEST ("a<U0>b<U0>@2c", 6),
89 TEST ("a<U0>b<U0>c<U0>@2", 7),
90
91 TEST ("x@128", 128),
92 TEST ("x@207", 207),
93 TEST ("x@334", 334),
94 TEST ("x@540", 540),
95 TEST ("x@873", 873),
96 TEST ("x@1412", 1412),
97 TEST ("x@2284", 2284),
98 TEST ("x@3695", 3695),
99 TEST ("x@4096", 4096),
100
101 TEST ("last", 4)
102};
103
104
106// used to exercise
107// max_size ()
108static const ContainerTestCase
109max_size_void_test_cases [] = {
110
111#undef TEST
112#define TEST(str) { \
113 __LINE__, -1, -1, -1, -1, -1, \
114 str, sizeof str - 1, 0, 0, \
115 0, 0, -1 \
116 }
117
118 // +------------------------------ controlled sequence
119 // |
120 // |
121 // |
122 // V
123 TEST (0),
124 TEST (""),
125
126 TEST ("<U0>"),
127 TEST ("a"),
128
129 TEST ("test string"),
130 TEST ("a<U0>b<U0>c<U0>@2"),
131
132 TEST ("x@128"),
133 TEST ("x@207"),
134 TEST ("x@2284"),
135 TEST ("x@3695"),
136
137 TEST ("last")
138};
139
140
142// used to exercise
143// resize (size_type, value_type)
144static const ContainerTestCase
145resize_size_val_test_cases [] = {
146
147#undef TEST
148#define TEST(str, size, val, res, bthrow) { \
149 __LINE__, -1, size, -1, -1, val, \
150 str, sizeof str - 1, 0, 0, \
151 res, sizeof res - 1, bthrow \
152 }
153
154 // +------------------------------------------ controlled sequence
155 // | +------------------- new size
156 // | | +------------- value_type argument
157 // | | | +-------- expected result sequence
158 // | | | | +- exception info
159 // | | | | | 0 - no exception
160 // | | | | | 1 - length_error
161 // | | | | |
162 // | | | | +-----------+
163 // V V V V V
164 TEST ("", 0, 'a', "", 0),
165 TEST ("", 5, '\0', "<U0>@3<U0>@2", 0),
166 TEST ("", 334, 'x', "x@334", 0),
167
168 TEST ("<U0>", 0, 'a', "", 0),
169 TEST ("<U0>", 2, 'a', "<U0>a", 0),
170 TEST ("<U0>", 1, 'a', "<U0>", 0),
171 TEST ("<U0>", 128, 'a', "<U0>a@127", 0),
172
173 TEST ("a", 0, 'a', "", 0),
174 TEST ("a", 2, '\0', "a<U0>", 0),
175 TEST ("a", 540, 'a', "a@540", 0),
176
177 TEST ("a<U0>@3b", 10, 'a', "a<U0>@3baaaaa", 0),
178 TEST ("ab<U0>@3", 10, 'a', "ab<U0>@3aaaaa", 0),
179 TEST ("<U0>@3ab", 10, 'a', "<U0>@3abaaaaa", 0),
180 TEST ("a<U0>@3b", 7, '\0', "a<U0>@3b<U0>@2", 0),
181 TEST ("ab<U0>@3", 7, '\0', "ab<U0>@3<U0>@2", 0),
182 TEST ("<U0>@3ba", 7, '\0', "<U0>@3ba<U0>@2", 0),
183
184 TEST ("a<U0>b<U0>c<U0>@2", 6, 'a', "a<U0>b<U0>c<U0>", 0),
185 TEST ("a<U0>b<U0>c<U0>@2", 5, '\0', "a<U0>b<U0>c", 0),
186 TEST ("<U0>ba<U0>c<U0>@2", 1, '\0', "<U0>", 0),
187 TEST ("<U0>ba<U0>c<U0>@2", 0, '\0', "", 0),
188
189 TEST ("x@540", 127, 'a', "x@127", 0),
190 TEST ("x@873", 127, 'a', "x@127", 0),
191 TEST ("x@1412", 127, 'a', "x@127", 0),
192 TEST ("x@2284", 127, 'a', "x@127", 0),
193
194 TEST ("x@127", 128, 'a', "x@127a", 0),
195 TEST ("x@128", 207, 'a', "x@128a@79", 0),
196 TEST ("x@207", 334, 'a', "x@207a@127", 0),
197 TEST ("x@334", 540, 'a', "x@334a@206", 0),
198 TEST ("x@540", 873, 'a', "x@540a@333", 0),
199 TEST ("x@873", 1412, 'a', "x@873a@539", 0),
200 TEST ("x@1412", 2284, 'a', "x@1412a@872", 0),
201 TEST ("x@2284", 3695, 'a', "x@2284a@1411", 0),
202
203 TEST ("last", 4, 't', "last", 0)
204};
205
206
208// used to exercise
209// resize (size_type)
210static const ContainerTestCase
211resize_size_test_cases [] = {
212
213#undef TEST
214#define TEST(str, size, res, bthrow) { \
215 __LINE__, -1, size, -1, -1, -1, \
216 str, sizeof str - 1, 0, 0, \
217 res, sizeof res - 1, bthrow \
218 }
219
220 // +------------------------------------------ controlled sequence
221 // | +------------------- new size
222 // | | +-------------- expected result sequence
223 // | | | +-- exception info
224 // | | | | 0 - no exception
225 // | | | | 1 - length_error
226 // | | | |
227 // V V V V
228 TEST ("", 0, "", 0),
229 TEST ("", 5, "\0@5", 0),
230 TEST ("", 334, "\0@334", 0),
231
232 TEST ("<U0>", 0, "", 0),
233 TEST ("<U0>", 2, "\0@2", 0),
234 TEST ("<U0>", 1, "\0", 0),
235 TEST ("<U0>", 127, "\0@127", 0),
236
237 TEST ("a", 0, "", 0),
238 TEST ("a", 2, "a\0", 0),
239 TEST ("a", 539, "a\0@538", 0),
240
241 TEST ("a<U0>@3b", 10, "a<U0>@3b\0@5", 0),
242 TEST ("ab<U0>@3", 10, "ab<U0>@3\0@5", 0),
243 TEST ("<U0>@3ab", 10, "<U0>@3ab\0@5", 0),
244 TEST ("a<U0>@3b", 7, "a<U0>@3b\0@2", 0),
245 TEST ("ab<U0>@3", 7, "ab<U0>@3\0@2", 0),
246 TEST ("<U0>@3ba", 7, "<U0>@3ba\0@2", 0),
247
248 TEST ("a<U0>b<U0>c<U0>@2", 5, "a<U0>b<U0>c", 0),
249 TEST ("a<U0>b<U0>c<U0>@2", 4, "a<U0>b<U0>", 0),
250 TEST ("<U0>ba<U0>c<U0>@2", 1, "<U0>", 0),
251 TEST ("<U0>ba<U0>c<U0>@2", 0, "", 0),
252
253 TEST ("x@540", 127, "x@127", 0),
254 TEST ("x@873", 127, "x@127", 0),
255 TEST ("x@1412", 127, "x@127", 0),
256 TEST ("x@2284", 127, "x@127", 0),
257
258 TEST ("x@127", 128, "x@127\0", 0),
259 TEST ("x@128", 207, "x@128\0@79", 0),
260 TEST ("x@207", 334, "x@207\0@127", 0),
261 TEST ("x@334", 540, "x@334\0@206", 0),
262 TEST ("x@540", 873, "x@540\0@333", 0),
263 TEST ("x@873", 1412, "x@873\0@539", 0),
264 TEST ("x@1412", 2284, "x@1412\0@872", 0),
265 TEST ("x@2284", 3695, "x@2284\0@1411", 0),
266
267 TEST ("last", 4, "last", 0)
268};
269
270
272// used to exercise
273// clear ()
274static const ContainerTestCase
275clear_void_test_cases [] = {
276
277#undef TEST
278#define TEST(str) { \
279 __LINE__, -1, -1, -1, -1, -1, \
280 str, sizeof str - 1, 0, 0, \
281 "", 0, -1 \
282 }
283
284 // +------------------------------ controlled sequence
285 // |
286 // |
287 // |
288 // V
289 TEST (0),
290 TEST (""),
291
292 TEST ("<U0>"),
293 TEST ("a"),
294
295 TEST ("test string"),
296 TEST ("a<U0>b<U0>c<U0>@2"),
297
298 TEST ("x@128"),
299 TEST ("x@207"),
300 TEST ("x@334"),
301 TEST ("x@540"),
302 TEST ("x@873"),
303 TEST ("x@1412"),
304 TEST ("x@2284"),
305 TEST ("x@3695"),
306 TEST ("x@4096"),
307
308 TEST ("last")
309};
310
311
313// used to exercise
314// empty ()
315static const ContainerTestCase
316empty_void_test_cases [] = {
317
318#undef TEST
319#define TEST(str, res) { \
320 __LINE__, -1, -1, -1, -1, -1, \
321 str, sizeof str - 1, 0, 0, \
322 0, res, -1 \
323}
324
325 // +------------------------------ controlled sequence
326 // | +--------------- expected result
327 // | |
328 // | |
329 // V V
330 TEST (0, 1),
331 TEST ("", 1),
332
333 TEST ("<U0>", 0),
334 TEST ("a", 0),
335 TEST ("<U0>ab<U0>c", 0),
336
337 TEST ("x@128", 0),
338 TEST ("x@3695", 0),
339
340 TEST ("last", 0)
341};
342
343
345template <class T, class Allocator>
347 const ContainerTestCaseData<T> &tdata)
348{
349 typedef std::list<T, Allocator> List;
350 typedef typename List::iterator ListIter;
351 typedef typename List::const_iterator ListCIter;
353
354 const ContainerFunc &func = tdata.func_;
355 const ContainerTestCase &tcase = tdata.tcase_;
356
357 // construct the list object to be modified and constant one
358 List lst (tdata.str_, tdata.str_ + tdata.strlen_, Allocator ());
359 const List clst (tdata.str_, tdata.str_ + tdata.strlen_, Allocator ());
360
361 // save the state of the list object before the call
362 // to detect exception safety violations (changes to
363 // the state of the object after an exception)
364 const ListState lst_state (lst);
365
366 const T arg_val = T::from_char (-1 != tcase.val ? char (tcase.val) : char ());
367
368 rwt_free_store* const pst = rwt_get_free_store (0);
369 SharedAlloc* const pal = SharedAlloc::instance ();
370
371 // iterate for`throw_after' starting at the next call to operator new,
372 // forcing each call to throw an exception, until the function finally
373 // succeeds (i.e, no exception is thrown)
374 std::size_t throw_count;
375 for (throw_count = 0; ; ++throw_count) {
376
377 // (name of) expected and caught exception
378 const char* expected = 0;
379 const char* caught = 0;
380
381#ifndef _RWSTD_NO_EXCEPTIONS
382
383 if (0 == tcase.bthrow) {
384 // by default exercise the exception safety of the function
385 // by iteratively inducing an exception at each call to operator
386 // new or Allocator::allocate() until the call succeeds
387 expected = exceptions [1]; // bad_alloc
388 *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
389 pal->throw_at_calls_ [pal->m_allocate] =
390 pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
391 }
392 else {
393 // exceptions disabled for this test case
394 }
395
396#else // if defined (_RWSTD_NO_EXCEPTIONS)
397
398 if (tcase.bthrow) {
399 return;
400 }
401
402#endif // _RWSTD_NO_EXCEPTIONS
403
404 const bool is_class = ListIds::UserClass == func.elem_id_;
405
406 const std::size_t x_count_save = UserClass::count_;
407
408 // start checking for memory leaks
409 rw_check_leaks (lst.get_allocator ());
410
411 std::size_t res = 0;
412
413 try {
414
415 // reset function call counters
416 if (is_class)
418
419 switch (func.which_) {
420
421 case Size (void):
422 res = clst.size ();
423 break;
424
425 case MaxSize (void):
426 res = clst.max_size ();
427 break;
428
429 case Resize (size_val):
430 lst.resize (tcase.size, arg_val);
431 break;
432
433 case Resize (size):
434 lst.resize (tcase.size);
435 break;
436
437 case Clear (void):
438 lst.clear ();
439 break;
440
441 case Empty (void):
442 res = clst.empty () ? 1 : 0;
443 break;
444
445 default:
446 RW_ASSERT (!"test logic error: unknown capacity overload");
447 }
448
449 if (is_class
450 &&
451 (func.which_ == ListIds::clear_void
452 || func.which_ == ListIds::resize_size
453 || func.which_ == ListIds::resize_size_val)) {
454
455 std::size_t nctors = tdata.reslen_ > tdata.strlen_ ?
456 tdata.reslen_ - tdata.strlen_ : 0;
457
458 std::size_t ndtors = tdata.reslen_ < tdata.strlen_ ?
459 tdata.strlen_ - tdata.reslen_ : 0;
460
461 std::size_t new_count = x_count_save + nctors - ndtors;
462
463 std::size_t ndefctors = 0;
464
465 if (func.which_ == ListIds::resize_size_val)
466 ++nctors;
467 else if (func.which_ == ListIds::resize_size)
468 ++ndefctors;
469
470 bool success = UserClass::is_total (new_count, ndefctors,
471 nctors, 0, 0, 0);
472 rw_assert (success, 0, tcase.line,
473 "line %d. %{$FUNCALL} called default/copy ctor "
474 "and operator=() %zu, %zu, and %zu times, "
475 "respectively, %zu, %zu, 0 expected",
476 __LINE__,
480 ndefctors, nctors);
481 }
482
483 // verify the returned value
484 if (func.which_ == ListIds::size_void
485 || func.which_ == ListIds::empty_void) {
486 rw_assert (res == tcase.nres, 0, tcase.line,
487 "line %d. %{$FUNCALL} expected %zu, got %zu",
488 __LINE__, tcase.nres, res);
489 }
490
491 if (func.which_ == ListIds::max_size_void) {
492 std::size_t cur_sz = clst.size ();
493
494 rw_assert (cur_sz <= res, 0, tcase.line,
495 "line %d. %{$FUNCALL} == %zu, expected res > %zu",
496 __LINE__, res, cur_sz);
497 }
498
499 if (func.which_ == ListIds::resize_size_val
500 || func.which_ == ListIds::resize_size
501 || func.which_ == ListIds::clear_void) {
502
503 // for convenience
504 static const int cwidth = sizeof (T);
505
506 const std::size_t got_size = lst.size ();
507 char* const got = new char [got_size + 1];
508
509 std::size_t index = 0;
510 for (ListCIter it = lst.begin (),
511 end = lst.end (); it != end; ++it) {
512 got [index++] = char (it->data_.val_);
513 }
514
515 got [got_size] = '\0';
516
517 // verify that strings length are equal
518 rw_assert (tdata.reslen_ == got_size, 0, tcase.line,
519 "line %d. %{$FUNCALL} expected \"%{X=*}\" "
520 "with length %zu, got %{/*.*Gs} with length %zu",
521 __LINE__, cwidth, int (tdata.reslen_),
522 tdata.res_, tdata.reslen_,
523 1, int (got_size), got, got_size);
524
525 if (tdata.reslen_ == got_size) {
526 // if the result length matches the expected length
527 // (and only then), also verify that the modified
528 // list matches the expected result
529 const std::size_t match = rw_match (tcase.res,
530 got, got_size);
531
532 rw_assert (match == tdata.reslen_, 0, tcase.line,
533 "line %d. %{$FUNCALL} expected \"%{X=*}\", "
534 "got %{/*.*Gs}, difference at offset %zu",
535 __LINE__,
536 cwidth, int (tdata.reslen_), tdata.res_,
537 1, int (got_size), got, match);
538 }
539
540 delete [] got;
541 }
542 }
543
544#ifndef _RWSTD_NO_EXCEPTIONS
545
546 catch (const std::bad_alloc &ex) {
547 caught = exceptions [1];
548 rw_assert (0 == tcase.bthrow, 0, tcase.line,
549 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
550 "unexpectedly%{;} caught std::%s(%#s)",
551 __LINE__, 0 != expected, expected, caught, ex.what ());
552 }
553 catch (const std::exception &ex) {
554 caught = exceptions [2];
555 rw_assert (0, 0, tcase.line,
556 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
557 "unexpectedly%{;} caught std::%s(%#s)",
558 __LINE__, 0 != expected, expected, caught, ex.what ());
559 }
560 catch (...) {
561 caught = exceptions [0];
562 rw_assert (0, 0, tcase.line,
563 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
564 "unexpectedly%{;} caught %s",
565 __LINE__, 0 != expected, expected, caught);
566 }
567
568#endif // _RWSTD_NO_EXCEPTIONS
569
570 // FIXME: verify the number of blocks the function call
571 // is expected to allocate and detect any memory leaks
572 rw_check_leaks (lst.get_allocator (), tcase.line,
573 std::size_t (-1), std::size_t (-1));
574
575 if (caught) {
576 // verify that an exception thrown during allocation
577 // didn't cause a change in the state of the object
578 lst_state.assert_equal (ListState (lst),
579 __LINE__, tcase.line, caught);
580
581 if (0 == tcase.bthrow) {
582 // allow this call to operator new to succeed and try
583 // to make the next one to fail during the next call
584 // to the same function again
585 continue;
586 }
587 }
588
589 break;
590 }
591
592 // disable bad_alloc exceptions
593 *pst->throw_at_calls_ [0] = 0;
594 pal->throw_at_calls_ [pal->m_allocate] = 0;
595}
596
597
600
601int main (int argc, char** argv)
602{
603 static const ContainerTest
604 tests [] = {
605
606#undef TEST
607#define TEST(gsig, sig) { \
608 gsig, sig ## _test_cases, \
609 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
610}
611
612 TEST (ListIds::size_void, size_void),
613 TEST (ListIds::max_size_void, max_size_void),
614 TEST (ListIds::resize_size_val, resize_size_val),
615 TEST (ListIds::resize_size, resize_size),
616 TEST (ListIds::clear_void, clear_void),
617 TEST (ListIds::empty_void, empty_void)
618 };
619
620 const std::size_t test_count = sizeof tests / sizeof *tests;
621
622 return rw_run_cont_test (argc, argv, __FILE__,
623 "lib.list.capacity",
625 test_capacity_func_array, tests, test_count);
626}
#define T
Definition 17.names.cpp:163
#define res
Definition 17.names.cpp:531
#define index
Definition 17.names.cpp:482
#define Size(sig)
#define TEST(str, res)
#define Clear(sig)
#define MaxSize(sig)
#define Resize(sig)
void test_capacity(T *, Allocator *, const ContainerTestCaseData< T > &tdata)
#define Empty(sig)
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 _RWSTD_SIZE_T rw_match(const char *, const char *, _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 rwt_free_store * rwt_get_free_store(rwt_free_store *)
Definition new.cpp:597
#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
static SharedAlloc * instance(SharedAlloc *=0)
_RWSTD_SIZE_T throw_at_calls_[n_funs]
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