Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
21.string.operators.cpp
Go to the documentation of this file.
1
30#include <string> // for string
31#include <stdexcept> // for out_of_range, length_error
32
33#include <cstddef> // for size_t
34
35#include <rw_strings.h> // for StringMembers
36#include <rw_driver.h> // for rw_test()
37#include <rw_allocator.h> // for UserAlloc
38#include <rw_char.h> // for rw_expand()
39#include <rw_new.h> // for bad_alloc, replacement operator new
40
41
43// for convenience and brevity
44#define OpEqual(which) StringIds::op_equal_ ## which
45#define OpNotEqual(which) StringIds::op_not_equal_ ## which
46#define OpLess(which) StringIds::op_less_ ## which
47#define OpLessEqual(which) StringIds::op_less_equal_ ## which
48#define OpGreater(which) StringIds::op_greater_ ## which
49#define OpGreaterEqual(which) StringIds::op_greater_equal_ ## which
50
51static const char* const exceptions[] = {
52 "unknown exception", "out_of_range", "length_error",
53 "bad_alloc", "exception"
54};
55
56
58// exercises:
59// operator == (const value_type*, const basic_string&)
60// operator != (const value_type*, const basic_string&)
61// operator < (const value_type*, const basic_string&)
62// operator <= (const value_type*, const basic_string&)
63// operator > (const value_type*, const basic_string&)
64// operator >= (const value_type*, const basic_string&)
65static const StringTestCase
66cptr_cstr_test_cases [] = {
67
68#undef TEST
69#define TEST(str, arg, res) \
70 { __LINE__, -1, -1, -1, -1, -1, \
71 str, sizeof str - 1, arg, sizeof arg - 1, \
72 0, (std::size_t) res, 0 \
73 }
74
75 // +----------------------------------------- first sequence
76 // | +----------------------- second sequence
77 // | | +---- expected result
78 // | | | -1 - first is less
79 // | | | 0 - equal
80 // | | | 1 - first is greater
81 // | | |
82 // | | |
83 // V V V
84 TEST ("ab", "c", -1),
85
86 TEST ("", "", 0),
87 TEST ("", "a", -1),
88 TEST ("a", "", 1),
89 TEST ("a", "a", 0),
90
91 TEST ("<U0>", "", 0),
92 TEST ("", "<U0>", -1),
93 TEST ("<U0>", "<U0>", -1),
94
95 TEST ("abcdefgjih", "abcdefgji", 1),
96 TEST ("abcdefgjih", "abcdefgjih", 0),
97 TEST ("abcdefgji", "abcdefgjih", -1),
98 TEST ("abcefgjih", "abcdefgjih", 1),
99 TEST ("abcdefgjih", "abcefgjih", -1),
100
101 TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2c", -1),
102 TEST ("ab<U0>@2c<U0>", "ab", 0),
103 TEST ("e<U0>", "ab<U0>@2c<U0>", 1),
104
105 TEST ("x@2048", "x@2048", 0),
106 TEST ("x@2048", "x@2049", -1),
107 TEST ("x@2048", "x@2047", 1),
108 TEST ("a@2048", "b@2048", -1),
109 TEST ("b@2048", "a@2048", 1),
110 TEST ("a@2048<U0>", "a@2048", 0),
111 TEST ("a@2048", "a@2048<U0>", -1),
112
113 TEST ("x@128", "x@207", -1),
114 TEST ("x@334", "x@334", 0),
115 TEST ("x@873", "x@540", 1),
116 TEST ("x@1412", "x@2284", -1),
117 TEST ("x@3695", "x@3695", 0),
118 TEST ("x@4096", "x@3695", 1),
119
120 TEST (0, "abc", 0),
121 TEST (0, "<U0>ab<U0>", -1),
122 TEST (0, "x@2048", 0),
123
124 TEST ("last", "last", 0)
125};
126
127
129// exercises:
130// operator == (const basic_string&, const basic_string&)
131// operator != (const basic_string&, const basic_string&)
132// operator < (const basic_string&, const basic_string&)
133// operator <= (const basic_string&, const basic_string&)
134// operator > (const basic_string&, const basic_string&)
135// operator >= (const basic_string&, const basic_string&)
136static const StringTestCase
137cstr_cstr_test_cases [] = {
138
139#undef TEST
140#define TEST(str, arg, res) \
141 { __LINE__, -1, -1, -1, -1, -1, \
142 str, sizeof str - 1, arg, sizeof arg - 1, \
143 0, (std::size_t) res, 0 \
144 }
145
146 // +----------------------------------------- first sequence
147 // | +----------------------- second sequence
148 // | | +---- expected result
149 // | | | -1 - first is less
150 // | | | 0 - equal
151 // | | | 1 - first is greater
152 // | | |
153 // | | |
154 // V V V
155 TEST ("ab", "c", -1),
156
157 TEST ("", "", 0),
158 TEST ("", "a", -1),
159 TEST ("a", "", 1),
160 TEST ("a", "a", 0),
161
162 TEST ("<U0>", "", 1),
163 TEST ("", "<U0>", -1),
164 TEST ("<U0>", "<U0>", 0),
165
166 TEST ("abcdefgjih", "abcdefgji", 1),
167 TEST ("abcdefgjih", "abcdefgjih", 0),
168 TEST ("abcdefgji", "abcdefgjih", -1),
169 TEST ("abcefgjih", "abcdefgjih", 1),
170 TEST ("abcdefgjih", "abcefgjih", -1),
171
172 TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2c", 0),
173 TEST ("ab<U0>@2c<U0>", "<U0>ab<U0>@2c", 1),
174 TEST ("ab<U0>@2c<U0>", "ab<U0>@2c<U0>", 0),
175 TEST ("ab<U0>@2c<U0>", "ab", 1),
176 TEST ("ab", "ab<U0>@2c<U0>", -1),
177 TEST ("ab<U0>@3", "ab<U0>@2c<U0>", -1),
178 TEST ("ab<U0>@3", "ab<U0>@3", 0),
179 TEST ("e<U0>", "ab<U0>@2c<U0>", 1),
180 TEST ("ab<U0>@2c<U0>", "e<U0>", -1),
181
182 TEST ("x@2048", "x@2048", 0),
183 TEST ("x@2048", "x@2049", -1),
184 TEST ("x@2048", "x@2047", 1),
185 TEST ("a@2048", "b@2048", -1),
186 TEST ("b@2048", "a@2048", 1),
187 TEST ("<U0>a@2048", "a@2048<U0>", -1),
188 TEST ("a@2048<U0>", "<U0>a@2048", 1),
189 TEST ("a@2048<U0>", "a@2048", 1),
190 TEST ("a@2048", "a@2048<U0>", -1),
191 TEST ("a@2048<U0>", "a@2048<U0>", 0),
192
193 TEST ("x@128", "x@207", -1),
194 TEST ("x@334", "x@334", 0),
195 TEST ("x@873", "x@540", 1),
196 TEST ("x@1412", "x@2284", -1),
197 TEST ("x@3695", "x@3695", 0),
198 TEST ("x@4096", "x@3695", 1),
199
200 TEST (0, "abc", 0),
201 TEST (0, "<U0>ab<U0>", 0),
202 TEST (0, "x@2048", 0),
203 TEST ("abc", 0, 0),
204 TEST ("<U0>ab<U0>", 0, 0),
205 TEST ("x@2048", 0, 0),
206
207 TEST ("last", "last", 0)
208};
209
210
212// exercises:
213// operator == (const basic_string&, const value_type*)
214// operator != (const basic_string&, const value_type*)
215// operator < (const basic_string&, const value_type*)
216// operator <= (const basic_string&, const value_type*)
217// operator > (const basic_string&, const value_type*)
218// operator >= (const basic_string&, const value_type*)
219static const StringTestCase
220cstr_cptr_test_cases [] = {
221
222#undef TEST
223#define TEST(str, arg, res) \
224 { __LINE__, -1, -1, -1, -1, -1, \
225 str, sizeof str - 1, arg, sizeof arg - 1, \
226 0, (std::size_t) res, 0 \
227 }
228
229 // +----------------------------------------- first sequence
230 // | +----------------------- second sequence
231 // | | +---- expected result
232 // | | | -1 - first is less
233 // | | | 0 - equal
234 // | | | 1 - first is greater
235 // | | |
236 // | | |
237 // V V V
238 TEST ("ab", "c", -1),
239
240 TEST ("", "", 0),
241 TEST ("", "a", -1),
242 TEST ("a", "", 1),
243 TEST ("a", "a", 0),
244
245 TEST ("<U0>", "", 1),
246 TEST ("", "<U0>", 0),
247 TEST ("<U0>", "<U0>", 1),
248
249 TEST ("abcdefgjih", "abcdefgji", 1),
250 TEST ("abcdefgjih", "abcdefgjih", 0),
251 TEST ("abcdefgji", "abcdefgjih", -1),
252 TEST ("abcefgjih", "abcdefgjih", 1),
253 TEST ("abcdefgjih", "abcefgjih", -1),
254
255 TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2c", 1),
256 TEST ("ab", "ab<U0>@2c<U0>", 0),
257 TEST ("e<U0>", "ab<U0>@2c<U0>", 1),
258 TEST ("ab<U0>@2c<U0>", "e<U0>", -1),
259
260 TEST ("x@2048", "x@2048", 0),
261 TEST ("x@2048", "x@2049", -1),
262 TEST ("x@2048", "x@2047", 1),
263 TEST ("a@2048", "b@2048", -1),
264 TEST ("b@2048", "a@2048", 1),
265 TEST ("a@2048", "a@2048<U0>", 0),
266 TEST ("a@2048<U0>", "a@2048<U0>", 1),
267
268 TEST ("x@128", "x@207", -1),
269 TEST ("x@334", "x@334", 0),
270 TEST ("x@873", "x@540", 1),
271 TEST ("x@1412", "x@2284", -1),
272 TEST ("x@3695", "x@3695", 0),
273 TEST ("x@4096", "x@3695", 1),
274
275 TEST ("abc", 0, 0),
276 TEST ("<U0>ab<U0>", 0, 1),
277 TEST ("x@2048", 0, 0),
278
279 TEST ("last", "last", 0)
280};
281
282
284template <class charT, class Traits, class Allocator>
286 const StringFunc &func,
287 const StringTestCase &tcase)
288{
289 typedef std::basic_string <charT, Traits, Allocator> String;
290 typedef typename UserTraits<charT>::MemFun UTMemFun;
291
292 static const std::size_t BUFSIZE = 256;
293
294 static charT wstr_buf [BUFSIZE];
295 static charT warg_buf [BUFSIZE];
296
297 std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
298 std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
299
300 charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
301 charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
302
303 // construct the string object to be modified
304 // and the (possibly unused) argument string
305 /* const */ String s_str (wstr, str_len);
306 const String s_arg (warg, arg_len);
307
308 if (wstr != wstr_buf)
309 delete[] wstr;
310
311 if (warg != warg_buf)
312 delete[] warg;
313
314 wstr = 0;
315 warg = 0;
316
317 const charT* const arg1_ptr = tcase.str ? s_str.c_str () : s_arg.c_str ();
318 const String& arg1_str = tcase.str ? s_str : s_arg;
319 const charT* const arg2_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
320 const String& arg2_str = tcase.arg ? s_arg : s_str;
321
322 std::size_t total_length_calls = 0;
323 std::size_t n_length_calls = 0;
324 std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
325
326 if (rg_calls)
327 total_length_calls = rg_calls [UTMemFun::length];
328
329 rwt_free_store* const pst = rwt_get_free_store (0);
330 SharedAlloc* const pal = SharedAlloc::instance ();
331
332 // iterate for`throw_after' starting at the next call to operator new,
333 // forcing each call to throw an exception, until the function finally
334 // succeeds (i.e, no exception is thrown)
335 std::size_t throw_count;
336 for (throw_count = 0; ; ++throw_count) {
337
338 // (name of) expected and caught exception
339 const char* expected = 0;
340 const char* caught = 0;
341
342#ifndef _RWSTD_NO_EXCEPTIONS
343
344 if (0 == tcase.bthrow) {
345 // by default excercise the exception safety of the function
346 // by iteratively inducing an exception at each call to operator
347 // new or Allocator::allocate() until the call succeeds
348 expected = exceptions [3]; // bad_alloc
349 *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
350 pal->throw_at_calls_ [pal->m_allocate] =
351 pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
352 }
353 else {
354 // exceptions disabled for this test case
355 }
356
357#else // if defined (_RWSTD_NO_EXCEPTIONS)
358
359 if (tcase.bthrow) {
360 if (wres != wres_buf)
361 delete[] wres;
362
363 return;
364 }
365
366#endif // _RWSTD_NO_EXCEPTIONS
367
368 try {
369
370 bool res = false;
371
372 switch (func.which_) {
373 // exercise cptr_cstr cases
374 case OpEqual (cptr_cstr):
375 res = arg1_ptr == arg2_str;
376 if (rg_calls)
377 n_length_calls = rg_calls [UTMemFun::length];
378 break;
379
380 case OpNotEqual (cptr_cstr):
381 res = arg1_ptr != arg2_str;
382 if (rg_calls)
383 n_length_calls = rg_calls [UTMemFun::length];
384 break;
385
386 case OpLess (cptr_cstr):
387 res = arg1_ptr < arg2_str;
388 if (rg_calls)
389 n_length_calls = rg_calls [UTMemFun::length];
390 break;
391
392 case OpLessEqual (cptr_cstr):
393 res = arg1_ptr <= arg2_str;
394 if (rg_calls)
395 n_length_calls = rg_calls [UTMemFun::length];
396 break;
397
398 case OpGreater (cptr_cstr):
399 res = arg1_ptr > arg2_str;
400 if (rg_calls)
401 n_length_calls = rg_calls [UTMemFun::length];
402 break;
403
404 case OpGreaterEqual (cptr_cstr):
405 res = arg1_ptr >= arg2_str;
406 if (rg_calls)
407 n_length_calls = rg_calls [UTMemFun::length];
408 break;
409
410
411 // exercise cstr_cstr cases
412 case OpEqual (cstr_cstr):
413 res = arg1_str == arg2_str;
414 break;
415
416 case OpNotEqual (cstr_cstr):
417 res = arg1_str != arg2_str;
418 break;
419
420 case OpLess (cstr_cstr):
421 res = arg1_str < arg2_str;
422 break;
423
424 case OpLessEqual (cstr_cstr):
425 res = arg1_str <= arg2_str;
426 break;
427
428 case OpGreater (cstr_cstr):
429 res = arg1_str > arg2_str;
430 break;
431
432 case OpGreaterEqual (cstr_cstr):
433 res = arg1_str >= arg2_str;
434 break;
435
436
437 // exercise cstr_cptr cases
438 case OpEqual (cstr_cptr):
439 res = arg1_str == arg2_ptr;
440 if (rg_calls)
441 n_length_calls = rg_calls [UTMemFun::length];
442 break;
443
444 case OpNotEqual (cstr_cptr):
445 res = arg1_str != arg2_ptr;
446 if (rg_calls)
447 n_length_calls = rg_calls [UTMemFun::length];
448 break;
449
450 case OpLess (cstr_cptr):
451 res = arg1_str < arg2_ptr;
452 if (rg_calls)
453 n_length_calls = rg_calls [UTMemFun::length];
454 break;
455
456 case OpLessEqual (cstr_cptr):
457 res = arg1_str <= arg2_ptr;
458 if (rg_calls)
459 n_length_calls = rg_calls [UTMemFun::length];
460 break;
461
462 case OpGreater (cstr_cptr):
463 res = arg1_str > arg2_ptr;
464 if (rg_calls)
465 n_length_calls = rg_calls [UTMemFun::length];
466 break;
467
468 case OpGreaterEqual (cstr_cptr):
469 res = arg1_str >= arg2_ptr;
470 if (rg_calls)
471 n_length_calls = rg_calls [UTMemFun::length];
472 break;
473
474 default:
475 RW_ASSERT ("test logic error: unknown operator overload");
476 return;
477 }
478
479 // form the expected result
480 bool exp_res = false;
481 switch (StringIds::fid_mask & int (func.which_)) {
483 exp_res = 0 == tcase.nres;
484 break;
485
487 exp_res = 0 != tcase.nres;
488 break;
489
491 exp_res = NPOS == tcase.nres;
492 break;
493
495 exp_res = 1 != tcase.nres;
496 break;
497
499 exp_res = 1 == tcase.nres;
500 break;
501
503 exp_res = NPOS != tcase.nres;
504 break;
505 }
506
507 // verify the result
508 rw_assert (res == exp_res, 0, tcase.line,
509 "line %d. %{$FUNCALL} expected %b, got %b",
510 __LINE__, exp_res, res);
511
512 // verify that Traits::length was used
513 std::size_t exp_len_used =
516 << int (StringIds::fid_bits));
517
518 std::size_t verlen =
519 func.which_ & ~StringIds::fid_mask & ~exp_len_used;
520
521 if (verlen && rg_calls) {
522 rw_assert (n_length_calls - total_length_calls > 0,
523 0, tcase.line, "line %d. %{$FUNCALL} doesn't "
524 "use traits::length()", __LINE__);
525 }
526 }
527
528#ifndef _RWSTD_NO_EXCEPTIONS
529
530 catch (const std::bad_alloc &ex) {
531 caught = exceptions [3];
532 rw_assert (0 == tcase.bthrow, 0, tcase.line,
533 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
534 "unexpectedly%{;} caught std::%s(%#s)",
535 __LINE__, 0 != expected, expected, caught, ex.what ());
536 }
537 catch (const std::exception &ex) {
538 caught = exceptions [4];
539 rw_assert (0, 0, tcase.line,
540 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
541 "unexpectedly%{;} caught std::%s(%#s)",
542 __LINE__, 0 != expected, expected, caught, ex.what ());
543 }
544 catch (...) {
545 caught = exceptions [0];
546 rw_assert (0, 0, tcase.line,
547 "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
548 "unexpectedly%{;} caught %s",
549 __LINE__, 0 != expected, expected, caught);
550 }
551
552#endif // _RWSTD_NO_EXCEPTIONS
553
554 if (caught) {
555
556 if (0 == tcase.bthrow) {
557 // allow this call to operator new to succeed and try
558 // to make the next one to fail during the next call
559 // to the same function again
560 continue;
561 }
562 }
563 else if (0 < tcase.bthrow) {
564 rw_assert (caught == expected, 0, tcase.line,
565 "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
566 "%{:}unexpectedly caught %s%{;}",
567 __LINE__, 0 != expected, expected, caught, caught);
568 }
569
570 break;
571 }
572
573 const std::size_t expect_throws = 0;
574
575 rw_assert (expect_throws == throw_count, 0, tcase.line,
576 "line %d: %{$FUNCALL}: expected no %s exceptions, got %zu",
577 __LINE__, exceptions [3], throw_count);
578
579 // disable bad_alloc exceptions
580 *pst->throw_at_calls_ [0] = 0;
581 pal->throw_at_calls_ [pal->m_allocate] = 0;
582}
583
584
587
588int main (int argc, char** argv)
589{
590 static const StringTest
591 tests [] = {
592
593#undef TEST
594#define TEST(oper, tag) { \
595 StringIds::op_ ## oper ## _ ## tag, tag ## _test_cases, \
596 sizeof tag ## _test_cases / sizeof *tag ## _test_cases \
597 }
598
599 TEST (equal, cptr_cstr),
600 TEST (equal, cstr_cptr),
601 TEST (equal, cstr_cstr),
602
603 TEST (not_equal, cptr_cstr),
604 TEST (not_equal, cstr_cptr),
605 TEST (not_equal, cstr_cstr),
606
607 TEST (less, cptr_cstr),
608 TEST (less, cstr_cptr),
609 TEST (less, cstr_cstr),
610
611 TEST (less_equal, cptr_cstr),
612 TEST (less_equal, cstr_cptr),
613 TEST (less_equal, cstr_cstr),
614
615 TEST (greater, cptr_cstr),
616 TEST (greater, cstr_cptr),
617 TEST (greater, cstr_cstr),
618
619 TEST (greater_equal, cptr_cstr),
620 TEST (greater_equal, cstr_cptr),
621 TEST (greater_equal, cstr_cstr)
622
623 };
624
625 const std::size_t test_count = sizeof tests / sizeof *tests;
626
627 return rw_run_string_test (argc, argv, __FILE__,
628 "lib.string.nonmembers",
629 test_operators, tests, test_count);
630}
#define res
Definition 17.names.cpp:531
#define charT
Definition 17.names.cpp:456
bool equal(const T &x, const U &y)
#define OpLessEqual(which)
#define OpGreater(which)
#define OpNotEqual(which)
#define OpEqual(which)
void test_operators(charT, Traits *, Allocator *, const StringFunc &func, const StringTestCase &tcase)
#define TEST(str, arg, res)
#define OpLess(which)
#define OpGreaterEqual(which)
std::char_traits< S > Traits
#define NPOS
#define main
int caught
_TEST_EXPORT char * rw_expand(char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, _RWSTD_SIZE_T *=0)
_RWSTD_SIZE_T * rw_get_call_counters(std::char_traits< charT > *, charT *)
Definition rw_char.h:495
_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 DEFINE_STRING_TEST_DISPATCH(fname)
Definition rw_strings.h:885
_TEST_EXPORT int rw_run_string_test(int, char **, const char *, const char *, StringTestFunc *, const StringTest *, _RWSTD_SIZE_T)
#define RW_ASSERT(expr)
static SharedAlloc * instance(SharedAlloc *=0)
_RWSTD_SIZE_T throw_at_calls_[n_funs]
@ fid_op_greater_equal
Definition rw_strings.h:80
@ fid_op_less_equal
Definition rw_strings.h:78
@ fid_op_not_equal
Definition rw_strings.h:76
@ fid_op_greater
Definition rw_strings.h:79
_RWSTD_SIZE_T arg_len
Definition rw_strings.h:600
_RWSTD_SIZE_T str_len
Definition rw_strings.h:597
const char * str
Definition rw_strings.h:596
const char * arg
Definition rw_strings.h:599
_RWSTD_SIZE_T nres
Definition rw_strings.h:603
_RWSTD_SIZE_T * throw_at_calls_[2]
Definition rw_new.h:83
_RWSTD_SIZE_T new_calls_[2]
Definition rw_new.h:47