Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
21.string.cons.cpp
Go to the documentation of this file.
1
27#include <string> // for string
28#include <stdexcept> // for out_of_range, length_error
29#include <cstddef> // for size_t
30
31#include <rw_strings.h>
32#include <rw_alg_test.h> // for InputIter
33#include <rw_driver.h> // for rw_test()
34#include <rw_allocator.h> // for UserAlloc
35#include <rw_char.h> // for rw_expand()
36#include <rw_new.h> // for bad_alloc, replacement operator new
37
38
40// for convenience and brevity
41#define Cons(sig) StringIds::ctor_ ## sig
42#define OpSet(sig) StringIds::op_set_ ## sig
43
44static const char* const exceptions[] = {
45 "unknown exception", "out_of_range", "length_error",
46 "bad_alloc", "exception"
47};
48
49
51// exercises:
52// basic_string (void)
53static const StringTestCase
54void_test_cases [] = {
55
56#define alloc_test_cases void_test_cases
57
58#undef TEST
59#define TEST(dummy) { \
60 __LINE__, -1, -1, -1, -1, -1, \
61 0, 0, dummy, sizeof dummy - 1, \
62 "", 0, 0 \
63 }
64
65 // +--------------------- dummy argument
66 // |
67 // V
68 TEST ("ab"),
69
70 TEST ("last test")
71};
72
73
75// exercises:
76// basic_string (const value_type*)
77static const StringTestCase
78cptr_test_cases [] = {
79
80#define cptr_alloc_test_cases cptr_test_cases
81
82#undef TEST
83#define TEST(arg, res) { \
84 __LINE__, -1, -1, -1, -1, -1, \
85 0, 0, arg, sizeof arg - 1, \
86 res, sizeof res - 1, 0 \
87 }
88
89 // +----------------------------------------- source sequence
90 // | +------------------------- expected result sequence
91 // | |
92 // | |
93 // V V
94 TEST ("ab", "ab"),
95
96 TEST ("", ""),
97 TEST ("<U0>", ""),
98
99 TEST ("a", "a"),
100 TEST ("bcd", "bcd"),
101 TEST ("cdefaihjb", "cdefaihjb"),
102
103 TEST ("<U0>@2ab", ""),
104 TEST ("a<U0>@2b", "a"),
105 TEST ("ab<U0>@2", "ab"),
106 TEST ("abefdcc<U0>a", "abefdcc"),
107
108 TEST ("x@128", "x@128"),
109 TEST ("x@207", "x@207"),
110 TEST ("x@334", "x@334"),
111 TEST ("x@540", "x@540"),
112 TEST ("x@873", "x@873"),
113 TEST ("x@1412", "x@1412"),
114 TEST ("x@3695", "x@3695"),
115 TEST ("x@4096", "x@4096"),
116
117 TEST ("last test", "last test")
118};
119
120
122// exercises:
123// basic_string (const basic_string&)
124static const StringTestCase
125cstr_test_cases [] = {
126
127#undef TEST
128#define TEST(arg, res) { \
129 __LINE__, -1, -1, -1, -1, -1, \
130 0, 0, arg, sizeof arg - 1, \
131 res, sizeof res - 1, 0 \
132 }
133
134 // +----------------------------------------- source sequence
135 // | +------------------------- expected result sequence
136 // | |
137 // | |
138 // V V
139 TEST ("ab", "ab"),
140
141 TEST ("", ""),
142 TEST ("<U0>", "<U0>"),
143 TEST ("<U0>@2", "<U0>@2"),
144
145 TEST ("a", "a"),
146 TEST ("bcd", "bcd"),
147 TEST ("cdefaihjb", "cdefaihjb"),
148
149 TEST ("<U0>@2ab", "<U0>@2ab"),
150 TEST ("a<U0>@2b", "a<U0>@2b"),
151 TEST ("ab<U0>@2", "ab<U0>@2"),
152 TEST ("abefdcc<U0>a", "abefdcc<U0>a"),
153
154 TEST ("x@128", "x@128"),
155 TEST ("x@207", "x@207"),
156 TEST ("x@334", "x@334"),
157 TEST ("x@540", "x@540"),
158 TEST ("x@873", "x@873"),
159 TEST ("x@1412", "x@1412"),
160 TEST ("x@3695", "x@3695"),
161 TEST ("x@4096", "x@4096"),
162
163 TEST ("last test", "last test")
164};
165
166
168// exercises:
169// basic_string (const value_type*, size_type)
170static const StringTestCase
171cptr_size_test_cases [] = {
172
173#define cptr_size_alloc_test_cases cptr_size_test_cases
174
175#undef TEST
176#define TEST(arg, size, res) { \
177 __LINE__, -1, size, -1, -1, -1, \
178 0, 0, arg, sizeof arg - 1, \
179 res, sizeof res - 1, 0 \
180 }
181
182 // +----------------------------------------- source sequence
183 // | +------------------------- ctor n argument
184 // | | +---------------------- expected result sequence
185 // | | |
186 // | | |
187 // V V V
188 TEST ("ab", 2, "ab"),
189
190 TEST ("", 0, ""),
191 TEST ("<U0>", 1, "<U0>"),
192
193 TEST ("a", 1, "a"),
194 TEST ("bcd", 3, "bcd"),
195 TEST ("cdefaihjb", 9, "cdefaihjb"),
196
197 TEST ("<U0>@2ab", 1, "<U0>"),
198 TEST ("<U0>@2ab", 4, "<U0>@2ab"),
199 TEST ("a<U0>@2b", 4, "a<U0>@2b"),
200 TEST ("ab<U0>@2", 3, "ab<U0>"),
201 TEST ("abefdcc<U0>a", 7, "abefdcc"),
202 TEST ("abefdcc<U0>a", 8, "abefdcc<U0>"),
203 TEST ("abefdcc<U0>a", 9, "abefdcc<U0>a"),
204
205 TEST ("x@207", 207, "x@207"),
206 TEST ("x@334", 207, "x@207"),
207 TEST ("x@207", 128, "x@128"),
208 TEST ("x@1412", 873, "x@873"),
209 TEST ("x@1412", 1412, "x@1412"),
210 TEST ("x@1412", 540, "x@540"),
211 TEST ("x@873", 873, "x@873"),
212 TEST ("x@3695", 2284, "x@2284"),
213 TEST ("x@4096", 4096, "x@4096"),
214
215 TEST ("last test", 9, "last test")
216};
217
218
220// exercises:
221// basic_string (const basic_string&, size_type)
222static const StringTestCase
223cstr_size_test_cases [] = {
224
225#undef TEST
226#define TEST(arg, off, res, bthrow) { \
227 __LINE__, off, -1, -1, -1, -1, \
228 0, 0, arg, sizeof arg - 1, \
229 res, sizeof res - 1, bthrow \
230 }
231
232 // +----------------------------------------- source sequence
233 // | +------------------------- ctor off argument
234 // | | +---------------------- expected result sequence
235 // | | | +------ exception info
236 // | | | | 0 - no exception
237 // | | | | 1 - out_of_range
238 // | | | |
239 // | | | |
240 // V V V V
241 TEST ("ab", 0, "ab", 0),
242
243 TEST ("", 0, "", 0),
244 TEST ("<U0>", 0, "<U0>", 0),
245 TEST ("<U0>@2", 0, "<U0>@2", 0),
246 TEST ("<U0>@2", 1, "<U0>", 0),
247 TEST ("<U0>@2", 2, "", 0),
248
249 TEST ("a", 0, "a", 0),
250 TEST ("bcd", 0, "bcd", 0),
251 TEST ("cdefaihjb", 0, "cdefaihjb", 0),
252
253 TEST ("<U0>@2ab", 0, "<U0>@2ab", 0),
254 TEST ("<U0>@2ab", 1, "<U0>ab", 0),
255 TEST ("a<U0>@2b", 0, "a<U0>@2b", 0),
256 TEST ("a<U0>@2b", 1, "<U0>@2b", 0),
257 TEST ("a<U0>@2b", 2, "<U0>b", 0),
258 TEST ("ab<U0>@2", 0, "ab<U0>@2", 0),
259 TEST ("ab<U0>@2", 2, "<U0>@2", 0),
260 TEST ("ab<U0>@2", 4, "", 0),
261 TEST ("abefdcc<U0>a", 0, "abefdcc<U0>a", 0),
262 TEST ("abefdcc<U0>a", 7, "<U0>a", 0),
263
264 TEST ("x@207", 0, "x@207", 0),
265 TEST ("x@334", 127, "x@207", 0),
266 TEST ("x@1412", 872, "x@540", 0),
267 TEST ("x@1412", 0, "x@1412", 0),
268 TEST ("x@1412", 539, "x@873", 0),
269 TEST ("x@873", 0, "x@873", 0),
270 TEST ("x@3695", 0, "x@3695", 0),
271 TEST ("x@4096", 0, "x@4096", 0),
272
273 TEST ("abc", 5, "abc", 1),
274 TEST ("x@4096", 4106, "x@4096", 1),
275
276 TEST ("last test", 0, "last test", 0)
277};
278
279
281// exercises:
282// basic_string (const basic_string&, size_type, size_type)
283// basic_string (InputIterator, InputIterator)
284static const StringTestCase
286
287#define range_test_cases cstr_size_size_test_cases
288#define cstr_size_size_alloc_test_cases cstr_size_size_test_cases
289#define range_alloc_test_cases cstr_size_size_test_cases
290
291#undef TEST
292#define TEST(arg, off, size, res, bthrow) { \
293 __LINE__, -1, -1, off, size, -1, \
294 0, 0, arg, sizeof arg - 1, \
295 res, sizeof res - 1, bthrow \
296 }
297
298 // +----------------------------------------- source sequence
299 // | +------------------------- ctor off argument
300 // | | +--------------------- ctor n argument
301 // | | | +---------------- expected result sequence
302 // | | | | +--- exception info
303 // | | | | | 0 - no exception
304 // | | | | | 1 - out_of_range
305 // | | | | |
306 // | | | | |
307 // V V V V V
308 TEST ("ab", 0, 2, "ab", 0),
309
310 TEST ("", 0, 0, "", 0),
311 TEST ("<U0>", 0, 1, "<U0>", 0),
312 TEST ("<U0>@2", 0, 2, "<U0>@2", 0),
313
314 TEST ("a", 0, 1, "a", 0),
315 TEST ("bcd", 0, 3, "bcd", 0),
316 TEST ("cdefaihjb", 0, 9, "cdefaihjb", 0),
317
318 TEST ("<U0>@2ab", 0, 4, "<U0>@2ab", 0),
319 TEST ("a<U0>@2b", 0, 4, "a<U0>@2b", 0),
320 TEST ("ab<U0>@2", 0, 4, "ab<U0>@2", 0),
321 TEST ("abefdcc<U0>a", 0, 9, "abefdcc<U0>a", 0),
322
323 TEST ("x@207", 0, 207, "x@207", 0),
324 TEST ("x@334", 10, 207, "x@207", 0),
325 TEST ("x@207", 50, 128, "x@128", 0),
326 TEST ("x@1412", 128, 873, "x@873", 0),
327 TEST ("x@1412", 0, 1412, "x@1412", 0),
328 TEST ("x@1412", 207, 540, "x@540", 0),
329 TEST ("x@874", 1, 873, "x@873", 0),
330 TEST ("x@3695", 10, 2284, "x@2284", 0),
331 TEST ("x@4096", 0, 4096, "x@4096", 0),
332
333 TEST ("abc", 5, 3, "", 1),
334 TEST ("x@4096", 4106, 3, "", 1),
335
336 TEST ("last test", 0, 9, "last test", 0)
337};
338
339
341// exercises:
342// basic_string (size_type, value_type)
343static const StringTestCase
344size_val_test_cases [] = {
345
346#define size_val_alloc_test_cases size_val_test_cases
347
348#undef TEST
349#define TEST(size, val, res) { \
350 __LINE__, -1, size, -1, -1, val, \
351 0, 0, 0, 0, \
352 res, sizeof res - 1, 0 \
353 }
354
355 // +---------------------------------------- ctor n argument
356 // | +----------------------------- source value
357 // | | +------------------------ expected result sequence
358 // | | |
359 // | | |
360 // V V V
361 TEST (1, 'a', "a"),
362 TEST (1, '\0', "<U0>"),
363
364 TEST (2, 'a', "aa"),
365 TEST (2, '\0', "<U0>@2"),
366
367 TEST (5, '\0', "<U0>@5"),
368 TEST (10, 'a', "aaaaaaaaaa"),
369
370 TEST (128, 'x', "x@128"),
371 TEST (207, 'x', "x@207"),
372 TEST (540, 'x', "x@540"),
373 TEST (873, 'x', "x@873"),
374 TEST (1412, 'x', "x@1412"),
375 TEST (3695, 'x', "x@3695"),
376
377 TEST (4096, 'x', "x@4096"),
378
379 TEST (4, 't', "tttt")
380};
381
382
383// exercises:
384// operator= (const value_type*)
385static const StringTestCase
386cptr_op_set_test_cases [] = {
387
388#undef TEST
389#define TEST(str, arg, res, bthrow) { \
390 __LINE__, -1, -1, -1, -1, -1, \
391 str, sizeof str - 1, arg, sizeof arg - 1, \
392 res, sizeof res - 1, bthrow \
393 }
394
395 // +----------------------------------------- source sequence
396 // | +------------------------------ argument sequence
397 // | | +-------------- expected result sequence
398 // | | | +--- exception info
399 // | | | | 0 - no exception
400 // | | | | -1 - excpetion safety
401 // | | | |
402 // | | | |
403 // V V V V
404 TEST ("", "ab", "ab", 0),
405
406 TEST ("", "", "", 0),
407 TEST ("abc", "", "", 0),
408 TEST ("", "<U0>", "", 0),
409 TEST ("abc", "<U0>", "", 0),
410
411 TEST ("", "a", "a", 0),
412 TEST ("<U0>@2", "a", "a", 0),
413 TEST ("a", "bcd", "bcd", 0),
414 TEST ("x@4096", "bcd", "bcd", 0),
415 TEST ("", "cdefaihjb", "cdefaihjb", 0),
416 TEST ("a<U0>b", "cdefaihjb", "cdefaihjb", 0),
417
418 TEST ("", "<U0>@2ab", "", 0),
419 TEST ("c<U0>d", "<U0>@2ab", "", 0),
420 TEST ("", "a<U0>@2b", "a", 0),
421 TEST ("bcd", "a<U0>@2b", "a", 0),
422 TEST ("<U0>", "ab<U0>@2", "ab", 0),
423 TEST ("x@4096", "ab<U0>@2", "ab", 0),
424 TEST ("<U0>a", "abefdcc<U0>a", "abefdcc", 0),
425 TEST ("x@4096", "abefdcc<U0>a", "abefdcc", 0),
426
427 TEST ("", "x@207", "x@207", 0),
428 TEST ("x@128", "x@207", "x@207", 0),
429 TEST ("x@540", "x@207", "x@207", 0),
430 TEST ("", "x@1412", "x@1412", 0),
431 TEST ("x@128", "x@1412", "x@1412", 0),
432 TEST ("x@3695", "x@1412", "x@1412", 0),
433 TEST ("x@872", "x@873", "x@873", 0),
434 TEST ("x@873", "x@3695", "x@3695", 0),
435
436 TEST ("abc", "x@4096", "x@4096", 0),
437
438 TEST ("", 0, "", 0),
439 TEST ("a<U0>b<U0>", 0, "a", 0),
440 TEST ("x@4096", 0, "x@4096", 0),
441
442 TEST ("abcd", "x@4096", "x@4096", 0),
443
444 TEST ("", "last test", "last test", 0)
445};
446
447
448// exercises:
449// operator= (const basic_string&)
450static const StringTestCase
451cstr_op_set_test_cases [] = {
452
453#undef TEST
454#define TEST(str, arg, res, bthrow) { \
455 __LINE__, -1, -1, -1, -1, -1, \
456 str, sizeof str - 1, arg, sizeof arg - 1, \
457 res, sizeof res - 1, bthrow \
458 }
459
460 // +----------------------------------------- source sequence
461 // | +------------------------------ argument sequence
462 // | | +--------------- expected result sequence
463 // | | | +- exception info
464 // | | | | 0 - no exception
465 // | | | | -1 - excpetion safety
466 // | | | |
467 // | | | |
468 // V V V V
469 TEST ("", "ab", "ab", 0),
470
471 TEST ("", "", "", 0),
472 TEST ("abc", "", "", 0),
473 TEST ("", "<U0>", "<U0>", 0),
474 TEST ("abc", "<U0>", "<U0>", 0),
475
476 TEST ("", "a", "a", 0),
477 TEST ("<U0>@2", "a", "a", 0),
478 TEST ("a", "bcd", "bcd", 0),
479 TEST ("x@4096", "bcd", "bcd", 0),
480 TEST ("", "cdefaihjb", "cdefaihjb", 0),
481 TEST ("a<U0>b", "cdefaihjb", "cdefaihjb", 0),
482
483 TEST ("", "<U0>@2ab", "<U0>@2ab", 0),
484 TEST ("c<U0>d", "<U0>@2ab", "<U0>@2ab", 0),
485 TEST ("", "a<U0>@2b", "a<U0>@2b", 0),
486 TEST ("bcd", "a<U0>@2b", "a<U0>@2b", 0),
487 TEST ("<U0>", "ab<U0>@2", "ab<U0>@2", 0),
488 TEST ("x@4096", "ab<U0>@2", "ab<U0>@2", 0),
489 TEST ("<U0>a", "abefdcc<U0>a", "abefdcc<U0>a", 0),
490 TEST ("x@4096", "abefdcc<U0>a", "abefdcc<U0>a", 0),
491
492 TEST ("", "x@207", "x@207", 0),
493 TEST ("x@128", "x@207", "x@207", 0),
494 TEST ("x@540", "x@207", "x@207", 0),
495 TEST ("", "x@1412", "x@1412", 0),
496 TEST ("x@128", "x@1412", "x@1412", 0),
497 TEST ("x@3695", "x@1412", "x@1412", 0),
498 TEST ("x@872", "x@873", "x@873", 0),
499 TEST ("x@873", "x@3695", "x@3695", 0),
500
501 TEST ("abc", "x@4096", "x@4096", 0),
502
503 TEST ("", 0, "", 0),
504 TEST ("a<U0>b<U0>", 0, "a<U0>b<U0>", 0),
505 TEST ("x@4096", 0, "x@4096", 0),
506
507 TEST ("", "last test", "last test", 0)
508};
509
510
511
513// exercises:
514// operator= (value_type)
515static const StringTestCase
516val_op_set_test_cases [] = {
517
518#undef TEST
519#define TEST(str, val, res) { \
520 __LINE__, -1, -1, -1, -1, val, \
521 str, sizeof str - 1, 0, 0, \
522 res, sizeof res - 1, 0 \
523 }
524
525 // +----------------------------------- initial sequence
526 // | +------------------------ source value
527 // | | +------------------- expected result sequence
528 // | | |
529 // | | |
530 // V V V
531 TEST ("", 'a', "a"),
532 TEST ("abcdef", 'a', "a"),
533 TEST ("", '\0', "<U0>"),
534 TEST ("a", '\0', "<U0>"),
535 TEST ("<U0>@2", 'x', "x"),
536
537 TEST ("x@207", 'a', "a"),
538 TEST ("x@873", '\0', "<U0>"),
539 TEST ("x@2284", 't', "t"),
540 TEST ("x@4096", 'x', "x"),
541
542 TEST ("", 't', "t")
543};
544
545
547// invokes specializations of the member function template
548// on the required iterator categories
549template <class String, class Iterator>
550struct ConsRange: RangeBase<String> {
551
552 typedef typename String::iterator StringIter;
553 typedef typename String::value_type StringChar;
554 typedef typename String::allocator_type StringAlloc;
555
557
558 virtual String&
560
561 const StringChar* const beg = tdata.arg_ + tdata.off2_;
562 const StringChar* const end = beg + tdata.ext2_;
563
564 const Iterator first (beg, beg, end);
565 const Iterator last (end, beg, end);
566
567 if (Cons (range_alloc) == tdata.func_.which_) {
569 String* tmp = new String (first, last, alloc);
570 return *tmp;
571 }
572
573 String* tmp = new String (first, last);
574 return *tmp;
575 }
576};
577
578
580// invokes possible overloads of the member function template
581// on common RandomAccessIterator types
582template <class String, class Iterator>
583struct ConsRangeOverload: RangeBase<String>
584{
585 typedef typename String::iterator StringIter;
586 typedef typename String::value_type StringChar;
587 typedef typename String::allocator_type StringAlloc;
588
590
591 virtual String&
593 const StringTestCaseData<StringChar>& tdata) const {
594
595 bool reverse_iter = StringIds::ReverseIterator == tdata.func_.iter_id_
597
598 const std::size_t off = reverse_iter ?
599 tdata.arglen_ - tdata.off2_ - tdata.ext2_ : tdata.off2_;
600 const std::size_t ext = tdata.ext2_;
601
602 const Iterator first (this->begin (str_arg, (Iterator*)0) + off);
603 const Iterator last (first + ext);
604
605 if (Cons (range_alloc) == tdata.func_.which_) {
607 String* tmp = new String (first, last, alloc);
608 return *tmp;
609 }
610
611 String* tmp = new String (first, last);
612 return *tmp;
613 }
614};
615
616
618template <class charT, class Traits, class Allocator>
620 std::basic_string <charT, Traits, Allocator> > &rng,
621 const StringTestCaseData<charT> &tdata)
622{
623 typedef std::basic_string <charT, Traits, Allocator> String;
624
625 const StringFunc &func = tdata.func_;
626 const StringTestCase &tcase = tdata.tcase_;
627
628 // construct the argument string
629 /* const */ String arg (tdata.arg_, tdata.arglen_);
630
631 // offset and extent function arguments
632 const std::size_t arg_off = -1 != tcase.off ?
633 std::size_t (tcase.off) : std::size_t (tcase.off2);
634 const std::size_t arg_size = -1 != tcase.size ?
635 std::size_t (tcase.size) : std::size_t (tcase.size2);
636
637 // string function argument
638 const charT* const arg_ptr = arg.c_str ();
639 const String& arg_str = arg;
640 const charT arg_val = make_char (char (tcase.val), (charT*)0);
641 const Allocator arg_alc;
642
643 // (name of) expected and caught exception
644 const char* expected = 0;
645 const char* caught = 0;
646
647#ifndef _RWSTD_NO_EXCEPTIONS
648
649 if (1 == tcase.bthrow && Cons (range) != func.which_
650 && Cons (range_alloc) != func.which_)
651 expected = exceptions [1]; // out_of_range
652 else if (2 == tcase.bthrow)
653 expected = exceptions [2]; // length_error
654
655#else // if defined (_RWSTD_NO_EXCEPTIONS)
656
657 if (tcase.bthrow)
658 return;
659
660#endif // _RWSTD_NO_EXCEPTIONS
661
662 // pointer to the returned reference
663 String* ret_ptr = 0;
664
665 // start checking for memory leaks
666 rwt_check_leaks (0, 0);
667
668 try {
669 switch (func.which_) {
670
671 case Cons (void):
672 ret_ptr = new String ();
673 break;
674
675 case Cons (alloc):
676 ret_ptr = new String (arg_alc);
677 break;
678
679 case Cons (cptr):
680 ret_ptr = new String (arg_ptr);
681 break;
682
683 case Cons (cptr_alloc):
684 ret_ptr = new String (arg_ptr, arg_alc);
685 break;
686
687 case Cons (cstr):
688 ret_ptr = new String (arg_str);
689 break;
690
691 case Cons (cptr_size):
692 ret_ptr = new String (arg_ptr, arg_size);
693 break;
694
695 case Cons (cptr_size_alloc):
696 ret_ptr = new String (arg_ptr, arg_size, arg_alc);
697 break;
698
699 case Cons (cstr_size):
700 ret_ptr = new String (arg_str, arg_off);
701 break;
702
703 case Cons (cstr_size_size):
704 ret_ptr = new String (arg_str, arg_off, arg_size);
705 break;
706
707 case Cons (cstr_size_size_alloc):
708 ret_ptr = new String (arg_str, arg_off, arg_size, arg_alc);
709 break;
710
711 case Cons (size_val):
712 ret_ptr = new String (arg_size, arg_val);
713 break;
714
715 case Cons (size_val_alloc):
716 ret_ptr = new String (arg_size, arg_val, arg_alc);
717 break;
718
719 case Cons (range):
720 ret_ptr = &rng (arg, tdata);
721 break;
722
723 case Cons (range_alloc):
724 ret_ptr = &rng (arg, tdata);
725 break;
726
727 default:
728 RW_ASSERT (!"logic error: unknown constructor overload");
729 }
730
731 // for convenience
732 static const int cwidth = sizeof (charT);
733
734 // verify that returned pointer is valid
735 rw_assert (0 != ret_ptr, 0, tcase.line,
736 "line %d. %{$FUNCALL} expected %{/*.*Gs}, got null",
737 __LINE__, cwidth, int (tdata.reslen_), tdata.res_);
738
739 if (0 != ret_ptr) {
740
741 // verfiy that the length of the resulting string
742 rw_assert (tdata.reslen_ == ret_ptr->size (), 0, tcase.line,
743 "line %d. %{$FUNCALL} expected %{/*.*Gs} with "
744 "length %zu, got %{/*.*Gs} with length %zu",
745 __LINE__,
746 cwidth, int (tdata.reslen_), tdata.res_,
747 tdata.reslen_, cwidth, int (ret_ptr->size ()),
748 ret_ptr->data (), ret_ptr->size ());
749
750 if (Cons (void) != func.which_) {
751 // verify the capacity of the resulting string
752 rw_assert (ret_ptr->size () <= ret_ptr->capacity (), 0,
753 tcase.line, "line %d. %{$FUNCALL} expected "
754 "capacity () >= size (), got capacity () == "
755 "%zu, size () == %zu", __LINE__,
756 ret_ptr->capacity (), ret_ptr->size ());
757 }
758
759 if (tdata.reslen_ == ret_ptr->size ()) {
760 // if the result length matches the expected length
761 // (and only then), also verify that the modified
762 // string matches the expected result
763 const std::size_t match =
764 rw_match (tcase.res, ret_ptr->c_str (), ret_ptr->size ());
765
766 rw_assert (match == tdata.reslen_, 0, tcase.line,
767 "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
768 "got %{/*.*Gs}, difference at offset %zu",
769 __LINE__,
770 cwidth, int (tdata.reslen_), tdata.res_,
771 cwidth, int (ret_ptr->size ()),
772 ret_ptr->data (), match);
773 }
774
775 delete ret_ptr;
776 }
777 }
778
779#ifndef _RWSTD_NO_EXCEPTIONS
780
781 catch (const std::out_of_range &ex) {
782 caught = exceptions [1];
783 rw_assert (caught == expected, 0, tcase.line,
784 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
785 "unexpectedly%{;} caught std::%s(%#s)",
786 __LINE__, 0 != expected, expected, caught, ex.what ());
787 }
788 catch (const std::length_error &ex) {
789 caught = exceptions [2];
790 rw_assert (caught == expected, 0, tcase.line,
791 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
792 "unexpectedly%{;} caught std::%s(%#s)",
793 __LINE__, 0 != expected, expected, caught, ex.what ());
794 }
795 catch (const std::bad_alloc &ex) {
796 caught = exceptions [3];
797 rw_assert (-1 == tcase.bthrow, 0, tcase.line,
798 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
799 "unexpectedly%{;} caught std::%s(%#s)",
800 __LINE__, 0 != expected, expected, caught, ex.what ());
801 }
802 catch (const std::exception &ex) {
803 caught = exceptions [4];
804 rw_assert (0, 0, tcase.line,
805 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
806 "unexpectedly%{;} caught std::%s(%#s)",
807 __LINE__, 0 != expected, expected, caught, ex.what ());
808 }
809 catch (...) {
810 caught = exceptions [0];
811 rw_assert (0, 0, tcase.line,
812 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
813 "unexpectedly%{;} caught %s",
814 __LINE__, 0 != expected, expected, caught);
815 }
816
817#endif // _RWSTD_NO_EXCEPTIONS
818
819 /* const */ std::size_t nbytes;
820 const std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
821
822 // FIXME: verify the number of blocks the function call
823 // is expected to allocate and detect any memory leaks
824 const std::size_t expect_blocks = nblocks;
825
826 rw_assert (nblocks == expect_blocks, 0, tcase.line,
827 "line %d. %{$FUNCALL} allocated %td bytes in %td blocks",
828 __LINE__, nbytes, expect_blocks);
829}
830
831
833template <class charT, class Traits, class Allocator>
835 const StringTestCaseData<charT> &tdata)
836{
837 typedef std::basic_string <charT, Traits, Allocator> String;
838 typedef typename UserTraits<charT>::MemFun TraitsFunc;
839
840 const StringFunc &func = tdata.func_;
841 const StringTestCase &tcase = tdata.tcase_;
842
843 // construct the string object to be modified
844 // and the (possibly unused) argument string
845 /* const */ String str (tdata.str_, tdata.strlen_, Allocator ());
846 const String arg (tdata.arg_, tdata.arglen_, Allocator ());
847
848 // save the state of the string object before the call
849 // to detect wxception safety violations (changes to
850 // the state of the object after an exception)
851 const StringState str_state (rw_get_string_state (str));
852
853 // string function argument
854 const charT* const arg_ptr = tcase.arg ? arg.data () : str.data ();
855 const String& arg_str = tcase.arg ? arg : str;
856 const charT arg_val = make_char (char (tcase.val), (charT*)0);
857
858 std::size_t total_length_calls = 0;
859 std::size_t n_length_calls = 0;
860 std::size_t* const rg_calls = OpSet (cptr) == func.which_ ?
861 rw_get_call_counters ((Traits*)0, (charT*)0) : 0;
862
863 if (rg_calls)
864 total_length_calls = rg_calls [TraitsFunc::length];
865
866 rwt_free_store* const pst = rwt_get_free_store (0);
867 SharedAlloc* const pal = SharedAlloc::instance ();
868
869 // iterate for`throw_after' starting at the next call to operator new,
870 // forcing each call to throw an exception, until the function finally
871 // succeeds (i.e, no exception is thrown)
872 std::size_t throw_count;
873 for (throw_count = 0; ; ++throw_count) {
874
875 // (name of) expected and caught exception
876 const char* expected = 0;
877 const char* caught = 0;
878
879#ifndef _RWSTD_NO_EXCEPTIONS
880
881 if (0 == tcase.bthrow) {
882 // by default excercise the exception safety of the function
883 // by iteratively inducing an exception at each call to operator
884 // new or Allocator::allocate() until the call succeeds
885 expected = exceptions [3]; // bad_alloc
886 *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
887 pal->throw_at_calls_ [pal->m_allocate] =
888 pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
889 }
890 else {
891 // exceptions disabled for this test case
892 }
893
894#else // if defined (_RWSTD_NO_EXCEPTIONS)
895
896 if (tcase.bthrow) {
897 return;
898 }
899
900#endif // _RWSTD_NO_EXCEPTIONS
901
902 // start checking for memory leaks
903 rw_check_leaks (str.get_allocator ());
904
905 try {
906 switch (func.which_) {
907
908 case OpSet (cptr):
909 str = arg_ptr;
910 break;
911
912 case OpSet (cstr):
913 str = arg_str;
914 break;
915
916 case OpSet (val):
917 str = arg_val;
918 break;
919
920 default:
921 RW_ASSERT (!"logic error: unknown operator= overload");
922 }
923
924 // for convenience
925 static const int cwidth = sizeof (charT);
926
927 // verfiy that the length of the resulting string
928 rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
929 "line %d. %{$FUNCALL} expected %{/*.*Gs} with "
930 "length %zu, got %{/*.*Gs} with length %zu",
931 __LINE__,
932 cwidth, int (tdata.reslen_), tdata.res_,
933 tdata.reslen_, cwidth, int (str.size ()), str.data (),
934 str.size ());
935
936 if (tdata.reslen_ == str.size ()) {
937 // if the result length matches the expected length
938 // (and only then), also verify that the modified
939 // string matches the expected result
940 const std::size_t match =
941 rw_match (tcase.res, str.c_str (), str.size ());
942
943 rw_assert (match == tdata.reslen_, 0, tcase.line,
944 "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
945 "got %{/*.*Gs}, difference at offset %zu",
946 __LINE__,
947 cwidth, int (tdata.reslen_), tdata.res_,
948 cwidth, int (str.size ()),str.data (), match);
949 }
950
951 // verify that Traits::length was used
952 if (rg_calls) {
953 rw_assert (n_length_calls - total_length_calls > 0,
954 0, tcase.line, "line %d. %{$FUNCALL} doesn't "
955 "use traits::length()", __LINE__);
956 }
957 }
958
959#ifndef _RWSTD_NO_EXCEPTIONS
960
961 catch (const std::bad_alloc &ex) {
962 caught = exceptions [3];
963 rw_assert (0 == tcase.bthrow, 0, tcase.line,
964 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
965 "unexpectedly%{;} caught std::%s(%#s)",
966 __LINE__, 0 != expected, expected, caught, ex.what ());
967 }
968 catch (const std::exception &ex) {
969 caught = exceptions [4];
970 rw_assert (0, 0, tcase.line,
971 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
972 "unexpectedly%{;} caught std::%s(%#s)",
973 __LINE__, 0 != expected, expected, caught, ex.what ());
974 }
975 catch (...) {
976 caught = exceptions [0];
977 rw_assert (0, 0, tcase.line,
978 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
979 "unexpectedly%{;} caught %s",
980 __LINE__, 0 != expected, expected, caught);
981 }
982
983#endif // _RWSTD_NO_EXCEPTIONS
984
985 // FIXME: verify the number of blocks the function call
986 // is expected to allocate and detect any memory leaks
987 rw_check_leaks (str.get_allocator (), tcase.line,
988 std::size_t (-1), std::size_t (-1));
989
990 if (caught) {
991 // verify that an exception thrown during allocation
992 // didn't cause a change in the state of the object
994 __LINE__, tcase.line, caught);
995
996 if (0 == tcase.bthrow) {
997 // allow this call to operator new to succeed and try
998 // to make the next one to fail during the next call
999 // to the same function again
1000 continue;
1001 }
1002 }
1003 else if (0 < tcase.bthrow) {
1004 rw_assert (caught == expected, 0, tcase.line,
1005 "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
1006 "%{:}unexpectedly caught %s%{;}",
1007 __LINE__, 0 != expected, expected, caught, caught);
1008 }
1009
1010 break;
1011 }
1012
1013 std::size_t expect_throws = 0;
1014
1015 if (OpSet (cstr) != func.which_) {
1016
1017#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
1018
1019 // verify that if exceptions are enabled and when capacity changes
1020 // at least one exception is thrown
1021 expect_throws = str_state.capacity_ < str.capacity ();
1022
1023#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
1024
1025 expect_throws = StringIds::UserAlloc == func.alloc_id_ ?
1026 str_state.capacity_ < str.capacity () : 0;
1027
1028#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
1029
1030 }
1031
1032 rw_assert (expect_throws == throw_count, 0, tcase.line,
1033 "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
1034 "while changing capacity from %zu to %zu, got %zu",
1035 __LINE__, exceptions [3],
1036 str_state.capacity_, str.capacity (), throw_count);
1037
1038 // disable bad_alloc exceptions
1039 *pst->throw_at_calls_ [0] = 0;
1040 pal->throw_at_calls_ [pal->m_allocate] = 0;
1041}
1042
1043
1045template <class charT, class Traits, class Allocator>
1047 const StringTestCaseData<charT> &tdata)
1048{
1049 typedef std::basic_string<charT, Traits, Allocator> String;
1050
1051 const int fid = int (tdata.func_.which_) & StringIds::fid_mask;
1052
1053 if (StringIds::fid_op_set == fid) {
1054 test_op_set ((charT*)0, (Traits*)0, (Allocator*)0, tdata);
1055 return;
1056 }
1057
1058 if (tdata.func_.which_ == Cons (range)
1059 || tdata.func_.which_ == Cons (range_alloc)) {
1060
1061 switch (tdata.func_.iter_id_) {
1062
1063 // exercise possible overloads of the member function template
1064 // on common RandomAccessIterator types
1065#undef TEST
1066#define TEST(Iterator) do { \
1067 typedef typename String::Iterator Iter; \
1068 static const \
1069 ConsRangeOverload<String, Iter> rng; \
1070 test_cons ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
1071 } while (0)
1072
1073 case StringIds::Pointer: TEST (pointer); break;
1074 case StringIds::ConstPointer: TEST (const_pointer); break;
1075 case StringIds::Iterator: TEST (iterator); break;
1076 case StringIds::ConstIterator: TEST (const_iterator); break;
1077
1078 case StringIds::ReverseIterator: TEST (reverse_iterator); break;
1079 case StringIds::ConstReverseIterator: TEST (const_reverse_iterator);
1080 break;
1081
1082 // exercise specializations of the member function template
1083 // on the required iterator categories
1084
1085#undef TEST
1086#define TEST(Iterator) do { \
1087 typedef Iterator<charT> Iter; \
1088 static const \
1089 ConsRange<String, Iter> rng; \
1090 test_cons ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
1091 } while (0)
1092
1093 case StringIds::Input: TEST (InputIter); break;
1094 case StringIds::Forward: TEST (ConstFwdIter); break;
1095 case StringIds::Bidir: TEST (ConstBidirIter); break;
1097
1098 default:
1099 rw_error (0, 0, __LINE__, "bad iterator id");
1100 }
1101 }
1102 else {
1103 // exercise ordinary overloads of the member function
1104 static const RangeBase<String> rng;
1105 test_cons ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata);
1106 }
1107}
1108
1109
1112
1113int main (int argc, char** argv)
1114{
1115 static const StringTest
1116 tests [] = {
1117
1118#undef TEST
1119#define TEST(sig) { \
1120 Cons (sig), sig ## _test_cases, \
1121 sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
1122 }
1123
1124 TEST (void),
1125 TEST (alloc),
1126 TEST (cptr),
1127 TEST (cptr_alloc),
1128 TEST (cstr),
1129 TEST (cptr_size),
1130 TEST (cptr_size_alloc),
1131 TEST (cstr_size),
1132 TEST (cstr_size_size),
1133 TEST (cstr_size_size_alloc),
1134 TEST (size_val),
1135 TEST (size_val_alloc),
1136 TEST (range),
1137 TEST (range_alloc),
1138
1139#undef TEST
1140#define TEST(sig) { \
1141 OpSet (sig), sig ## _op_set_test_cases, \
1142 sizeof sig ## _op_set_test_cases \
1143 / sizeof *sig ## _op_set_test_cases \
1144 }
1145
1146 TEST (cptr),
1147 TEST (cstr),
1148 TEST (val)
1149
1150 };
1151
1152 const std::size_t test_count = sizeof tests / sizeof *tests;
1153
1154 const int status =
1155 rw_run_string_test (argc, argv, __FILE__,
1156 "lib.string.cons",
1157 test_cons_func_array, tests, test_count);
1158
1159 return status;
1160}
#define alloc
Definition 17.names.cpp:441
#define last
Definition 17.names.cpp:487
#define off
Definition 17.names.cpp:507
#define charT
Definition 17.names.cpp:456
#define tmp
Definition 17.names.cpp:553
#define val
Definition 17.names.cpp:570
#define cstr_size_size_test_cases
void test_op_set(charT *, Traits *, Allocator *, const StringTestCaseData< charT > &tdata)
void test_cons(charT *, Traits *, Allocator *, const RangeBase< std::basic_string< charT, Traits, Allocator > > &rng, const StringTestCaseData< charT > &tdata)
#define TEST(dummy)
#define OpSet(sig)
#define Cons(sig)
std::char_traits< S > Traits
const int end
#define main
int caught
const StringTestCase & tcase_
Definition rw_strings.h:692
const charT *const arg_
Definition rw_strings.h:688
const charT *const res_
Definition rw_strings.h:689
const StringFunc & func_
Definition rw_strings.h:691
const charT *const str_
Definition rw_strings.h:687
const char * str
Definition exec.cpp:170
_TEST_EXPORT void rw_check_leaks(const SharedAlloc *=0, int=0, _RWSTD_SIZE_T=0, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX)
UserChar make_char(char c, UserChar *)
Definition rw_char.h:74
_RWSTD_SIZE_T * rw_get_call_counters(std::char_traits< charT > *, charT *)
Definition rw_char.h:495
_TEST_EXPORT _RWSTD_SIZE_T rw_match(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX)
_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 _RWSTD_SIZE_T rwt_check_leaks(_RWSTD_SIZE_T *, const rwt_free_store *)
Definition new.cpp:684
_TEST_EXPORT rwt_free_store * rwt_get_free_store(rwt_free_store *)
Definition new.cpp:597
StringState rw_get_string_state(const String &str)
Definition rw_strings.h:752
_TEST_EXPORT int rw_run_string_test(int, char **, const char *, const char *, StringTestFunc *, const StringTest *, _RWSTD_SIZE_T)
#define DEFINE_STRING_TEST_FUNCTIONS(fname)
Definition rw_strings.h:909
#define RW_ASSERT(expr)
String::iterator StringIter
String::value_type StringChar
String::allocator_type StringAlloc
virtual List & operator()(List &list_arg, const ContainerTestCaseData< ListVal > &tdata) const
String::allocator_type StringAlloc
String::value_type StringChar
virtual List & operator()(List &, const ContainerTestCaseData< ListVal > &tdata) const
String::iterator StringIter
static ContIter begin(List &cont, ContIter *)
static SharedAlloc * instance(SharedAlloc *=0)
_RWSTD_SIZE_T throw_at_calls_[n_funs]
StringIds::OverloadId which_
Definition rw_strings.h:577
StringIds::IteratorId iter_id_
Definition rw_strings.h:576
_RWSTD_SIZE_T capacity_
Definition rw_strings.h:741
int assert_equal(const StringState &, int, int, const char *) const
const char * arg
Definition rw_strings.h:599
const char * res
Definition rw_strings.h:602
_RWSTD_SIZE_T * throw_at_calls_[2]
Definition rw_new.h:83
_RWSTD_SIZE_T new_calls_[2]
Definition rw_new.h:47
int arg
Definition locale.cpp:2806