Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
23.list.assign.cpp
Go to the documentation of this file.
1
27#include <list> // for list
28#include <cstddef> // for size_t
29
30#include <rw_lists.h> // for ListMembers
31#include <rw_alg_test.h> // for InputIter
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
38// for convenience and brevity
39#define Assign(sig) ListIds::assign_ ## sig
40
41static const char* const exceptions[] = {
42 "unknown exception", "bad_alloc", "exception"
43};
44
45
47// used to exercise:
48// assign (InputIterator, InputIterator)
49static const ContainerTestCase
51
52#undef TEST
53#define TEST(lst, arg, off, size, res, bthrow) { \
54 __LINE__, -1, -1, off, size, -1, \
55 lst, sizeof lst - 1, \
56 arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
57 }
58
59 // +------------------------------------------ controlled sequence
60 // | +------------------------- sequence to be inserted
61 // | | +------------ assign() pos argument
62 // | | | +--------- assign() n argument
63 // | | | | +------ expected result sequence
64 // | | | | | +--- exception info
65 // | | | | | | 0 - no exception
66 // | | | | | | 1 - out_of_range
67 // | | | | | | 2 - length_error
68 // | | | | | | -1 - exc. safety
69 // | | | | | |
70 // | | | | | +--------------------+
71 // | | | | +------+ |
72 // | | | +------+ | |
73 // | | +---+ | | |
74 // | | | | | |
75 // | | | | | |
76 // V V V V V V
77 TEST ("ab", "c", 0, 1, "c", 0),
78
79 TEST ("", "", 0, 0, "", 0),
80 TEST ("", "abc", 1, 1, "b", 0),
81 TEST ("", "<U0>", 0, 1, "<U0>", 0),
82
83 TEST ("<U0>", "", 0, 0, "", 0),
84
85 TEST ("abc", "", 0, 0, "", 0),
86
87 TEST ("<U0>", "a", 0, 1, "a", 0),
88 TEST ("<U0>", "<U0>@2", 1, 1, "<U0>", 0),
89 TEST ("<U0>", "<U0>@2", 0, 2, "<U0>@2", 0),
90 TEST ("<U0>", "<U0>@2", 1, 5, "<U0>", 0),
91
92 TEST ("cde", "ab", 0, 2, "ab", 0),
93 TEST ("cde", "ab", 0, 1, "a", 0),
94 TEST ("cde", "ab", 1, 5, "b", 0),
95
96 TEST ("ab", "c<U0>e", 0, 3, "c<U0>e", 0),
97 TEST ("ab", "c<U0>e", 1, 2, "<U0>e", 0),
98 TEST ("ab", "c<U0>e", 0, 2, "c<U0>", 0),
99
100 TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 9, "<U0>ab<U0>@2c", 0),
101 TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 3, "<U0>ab", 0),
102 TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 0, 3, "<U0>e<U0>", 0),
103 TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 0, 2, "<U0>@2", 0),
104 TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 2, 1, "<U0>", 0),
105 TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 2, 9, "<U0>", 0),
106 TEST ("a<U0>bc<U0>@2", "<U0>e", 0, 2, "<U0>e", 0),
107
108 TEST ("x@4096", "", 0, 0, "", 0),
109 TEST ("", "x@4096", 9, 2, "xx", 0),
110 TEST ("", "x@4096", 9, 0, "", 0),
111 TEST ("abc", "x@4096", 2, 1, "x", 0),
112 TEST ("x@4096", "x@4096", 2, 3, "xxx", 0),
113 TEST ("", "x@4096", 0, 4096, "x@4096", 0),
114 TEST ("", "x@4096", 100, 2000, "x@2000", 0),
115
116 TEST ("", "x@207", 0, 207, "x@207", 0),
117 TEST ("x@128", "x@334", 10, 207, "x@207", 0),
118 TEST ("x@540", "x@207", 50, 128, "x@128", 0),
119 TEST ("", "x@1412", 128, 873, "x@873", 0),
120 TEST ("x@128", "x@1412", 0, 1412, "x@1412", 0),
121 TEST ("x@3695", "x@1412", 207, 540, "x@540", 0),
122 TEST ("x@872", "x@874", 1, 873, "x@873", 0),
123 TEST ("x@873", "x@3695", 10, 2284, "x@2284", 0),
124
125 TEST ("", "<U0>", 2, 0, "", 1),
126 TEST ("", "a", 2, 0, "", 1),
127 TEST ("", "x@4096", 4106, 0, "", 1),
128
129 TEST ("last", "test", 0, 4, "test", 0)
130};
131
132
134// used to exercise:
135// assign (size_type, const value_type&)
136static const ContainerTestCase
137size_cref_test_cases [] = {
138
139#undef TEST
140#define TEST(lst, size, val, res, bthrow) { \
141 __LINE__, -1, size, -1, -1, val, \
142 lst, sizeof lst - 1, \
143 0, 0, res, sizeof res - 1, bthrow \
144 }
145
146 // +----------------------------------------- controlled sequence
147 // | +------------------------ assign() count argument
148 // | | +-------------------- character to be assigned
149 // | | | +---------------- expected result sequence
150 // | | | | +-------- exception info
151 // | | | | | 0 - no exception
152 // | | | | | 1 - out_of_range
153 // | | | | | 2 - length_error
154 // | | | | | -1 - exc. safety
155 // | | | | |
156 // | | | | +--------+
157 // V V V V V
158 TEST ("ab", 1, 'c', "c", 0),
159
160 TEST ("", 0, ' ', "", 0),
161 TEST ("", 1, 'b', "b", 0),
162 TEST ("", 3, 'b', "bbb", 0),
163
164 TEST ("<U0>", 0, ' ', "", 0),
165 TEST ("", 2, '\0', "<U0>@2", 0),
166
167 TEST ("<U0>", 1, 'a', "a", 0),
168 TEST ("<U0>", 1, '\0', "<U0>", 0),
169 TEST ("<U0>", 2, '\0', "<U0>@2", 0),
170 TEST ("<U0>", 0, '\0', "", 0),
171
172 TEST ("cde", 3, 'a', "aaa", 0),
173 TEST ("ab", 2, '\0', "<U0>@2", 0),
174 TEST ("ab", 1, '\0', "<U0>", 0),
175
176 TEST ("a<U0>b<U0>@2c", 2, '\0', "<U0>@2", 0),
177 TEST ("a<U0>b<U0>@2c", 1, '\0', "<U0>", 0),
178 TEST ("<U0>ab<U0>@2c", 3, '\0', "<U0>@3", 0),
179 TEST ("a<U0>bc<U0>@2", 2, 'a', "aa", 0),
180
181 TEST ("", 4096, 'x', "x@4096", 0),
182 TEST ("x@4096", 0, 'x', "", 0),
183
184 TEST ("x@127", 128, 'x', "x@128", 0),
185 TEST ("x@200", 207, 'x', "x@207", 0),
186 TEST ("x@334", 128, 'x', "x@128", 0),
187 TEST ("", 540, 'x', "x@540", 0),
188 TEST ("xx", 873, 'x', "x@873", 0),
189 TEST ("x@873", 1412, 'x', "x@1412", 0),
190 TEST ("x@3695", 207, 'x', "x@207", 0),
191 TEST ("x@540", 3695, 'x', "x@3695", 0),
192
193 TEST ("last", 4, 't', "tttt", 0)
194};
195
196
198template <class InputIterator, class Distance>
199inline void
201
202 while (0 < dist) {
203 --dist;
204 ++it;
205 }
206}
207
208// invokes specializations of the member function template
209// on the required iterator categories
210template <class List, class Iterator>
212
213 typedef typename List::iterator ListIter;
214 typedef typename List::value_type ListVal;
215
217
218 virtual List&
219 operator() (List &lst,
220 const ContainerTestCaseData<ListVal>& tdata) const {
221
222 const ListVal* const beg = tdata.arg_ + tdata.off2_;
223 const ListVal* const end = beg + tdata.ext2_;
224
225 const Iterator first (beg, beg, end);
226 const Iterator last (end, beg, end);
227
228 lst.assign (first, last);
229 return lst;
230 }
231};
232
233
235// invokes possible overloads of the member function template
236// on common RandomAccessIterator types
237template <class List, class Iterator>
239{
240 typedef typename List::iterator ListIter;
241 typedef typename List::value_type ListVal;
242
244
245 virtual List&
246 operator() (List &lst,
247 const ContainerTestCaseData<ListVal>& tdata) const {
248
249 const bool reverse_iter =
252
253 const std::size_t off = tdata.arglen_ - tdata.off2_ - tdata.ext2_;
254
255 List str_arg (tdata.arg_, tdata.arg_ + tdata.arglen_);
256
257 Iterator first (this->begin (str_arg, (Iterator*)0));
258 _rw_advance (first, reverse_iter ? off : tdata.off2_);
259
260 Iterator last (first);
261 _rw_advance (last, tdata.ext2_);
262
263 lst.assign (first, last);
264 return lst;
265 }
266};
267
268
270// invokes specializations of the member function template
271// on the required iterator categories
272template <class List, class Iterator>
274
275 typedef typename List::value_type ListVal;
276
278
279 virtual List&
280 operator() (List& lst,
281 const ContainerTestCaseData<ListVal>& tdata) const {
282
283 const ListVal* const beg = tdata.arg_ + tdata.off2_;
284 const ListVal* const end = beg + tdata.ext2_;
285
286 const Iterator first = _RWSTD_CONST_CAST (Iterator, beg);
288
289 lst.assign (first, last);
290 return lst;
291 }
292};
293
294
296template <class T, class Allocator>
298 const ContRangeBase< std::list <T, Allocator> > &rng,
299 const ContainerTestCaseData<T> &tdata)
300{
301 typedef std::list <T, Allocator> List;
302 typedef typename List::iterator ListIter;
303 typedef typename List::const_iterator ListCIter;
305
306 const ContainerFunc &func = tdata.func_;
307 const ContainerTestCase &tcase = tdata.tcase_;
308
309 // construct the list object to be modified
310 List lst (tdata.str_, tdata.str_ + tdata.strlen_);
311
312 std::size_t size = tcase.size >= 0 ? tcase.size : 0;
313
314 rwt_free_store* const pst = rwt_get_free_store (0);
315 SharedAlloc* const pal = SharedAlloc::instance ();
316
317 // iterate for`throw_after' starting at the next call to operator new,
318 // forcing each call to throw an exception, until the function finally
319 // succeeds (i.e, no exception is thrown)
320 std::size_t throw_count;
321 for (throw_count = 0; ; ++throw_count) {
322
323 // (name of) expected and caught exception
324 const char* expected = 0;
325 const char* caught = 0;
326
327#ifndef _RWSTD_NO_EXCEPTIONS
328
329 if (0 == tcase.bthrow) {
330 // by default exercise the exception safety of the function
331 // by iteratively inducing an exception at each call to operator
332 // new or Allocator::allocate() until the call succeeds
333 expected = exceptions [1]; // bad_alloc
334 *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
335 pal->throw_at_calls_ [pal->m_allocate] =
336 pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
337 }
338 else {
339 // exceptions disabled for this test case
340 }
341
342#else // if defined (_RWSTD_NO_EXCEPTIONS)
343
344 if (tcase.bthrow)
345 return;
346
347#endif // _RWSTD_NO_EXCEPTIONS
348
349 // start checking for memory leaks
350 rw_check_leaks (lst.get_allocator ());
351
352 try {
353 switch (func.which_) {
354
355 case Assign (size_cref): {
356 const T val = T::from_char (char (tcase.val));
357 lst.assign (size, val);
358 break;
359 }
360
361 case Assign (range):
362 rng (lst, tdata);
363 break;
364
365 default:
366 RW_ASSERT (!"test logic error: unknown assign overload");
367 }
368
369 // for convenience
370 static const int cwidth = sizeof (T);
371
372 const std::size_t got_size = lst.size ();
373 char* const got = new char [got_size + 1];
374
375 std::size_t index = 0;
376 for (ListCIter it = lst.begin (),
377 end = lst.end (); it != end; ++it) {
378 got [index++] = char (it->data_.val_);
379 }
380
381 got [got_size] = '\0';
382
383 // verify that list length are equal to the expected
384 rw_assert (tdata.reslen_ == got_size, 0, tcase.line,
385 "line %d. %{$FUNCALL}: expected \"%{X=*}\" with length "
386 "%zu, got %{/*.*Gs} with length %zu", __LINE__,
387 cwidth, int (tdata.reslen_), tdata.res_, tdata.reslen_,
388 1, int (got_size), got, got_size);
389
390 if (tdata.reslen_ == got_size) {
391 // if the result length matches the expected length
392 // (and only then), also verify that the modified
393 // list matches the expected result
394 const std::size_t match =
395 rw_match (tcase.res, got, got_size);
396
397 rw_assert (match == tdata.reslen_, 0, tcase.line,
398 "line %d. %{$FUNCALL}: expected \"%{X=*}\", "
399 "got %{/*.*Gs}, difference at off %zu",
400 __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
401 1, int (got_size), got, match);
402 }
403
404 delete [] got;
405 }
406
407#ifndef _RWSTD_NO_EXCEPTIONS
408
409 catch (const std::bad_alloc &ex) {
410 caught = exceptions [1];
411 rw_assert (0 == tcase.bthrow, 0, tcase.line,
412 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
413 "unexpectedly%{;} caught std::%s(%#s)",
414 __LINE__, 0 != expected, expected, caught, ex.what ());
415 }
416 catch (const std::exception &ex) {
417 caught = exceptions [2];
418 rw_assert (0, 0, tcase.line,
419 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
420 "unexpectedly%{;} caught std::%s(%#s)",
421 __LINE__, 0 != expected, expected, caught, ex.what ());
422 }
423 catch (...) {
424 caught = exceptions [0];
425 rw_assert (0, 0, tcase.line,
426 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
427 "unexpectedly%{;} caught %s",
428 __LINE__, 0 != expected, expected, caught);
429 }
430
431#endif // _RWSTD_NO_EXCEPTIONS
432
433 // FIXME: verify the number of blocks the function call
434 // is expected to allocate and detect any memory leaks
435 rw_check_leaks (lst.get_allocator (), tcase.line,
436 std::size_t (-1), std::size_t (-1));
437
438 if (caught) {
439 if (0 == tcase.bthrow && caught == exceptions [1]) {
440 // allow this call to operator new to succeed and try
441 // to make the next one to fail during the next call
442 // to the same function again
443 continue;
444 }
445 }
446 else if (0 < tcase.bthrow) {
447 rw_assert (caught == expected, 0, tcase.line,
448 "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
449 "%{:}unexpectedly caught %s%{;}",
450 __LINE__, 0 != expected, expected, caught, caught);
451 }
452
453 break;
454 }
455
456 // disable bad_alloc exceptions
457 *pst->throw_at_calls_ [0] = 0;
458 pal->throw_at_calls_ [pal->m_allocate] = 0;
459}
460
461
463template <class T, class Allocator>
465 const ContainerTestCaseData<T> &tdata)
466{
467 typedef std::list<T, Allocator> List;
468
469 if (tdata.func_.which_ == Assign (range)) {
470
471 switch (tdata.func_.iter_id_) {
472
473 // exercise possible overloads of the member function template
474 // on common RandomAccessIterator types
475#undef TEST
476#define TEST(Iterator) do { \
477 typedef typename List::Iterator Iter; \
478 static const \
479 AssignRangePtrOverload<List, Iter> rng; \
480 test_assign ((T*)0, (Allocator*)0, rng, tdata); \
481 } while (0)
482
483 case ListIds::Pointer: TEST (pointer); break;
484 case ListIds::ConstPointer: TEST (const_pointer); break;
485
486#undef TEST
487#define TEST(Iterator) do { \
488 typedef typename List::Iterator Iter; \
489 static const \
490 AssignRangeOverload<List, Iter> rng; \
491 test_assign ((T*)0, (Allocator*)0, rng, tdata); \
492 } while (0)
493
494 case ListIds::Iterator: TEST (iterator); break;
495 case ListIds::ConstIterator: TEST (const_iterator); break;
496
497 case ListIds::ReverseIterator: TEST (reverse_iterator); break;
498 case ListIds::ConstReverseIterator: TEST (const_reverse_iterator);
499 break;
500
501 // exercise specializations of the member function template
502 // on the required iterator categories
503
504#undef TEST
505#define TEST(Iterator) do { \
506 typedef Iterator<T> Iter; \
507 static const \
508 AssignRange<List, Iter> rng; \
509 test_assign ((T*)0, (Allocator*)0, rng, tdata); \
510 } while (0)
511
512 case ListIds::Input: TEST (InputIter); break;
513 case ListIds::Forward: TEST (ConstFwdIter); break;
514 case ListIds::Bidir: TEST (ConstBidirIter); break;
516
517 default:
518 rw_error (0, 0, __LINE__, "bad iterator id");
519 }
520 }
521 else {
522 // exercise ordinary overloads of the member function
523 static const ContRangeBase<List> rng;
524 test_assign ((T*)0, (Allocator*)0, rng, tdata);
525 }
526}
527
528
531
532int main (int argc, char** argv)
533{
534 static const ContainerTest
535 tests [] = {
536
537#undef TEST
538#define TEST(sig) { \
539 Assign (sig), sig ## _test_cases, \
540 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
541 }
542
543 TEST (size_cref),
544 TEST (range)
545 };
546
547 const std::size_t test_count = sizeof tests / sizeof *tests;
548
549 const int status =
550 rw_run_cont_test (argc, argv, __FILE__,
551 "lib.list.assign",
553 test_assign_func_array, tests, test_count);
554
555 return status;
556}
#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 off
Definition 17.names.cpp:507
#define val
Definition 17.names.cpp:570
#define range_test_cases
void test_assign()
#define Assign(sig)
#define TEST(lst, arg, off, size, res, bthrow)
void _rw_advance(InputIterator &it, Distance dist)
const int end
#define main
int caught
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
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 int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_TEST_EXPORT rwt_free_store * rwt_get_free_store(rwt_free_store *)
Definition new.cpp:597
#define RW_ASSERT(expr)
List::value_type ListVal
virtual List & operator()(List &lst, const ContainerTestCaseData< ListVal > &tdata) const
List::iterator ListIter
virtual List & operator()(List &lst, const ContainerTestCaseData< ListVal > &tdata) const
List::iterator ListIter
virtual List & operator()(List &lst, const ContainerTestCaseData< ListVal > &tdata) const
List::value_type ListVal
static ContIter begin(List &cont, ContIter *)
_RWSTD_SIZE_T which_
ContainerIds::IteratorId iter_id_
static SharedAlloc * instance(SharedAlloc *=0)
_RWSTD_SIZE_T throw_at_calls_[n_funs]
_RWSTD_SIZE_T * throw_at_calls_[2]
Definition rw_new.h:83
_RWSTD_SIZE_T new_calls_[2]
Definition rw_new.h:47