28#define _RWSTD_TEST_SRC
48_rw_this_file[] = __FILE__;
51static const char*
const
53 "UserPOD",
"UserClass"
57static const char*
const
59 "allocator",
"UserAlloc"
63static const char*
const
66 "InputIterator",
"ForwardIterator",
"BidirectionalIterator",
67 "RandomAccessIterator",
68 "pointer",
"const_pointer",
69 "iterator",
"const_iterator",
70 "reverse_iterator",
"const_reverse_iterator"
74static const char*
const
76 "list",
"vector",
"deque",
"queue",
"stack"
81static const char*
const
83 0 ,
"operator=",
"assign",
84 "get_allocator",
"begin",
"end",
"rbegin",
"rend",
"empty",
85 "size",
"max_size",
"resize",
"insert",
"erase",
"swap",
86 "clear",
"operator==",
"operator<",
"operator!=",
"operator>",
87 "operator>=",
"operator<=",
"push_back",
"front",
"back",
88 "pop_back",
"push_front",
"pop_front",
"splice",
"remove",
89 "remove_if",
"unique",
"merge",
"sort",
"reverse",
"operator[]",
90 "at",
"capacity",
"reserve",
"flip"
111_rw_opt_elem_types [
sizeof _rw_elem_names /
sizeof *_rw_elem_names];
114_rw_opt_alloc_types [
sizeof _rw_alloc_names /
sizeof *_rw_alloc_names];
117_rw_opt_iter_types [
sizeof _rw_iter_names /
sizeof *_rw_iter_names];
120_rw_opt_no_exceptions;
123_rw_opt_no_exception_safety;
131_rw_get_func_inx (
size_t fid)
133 size_t inx = _RWSTD_SIZE_MAX;
135 for (
size_t i = 0; _rw_cont_test_count; ++
i) {
136 if (fid == _rw_cont_tests [
i].
which) {
152 return _rw_cont_names [
func.cont_id_];
162_rw_sigcat (
char **pbuf,
size_t *pbufsize,
173 const bool is_member = 0 != (Ids::bit_member &
which);
176 int argmap = int ((
which & ~Ids::bit_member) >> Ids::fid_bits);
179 bool is_const_member =
180 is_member && Ids::arg_ccont == (argmap & Ids::arg_mask);
184 argmap >>= Ids::arg_bits;
186 const char* funcname = 0;
193 case Ids::fid_ctor: funcname =
"ctor";
break;
194 case Ids::fid_op_index: funcname =
"op_index";
break;
195 case Ids::fid_op_set: funcname =
"op_assign";
break;
196 case Ids::fid_op_equal: funcname =
"op_equal";
break;
197 case Ids::fid_op_less: funcname =
"op_less";
break;
198 case Ids::fid_op_not_equal: funcname =
"op_not_equal";
break;
199 case Ids::fid_op_greater: funcname =
"op_greater";
break;
200 case Ids::fid_op_greater_equal: funcname =
"op_greater_equal";
break;
201 case Ids::fid_op_less_equal: funcname =
"op_less_equal";
break;
203 case Ids::fid_get_allocator:
206 case Ids::fid_max_size:
209 is_const_member =
false;
215 const size_t nfuncs =
216 sizeof _rw_func_names /
sizeof *_rw_func_names;
220 funcname = _rw_func_names [fid];
228 const char*
const iname =
func ? _rw_iter_names [
func->iter_id_] :
"";
231 "%{+}%{?}%s%{?}_const%{;}%{:}%{?}<%s>%{;}(%{;}",
232 0 ==
func, funcname, is_const_member, 0 != *iname, iname);
240 for (
size_t argno = 0; argmap; ++argno, argmap >>= Ids::arg_bits) {
242 const char* pfx =
"";
243 const char* sfx =
"";
245 const int argtype = argmap & Ids::arg_mask;
247 const char* tname = 0;
251 case Ids::arg_size: tname =
"size_type";
break;
252 case Ids::arg_val: tname =
"value_type";
break;
253 case Ids::arg_ref: tname =
"reference";
break;
254 case Ids::arg_cref: tname =
"const_reference";
break;
255 case Ids::arg_iter: tname =
"iterator";
break;
256 case Ids::arg_citer: tname =
"const_iterator";
break;
258 if (
'\0' == *iname_buf) {
259 strcpy (iname_buf, iname);
260 strcat (iname_buf,
", ");
261 strcat (iname_buf, iname);
270 tname = _rw_class_name (*
func);
274 case Ids::arg_alloc: tname =
"const allocator_type&";
break;
275 case Ids::arg_pred: tname =
"Predicate";
break;
276 case Ids::arg_bpred: tname =
"BinaryPredicate";
break;
277 case Ids::arg_comp: tname =
"Compare";
break;
282 case Ids::arg_size: tname =
"size";
break;
283 case Ids::arg_val: tname =
"val";
break;
284 case Ids::arg_ref: tname =
"ref";
break;
285 case Ids::arg_cref: tname =
"cref";
break;
286 case Ids::arg_iter: tname =
"iter";
break;
287 case Ids::arg_citer: tname =
"citer";
break;
288 case Ids::arg_range: tname =
"range";
break;
289 case Ids::arg_cont: tname =
"cont";
break;
290 case Ids::arg_ccont: tname =
"ccont";
break;
291 case Ids::arg_alloc: tname =
"alloc";
break;
292 case Ids::arg_pred: tname =
"pred";
break;
293 case Ids::arg_bpred: tname =
"bpred";
break;
294 case Ids::arg_comp: tname =
"comp";
break;
300 if ( 0 ==
func || is_member
301 || (Ids::arg_cont != argtype && Ids::arg_ccont != argtype)) {
304 "%{+}%{?}_%{:}%{?}, %{;}%{;}%s%s%s",
305 0 ==
func, 0 < argno, pfx, tname, sfx);
312 "%{+}%{?}, %{;}%{?}const %{;}%{$CLASS}&",
313 0 < argno, Ids::arg_ccont == argtype);
319 rw_asnprintf (pbuf, pbufsize,
"%{+})%{?} const%{;}", is_const_member);
352 bool self,
const char*
str,
size_t str_len,
353 const char*
arg,
size_t arg_len,
357 const size_t range1_end = tcase.
off + tcase.
size;
358 const size_t range2_end = tcase.
off2 + tcase.
size2;
366 case ListIds::ctor_ccont:
367 case ListIds::op_set_ccont:
368 case ListIds::swap_cont:
369 case ListIds::merge_cont:
372 "%{+} (%{?}*this%{:}%{$Container}(%{#*s})%{;}"
373 "%{?}, const allocator_type&%{;})",
374 self,
int (arg_len),
arg, use_alloc);
377 case ListIds::assign_size_cref:
378 case ListIds::ctor_size_cref:
379 case ListIds::ctor_size_cref_alloc:
381 "%{+} (%zu, %{#c}%{?}, const allocator_type&%{;})",
382 tcase.
size, tcase.
val, use_alloc);
385 case ListIds::assign_range:
386 case ListIds::ctor_range:
387 case ListIds::ctor_range_alloc:
388 rw_asnprintf (pbuf, pbufsize,
"%{+}<%{$Iterator:-Iterator}>("
389 "%{?}begin()%{:}%{$Iterator:-Iterator}(%{#*s})%{;}"
391 "%{?}begin()%{:}%{$Iterator:-Iterator}(...)%{;}"
393 "%{?}, const allocator_type&%{;})",
394 self,
int (arg_len),
arg,
396 self, 0 != range2_end, range2_end, use_alloc);
399 case ListIds::insert_iter_cref:
401 "%{+} (begin()%{?} + %zu%{;}, %{#c})",
405 case ListIds::insert_iter_size_cref:
407 "%{+} (begin()%{?} + %zu%{;}, %zu, %{#c})",
411 case ListIds::insert_iter_range:
412 rw_asnprintf (pbuf, pbufsize,
"%{+}<%{$Iterator:-Iterator}>"
413 "(begin()%{?} + %zu%{;}, "
414 "%{?}begin()%{:}%{$Iterator:-Iterator}(%{#*s})%{;}"
416 "%{?}begin()%{:}%{$Iterator:-Iterator}(...)%{;}"
418 0 != tcase.
off, tcase.
off,
419 self, int (arg_len),
arg,
421 self, 0 != range2_end, range2_end);
424 case ListIds::push_front_cref:
425 case ListIds::push_back_cref:
426 case ListIds::remove_cref:
428 "%{+} (%{#c})", tcase.
val);
431 case ListIds::ctor_void:
432 case ListIds::get_allocator_void:
433 case ListIds::begin_void:
434 case ListIds::end_void:
435 case ListIds::rbegin_void:
436 case ListIds::rend_void:
437 case ListIds::empty_void:
438 case ListIds::size_void:
439 case ListIds::max_size_void:
440 case ListIds::front_void:
441 case ListIds::back_void:
442 case ListIds::pop_front_void:
443 case ListIds::pop_back_void:
444 case ListIds::clear_void:
445 case ListIds::sort_void:
446 case ListIds::reverse_void:
451 case ListIds::begin_const_void:
452 case ListIds::end_const_void:
453 case ListIds::rbegin_const_void:
454 case ListIds::rend_const_void:
455 case ListIds::front_const_void:
456 case ListIds::back_const_void:
461 case ListIds::ctor_alloc:
463 "%{+} (const allocator_type&)");
466 case ListIds::erase_iter:
468 "%{+} (begin()%{?} + %zu%{;})",
469 0 != tcase.
off, tcase.
off);
472 case ListIds::erase_iter_iter:
474 "%{+} (begin()%{?} + %zu%{;}, begin()%{?} + %zu%{;})",
475 0 != tcase.
off, tcase.
off,
476 0 != range1_end, range1_end);
479 case ListIds::op_equal_ccont_ccont:
480 case ListIds::op_less_ccont_ccont:
481 case ListIds::op_not_equal_ccont_ccont:
482 case ListIds::op_greater_ccont_ccont:
483 case ListIds::op_greater_equal_ccont_ccont:
484 case ListIds::op_less_equal_ccont_ccont:
487 "%{+} (%{?}arg2%{:}%{$CLASS}(%{#*s})%{;}, "
488 "%{?}arg1%{:}%{$CLASS}(%{#*s})%{;})",
489 0 ==
str,
int (str_len),
str, self,
int (arg_len),
arg);
492 case ListIds::ctor_size:
493 case ListIds::resize_size:
495 "%{+} (%zu)", tcase.
size);
498 case ListIds::resize_size_val:
500 "%{+} (%zu, %{#c})", tcase.
size, tcase.
val);
503 case ListIds::swap_cont_cont:
504 case ListIds::splice_iter_cont:
505 case ListIds::splice_iter_cont_iter:
506 case ListIds::splice_iter_cont_iter_iter:
507 case ListIds::remove_if_pred:
508 case ListIds::unique_bpred:
509 case ListIds::merge_cont_comp:
510 case ListIds::sort_comp:
516 RW_ASSERT (!
"test logic error: unknown list overload");
532 bool self,
const char*
str,
size_t str_len,
533 const char*
arg,
size_t arg_len,
561 bool self,
const char*
str,
size_t str_len,
562 const char*
arg,
size_t arg_len,
590 bool self,
const char*
str,
size_t str_len,
591 const char*
arg,
size_t arg_len,
619 bool self,
const char*
str,
size_t str_len,
620 const char*
arg,
size_t arg_len,
654 const char*
const class_name = _rw_class_name (
func);
662 rw_fprintf (0,
"%{$Allocator!:*}", _rw_alloc_names [
func.alloc_id_]);
664 rw_fprintf (0,
"%{$Iterator!:*}", _rw_iter_names [
func.iter_id_]);
666 rw_fprintf (0,
"%{$Container!:*}", class_name);
676 "std::%s<%s%{?}, %s<%2$s>%{;}>",
678 _rw_elem_names [
func.elem_id_],
680 _rw_alloc_names [
func.alloc_id_]);
691 const size_t nfuncs =
sizeof _rw_func_names /
sizeof *_rw_func_names;
698 const char*
const funcname = _rw_func_names [funcinx] ?
699 _rw_func_names [funcinx] : class_name;
707 !is_member, funcname);
712 _rw_sigcat (&
buf, &bufsize, &
func);
721 const bool self = 0 == pcase->arg;
729 size_t str_len =
sizeof str_buf;
730 size_t arg_len =
sizeof arg_buf;
733 str =
rw_expand (str_buf, pcase->str, pcase->str_len, &str_len);
738 arg =
rw_expand (arg_buf, pcase->arg, pcase->arg_len, &arg_len);
754 else if (is_member) {
758 "%{$CLASS} (%{?}%{#*s}%{;}).%{$FUNC}",
759 str != 0,
int (str_len),
str);
770 switch (
func.cont_id_) {
773 _rw_list_sigcat (&
buf, &bufsize,
775 self,
str, str_len,
arg, arg_len, *pcase);
779 _rw_vector_sigcat (&
buf, &bufsize,
781 self,
str, str_len,
arg, arg_len, *pcase);
785 _rw_deque_sigcat (&
buf, &bufsize,
787 self,
str, str_len,
arg, arg_len, *pcase);
791 _rw_queue_sigcat (&
buf, &bufsize,
793 self,
str, str_len,
arg, arg_len, *pcase);
797 _rw_stack_sigcat (&
buf, &bufsize,
799 self,
str, str_len,
arg, arg_len, *pcase);
821 size_t off,
size_t ext)
828 const size_t res_off =
off;
829 const size_t res_ext = (ext < res_len ? ext : res_len) - 1;
831 char* beg = new_res + res_off;
832 char*
end = beg + res_ext;
834 for (; beg <
end; ++beg, --
end) {
835 const char tmp = *beg;
851template <
class T,
class Allocator>
859 typedef void TestFunc (
T*,
Allocator*,
const Data&);
861 const size_t inx =
func.elem_id_ * 2 +
func.alloc_id_;
867 "logic error: null test function for %{$FUNCSIG}");
871 const bool reverse_iter =
875 const Data tdata (
func, tcase);
882 const bool like_ctor =
887 const size_t off = like_ctor ? 0 : tdata.off1_;
888 const size_t ext = like_ctor ? tdata.reslen_ : tdata.ext2_;
893 const Data rev_tdata (
func, rev_tcase);
898 delete[] rev_tcase.
res;
913 typedef std::allocator<T>
Alloc;
921 RW_ASSERT (!
"logic error: unknown Allocator argument");
938 RW_ASSERT (!
"logic error: unknown T argument");
954 if (-1 == tcase.
bthrow && _rw_opt_no_exception_safety) {
957 rw_note (1 < _rw_opt_no_exception_safety++, _rw_this_file, __LINE__,
958 "exception safety tests disabled");
965 if (tcase.
bthrow && _rw_opt_no_exceptions) {
968 rw_note (1 < _rw_opt_no_exceptions++, _rw_this_file, __LINE__,
969 "exception tests disabled");
973 const bool self_ref = 0 == tcase.
arg;
977 if (_rw_opt_self_ref < 0 && self_ref) {
980 "self-referential test disabled");
983 else if (0 < _rw_opt_self_ref && !self_ref) {
986 "non-self-referential test disabled");
995 _rw_setvars (
func, &tcase);
999 test_callback (
func, tcase);
1007 "test on line %d disabled", tcase.
line);
1037 const size_t siginx = _rw_get_func_inx (
test.which);
1041 if (0 ==
rw_note (0 <= _rw_opt_func [siginx], _rw_this_file, __LINE__,
1042 "%{?}%{$CLASS}::%{;}%{$FUNCSIG} tests disabled",
1046 rw_info (0, 0, 0,
"%{?}%{$CLASS}::%{;}%{$FUNCSIG}", is_member);
1048 const size_t case_count =
test.case_count;
1053 for (
size_t n = 0;
n != case_count; ++
n) {
1057 _rw_test_case (
func, tcase, _rw_test_callback, _rw_func_array);
1066 for (
size_t i = 0;
i !=
count; ++
i) {
1082_rw_run_test (
int,
char*[])
1084#ifdef _RWSTD_NO_EXCEPTIONS
1086 rw_note (0, 0, 0,
"exception tests disabled (macro "
1087 "_RWSTD_NO_EXCEPTIONS #defined)");
1090 _rw_no_exceptions = 2;
1091 _rw_no_exception_safety = 2;
1100 const size_t nopts =
sizeof _rw_opt_func /
sizeof *_rw_opt_func;
1119 const size_t n_elem_types =
sizeof elem_types /
sizeof *elem_types;
1120 const size_t n_alloc_types =
sizeof alloc_types /
sizeof *alloc_types;
1121 const size_t n_iter_types =
sizeof iter_types /
sizeof *iter_types;
1130 for (
size_t i = 0;
i != n_elem_types; ++
i) {
1132 if (_rw_opt_elem_types [
i] < 0) {
1134 rw_note (-1 > _rw_opt_elem_types [
i]--,
1135 _rw_this_file, __LINE__,
1136 "%s tests disabled", _rw_elem_names [
i]);
1140 for (
size_t k = 0;
k != n_alloc_types; ++
k) {
1142 if (_rw_opt_alloc_types [
k] < 0) {
1144 rw_note (-1 > _rw_opt_alloc_types [
k]--,
1145 _rw_this_file, __LINE__,
1146 "%s tests disabled", _rw_alloc_names [
k]);
1150 for (
size_t m = 0;
m != _rw_cont_test_count; ++
m) {
1171 for (
size_t l = 0; l != n_iter_types; ++l) {
1173 if (_rw_opt_iter_types [l] < 0) {
1175 rw_note (-1 > _rw_opt_iter_types [l]--,
1176 _rw_this_file, __LINE__,
1177 "%s tests disabled",
1178 _rw_iter_names [l]);
1182 func.iter_id_ = iter_types [l];
1205_rw_add_toggles (
char **pbuf,
size_t *pbufsize,
1206 const char*
const names[],
size_t count)
1208 for (
size_t i = 0;
i !=
count; ++
i) {
1214_rw_add_container_toggles (
char **pbuf,
size_t *pbufsize)
1216 _rw_add_toggles (pbuf, pbufsize, _rw_alloc_names,
1217 sizeof _rw_alloc_names /
sizeof *_rw_alloc_names);
1218 _rw_add_toggles (pbuf, pbufsize, _rw_iter_names + 1,
1219 sizeof _rw_iter_names /
sizeof *_rw_iter_names - 1);
1224_rw_run_test (
int argc,
1235 _rw_container_id = container;
1236 _rw_test_callback = test_callback;
1237 _rw_func_array = func_array,
1238 _rw_cont_tests = tests;
1239 _rw_cont_test_count = test_count;
1245 size_t optbufsize = 0;
1249 "|-no-exception-safety# "
1252 const size_t n_elems =
sizeof _rw_elem_names /
sizeof *_rw_elem_names;
1256 _rw_add_toggles (&optbuf, &optbufsize, _rw_elem_names, n_elems);
1257 _rw_add_container_toggles (&optbuf, &optbufsize);
1259 for (
size_t i = 0;
i != test_count; ++
i) {
1264 _rw_sigcat (&optbuf, &optbufsize, 0, tests [
i].
which);
1273 rw_test (argc, argv, file, clause,
1279 &_rw_opt_no_exceptions,
1280 &_rw_opt_no_exception_safety,
1287 _rw_opt_elem_types + 0,
1288 _rw_opt_elem_types + 1,
1291 _rw_opt_alloc_types + 0,
1292 _rw_opt_alloc_types + 1,
1300 _rw_opt_iter_types + 0,
1301 _rw_opt_iter_types + 1,
1302 _rw_opt_iter_types + 2,
1303 _rw_opt_iter_types + 3,
1304 _rw_opt_iter_types + 4,
1305 _rw_opt_iter_types + 5,
1306 _rw_opt_iter_types + 6,
1307 _rw_opt_iter_types + 7,
1308 _rw_opt_iter_types + 8,
1309 _rw_opt_iter_types + 9,
1369 return _rw_run_test (argc, argv, file, clause, container,
1370 callback, 0, tests,
count);
1384 return _rw_run_test (argc, argv, file, clause, container,
1385 0, farray, tests,
count);
void count(T, T, const U &,...)
_RWSTD_INTERNAL ContainerTestCase _rw_reverse_results(const ContainerTestCase &tsrc, size_t off, size_t ext)
const size_t MAX_OVERLOADS
void _rw_dispatch(T *, Allocator *, VoidFunc *const *farray, const ContainerFunc &func, const ContainerTestCase &tcase)
_TEST_EXPORT int rw_run_cont_test(int argc, char *argv[], const char *file, const char *clause, ContainerIds::ContainerId container, ContainerTestFunc *callback, const ContainerTest *tests, size_t count)
void _rw_toggle_options(int *opts, size_t count)
#define _RWSTD_REINTERPRET_CAST(T, x)
#define _RWSTD_UNUSED(arg)
#define _RWSTD_STATIC_CAST(T, x)
_TEST_EXPORT char * rw_expand(char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, _RWSTD_SIZE_T *=0)
_TEST_EXPORT int rw_enabled(const char *name)
void ContainerTestFunc(const ContainerFunc &, const ContainerTestCase &)
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_fprintf(rw_file *, const char *,...)
_TEST_EXPORT int rw_asnprintf(char **pbuf, _RWSTD_SIZE_T *pbufsize, const char *fmt,...)