first commit

This commit is contained in:
Jose Caban
2025-06-07 11:34:38 -04:00
commit 0eb2d7c07d
4708 changed files with 1500614 additions and 0 deletions

View File

@@ -0,0 +1,699 @@
/***************************************************************************
*
* 21.cctype.cpp - test exercising clause lib.string.c.strings,
* header <cctype>
*
* $Id: 21.cctype.cpp 550991 2007-06-26 23:58:07Z sebor $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2006 Rogue Wave Software.
*
**************************************************************************/
#include <cctype>
#include <driver.h>
/**************************************************************************/
// detect masking macros
const char* const cctype_macros [] = {
#ifdef isalnum
"isalnum",
#else
"",
#endif
#ifdef isalpha
"isalpha",
#else
"",
#endif
#ifdef iscntrl
"iscntrl",
#else
"",
#endif
#ifdef isdigit
"isdigit",
#else
"",
#endif
#ifdef isgraph
"isgraph",
#else
"",
#endif
#ifdef islower
"islower",
#else
"",
#endif
#ifdef isprint
"isprint",
#else
"",
#endif
#ifdef ispunct
"ispunct",
#else
"",
#endif
#ifdef isspace
"isspace",
#else
"",
#endif
#ifdef isupper
"isupper",
#else
"",
#endif
#ifdef isxdigit
"isxdigit",
#else
"",
#endif
#ifdef tolower
"tolower",
#else
"",
#endif
#ifdef toupper
"toupper",
#else
"",
#endif
0
};
/**************************************************************************/
// define function template overloads for the <cctype> functions with
// the same name to detect whether the C versions are declared or not
#define TEST_FUNCTION(name) \
template <class T> int name (T) { function_called = 0; return 0; } \
typedef void rw_unused_typedef
int function_called;
_RWSTD_NAMESPACE (std) {
TEST_FUNCTION (isalnum);
TEST_FUNCTION (isalpha);
TEST_FUNCTION (iscntrl);
TEST_FUNCTION (isdigit);
TEST_FUNCTION (isprint);
TEST_FUNCTION (isupper);
TEST_FUNCTION (tolower);
TEST_FUNCTION (isgraph);
TEST_FUNCTION (ispunct);
TEST_FUNCTION (isxdigit);
TEST_FUNCTION (toupper);
} // namespace std
/**************************************************************************/
enum {
bit_alnum = 1,
bit_alpha = 1 << 1,
bit_cntrl = 1 << 2,
bit_digit = 1 << 3,
bit_graph = 1 << 4,
bit_lower = 1 << 5,
bit_print = 1 << 6,
bit_punct = 1 << 7,
bit_space = 1 << 8,
bit_upper = 1 << 9,
bit_xdigit = 1 << 10
};
static char*
get_bitmask (int mask, char *str)
{
char *str_save = str;
#define APPEND(bit) \
if (mask & bit_ ## bit) { \
for (const char *s = #bit; *s; ++s, ++str) \
*str = *s; \
*str++ = '|'; \
} else (void)0
APPEND (alnum);
APPEND (alpha);
APPEND (cntrl);
APPEND (digit);
APPEND (graph);
APPEND (lower);
APPEND (print);
APPEND (punct);
APPEND (space);
APPEND (upper);
APPEND (xdigit);
if (str == str_save)
*str = '\0';
else
str [-1] = '\0';
return str_save;
}
static const int
char_mask [256] = {
#undef LETTER
#define LETTER(bits) bit_alpha | bit_alnum | bit_print | bit_graph | bits
#if 'A' == 0x41
/* 0x00 */ bit_cntrl,
/* 0x01 */ bit_cntrl,
/* 0x02 */ bit_cntrl,
/* 0x03 */ bit_cntrl,
/* 0x04 */ bit_cntrl,
/* 0x05 */ bit_cntrl,
/* 0x06 */ bit_cntrl,
/* 0x07 */ bit_cntrl,
/* 0x08 */ bit_cntrl,
/* 0x09 */ bit_space | bit_cntrl,
/* 0x0a */ bit_space | bit_cntrl,
/* 0x0b */ bit_space | bit_cntrl,
/* 0x0c */ bit_space | bit_cntrl,
/* 0x0d */ bit_space | bit_cntrl,
/* 0x0e */ bit_cntrl,
/* 0x0f */ bit_cntrl,
/* 0x10 */ bit_cntrl,
/* 0x11 */ bit_cntrl,
/* 0x12 */ bit_cntrl,
/* 0x13 */ bit_cntrl,
/* 0x14 */ bit_cntrl,
/* 0x15 */ bit_cntrl,
/* 0x16 */ bit_cntrl,
/* 0x17 */ bit_cntrl,
/* 0x18 */ bit_cntrl,
/* 0x19 */ bit_cntrl,
/* 0x1a */ bit_cntrl,
/* 0x1b */ bit_cntrl,
/* 0x1c */ bit_cntrl,
/* 0x1d */ bit_cntrl,
/* 0x1e */ bit_cntrl,
/* 0x1f */ bit_cntrl,
/* ' ' */ bit_space | bit_print,
/* '!' */ bit_print | bit_punct | bit_graph,
/* '"' */ bit_print | bit_punct | bit_graph,
/* '#' */ bit_print | bit_punct | bit_graph,
/* '$' */ bit_print | bit_punct | bit_graph,
/* '%' */ bit_print | bit_punct | bit_graph,
/* '&' */ bit_print | bit_punct | bit_graph,
/* '\'' */ bit_print | bit_punct | bit_graph,
/* '(' */ bit_print | bit_punct | bit_graph,
/* ')' */ bit_print | bit_punct | bit_graph,
/* '*' */ bit_print | bit_punct | bit_graph,
/* '+' */ bit_print | bit_punct | bit_graph,
/* ',' */ bit_print | bit_punct | bit_graph,
/* '-' */ bit_print | bit_punct | bit_graph,
/* '.' */ bit_print | bit_punct | bit_graph,
/* '/' */ bit_print | bit_punct | bit_graph,
/* '0' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '1' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '2' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '3' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '4' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '5' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '6' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '7' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '8' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '9' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* ':' */ bit_print | bit_punct | bit_graph,
/* ';' */ bit_print | bit_punct | bit_graph,
/* '<' */ bit_print | bit_punct | bit_graph,
/* '=' */ bit_print | bit_punct | bit_graph,
/* '>' */ bit_print | bit_punct | bit_graph,
/* '?' */ bit_print | bit_punct | bit_graph,
/* '@' */ bit_print | bit_punct | bit_graph,
/* 'A' */ LETTER (bit_upper | bit_xdigit),
/* 'B' */ LETTER (bit_upper | bit_xdigit),
/* 'C' */ LETTER (bit_upper | bit_xdigit),
/* 'D' */ LETTER (bit_upper | bit_xdigit),
/* 'E' */ LETTER (bit_upper | bit_xdigit),
/* 'F' */ LETTER (bit_upper | bit_xdigit),
/* 'G' */ LETTER (bit_upper),
/* 'H' */ LETTER (bit_upper),
/* 'I' */ LETTER (bit_upper),
/* 'J' */ LETTER (bit_upper),
/* 'K' */ LETTER (bit_upper),
/* 'L' */ LETTER (bit_upper),
/* 'M' */ LETTER (bit_upper),
/* 'N' */ LETTER (bit_upper),
/* 'O' */ LETTER (bit_upper),
/* 'P' */ LETTER (bit_upper),
/* 'Q' */ LETTER (bit_upper),
/* 'R' */ LETTER (bit_upper),
/* 'S' */ LETTER (bit_upper),
/* 'T' */ LETTER (bit_upper),
/* 'U' */ LETTER (bit_upper),
/* 'V' */ LETTER (bit_upper),
/* 'W' */ LETTER (bit_upper),
/* 'X' */ LETTER (bit_upper),
/* 'Y' */ LETTER (bit_upper),
/* 'Z' */ LETTER (bit_upper),
/* '[' */ bit_print | bit_punct | bit_graph,
/* '\\' */ bit_print | bit_punct | bit_graph,
/* ']' */ bit_print | bit_punct | bit_graph,
/* '^' */ bit_print | bit_punct | bit_graph,
/* '_' */ bit_print | bit_punct | bit_graph,
/* '`' */ bit_print | bit_punct | bit_graph,
/* 'a' */ LETTER (bit_lower | bit_xdigit),
/* 'b' */ LETTER (bit_lower | bit_xdigit),
/* 'c' */ LETTER (bit_lower | bit_xdigit),
/* 'd' */ LETTER (bit_lower | bit_xdigit),
/* 'e' */ LETTER (bit_lower | bit_xdigit),
/* 'f' */ LETTER (bit_lower | bit_xdigit),
/* 'g' */ LETTER (bit_lower),
/* 'h' */ LETTER (bit_lower),
/* 'i' */ LETTER (bit_lower),
/* 'j' */ LETTER (bit_lower),
/* 'k' */ LETTER (bit_lower),
/* 'l' */ LETTER (bit_lower),
/* 'm' */ LETTER (bit_lower),
/* 'n' */ LETTER (bit_lower),
/* 'o' */ LETTER (bit_lower),
/* 'p' */ LETTER (bit_lower),
/* 'q' */ LETTER (bit_lower),
/* 'r' */ LETTER (bit_lower),
/* 's' */ LETTER (bit_lower),
/* 't' */ LETTER (bit_lower),
/* 'u' */ LETTER (bit_lower),
/* 'v' */ LETTER (bit_lower),
/* 'w' */ LETTER (bit_lower),
/* 'x' */ LETTER (bit_lower),
/* 'y' */ LETTER (bit_lower),
/* 'z' */ LETTER (bit_lower),
/* '{' */ bit_print | bit_punct | bit_graph,
/* '|' */ bit_print | bit_punct | bit_graph,
/* '}' */ bit_print | bit_punct | bit_graph,
/* '~' */ bit_print | bit_punct | bit_graph,
/* 0x7f */ bit_cntrl
#elif 'A' == 0xc1
/* NUL */ bit_cntrl,
/* SOH */ bit_cntrl,
/* STX */ bit_cntrl,
/* ETX */ bit_cntrl,
/* PF */ bit_cntrl,
/* HT */ bit_cntrl,
/* LC */ bit_cntrl,
/* DEL */ bit_cntrl,
/* */ 0,
/* */ 0,
/* SMM */ bit_cntrl,
/* VT */ bit_cntrl,
/* FF */ bit_cntrl,
/* CR */ bit_cntrl,
/* SO */ bit_cntrl,
/* SI */ bit_cntrl,
/* DLE */ bit_cntrl,
/* DC1 */ bit_cntrl,
/* DC2 */ bit_cntrl,
/* TM */ bit_cntrl,
/* RES */ bit_cntrl,
/* NL */ bit_cntrl,
/* BS */ bit_cntrl,
/* IL */ bit_cntrl,
/* CAN */ bit_cntrl,
/* EM */ bit_cntrl,
/* CC */ bit_cntrl,
/* CU1 */ bit_cntrl,
/* IFS */ bit_cntrl,
/* IGS */ bit_cntrl,
/* IRS */ bit_cntrl,
/* IUS */ bit_cntrl,
/* DS */ bit_cntrl,
/* SOS */ bit_cntrl,
/* FS */ bit_cntrl,
/* */ 0,
/* BYP */ bit_cntrl,
/* LF */ bit_cntrl,
/* ETB */ bit_cntrl,
/* ESC */ bit_cntrl,
/* */ 0,
/* */ 0,
/* SM */ bit_cntrl,
/* CU2 */ bit_cntrl,
/* */ 0,
/* ENQ */ bit_cntrl,
/* ACK */ bit_cntrl,
/* BEL */ bit_cntrl,
/* */ 0,
/* */ 0,
/* SYN */ bit_cntrl,
/* */ 0,
/* PN */ bit_cntrl,
/* RS */ bit_cntrl,
/* UC */ bit_cntrl,
/* EOT */ bit_cntrl,
/* */ 0,
/* */ 0,
/* */ 0,
/* CU3 */ bit_cntrl,
/* DC4 */ bit_cntrl,
/* NAK */ bit_cntrl,
/* */ 0,
/* SUB */ bit_cntrl,
/* SP */ bit_cntrl,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* ct. */ bit_print | bit_punct | bit_graph,
/* '.' */ bit_print | bit_punct | bit_graph,
/* '<' */ bit_print | bit_punct | bit_graph,
/* '(' */ bit_print | bit_punct | bit_graph,
/* '+' */ bit_print | bit_punct | bit_graph,
/* '|' */ bit_print | bit_punct | bit_graph,
/* '&' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* '!' */ bit_print | bit_punct | bit_graph,
/* '$' */ bit_print | bit_punct | bit_graph,
/* '*' */ bit_print | bit_punct | bit_graph,
/* ')' */ bit_print | bit_punct | bit_graph,
/* ';' */ bit_print | bit_punct | bit_graph,
/* '~' */ bit_print | bit_punct | bit_graph,
/* '-' */ bit_print | bit_punct | bit_graph,
/* '/' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* ',' */ bit_print | bit_punct | bit_graph,
/* '%' */ bit_print | bit_punct | bit_graph,
/* '_' */ bit_print | bit_punct | bit_graph,
/* '>' */ bit_print | bit_punct | bit_graph,
/* '?' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* ':' */ bit_print | bit_punct | bit_graph,
/* '#' */ bit_print | bit_punct | bit_graph,
/* '@' */ bit_print | bit_punct | bit_graph,
/* ''' */ bit_print | bit_punct | bit_graph,
/* '=' */ bit_print | bit_punct | bit_graph,
/* '"' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* 'a' */ LETTER (bit_lower | bit_xdigit),
/* 'b' */ LETTER (bit_lower | bit_xdigit),
/* 'c' */ LETTER (bit_lower | bit_xdigit),
/* 'd' */ LETTER (bit_lower | bit_xdigit),
/* 'e' */ LETTER (bit_lower | bit_xdigit),
/* 'f' */ LETTER (bit_lower | bit_xdigit),
/* 'g' */ LETTER (bit_lower),
/* 'h' */ LETTER (bit_lower),
/* 'i' */ LETTER (bit_lower),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'j' */ LETTER (bit_lower),
/* 'k' */ LETTER (bit_lower),
/* 'l' */ LETTER (bit_lower),
/* 'm' */ LETTER (bit_lower),
/* 'n' */ LETTER (bit_lower),
/* 'o' */ LETTER (bit_lower),
/* 'p' */ LETTER (bit_lower),
/* 'q' */ LETTER (bit_lower),
/* 'r' */ LETTER (bit_lower),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 's' */ LETTER (bit_lower),
/* 't' */ LETTER (bit_lower),
/* 'u' */ LETTER (bit_lower),
/* 'v' */ LETTER (bit_lower),
/* 'w' */ LETTER (bit_lower),
/* 'x' */ LETTER (bit_lower),
/* 'y' */ LETTER (bit_lower),
/* 'z' */ LETTER (bit_lower),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* '`' */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'A' */ LETTER (bit_upper | bit_xdigit),
/* 'B' */ LETTER (bit_upper | bit_xdigit),
/* 'C' */ LETTER (bit_upper | bit_xdigit),
/* 'D' */ LETTER (bit_upper | bit_xdigit),
/* 'E' */ LETTER (bit_upper | bit_xdigit),
/* 'F' */ LETTER (bit_upper | bit_xdigit),
/* 'G' */ LETTER (bit_upper),
/* 'H' */ LETTER (bit_upper),
/* 'I' */ LETTER (bit_upper),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'J' */ LETTER (bit_upper),
/* 'K' */ LETTER (bit_upper),
/* 'L' */ LETTER (bit_upper),
/* 'M' */ LETTER (bit_upper),
/* 'N' */ LETTER (bit_upper),
/* 'O' */ LETTER (bit_upper),
/* 'P' */ LETTER (bit_upper),
/* 'Q' */ LETTER (bit_upper),
/* 'R' */ LETTER (bit_upper),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'S' */ LETTER (bit_upper),
/* 'T' */ LETTER (bit_upper),
/* 'U' */ LETTER (bit_upper),
/* 'V' */ LETTER (bit_upper),
/* 'W' */ LETTER (bit_upper),
/* 'X' */ LETTER (bit_upper),
/* 'Y' */ LETTER (bit_upper),
/* 'Z' */ LETTER (bit_upper),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* '0' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '1' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '2' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '3' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '4' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '5' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '6' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '7' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '8' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '9' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0
#else // 'A' != 0x41 && 'A' != 0xc1
# error unknown character set (neither ASCII nor EBCDIC)
#endif // ASCII or EBCDIC
};
static void
test_behavior ()
{
rw_info (0, 0, 0, "behavior of <cctype> functions in the \"C\" locale");
char extra_str [80];
char missing_str [80];
for (int i = 0; i != 256; ++i) {
typedef unsigned char UChar;
const int c = UChar (i);
int mask = 0;
mask |= std::isalnum (c) ? bit_alnum : 0;
mask |= std::isalpha (c) ? bit_alpha : 0;
mask |= std::iscntrl (c) ? bit_cntrl : 0;
mask |= std::isdigit (c) ? bit_digit : 0;
mask |= std::isgraph (c) ? bit_graph : 0;
mask |= std::islower (c) ? bit_lower : 0;
mask |= std::isprint (c) ? bit_print : 0;
mask |= std::ispunct (c) ? bit_punct : 0;
mask |= std::isspace (c) ? bit_space : 0;
mask |= std::isupper (c) ? bit_upper : 0;
mask |= std::isxdigit (c) ? bit_xdigit : 0;
const int extra_bits = mask & ~char_mask [i];
const int missing_bits = ~mask & char_mask [i];
rw_assert (mask == char_mask [i], 0, 0,
"%#c mask%{?} missing bits %s (%#x)%{;}"
"%{?} extra bits %s (%#x)%{;}",
c,
missing_bits,
get_bitmask (missing_bits, missing_str), missing_bits,
extra_bits,
get_bitmask (extra_bits, extra_str), extra_bits);
}
}
/**************************************************************************/
static int rw_opt_no_behavior; // for --no-behavior
static int
run_test (int, char**)
{
//////////////////////////////////////////////////////////////////
rw_info (0, 0, 0, "checking for the absence of masking macros");
// verify the shadow macros are not #defined (explicitly
// disallowed by 17.4.1.2, p6 and Footnote 159 of C++ '03)
for (unsigned i = 0; cctype_macros [i]; ++i) {
rw_assert ('\0' == cctype_macros [i][0], 0, 0,
"macro %s unexpectedly #defined", cctype_macros [i]);
}
//////////////////////////////////////////////////////////////////
// verify that each function is defined
#define TEST(function) \
do { \
rw_info (0, 0, 0, "%s(int) definition", #function); \
function (function_called = 1); \
rw_assert (1 == function_called, 0, __LINE__, \
"%s (int) not defined", #function); \
} while (0)
TEST (std::isalnum);
TEST (std::isalpha);
TEST (std::iscntrl);
TEST (std::isdigit);
TEST (std::isgraph);
TEST (std::islower);
TEST (std::isprint);
TEST (std::ispunct);
TEST (std::isupper);
TEST (std::isxdigit);
TEST (std::tolower);
TEST (std::toupper);
//////////////////////////////////////////////////////////////////
if (rw_opt_no_behavior)
rw_note (0, 0, 0, "behavior test disabled (use --test-behavior)");
else
test_behavior ();
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.c.strings",
"header <cctype>",
run_test,
"|-no-behavior#0-1 ",
&rw_opt_no_behavior);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,932 @@
/***************************************************************************
*
* 21.cwctype.cpp - test exercising clause lib.string.c.strings,
* header <cwctype>
*
* $Id: 21.cwctype.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2005 Rogue Wave Software.
*
**************************************************************************/
#include <cwctype>
#include <driver.h>
/**************************************************************************/
// detect masking macros
const char* const cwctype_macros [] = {
#ifdef iswalnum
# undef iswalnum
"iswalnum",
#else
"",
#endif
#ifdef iswalpha
# undef iswalpha
"iswalpha",
#else
"",
#endif
#ifdef iswcntrl
# undef iswcntrl
"iswcntrl",
#else
"",
#endif
#ifdef iswctype
# undef iswctype
"iswctype",
#else
"",
#endif
#ifdef iswdigit
# undef iswdigit
"iswdigit",
#else
"",
#endif
#ifdef iswgraph
# undef iswgraph
"iswgraph",
#else
"",
#endif
#ifdef iswlower
# undef iswlower
"iswlower",
#else
"",
#ifdef iswprint
# undef iswprint
"iswprint",
#else
"",
#endif
#ifdef iswpunct
# undef iswpunct
"iswpunct",
#else
"",
#endif
#ifdef iswspace
# undef iswspace
"iswspace",
#else
"",
#endif
#ifdef iswupper
# undef iswupper
"iswupper",
#else
"",
#endif
#ifdef iswxdigit
# undef iswxdigit
"iswxdigit",
#else
"",
#endif
#endif
#ifdef tolower
# undef tolower
"tolower",
#else
"",
#endif
#ifdef toupper
# undef toupper
"toupper",
#else
"",
#endif
#ifdef towctrans
# undef towctrans
"towctrans",
#else
"",
#endif
#ifdef wctrans
# undef wctrans
"wctrans",
#else
"",
#endif
#ifdef wctype
# undef wctype
"wctype",
#else
"",
#endif
0
};
/**************************************************************************/
#ifndef _RWSTD_NO_NAMESPACE
// check types
namespace Fallback {
struct wint_t {
int i_;
char dummy_ [256]; // make sure we're bigger than the real thing
// this (fake) wint_t emulates a scalar type
wint_t (int i): i_ (i) { }
operator int () const { return i_; }
};
struct wctype_t {
int i_;
char dummy_ [256]; // make sure we're bigger than the real thing
// this (fake) wctype_t emulates a scalar type
wctype_t (int i): i_ (i) { }
operator int () const { return i_; }
};
struct wctrans_t {
int i_;
char dummy_ [256]; // make sure we're bigger than the real thing
// this (fake) wctrans_t emulates a scalar type
wctrans_t (int i): i_ (i) { }
operator int () const { return i_; }
};
} // Namespace Fallback
namespace std {
// define test functions in namespace std to detect the presece
// or absence of the required types
namespace Nested {
using namespace Fallback;
// each test_xxx_t typedef aliases std::xxx_t if the corresponding
// type is defined in namespace std, or Fallback::xxx_t otherwise
typedef wint_t test_wint_t;
typedef wctrans_t test_wctrans_t;
typedef wctype_t test_wctype_t;
} // namespace Nested
} // namespace std
typedef std::Nested::test_wint_t test_wint_t;
typedef std::Nested::test_wctrans_t test_wctrans_t;
typedef std::Nested::test_wctype_t test_wctype_t;
const char std_name[] = "std";
static void
test_types ()
{
rw_info (0, 0, 0,
"types %s::wint_t, %1$s::wctrans_t, and %1$s::wctype_t",
std_name);
rw_assert (sizeof (test_wint_t) != sizeof (Fallback::wint_t), 0, 0,
"%s::wint_t not defined", std_name);
// TO DO: exercise wint_t requirements
rw_assert (sizeof (test_wctrans_t) != sizeof (Fallback::wctrans_t), 0, 0,
"%s::wctrans_t not defined", std_name);
// TO DO: exercise wctrans_t requirements (must be a scalar type)
rw_assert (sizeof (test_wctype_t) != sizeof (Fallback::wctype_t), 0, 0,
"%s::wctype_t not defined", std_name);
// TO DO: exercise wctype_t requirements (must be a scalar type)
}
#else // if defined (_RWSTD_NO_NAMESPACE)
const char std_name[] = "";
static void
test_types ()
{
rw_info (0, 0, 0,
"types %s::wint_t, %1s::wctrans_t, and %1s::wctype_t", std_name);
rw_note (0, 0, 0, "_RWSTD_NO_NAMESPACE defined, cannot test");
}
#endif // _RWSTD_NO_NAMESPACE
/**************************************************************************/
enum {
// character classification/function missing bits
bit_alnum = 1, bit_iswalnum = bit_alnum,
bit_alpha = 1 << 1, bit_iswalpha = bit_alpha,
bit_cntrl = 1 << 2, bit_iswcntrl = bit_cntrl,
bit_digit = 1 << 3, bit_iswdigit = bit_digit,
bit_graph = 1 << 4, bit_iswgraph = bit_graph,
bit_lower = 1 << 5, bit_iswlower = bit_lower,
bit_print = 1 << 6, bit_iswprint = bit_print,
bit_punct = 1 << 7, bit_iswpunct = bit_punct,
bit_space = 1 << 8, bit_iswspace = bit_space,
bit_upper = 1 << 9, bit_iswupper = bit_upper,
bit_xdigit = 1 << 10, bit_iswxdigit = bit_xdigit,
// function missing bits
bit_towctrans = 1 << 11,
bit_towlower = 1 << 12,
bit_towupper = 1 << 13,
bit_iswctype = 1 << 14,
bit_wctrans = 1 << 16,
bit_wctype = 1 << 17
};
// each bit is set to 1 if and only if the corresponding function
// is determined to be missing (not declared) in <cwctype>
/* extern */ int missing_set;
// define function template overloads for the <cctype> functions with
// the same name to detect whether the C versions are declared or not
#define TEST_FUNCTION(name, ret) \
template <class T> ret name (T) { \
missing_set |= bit_ ## name; \
return -1; \
} typedef void rw_unused_typedef
_RWSTD_NAMESPACE (std) {
TEST_FUNCTION (iswalnum, int);
TEST_FUNCTION (iswalpha, int);
TEST_FUNCTION (iswcntrl, int);
TEST_FUNCTION (iswdigit, int);
TEST_FUNCTION (iswgraph, int);
TEST_FUNCTION (iswlower, int);
TEST_FUNCTION (iswprint, int);
TEST_FUNCTION (iswpunct, int);
TEST_FUNCTION (iswspace, int);
TEST_FUNCTION (iswupper, int);
TEST_FUNCTION (iswxdigit, int);
TEST_FUNCTION (towlower, wchar_t);
TEST_FUNCTION (towupper, wchar_t);
TEST_FUNCTION (wctrans, wctrans_t);
TEST_FUNCTION (wctype, wctype_t);
template <class T, class U>
int iswctype (T, U) { missing_set |= bit_iswctype; return -1; }
template <class T, class U>
wint_t towctrans (T, U) { missing_set |= bit_towctrans; return -1; }
} // namespace std
/**************************************************************************/
static char*
get_bitmask (int mask, char *str)
{
char *str_save = str;
#define APPEND(bit) \
if (mask & bit_ ## bit) { \
for (const char *s = #bit; *s; ++s, ++str) \
*str = *s; \
*str++ = '|'; \
} else (void)0
APPEND (alnum);
APPEND (alpha);
APPEND (cntrl);
APPEND (digit);
APPEND (graph);
APPEND (lower);
APPEND (print);
APPEND (punct);
APPEND (space);
APPEND (upper);
APPEND (xdigit);
if (str == str_save)
*str = '\0';
else
str [-1] = '\0';
return str_save;
}
static const int
char_mask [256] = {
#undef LETTER
#define LETTER(bits) bit_alpha | bit_alnum | bit_print | bit_graph | bits
#if 'A' == 0x41
/* 0x00 */ bit_cntrl,
/* 0x01 */ bit_cntrl,
/* 0x02 */ bit_cntrl,
/* 0x03 */ bit_cntrl,
/* 0x04 */ bit_cntrl,
/* 0x05 */ bit_cntrl,
/* 0x06 */ bit_cntrl,
/* 0x07 */ bit_cntrl,
/* 0x08 */ bit_cntrl,
/* 0x09 */ bit_space | bit_cntrl,
/* 0x0a */ bit_space | bit_cntrl,
/* 0x0b */ bit_space | bit_cntrl,
/* 0x0c */ bit_space | bit_cntrl,
/* 0x0d */ bit_space | bit_cntrl,
/* 0x0e */ bit_cntrl,
/* 0x0f */ bit_cntrl,
/* 0x10 */ bit_cntrl,
/* 0x11 */ bit_cntrl,
/* 0x12 */ bit_cntrl,
/* 0x13 */ bit_cntrl,
/* 0x14 */ bit_cntrl,
/* 0x15 */ bit_cntrl,
/* 0x16 */ bit_cntrl,
/* 0x17 */ bit_cntrl,
/* 0x18 */ bit_cntrl,
/* 0x19 */ bit_cntrl,
/* 0x1a */ bit_cntrl,
/* 0x1b */ bit_cntrl,
/* 0x1c */ bit_cntrl,
/* 0x1d */ bit_cntrl,
/* 0x1e */ bit_cntrl,
/* 0x1f */ bit_cntrl,
/* ' ' */ bit_space | bit_print,
/* '!' */ bit_print | bit_punct | bit_graph,
/* '"' */ bit_print | bit_punct | bit_graph,
/* '#' */ bit_print | bit_punct | bit_graph,
/* '$' */ bit_print | bit_punct | bit_graph,
/* '%' */ bit_print | bit_punct | bit_graph,
/* '&' */ bit_print | bit_punct | bit_graph,
/* '\'' */ bit_print | bit_punct | bit_graph,
/* '(' */ bit_print | bit_punct | bit_graph,
/* ')' */ bit_print | bit_punct | bit_graph,
/* '*' */ bit_print | bit_punct | bit_graph,
/* '+' */ bit_print | bit_punct | bit_graph,
/* ',' */ bit_print | bit_punct | bit_graph,
/* '-' */ bit_print | bit_punct | bit_graph,
/* '.' */ bit_print | bit_punct | bit_graph,
/* '/' */ bit_print | bit_punct | bit_graph,
/* '0' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '1' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '2' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '3' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '4' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '5' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '6' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '7' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '8' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* '9' */ bit_alnum | bit_print | bit_digit | bit_graph | bit_xdigit,
/* ':' */ bit_print | bit_punct | bit_graph,
/* ';' */ bit_print | bit_punct | bit_graph,
/* '<' */ bit_print | bit_punct | bit_graph,
/* '=' */ bit_print | bit_punct | bit_graph,
/* '>' */ bit_print | bit_punct | bit_graph,
/* '?' */ bit_print | bit_punct | bit_graph,
/* '@' */ bit_print | bit_punct | bit_graph,
/* 'A' */ LETTER (bit_upper | bit_xdigit),
/* 'B' */ LETTER (bit_upper | bit_xdigit),
/* 'C' */ LETTER (bit_upper | bit_xdigit),
/* 'D' */ LETTER (bit_upper | bit_xdigit),
/* 'E' */ LETTER (bit_upper | bit_xdigit),
/* 'F' */ LETTER (bit_upper | bit_xdigit),
/* 'G' */ LETTER (bit_upper),
/* 'H' */ LETTER (bit_upper),
/* 'I' */ LETTER (bit_upper),
/* 'J' */ LETTER (bit_upper),
/* 'K' */ LETTER (bit_upper),
/* 'L' */ LETTER (bit_upper),
/* 'M' */ LETTER (bit_upper),
/* 'N' */ LETTER (bit_upper),
/* 'O' */ LETTER (bit_upper),
/* 'P' */ LETTER (bit_upper),
/* 'Q' */ LETTER (bit_upper),
/* 'R' */ LETTER (bit_upper),
/* 'S' */ LETTER (bit_upper),
/* 'T' */ LETTER (bit_upper),
/* 'U' */ LETTER (bit_upper),
/* 'V' */ LETTER (bit_upper),
/* 'W' */ LETTER (bit_upper),
/* 'X' */ LETTER (bit_upper),
/* 'Y' */ LETTER (bit_upper),
/* 'Z' */ LETTER (bit_upper),
/* '[' */ bit_print | bit_punct | bit_graph,
/* '\\' */ bit_print | bit_punct | bit_graph,
/* ']' */ bit_print | bit_punct | bit_graph,
/* '^' */ bit_print | bit_punct | bit_graph,
/* '_' */ bit_print | bit_punct | bit_graph,
/* '`' */ bit_print | bit_punct | bit_graph,
/* 'a' */ LETTER (bit_lower | bit_xdigit),
/* 'b' */ LETTER (bit_lower | bit_xdigit),
/* 'c' */ LETTER (bit_lower | bit_xdigit),
/* 'd' */ LETTER (bit_lower | bit_xdigit),
/* 'e' */ LETTER (bit_lower | bit_xdigit),
/* 'f' */ LETTER (bit_lower | bit_xdigit),
/* 'g' */ LETTER (bit_lower),
/* 'h' */ LETTER (bit_lower),
/* 'i' */ LETTER (bit_lower),
/* 'j' */ LETTER (bit_lower),
/* 'k' */ LETTER (bit_lower),
/* 'l' */ LETTER (bit_lower),
/* 'm' */ LETTER (bit_lower),
/* 'n' */ LETTER (bit_lower),
/* 'o' */ LETTER (bit_lower),
/* 'p' */ LETTER (bit_lower),
/* 'q' */ LETTER (bit_lower),
/* 'r' */ LETTER (bit_lower),
/* 's' */ LETTER (bit_lower),
/* 't' */ LETTER (bit_lower),
/* 'u' */ LETTER (bit_lower),
/* 'v' */ LETTER (bit_lower),
/* 'w' */ LETTER (bit_lower),
/* 'x' */ LETTER (bit_lower),
/* 'y' */ LETTER (bit_lower),
/* 'z' */ LETTER (bit_lower),
/* '{' */ bit_print | bit_punct | bit_graph,
/* '|' */ bit_print | bit_punct | bit_graph,
/* '}' */ bit_print | bit_punct | bit_graph,
/* '~' */ bit_print | bit_punct | bit_graph,
/* 0x7f */ bit_cntrl
#elif 'A' == 0xc1
/* NUL */ bit_cntrl,
/* SOH */ bit_cntrl,
/* STX */ bit_cntrl,
/* ETX */ bit_cntrl,
/* PF */ bit_cntrl,
/* HT */ bit_cntrl,
/* LC */ bit_cntrl,
/* DEL */ bit_cntrl,
/* */ 0,
/* */ 0,
/* SMM */ bit_cntrl,
/* VT */ bit_cntrl,
/* FF */ bit_cntrl,
/* CR */ bit_cntrl,
/* SO */ bit_cntrl,
/* SI */ bit_cntrl,
/* DLE */ bit_cntrl,
/* DC1 */ bit_cntrl,
/* DC2 */ bit_cntrl,
/* TM */ bit_cntrl,
/* RES */ bit_cntrl,
/* NL */ bit_cntrl,
/* BS */ bit_cntrl,
/* IL */ bit_cntrl,
/* CAN */ bit_cntrl,
/* EM */ bit_cntrl,
/* CC */ bit_cntrl,
/* CU1 */ bit_cntrl,
/* IFS */ bit_cntrl,
/* IGS */ bit_cntrl,
/* IRS */ bit_cntrl,
/* IUS */ bit_cntrl,
/* DS */ bit_cntrl,
/* SOS */ bit_cntrl,
/* FS */ bit_cntrl,
/* */ 0,
/* BYP */ bit_cntrl,
/* LF */ bit_cntrl,
/* ETB */ bit_cntrl,
/* ESC */ bit_cntrl,
/* */ 0,
/* */ 0,
/* SM */ bit_cntrl,
/* CU2 */ bit_cntrl,
/* */ 0,
/* ENQ */ bit_cntrl,
/* ACK */ bit_cntrl,
/* BEL */ bit_cntrl,
/* */ 0,
/* */ 0,
/* SYN */ bit_cntrl,
/* */ 0,
/* PN */ bit_cntrl,
/* RS */ bit_cntrl,
/* UC */ bit_cntrl,
/* EOT */ bit_cntrl,
/* */ 0,
/* */ 0,
/* */ 0,
/* CU3 */ bit_cntrl,
/* DC4 */ bit_cntrl,
/* NAK */ bit_cntrl,
/* */ 0,
/* SUB */ bit_cntrl,
/* SP */ bit_cntrl,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* ct. */ bit_print | bit_punct | bit_graph,
/* '.' */ bit_print | bit_punct | bit_graph,
/* '<' */ bit_print | bit_punct | bit_graph,
/* '(' */ bit_print | bit_punct | bit_graph,
/* '+' */ bit_print | bit_punct | bit_graph,
/* '|' */ bit_print | bit_punct | bit_graph,
/* '&' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* '!' */ bit_print | bit_punct | bit_graph,
/* '$' */ bit_print | bit_punct | bit_graph,
/* '*' */ bit_print | bit_punct | bit_graph,
/* ')' */ bit_print | bit_punct | bit_graph,
/* ';' */ bit_print | bit_punct | bit_graph,
/* '~' */ bit_print | bit_punct | bit_graph,
/* '-' */ bit_print | bit_punct | bit_graph,
/* '/' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* ',' */ bit_print | bit_punct | bit_graph,
/* '%' */ bit_print | bit_punct | bit_graph,
/* '_' */ bit_print | bit_punct | bit_graph,
/* '>' */ bit_print | bit_punct | bit_graph,
/* '?' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* ':' */ bit_print | bit_punct | bit_graph,
/* '#' */ bit_print | bit_punct | bit_graph,
/* '@' */ bit_print | bit_punct | bit_graph,
/* ''' */ bit_print | bit_punct | bit_graph,
/* '=' */ bit_print | bit_punct | bit_graph,
/* '"' */ bit_print | bit_punct | bit_graph,
/* */ 0,
/* 'a' */ LETTER (bit_lower | bit_xdigit),
/* 'b' */ LETTER (bit_lower | bit_xdigit),
/* 'c' */ LETTER (bit_lower | bit_xdigit),
/* 'd' */ LETTER (bit_lower | bit_xdigit),
/* 'e' */ LETTER (bit_lower | bit_xdigit),
/* 'f' */ LETTER (bit_lower | bit_xdigit),
/* 'g' */ LETTER (bit_lower),
/* 'h' */ LETTER (bit_lower),
/* 'i' */ LETTER (bit_lower),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'j' */ LETTER (bit_lower),
/* 'k' */ LETTER (bit_lower),
/* 'l' */ LETTER (bit_lower),
/* 'm' */ LETTER (bit_lower),
/* 'n' */ LETTER (bit_lower),
/* 'o' */ LETTER (bit_lower),
/* 'p' */ LETTER (bit_lower),
/* 'q' */ LETTER (bit_lower),
/* 'r' */ LETTER (bit_lower),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 's' */ LETTER (bit_lower),
/* 't' */ LETTER (bit_lower),
/* 'u' */ LETTER (bit_lower),
/* 'v' */ LETTER (bit_lower),
/* 'w' */ LETTER (bit_lower),
/* 'x' */ LETTER (bit_lower),
/* 'y' */ LETTER (bit_lower),
/* 'z' */ LETTER (bit_lower),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* '`' */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'A' */ LETTER (bit_upper | bit_xdigit),
/* 'B' */ LETTER (bit_upper | bit_xdigit),
/* 'C' */ LETTER (bit_upper | bit_xdigit),
/* 'D' */ LETTER (bit_upper | bit_xdigit),
/* 'E' */ LETTER (bit_upper | bit_xdigit),
/* 'F' */ LETTER (bit_upper | bit_xdigit),
/* 'G' */ LETTER (bit_upper),
/* 'H' */ LETTER (bit_upper),
/* 'I' */ LETTER (bit_upper),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'J' */ LETTER (bit_upper),
/* 'K' */ LETTER (bit_upper),
/* 'L' */ LETTER (bit_upper),
/* 'M' */ LETTER (bit_upper),
/* 'N' */ LETTER (bit_upper),
/* 'O' */ LETTER (bit_upper),
/* 'P' */ LETTER (bit_upper),
/* 'Q' */ LETTER (bit_upper),
/* 'R' */ LETTER (bit_upper),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* 'S' */ LETTER (bit_upper),
/* 'T' */ LETTER (bit_upper),
/* 'U' */ LETTER (bit_upper),
/* 'V' */ LETTER (bit_upper),
/* 'W' */ LETTER (bit_upper),
/* 'X' */ LETTER (bit_upper),
/* 'Y' */ LETTER (bit_upper),
/* 'Z' */ LETTER (bit_upper),
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* '0' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '1' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '2' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '3' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '4' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '5' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '6' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '7' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '8' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* '9' */ bit_print | bit_digit | bit_graph | bit_xdigit,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0,
/* */ 0
#else // 'A' != 0x41 && 'A' != 0xc1
# error unknown character set (neither ASCII nor EBCDIC)
#endif // ASCII or EBCDIC
};
static void
test_behavior ()
{
rw_info (0, 0, 0, "behavior of <cwctype> functions in the \"C\" locale");
char missing_str [80];
for (int i = 0; i != 256; ++i) {
const test_wint_t c = i;
int mask = 0;
// invoke each function that is found to be declared in the header
// and exercise its return value; avoid testing functions that are
// not found to be declared in the header to prevent unnecessary
// noise
#define SET_MASK_BIT(bitno) \
if (bit_ ## bitno & missing_set) \
mask |= char_mask [i] & bit_ ## bitno; \
else \
mask |= std::isw ## bitno (c) ? bit_ ## bitno : 0; \
SET_MASK_BIT (alnum);
SET_MASK_BIT (alpha);
SET_MASK_BIT (cntrl);
SET_MASK_BIT (digit);
SET_MASK_BIT (graph);
SET_MASK_BIT (lower);
SET_MASK_BIT (print);
SET_MASK_BIT (punct);
SET_MASK_BIT (space);
SET_MASK_BIT (upper);
SET_MASK_BIT (xdigit);
// C99 standard (7.25.2.1 p2) implicitly allows
// defining the extra bits in iswxxx()
const int missing_bits = ~mask & char_mask [i];
rw_assert (0 == missing_bits, 0, 0,
"%#c mask missing bits %s (%#x)",
i, get_bitmask (missing_bits, missing_str), missing_bits);
}
}
/**************************************************************************/
static int rw_opt_no_behavior; // for --no-behavior
static int
run_test (int, char**)
{
#ifdef _RWSTD_STRICT_ANSI
# define RW_DIAG rw_assert
#else
# define RW_DIAG rw_warn
#endif
//////////////////////////////////////////////////////////////////
rw_info (0, 0, 0, "checking for the absence of masking macros");
// verify the shadow macros are not #defined (explicitly
// disallowed by 17.4.1.2, p6 and Footnote 159 of C++ '03)
for (unsigned i = 0; cwctype_macros [i]; ++i) {
RW_DIAG ('\0' == cwctype_macros [i][0], 0, 0,
"macro %s unexpectedly #defined", cwctype_macros [i]);
}
//////////////////////////////////////////////////////////////////
#ifndef WEOF
const int weof_defined = 0;
#else // if defined (WEOF)
const int weof_defined = 1;
#endif // WEOF
rw_assert (weof_defined, 0, 0, "macro WEOF unexpectedly not #defined");
//////////////////////////////////////////////////////////////////
test_types ();
//////////////////////////////////////////////////////////////////
// verify that each function is defined
#define TEST(function) \
do { \
rw_info (0, 0, 0, "%s::%s (%s::wint_t) definition", \
std_name, #function, std_name); \
const int result = std::function (test_wint_t ('a')); \
RW_DIAG (-1 != result && !(missing_set & bit_ ## function), \
0, __LINE__, "%s::%s (%s::wint_t) not defined", \
std_name, #function, std_name); \
} while (0)
TEST (iswalnum);
TEST (iswalpha);
TEST (iswcntrl);
TEST (iswdigit);
TEST (iswgraph);
TEST (iswlower);
TEST (iswprint);
TEST (iswspace);
TEST (iswpunct);
TEST (iswupper);
TEST (iswxdigit);
TEST (towlower);
TEST (towupper);
// exercise std::wctype(const char*)
rw_info (0, 0, 0,
"%s::wctype (const char*) definition", std_name);
int result = std::wctype ("");
RW_DIAG (-1 != result && !(missing_set & bit_wctype), 0, __LINE__,
"%s::wctype (const char*) not defined", std_name);
// exercise std::iswctype(std::wint_t, std::wctype_t)
rw_info (0, 0, 0,
"%s::iswctype (%1$s::wint_t, %1$s::wctype_t) definition",
std_name);
const test_wint_t wc = 0;
const test_wctype_t desc = 0;
result = std::iswctype (wc, desc);
RW_DIAG (-1 != result && !(missing_set & bit_iswctype), 0, __LINE__,
"%s::iswctype (%1$s::wint_t, %1$s::wctype_t) not defined",
std_name);
// exercise std::wctrans(const char*)
rw_info (0, 0, 0,
"%s::wctrans (const char*) definition", std_name);
// cast wctrans() result to ptrdiff_t in case it's a pointer
// such as in GNU glibc
result = (int)(_RWSTD_PTRDIFF_T)std::wctrans ("");
RW_DIAG (-1 != result && !(missing_set & bit_wctrans), 0, __LINE__,
"%s::wctrans (const char*) not defined", std_name);
// exercise std::towctrans(wint_t, wctrans_t)
rw_info (0, 0, 0,
"%s::towctrans(wint_t, wctrans_t) definition", std_name);
const test_wctrans_t category = 0;
result = std::towctrans (wc, category);
RW_DIAG (-1 != result && !(missing_set & bit_towctrans), 0, __LINE__,
"%s::towctrans(wint_t, wctrans_t) not defined", std_name);
//////////////////////////////////////////////////////////////////
if (rw_opt_no_behavior)
rw_note (0, 0, 0, "behavior test disabled (use --test-behavior)");
else
test_behavior ();
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.c.strings",
"header <cwctype>",
run_test,
"|-no-behavior#0-1 ",
&rw_opt_no_behavior);
}

View File

@@ -0,0 +1,340 @@
/***************************************************************************
*
* 21.string.access.cpp - test exercising [lib.string.access]
*
* $Id: 21.string.access.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstdlib> // for free(), size_t
#include <stdexcept> // for out_of_range
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define At(sig) StringIds::at_ ## sig
#define OpIndex(sig) StringIds::op_index_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// operator[] (size_type)
static const StringTestCase
op_index_size_test_cases [] = {
#undef TEST
#define TEST(str, off, res) { \
__LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +----------------- index
// | | +------------- expected result
// | | |
// V V V
TEST ("a", 0, 'a' ),
TEST ("<U0>", 0, '\0'),
TEST ("abc", 0, 'a' ),
TEST ("abc", 1, 'b' ),
TEST ("abc", 2, 'c' ),
TEST ("<U0>ab<U0><U0>c", 0, '\0'),
TEST ("a<U0>b<U0><U0>c", 0, 'a' ),
TEST ("a<U0>b<U0><U0>c", 1, '\0'),
TEST ("a<U0>b<U0><U0>c", 2, 'b' ),
TEST ("a<U0>b<U0><U0>c", 3, '\0'),
TEST ("a<U0>b<U0><U0>c", 4, '\0'),
TEST ("a<U0>b<U0><U0>c", 5, 'c' ),
TEST ("a<U0>bc<U0><U0>", 5, '\0'),
TEST ("x@4096", 0, 'x' ),
TEST ("x@4096", 2048, 'x' ),
TEST ("x@4096", 4095, 'x' ),
TEST ("last", 3, 't' )
};
/**************************************************************************/
// used to exercise
// operator[] (size_type) const
static const StringTestCase
op_index_const_size_test_cases [] = {
#undef TEST
#define TEST(str, off, res) { \
__LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +----------------- index
// | | +------------- expected result
// | | |
// V V V
TEST ("a", 0, 'a' ),
TEST ("a", 1, NPOS),
TEST ("", 0, NPOS),
TEST ("<U0>", 0, '\0'),
TEST ("<U0>", 1, NPOS),
TEST ("abc", 0, 'a' ),
TEST ("abc", 1, 'b' ),
TEST ("abc", 2, 'c' ),
TEST ("abc", 3, NPOS),
TEST ("<U0>ab<U0><U0>c", 0, '\0'),
TEST ("a<U0>b<U0><U0>c", 0, 'a' ),
TEST ("a<U0>b<U0><U0>c", 1, '\0'),
TEST ("a<U0>b<U0><U0>c", 2, 'b' ),
TEST ("a<U0>b<U0><U0>c", 3, '\0'),
TEST ("a<U0>b<U0><U0>c", 4, '\0'),
TEST ("a<U0>b<U0><U0>c", 5, 'c' ),
TEST ("a<U0>b<U0><U0>c", 6, NPOS),
TEST ("a<U0>bc<U0><U0>", 5, '\0'),
TEST ("x@4096", 0, 'x' ),
TEST ("x@4096", 2048, 'x' ),
TEST ("x@4096", 4095, 'x' ),
TEST ("x@4096", 4096, NPOS),
TEST ("last", 3, 't' )
};
/**************************************************************************/
// used to exercise
// at (size_type)
// at (size_type) const
static const StringTestCase
at_size_test_cases [] = {
#define at_const_size_test_cases at_size_test_cases
#undef TEST
#define TEST(str, off, res, bthrow) { \
__LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, \
0, 0, 0, res, bthrow \
}
// +--------------------------------------- controlled sequence
// | +----------------- index
// | | +-------------- expected result
// | | | +----- exception info
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// | | | |
// V V V V
TEST ("a", 0, 'a', 0),
TEST ("a", 1, NPOS, 1),
TEST ("", 0, NPOS, 1),
TEST ("<U0>", 0, '\0', 0),
TEST ("<U0>", 1, NPOS, 1),
TEST ("abc", 0, 'a', 0),
TEST ("abc", 1, 'b', 0),
TEST ("abc", 2, 'c', 0),
TEST ("abc", 3, NPOS, 1),
TEST ("<U0>ab<U0><U0>c", 0, '\0', 0),
TEST ("a<U0>b<U0><U0>c", 0, 'a', 0),
TEST ("a<U0>b<U0><U0>c", 1, '\0', 0),
TEST ("a<U0>b<U0><U0>c", 2, 'b', 0),
TEST ("a<U0>b<U0><U0>c", 3, '\0', 0),
TEST ("a<U0>b<U0><U0>c", 4, '\0', 0),
TEST ("a<U0>b<U0><U0>c", 5, 'c', 0),
TEST ("a<U0>b<U0><U0>c", 6, NPOS, 1),
TEST ("a<U0>bc<U0><U0>", 5, '\0', 0),
TEST ("x@4096", 0, 'x', 0),
TEST ("x@4096", 2048, 'x', 0),
TEST ("x@4096", 4095, 'x', 0),
TEST ("x@4096", 4096, NPOS, 1),
TEST ("last", 3, 't', 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_access (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename String::size_type SizeT;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
// construct the string object
/* const */ String str (wstr, str_len);
const String const_str = str;
if (wstr != wstr_buf)
delete[] wstr;
wstr = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 1 == tcase.bthrow ? exceptions[1] : 0;
const char* caught = 0;
#endif // _RWSTD_NO_EXCEPTIONS
try {
const charT *pres = 0;
switch (func.which_) {
case OpIndex (size):
pres = &str [SizeT (tcase.off)];
break;
case OpIndex (const_size):
pres = &const_str [SizeT (tcase.off)];
break;
case At (size):
pres = &str.at (SizeT (tcase.off));
break;
case At (const_size):
pres = &const_str.at (SizeT (tcase.off));
break;
default:
RW_ASSERT (!"test logic error: unknown access overload");
return;
}
const char exp_res [2] = {
NPOS != tcase.nres ? char (tcase.nres) : char (),
char ()
};
const bool success = 1 == rw_match (exp_res, pres, 1);
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL} == %{#c}, got %{#c}",
__LINE__, tcase.nres, *pres);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_access);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
StringIds::sig, sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (op_index_size),
TEST (op_index_const_size),
TEST (at_size),
TEST (at_const_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.access",
test_access, tests, test_count);
}

View File

@@ -0,0 +1,924 @@
/***************************************************************************
*
* 21.string.append.cpp - string test exercising lib.string.append
*
* $Id: 21.string.append.cpp 526961 2007-04-10 00:06:12Z sebor $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
**************************************************************************/
#include <string> // for string
#include <stdexcept> // for out_of_range, length_error
#include <cstddef> // for size_t
#include <21.strings.h> // for StringMembers
#include <alg_test.h> // for InputIter
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define Append(sig) StringIds::append_ ## sig
#define PushBack(sig) StringIds::push_back_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// append (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res, bthrow) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +----------------------- sequence to be appended
// | | +---------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// | | | | 2 - length_error
// | | | | -1 - avoid exc. safety
// | | | |
// | | | +--------------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "<U0>", "", 0),
TEST ("", "abc", "abc", 0),
TEST ("<U0>", "", "<U0>", 0),
TEST ("<U0>", "a", "<U0>a", 0),
TEST ("<U0>", "<U0>@2", "<U0>", 0),
TEST ("ab", "cd", "abcd", 0),
TEST ("bcd", "a", "bcda", 0),
TEST ("cde", "ab", "cdeab", 0),
TEST ("abc", "", "abc", 0),
TEST ("ab", "c<U0>e", "abc", 0),
TEST ("<U0>@2ab", "cdefghij", "<U0>@2abcdefghij", 0),
TEST ("a<U0>@2b", "cdefghij", "a<U0>@2bcdefghij", 0),
TEST ("ab<U0>@2", "cdefghij", "ab<U0>@2cdefghij", 0),
TEST ("a<U0>b<U0>@2c", "e<U0>", "a<U0>b<U0>@2ce", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce", 0),
TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
TEST ("", "x@4096", "x@4096", 0),
TEST ("x@4096", "", "x@4096", 0),
TEST ("x@4096", "x@4096", "x@8192", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST ("", 0, "", 0),
TEST ("abc", 0, "abcabc", 0),
TEST ("a<U0>@2bc", 0, "a<U0>@2bca", 0),
TEST ("<U0>@2abc", 0, "<U0>@2abc", 0),
TEST ("abc<U0>@2", 0, "abc<U0>@2abc", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// append (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(s, arg, res, bthrow) { \
__LINE__, -1, -1, -1, -1, -1, \
s, sizeof s - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +----------------------- sequence to be appended
// | | +---------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// | | | | 2 - length_error
// | | | | -1 - avoid exc. safety
// | | | |
// | | | +--------------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "<U0>", "<U0>", 0),
TEST ("", "abc", "abc", 0),
TEST ("<U0>", "", "<U0>", 0),
TEST ("<U0>", "a", "<U0>a", 0),
TEST ("<U0>", "<U0>@2", "<U0>@3", 0),
TEST ("ab", "cd", "abcd", 0),
TEST ("bcd", "a", "bcda", 0),
TEST ("cde", "ab", "cdeab", 0),
TEST ("abc", "", "abc", 0),
TEST ("ab", "c<U0>e", "abc<U0>e", 0),
TEST ("<U0>@2ab", "cdefghij", "<U0>@2abcdefghij", 0),
TEST ("a<U0>@2b", "cdefghij", "a<U0>@2bcdefghij", 0),
TEST ("ab<U0>@2", "cdefghij", "ab<U0>@2cdefghij", 0),
TEST ("a<U0>b<U0>@2c", "e<U0>", "a<U0>b<U0>@2ce<U0>", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce<U0>", 0),
TEST ("ab<U0>@2c<U0>", "<U0>e", "ab<U0>@2c<U0>@2e", 0),
TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
TEST ("", "x@4096", "x@4096", 0),
TEST ("x@4096", "", "x@4096", 0),
TEST ("x@4096", "x@4096", "x@8192", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST ("", 0, "", 0),
TEST ("abc", 0, "abcabc", 0),
TEST ("a<U0>@2bc", 0, "a<U0>@2bca<U0>@2bc", 0),
TEST ("<U0>@2abc", 0, "<U0>@2abc<U0>@2abc", 0),
TEST ("abc<U0>@2", 0, "abc<U0>@2abc<U0>@2", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// append (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, size, res, bthrow) { \
__LINE__, -1, size, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------- sequence to be appended
// | | +------------ append() n argument
// | | | +--------- expected result sequence
// | | | | +---- exception info
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | | 2 - length_error
// | | | | | -1 - avoid exc. safety
// | | | | |
// | | | | +------------+
// V V V V V
TEST ("ab", "c", 1, "abc", 0),
TEST ("", "", 0, "", 0),
TEST ("", "abc", 1, "a", 0),
TEST ("", "<U0>", 1, "<U0>", 0),
TEST ("<U0>", "", 0, "<U0>", 0),
TEST ("<U0>", "a", 0, "<U0>", 0),
TEST ("<U0>", "a", 1, "<U0>a", 0),
TEST ("<U0>", "<U0>@2", 1, "<U0>@2", 0),
TEST ("<U0>", "<U0>@2", 2, "<U0>@3", 0),
TEST ("cde", "ab", 2, "cdeab", 0),
TEST ("cde", "ab", 1, "cdea", 0),
TEST ("<U0>e<U0>", "a<U0>b<U0>@2c", 0, "<U0>e<U0>", 0),
TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 3, "<U0>e<U0>@2ab", 0),
TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 3, "a<U0>b<U0>@2c<U0>e<U0>", 0),
TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 2, "a<U0>b<U0>@2c<U0>@2", 0),
TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 1, "<U0>ab<U0>@2c<U0>", 0),
TEST ("a<U0>bc<U0>@2", "<U0>e", 2, "a<U0>bc<U0>@3e", 0),
TEST ("x@10", "x@118", 118, "x@128", 0),
TEST ("x@128", "x@79", 79, "x@207", 0),
TEST ("x@207", "x@127", 127, "x@334", 0),
TEST ("x@207", "x@207", 127, "x@334", 0),
TEST ("x@334", "x@206", 206, "x@540", 0),
TEST ("x@540", "x@333", 333, "x@873", 0),
TEST ("x@539", "x@873", 873, "x@1412", 0),
TEST ("x@873", "x@540", 539, "x@1412", 0),
TEST ("x@872", "x@1412", 1412, "x@2284", 0),
TEST ("x@1411", "x@2284", 2284, "x@3695", 0),
TEST ("x@1411", "x@3695", 2284, "x@3695", 0),
TEST ("x@1412", "x@2284", 2284, "x@3696", 0),
TEST ("", 0, 0, "", 0),
TEST ("abc", 0, 0, "abc", 0),
TEST ("abc", 0, 1, "abca", 0),
TEST ("abc", 0, 2, "abcab", 0),
TEST ("a<U0>bc", 0, 2, "a<U0>bca<U0>", 0),
TEST ("<U0>abc<U0>@2", 0, 1, "<U0>abc<U0>@3", 0),
TEST ("a<U0>bc<U0>@2", 0, 3, "a<U0>bc<U0>@2a<U0>b", 0),
TEST ("a@4096", 0, 1111, "a@5207", 0),
TEST ("b@4096", 0, 2222, "b@6318", 0),
TEST ("", "x@4096", 4096, "x@4096", 0),
TEST ("x@4096", "", 0, "x@4096", 0),
TEST ("last", "test", 4, "lasttest", 0)
};
/**************************************************************************/
// exercises:
// append (const basic_string&, size_type, size_type)
// append (InputIterator, InputIterator)
static const StringTestCase
range_test_cases [] = {
// range_test_cases serves a double duty
#define cstr_size_size_test_cases range_test_cases
#undef TEST
#define TEST(str, arg, off, size, res, bthrow) { \
__LINE__, -1, -1, off, size, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------- sequence to be appended
// | | +------------ append() pos argument
// | | | +--------- append() n argument
// | | | | +------ expected result sequence
// | | | | | +--- exception info
// | | | | | | 0 - no exception
// | | | | | | 1 - out_of_range
// | | | | | | 2 - length_error
// | | | | | | -1 - exc. safety
// | | | | | |
// | | | | | +----------------+
// V V V V V V
TEST ("ab", "c", 0, 1, "abc", 0),
TEST ("", "", 0, 0, "", 0),
TEST ("", "abc", 1, 1, "b", 0),
TEST ("", "<U0>", 0, 1, "<U0>", 0),
TEST ("<U0>", "", 0, 0, "<U0>", 0),
TEST ("abc", "", 0, 0, "abc", 0),
TEST ("<U0>", "a", 0, 1, "<U0>a", 0),
TEST ("<U0>", "<U0>@2", 1, 1, "<U0>@2", 0),
TEST ("<U0>", "<U0>@2", 0, 2, "<U0>@3", 0),
TEST ("<U0>", "<U0>@2", 1, 5, "<U0>@2", 0),
TEST ("cde", "ab", 0, 2, "cdeab", 0),
TEST ("cde", "ab", 0, 1, "cdea", 0),
TEST ("cde", "ab", 1, 5, "cdeb", 0),
TEST ("ab", "c<U0>e", 0, 3, "abc<U0>e", 0),
TEST ("ab", "c<U0>e", 1, 2, "ab<U0>e", 0),
TEST ("ab", "c<U0>e", 0, 2, "abc<U0>", 0),
TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 9, "<U0>e<U0>@2ab<U0>@2c", 0),
TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 3, "<U0>e<U0>@2ab", 0),
TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 0, 3, "a<U0>b<U0>@2c<U0>e<U0>", 0),
TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 0, 2, "a<U0>b<U0>@2c<U0>@2", 0),
TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 2, 1, "<U0>ab<U0>@2c<U0>", 0),
TEST ("a<U0>bc<U0>@2", "<U0>e", 0, 2, "a<U0>bc<U0>@3e", 0),
TEST ("", 0, 0, 0, "", 0),
TEST ("abc", 0, 1, 0, "abc", 0),
TEST ("abc", 0, 1, 1, "abcb", 0),
TEST ("abc", 0, 0, 2, "abcab", 0),
TEST ("a<U0>bc<U0>@2", 0, 4, 2, "a<U0>bc<U0>@3<U0>", 0),
TEST ("a<U0>bc<U0>@2", 0, 1, 3, "a<U0>bc<U0>@3bc", 0),
TEST ("a<U0>bc<U0>@2", 0, 3, 9, "a<U0>bc<U0>@2c<U0>@2", 0),
TEST ("abcdef", 0, 1, 2, "abcdefbc", 0),
TEST ("a@1000", "b@1000", 0, 999, "a@1000b@999", 0),
TEST ("a@1000", "b@1001", 0, 1000, "a@1000b@1000", 0),
TEST ("a@1000", "b@1002", 0, 102, "a@1000b@102", 0),
TEST ("", "x@4096", 0, 4096, "x@4096", 0),
TEST ("x@4096", "", 0, 0, "x@4096", 0),
TEST ("x@4096", "a@4096", 100, 10, "x@4096a@10", 0),
TEST ("x@10", "x@118", 0, 118, "x@128", 0),
TEST ("x@128", "x@129", 50, 79, "x@207", 0),
TEST ("x@207", "x@127", 0, 127, "x@334", 0),
TEST ("x@207", "x@207", 10, 127, "x@334", 0),
TEST ("x@334", "x@208", 2, 206, "x@540", 0),
TEST ("x@540", "x@336", 3, 333, "x@873", 0),
TEST ("x@539", "x@873", 0, 873, "x@1412", 0),
TEST ("x@873", "x@540", 1, 539, "x@1412", 0),
TEST ("x@872", "x@1412", 0, 1412, "x@2284", 0),
TEST ("x@1411", "x@2288", 4, 2284, "x@3695", 0),
TEST ("x@1411", "x@3695", 128, 2284, "x@3695", 0),
TEST ("x@1412", "x@2284", 0, 2284, "x@3696", 0),
TEST ("", "<U0>", 2, 0, "", 1),
TEST ("", "a", 2, 0, "", 1),
TEST ("", "x@4096", 4106, 0, "", 1),
TEST ("last", "test", 0, 4, "lasttest", 0)
};
/**************************************************************************/
// exercises:
// append (value_type, size_type)
static const StringTestCase
size_val_test_cases [] = {
#undef TEST
#define TEST(str, size, val, res, bthrow) { \
__LINE__, -1, size, -1, -1, val, \
str, sizeof str - 1, \
0, 0, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------- append() count argument
// | | +--------------------- character to be appended
// | | | +----------------- expected result sequence
// | | | | +--------- exception info
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | | 2 - length_error
// | | | | | -1 - exc. safety
// | | | | |
// | | | | +-----------+
// V V V V V
TEST ("ab", 1, 'c', "abc", 0),
TEST ("", 0, ' ', "", 0),
TEST ("", 1, 'b', "b", 0),
TEST ("", 3, 'b', "bbb", 0),
TEST ("<U0>", 0, ' ', "<U0>", 0),
TEST ("", 2, '\0', "<U0>@2", 0),
TEST ("<U0>", 1, 'a', "<U0>a", 0),
TEST ("<U0>", 1, '\0', "<U0>@2", 0),
TEST ("<U0>", 2, '\0', "<U0>@3", 0),
TEST ("<U0>", 0, '\0', "<U0>", 0),
TEST ("cde", 1, 'a', "cdea", 0),
TEST ("cde", 2, 'a', "cdeaa", 0),
TEST ("cde", 3, 'a', "cdeaaa", 0),
TEST ("ab", 2, '\0', "ab<U0>@2", 0),
TEST ("ab", 1, '\0', "ab<U0>", 0),
TEST ("ab", 2, '\0', "ab<U0>@2", 0),
TEST ("a<U0>b<U0>@2c", 2, '\0', "a<U0>b<U0>@2c<U0>@2", 0),
TEST ("a<U0>b<U0>@2c", 1, '\0', "a<U0>b<U0>@2c<U0>", 0),
TEST ("<U0>ab<U0>@2c", 3, '\0', "<U0>ab<U0>@2c<U0>@3", 0),
TEST ("a<U0>bc<U0>@2", 2, 'a', "a<U0>bc<U0>@2aa", 0),
TEST ("", 4096, 'x', "x@4096", 0),
TEST ("x@4096", 0, 'x', "x@4096", 0),
TEST ("x@127", 1, 'x', "x@128", 0),
TEST ("x@200", 7, 'x', "x@207", 0),
TEST ("x@331", 3, 'x', "x@334", 0),
TEST ("x@539", 1, 'x', "x@540", 0),
TEST ("x@539", 873, 'x', "x@1412", 0),
TEST ("x@873", 1411, 'x', "x@2284", 0),
TEST ("x@3694", 1, 'x', "x@3695", 0),
TEST ("x@540", 1, 'x', "x@541", 0),
TEST ("last", 4, 't', "lasttttt", 0)
};
/**************************************************************************/
// exercises:
// push_back (value_type)
static const StringTestCase
push_back_val_test_cases [] = {
#undef TEST
#define TEST(str, val, res, bthrow) { \
__LINE__, -1, -1, -1, -1, val, \
str, sizeof str - 1, \
0, 0, res, sizeof res - 1, bthrow \
}
// +---------------------------------------- controlled sequence
// | +---------------------- character to be appended
// | | +----------------- expected result sequence
// | | | +--------- exception info
// | | | | 0 - no exception
// | | | | -1 - exc. safety
// | | | |
// | | | +------------+
// V V V V
TEST ("ab", 'c', "abc", 0),
TEST ("", 'a', "a", 0),
TEST ("", '\0', "<U0>", 0),
TEST ("<U0>", 'a', "<U0>a", 0),
TEST ("<U0>", '\0', "<U0>@2", 0),
TEST ("a<U0>b<U0>@2c", '\0', "a<U0>b<U0>@2c<U0>", 0),
TEST ("a<U0>bc<U0>@2", 'a', "a<U0>bc<U0>@2a", 0),
TEST ("<U0>abc<U0>@2", 'a', "<U0>abc<U0>@2a", 0),
TEST ("x@4095", 'x', "x@4096", 0),
TEST ("x@127", 'x', "x@128", 0),
TEST ("x@206", 'x', "x@207", 0),
TEST ("x@333", 'x', "x@334", 0),
TEST ("x@539", 'x', "x@540", 0),
TEST ("x@1411", 'x', "x@1412", 0),
TEST ("x@2283", 'x', "x@2284", 0),
TEST ("x@3694", 'x', "x@3695", 0),
TEST ("x@540", 'x', "x@541", 0),
TEST ("last", 't', "lastt", 0)
};
/**************************************************************************/
// invokes specializations of the member function template
// on the required iterator categories
template <class String, class Iterator>
struct AppendRange: RangeBase<String> {
typedef typename String::iterator StringIter;
typedef typename String::value_type StringChar;
AppendRange () { }
virtual String&
operator() (String &str,
const StringTestCaseData<StringChar>& tdata) const {
const StringTestCase &tcase = tdata.tcase_;
const String &cstr = str;
// when (0 == tcase.arg) exercise self-referential modification
// (i.e., replacing a range of elements with a subrange of its
// own elements)
const StringChar* const beg =
(tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
const StringChar* const end = beg + tdata.ext2_;
const Iterator first (beg, beg, end);
const Iterator last (end, beg, end);
return str.append (first, last);
}
};
/**************************************************************************/
// invokes possible overloads of the member function template
// on common RandomAccessIterator types
template <class String, class Iterator>
struct AppendRangeOverload: RangeBase<String>
{
typedef typename String::iterator StringIter;
typedef typename String::value_type StringChar;
AppendRangeOverload () { }
virtual String&
operator() (String &str,
const StringTestCaseData<StringChar>& tdata) const {
const StringTestCase &tcase = tdata.tcase_;
bool reverse_iter = StringIds::ReverseIterator == tdata.func_.iter_id_
|| StringIds::ConstReverseIterator == tdata.func_.iter_id_;
const std::size_t srclen_ = tcase.arg ? tdata.arglen_ : str.size ();
const std::size_t off =
reverse_iter ? srclen_ - tdata.off2_ - tdata.ext2_ : tdata.off2_;
const std::size_t ext = tdata.ext2_;
if (0 == tcase.arg) {
// exercise self-referential modification (i.e., replacing
// a range of elements with a subrange of its own elements)
const Iterator first (this->begin (str, (Iterator*)0) + off);
const Iterator last (first + ext);
return str.append (first, last);
}
String str_arg (tdata.arg_, tdata.arglen_);
const Iterator first (this->begin (str_arg, (Iterator*)0) + off);
const Iterator last (first + ext);
return str.append (first, last);
}
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_append (charT*, Traits*, Allocator*, const RangeBase<
std::basic_string <charT, Traits, Allocator> > &rng,
const StringTestCaseData<charT> &tdata)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename String::size_type SizeT;
typedef typename String::iterator StringIter;
typedef typename UserTraits<charT>::MemFun TraitsFunc;
const StringFunc &func = tdata.func_;
const StringTestCase &tcase = tdata.tcase_;
// construct the string object to be modified
// and the (possibly unused) argument string
/* const */ String str (tdata.str_, tdata.strlen_);
const String arg (tdata.arg_, tdata.arglen_);
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
const charT* const ptr_arg = tcase.arg ? arg.c_str () : str.c_str ();
const String& str_arg = tcase.arg ? arg : str;
const charT val_arg = (make_char (char (tcase.val), (charT*)0));
std::size_t total_length_calls = 0;
std::size_t n_length_calls = 0;
std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls)
total_length_calls = rg_calls [TraitsFunc::length];
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (1 == tcase.bthrow && Append (cstr_size_size) == func.which_)
expected = exceptions [1]; // out_of_range
else if (2 == tcase.bthrow)
expected = exceptions [2]; // length_error
else if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
else {
// exceptions disabled for this test case
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
// pointer to the returned reference
const String* ret_ptr = 0;
// start checking for memory leaks
rw_check_leaks (str.get_allocator ());
try {
switch (func.which_) {
case Append (cptr):
ret_ptr = &str.append (ptr_arg);
if (rg_calls)
n_length_calls = rg_calls [TraitsFunc::length];
break;
case Append (cstr):
ret_ptr = &str.append (str_arg);
break;
case Append (cptr_size):
ret_ptr = &str.append (ptr_arg, tcase.size);
break;
case Append (cstr_size_size):
ret_ptr = &str.append (str_arg,
SizeT (tcase.off2), SizeT (tcase.size2));
break;
case Append (size_val):
ret_ptr = &str.append (tcase.size, val_arg);
break;
case Append (range):
ret_ptr = &rng (str, tdata);
break;
case PushBack (val):
str.push_back (val_arg);
ret_ptr = &str;
break;
default:
RW_ASSERT (!"logic error: unknown append overload");
}
// verify that the reference returned from the function
// refers to the modified string object (i.e., *this
// within the function)
const std::ptrdiff_t ret_off = ret_ptr - &str;
// verify the returned value
rw_assert (0 == ret_off, 0, tcase.line,
"line %d. %{$FUNCALL} returned invalid reference, "
"offset is %td", __LINE__, ret_off);
// for convenience
static const int cwidth = sizeof (charT);
// verify that strings are of equal length
rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
"line %d. %{$FUNCALL} expected %{/*.*Gs}, "
"length %zu, got %{/*.*Gs}, length %zu",
__LINE__, cwidth, int (tdata.reslen_), tdata.res_,
tdata.reslen_, cwidth,
int (str.size ()), str.c_str (), str.size ());
if (tdata.reslen_ == str.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the modified
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, str.c_str (), str.size ());
rw_assert (match == tdata.reslen_, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{/*.*Gs}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, cwidth, int (tdata.reslen_), tdata.res_,
cwidth, int (str.size ()), str.c_str (), match);
}
// verify that Traits::length was used
if (Append (cptr) == func.which_ && rg_calls) {
rw_assert (n_length_calls - total_length_calls > 0,
0, tcase.line, "line %d. %{$FUNCALL} doesn't "
"use traits::length()", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::bad_alloc &ex) {
caught = exceptions [3];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
// verify that if exceptions are enabled and when capacity changes
// at least one exception is thrown
const std::size_t expect_throws = str_state.capacity_ < str.capacity ();
#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
const std::size_t expect_throws =
(StringIds::UserAlloc == func.alloc_id_)
? str_state.capacity_ < str.capacity (): 0;
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
// verify number of exceptions thrown
// for range version the allocation may take place several times
if (Append (range) != func.which_)
rw_assert (expect_throws == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected exactly 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, str.capacity (), throw_count);
else
rw_assert (expect_throws <= throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected at least 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, str.capacity (), throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
}
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_append (charT*, Traits*, Allocator*,
const StringTestCaseData<charT> &tdata)
{
typedef std::basic_string<charT, Traits, Allocator> String;
if (tdata.func_.which_ == Append (range)) {
switch (tdata.func_.iter_id_) {
// exercise possible overloads of the member function template
// on common RandomAccessIterator types
#undef TEST
#define TEST(Iterator) do { \
typedef typename String::Iterator Iter; \
static const \
AppendRangeOverload<String, Iter> rng; \
test_append ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
} while (0)
case StringIds::Pointer: TEST (pointer); break;
case StringIds::ConstPointer: TEST (const_pointer); break;
case StringIds::Iterator: TEST (iterator); break;
case StringIds::ConstIterator: TEST (const_iterator); break;
case StringIds::ReverseIterator: TEST (reverse_iterator); break;
case StringIds::ConstReverseIterator: TEST (const_reverse_iterator);
break;
// exercise specializations of the member function template
// on the required iterator categories
#undef TEST
#define TEST(Iterator) do { \
typedef Iterator<charT> Iter; \
static const \
AppendRange<String, Iter> rng; \
test_append ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
} while (0)
case StringIds::Input: TEST (InputIter); break;
case StringIds::Forward: TEST (ConstFwdIter); break;
case StringIds::Bidir: TEST (ConstBidirIter); break;
case StringIds::Random: TEST (ConstRandomAccessIter); break;
default:
rw_error (0, 0, __LINE__, "bad iterator id");
}
}
else {
// exercise ordinary overloads of the member function
static const RangeBase<String > rng;
test_append ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_FUNCTIONS (test_append);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Append (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cstr_size_size),
TEST (size_val),
TEST (range),
{
StringIds::push_back_val, push_back_val_test_cases,
sizeof push_back_val_test_cases / sizeof *push_back_val_test_cases
}
};
const std::size_t test_count = sizeof tests / sizeof *tests;
const int status =
rw_run_string_test (argc, argv, __FILE__,
"lib.string.append",
test_append_func_array, tests, test_count);
return status;
}

View File

@@ -0,0 +1,870 @@
/***************************************************************************
*
* 21.string.assign.cpp - test exercising [lib.string.assign]
*
* $Id: 21.string.assign.cpp 424860 2006-07-23 23:50:25Z sebor $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for size_t
#include <stdexcept> // for out_of_range, length_error
#include <21.strings.h> // for StringMembers
#include <alg_test.h> // for InputIter
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define Assign(sig) StringIds::assign_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise:
// assign (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res, bthrow) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------ sequence to be assigned
// | | +---------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// | | | | 2 - length_error
// | | | | -1 - exc. safety
// | | | |
// | | | +-------+
// V V V V
TEST ("ab", "c", "c", 0),
TEST ("", "", "", 0),
TEST ("", "<U0>", "", 0),
TEST ("", "abc", "abc", 0),
TEST ("abc", "", "", 0),
TEST ("<U0>", "", "", 0),
TEST ("<U0>", "a", "a", 0),
TEST ("<U0>", "<U0>@2", "", 0),
TEST ("<U0>@2ab", "cdefghij", "cdefghij", 0),
TEST ("a<U0>@2b", "cdefghij", "cdefghij", 0),
TEST ("ab<U0>@2", "cdefghij", "cdefghij", 0),
TEST ("a<U0>b<U0>@2c", "e<U0>", "e", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "e", 0),
TEST ("", "x@4096", "x@4096", 0),
TEST ("x@4096", "", "", 0),
TEST ("a@4096", "b@4096", "b@4096", 0),
TEST ("", "x@207", "x@207", 0),
TEST ("x@128", "x@207", "x@207", 0),
TEST ("x@540", "x@207", "x@207", 0),
TEST ("", "x@1412", "x@1412", 0),
TEST ("x@128", "x@1412", "x@1412", 0),
TEST ("x@3695", "x@1412", "x@1412", 0),
TEST ("x@872", "x@873", "x@873", 0),
TEST ("x@873", "x@3695", "x@3695", 0),
TEST ("", 0, "", 0),
TEST ("abc", 0, "abc", 0),
TEST ("a<U0>@2bc", 0, "a", 0),
TEST ("<U0>@2abc", 0, "", 0),
TEST ("abc<U0>@2", 0, "abc", 0),
TEST ("x@4096", 0, "x@4096", 0),
TEST ("last", "test", "test", 0)
};
/**************************************************************************/
// used to exercise:
// assign (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(s, arg, res, bthrow) { \
__LINE__, -1, -1, -1, -1, -1, \
s, sizeof s - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------ sequence to be assigned
// | | +---------- expected result sequence
// | | | +- exception info:
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// | | | | 2 - length_error
// | | | | -1 - exc. safety
// | | | |
// | | | +-----+
// | | | |
// V V V V
TEST ("ab", "c", "c", 0),
TEST ("", "", "", 0),
TEST ("", "<U0>", "<U0>", 0),
TEST ("", "abc", "abc", 0),
TEST ("abc", "", "", 0),
TEST ("<U0>", "", "", 0),
TEST ("<U0>", "a", "a", 0),
TEST ("<U0>", "<U0>@2", "<U0>@2", 0),
TEST ("ab", "c<U0>e", "c<U0>e", 0),
TEST ("<U0>@2ab", "cdefghij", "cdefghij", 0),
TEST ("a<U0>@2b", "cdefghij", "cdefghij", 0),
TEST ("ab<U0>@2", "cdefghij", "cdefghij", 0),
TEST ("a<U0>b<U0>@2c", "e<U0>", "e<U0>", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "e<U0>", 0),
TEST ("ab<U0>@2c<U0>", "<U0>e", "<U0>e", 0),
TEST ("e<U0>", "a<U0>b<U0>@2c", "a<U0>b<U0>@2c", 0),
TEST ("e<U0>@2", "<U0>ab<U0>@2c", "<U0>ab<U0>@2c", 0),
TEST ("<U0>e", "ab<U0>@2c<U0>", "ab<U0>@2c<U0>", 0),
TEST ("", "x@4096", "x@4096", 0),
TEST ("x@4096", "", "", 0),
TEST ("a@4096", "b@4096", "b@4096", 0),
TEST ("", "x@207", "x@207", 0),
TEST ("x@128", "x@207", "x@207", 0),
TEST ("x@540", "x@207", "x@207", 0),
TEST ("", "x@1412", "x@1412", 0),
TEST ("x@128", "x@1412", "x@1412", 0),
TEST ("x@3695", "x@1412", "x@1412", 0),
TEST ("x@872", "x@873", "x@873", 0),
TEST ("x@873", "x@3695", "x@3695", 0),
TEST ("", 0, "", 0),
TEST ("abc", 0, "abc", 0),
TEST ("a<U0>@2bc", 0, "a<U0>@2bc", 0),
TEST ("<U0>@2abc", 0, "<U0>@2abc", 0),
TEST ("abc<U0>@2", 0, "abc<U0>@2", 0),
TEST ("x@4096", 0, "x@4096", 0),
TEST ("last", "test", "test", 0)
};
/**************************************************************************/
// used to exercise:
// assign (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, size, res, bthrow) { \
__LINE__, -1, size, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------- sequence to be assigned
// | | +------------ assign() n argument
// | | | +-------- expected result sequence
// | | | | +-- exception info
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | | 2 - length_error
// | | | | | -1 - exc. safety
// | | | | |
// | | | | +----------+
// V V V V V
TEST ("ab", "c", 1, "c", 0),
TEST ("", "", 0, "", 0),
TEST ("", "abc", 1, "a", 0),
TEST ("", "<U0>", 1, "<U0>", 0),
TEST ("<U0>", "", 0, "", 0),
TEST ("<U0>", "a", 0, "", 0),
TEST ("<U0>", "a", 1, "a", 0),
TEST ("<U0>", "<U0>@2", 1, "<U0>", 0),
TEST ("<U0>", "<U0>@2", 2, "<U0>@2", 0),
TEST ("cde", "ab", 2, "ab", 0),
TEST ("cde", "ab", 1, "a", 0),
TEST ("<U0>e<U0>", "a<U0>b<U0>@2c", 0, "", 0),
TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 3, "<U0>ab", 0),
TEST ("<U0>e<U0>", "a<U0>b<U0>@2c", 6, "a<U0>b<U0>@2c", 0),
TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 3, "<U0>e<U0>", 0),
TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 2, "<U0>@2", 0),
TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 1, "<U0>", 0),
TEST ("a<U0>bc<U0>@2", "<U0>e", 2, "<U0>e", 0),
TEST ("", 0, 0, "", 0),
TEST ("abc", 0, 0, "", 0),
TEST ("abc", 0, 1, "a", 0),
TEST ("abc", 0, 2, "ab", 0),
TEST ("a<U0>bc", 0, 2, "a<U0>", 0),
TEST ("<U0>abc<U0>@2", 0, 1, "<U0>", 0),
TEST ("a<U0>bc<U0>@2", 0, 3, "a<U0>b", 0),
TEST ("a<U0>bc<U0>@2", 0, 6, "a<U0>bc<U0>@2", 0),
TEST ("x@4096", 0, 2048, "x@2048", 0),
TEST ("", "x@4096", 4096, "x@4096", 0),
TEST ("abcd", "x@4096", 0, "", 0),
TEST ("x@4096", "x@4096", 0, "", 0),
TEST ("x@4096", "x@4096", 1, "x", 0),
TEST ("x@4096", "", 0, "", 0),
TEST ("a@4096", "b@4096", 2048, "b@2048", 0),
TEST ("", "x@207", 207, "x@207", 0),
TEST ("x@128", "x@334", 207, "x@207", 0),
TEST ("x@540", "x@207", 128, "x@128", 0),
TEST ("", "x@1412", 873, "x@873", 0),
TEST ("x@128", "x@1412", 1412, "x@1412", 0),
TEST ("x@3695", "x@1412", 540, "x@540", 0),
TEST ("x@872", "x@873", 873, "x@873", 0),
TEST ("x@873", "x@3695", 2284, "x@2284", 0),
TEST ("", "", -1, "", 2),
TEST ("last", "test", 4, "test", 0)
};
/**************************************************************************/
// used to exercise:
// assign (const basic_string&, size_type, size_type)
// assign (InputIterator, InputIterator)
static const StringTestCase
range_test_cases [] = {
// range_test_cases serves a double duty
#define cstr_size_size_test_cases range_test_cases
#undef TEST
#define TEST(str, arg, off, size, res, bthrow) { \
__LINE__, -1, -1, off, size, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------------- sequence to be inserted
// | | +------------ assign() pos argument
// | | | +--------- assign() n argument
// | | | | +------ expected result sequence
// | | | | | +--- exception info
// | | | | | | 0 - no exception
// | | | | | | 1 - out_of_range
// | | | | | | 2 - length_error
// | | | | | | -1 - exc. safety
// | | | | | |
// | | | | | +---------------+
// V V V V V V
TEST ("ab", "c", 0, 1, "c", 0),
TEST ("", "", 0, 0, "", 0),
TEST ("", "abc", 1, 1, "b", 0),
TEST ("", "<U0>", 0, 1, "<U0>", 0),
TEST ("<U0>", "", 0, 0, "", 0),
TEST ("abc", "", 0, 0, "", 0),
TEST ("<U0>", "a", 0, 1, "a", 0),
TEST ("<U0>", "<U0>@2", 1, 1, "<U0>", 0),
TEST ("<U0>", "<U0>@2", 0, 2, "<U0>@2", 0),
TEST ("<U0>", "<U0>@2", 1, 5, "<U0>", 0),
TEST ("cde", "ab", 0, 2, "ab", 0),
TEST ("cde", "ab", 0, 1, "a", 0),
TEST ("cde", "ab", 1, 5, "b", 0),
TEST ("ab", "c<U0>e", 0, 3, "c<U0>e", 0),
TEST ("ab", "c<U0>e", 1, 2, "<U0>e", 0),
TEST ("ab", "c<U0>e", 0, 2, "c<U0>", 0),
TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 9, "<U0>ab<U0>@2c", 0),
TEST ("<U0>e<U0>", "<U0>ab<U0>@2c", 0, 3, "<U0>ab", 0),
TEST ("a<U0>b<U0>@2c", "<U0>e<U0>", 0, 3, "<U0>e<U0>", 0),
TEST ("a<U0>b<U0>@2c", "<U0>@2e<U0>", 0, 2, "<U0>@2", 0),
TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 2, 1, "<U0>", 0),
TEST ("<U0>ab<U0>@2c", "<U0>e<U0>", 2, 9, "<U0>", 0),
TEST ("a<U0>bc<U0>@2", "<U0>e", 0, 2, "<U0>e", 0),
TEST ("", 0, 0, 0, "", 0),
TEST ("abc", 0, 1, 0, "", 0),
TEST ("abc", 0, 1, 1, "b", 0),
TEST ("abc", 0, 0, 2, "ab", 0),
TEST ("a<U0>bc<U0>@2", 0, 4, 2, "<U0>@2", 0),
TEST ("a<U0>bc<U0>@2", 0, 1, 3, "<U0>bc", 0),
TEST ("a<U0>bc<U0>@2", 0, 0, 9, "a<U0>bc<U0>@2", 0),
TEST ("abcdef", 0, 1, 2, "bc", 0),
TEST ("x@4096", 0, 1, 2, "xx", 0),
TEST ("x@4096", "", 0, 0, "", 0),
TEST ("", "x@4096", 9, 2, "xx", 0),
TEST ("", "x@4096", 9, 0, "", 0),
TEST ("abc", "x@4096", 2, 1, "x", 0),
TEST ("x@4096", "x@4096", 2, 3, "xxx", 0),
TEST ("", "x@4096", 0, 4096, "x@4096", 0),
TEST ("", "x@4096", 100, 2000, "x@2000", 0),
TEST ("", "x@207", 0, 207, "x@207", 0),
TEST ("x@128", "x@334", 10, 207, "x@207", 0),
TEST ("x@540", "x@207", 50, 128, "x@128", 0),
TEST ("", "x@1412", 128, 873, "x@873", 0),
TEST ("x@128", "x@1412", 0, 1412, "x@1412", 0),
TEST ("x@3695", "x@1412", 207, 540, "x@540", 0),
TEST ("x@872", "x@874", 1, 873, "x@873", 0),
TEST ("x@873", "x@3695", 10, 2284, "x@2284", 0),
TEST ("", "<U0>", 2, 0, "", 1),
TEST ("", "a", 2, 0, "", 1),
TEST ("", "x@4096", 4106, 0, "", 1),
TEST ("last", "test", 0, 4, "test", 0)
};
/**************************************************************************/
// used to exercise:
// assign (size_type, value_type)
static const StringTestCase
size_val_test_cases [] = {
#undef TEST
#define TEST(str, size, val, res, bthrow) { \
__LINE__, -1, size, -1, -1, val, \
str, sizeof str - 1, \
0, 0, res, sizeof res - 1, bthrow \
}
// +----------------------------------------- controlled sequence
// | +------------------------ assign() count argument
// | | +-------------------- character to be assigned
// | | | +---------------- expected result sequence
// | | | | +-------- exception info
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | | 2 - length_error
// | | | | | -1 - exc. safety
// | | | | |
// | | | | +--------+
// V V V V V
TEST ("ab", 1, 'c', "c", 0),
TEST ("", 0, ' ', "", 0),
TEST ("", 1, 'b', "b", 0),
TEST ("", 3, 'b', "bbb", 0),
TEST ("<U0>", 0, ' ', "", 0),
TEST ("", 2, '\0', "<U0>@2", 0),
TEST ("<U0>", 1, 'a', "a", 0),
TEST ("<U0>", 1, '\0', "<U0>", 0),
TEST ("<U0>", 2, '\0', "<U0>@2", 0),
TEST ("<U0>", 0, '\0', "", 0),
TEST ("cde", 3, 'a', "aaa", 0),
TEST ("ab", 2, '\0', "<U0>@2", 0),
TEST ("ab", 1, '\0', "<U0>", 0),
TEST ("a<U0>b<U0>@2c", 2, '\0', "<U0>@2", 0),
TEST ("a<U0>b<U0>@2c", 1, '\0', "<U0>", 0),
TEST ("<U0>ab<U0>@2c", 3, '\0', "<U0>@3", 0),
TEST ("a<U0>bc<U0>@2", 2, 'a', "aa", 0),
TEST ("", 4096, 'x', "x@4096", 0),
TEST ("x@4096", 0, 'x', "", 0),
TEST ("x@127", 128, 'x', "x@128", 0),
TEST ("x@200", 207, 'x', "x@207", 0),
TEST ("x@334", 128, 'x', "x@128", 0),
TEST ("", 540, 'x', "x@540", 0),
TEST ("xx", 873, 'x', "x@873", 0),
TEST ("x@873", 1412, 'x', "x@1412", 0),
TEST ("x@3695", 207, 'x', "x@207", 0),
TEST ("x@540", 3695, 'x', "x@3695", 0),
TEST ("", -1, 'x', "", 2),
TEST ("last", 4, 't', "tttt", 0)
};
/**************************************************************************/
// invokes specializations of the member function template
// on the required iterator categories
template <class String, class Iterator>
struct AssignRange: RangeBase<String> {
typedef typename String::iterator StringIter;
typedef typename String::value_type StringChar;
AssignRange () { }
virtual String&
operator() (String &str,
const StringTestCaseData<StringChar>& tdata) const {
const StringTestCase &tcase = tdata.tcase_;
const String &cstr = str;
// when (0 == tcase.arg) exercise self-referential modification
// (i.e., replacing a range of elements with a subrange of its
// own elements)
const StringChar* const beg =
(tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
const StringChar* const end = beg + tdata.ext2_;
const Iterator first (beg, beg, end);
const Iterator last (end, beg, end);
return str.assign (first, last);
}
};
/**************************************************************************/
// invokes possible overloads of the member function template
// on common RandomAccessIterator types
template <class String, class Iterator>
struct AssignRangeOverload: RangeBase<String>
{
typedef typename String::iterator StringIter;
typedef typename String::value_type StringChar;
AssignRangeOverload () { }
virtual String&
operator() (String &str,
const StringTestCaseData<StringChar>& tdata) const {
const StringTestCase &tcase = tdata.tcase_;
bool reverse_iter = StringIds::ReverseIterator == tdata.func_.iter_id_
|| StringIds::ConstReverseIterator == tdata.func_.iter_id_;
const std::size_t srclen_ = tcase.arg ? tdata.arglen_ : str.size ();
const std::size_t off =
reverse_iter ? srclen_ - tdata.off2_ - tdata.ext2_ : tdata.off2_;
const std::size_t ext = tdata.ext2_;
if (0 == tcase.arg) {
// exercise self-referential modification (i.e., replacing
// a range of elements with a subrange of its own elements)
const Iterator first (this->begin (str, (Iterator*)0) + off);
const Iterator last (first + ext);
return str.assign (first, last);
}
String str_arg (tdata.arg_, tdata.arglen_);
const Iterator first (this->begin (str_arg, (Iterator*)0) + off);
const Iterator last (first + ext);
return str.assign (first, last);
}
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_assign (charT*, Traits*, Allocator*, const RangeBase<
std::basic_string <charT, Traits, Allocator> > &rng,
const StringTestCaseData<charT> &tdata)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename String::iterator StringIter;
typedef typename UserTraits<charT>::MemFun TraitsFunc;
const StringFunc &func = tdata.func_;
const StringTestCase &tcase = tdata.tcase_;
// construct the string object to be modified
// and the (possibly unused) argument string
/* const */ String str (tdata.str_, tdata.strlen_);
const String arg (tdata.arg_, tdata.arglen_);
std::size_t size = tcase.size >= 0 ? tcase.size : str.max_size () + 1;
std::size_t size2 = tcase.size2 >= 0 ? tcase.size2 : str.max_size () + 1;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
// first function argument
const charT* const arg_ptr = tcase.arg ? arg.c_str () : str.c_str ();
const String& arg_str = tcase.arg ? arg : str;
std::size_t total_length_calls = 0;
std::size_t n_length_calls = 0;
std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls)
total_length_calls = rg_calls [TraitsFunc::length];
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (1 == tcase.bthrow && Assign (cstr_size_size) == func.which_)
expected = exceptions [1]; // out_of_range
else if (2 == tcase.bthrow)
expected = exceptions [2]; // length_error
else if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
else {
// exceptions disabled for this test case
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
// pointer to the returned reference
const String* ret_ptr = 0;
// start checking for memory leaks
rw_check_leaks (str.get_allocator ());
try {
switch (func.which_) {
case Assign (cptr):
ret_ptr = &str.assign (arg_ptr);
if (rg_calls)
n_length_calls = rg_calls [TraitsFunc::length];
break;
case Assign (cstr):
ret_ptr = &str.assign (arg_str);
break;
case Assign (cptr_size):
ret_ptr = &str.assign (arg_ptr, size);
break;
case Assign (cstr_size_size):
ret_ptr = &str.assign (arg_str, tcase.off2, size2);
break;
case Assign (size_val): {
const charT val = make_char (char (tcase.val), (charT*)0);
ret_ptr = &str.assign (size, val);
break;
}
case Assign (range):
ret_ptr = &rng (str, tdata);
break;
default:
RW_ASSERT (!"test logic error: unknown assign overload");
}
// verify that the reference returned from the function
// refers to the modified string object (i.e., *this
// within the function)
const std::ptrdiff_t ret_off = ret_ptr - &str;
// verify the returned value
rw_assert (0 == ret_off, 0, tcase.line,
"line %d. %{$FUNCALL} returned invalid reference, "
"offset is %td", __LINE__, ret_off);
// for convenience
static const int cwidth = sizeof (charT);
// verfiy that strings length are equal
rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
"line %d. %{$FUNCALL}: expected %{/*.*Gs} with length "
"%zu, got %{/*.*Gs} with length %zu", __LINE__,
cwidth, int (tdata.reslen_), tdata.res_, tdata.reslen_,
cwidth, int (str.size ()), str.c_str (), str.size ());
if (tdata.reslen_ == str.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the modified
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, str.c_str(), str.size ());
rw_assert (match == tdata.reslen_, 0, tcase.line,
"line %d. %{$FUNCALL}: expected %{/*.*Gs}, "
"got %{/*.*Gs}, difference at off %zu",
__LINE__, cwidth, int (tdata.reslen_), tdata.res_,
cwidth, int (str.size ()), str.c_str (), match);
}
// verify that Traits::length was used
if (Assign (cptr) == func.which_ && rg_calls) {
rw_assert (n_length_calls - total_length_calls > 0,
0, tcase.line, "line %d. %{$FUNCALL} doesn't "
"use traits::length()", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::bad_alloc &ex) {
caught = exceptions [3];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
std::size_t expect_throws = 0;
#ifndef _RWSTD_NO_STRING_REF_COUNT
if (Assign (cstr) != func.which_) {
#endif
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
// verify that if exceptions are enabled and when capacity changes
// at least one exception is thrown
expect_throws = str_state.capacity_ < str.capacity ();
#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
expect_throws = (StringIds::UserAlloc == func.alloc_id_)
? str_state.capacity_ < str.capacity (): 0;
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
#ifndef _RWSTD_NO_STRING_REF_COUNT
}
#endif
// verify number of exceptions thrown
// for range version the allocation may take place several times
if (Assign (range) != func.which_)
rw_assert (expect_throws == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected exactly 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, str.capacity (), throw_count);
else
rw_assert (expect_throws <= throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected at least 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, str.capacity (), throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
}
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_assign (charT*, Traits*, Allocator*,
const StringTestCaseData<charT> &tdata)
{
typedef std::basic_string<charT, Traits, Allocator> String;
if (tdata.func_.which_ == Assign (range)) {
switch (tdata.func_.iter_id_) {
// exercise possible overloads of the member function template
// on common RandomAccessIterator types
#undef TEST
#define TEST(Iterator) do { \
typedef typename String::Iterator Iter; \
static const \
AssignRangeOverload<String, Iter> rng; \
test_assign ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
} while (0)
case StringIds::Pointer: TEST (pointer); break;
case StringIds::ConstPointer: TEST (const_pointer); break;
case StringIds::Iterator: TEST (iterator); break;
case StringIds::ConstIterator: TEST (const_iterator); break;
case StringIds::ReverseIterator: TEST (reverse_iterator); break;
case StringIds::ConstReverseIterator: TEST (const_reverse_iterator);
break;
// exercise specializations of the member function template
// on the required iterator categories
#undef TEST
#define TEST(Iterator) do { \
typedef Iterator<charT> Iter; \
static const \
AssignRange<String, Iter> rng; \
test_assign ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \
} while (0)
case StringIds::Input: TEST (InputIter); break;
case StringIds::Forward: TEST (ConstFwdIter); break;
case StringIds::Bidir: TEST (ConstBidirIter); break;
case StringIds::Random: TEST (ConstRandomAccessIter); break;
default:
rw_error (0, 0, __LINE__, "bad iterator id");
}
}
else {
// exercise ordinary overloads of the member function
static const RangeBase<String> rng;
test_assign ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_FUNCTIONS (test_assign);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Assign (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cstr_size_size),
TEST (size_val),
TEST (range)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
const int status =
rw_run_string_test (argc, argv, __FILE__,
"lib.string.assign",
test_assign_func_array, tests, test_count);
return status;
}

View File

@@ -0,0 +1,846 @@
/***************************************************************************
*
* 21.string.capacity.cpp - test exercising [lib.string.capacity]
*
* $Id: 21.string.capacity.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for ptrdiff_t, size_t
#include <stdexcept> // for out_of_range
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define Size(sig) StringIds::size_ ## sig
#define Length(sig) StringIds::length_ ## sig
#define MaxSize(sig) StringIds::max_size_ ## sig
#define Resize(sig) StringIds::resize_ ## sig
#define Capacity(sig) StringIds::capacity_ ## sig
#define Reserve(sig) StringIds::reserve_ ## sig
#define Clear(sig) StringIds::clear_ ## sig
#define Empty(sig) StringIds::empty_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// size ()
static const StringTestCase
size_void_test_cases [] = {
#define length_void_test_cases size_void_test_cases
#undef TEST
#define TEST(str, res) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
0, res, -1 \
}
// +--------------------------------------- controlled sequence
// | +------------------ expected result
// | |
// | |
// V V
TEST (0, 0),
TEST ("", 0),
TEST ("<U0>", 1),
TEST ("a", 1),
TEST (" ", 1),
TEST ("ab", 2),
TEST ("bc", 2),
TEST ("test string", 11),
TEST ("Test String", 11),
TEST ("t<U0> s", 4),
TEST ("Test<U0>string", 11),
TEST ("<U0>a<U0>b", 4),
TEST ("a<U0>@2b", 4),
TEST ("a<U0>@3b", 5),
TEST ("a<U0>@2b<U0>", 5),
TEST ("a<U0>b<U0>@2c", 6),
TEST ("a<U0>b<U0>c<U0>@2", 7),
TEST ("x@128", 128),
TEST ("x@207", 207),
TEST ("x@334", 334),
TEST ("x@540", 540),
TEST ("x@873", 873),
TEST ("x@1412", 1412),
TEST ("x@2284", 2284),
TEST ("x@3695", 3695),
TEST ("x@4096", 4096),
TEST ("last", 4)
};
/**************************************************************************/
// used to exercise
// max_size ()
static const StringTestCase
max_size_void_test_cases [] = {
#undef TEST
#define TEST(str) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
0, 0, -1 \
}
// +------------------------------ controlled sequence
// |
// |
// |
// V
TEST (0),
TEST (""),
TEST ("<U0>"),
TEST ("a"),
TEST ("test string"),
TEST ("a<U0>b<U0>c<U0>@2"),
TEST ("x@128"),
TEST ("x@207"),
TEST ("x@2284"),
TEST ("x@3695"),
TEST ("last")
};
/**************************************************************************/
// used to exercise
// resize (size_type, value_type)
static const StringTestCase
resize_size_val_test_cases [] = {
#undef TEST
#define TEST(str, size, val, res, bthrow) { \
__LINE__, -1, size, -1, -1, val, \
str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------- new size
// | | +------------- value_type argument
// | | | +-------- expected result sequence
// | | | | +- exception info
// | | | | | 0 - no exception
// | | | | | 1 - length_error
// | | | | |
// | | | | +-----------+
// V V V V V
TEST ("", 0, 'a', "", 0),
TEST ("", 5, '\0', "<U0>@3<U0>@2", 0),
TEST ("", 334, 'x', "x@334", 0),
TEST ("<U0>", 0, 'a', "", 0),
TEST ("<U0>", 2, 'a', "<U0>a", 0),
TEST ("<U0>", 1, 'a', "<U0>", 0),
TEST ("<U0>", 128, 'a', "<U0>a@127", 0),
TEST ("a", 0, 'a', "", 0),
TEST ("a", 2, '\0', "a<U0>", 0),
TEST ("a", 540, 'a', "a@540", 0),
TEST ("a<U0>@3b", 10, 'a', "a<U0>@3baaaaa", 0),
TEST ("ab<U0>@3", 10, 'a', "ab<U0>@3aaaaa", 0),
TEST ("<U0>@3ab", 10, 'a', "<U0>@3abaaaaa", 0),
TEST ("a<U0>@3b", 7, '\0', "a<U0>@3b<U0>@2", 0),
TEST ("ab<U0>@3", 7, '\0', "ab<U0>@3<U0>@2", 0),
TEST ("<U0>@3ba", 7, '\0', "<U0>@3ba<U0>@2", 0),
TEST ("a<U0>b<U0>c<U0>@2", 6, 'a', "a<U0>b<U0>c<U0>", 0),
TEST ("a<U0>b<U0>c<U0>@2", 5, '\0', "a<U0>b<U0>c", 0),
TEST ("<U0>ba<U0>c<U0>@2", 1, '\0', "<U0>", 0),
TEST ("<U0>ba<U0>c<U0>@2", 0, '\0', "", 0),
TEST ("x@540", 127, 'a', "x@127", 0),
TEST ("x@873", 127, 'a', "x@127", 0),
TEST ("x@1412", 127, 'a', "x@127", 0),
TEST ("x@2284", 127, 'a', "x@127", 0),
TEST ("x@127", 128, 'a', "x@127a", 0),
TEST ("x@128", 207, 'a', "x@128a@79", 0),
TEST ("x@207", 334, 'a', "x@207a@127", 0),
TEST ("x@334", 540, 'a', "x@334a@206", 0),
TEST ("x@540", 873, 'a', "x@540a@333", 0),
TEST ("x@873", 1412, 'a', "x@873a@539", 0),
TEST ("x@1412", 2284, 'a', "x@1412a@872", 0),
TEST ("x@2284", 3695, 'a', "x@2284a@1411", 0),
TEST ("", NPOS, 'a', "", 1),
TEST ("abc", NPOS, 'a', "abc", 1),
TEST ("x@3695", NPOS, 'a', "x@3695", 1),
TEST ("last", 4, 't', "last", 0)
};
/**************************************************************************/
// used to exercise
// resize (size_type)
static const StringTestCase
resize_size_test_cases [] = {
#undef TEST
#define TEST(str, size, res, bthrow) { \
__LINE__, -1, size, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------- new size
// | | +-------------- expected result sequence
// | | | +-- exception info
// | | | | 0 - no exception
// | | | | 1 - length_error
// | | | |
// V V V V
TEST ("", 0, "", 0),
TEST ("", 5, "", 0),
TEST ("", 334, "", 0),
TEST ("<U0>", 0, "", 0),
TEST ("<U0>", 2, "<U0>", 0),
TEST ("<U0>", 1, "<U0>", 0),
TEST ("<U0>", 127, "<U0>", 0),
TEST ("a", 0, "", 0),
TEST ("a", 2, "a", 0),
TEST ("a", 539, "a", 0),
TEST ("a<U0>@3b", 10, "a<U0>@3b", 0),
TEST ("ab<U0>@3", 10, "ab<U0>@3", 0),
TEST ("<U0>@3ab", 10, "<U0>@3ab", 0),
TEST ("a<U0>@3b", 7, "a<U0>@3b", 0),
TEST ("ab<U0>@3", 7, "ab<U0>@3", 0),
TEST ("<U0>@3ba", 7, "<U0>@3ba", 0),
TEST ("a<U0>b<U0>c<U0>@2", 5, "a<U0>b<U0>c", 0),
TEST ("a<U0>b<U0>c<U0>@2", 4, "a<U0>b<U0>", 0),
TEST ("<U0>ba<U0>c<U0>@2", 1, "<U0>", 0),
TEST ("<U0>ba<U0>c<U0>@2", 0, "", 0),
TEST ("x@540", 127, "x@127", 0),
TEST ("x@873", 127, "x@127", 0),
TEST ("x@1412", 127, "x@127", 0),
TEST ("x@2284", 127, "x@127", 0),
TEST ("x@127", 128, "x@127", 0),
TEST ("x@128", 207, "x@128", 0),
TEST ("x@207", 334, "x@207", 0),
TEST ("x@334", 540, "x@334", 0),
TEST ("x@540", 873, "x@540", 0),
TEST ("x@873", 1412, "x@873", 0),
TEST ("x@1412", 2284, "x@1412", 0),
TEST ("x@2284", 3695, "x@2284", 0),
TEST ("", NPOS, "", 1),
TEST ("abc", NPOS, "abc", 1),
TEST ("x@3695", NPOS, "x@3695", 1),
TEST ("last", 4, "last", 0)
};
/**************************************************************************/
// used to exercise
// capacity ()
static const StringTestCase
capacity_void_test_cases [] = {
#undef TEST
#define TEST(str) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
0, 0, -1 \
}
// +------------------------------ controlled sequence
// |
// |
// |
// V
TEST (0),
TEST (""),
TEST ("<U0>"),
TEST ("a"),
TEST ("test string"),
TEST ("a<U0>b<U0>c<U0>@2"),
TEST ("x@128"),
TEST ("x@207"),
TEST ("x@334"),
TEST ("x@540"),
TEST ("x@873"),
TEST ("x@1412"),
TEST ("x@2284"),
TEST ("x@3695"),
TEST ("x@4096"),
TEST ("last")
};
/**************************************************************************/
// used to exercise
// reserve (size_type)
static const StringTestCase
reserve_size_test_cases [] = {
#undef TEST
#define TEST(str, size, bthrow) { \
__LINE__, -1, size, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
0, 0, bthrow \
}
// +--------------------------------------- controlled sequence
// | +---------------- requested capacity
// | | +----------- exception info
// | | | 0 - no exception
// | | | 1 - length_error
// | | |
// V V V
TEST ("", 0, 0),
TEST ("", 5, 0),
TEST ("", 334, 0),
TEST ("<U0>", 0, 0),
TEST ("<U0>", 2, 0),
TEST ("<U0>", 1, 0),
TEST ("<U0>", 127, 0),
TEST ("a", 0, 0),
TEST ("a", 2, 0),
TEST ("a", 539, 0),
TEST ("a<U0>@3b", 10, 0),
TEST ("ab<U0>@3", 10, 0),
TEST ("<U0>@3ab", 10, 0),
TEST ("a<U0>b<U0>c<U0>@2", 5, 0),
TEST ("a<U0>b<U0>c<U0>@2", 4, 0),
TEST ("<U0>ba<U0>c<U0>@2", 1, 0),
TEST ("<U0>ba<U0>c<U0>@2", 0, 0),
TEST ("x@540", 127, 0),
TEST ("x@873", 127, 0),
TEST ("x@1412", 127, 0),
TEST ("x@2284", 127, 0),
TEST ("x@127", 1412, 0),
TEST ("x@128", 1412, 0),
TEST ("x@206", 207, 0),
TEST ("x@333", 334, 0),
TEST ("x@540", 540, 0),
TEST ("x@873", 873, 0),
TEST ("x@1412", 2284, 0),
TEST ("x@2284", 3695, 0),
TEST ("", NPOS, 1),
TEST ("abc", NPOS, 1),
TEST ("x@3695", NPOS, 1),
TEST ("last", 4, 0)
};
/**************************************************************************/
// used to exercise
// reserve ()
static const StringTestCase
reserve_void_test_cases [] = {
#undef TEST
#define TEST(str) { \
__LINE__, -1, 0, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
0, 0, -1 \
}
// +----------------------------- controlled sequence
// |
// |
// V
TEST (""),
TEST ("<U0>"),
TEST ("a"),
TEST ("a<U0>@3b"),
TEST ("a<U0>b<U0>c<U0>@2"),
TEST ("x@127"),
TEST ("x@128"),
TEST ("x@206"),
TEST ("x@333"),
TEST ("x@540"),
TEST ("x@873"),
TEST ("x@1412"),
TEST ("x@2284"),
TEST ("last")
};
/**************************************************************************/
// used to exercise
// clear ()
static const StringTestCase
clear_void_test_cases [] = {
#undef TEST
#define TEST(str) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
"", 0, -1 \
}
// +------------------------------ controlled sequence
// |
// |
// |
// V
TEST (0),
TEST (""),
TEST ("<U0>"),
TEST ("a"),
TEST ("test string"),
TEST ("a<U0>b<U0>c<U0>@2"),
TEST ("x@128"),
TEST ("x@207"),
TEST ("x@334"),
TEST ("x@540"),
TEST ("x@873"),
TEST ("x@1412"),
TEST ("x@2284"),
TEST ("x@3695"),
TEST ("x@4096"),
TEST ("last")
};
/**************************************************************************/
// used to exercise
// empty ()
static const StringTestCase
empty_void_test_cases [] = {
#undef TEST
#define TEST(str, res) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
0, res, -1 \
}
// +------------------------------ controlled sequence
// | +--------------- expected result
// | |
// | |
// V V
TEST (0, 1),
TEST ("", 1),
TEST ("<U0>", 0),
TEST ("a", 0),
TEST ("<U0>ab<U0>c", 0),
TEST ("x@128", 0),
TEST ("x@3695", 0),
TEST ("last", 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_capacity (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename UserTraits<charT>::MemFun UTMemFun;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
static charT wres_buf [BUFSIZE];
std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
// construct the string object to be modified and constant one
String str (wstr, str_len);
const String cstr (wstr, str_len);
if (wstr != wstr_buf)
delete[] wstr;
wstr = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
const charT arg_val = -1 != tcase.val ?
make_char (char (tcase.val), (charT*)0)
: make_char (char (), (charT*)0);
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (1 == tcase.bthrow)
expected = exceptions [2]; // length_error
else if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
else {
// exceptions disabled for this test case
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
// start checking for memory leaks
rw_check_leaks (str.get_allocator ());
std::size_t res = 0;
try {
switch (func.which_) {
case Size (void):
res = cstr.size ();
break;
case Length (void):
res = cstr.length ();
break;
case MaxSize (void):
res = cstr.max_size ();
break;
case Resize (size_val):
str.resize (tcase.size, arg_val);
break;
case Resize (size):
str.resize (tcase.size);
break;
case Capacity (void):
res = cstr.capacity ();
break;
case Reserve (size):
str.reserve (tcase.size);
break;
case Reserve (void):
str.reserve ();
break;
case Clear (void):
str.clear ();
break;
case Empty (void):
res = cstr.empty () ? 1 : 0;
break;
default:
RW_ASSERT ("test logic error: unknown capacity overload");
return;
}
// verify the returned value
if (func.which_ == StringIds::size_void
|| func.which_ == StringIds::length_void
|| func.which_ == StringIds::empty_void) {
rw_assert (res == tcase.nres, 0, tcase.line,
"line %d. %{$FUNCALL} expected %zu, got %zu",
__LINE__, tcase.nres, res);
}
if (func.which_ == StringIds::capacity_void) {
std::size_t cur_sz = cstr.size ();
std::size_t max_sz = cstr.max_size ();
rw_assert (cur_sz <= res && res <= max_sz, 0, tcase.line,
"line %d. %{$FUNCALL} == %zu, "
"expected %zu < res < %zu",
__LINE__, res, cur_sz, max_sz);
}
if (func.which_ == StringIds::max_size_void) {
std::size_t cur_sz = cstr.size ();
rw_assert (cur_sz <= res, 0, tcase.line,
"line %d. %{$FUNCALL} == %zu, expected res > %zu",
__LINE__, res, cur_sz);
}
if (func.which_ == StringIds::reserve_size
|| func.which_ == StringIds::reserve_void) {
res = str.capacity ();
rw_assert (std::size_t (tcase.size) <= res, 0, tcase.line,
"line %d. %{$FUNCALL} : capacity() >= "
"%zu, got %zu", __LINE__, tcase.size, res);
}
if (func.which_ == StringIds::resize_size_val
|| func.which_ == StringIds::clear_void) {
// verfiy that strings length are equal
rw_assert (res_len == str.size (), 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s} "
"with length %zu, got %{/*.*Gs} with length %zu",
__LINE__, int (tcase.nres), tcase.res, res_len,
int (sizeof (charT)), int (str.size ()),
str.c_str (), str.size ());
if (res_len == str.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the modified
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, str.c_str(), str.size ());
rw_assert (match == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (str.size ()),
str.c_str (), match);
}
}
if (func.which_ == StringIds::resize_size) {
std::size_t match =
rw_match (tcase.res, str.data (), res_len);
rw_assert (match == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (str.size ()),
str.c_str (), match);
for (std::size_t tmp = res_len; tmp < str.size (); tmp++) {
char c = char ();
match = rw_match (&c, str.data () + tmp, 1);
rw_assert (1 == match, 0, tcase.line,
"line %d. %{$FUNCALL} expected %c "
"at offset %zu, got %{#c}",
__LINE__, c, tmp, str.data () + tmp);
}
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::bad_alloc &ex) {
caught = exceptions [3];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
// verify that if exceptions are enabled and when capacity changes
// at least one exception is thrown
const std::size_t expect_throws = str_state.capacity_ < str.capacity ();
#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
const std::size_t expect_throws =
(StringIds::UserAlloc == func.alloc_id_)
? str_state.capacity_ < str.capacity () : 0;
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
rw_assert (expect_throws == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected exactly 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, str.capacity (), throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
if (wres != wres_buf)
delete[] wres;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_capacity);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(gsig, sig) { \
gsig, sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (StringIds::size_void, size_void),
TEST (StringIds::length_void, length_void),
TEST (StringIds::max_size_void, max_size_void),
TEST (StringIds::resize_size_val, resize_size_val),
TEST (StringIds::resize_size, resize_size),
TEST (StringIds::capacity_void, capacity_void),
TEST (StringIds::reserve_size, reserve_size),
TEST (StringIds::reserve_void, reserve_void),
TEST (StringIds::clear_void, clear_void),
TEST (StringIds::empty_void, empty_void)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.capacity",
test_capacity, tests, test_count);
}

View File

@@ -0,0 +1,889 @@
/***************************************************************************
*
* 21.string.compare.cpp - string test exercising lib.string.compare
*
* $Id: 21.string.compare.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for size_t
#include <stdexcept> // for out_of_range, length_error
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_assert()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define Compare(sig) StringIds::compare_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// compare (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res, bthrow) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, bthrow \
}
// +------------------------------------------ controlled sequence
// | +----------------------- sequence to be inserted
// | | +------ expected result
// | | | +-- exception info
// | | | | 0 - no exception
// | | | | 1,2 - out_of_range
// | | | | 3 - length_error
// | | | |
// | | | |
// V V V V
TEST ("ab", "ab", 0, 0),
TEST ("", "", 0, 0),
TEST ("", "\0", 0, 0),
TEST ("", "a", NPOS, 0),
TEST ("\0", "", 1, 0),
TEST ("\0", "\0", 1, 0),
TEST ("\0", "a", NPOS, 0),
TEST ("abcdefghij", "abcdefghij", 0, 0),
TEST ("abcdefghij", "abcdefghi", 1, 0),
TEST ("abcdefghi", "abcdefghij", NPOS, 0),
TEST ("abbdefghij", "abcdefghij", NPOS, 0),
TEST ("abcdeeghij", "abcdefghij", NPOS, 0),
TEST ("abcdefghii", "abcdefghij", NPOS, 0),
TEST ("bbcdefghij", "a", 1, 0),
TEST ("eeeeeeghij", "aeeee", 1, 0),
TEST ("a", "bbcdefghij", NPOS, 0),
TEST ("aeeee", "eeeeeeghij", NPOS, 0),
TEST ("bbcdefghij", "abcdefghij", 1, 0),
TEST ("abcdffghij", "abcdefghij", 1, 0),
TEST ("abcdefghjj", "abcdefghij", 1, 0),
TEST ("a\0b\0\0c", "a\0b\0\0c", 1, 0),
TEST ("abc\0\0\0", "abc\0\0\0", 1, 0),
TEST ("\0ab\0\0c", "e\0ab\0\0c", NPOS, 0),
TEST ("a\0b", "a\0b\0\0c", 1, 0),
TEST ("ab\0", "abc\0\0\0", NPOS, 0),
TEST ("\0ab", "e\0ab\0\0c", NPOS, 0),
TEST ("x@4096", "x@4096", 0, 0),
TEST ("xx", "x@4096", NPOS, 0),
TEST ("x@4096", "xxxxxx", 1, 0),
TEST ("a\0b", "x@4096", NPOS, 0),
TEST ("x@4096", "a\0b", 1, 0),
TEST ("a@2048b@2048", "a@2048b@2047", 1, 0),
TEST ("a@2048b@2048", "a@2048b@2047c", NPOS, 0),
TEST ("a@2048cb@2047", "a@2048cb@2047", 0, 0),
TEST ("last", "last", 0, 0)
};
/**************************************************************************/
// exercises:
// compare (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res, bthrow) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, bthrow \
}
// +------------------------------------------- controlled sequence
// | +------------------------ sequence to be compared
// | | +------- expected result
// | | | +- exception info
// | | | | 0 - no exception
// | | | | 1,2 - out_of_range
// | | | | 3 - length_error
// | | | |
// | | | |
// V V V V
TEST ("ab", "ab", 0, 0),
TEST ("", "", 0, 0),
TEST ("", "\0", NPOS, 0),
TEST ("", "a", NPOS, 0),
TEST ("\0", "", 1, 0),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "a", NPOS, 0),
TEST ("abcdefghij", "abcdefghij", 0, 0),
TEST ("abcdefghij", "abcdefghi", 1, 0),
TEST ("abcdefghi", "abcdefghij", NPOS, 0),
TEST ("abbdefghij", "abcdefghij", NPOS, 0),
TEST ("abcdeeghij", "abcdefghij", NPOS, 0),
TEST ("abcdefghii", "abcdefghij", NPOS, 0),
TEST ("bbcdefghij", "a", 1, 0),
TEST ("eeeeeeghij", "aeeee", 1, 0),
TEST ("a", "bbcdefghij", NPOS, 0),
TEST ("aeeee", "eeeeeeghij", NPOS, 0),
TEST ("bbcdefghij", "abcdefghij", 1, 0),
TEST ("abcdffghij", "abcdefghij", 1, 0),
TEST ("abcdefghjj", "abcdefghij", 1, 0),
TEST ("a\0b\0\0c", "a\0b\0\0c", 0, 0),
TEST ("abc\0\0\0", "bac\0\0\0", NPOS, 0),
TEST ("\0ab\0\0c", "e\0ab\0\0c", NPOS, 0),
TEST ("\0ab\0\0c", "\0ab\0\0b", 1, 0),
TEST ("a\0b", "a\0b\0\0c", NPOS, 0),
TEST ("ab\0", "abc\0\0\0", NPOS, 0),
TEST ("\0ab", "e\0ab\0\0c", NPOS, 0),
TEST ("bb\0", "ab\0\0\0c", 1, 0),
TEST ("\0ac", "\0abe\0\0c", 1, 0),
TEST ("x@4096", "x@4096", 0, 0),
TEST ("xx", "x@4096", NPOS, 0),
TEST ("x@4096", "xxxxxx", 1, 0),
TEST ("a\0b", "x@4096", NPOS, 0),
TEST ("x@4096", "a\0b", 1, 0),
TEST ("a@2048b@2048", "a@2048b@2047", 1, 0),
TEST ("a@2048b@2048", "a@2048b@2047c", NPOS, 0),
TEST ("a@2048cb@2047", "a@2048cb@2047", 0, 0),
TEST ("last", "last", 0, 0)
};
/**************************************************************************/
// exercises:
// compare (size_type, size_type, const value_type*)
static const StringTestCase
size_size_cptr_test_cases [] = {
#undef TEST
#define TEST(str, off, size, arg, res, bthrow) { \
__LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, bthrow \
}
// +------------------------------------------ controlled sequence
// | +--------------------------- compare() off argument
// | | +----------------------- compare() n1 argument
// | | | +-------------------- sequence to be compared
// | | | | +--- expected result
// | | | | | +- exception info
// | | | | | | 0 - no exception
// | | | | | | 1,2 - out_of_range
// | | | | | | 3 - length_error
// | | | | | |
// | | | | | |
// V V V V V V
TEST ("ab", 0, 2, "ab", 0, 0),
TEST ("", 0, 0, "", 0, 0),
TEST ("", 0, 0, "\0", 0, 0),
TEST ("", 0, 0, "a", NPOS, 0),
TEST ("\0", 0, 1, "", 1, 0),
TEST ("\0", 0, 1, "\0", 1, 0),
TEST ("\0", 0, 1, "a", NPOS, 0),
TEST ("abcdefghij", 0, 10, "abcdefghij", 0, 0),
TEST ("abcdefghij", 0, 10, "abcdefghi", 1, 0),
TEST ("abcdefghij", 1, 9, "abcdefghi", 1, 0),
TEST ("abcdefghij", 1, 8, "abcdefghi", 1, 0),
TEST ("abcdefghij", 2, 5, "abcdefghi", 1, 0),
TEST ("abcdefghi", 0, 9, "abcdefghij", NPOS, 0),
TEST ("abbdefghij", 0, 10, "abcdefghij", NPOS, 0),
TEST ("abbdefghij", 1, 9, "abcdefghij", 1, 0),
TEST ("abcdeeghij", 0, 10, "abcdefghij", NPOS, 0),
TEST ("abcdeeghij", 5, 10, "abcdefghij", 1, 0),
TEST ("abcdeeghij", 0, 5, "abcdefghij", NPOS, 0),
TEST ("abcdefghii", 0, 10, "abcdefghij", NPOS, 0),
TEST ("abcdefghii", 9, 10, "abcdefghij", 1, 0),
TEST ("abcdefghij", 1, 1, "b", 0, 0),
TEST ("abcdefghij", 0, 1, "b", NPOS, 0),
TEST ("abcdefghij", 1, 4, "bcde", 0, 0),
TEST ("abcdefghij", 1, 3, "bcde", NPOS, 0),
TEST ("bbcdefghij", 2, 4, "a", 1, 0),
TEST ("bbcdefghij", 2, 0, "a", NPOS, 0),
TEST ("aeeeeeghij", 6, 1, "aeeee", 1, 0),
TEST ("aeeeeeghij", 0, 2, "aeeee", NPOS, 0),
TEST ("a", 0, 2, "bbcdefghij", NPOS, 0),
TEST ("jeeee", 1, 2, "eeeeeeghij", NPOS, 0),
TEST ("a\0b\0\0c", 0, 6, "a\0b\0\0c", 1, 0),
TEST ("a\0b\0\0c", 0, 1, "a\0b\0\0c", 0, 0),
TEST ("abc\0\0\0", 0, 4, "abc\0\0\0", 1, 0),
TEST ("abc\0\0\0", 0, 3, "abc\0\0\0", 0, 0),
TEST ("\0af\0\0c", 0, 6, "e\0ab\0\0c", NPOS, 0),
TEST ("\0af\0\0c", 2, 2, "e\0ab\0\0c", 1, 0),
TEST ("a\0b", 0, 3, "a\0b\0\0c", 1, 0),
TEST ("a\0b", 0, 1, "a\0b\0\0c", 0, 0),
TEST ("ab\0", 0, 5, "abc\0\0\0", NPOS, 0),
TEST ("\0eb", 0, 5, "e\0ab\0\0c", NPOS, 0),
TEST ("\0eb", 1, 5, "e\0ab\0\0c", 1, 0),
TEST ("x@4096", 0, 4096, "x@4096", 0, 0),
TEST ("x@4096", 1, 4096, "x@4096", NPOS, 0),
TEST ("xx", 0, 2, "x@4096", NPOS, 0),
TEST ("x@4096", 0, 4096, "xxxxx", 1, 0),
TEST ("x@4096", 2, 5, "xxxxx", 0, 0),
TEST ("x@4096", 5, 2, "xxxxx", NPOS, 0),
TEST ("a\0x", 0, 3, "x@4096", NPOS, 0),
TEST ("x@4096", 0, 10, "x\0b", 1, 0),
TEST ("x@4096", 0, 1, "x\0b", 0, 0),
TEST ("\0", 2, 0, "", 1, 1),
TEST ("a", 10, 0, "", 1, 1),
TEST ("x@4096", 4106, 0, "", 1, 1),
TEST ("last", 0, 4, "last", 0, 0)
};
/**************************************************************************/
// exercises:
// compare (size_type, size_type, basic_string&)
static const StringTestCase
size_size_cstr_test_cases [] = {
#undef TEST
#define TEST(str, off, size, arg, res, bthrow) { \
__LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, bthrow \
}
// +------------------------------------------ controlled sequence
// | +--------------------------- compare() off argument
// | | +----------------------- compare() n1 argument
// | | | +-------------------- sequence to be compared
// | | | | +--- expected result
// | | | | | +- exception info
// | | | | | | 0 - no exception
// | | | | | | 1,2 - out_of_range
// | | | | | | 3 - length_error
// | | | | | |
// | | | | | |
// V V V V V V
TEST ("ab", 0, 2, "ab", 0, 0),
TEST ("", 0, 0, "", 0, 0),
TEST ("", 0, 0, "\0", NPOS, 0),
TEST ("", 0, 0, "a", NPOS, 0),
TEST ("\0", 0, 1, "", 1, 0),
TEST ("\0", 0, 1, "\0", 0, 0),
TEST ("\0", 0, 1, "\0\0", NPOS, 0),
TEST ("\0", 0, 1, "a", NPOS, 0),
TEST ("abcdefghij", 0, 10, "abcdefghij", 0, 0),
TEST ("abcdefghij", 0, 10, "abcdefghi", 1, 0),
TEST ("abcdefghij", 1, 9, "abcdefghi", 1, 0),
TEST ("abcdefghij", 1, 8, "abcdefghi", 1, 0),
TEST ("abcdefghij", 2, 5, "abcdefghi", 1, 0),
TEST ("abcdefghi", 0, 9, "abcdefghij", NPOS, 0),
TEST ("abbdefghij", 0, 10, "abcdefghij", NPOS, 0),
TEST ("abbdefghij", 1, 9, "abcdefghij", 1, 0),
TEST ("abcdeeghij", 0, 10, "abcdefghij", NPOS, 0),
TEST ("abcdeeghij", 5, 10, "abcdefghij", 1, 0),
TEST ("abcdeeghij", 0, 5, "abcdefghij", NPOS, 0),
TEST ("abcdefghii", 0, 10, "abcdefghij", NPOS, 0),
TEST ("abcdefghii", 9, 10, "abcdefghij", 1, 0),
TEST ("abcdefghij", 1, 1, "b", 0, 0),
TEST ("abcdefghij", 0, 1, "b", NPOS, 0),
TEST ("abcdefghij", 1, 4, "bcde", 0, 0),
TEST ("abcdefghij", 1, 3, "bcde", NPOS, 0),
TEST ("bbcdefghij", 2, 4, "a", 1, 0),
TEST ("bbcdefghij", 2, 0, "a", NPOS, 0),
TEST ("aeeeeeghij", 6, 1, "aeeee", 1, 0),
TEST ("aeeeeeghij", 0, 2, "aeeee", NPOS, 0),
TEST ("a", 0, 2, "bbcdefghij", NPOS, 0),
TEST ("jeeee", 1, 2, "eeeeeeghij", NPOS, 0),
TEST ("a\0b\0\0c", 0, 6, "a\0b\0\0c", 0, 0),
TEST ("a\0b\0\0c", 2, 4, "a\0b\0\0c", 1, 0),
TEST ("e\0b\0\0c", 0, 1, "a\0b\0\0c", 1, 0),
TEST ("abc\0\0\0", 0, 4, "abc\0\0\0", NPOS, 0),
TEST ("ab\0c\0\0", 2, 2, "ab\0b\0\0", NPOS, 0),
TEST ("abc\0\0\0", 3, 3, "abc\0\0\0", NPOS, 0),
TEST ("\0af\0\0c", 0, 6, "e\0ab\0\0c", NPOS, 0),
TEST ("\0af\0\0c", 0, 1, "\0ab\0\0ce", NPOS, 0),
TEST ("\0af\0\0c", 2, 2, "e\0ab\0\0c", 1, 0),
TEST ("\0ae\0\0c", 2, 4, "e\0\0b\0ca", 1, 0),
TEST ("a\0b", 0, 3, "a\0b\0\0c", NPOS, 0),
TEST ("a\0b", 0, 1, "a\0b\0\0c", NPOS, 0),
TEST ("ab\0", 0, 5, "abc\0\0\0", NPOS, 0),
TEST ("\0eb", 0, 5, "e\0ab\0\0c", NPOS, 0),
TEST ("a\0b\0\0c", 0, 3, "a\0b", 0, 0),
TEST ("a\0b\0\0c", 0, 1, "a", 0, 0),
TEST ("abc\0\0\0", 0, 5, "abc\0\0", 0, 0),
TEST ("e\0ab\0\0c", 0, 7, "e\0ab\0\0c", 0, 0),
TEST ("a\0b\0\0c", 2, 3, "a\0b", 1, 0),
TEST ("a\0b\0\0c", 2, 1, "a", 1, 0),
TEST ("abc\0\0\0", 2, 5, "abc\0\0", 1, 0),
TEST ("e\0ag\0\0c", 3, 6, "e\0ab\0\0c", 1, 0),
TEST ("x@4096", 0, 4096, "x@4096", 0, 0),
TEST ("x@4096", 1, 4096, "x@4096", NPOS, 0),
TEST ("xx", 0, 2, "x@4096", NPOS, 0),
TEST ("x@4096", 0, 4096, "xxxxx", 1, 0),
TEST ("x@4096", 2, 5, "xxxxx", 0, 0),
TEST ("x@4096", 5, 2, "xxxxx", NPOS, 0),
TEST ("a\0x", 0, 3, "x@4096", NPOS, 0),
TEST ("x@4096", 0, 10, "x\0b", 1, 0),
TEST ("x@4096", 0, 1, "x\0b", NPOS, 0),
TEST ("a@4096\0", 4096, 1, "\0", 0, 0),
TEST ("\0", 2, 0, "", 1, 1),
TEST ("a", 10, 0, "", 1, 1),
TEST ("x@4096", 4106, 0, "", 1, 1),
TEST ("last", 0, 4, "last", 0, 0)
};
/**************************************************************************/
// exercises:
// compare (size_type, size_type, const value_type*, size_type)
static const StringTestCase
size_size_cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, off, size, arg, size2, res, bthrow) { \
__LINE__, off, size, -1, size2, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, bthrow \
}
// +------------------------------------------- controlled sequence
// | +---------------------------- compare() off argument
// | | +------------------------ compare() n1 argument
// | | | +--------------------- sequence to be compared
// | | | | +------ compare() n2 argument
// | | | | | +----- expected result
// | | | | | | +- exception info
// | | | | | | | 0 - no exception
// | | | | | | | 1,2 - out_of_range
// | | | | | | | 3 - length_error
// | | | | | | |
// | | | | | | |
// V V V V V V V
TEST ("ab", 0, 2, "ab", 2, 0, 0),
TEST ("", 0, 0, "", 0, 0, 0),
TEST ("", 0, 0, "\0", 1, NPOS, 0),
TEST ("", 0, 0, "a", 0, 0, 0),
TEST ("", 0, 0, "a", 1, NPOS, 0),
TEST ("\0", 0, 1, "", 0, 1, 0),
TEST ("\0", 0, 1, "\0", 1, 0, 0),
TEST ("\0", 0, 1, "\0\0", 2, NPOS, 0),
TEST ("\0", 0, 1, "\0\0", 1, 0, 0),
TEST ("\0\0", 1, 1, "\0", 1, 0, 0),
TEST ("\0", 0, 1, "a", 1, NPOS, 0),
TEST ("abcdefghij", 0, 10, "abcdefghij", 10, 0, 0),
TEST ("abcdefghij", 0, 10, "abcdefghi", 9, 1, 0),
TEST ("abcdefghij", 1, 9, "abcdefghi", 9, 1, 0),
TEST ("abcdefghij", 1, 8, "abcdefghi", 9, 1, 0),
TEST ("abcdefghij", 2, 5, "abcdefghi", 9, 1, 0),
TEST ("abcdefghi", 0, 9, "abcdefghij", 10, NPOS, 0),
TEST ("abcdefghi", 0, 4, "abcdefghij", 4, 0, 0),
TEST ("abcdefghi", 0, 5, "abcdefghij", 4, 1, 0),
TEST ("abbdefghij", 0, 10, "abcdefghij", 10, NPOS, 0),
TEST ("abbdefghij", 1, 9, "abcdefghij", 10, 1, 0),
TEST ("abcdeeghij", 0, 10, "abcdefghij", 10, NPOS, 0),
TEST ("abcdeeghij", 5, 10, "abcdefghij", 10, 1, 0),
TEST ("abcdeeghij", 0, 3, "abcdefghij", 3, 0, 0),
TEST ("abcdeeghij", 0, 5, "abcdefghij", 10, NPOS, 0),
TEST ("abcdefghii", 0, 10, "abcdefghij", 10, NPOS, 0),
TEST ("abcdefghii", 0, 9, "abcdefghij", 9, 0, 0),
TEST ("abcdefghii", 9, 10, "abcdefghij", 10, 1, 0),
TEST ("abcdefghij", 1, 1, "b", 1, 0, 0),
TEST ("abcdefghij", 1, 1, "g", 1, NPOS, 0),
TEST ("abcdefghij", 1, 1, "g", 0, 1, 0),
TEST ("abcdefghij", 1, 1, "bfg", 1, 0, 0),
TEST ("abcdefghij", 0, 1, "b", 1, NPOS, 0),
TEST ("abcdefghij", 1, 4, "bcde", 4, 0, 0),
TEST ("abcdefghij", 1, 3, "bcde", 4, NPOS, 0),
TEST ("abcdefghij", 1, 3, "bcde", 2, 1, 0),
TEST ("bbcdefghij", 2, 4, "a", 1, 1, 0),
TEST ("bbcdefghij", 2, 0, "a", 1, NPOS, 0),
TEST ("bbcaefghij", 3, 1, "age", 1, 0, 0),
TEST ("aeeeeeghij", 6, 1, "aeeee", 2, 1, 0),
TEST ("aeeeeeghij", 0, 2, "aeeee", 3, NPOS, 0),
TEST ("aeeeeeghij", 2, 3, "aeeee", 5, 1, 0),
TEST ("a", 0, 2, "bbcdefghij", 10, NPOS, 0),
TEST ("jeeee", 1, 2, "eeeeeeghij", 10, NPOS, 0),
TEST ("jeeee", 1, 4, "eeeeeeghij", 4, 0, 0),
TEST ("a\0b\0\0c", 0, 6, "a\0b\0\0c", 6, 0, 0),
TEST ("a\0b\0\0c", 2, 4, "a\0b\0\0c", 6, 1, 0),
TEST ("e\0b\0\0c", 0, 1, "a\0b\0\0c", 6, 1, 0),
TEST ("e\0b\0\0c", 3, 2, "\0\0a\0bc", 2, 0, 0),
TEST ("e\0b\0\0c", 3, 3, "\0\0c\0ba", 4, NPOS, 0),
TEST ("abc\0\0\0", 0, 4, "abc\0\0\0", 5, NPOS, 0),
TEST ("ab\0c\0\0", 2, 2, "ab\0b\0\0", 4, NPOS, 0),
TEST ("abc\0\0\0", 3, 3, "abc\0\0\0", 3, NPOS, 0),
TEST ("\0af\0\0c", 0, 6, "e\0ab\0\0c", 6, NPOS, 0),
TEST ("\0af\0\0c", 0, 1, "\0ab\0\0ce", 2, NPOS, 0),
TEST ("\0\0c\0af", 3, 3, "\0ab\0\0ce", 3, 1, 0),
TEST ("\0af\0\0c", 2, 2, "e\0ab\0\0c", 2, 1, 0),
TEST ("\0ae\0\0c", 2, 4, "e\0\0b\0ca", 4, 1, 0),
TEST ("a\0b", 0, 3, "a\0b\0\0c", 4, NPOS, 0),
TEST ("a\0b", 0, 1, "a\0b\0\0c", 2, NPOS, 0),
TEST ("ab\0", 0, 5, "abc\0\0\0", 3, NPOS, 0),
TEST ("\0eb", 0, 5, "e\0ab\0\0c", 1, NPOS, 0),
TEST ("a\0b\0\0c", 0, 3, "a\0b", 3, 0, 0),
TEST ("a\0b\0\0c", 0, 1, "a", 1, 0, 0),
TEST ("abc\0\0\0", 0, 5, "abc\0\0", 5, 0, 0),
TEST ("e\0ab\0\0c", 0, 7, "e\0ab\0\0c", 7, 0, 0),
TEST ("a\0b\0\0c", 2, 3, "a\0b", 2, 1, 0),
TEST ("a\0b\0\0c", 2, 1, "a", 0, 1, 0),
TEST ("abc\0\0\0", 2, 5, "c\0\0ab", 3, 1, 0),
TEST ("e\0ag\0\0c", 3, 6, "e\0ab\0\0c", 7, 1, 0),
TEST ("abc\0\0\0", 2, 5, "c\0\0ab", 4, NPOS, 0),
TEST ("x@4096", 0, 4096, "x@4096", 4096, 0, 0),
TEST ("x@4096", 1, 4096, "x@4096", 4096, NPOS, 0),
TEST ("x@4096", 1, 4096, "x@4096", 4092, 1, 0),
TEST ("xx", 0, 2, "x@4096", 4092, NPOS, 0),
TEST ("x@4096", 0, 4096, "xxxxx", 5, 1, 0),
TEST ("x@4096", 4090, 5, "xxxxx", 5, 0, 0),
TEST ("x@4096", 2, 5, "xxxxx", 5, 0, 0),
TEST ("x@4096", 5, 2, "xxxxx", 3, NPOS, 0),
TEST ("a\0x", 0, 3, "x@4096", 10, NPOS, 0),
TEST ("x@4096", 0, 10, "x\0b", 2, 1, 0),
TEST ("x@4096", 0, 1, "x\0b", 2, NPOS, 0),
TEST ("a@4096\0", 4096, 1, "\0b", 1, 0, 0),
TEST ("\0", 2, 0, "", 0, 1, 1),
TEST ("a", 10, 0, "", 0, 1, 1),
TEST ("x@4096", 4106, 0, "", 0, 1, 1),
TEST ("last", 0, 4, "last", 4, 0, 0)
};
/**************************************************************************/
// exercises:
// compare (size_type, size_type, basic_string&, size_type, size_type)
static const StringTestCase
size_size_cstr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, off, size, arg, off2, size2, res, bthrow) { \
__LINE__, off, size, off2, size2, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, bthrow \
}
// +------------------------------------------- controlled sequence
// | +---------------------------- compare() off argument
// | | +------------------------ compare() n1 argument
// | | | +--------------------- sequence to be inserted
// | | | | +------ compare() off2 argument
// | | | | | +-- compare() n2 argument
// | | | | | | +-- expected result
// | | | | | | | +- exception info
// | | | | | | | | 0-no exception
// | | | | | | | | 1-out_of_range
// | | | | | | | | 2-out_of_range
// | | | | | | | | 3-length_error
// | | | | | | | |
// | | | | | | | |
// V V V V V V V V
TEST ("ab", 0, 2, "ab", 0, 2, 0, 0),
TEST ("", 0, 0, "", 0, 0, 0, 0),
TEST ("", 0, 0, "\0", 0, 1, NPOS, 0),
TEST ("", 0, 0, "a", 0, 0, 0, 0),
TEST ("", 0, 0, "a", 0, 1, NPOS, 0),
TEST ("\0", 0, 1, "", 0, 0, 1, 0),
TEST ("\0", 0, 1, "\0", 0, 1, 0, 0),
TEST ("\0", 0, 1, "\0", 0, 0, 1, 0),
TEST ("\0", 0, 1, "\0\0", 0, 2, NPOS, 0),
TEST ("\0", 0, 1, "\0\0", 1, 1, 0, 0),
TEST ("\0", 0, 1, "\0\0", 2, 2, 1, 0),
TEST ("\0\0", 1, 1, "\0", 0, 1, 0, 0),
TEST ("\0", 0, 1, "a", 0, 1, NPOS, 0),
TEST ("abcdefghij", 0, 10, "abcdefghij", 0, 10, 0, 0),
TEST ("abcdefghij", 0, 10, "abcdefghij", 1, 10, NPOS, 0),
TEST ("abcdefghij", 0, 10, "abcdefghi", 0, 9, 1, 0),
TEST ("abcdefghij", 5, 4, "abcdefghi", 5, 9, 0, 0),
TEST ("abcdefghij", 1, 9, "abcdefghi", 0, 9, 1, 0),
TEST ("abcdefghij", 1, 9, "abcdefghi", 1, 8, 1, 0),
TEST ("abcdefghij", 1, 8, "abcdefghi", 0, 9, 1, 0),
TEST ("abcdefghij", 1, 8, "abcdefghi", 2, 9, NPOS, 0),
TEST ("abcdefghij", 2, 5, "abcdefghi", 0, 9, 1, 0),
TEST ("abcdefghij", 2, 5, "abcdefghi", 2, 5, 0, 0),
TEST ("abcdefghi", 0, 9, "abcdefghij", 0, 10, NPOS, 0),
TEST ("abcdefghi", 0, 9, "abcdefghij", 3, 10, NPOS, 0),
TEST ("abcdefghi", 0, 4, "abcdefghij", 0, 4, 0, 0),
TEST ("abcdefghi", 0, 4, "abcdefghij", 9, 1, NPOS, 0),
TEST ("abcdefghi", 0, 5, "abcdefghij", 0, 4, 1, 0),
TEST ("abbdefghij", 0, 10, "abcdefghij", 0, 10, NPOS, 0),
TEST ("abbdefghij", 0, 10, "abcdefghij", 1, 2, NPOS, 0),
TEST ("abbdefghij", 1, 9, "abcdefghij", 0, 10, 1, 0),
TEST ("abbdefghij", 1, 9, "abcdefghij", 5, 10, NPOS, 0),
TEST ("abcdeeghij", 0, 10, "abcdefghij", 0, 10, NPOS, 0),
TEST ("abcdeeghij", 0, 10, "abcdefghij", 1, 5, NPOS, 0),
TEST ("abcdeeghij", 5, 10, "abcdefghij", 0, 10, 1, 0),
TEST ("abcdeeghij", 0, 3, "abcdefghij", 0, 3, 0, 0),
TEST ("abcdeeghij", 0, 5, "abcdefghij", 0, 10, NPOS, 0),
TEST ("abcdeeghij", 0, 5, "abcdeabcde", 5, 10, 0, 0),
TEST ("abcdefghii", 0, 10, "abcdefghij", 0, 10, NPOS, 0),
TEST ("abcdefghii", 0, 10, "abcdefghij", 8, 2, NPOS, 0),
TEST ("abcdefghii", 0, 9, "abcdefghij", 0, 9, 0, 0),
TEST ("abcdefghii", 9, 10, "abcdefghij", 0, 10, 1, 0),
TEST ("abcdefghii", 9, 10, "abcdefghij", 9, 10, NPOS, 0),
TEST ("abcdefghij", 1, 1, "b", 0, 1, 0, 0),
TEST ("abcdefghij", 1, 1, "g", 0, 1, NPOS, 0),
TEST ("abcdefghij", 1, 1, "g", 0, 0, 1, 0),
TEST ("abcdefghij", 1, 1, "bfg", 0, 1, 0, 0),
TEST ("abcdefghij", 1, 1, "bfg", 2, 1, NPOS, 0),
TEST ("abcdefghij", 0, 1, "b", 0, 1, NPOS, 0),
TEST ("abcdefghij", 1, 4, "bcde", 0, 4, 0, 0),
TEST ("abcdefghij", 1, 4, "bcde", 2, 4, NPOS, 0),
TEST ("abcdefghij", 1, 3, "bcde", 0, 4, NPOS, 0),
TEST ("abcdefghij", 1, 3, "aebcd", 2, 3, 0, 0),
TEST ("abcdefghij", 1, 3, "bcde", 0, 2, 1, 0),
TEST ("abcdefghij", 1, 3, "bcde", 1, 2, NPOS, 0),
TEST ("bbcdefghij", 2, 4, "a", 0, 1, 1, 0),
TEST ("bbcdefghij", 2, 0, "a", 0, 1, NPOS, 0),
TEST ("bbcaefghij", 3, 1, "age", 0, 1, 0, 0),
TEST ("aeeeeeghij", 6, 1, "aeeee", 0, 2, 1, 0),
TEST ("aeeeeeghij", 0, 2, "aeeee", 0, 3, NPOS, 0),
TEST ("aeeeeeghij", 2, 3, "aeeee", 0, 5, 1, 0),
TEST ("aeeeeeghij", 2, 3, "eeeea", 1, 3, 0, 0),
TEST ("a", 0, 2, "bbcdefghij", 0, 10, NPOS, 0),
TEST ("jeeee", 1, 2, "eeeeeeghij", 0, 10, NPOS, 0),
TEST ("jeeee", 1, 2, "eeeeeeghij", 1, 1, 1, 0),
TEST ("jeeee", 1, 4, "eeeeeeghij", 0, 4, 0, 0),
TEST ("a\0b\0\0c", 0, 6, "a\0b\0\0c", 0, 6, 0, 0),
TEST ("a\0b\0\0c", 1, 1, "a\0b\0\0c", 3, 1, 0, 0),
TEST ("a\0b\0\0c", 2, 4, "a\0b\0\0c", 0, 6, 1, 0),
TEST ("a\0b\0\0c", 2, 4, "ab\0\0c\0", 1, 4, 0, 0),
TEST ("e\0b\0\0c", 0, 1, "a\0b\0\0c", 0, 6, 1, 0),
TEST ("e\0b\0\0c", 3, 2, "\0\0a\0bc", 0, 2, 0, 0),
TEST ("e\0b\0\0c", 3, 3, "\0\0c\0ba", 0, 4, NPOS, 0),
TEST ("e\0b\0\0c", 3, 3, "a\0\0c\0b", 1, 3, 0, 0),
TEST ("abc\0\0\0", 0, 4, "abc\0\0\0", 0, 5, NPOS, 0),
TEST ("abc\0\0\0", 3, 4, "a\0\0\0bc", 1, 3, 0, 0),
TEST ("ab\0c\0\0", 2, 2, "ab\0b\0\0", 0, 4, NPOS, 0),
TEST ("ab\0c\0\0", 2, 4, "ab\0b\0\0", 2, 4, 1, 0),
TEST ("\0af\0\0c", 0, 6, "e\0ab\0\0c", 0, 6, NPOS, 0),
TEST ("\0af\0\0c", 2, 6, "e\0ab\0\0c", 2, 6, 1, 0),
TEST ("\0af\0\0c", 0, 1, "\0ab\0\0ce", 0, 2, NPOS, 0),
TEST ("\0af\0\0c", 3, 1, "\0ab\0\0ce", 0, 1, 0, 0),
TEST ("\0\0c\0af", 3, 3, "\0ab\0\0ce", 0, 3, 1, 0),
TEST ("\0\0c\0af", 1, 2, "\0ab\0\0ec", 4, 3, NPOS, 0),
TEST ("\0af\0\0c", 2, 2, "e\0ab\0\0c", 0, 2, 1, 0),
TEST ("\0ae\0\0c", 0, 3, "e\0\0b\0ca", 4, 4, NPOS, 0),
TEST ("a\0b", 0, 3, "a\0b\0\0c", 0, 4, NPOS, 0),
TEST ("a\0b", 1, 3, "a\0b\0\0c", 4, 4, NPOS, 0),
TEST ("a\0b", 0, 1, "a\0b\0\0c", 0, 2, NPOS, 0),
TEST ("ab\0", 0, 5, "abc\0\0\0", 0, 3, NPOS, 0),
TEST ("ab\0", 2, 1, "abc\0\0\0", 3, 3, NPOS, 0),
TEST ("\0eb", 0, 5, "e\0ab\0\0c", 0, 1, NPOS, 0),
TEST ("a\0b\0\0c", 0, 3, "a\0b", 0, 3, 0, 0),
TEST ("a\0b\0\0c", 3, 2, "a\0b", 1, 2, NPOS, 0),
TEST ("a\0b\0\0c", 0, 1, "a", 0, 1, 0, 0),
TEST ("abc\0\0\0", 0, 5, "abc\0\0", 0, 5, 0, 0),
TEST ("e\0ab\0\0c", 0, 7, "e\0ab\0\0c", 0, 7, 0, 0),
TEST ("e\0ab\0\0c", 0, 7, "e\0ab\0\0c", 2, 7, 1, 0),
TEST ("a\0b\0\0c", 2, 3, "a\0b", 0, 2, 1, 0),
TEST ("a\0b\0\0c", 2, 1, "a", 0, 0, 1, 0),
TEST ("abc\0\0\0", 2, 5, "c\0\0ab", 0, 3, 1, 0),
TEST ("e\0ag\0\0c", 3, 6, "e\0ab\0\0c", 0, 7, 1, 0),
TEST ("abc\0\0\0", 2, 5, "c\0\0ab", 0, 4, NPOS, 0),
TEST ("x@4096", 0, 4096, "x@4096", 0, 4096, 0, 0),
TEST ("x@4096", 1, 4096, "x@4096", 0, 4096, NPOS, 0),
TEST ("x@4096", 1, 4096, "x@4096", 0, 4092, 1, 0),
TEST ("x@4096", 1, 4090, "x@4096", 2, 4090, 0, 0),
TEST ("x@4096", 1, 4102, "x@4096", 2, 4102, 1, 0),
TEST ("xx", 0, 2, "x@4096", 0, 4092, NPOS, 0),
TEST ("xx", 0, 2, "x@4096", 4090, 2, 0, 0),
TEST ("x@4096", 0, 4096, "xxxxx", 0, 5, 1, 0),
TEST ("x@4096", 4090, 5, "xxxxx", 0, 5, 0, 0),
TEST ("x@4096", 2, 5, "xxxxx", 0, 5, 0, 0),
TEST ("x@4096", 5, 2, "xxxxx", 0, 3, NPOS, 0),
TEST ("a\0x", 0, 3, "x@4096", 0, 10, NPOS, 0),
TEST ("a\0x", 2, 1, "x@4096", 4095, 1, 0, 0),
TEST ("x@4096", 0, 10, "x\0b", 0, 2, 1, 0),
TEST ("x@4096", 0, 1, "x\0b", 0, 2, NPOS, 0),
TEST ("a@4096\0", 4096, 1, "b\0", 1, 1, 0, 0),
TEST ("\0", 2, 0, "", 0, 0, 1, 1),
TEST ("a", 10, 0, "", 0, 0, 1, 1),
TEST ("x@4096", 4106, 0, "", 0, 0, 1, 1),
TEST ("", 0, 0, "\0", 2, 0, 1, 2),
TEST ("", 0, 0, "a", 10, 0, 1, 2),
TEST ("", 0, 0, "x@4096", 4106, 0, 1, 2),
TEST ("last", 0, 4, "last", 0, 4, 0, 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_compare (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename UserTraits<charT>::MemFun UTMemFun;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object to be modified
// and the (possibly unused) argument string
const String str (wstr, str_len);
const String arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
int res = 0;
// string function argument
const charT* const arg_ptr = tcase.arg ? arg.c_str () : str.c_str ();
const String& arg_str = tcase.arg ? arg : str;
std::size_t total_compare_calls = 0;
std::size_t n_compare_calls = 0;
std::size_t* const rg_calls =
rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls)
total_compare_calls = rg_calls[UTMemFun::compare];
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (1 == tcase.bthrow)
expected = exceptions [1];
else if ( 2 == tcase.bthrow
&& Compare (size_size_cstr_size_size) == func.which_)
expected = exceptions [1];
else if (3 == tcase.bthrow)
expected = exceptions [2];
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
switch (func.which_) {
case Compare (cptr):
res = str.compare (arg_ptr);
break;
case Compare (cstr):
res = str.compare (arg_str);
if (rg_calls)
n_compare_calls = rg_calls[UTMemFun::compare];
break;
case Compare (size_size_cptr):
res = str.compare (tcase.off, tcase.size, arg_ptr);
break;
case Compare (size_size_cstr):
res = str.compare (tcase.off, tcase.size, arg_str);
break;
case Compare (size_size_cptr_size):
res = str.compare (tcase.off, tcase.size,
arg_ptr, tcase.size2);
break;
case Compare (size_size_cstr_size_size):
res = str.compare (tcase.off, tcase.size,
arg_str, tcase.off2, tcase.size2);
break;
default:
RW_ASSERT ("test logic error: unknown compare overload");
return;
}
// verify the returned value
const bool success = res < 0 && tcase.nres == NPOS
|| res > 0 && tcase.nres > 0
|| res == 0 && tcase.nres == 0;
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL} == %d, got %d",
__LINE__, tcase.nres == NPOS ? -1 : int (tcase.nres), res);
// verify that Traits::length was used
if (Compare (cstr) == func.which_ && rg_calls) {
rw_assert (n_compare_calls - total_compare_calls > 0,
0, tcase.line, "line %d. %{$FUNCALL} doesn't "
"use traits::compare()", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_compare);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Compare (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (size_size_cptr),
TEST (size_size_cstr),
TEST (size_size_cptr_size),
TEST (size_size_cstr_size_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.compare",
test_compare, tests, test_count);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,261 @@
/***************************************************************************
*
* 21.string.cons.mt.cpp:
*
* Test exercising the thread safety of basic_string constructors
* and assignment operators.
*
* $Id: 21.string.cons.mt.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for size_t
#include <driver.h> // for rw_test()
#include <rw_thread.h> // for rw_thread_pool(), ...
#include <valcmp.h> // for rw_strncmp()
/**************************************************************************/
#define MAX_THREADS 32
#define MAX_LOOPS 100000
const char* const
data [] = {
/* 0 */ "",
/* 1 */ "a",
/* 2 */ "bc",
/* 3 */ "cde",
/* 4 */ "defg",
/* 5 */ "efghi",
/* 6 */ "fghijk",
/* 7 */ "ghijklm"
};
const std::size_t
nstrings = sizeof data / sizeof *data;
const std::string
shared [nstrings] = {
data [0], data [1], data [2], data [3],
data [4], data [5], data [6], data [7]
};
#ifndef _RWSTD_NO_WCHAR_T
const wchar_t* const
wdata [] = {
/* 0 */ L"",
/* 1 */ L"a",
/* 2 */ L"bc",
/* 3 */ L"cde",
/* 4 */ L"defg",
/* 5 */ L"efghi",
/* 6 */ L"fghijk",
/* 7 */ L"ghijklm"
};
const std::wstring
wshared [nstrings] = {
wdata [0], wdata [1], wdata [2], wdata [3],
wdata [4], wdata [5], wdata [6], wdata [7]
};
#endif // _RWSTD_NO_WCHAR_T
/**************************************************************************/
#ifdef _RWSTD_REENTRANT
int rw_opt_nthreads = 4;
#else // if !defined (_RWSTD_REENTRANT)
// in non-threaded builds use just one thread
int rw_opt_nthreads = 1;
#endif // _RWSTD_REENTRANT
// the number of times each thread should iterate
int rw_opt_nloops = MAX_LOOPS;
template <class T>
void
test_string_cons (const T* const *pdata,
const std::basic_string<T> *pshared,
std::size_t threadno)
{
typedef std::basic_string<T> String;
for (std::size_t i = 0; i != std::size_t (rw_opt_nloops); ++i) {
const std::size_t inx1 = (i + threadno) % nstrings;
const std::size_t inx2 = (inx1 + 1) % nstrings;
// create a copy of the global string
const String copy (pshared [inx1]);
String assigned (pshared [inx2]);
{
// create another copy of the same global string
const String copy2 (pshared [inx1]);
// verify that this copy has the expected length...
RW_ASSERT (pshared [inx1].length () == copy2.length ());
// ...and the expected data
RW_ASSERT (0 == rw_strncmp (pdata [inx1], copy2.data ()));
assigned = pshared [inx1];
// copy2 gets destroyed...
}
// verify that local copy has the expected length...
RW_ASSERT (pshared [inx1].length () == copy.length ());
// ...and the expected data
RW_ASSERT (0 == rw_strncmp (pdata [inx1], copy.data ()));
// verify that assigned string has the expected length...
RW_ASSERT (pshared [inx1].length () == assigned.length ());
// ...and the expected data
RW_ASSERT (0 == rw_strncmp (pdata [inx1], assigned.data ()));
// reassign and verify again
assigned = pdata [inx2];
RW_ASSERT (pshared [inx2].length () == assigned.length ());
RW_ASSERT (0 == rw_strncmp (pdata [inx2], assigned.data ()));
}
}
extern "C" {
bool test_wstring;
static void*
thread_func (void *arg)
{
const rw_thread_t* const pthread = (rw_thread_t*)arg;
// get the 0-based thread number
const std::size_t threadno = std::size_t (pthread->threadno);
if (test_wstring) {
#ifndef _RWSTD_NO_WCHAR_T
test_string_cons<wchar_t>(wdata, wshared, threadno);
#endif // _RWSTD_NO_WCHAR_T
}
else {
test_string_cons (data, shared, threadno);
}
return 0;
}
} // extern "C"
/**************************************************************************/
static int
run_test (int, char**)
{
rw_info (0, 0, 0,
"testing std::string with %d thread%{?}s%{;}, "
"%d iteration%{?}s%{;} each",
rw_opt_nthreads, 1 != rw_opt_nthreads,
rw_opt_nloops, 1 != rw_opt_nloops);
test_wstring = false;
// create and start a pool of threads and wait for them to finish
int result =
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
rw_error (result == 0, 0, __LINE__,
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
rw_opt_nthreads, thread_func);
for (std::size_t i = 0; i != nstrings; ++i) {
const std::size_t size =
std::string::traits_type::length (data [i]);
rw_assert (size == shared [i].size (), 0, 0,
"shared string modifed from %#s to %{#S}",
data [i], &shared [i]);
}
#ifndef _RWSTD_NO_WCHAR_T
rw_info (0, 0, 0,
"testing std::wstring with %d thread%{?}s%{;}, "
"%d iteration%{?}s%{;} each",
rw_opt_nthreads, 1 != rw_opt_nthreads,
rw_opt_nloops, 1 != rw_opt_nloops);
test_wstring = true;
// start a pool of threads to exercise wstring thread safety
result =
rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
rw_error (result == 0, 0, __LINE__,
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
rw_opt_nthreads, thread_func);
for (std::size_t i = 0; i != nstrings; ++i) {
const std::size_t size =
std::wstring::traits_type::length (wdata [i]);
rw_assert (size == wshared [i].size (), 0, 0,
"shared string modifed from %#ls to %{#lS}",
wdata [i], &wshared [i]);
}
#endif // _RWSTD_NO_WCHAR_T
return result;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.string.cons",
"thread safety", run_test,
"|-nloops#0 " // must be non-negative
"|-nthreads#0-*", // must be in [0, MAX_THREADS]
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads);
}

View File

@@ -0,0 +1,328 @@
/***************************************************************************
*
* 21.string.copy.cpp - string test exercising [lib.string::copy]
*
* $Id: 21.string.copy.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // size_t
#include <stdexcept> // for out_of_range
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_assert()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define Copy(which) StringIds::copy_ ## which
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// copy (value_type*, size_type)
static const StringTestCase
ptr_size_test_cases [] = {
#undef TEST
#define TEST(str, size, res) { \
__LINE__, -1, size, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, 0 \
}
// +--------------------------------------- controlled sequence
// | +--------------- copy() n argument
// | | +----------- expected result sequence
// | | |
// V V V
TEST ("ab", 2, "ab"),
TEST ("", 0, ""),
TEST ("", 10, ""),
TEST ("<U0>", 1, "<U0>"),
TEST ("<U0>@2", 2, "<U0>@2"),
TEST ("abc", 0, ""),
TEST ("abc", 1, "a"),
TEST ("abc", 2, "ab"),
TEST ("abc", 3, "abc"),
TEST ("abc", 5, "abc"),
TEST ("a<U0>b<U0>@2c", 10, "a<U0>b<U0>@2c"),
TEST ("<U0>ab<U0>@3c<U0>", 1, "<U0>"),
TEST ("<U0>ab<U0>@3c<U0>", 8, "<U0>ab<U0>@3c<U0>"),
TEST ("<U0>ab<U0>@3c<U0>", 5, "<U0>ab<U0>@2"),
TEST ("<U0>@2ab<U0>@2c<U0>", 6, "<U0>@2ab<U0>@2"),
TEST ("x@4096", 4096, "x@4096"),
TEST ("last", 4, "last")
};
/**************************************************************************/
// exercises:
// copy (value_type*, size_type, size_type)
static const StringTestCase
ptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, size, off, res, bthrow) { \
__LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, bthrow \
}
// +------------------------------------------ controlled sequence
// | +------------------ copy() n argument
// | | +-------------- copy() pos argument
// | | | +----------- expected result sequence
// | | | | +--- exception info:
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | |
// | | | | +---------+
// V V V V V
TEST ("ab", 2, 0, "ab", 0),
TEST ("", 0, 0, "", 0),
TEST ("", 10, 0, "", 0),
TEST ("<U0>", 1, 0, "<U0>", 0),
TEST ("<U0>@2", 1, 1, "<U0>", 0),
TEST ("<U0>@2", 2, 0, "<U0>@2", 0),
TEST ("abc", 1, 0, "a", 0),
TEST ("abc", 1, 1, "b", 0),
TEST ("abc", 1, 2, "c", 0),
TEST ("abc", 0, 0, "", 0),
TEST ("abc", 2, 0, "ab", 0),
TEST ("abc", 2, 1, "bc", 0),
TEST ("abc", 3, 0, "abc", 0),
TEST ("abc", 10, 1, "bc", 0),
TEST ("abc", 3, 2, "c", 0),
TEST ("a<U0>b<U0>@2c", 10, 1, "<U0>b<U0>@2c", 0),
TEST ("a<U0>b<U0>@2c", 10, 0, "a<U0>b<U0>@2c", 0),
TEST ("a<U0>b<U0>@2c", 1, 1, "<U0>", 0),
TEST ("<U0>ab<U0>@3c<U0>", 10, 1, "ab<U0>@3c<U0>", 0),
TEST ("<U0>ab<U0>@3c<U0>", 5, 0, "<U0>ab<U0>@2", 0),
TEST ("<U0>ab<U0>@3c<U0>", 3, 3, "<U0>@3", 0),
TEST ("<U0>@2ab<U0>@2c<U0>", 6, 0, "<U0>@2ab<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2c<U0>", 4, 1, "<U0>ab<U0>", 0),
TEST ("x@4096", 4096, 0, "x@4096", 0),
TEST ("x@4096", 2, 1, "xx", 0),
TEST ("x@4096", 4096, 4095, "x", 0),
TEST ("<U0>", 0, 2, "", 1),
TEST ("a", 0, 10, "", 1),
TEST ("x@4096", 0, 4106, "", 1),
TEST ("last", 4, 0, "last", 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_copy (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
static charT wres_buf [BUFSIZE];
std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
// construct the string object
const String str (wstr, str_len);
if (wstr != wstr_buf)
delete[] wstr;
wstr = 0;
const std::size_t min_len =
str_len < std::size_t (tcase.size) ? str_len : tcase.size;
std::size_t res = 0;
// create destination array and initialize it with garbage
charT* const s_res = new charT [min_len + 2];
const char cgb [2] = "#";
const charT wcgb = make_char (cgb [0], (charT*)0);
Traits::assign (s_res, min_len + 1, wcgb);
s_res [min_len + 1] = charT ();
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected?
const char* const expected = tcase.bthrow ? exceptions [1] : 0;
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
try {
switch (func.which_) {
case Copy (ptr_size): {
res = str.copy (s_res, tcase.size);
break;
}
case Copy (ptr_size_size): {
res = str.copy (s_res, tcase.size, tcase.off);
break;
}
default:
RW_ASSERT (!"logic error: unknown copy overload");
return;
}
// verify the returned value
rw_assert (res == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} == %zu, got %zu",
__LINE__, res_len, res);
if (res == res_len)
{
const std::size_t match = rw_match (tcase.res, s_res, res_len);
bool success = match == res_len;
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, differ at pos %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (res), s_res, match);
success = 1 == rw_match (cgb, s_res + min_len, 1);
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL} detected writing past the end of "
"the provided buffer", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (wres != wres_buf)
delete[] wres;
delete[] s_res;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_copy);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(which) { \
Copy (which), which ## _test_cases, \
sizeof which ## _test_cases / sizeof *which ## _test_cases \
}
TEST (ptr_size),
TEST (ptr_size_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.copy",
test_copy, tests, test_count);
}

View File

@@ -0,0 +1,521 @@
/***************************************************************************
*
* 21.string.erase.cpp - string test exercising [lib.string::erase]
*
* $Id: 21.string.erase.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for ptrdiff_t, size_t
#include <stdexcept> // for out_of_range
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define Erase(sig) StringIds::erase_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// erase ()
static const StringTestCase
void_test_cases [] = {
#undef TEST
#define TEST(str, res) { \
__LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, \
0, 0, res, sizeof res - 1, 0 }
// +--------------------------------- controlled sequence
// | +--------------- expected result sequence
// | |
// V V
TEST ("a", ""),
TEST ("", ""),
TEST ("<U0>", ""),
TEST ("abc", ""),
TEST ("t<U0> s", ""),
TEST ("<U0>ab<U0>@2c", ""),
TEST ("a<U0>b<U0>@2c", ""),
TEST ("a<U0>bc<U0>@2", ""),
TEST ("x@4096", ""),
TEST ("last", "")
};
/**************************************************************************/
// used to exercise
// erase (size_type)
static const StringTestCase
size_test_cases [] = {
#undef TEST
#define TEST(str, off, res, bthrow) { \
__LINE__, off, -1, -1, -1, -1, str, sizeof str - 1, \
0, 0, res, sizeof res - 1, bthrow }
// +-------------------------------------- controlled sequence
// | +------------------ erase() pos argument
// | | +------------- expected result sequence
// | | | +--- exception info
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// | | | |
// V V V V
TEST ("", 0, "", 0),
TEST ("<U0>", 0, "", 0),
TEST ("<U0>", 1, "<U0>", 0),
TEST ("<U0>@2", 1, "<U0>", 0),
TEST ("a", 0, "", 0),
TEST ("a", 1, "a", 0),
TEST ("abc", 0, "", 0),
TEST ("abc", 1, "a", 0),
TEST ("abc", 2, "ab", 0),
TEST ("abc", 3, "abc", 0),
TEST ("t<U0> s", 0, "", 0),
TEST ("t<U0> s", 1, "t", 0),
TEST ("t<U0> s", 2, "t<U0>", 0),
TEST ("t<U0> s", 3, "t<U0> ", 0),
TEST ("t<U0> s", 4, "t<U0> s", 0),
TEST ("a<U0>@3b", 2, "a<U0>", 0),
TEST ("a<U0>@3b", 1, "a", 0),
TEST ("a<U0>@3b", 0, "", 0),
TEST ("a<U0>b<U0>@2c", 0, "", 0),
TEST ("a<U0>b<U0>@2c", 4, "a<U0>b<U0>", 0),
TEST ("<U0>ab<U0>@2c", 2, "<U0>a", 0),
TEST ("ab<U0>c<U0>@2", 5, "ab<U0>c<U0>", 0),
TEST ("a", 3, "a", 1),
TEST ("t<U0> s", 5, "t<U0> s", 1),
TEST ("ab<U0>c<U0>@2", 10, "ab<U0>c<U0>@2", 1),
TEST ("x@4096", 4106, "x@4096", 1),
TEST ("x@4096", 0, "", 0),
TEST ("x@4096", 1, "x", 0),
TEST ("x@4096", 4, "xxxx", 0),
TEST ("x@4096", 4096, "x@4096", 0),
TEST ("x@2048y@2048", 2048, "x@2048", 0),
TEST ("last test", 4, "last", 0)
};
/**************************************************************************/
// used to exercise
// erase (size_type, size_type)
// erase (iterator, iterator)
static const StringTestCase
size_size_test_cases [] = {
// size_size_test_cases serves a double duty
#define iter_iter_test_cases size_size_test_cases
#undef TEST
#define TEST(str, off, size, res, bthrow) { \
__LINE__, off, size, -1, -1, -1, str, sizeof str - 1, \
0, 0, res, sizeof res - 1, bthrow }
// +----------------------------------------- controlled sequence
// | +--------------------- erase() pos argument
// | | +----------- erase() n argument
// | | | +------- expected result sequence
// | | | | +--- exception info
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | |
// | | | | +-------+
// V V V V V
TEST ("", 0, 0, "", 0),
TEST ("<U0>", 0, 1, "", 0),
TEST ("<U0>", 0, 0, "<U0>", 0),
TEST ("<U0>", 1, 1, "<U0>", 0),
TEST ("<U0>@2", 1, 1, "<U0>", 0),
TEST ("<U0>@2", 0, 1, "<U0>", 0),
TEST ("a", 0, 1, "", 0),
TEST ("a", 0, 0, "a", 0),
TEST ("a", 1, 1, "a", 0),
TEST ("abc", 0, 3, "", 0),
TEST ("abc", 0, 2, "c", 0),
TEST ("abc", 1, 2, "a", 0),
TEST ("abc", 1, 1, "ac", 0),
TEST ("abc", 2, 1, "ab", 0),
TEST ("abc", 3, 0, "abc", 0),
TEST ("t<U0> s", 0, 3, "s", 0),
TEST ("t<U0> s", 0, 4, "", 0),
TEST ("t<U0> s", 0, 1, "<U0> s", 0),
TEST ("t<U0> s", 1, 3, "t", 0),
TEST ("t<U0> s", 1, 2, "ts", 0),
TEST ("t<U0> s", 2, 2, "t<U0>", 0),
TEST ("t<U0> s", 2, 1, "t<U0>s", 0),
TEST ("t<U0> s", 3, 2, "t<U0> ", 0),
TEST ("t<U0> s", 4, 0, "t<U0> s", 0),
TEST ("a<U0>@3b", 2, 0, "a<U0>@3b", 0),
TEST ("a<U0>@3b", 2, 3, "a<U0>", 0),
TEST ("a<U0>@3b", 2, 2, "a<U0>b", 0),
TEST ("a<U0>@3b", 1, 4, "a", 0),
TEST ("a<U0>@3b", 0, 5, "", 0),
TEST ("a<U0>@3b", 0, 2, "<U0>@2b", 0),
TEST ("a<U0>b<U0>@2c", 0, 6, "", 0),
TEST ("a<U0>b<U0>@2c", 4, 2, "a<U0>b<U0>", 0),
TEST ("a<U0>b<U0>@2c", 4, 1, "a<U0>b<U0>c", 0),
TEST ("<U0>ab<U0>@2c", 2, 5, "<U0>a", 0),
TEST ("<U0>ab<U0>@2c", 0, 4, "<U0>c", 0),
TEST ("ab<U0>c<U0>@2", 5, 1, "ab<U0>c<U0>", 0),
TEST ("a", 0, 3, "", 0),
TEST ("t<U0> s", 0, 9, "", 0),
TEST ("ab<U0>c<U0>@2", 0, 10, "", 0),
TEST ("x@4096", 0, 4105, "", 0),
TEST ("a", 3, 1, "a", 1),
TEST ("t<U0> s", 5, 1, "t<U0> s", 1),
TEST ("ab<U0>c<U0>@2", 10, 1, "ab<U0>c<U0>@2", 1),
TEST ("x@4096", 4106, 1, "x@4096", 1),
TEST ("x@4096", 0, 4096, "", 0),
TEST ("x@4096", 1, 4095, "x", 0),
TEST ("x@4096", 4, 4092, "xxxx", 0),
TEST ("x@4096", 4, 4090, "xxxxxx", 0),
TEST ("x@4096", 4096, 4096, "x@4096", 0),
TEST ("x@2048y@2048", 1, 4094, "xy", 0),
TEST ("last test", 4, 1, "lasttest", 0)
};
/**************************************************************************/
// used to exercise
// erase (iterator)
static const StringTestCase
iter_test_cases [] = {
#undef TEST
#define TEST(str, off, res) { \
__LINE__, off, -1, -1, -1, -1, str, sizeof str - 1, \
0, 0, res, sizeof res - 1, 0 }
// +-------------------------------------- controlled sequence
// | +------------------ iterator offset
// | | +------------- expected result sequence
// | | |
// V V V
TEST ("a", 0, ""),
TEST ("<U0>", 0, ""),
TEST ("<U0>@2", 0, "<U0>"),
TEST ("<U0>@2", 1, "<U0>"),
TEST ("abc", 0, "bc"),
TEST ("abc", 1, "ac"),
TEST ("abc", 2, "ab"),
TEST ("t<U0> s", 0, "<U0> s"),
TEST ("t<U0> s", 1, "t s"),
TEST ("t<U0> s", 2, "t<U0>s"),
TEST ("t<U0> s", 3, "t<U0> "),
TEST ("a<U0>@3b", 4, "a<U0>@3"),
TEST ("a<U0>@3b", 2, "a<U0>@2b"),
TEST ("a<U0>@3b", 1, "a<U0>@2b"),
TEST ("a<U0>@3b", 0, "<U0>@3b"),
TEST ("a<U0>b<U0>@2c", 4, "a<U0>b<U0>c"),
TEST ("<U0>ab<U0>@2c", 0, "ab<U0>@2c"),
TEST ("<U0>ab<U0>@2c", 2, "<U0>a<U0>@2c"),
TEST ("ab<U0>c<U0>@2", 5, "ab<U0>c<U0>"),
TEST ("x@4096y", 4096, "x@4096"),
TEST ("x@4096", 4088, "x@4095"),
TEST ("ax@4096", 0, "x@4096"),
TEST ("x@4096", 9, "x@4095"),
TEST ("last test", 4, "lasttest")
};
/**************************************************************************/
// exercises basic_string::erase, 21.3.5.5
template <class charT, class Traits, class Allocator>
void test_erase (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename String::iterator StringIter;
typedef typename String::const_iterator ConstStringIter;
const bool use_iters =
StringIds::arg_iter == StringIds::arg_type (func.which_, 1);
if (use_iters && tcase.bthrow)
return;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
static charT wres_buf [BUFSIZE];
std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
static char nres_buf [BUFSIZE];
char* nres = 0;
if (use_iters) {
std::size_t nreslen = sizeof nres_buf / sizeof *nres_buf;
nres = rw_expand (nres_buf, tcase.res, tcase.nres, &nreslen);
}
// construct the string object to be modified
// and the (possibly unused) argument string
String str (wstr, str_len);
if (wstr != wstr_buf)
delete[] wstr;
wstr = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
StringIter res_iter = str.begin ();
// compute the offset and the extent (the number of elements)
// of the first range into the string object being modified
const std::size_t size1 = str_len;
const std::size_t off1 =
std::size_t (tcase.off) < size1 ? std::size_t (tcase.off) : size1;
const std::size_t ext1 =
off1 + tcase.size < size1 ? tcase.size : size1 - off1;
// create a pair of iterators into the string object being
// modified (used only by the iterator overloads)
const StringIter it_first (str.begin () + off1);
const StringIter it_last (it_first + ext1);
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 0;
if (1 == tcase.bthrow)
expected = exceptions [1];
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
// pointer to the returned reference
const String* ret_ptr = 0;
try {
switch (func.which_) {
case Erase (void):
ret_ptr = &str.erase ();
break;
case Erase (size):
ret_ptr = &str.erase (tcase.off);
break;
case Erase (size_size):
ret_ptr = &str.erase (tcase.off, tcase.size);
break;
case Erase (iter):
res_iter = str.erase (it_first);
break;
case Erase (iter_iter):
res_iter = str.erase (it_first, it_last);
break;
default:
RW_ASSERT (!"test logic error: unknown erase overload");
return;
}
// verify the returned value
if (use_iters) {
const ConstStringIter begin = str.begin ();
const ConstStringIter end = str.end ();
const bool success = begin <= res_iter && res_iter <= end;
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL} returned invalid iterator, "
"difference with begin is %td",
__LINE__, res_iter - begin);
if (std::size_t (tcase.off) >= res_len) {
rw_assert (res_iter == end, 0, tcase.line,
"line %d. %{$FUNCALL} != end()", __LINE__);
}
else {
const std::size_t match =
rw_match (nres + tcase.off, &(*res_iter), 1);
rw_assert (1 == match, 0, tcase.line,
"line %d. %{$FUNCALL} == %{#c}, got %{#c}",
__LINE__, nres[tcase.off], *res_iter);
}
}
else {
// verify that the reference returned from the function
// refers to the modified string object (i.e., *this
// within the function)
const std::ptrdiff_t ret_off = ret_ptr - &str;
// verify the returned value
rw_assert (0 == ret_off, 0, tcase.line,
"line %d. %{$FUNCALL} returned invalid reference, "
"offset is %td", __LINE__, ret_off);
}
// verfiy that strings length are equal
rw_assert (res_len == str.size (), 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s} with length "
"%zu, got %{/*.*Gs} with length %zu",
__LINE__, int (tcase.nres), tcase.res,
res_len, int (sizeof (charT)),
int (str.size ()), str.c_str (), str.size ());
if (res_len == str.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the modified
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, str.c_str(), str.size ());
rw_assert (match == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (str.size ()),
str.c_str (), match);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
}
if (nres != nres_buf)
delete[] nres;
if (wres != wres_buf)
delete[] wres;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_erase);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Erase (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (void),
TEST (size),
TEST (size_size),
TEST (iter),
TEST (iter_iter)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.erase",
test_erase, tests, test_count);
}

View File

@@ -0,0 +1,832 @@
/***************************************************************************
*
* 21.string.exceptions.cpp - test string members that throw exceptions
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2008 Rogue Wave Software.
*
**************************************************************************/
#include <cassert>
#include <cstddef>
#include <stdexcept>
#include <string>
#include <driver.h>
// uses setjmp() and longjmp() to verify correct function if exception
// exception support is disabled
#ifdef _RWSTD_NO_EXCEPTIONS
# include <csetjmp>
int id; // "thrown" from user_throw () defined below
jmp_buf env; // used to implement fake exception handling
# undef try
# define try if (0 == (id = setjmp (env)))
# undef catch
# define catch(ignore) else if (0 != id)
#endif // _RWSTD_NO_EXCEPTIONS
// use a type that string isn't instantiated/specialized on by the library
// also use a native type to avoid having to specialize char_traits
typedef int Char;
typedef std::char_traits<Char> CharTraits;
typedef std::allocator<Char> CharAllocator;
typedef std::basic_string<Char, CharTraits, CharAllocator> String;
_RWSTD_NAMESPACE (std) {
// specialize in order to easily induce exceptional conditions
_RWSTD_SPECIALIZED_CLASS
String::size_type String::max_size () const
{
return _RWSTD_NEW_CAPACITY (String, this, 0);
}
} // namespace std
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
# include <rw_new.h>
#else
// can't check for memory leaks using the replacement
// operators new and delete
# define rwt_check_leaks(psize, ignore) \
((psize) ? *(std::size_t*)(psize) = 0 : 0)
#endif
/* static */ void
user_throw (int ex_id, char *what)
{
delete[] what;
#ifndef _RWSTD_NO_EXCEPTIONS
throw ex_id;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
longjmp (env, ex_id);
#endif // _RWSTD_NO_EXCEPTIONS
}
/**************************************************************************/
static void
test_simple_throw ()
{
rw_info (0, __FILE__, __LINE__, "exception handling test setup");
// establish a chekpoint for memory leaks
rwt_check_leaks (0, 0);
#ifdef _RWSTD_NO_EXCEPTIONS
// prevent library from aborting if exception support is disabled
_RW::__rw_throw_proc = user_throw;
#endif // _RWSTD_NO_EXCEPTIONS
int thrown = 0;
try {
// throw and catch a bogus exception in order to initialize
// data structures internal to the library to prevent any
// memory allocation from throwing off memory leak detection
_RWSTD_REQUIRES (0, (_RWSTD_ERROR_OUT_OF_RANGE,
_RWSTD_FUNC ("test_simple_throw ()"), 0, 0));
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (std::out_of_range&) {
thrown = 1;
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
catch (int id) {
thrown = id == _RWSTD_ERROR_OUT_OF_RANGE;
}
#endif // _RWSTD_NO_EXCEPTIONS
catch (...) {
thrown = -1;
}
rw_assert (1 == thrown, __FILE__, __LINE__,
"_RWSTD_REQUIRES (_RWSTD_ERROR_OUT_OF_RANGE) failed to "
"throw std::out_of_range");
}
/**************************************************************************/
// const objects used throughout remaining test cases
const Char s[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', '\0'
};
const String s0 (s);
/**************************************************************************/
// constructor tests
static void
test_size_ctor ()
{
rw_info (0, __FILE__, __LINE__, "21.3.1, p4 (size)");
// establish a chekpoint for memory leaks
rwt_check_leaks (0, 0);
int thrown = 0;
try {
// throws std::out_of_range if pos > str.size ()
String s1 (s0, s0.size () + 1);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (std::out_of_range&) {
thrown = 1;
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
catch (int id) {
thrown = id == _RWSTD_ERROR_OUT_OF_RANGE;
}
#endif // _RWSTD_NO_EXCEPTIONS
catch (...) {
thrown = -1;
}
std::size_t nbytes; /* uninitialized */
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
_RWSTD_UNUSED (nblocks);
rw_assert (1 == thrown, __FILE__, __LINE__,
("string::string (const string&, size_type, size_type, "
"const allocator_type&) failed to throw std::out_of_range"));
rw_assert (s == s0, __FILE__, __LINE__,
"original const string modified");
rw_assert (0 == nbytes, __FILE__, __LINE__,
"string::string (const string&, size_type, size_type, "
"const allocator_type&) leaked %u bytes", nbytes);
}
static void
test_npos_ctor ()
{
rw_info (0, __FILE__, __LINE__, "21.3.1, p4 (npos)");
_RW::__rw_throw_proc = user_throw;
// establish a chekpoint for memory leaks
rwt_check_leaks (0, 0);
int thrown = 0;
try {
// throws std::out_of_range if pos > str.size ()
String s1 (s0, String::npos);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
std::size_t nbytes; /* uninitialized */
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
_RWSTD_UNUSED (nblocks);
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::string (const string&, size_type, size_type, "
"const allocator_type&) failed to use __rw::__rw_throw()");
rw_assert (0 == nbytes, __FILE__, __LINE__,
"string::string (const string&, size_type, size_type, "
"const allocator_type&) leaked %u bytes", nbytes);
rw_assert (s == s0, __FILE__, __LINE__,
"original const string modified");
}
static void
test_max_size_ctor1 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.1, p7");
// establish a chekpoint for memory leaks
rwt_check_leaks (0, 0);
int thrown = 0;
try {
// throws std::out_of_range if n > max_size () (*)
// (*) see also lwg issue 83
String s1 (s0.data (), s0.max_size () + 1);
}
catch (int id) {
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
}
catch (...) { /* empty */ }
std::size_t nbytes; /* uninitialized */
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
_RWSTD_UNUSED (nblocks);
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::string (const char_type*, size_type) "
"failed to use __rw::__rw_throw()");
rw_assert (0 == nbytes, __FILE__, __LINE__,
"string::string (const char_type*, size_type)"
"leaked %u bytes", nbytes);
rw_assert (s == s0, __FILE__, __LINE__,
"original const string modified");
}
static void
test_max_size_ctor2 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.1, p13");
int thrown = 0;
try {
// throws std::length_error if n > max_size () (*)
// (*) see also lwg issue 83
String s1 (s0.max_size () + 1, Char ());
}
catch (int id) {
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::string (size_type, char_type) "
"failed to use __rw::__rw_throw()");
}
static void
test_len_ctor ()
{
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
rw_info (0, __FILE__, __LINE__, "21.3.1, p15");
int thrown = 0;
try {
// same as 21.3.1, p13 for integral arguments
String s1 = String (long (String::npos), long (' '));
}
catch (int id) {
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::string (InputIterator, InputIterator)"
"failed to use __rw::__rw_throw()");
#endif // _RWSTD_NO_MEMBER_TEMPLATES
}
/**************************************************************************/
// member functions
static void
test_resize ()
{
rw_info (0, __FILE__, __LINE__, "21.3.3, p6");
String s1 (s0);
// save data, size and capacity of a constructed string
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
rw_assert (s1.size () == s0.size () && s1 == s0, __FILE__, __LINE__,
"std::string::string (const string&)");
int thrown = 0;
try {
// throws std::length_error if n > max_size ()
s1.resize (s1.max_size () + 1U /* , char () */);
}
catch (int id) {
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::resize (size_type, char_type)"
"failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::resize (size_type, char_type) modified *this");
}
static void
test_reserve ()
{
rw_info (0, __FILE__, __LINE__, "21.3.3, p12");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::length_error if n > max_size ()
s1.reserve (s1.max_size () + 1U);
}
catch (int id) {
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::reserve (size_type)"
"failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::reserve (size_type) modified *this");
}
static void
test_at ()
{
rw_info (0, __FILE__, __LINE__, "21.3.4, p3");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if pos > size ()
s1.at (s1.size ());
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::at (size_type) failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::at (size_type) modified *this");
}
static void
test_append ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.2, p3");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if pos > size ()
s1.append (s1, s1.size () + 1, 0);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::append (const string&, size_type, size_type) "
"failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::append (const string&, size_type, size_type) "
"modified *this");
}
static void
test_assign ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.3, p3");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if pos > size ()
s1.assign (s1, s1.size () + 1, 0);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::assign (const string&, size_type, size_type) "
"failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::assign (const string&, size_type, size_type) "
"modified *this");
}
static void
test_insert1 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.4, p3 (pos1 > size ())");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if:
// 1) pos1 > size () <-- testing
// 2) or pos2 > str.size ()
s1.insert (s1.size () + 1, s1, 0, 0);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::insert (size_type, const string&, size_type, "
"size_type) failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::insert (size_type, const string&, size_type, "
"modified *this");
}
static void
test_insert2 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.4, p3 (pos2 > str.size ())");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if:
// 1) pos1 > size ()
// 2) or pos2 > str.size () <-- testing
s1.insert (s1.size (), s1, s1.size () + 1, 0);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::insert (size_type, const string&, size_type, "
"size_type) failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::insert (size_type, const string&, size_type, "
"modified *this");
}
static void
test_erase ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.5, p2");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if pos > size ()
s1.erase (s1.size () + 1 /* , String::npos */);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::erase (size_type, size_type) "
"failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::erase (size_type, size_type) modified *this");
}
static void
test_replace1 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.6, p3 (pos1 > size ())");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if:
// 1) pos1 > size () <-- testing
// 2) or pos2 > str.size ()
s1.replace (s1.size () + 1, 0, s0, s0.size (), 0);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) modified *this");
}
static void
test_replace2 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.6, p3 (pos2 > str.size ())");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
try {
// throws std::out_of_range if:
// 1) pos1 > size ()
// 2) or pos2 > str.size () <-- testing
s1.replace (s1.size (), 0, s1, s1.size () + 1, 0);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) modified *this");
}
static void
test_replace3 ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.6, p5");
int thrown = 0;
String s1 (s0);
const String::const_pointer s1_data = s1.data ();
const String::size_type s1_size = s1.size ();
const String::size_type s1_cap = s1.capacity ();
// establish a chekpoint for memory leaks
rwt_check_leaks (0, 0);
try {
// make sure max_size() isn't too big
assert (s1.max_size () == _RWSTD_NEW_CAPACITY (String, &s1, 0));
thrown = -1;
// must not throw
String s2 (s1.max_size () - s1.size () + 2, Char ());
thrown = 0;
// throws std::length_error if:
// size () - xlen >= max_size () - rlen (*)
// where xlen = min (n1, this->size () - pos1)
// and rlen = min (n2, str.size () - pos2)
// (*) see also lwg issue 86
s1.replace (0, 1, s2, 0, s2.size ());
}
catch (int id) {
thrown = 0 == thrown && _RWSTD_ERROR_LENGTH_ERROR == id;
}
catch (...) { /* empty */ }
std::size_t nbytes; /* uninitialized */
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
_RWSTD_UNUSED (nblocks);
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) failed to use __rw::__rw_throw()");
// verify that string wasn't modified
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) modified *this");
// tests not only replace() but also string ctor (s2 above)
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::replace (size_type, size_type, const string&, "
"size_type, size_type) leaked %u bytes", nbytes);
}
static void
test_copy ()
{
rw_info (0, __FILE__, __LINE__, "21.3.5.7, p2");
int thrown = 0;
Char c = '\1';
String s1 (s0);
try {
// throws std::out_of_range if pos > size ()
s1.copy (&c, 1, s1.size () + 1);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::copy (pointer, size_type, size_type) "
"failed to use __rw::__rw_throw()");
// verify that destination buffer wasn't modified
rw_assert ('\1' == c, __FILE__, __LINE__,
"string::copy (pointer, size_type, size_type) "
"modified buffer");
}
static void
test_substr ()
{
rw_info (0, __FILE__, __LINE__, "21.3.6.7, p2");
int thrown = 0;
String s1 (s0);
try {
// throws std::out_of_range if pos > size ()
s1.substr (s1.size () + 1 /* , String::npos */);
}
catch (int id) {
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
}
catch (...) { /* empty */ }
rw_assert (1 == thrown, __FILE__, __LINE__,
"string::substr (size_type, size_type) "
"failed to use __rw::__rw_throw()");
}
/**************************************************************************/
static int
run_test (int /*unused*/, char* /*unused*/ [])
{
test_simple_throw ();
// constructors
test_size_ctor ();
test_npos_ctor ();
test_max_size_ctor1 ();
test_max_size_ctor2 ();
test_len_ctor ();
// member functions
test_resize ();
test_reserve ();
test_at ();
test_append ();
test_assign ();
test_insert1 ();
test_insert2 ();
test_erase ();
test_replace1 ();
test_replace2 ();
test_replace3 ();
test_copy ();
test_substr ();
return 0;
}
/*extern*/ int
main (int argc, char* argv [])
{
return rw_test (argc, argv, __FILE__,
"lib.basic.string",
"exception saftety",
run_test, "", 0);
}

View File

@@ -0,0 +1,804 @@
/***************************************************************************
*
* 21.string.find.cpp - string test exercising lib.string.find
*
* $Id: 21.string.find.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // size_t
#include <exception> // for exception
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_assert()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define Find(sig) StringIds::find_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// find (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +---- expected result
// | | |
// | | |
// V V V
TEST ("", "", 0),
TEST ("", "a", NPOS),
TEST ("", "\0", 0),
TEST ("ab", "a", 0),
TEST ("\0", "", 0),
TEST ("\0", "\0", 0),
TEST ("\0", "a", NPOS),
TEST ("aababcabcd", "", 0),
TEST ("aababcabcd", "a", 0),
TEST ("aababcabcd", "ab", 1),
TEST ("aababcabcd", "abc", 3),
TEST ("aababcabcd", "abcd", 6),
TEST ("aababcabcd", "abcde", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", NPOS),
TEST ("edfcbahjig", "cba", 3),
TEST ("edfcbahcba", "cba", 3),
TEST ("cbacbahjig", "cba", 0),
TEST ("e\0cb\0\0g", "b\0\0g", 3),
TEST ("e\0cb\0\0g", "ecb", NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 0),
TEST ("\0cb\0\0ge", "cb\0", 1),
TEST ("e\0cbg\0\0", "bg", 3),
TEST ("e\0cbg\0\0", "cba", NPOS),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 2),
TEST ("bcedfaajih", "a", 5),
TEST ("bcaaedfaji", "a", 2),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0),
TEST ("aaaaabaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaabaaaaa", "aaaaa", 5),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0),
TEST ("aaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", 0),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 0),
TEST ("x@4096", "xxx", 0),
TEST ("x@4096", "xxa", NPOS),
TEST ("abc", "x@4096", NPOS),
TEST ("xxxxxxxxxx", "x@4096", NPOS),
TEST ("abcdefghij", 0, 0),
TEST ("\0cb\0\0ge", 0, 0),
TEST ("x@4096", 0, 0),
TEST ("last test", "test", 5)
};
/**************************************************************************/
// exercises:
// find (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------ controlled sequence
// | +---------------------- sequence to be found
// | | +----- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", 0),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", 0),
TEST ("\0", "\0", 0),
TEST ("\0", "\0\0", NPOS),
TEST ("\0", "a", NPOS),
TEST ("\0a", "a\0", NPOS),
TEST ("aababcabcd", "", 0),
TEST ("aababcabcd", "a", 0),
TEST ("aababcabcd", "ab", 1),
TEST ("aababcabcd", "abc", 3),
TEST ("aababcabcd", "abcd", 6),
TEST ("aababcabcd", "abcde", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", NPOS),
TEST ("edfcbahjig", "cba", 3),
TEST ("edfcbahcba", "cba", 3),
TEST ("cbacbahjig", "cba", 0),
TEST ("e\0cb\0\0g", "b\0\0g", 3),
TEST ("e\0cb\0\0g", "ecb", NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 3),
TEST ("\0cb\0\0ge", "cb\0", 1),
TEST ("\0cb\0\0ge", "cb\0a", NPOS),
TEST ("e\0cbg\0\0", "bg", 3),
TEST ("e\0cbg\0\0", "\0\0", 5),
TEST ("e\0cbg\0\0", "\0\0a", NPOS),
TEST ("e\0cbg\0\0", "cba", NPOS),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 2),
TEST ("bcedfaajih", "a", 5),
TEST ("bcaaedfaji", "a", 2),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0),
TEST ("aaaaabaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaabaaaaa", "aaaaa", 5),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0),
TEST ("aaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", 0),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 0),
TEST ("x@4096", "xxx", 0),
TEST ("x@4096", "xxa", NPOS),
TEST ("abc", "x@4096", NPOS),
TEST ("xxxxxxxxxx", "x@4096", NPOS),
TEST ("abcdefghij", 0, 0),
TEST ("\0cb\0\0ge", 0, 0),
TEST ("x@4096", 0, 0),
TEST ("last test", "test", 5)
};
/**************************************************************************/
// exercises:
// find (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) { \
__LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, 0 \
}
// +-------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +--------- find() off argument
// | | | +-- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, 0),
TEST ("", "\0", 0, 0),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, 1),
TEST ("\0", "a", 0, NPOS),
TEST ("aababcabcd", "", 0, 0),
TEST ("aababcabcd", "a", 0, 0),
TEST ("aababcabcd", "ab", 0, 1),
TEST ("aababcabcd", "abc", 0, 3),
TEST ("aababcabcd", "abcd", 0, 6),
TEST ("aababcabcd", "abcde", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, NPOS),
TEST ("abcdefghij", "f", 2, 5),
TEST ("abcdefghij", "f", 7, NPOS),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 0, NPOS),
TEST ("edfcbahjig", "cba", 1, 3),
TEST ("edfcbahjig", "cba", 4, NPOS),
TEST ("edfcbahcba", "cba", 1, 3),
TEST ("edfcbahcba", "cba", 5, 7),
TEST ("cbacbahjig", "cba", 5, NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 4, NPOS),
TEST ("e\0cb\0\0g", "ecb", 0, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 6),
TEST ("\0cb\0\0ge", "cb\0", 1, 1),
TEST ("e\0cbg\0\0", "bg", 1, 3),
TEST ("e\0cbg\0\0", "cba", 0, NPOS),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 1, 2),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 5, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, NPOS),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 0, NPOS),
TEST ("aaaabaaaaa", "aaaaa", 0, 5),
TEST ("aaaabaaaaa", "aaaaa", 6, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 1, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 2, NPOS),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 0, NPOS),
TEST ("x@4096", "", 0, 0),
TEST ("x@4096", "a", 0, NPOS),
TEST ("x@4096", "x", 0, 0),
TEST ("x@4096", "xxx", 10, 10),
TEST ("x@4096", "xxa", 10, NPOS),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 0, NPOS),
TEST ("x@4096", "xxx", 4092, 4092),
TEST ("x@4096", "xxx", 4094, NPOS),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 1, NPOS),
TEST ("\0cb\0\0ge", 0, 5, 5),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 1, NPOS),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, NPOS),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 0, 5)
};
/**************************************************************************/
// exercises:
// find (const value_type*, size_type, size_type)
static const StringTestCase
cptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, size, res) { \
__LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +-------------------------- sequence to be found
// | | +---------- find() off argument
// | | | +------ find() n argument
// | | | | +-- expected result
// | | | | |
// | | | | |
// | | | | |
// | | | | |
// | | | | |
// V V V V V
TEST ("ab", "a", 0, 1, 0),
TEST ("", "", 0, 0, 0),
TEST ("", "\0", 0, 0, 0),
TEST ("", "\0", 0, 1, NPOS),
TEST ("", "a", 0, 0, 0),
TEST ("", "a", 0, 1, NPOS),
TEST ("aababcabcd", "", 0, 0, 0),
TEST ("aababcabcd", "a", 0, 1, 0),
TEST ("aababcabcd", "ab", 0, 2, 1),
TEST ("aababcabcd", "abc", 0, 3, 3),
TEST ("aababcabcd", "abcd", 0, 4, 6),
TEST ("aababcabcd", "abcde", 0, 5, NPOS),
TEST ("aababcabcd", "aababcabcde", 0, 11, NPOS),
TEST ("\0", "", 0, 0, 0),
TEST ("\0", "\0", 0, 1, 0),
TEST ("\0", "\0", 1, 1, NPOS),
TEST ("\0\0", "\0\0", 1, 1, 1),
TEST ("\0", "a", 0, 1, NPOS),
TEST ("edfcbbhjig", "cba", 0, 3, NPOS),
TEST ("edfcbbhjig", "cba", 0, 2, 3),
TEST ("edfcbahjig", "cba", 1, 3, 3),
TEST ("edfcbahjig", "cba", 4, 3, NPOS),
TEST ("edfcbahjig", "cba", 4, 1, NPOS),
TEST ("edfcbahcba", "cba", 1, 3, 3),
TEST ("edfcbehcba", "cba", 1, 2, 3),
TEST ("edfcbahcba", "cba", 5, 3, 7),
TEST ("cbacbahjig", "cba", 5, 3, NPOS),
TEST ("cbacbahjcg", "cba", 5, 1, 8),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 4, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 4, NPOS),
TEST ("e\0cb\0\0b", "b\0\0g", 4, 1, 6),
TEST ("\0b\0\0gb\0","b\0\0g", 2, 2, 5),
TEST ("\0b\0\0gb\0","b\0\0g", 0, 2, 1),
TEST ("\0b\0\0gb\0","b\0\0g", 0, 3, 1),
TEST ("e\0cb\0\0g", "ecb", 0, 2, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 4, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 0, 6),
TEST ("\0cb\0\0ge", "cb\0", 1, 3, 1),
TEST ("e\0cbg\0\0", "bg", 1, 2, 3),
TEST ("e\0cbg\0\0", "cba", 0, 3, NPOS),
TEST ("e\0cbg\0\0", "cba", 0, 2, 2),
TEST ("e\0a\0", "e\0a\0\0", 0, 4, 0),
TEST ("e\0a\0", "e\0a\0\0", 0, 5, NPOS),
TEST ("ee\0a\0", "e\0a\0\0", 1, 4, 1),
TEST ("ee\0a\0", "e\0a\0\0", 1, 5, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 10, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, 10, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, 9, 1),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 0, 10, NPOS),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 1, 4, 1),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 2, 4, 6),
TEST ("aaaabaaaaa", "aaaaa", 0, 5, 5),
TEST ("aaaabaaaaa", "aaaaa", 0, 4, 0),
TEST ("aaaabaaaaa", "aaaaa", 6, 5, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0, 9, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 1, 9, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 2, 9, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 2, 8, 2),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 0, 10, NPOS),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 0, 7, 0),
TEST ("x@4096", "", 0, 0, 0),
TEST ("x@4096", "a", 0, 1, NPOS),
TEST ("x@4096", "x", 0, 1, 0),
TEST ("x@4096", "xxx", 10, 3, 10),
TEST ("x@4096", "xxa", 10, 3, NPOS),
TEST ("x@4096", "xxa", 10, 2, 10),
TEST ("abc", "x@4096", 2, 10, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 0, 4096, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 2, 4, 2),
TEST ("x@4096", "xxx", 4093, 3, 4093),
TEST ("x@4096", "xxx", 4094, 3, NPOS),
TEST ("x@4096", "xxx", 4094, 2, 4094),
TEST ("abcdefghij", 0, 0, 9, 0),
TEST ("abcdefghij", 0, 1, 9, NPOS),
TEST ("\0cb\0\0ge", 0, 5, 7, NPOS),
TEST ("\0cb\0ge\0", 0, 6, 1, 6),
TEST ("x@4096", 0, 0, 4096, 0),
TEST ("x@4096", 0, 1, 4096, NPOS),
TEST ("x@4096", 0, 5, 4091, 5),
TEST ("", "", 1, 0, NPOS),
TEST ("abcdefghij", "abc", 10, 3, NPOS),
TEST ("abcdefghij", "cba", 10, 1, NPOS),
// excercise strictly undefined behavior
TEST ("", "cba", 0, -1, NPOS),
TEST ("abcdefghij", "cba", 0, -1, NPOS),
TEST ("x@4096", "xxx", 0, -1, NPOS),
TEST ("abcdefghij", "x@4096", 0, -1, NPOS),
TEST ("last test", "test", 0, 4, 5)
};
/**************************************************************************/
// exercises:
// find (const basic_string&, size_type)
static const StringTestCase
cstr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) { \
__LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, \
arg, sizeof arg - 1, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +---------- find() off argument
// | | | +---- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, 0),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0\0", "\0", 1, 1),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, NPOS),
TEST ("abcdefghij", "f", 2, 5),
TEST ("abcdefghij", "f", 7, NPOS),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 0, NPOS),
TEST ("edfcbahjig", "cba", 1, 3),
TEST ("edfcbahjig", "cba", 4, NPOS),
TEST ("edfcbahcba", "cba", 1, 3),
TEST ("edfcbahcba", "cba", 5, 7),
TEST ("cbacbahjig", "cba", 5, NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 4, NPOS),
TEST ("e\0cb\0\0g", "ecb", 0, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 1, 3),
TEST ("\0cb\0\0ge", "cb\0", 1, 1),
TEST ("\0cbg\0\0e", "cb\0", 1, NPOS),
TEST ("e\0cbg\0\0", "bg", 1, 3),
TEST ("e\0cbg\0\0", "cba", 0, NPOS),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 1, 2),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 5, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, NPOS),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 0, NPOS),
TEST ("aaaabaaaaa", "aaaaa", 0, 5),
TEST ("aaaabaaaaa", "aaaaa", 6, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 1, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 2, NPOS),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 0, NPOS),
TEST ("x@4096", "", 0, 0),
TEST ("x@4096", "a", 0, NPOS),
TEST ("x@4096", "x", 0, 0),
TEST ("x@4096", "xxx", 10, 10),
TEST ("x@4096", "xxa", 10, NPOS),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 0, NPOS),
TEST ("x@4096", "xxx", 4093, 4093),
TEST ("x@4096", "xxx", 4094, NPOS),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 1, NPOS),
TEST ("\0cb\0\0ge", 0, 5, NPOS),
TEST ("\0cb\0\0ge", 0, 0, 0),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 1, NPOS),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, NPOS),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 0, 5)
};
/**************************************************************************/
// exercises:
// find (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res) { \
__LINE__, -1, -1, -1, -1, val, \
str, sizeof str - 1, 0, 0, 0, res, 0 \
}
// +----------------------------- controlled sequence
// | +-------------- character to be found
// | | +------ expected result
// | | |
// | | |
// V V V
TEST ("ab", 'a', 0),
TEST ("", 'a', NPOS),
TEST ("", '\0', NPOS),
TEST ("\0", '\0', 0),
TEST ("\0\0", '\0', 0),
TEST ("\0", 'a', NPOS),
TEST ("e\0cb\0\0g", '\0', 1),
TEST ("e\0cb\0\0g", 'b', 3),
TEST ("e\0cb\0\0g", 'a', NPOS),
TEST ("\0cbge\0\0", '\0', 0),
TEST ("\0cbge\0\0", 'b', 2),
TEST ("\0cbge\0\0", 'a', NPOS),
TEST ("x@4096", 'x', 0),
TEST ("x@4096", '\0', NPOS),
TEST ("x@4096", 'a', NPOS),
TEST ("last test", 't', 3)
};
/**************************************************************************/
// exercises:
// find (value_type, size_type)
static const StringTestCase
val_size_test_cases [] = {
#undef TEST
#define TEST(str, val, off, res) { \
__LINE__, off, -1, -1, -1, val, \
str, sizeof str - 1, 0, 0, 0, res, 0 \
}
// +------------------------------ controlled sequence
// | +--------------- character to be found
// | | +--------- find() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", 'a', 0, 0),
TEST ("", 'a', 0, NPOS),
TEST ("", '\0', 0, NPOS),
TEST ("\0", '\0', 1, NPOS),
TEST ("\0", 'a', 0, NPOS),
TEST ("\0\0", '\0', 1, 1),
TEST ("\0\0", 'a', 3, NPOS),
TEST ("\0\0", '\0', 3, NPOS),
TEST ("e\0cb\0\0g", '\0', 1, 1),
TEST ("e\0cb\0\0g", '\0', 2, 4),
TEST ("e\0cb\0\0g", '\0', 6, NPOS),
TEST ("e\0cb\0\0g", 'b', 1, 3),
TEST ("e\0cb\0\0g", 'b', 4, NPOS),
TEST ("e\0cb\0\0g", 'a', 0, NPOS),
TEST ("\0cbge\0\0", '\0', 0, 0),
TEST ("\0cbge\0\0", '\0', 1, 5),
TEST ("\0cbge\0\0", '\0', 9, NPOS),
TEST ("\0cbge\0\0", 'b', 0, 2),
TEST ("\0bgeb\0\0", 'b', 2, 4),
TEST ("\0cbge\0\0", 'a', 1, NPOS),
TEST ("x@4096", 'x', 0, 0),
TEST ("x@4096", 'x', 5, 5),
TEST ("x@4096", '\0', 0, NPOS),
TEST ("x@2048\0xxx",'\0', 0, 2048),
TEST ("x@4096", 'a', 3, NPOS),
TEST ("x@4096", 'x', 4096, NPOS),
TEST ("x@4096", 'x', 4095, 4095),
TEST ("last test", 't', 0, 3)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_find (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object and the argument string
const String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
// string function argument
const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;
#ifndef _RWSTD_NO_EXCEPTIONS
// no exceptions expected
const char* expected = 0;
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
std::size_t res = 0;
switch (func.which_) {
case Find (cptr):
res = s_str.find (arg_ptr);
break;
case Find (cstr):
res = s_str.find (arg_str);
break;
case Find (cptr_size):
res = s_str.find (arg_ptr, tcase.off);
break;
case Find (cptr_size_size):
res = s_str.find (arg_ptr, tcase.off, size);
break;
case Find (cstr_size):
res = s_str.find (arg_str, tcase.off);
break;
case Find (val):
res = s_str.find (arg_val);
break;
case Find (val_size):
res = s_str.find (arg_val, tcase.off);
break;
default:
RW_ASSERT (!"logic error: unknown find overload");
return;
}
const std::size_t exp_res =
NPOS != tcase.nres ? tcase.nres : String::npos;
// verify the returned value
rw_assert (exp_res == res, 0, tcase.line,
"line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
"got %{?}%zu%{;}%{?}npos%{;}",
__LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres,
String::npos != res, res, String::npos == res);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_find);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Find (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cptr_size_size),
TEST (cstr_size),
TEST (val),
TEST (val_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.find",
test_find, tests, test_count);
}

View File

@@ -0,0 +1,773 @@
/***************************************************************************
*
* 21.string.find.first.not.of.cpp -
* string test exercising lib.string.find.first.not.of
*
* $Id: 21.string.find.first.not.of.cpp 580483 2007-09-28 20:55:52Z sebor $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
**************************************************************************/
#include <string> // for string
#include <cstdlib> // for free(), size_t
#include <stdexcept> // for length_error
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define FindFirstNotOf(sig) StringIds::find_first_not_of_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// find_first_not_of (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +---- expected result
// | | |
// | | |
// V V V
TEST ("ab", "c", 0),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", 0),
TEST ("\0", "\0", 0),
TEST ("\0", "a", 0),
TEST ("bbcdefghij", "a", 0),
TEST ("abcdefghij", "a", 1),
TEST ("abcdefghij", "f", 0),
TEST ("eaccbbhjig", "cba", 0),
TEST ("ceabcbahca", "cba", 1),
TEST ("bacbahjicg", "cba", 5),
TEST ("abbcbacbca", "cba", NPOS),
TEST ("bcbedfbjih", "abce", 4),
TEST ("bcaedfajih", "aabced", 5),
TEST ("bcedfaacdh", "abcdef", 9),
TEST ("e\0cb\0\0g", "b\0\0g", 0),
TEST ("e\0cb\0\0g", "cbe", 1),
TEST ("\0cb\0\0ge", "\0\0ge", 0),
TEST ("bcbc\0\0be", "b\0c", 1),
TEST ("gbg\0\0e\0", "bg", 3),
TEST ("a\0b", "e\0gbg\0\0", 0),
TEST ("b\0a", "eb\0gg\0\0", 1),
TEST ("ab\0", "ab\0gg\0\0", 2),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaaabaaaa", "cccccccccb", 0),
TEST ("aabaabaaaa", "aaaaaaaaab", NPOS),
TEST ("bbb", "aaaaaaaaba", NPOS),
TEST ("aab", "aaaaaaaaaa", 2),
TEST ("x@4096", "", 0),
TEST ("x@4096", "a", 0),
TEST ("x@4096", "x", NPOS),
TEST ("x@4096", "axa", NPOS),
TEST ("abc", "x@4096", 0),
TEST ("xabc", "x@4096", 1),
TEST ("abcdefghij", 0, NPOS),
TEST ("\0cb\0\0ge", 0, 0),
TEST ("x@4096", 0, NPOS),
TEST ("last test", "test", 0)
};
/**************************************************************************/
// used to exercise
// find_first_not_of (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------ controlled sequence
// | +---------------------- sequence to be found
// | | +----- expected result
// | | |
// | | |
// V V V
TEST ("ab", "c", 0),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", 0),
TEST ("\0", "\0", NPOS),
TEST ("\0\0", "\0", NPOS),
TEST ("\0", "a", 0),
TEST ("bbcdefghij", "a", 0),
TEST ("abcdefghij", "a", 1),
TEST ("abcdefghij", "f", 0),
TEST ("eaccbbhjig", "cba", 0),
TEST ("ceabcbahca", "cba", 1),
TEST ("bacbahjicg", "cba", 5),
TEST ("abbcbacbca", "cba", NPOS),
TEST ("bcbedfbjih", "abce", 4),
TEST ("bcaedfajih", "aabced", 5),
TEST ("bcedfaacdh", "abcdef", 9),
TEST ("e\0cb\0\0g", "b\0\0g", 0),
TEST ("\0cb\0\0ge", "b\0\0g", 1),
TEST ("\0gb\0\0ge", "b\0\0g", 6),
TEST ("e\0cb\0\0g", "cbe", 1),
TEST ("\0cb\0\0ge", "\0\0ge", 1),
TEST ("bcbc\0\0bc", "b\0c", NPOS),
TEST ("gbg\0\0e\0", "bg", 3),
TEST ("a\0b", "e\0gbg\0\0", 0),
TEST ("b\0a", "eb\0gg\0\0", 2),
TEST ("ab\0", "ab\0gg\0\0", NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaaabaaaa", "cccccccccb", 0),
TEST ("aabaabaaaa", "aaaaaaaaab", NPOS),
TEST ("bbb", "aaaaaaaaba", NPOS),
TEST ("aab", "aaaaaaaaaa", 2),
TEST ("x@4096", "", 0),
TEST ("x@4096", "a", 0),
TEST ("x@4096", "x", NPOS),
TEST ("x@4096", "axa", NPOS),
TEST ("abc", "x@4096", 0),
TEST ("xabc", "x@4096", 1),
TEST ("abcdefghij", 0, NPOS),
TEST ("\0cb\0\0ge", 0, NPOS),
TEST ("x@4096", 0, NPOS),
TEST ("last test", "test", 0)
};
/**************************************************************************/
// used to exercise
// find_first_not_of (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +---------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +----- find_first_not_of() off argument
// | | | +- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "c", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0", "a", 0, 0),
TEST ("bbcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 0, 1),
TEST ("bcaaaaaaaa", "a", 2, NPOS),
TEST ("bcaaafaaaa", "a", 2, 5),
TEST ("abcdefghij", "j", 9, NPOS),
TEST ("cbbedfhjig", "cba", 0, 3),
TEST ("edfcbahjig", "cba", 4, 6),
TEST ("edfcbaaabc", "cba", 6, NPOS),
TEST ("edfcbahcba", "cba", 9, NPOS),
TEST ("cbacbabjig", "cbaig", 0, 7),
TEST ("bcaedfajih", "aabced", 0, 5),
TEST ("bcedfaacdh", "abcdef", 3, 9),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 0),
TEST ("\0cbe\0\0g", "b\0\0g", 4, 4),
TEST ("e\0cb\0\0g", "cbe", 0, 1),
TEST ("\0cb\0\0ge", "\0\0ge", 0, 0),
TEST ("\0cb\0\0ge", "cb\0", 6, 6),
TEST ("e\0gbg\0\0", "bg", 2, 5),
TEST ("a\0b", "a\0gbg\0\0", 0, 1),
TEST ("ab\0", "ab\0gg\0\0", 1, 2),
TEST ("a\0b", "e\0gg\0\0a", 3, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, NPOS),
TEST ("aaabaaaaaa", "aaaaaaaaaa", 4, NPOS),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 1, 5),
TEST ("aabaabaaaa", "aaaaaaaaaa", 0, 2),
TEST ("aabaabaaaa", "aaaaaaaaaa", 3, 5),
TEST ("aabaabaaaa", "aaaaaaaaab", 0, NPOS),
TEST ("cbb", "aaaaaaaaba", 2, NPOS),
TEST ("bac", "aaaaaaaaba", 0, 2),
TEST ("baa", "aaaaaaaaaa", 0, 0),
TEST ("x@4096", "", 0, 0),
TEST ("x@4096", "a", 0, 0),
TEST ("x@4096", "x", 0, NPOS),
TEST ("x@4096", "xxx", 10, NPOS),
TEST ("x@4096", "axa", 10, NPOS),
TEST ("abc", "x@4096", 2, 2),
TEST ("xxxxxxxxxx", "x@4096", 0, NPOS),
TEST ("x@4096", "xxx", 4094, NPOS),
TEST ("x@4096", "xxx", 4095, NPOS),
TEST ("x@2048axxx", "x", 1, 2048),
TEST ("abcdefghij", 0, 0, NPOS),
TEST ("abcdefghij", 0, 1, NPOS),
TEST ("\0cb\0\0ge", 0, 5, 5),
TEST ("x@4096", 0, 0, NPOS),
TEST ("x@4096", 0, 7, NPOS),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, NPOS),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 0, 0)
};
/**************************************************************************/
// used to exercise
// find_first_not_of (const value_type*, size_type, size_type)
static const StringTestCase
cptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, size, res, bthrow) \
{ __LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, bthrow \
}
// +---------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +----- find_first_not_of() off argument
// | | | +- find_first_not_of() n argument
// | | | | +- expected result
// | | | | | exception info
// | | | | | | 0 - no exception
// | | | | | | 1 - length_error
// | | | | | |
// | | | | | +-----+
// V V V V V V
TEST ("ab", "c", 0, 1, 0, 0),
TEST ("", "", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 1, NPOS, 0),
TEST ("", "a", 0, 0, NPOS, 0),
TEST ("", "a", 0, 1, NPOS, 0),
TEST ("\0", "", 0, 0, 0, 0),
TEST ("\0", "\0", 0, 1, NPOS, 0),
TEST ("\0", "\0", 1, 1, NPOS, 0),
TEST ("\0\0", "\0\0", 1, 1, NPOS, 0),
TEST ("\0", "a", 0, 1, 0, 0),
TEST ("a", "\0", 0, 1, 0, 0),
TEST ("cbbedfhjig", "cba", 0, 3, 3, 0),
TEST ("edfcbbhjig", "bac", 0, 2, 0, 0),
TEST ("edfcbahaib", "cba", 7, 3, 8, 0),
TEST ("edfcbahbcb", "cba", 7, 2, NPOS, 0),
TEST ("edfcbahbcb", "cba", 3, 2, 5, 0),
TEST ("edfcbahcba", "bac", 3, 3, 6, 0),
TEST ("edacbehcba", "abc", 2, 2, 3, 0),
TEST ("babcbahcba", "cba", 0, 3, 6, 0),
TEST ("hjigcbacba", "cba", 4, 3, NPOS, 0),
TEST ("cbacbcccbc", "cba", 5, 1, 8, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 4, 0, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 4, NPOS, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 1, 4, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 2, 6, 0),
TEST ("\0b\0\0gb\0","bg\0", 2, 2, 2, 0),
TEST ("\0b\0\0gb\0","bg\0", 0, 2, 0, 0),
TEST ("\0b\0\0gb\0","bg\0", 0, 3, NPOS, 0),
TEST ("e\0cb\0\0g", "a\0e", 0, 3, 2, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 7, 4, NPOS, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 0, 6, 0),
TEST ("a\0b", "e\0gbg\0\0", 0, 1, 0, 0),
TEST ("a\0b", "ab\0gg\0\0", 1, 2, 1, 0),
TEST ("a\0b", "\0ba\0\0fe", 1, 2, NPOS, 0),
TEST ("a\0b", "e\0gg\0\0a", 3, 6, NPOS, 0),
TEST ("a\0b", "e\0gg\0\0a", 0, 7, 2, 0),
TEST ("\0baa", "b\0g\0\0ac", 0, 4, 2, 0),
TEST ("e\0a\0", "e\0a\0\0", 0, 4, NPOS, 0),
TEST ("\0\0ea", "b\0c\0\0", 0, 5, 2, 0),
TEST ("ee\0b\0", "e\0a\0b", 1, 4, 3, 0),
TEST ("be\0a\0", "\0acefdg", 1, 5, NPOS, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 10, NPOS, 0),
TEST ("baaaaaaaaa", "aaaaaaaaaa", 1, 10, NPOS, 0),
TEST ("aaaaabaaaa", "cccccccccc", 0, 10, 0, 0),
TEST ("aaaaabaaaa", "aaaaaccbcc", 1, 4, 5, 0),
TEST ("aaaabaaaaa", "cccca", 0, 5, 4, 0),
TEST ("aabaabadca", "acaaacccab", 0, 5, 2, 0),
TEST ("abcdefghij", "jihgfedcba", 0, 10, NPOS, 0),
TEST ("abcdefghij", "jihgfedcba", 0, 9, 0, 0),
TEST ("bbb", "aaaaaaaaba", 2, 2, 2, 0),
TEST ("bbb", "aaaaaaaaba", 0, 9, NPOS, 0),
TEST ("bab", "baaaaaaaaa", 0, 0, 0, 0),
TEST ("bab", "ccccccccba", 1, 10, NPOS, 0),
TEST ("x@4096", "", 0, 0, 0, 0),
TEST ("x@4096", "a", 0, 1, 0, 0),
TEST ("x@4096", "x", 0, 1, NPOS, 0),
TEST ("x@4096", "xxx", 10, 3, NPOS, 0),
TEST ("x@4096", "axx", 10, 1, 10, 0),
TEST ("x@4096", "xxa", 10, 0, 10, 0),
TEST ("x@4096", "xxa", 10, 1, NPOS, 0),
TEST ("abc", "x@4096", 2, 10, 2, 0),
TEST ("xxxxxxxxxx", "x@4096", 0, 4096, NPOS, 0),
TEST ("xxxxxxxxxx", "x@4096", 2, 4, NPOS, 0),
TEST ("xxxxxxxxxa", "x@4096", 0, 4, 9, 0),
TEST ("x@4096", "xxx", 4094, 3, NPOS, 0),
TEST ("x@4096", "xxx", 4093, 0, 4093, 0),
TEST ("abcdefghij", 0, 0, 10, NPOS, 0),
TEST ("abcdefghij", 0, 1, 9, 9, 0),
TEST ("abcdefghij", 0, 0, 8, 8, 0),
TEST ("\0cb\0\0ge", 0, 5, 7, NPOS, 0),
TEST ("\0cb\0\0ge", 0, 5, 5, 5, 0),
TEST ("\0cb\0\0cb", 0, 3, 5, NPOS, 0),
TEST ("\0cb\0ge\0", 0, 6, 1, NPOS, 0),
TEST ("x@4096", 0, 0, 4096, NPOS, 0),
TEST ("x@4096", 0, 4096, 4096, NPOS, 0),
TEST ("x@4096", 0, 4095, 1, NPOS, 0),
TEST ("", "", 1, 0, NPOS, 0),
TEST ("abcdefghij", "abc", 10, 3, NPOS, 0),
TEST ("abcdefghij", "cba", 10, 1, NPOS, 0),
TEST ("", "cba", 0, -1, NPOS, 0),
TEST ("last test", "test", 0, 4, 0, 0)
};
/**************************************************************************/
// used to exercise
// find_first_not_of (const basic_string&, size_type)
static const StringTestCase
cstr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +---------------------------------- controlled sequence
// | +-------------------- sequence to be found
// | | +----- find_first_not_of() off argument
// | | | +- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "c", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "\0", 0, NPOS),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0\0", "\0", 0, NPOS),
TEST ("\0", "a", 0, 0),
TEST ("bbcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 0, 1),
TEST ("bcaaaaaaaa", "a", 2, NPOS),
TEST ("bcaaafaaaa", "a", 2, 5),
TEST ("abcdefghij", "j", 9, NPOS),
TEST ("cbbedfhjig", "cba", 0, 3),
TEST ("edfcbahjig", "cba", 4, 6),
TEST ("edfcbaaabc", "cba", 6, NPOS),
TEST ("edfcbahcba", "cba", 9, NPOS),
TEST ("cbacbabjig", "cbaig", 0, 7),
TEST ("bcaedfajih", "aabced", 0, 5),
TEST ("bcedfaacdh", "abcdef", 3, 9),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 0),
TEST ("\0cbe\0\0g", "b\0\0g", 4, NPOS),
TEST ("e\0cb\0\0g", "cbe", 0, 1),
TEST ("\0ge\0\0cb", "\0\0ge", 0, 5),
TEST ("\0cb\0\0ge", "cb\0", 6, 6),
TEST ("\0cb\0\0ce", "cb\0", 0, 6),
TEST ("e\0gbg\0\0", "bg", 2, 5),
TEST ("a\0c", "a\0gbg\0\0", 0, 2),
TEST ("a\0b", "a\0gbg\0\0", 0, NPOS),
TEST ("ab\0", "ab\0gg\0\0", 1, NPOS),
TEST ("a\0b", "e\0gg\0\0a", 3, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, NPOS),
TEST ("aaabaaaaaa", "aaaaaaaaaa", 4, NPOS),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 1, 5),
TEST ("aabaabaaaa", "aaaaaaaaaa", 0, 2),
TEST ("aabaabaaaa", "aaaaaaaaaa", 3, 5),
TEST ("aabaabaaaa", "aaaaaaaaab", 0, NPOS),
TEST ("cbb", "aaaaaaaaba", 2, NPOS),
TEST ("bac", "aaaaaaaaba", 0, 2),
TEST ("baa", "aaaaaaaaaa", 0, 0),
TEST ("x@4096", "", 0, 0),
TEST ("x@4096", "a", 0, 0),
TEST ("x@4096", "x", 0, NPOS),
TEST ("x@4096", "xxx", 10, NPOS),
TEST ("x@4096", "axa", 10, NPOS),
TEST ("abc", "x@4096", 2, 2),
TEST ("xxxxxxxxxx", "x@4096", 0, NPOS),
TEST ("x@4096", "xxx", 4094, NPOS),
TEST ("x@4096", "xxx", 4096, NPOS),
TEST ("x@2048axxx", "xxx", 10, 2048),
TEST ("abcdefghij", 0, 0, NPOS),
TEST ("abcdefghij", 0, 1, NPOS),
TEST ("\0cb\0\0ge", 0, 5, NPOS),
TEST ("x@4096", 0, 0, NPOS),
TEST ("x@4096", 0, 7, NPOS),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, NPOS),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 0, 0)
};
/**************************************************************************/
// used to exercise
// find_first_not_of (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res) \
{ __LINE__, -1, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +----------------------------- controlled sequence
// | +-------------- character to be found
// | | +------ expected result
// | | |
// | | |
// V V V
TEST ("ab", 'c', 0),
TEST ("", 'a', NPOS),
TEST ("", '\0', NPOS),
TEST ("\0", '\0', NPOS),
TEST ("\0\0", '\0', NPOS),
TEST ("\0", 'a', 0),
TEST ("a\0", 'a', 1),
TEST ("e\0cb\0\0g", '\0', 0),
TEST ("\0ecb\0\0g", '\0', 1),
TEST ("bbb\0cb\0e", 'b', 3),
TEST ("\0ecb\0\0g", 'a', 0),
TEST ("\0cbge\0\0", '\0', 1),
TEST ("x@4096", 'x', NPOS),
TEST ("x@4096", '\0', 0),
TEST ("x@4096", 'a', 0),
TEST ("last test", 't', 0)
};
/**************************************************************************/
// used to exercise
// find_first_not_of (value_type, size_type)
static const StringTestCase
val_size_test_cases [] = {
#undef TEST
#define TEST(str, val, off, res) \
{ __LINE__, off, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +------------------------------ controlled sequence
// | +--------------- character to be found
// | | +--------- find_first_not_of() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", 'c', 0, 0),
TEST ("", 'a', 0, NPOS),
TEST ("", '\0', 0, NPOS),
TEST ("\0", '\0', 1, NPOS),
TEST ("\0", 'a', 0, 0),
TEST ("\0\0", '\0', 1, NPOS),
TEST ("\0\0", 'a', 3, NPOS),
TEST ("\0\0", 'a', 1, 1),
TEST ("\0\0", '\0', 3, NPOS),
TEST ("e\0cb\0\0g", '\0', 1, 2),
TEST ("ecb\0\0\0g", '\0', 3, 6),
TEST ("e\0cbg\0\0", '\0', 5, NPOS),
TEST ("eb\0\0\0cg", 'b', 1, 2),
TEST ("e\0\0\0bbb", 'b', 4, NPOS),
TEST ("e\0cb\0\0g", 'a', 0, 0),
TEST ("\0cbge\0\0", '\0', 0, 1),
TEST ("\0\0\0cbge", '\0', 0, 3),
TEST ("\0cbge\0\0", '\0', 9, NPOS),
TEST ("x@4096", 'x', 0, NPOS),
TEST ("x@4096", 'x', 5, NPOS),
TEST ("x@4096", '\0', 0, 0),
TEST ("x@4096", 'a', 3, 3),
TEST ("x@4096", 'x', 4096, NPOS),
TEST ("x@4096", 'x', 4095, NPOS),
TEST ("x@2048axxx", 'x', 1, 2048),
TEST ("last test", 't', 0, 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_find_first_not_of (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object and the argument string
const String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 0;
if (1 == tcase.bthrow)
expected = exceptions [2];
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
std::size_t res = 0;
switch (func.which_) {
case FindFirstNotOf (cptr):
res = s_str.find_first_not_of (arg_ptr);
break;
case FindFirstNotOf (cstr):
res = s_str.find_first_not_of (arg_str);
break;
case FindFirstNotOf (cptr_size):
res = s_str.find_first_not_of (arg_ptr, tcase.off);
break;
case FindFirstNotOf (cptr_size_size):
res = s_str.find_first_not_of (arg_ptr, tcase.off, size);
break;
case FindFirstNotOf (cstr_size):
res = s_str.find_first_not_of (arg_str, tcase.off);
break;
case FindFirstNotOf (val):
res = s_str.find_first_not_of (arg_val);
break;
case FindFirstNotOf (val_size):
res = s_str.find_first_not_of (arg_val, tcase.off);
break;
default:
RW_ASSERT (!"logic error: unknown find_first_not_of overload");
return;
}
const std::size_t exp_res =
NPOS != tcase.nres ? tcase.nres : String::npos;
// verify the returned value
rw_assert (exp_res == res, 0, tcase.line,
"line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
"got %{?}%zu%{;}%{?}npos%{;}",
__LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres,
String::npos != res, res, String::npos == res);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_find_first_not_of);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
FindFirstNotOf (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cptr_size_size),
TEST (cstr_size),
TEST (val),
TEST (val_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.find.first.not.of",
test_find_first_not_of, tests, test_count);
}

View File

@@ -0,0 +1,792 @@
/***************************************************************************
*
* 21.string.find.first.of.cpp -
* string test exercising lib.string.find.first.of
*
* $Id: 21.string.find.first.of.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstdlib> // for free(), size_t
#include <stdexcept> // for length_error
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define FindFirstOf(sig) StringIds::find_first_of_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// find_first_of (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +---- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", NPOS),
TEST ("\0", "\0", NPOS),
TEST ("\0", "a", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", 3),
TEST ("ecdfcbahca", "cba", 1),
TEST ("bacbahjicg", "cba", 0),
TEST ("efhijhjieg", "cba", NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 3),
TEST ("e\0cb\0\0g", "cbe", 0),
TEST ("\0cb\0\0ge", "\0\0ge", NPOS),
TEST ("\0cb\0\0be", "b\0c", 2),
TEST ("e\0gbg\0\0", "bg", 2),
TEST ("e\0dg\0\0a", "cba", 6),
TEST ("a\0b", "e\0gbg\0\0", NPOS),
TEST ("a\0b", "eb\0gg\0\0", 2),
TEST ("a\0b", "e\0gg\0\0a", NPOS),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 2),
TEST ("bcedfaajih", "a", 5),
TEST ("bcaaedfaji", "a", 2),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0),
TEST ("aaaaabaaaa", "cccccccccb", 5),
TEST ("aabaabaaaa", "cccccccccb", 2),
TEST ("bbb", "aaaaaaaaba", 0),
TEST ("bbb", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", NPOS),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 0),
TEST ("x@4096", "axa", 0),
TEST ("abc", "x@4096", NPOS),
TEST ("axbc", "x@4096", 1),
TEST ("x@2048axxx", "y@4096a", 2048),
TEST ("abcdefghij", 0, 0),
TEST ("\0cb\0\0ge", 0, NPOS),
TEST ("x@4096", 0, 0),
TEST ("last test", "test", 2)
};
/**************************************************************************/
// used to exercise
// find_first_of (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------ controlled sequence
// | +---------------------- sequence to be found
// | | +----- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", NPOS),
TEST ("\0", "\0", 0),
TEST ("\0", "a", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", 3),
TEST ("ecdfcbahca", "cba", 1),
TEST ("bacbahjicg", "cba", 0),
TEST ("efhijhjieg", "cba", NPOS),
TEST ("e\0cb\0\0g", "ad", NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 1),
TEST ("e\0cb\0\0g", "cbe", 0),
TEST ("\0cb\0\0ge", "\0\0ge", 0),
TEST ("\0cb\0\0be", "b\0c", 0),
TEST ("\0cb\0\0be", "bc", 1),
TEST ("\0ab\0\0be", "bc", 2),
TEST ("e\0gbg\0\0", "bg", 2),
TEST ("e\0dg\0\0a", "cba", 6),
TEST ("a\0b", "e\0gbg\0\0", 1),
TEST ("a\0b", "eb\0gg\0\0", 1),
TEST ("a\0b", "e\0gg\0\0a", 0),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 2),
TEST ("bcedfaajih", "a", 5),
TEST ("bcaaedfaji", "a", 2),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0),
TEST ("aaaaabaaaa", "cccccccccb", 5),
TEST ("aabaabaaaa", "cccccccccb", 2),
TEST ("bbb", "aaaaaaaaba", 0),
TEST ("bbb", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", NPOS),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 0),
TEST ("x@4096", "axa", 0),
TEST ("abc", "x@4096", NPOS),
TEST ("axbc", "x@4096", 1),
TEST ("x@2048axxx", "y@4096a", 2048),
TEST ("abcdefghij", 0, 0),
TEST ("\0cb\0\0ge", 0, 0),
TEST ("x@4096", 0, 0),
TEST ("last test", "test", 2)
};
/**************************************************************************/
// used to exercise
// find_first_of (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------- controlled sequence
// | +------------------------ sequence to be found
// | | +-------- find_first_of() off argument
// | | | +-- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, NPOS),
TEST ("\0", "\0", 0, NPOS),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, NPOS),
TEST ("abcdefghij", "f", 2, 5),
TEST ("abcdefghij", "f", 7, NPOS),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 0, 3),
TEST ("edfcbahjig", "cba", 4, 4),
TEST ("edfcbahjig", "cba", 6, NPOS),
TEST ("edfcbahcba", "cba", 9, 9),
TEST ("cbacbahjig", "cba", 7, NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 4, NPOS),
TEST ("e\0cb\0\0g", "cbe", 0, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 0, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 6, NPOS),
TEST ("e\0gbg\0\0", "bg", 1, 2),
TEST ("e\0dg\0\0a", "cba", 0, 6),
TEST ("a\0b", "e\0gbg\0\0", 0, NPOS),
TEST ("a\0b", "eb\0gg\0\0", 1, 2),
TEST ("a\0b", "e\0gg\0\0a", 3, NPOS),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 1, 2),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 5, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 4, 4),
TEST ("aaaaabaaaa", "cccccccccb", 1, 5),
TEST ("aabaabaaaa", "cccccccccb", 0, 2),
TEST ("aabaabaaaa", "cccccccccb", 6, NPOS),
TEST ("bbb", "aaaaaaaaba", 2, 2),
TEST ("bab", "aaaaaaaaba", 0, 0),
TEST ("bbb", "aaaaaaaaaa", 0, NPOS),
TEST ("x@4096", "", 0, NPOS),
TEST ("x@4096", "a", 0, NPOS),
TEST ("x@4096", "x", 0, 0),
TEST ("x@4096", "xxx", 10, 10),
TEST ("x@4096", "axa", 10, 10),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 0, 0),
TEST ("x@2048axxx", "y@4096a", 10, 2048),
TEST ("x@4096", "xxx", 4093, 4093),
TEST ("x@4096", "xxx", 4096, NPOS),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 1, 1),
TEST ("\0cb\0\0ge", 0, 5, NPOS),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 7, 7),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, NPOS),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 0, 2)
};
/**************************************************************************/
// used to exercise
// find_first_of (const value_type*, size_type, size_type)
static const StringTestCase
cptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, size, res, bthrow) \
{ __LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, bthrow \
}
// +-------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +--------- find_first_of() off argument
// | | | +----- find_first_of() n argument
// | | | | +- expected result
// | | | | | exception info
// | | | | | | 0 - no exception
// | | | | | | 1 - length_error
// | | | | | |
// | | | | | +-----+
// V V V V V V
TEST ("ab", "a", 0, 1, 0, 0),
TEST ("", "", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 1, NPOS, 0),
TEST ("", "a", 0, 0, NPOS, 0),
TEST ("", "a", 0, 1, NPOS, 0),
TEST ("\0", "", 0, 0, NPOS, 0),
TEST ("\0", "\0", 0, 1, 0, 0),
TEST ("\0", "\0", 1, 1, NPOS, 0),
TEST ("\0\0", "\0\0", 1, 1, 1, 0),
TEST ("\0", "a", 0, 1, NPOS, 0),
TEST ("edfcbbhjig", "cba", 0, 3, 3, 0),
TEST ("edfcbbhjig", "bac", 0, 2, 4, 0),
TEST ("edfcbahjig", "cba", 7, 3, NPOS, 0),
TEST ("ebcfeahjig", "cba", 3, 2, NPOS, 0),
TEST ("ebcfeahjig", "cab", 3, 2, 5, 0),
TEST ("edfcbahcba", "bac", 6, 3, 7, 0),
TEST ("edfcbehcba", "abc", 1, 2, 4, 0),
TEST ("edfcbahcba", "cba", 5, 1, 7, 0),
TEST ("cbacbahjig", "cba", 6, 3, NPOS, 0),
TEST ("cbacbahjcg", "cba", 5, 1, 8, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 4, 1, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 4, 4, 0),
TEST ("e\0cb\0\0b", "b\0\0g", 4, 1, 6, 0),
TEST ("\0b\0\0gb\0","bg\0", 2, 2, 4, 0),
TEST ("\0b\0\0gb\0","bg\0", 0, 2, 1, 0),
TEST ("\0b\0\0gb\0","bg\0", 0, 3, 0, 0),
TEST ("e\0cb\0\0g", "afe", 0, 2, NPOS, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 7, 4, NPOS, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 0, NPOS, 0),
TEST ("a\0b", "e\0gbg\0\0", 0, 1, NPOS, 0),
TEST ("a\0b", "eb\0gg\0\0", 1, 2, 2, 0),
TEST ("a\0b", "e\0gg\0\0a", 3, 6, NPOS, 0),
TEST ("a\0b", "e\0gg\0\0a", 0, 7, 0, 0),
TEST ("a\0b", "e\0gg\0\0a", 0, 4, 1, 0),
TEST ("e\0a\0", "e\0a\0\0", 0, 4, 0, 0),
TEST ("e\0a\0", "b\0c\0\0", 0, 5, 1, 0),
TEST ("ee\0a\0", "b\0c\0\0", 1, 4, 2, 0),
TEST ("be\0a\0", "fdbcb\0a", 1, 5, NPOS, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 10, 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, 10, 1, 0),
TEST ("aaaaabaaaa", "cccccccccc", 0, 10, NPOS, 0),
TEST ("aaaaabaaaa", "cccbcccccc", 1, 4, 5, 0),
TEST ("aaaabaaaaa", "cccca", 0, 5, 0, 0),
TEST ("aabaabaaaa", "cbccccccca", 0, 5, 2, 0),
TEST ("bbb", "aaaaaaaaba", 2, 2, NPOS, 0),
TEST ("bbb", "aaaaaaaaaa", 0, 9, NPOS, 0),
TEST ("bab", "aaaaaaaaba", 0, 0, NPOS, 0),
TEST ("bab", "ccccccccba", 1, 10, 1, 0),
TEST ("x@4096", "", 0, 0, NPOS, 0),
TEST ("x@4096", "a", 0, 1, NPOS, 0),
TEST ("x@4096", "x", 0, 1, 0, 0),
TEST ("x@4096", "xxx", 10, 3, 10, 0),
TEST ("x@4096", "axx", 10, 1, NPOS, 0),
TEST ("x@4096", "xxa", 10, 0, NPOS, 0),
TEST ("abc", "x@4096", 2, 10, NPOS, 0),
TEST ("xxxxxxxxxx", "x@4096", 0, 4096, 0, 0),
TEST ("xxxxxxxxxx", "x@4096", 2, 4, 2, 0),
TEST ("x@2048axyx", "y@4096a", 10, 4097, 2048, 0),
TEST ("x@4096", "xxx", 4093, 3, 4093, 0),
TEST ("x@4096", "xxx", 4094, 0, NPOS, 0),
TEST ("x@4096", "xxx", 4095, 1, 4095, 0),
TEST ("abcdefghij", 0, 0, 9, 0, 0),
TEST ("abcdefghij", 0, 1, 9, 1, 0),
TEST ("\0cb\0\0ge", 0, 5, 7, 5, 0),
TEST ("\0cb\0\0ge", 0, 5, 5, NPOS, 0),
TEST ("\0cb\0ge\0", 0, 6, 1, 6, 0),
TEST ("x@4096", 0, 0, 4096, 0, 0),
TEST ("x@4096", 0, 4096, 4096, NPOS, 0),
TEST ("x@4096", 0, 4095, 1, 4095, 0),
TEST ("", "", 1, 0, NPOS, 0),
TEST ("abcdefghij", "abc", 10, 3, NPOS, 0),
TEST ("abcdefghij", "cba", 10, 1, NPOS, 0),
TEST ("", "cba", 0, -1, NPOS, 0),
TEST ("abcdefghij", "cba", 0, -1, 0, 0),
TEST ("x@4096", "xxx", 0, -1, 0, 0),
TEST ("abcdefghij", "ax@4096", 0, -1, 0, 0),
TEST ("last test", "test", 0, 4, 2, 0)
};
/**************************************************************************/
// used to exercise
// find_first_of (const basic_string&, size_type)
static const StringTestCase
cstr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +-------------------------------------- controlled sequence
// | +------------------------ sequence to be found
// | | +--------- find_first_of() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, NPOS),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, NPOS),
TEST ("abcdefghij", "f", 2, 5),
TEST ("abcdefghij", "f", 7, NPOS),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 0, 3),
TEST ("edfcbahjig", "cba", 4, 4),
TEST ("edfcbahjig", "cba", 6, NPOS),
TEST ("edfcbahcba", "cba", 9, 9),
TEST ("cbacbahjig", "cba", 7, NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 1),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 4),
TEST ("e\0cb\0\0g", "cbe", 0, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 0, 0),
TEST ("\0cb\0\0ge", "cb\0", 6, NPOS),
TEST ("e\0gbg\0\0", "bg", 1, 2),
TEST ("e\0gbg\0\0", "\0bg", 5, 5),
TEST ("e\0dg\0\0a", "cba", 0, 6),
TEST ("a\0b", "e\0gbg\0\0", 0, 1),
TEST ("a\0b", "eb\0gg\0\0", 1, 1),
TEST ("a\0b", "e\0gg\0\0b", 2, 2),
TEST ("a\0b", "e\0gg\0\0a", 3, NPOS),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 1, 2),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 5, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 4, 4),
TEST ("aaaaabaaaa", "cccccccccb", 1, 5),
TEST ("aabaabaaaa", "cccccccccb", 0, 2),
TEST ("aabaabaaaa", "cccccccccb", 6, NPOS),
TEST ("bbb", "aaaaaaaaba", 2, 2),
TEST ("bab", "aaaaaaaaba", 0, 0),
TEST ("bbb", "aaaaaaaaaa", 0, NPOS),
TEST ("x@4096", "", 0, NPOS),
TEST ("x@4096", "a", 0, NPOS),
TEST ("x@4096", "x", 0, 0),
TEST ("x@4096", "xxx", 10, 10),
TEST ("x@4096", "axa", 10, 10),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 0, 0),
TEST ("x@2048axxx", "y@4096a", 10, 2048),
TEST ("x@4096", "xxx", 4093, 4093),
TEST ("x@4096", "xxx", 4096, NPOS),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 1, 1),
TEST ("\0cb\0\0ge", 0, 5, 5),
TEST ("\0cb\0\0ge", 0, 4, 4),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 7, 7),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, NPOS),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 0, 2)
};
/**************************************************************************/
// used to exercise
// find_first_of (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res) \
{ __LINE__, -1, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +----------------------------- controlled sequence
// | +-------------- character to be found
// | | +------ expected result
// | | |
// | | |
// V V V
TEST ("ab", 'a', 0),
TEST ("", 'a', NPOS),
TEST ("", '\0', NPOS),
TEST ("\0", '\0', 0),
TEST ("\0\0", '\0', 0),
TEST ("\0", 'a', NPOS),
TEST ("e\0cb\0\0g", '\0', 1),
TEST ("e\0cb\0\0g", 'b', 3),
TEST ("e\0cb\0\0g", 'a', NPOS),
TEST ("\0cbge\0\0", '\0', 0),
TEST ("\0cbge\0\0", 'b', 2),
TEST ("\0cbge\0\0", 'a', NPOS),
TEST ("x@4096", 'x', 0),
TEST ("x@4096", '\0', NPOS),
TEST ("x@4096", 'a', NPOS),
TEST ("x@2048axxx", 'a', 2048),
TEST ("last test", 't', 3)
};
/**************************************************************************/
// used to exercise
// find_first_of (value_type, size_type)
static const StringTestCase
val_size_test_cases [] = {
#undef TEST
#define TEST(str, val, off, res) \
{ __LINE__, off, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +------------------------------ controlled sequence
// | +--------------- character to be found
// | | +--------- find_first_of() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", 'a', 0, 0),
TEST ("", 'a', 0, NPOS),
TEST ("", '\0', 0, NPOS),
TEST ("\0", '\0', 1, NPOS),
TEST ("\0", 'a', 0, NPOS),
TEST ("\0\0", '\0', 1, 1),
TEST ("\0\0", 'a', 3, NPOS),
TEST ("\0\0", '\0', 3, NPOS),
TEST ("e\0cb\0\0g", '\0', 1, 1),
TEST ("e\0cb\0\0g", '\0', 2, 4),
TEST ("e\0cb\0\0g", '\0', 6, NPOS),
TEST ("e\0cb\0\0g", 'b', 1, 3),
TEST ("e\0cb\0\0g", 'b', 4, NPOS),
TEST ("e\0cb\0\0g", 'a', 0, NPOS),
TEST ("\0cbge\0\0", '\0', 0, 0),
TEST ("\0cbge\0\0", '\0', 1, 5),
TEST ("\0cbge\0\0", '\0', 9, NPOS),
TEST ("\0cbge\0\0", 'b', 0, 2),
TEST ("\0bgeb\0\0", 'b', 2, 4),
TEST ("\0cbge\0\0", 'a', 1, NPOS),
TEST ("x@4096", 'x', 0, 0),
TEST ("x@4096", 'x', 5, 5),
TEST ("x@4096", '\0', 0, NPOS),
TEST ("x@4096", 'a', 3, NPOS),
TEST ("x@4096", 'x', 4096, NPOS),
TEST ("x@4096", 'x', 4095, 4095),
TEST ("x@2048axxx", 'a', 10, 2048),
TEST ("last test", 't', 0, 3)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_find_first_of (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object and the argument string
const String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 0;
if (1 == tcase.bthrow)
expected = exceptions [2];
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
std::size_t res = 0;
switch (func.which_) {
case FindFirstOf (cptr):
res = s_str.find_first_of (arg_ptr);
break;
case FindFirstOf (cstr):
res = s_str.find_first_of (arg_str);
break;
case FindFirstOf (cptr_size):
res = s_str.find_first_of (arg_ptr, tcase.off);
break;
case FindFirstOf (cptr_size_size):
res = s_str.find_first_of (arg_ptr, tcase.off, size);
break;
case FindFirstOf (cstr_size):
res = s_str.find_first_of (arg_str, tcase.off);
break;
case FindFirstOf (val):
res = s_str.find_first_of (arg_val);
break;
case FindFirstOf (val_size):
res = s_str.find_first_of (arg_val, tcase.off);
break;
default:
RW_ASSERT ("test logic error: unknown find_first_of overload");
return;
}
const std::size_t exp_res =
NPOS != tcase.nres ? tcase.nres : String::npos;
// verify the returned value
rw_assert (exp_res == res, 0, tcase.line,
"line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
"got %{?}%zu%{;}%{?}npos%{;}",
__LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres,
String::npos != res, res, String::npos == res);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_find_first_of);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
FindFirstOf (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cptr_size_size),
TEST (cstr_size),
TEST (val),
TEST (val_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.find.first.of",
test_find_first_of, tests, test_count);
}

View File

@@ -0,0 +1,791 @@
/***************************************************************************
*
* 21.string.find.last.not.of.cpp -
* string test exercising lib.string.find.last.not.of
*
* $Id: 21.string.find.last.not.of.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstdlib> // for free(), size_t
#include <stdexcept> // for length_error
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define FindLastNotOf(sig) StringIds::find_last_not_of_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// find_last_not_of (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +---- expected result
// | | |
// | | |
// V V V
TEST ("ab", "c", 1),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", 0),
TEST ("\0", "\0", 0),
TEST ("\0", "a", 0),
TEST ("bbcdefghij", "a", 9),
TEST ("bcdefghija", "a", 8),
TEST ("abcdedaaaa", "a", 5),
TEST ("aabaaacaaa", "a", 6),
TEST ("edfcbbhjig", "cba", 9),
TEST ("edfcbaacba", "bca", 2),
TEST ("edhcbahcba", "cba", 6),
TEST ("cbacbbcbac", "cab", NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 6),
TEST ("e\0cb\0\0g", "ecbg", 5),
TEST ("\0cb\0\0ge", "\0\0ge", 6),
TEST ("ge\0\0\0cb", "bc\0", 4),
TEST ("e\0cdg\0\0", "abc", 6),
TEST ("a\0b", "e\0gbg\0\0", 2),
TEST ("a\0b", "ab\0gg\0\0", 1),
TEST ("\0ab", "b\0gg\0\0a", 1),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaaabaaaa", "ccccccccca", 5),
TEST ("aabaabaaaa", "ccccccccca", 5),
TEST ("bbb", "aaaaaaaaba", NPOS),
TEST ("bbb", "aaaaaaaaaa", 2),
TEST ("abcdefghij", "jihgfedcba", NPOS),
TEST ("x@4096", "", 4095),
TEST ("x@4096", "a", 4095),
TEST ("x@4096", "x", NPOS),
TEST ("x@4096", "xxx", NPOS),
TEST ("x@4096", "aax", NPOS),
TEST ("abc", "x@4096", 2),
TEST ("xxxxxxxxxx", "x@4096", NPOS),
TEST ("xxax@2048", "x@4096", 2),
TEST ("abcdefghij", 0, NPOS),
TEST ("\0cb\0\0ge", 0, 6),
TEST ("x@4096", 0, NPOS),
TEST ("last test", "test", 4)
};
/**************************************************************************/
// used to exercise
// find_last_not_of (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------ controlled sequence
// | +---------------------- sequence to be found
// | | +----- expected result
// | | |
// | | |
// V V V
TEST ("ab", "c", 1),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", 0),
TEST ("\0", "\0", NPOS),
TEST ("\0\0", "\0", NPOS),
TEST ("\0", "a", 0),
TEST ("a", "\0", 0),
TEST ("bbcdefghij", "a", 9),
TEST ("bcdefghija", "a", 8),
TEST ("abcdedaaaa", "a", 5),
TEST ("aabaaacaaa", "a", 6),
TEST ("edfcbbhjig", "cba", 9),
TEST ("edfcbaacba", "bca", 2),
TEST ("edhcbahcba", "cba", 6),
TEST ("cbacbbcbac", "cab", NPOS),
TEST ("e\0bb\0\0g", "b\0\0g", 0),
TEST ("e\0cb\0\0g", "ecbg", 5),
TEST ("\0cb\0\0ge", "\0\0ge", 2),
TEST ("be\0\0\0cb", "bc\0", 1),
TEST ("e\0cdg\0\0", "abc", 6),
TEST ("a\0b", "e\0gbg\0\0", 0),
TEST ("a\0b", "ab\0gg\0\0", NPOS),
TEST ("\0ab", "abcdefghij", 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaaabaaaa", "ccccccccca", 5),
TEST ("aabaabaaaa", "ccccccccca", 5),
TEST ("bbb", "aaaaaaaaba", NPOS),
TEST ("bbb", "aaaaaaaaaa", 2),
TEST ("abcdefghij", "jihgfedcba", NPOS),
TEST ("x@4096", "", 4095),
TEST ("x@4096", "a", 4095),
TEST ("x@4096", "x", NPOS),
TEST ("x@4096", "xxx", NPOS),
TEST ("x@4096", "aax", NPOS),
TEST ("abc", "x@4096", 2),
TEST ("xxxxxxxxxx", "x@4096", NPOS),
TEST ("xxax@2048", "x@4096", 2),
TEST ("abcdefghij", 0, NPOS),
TEST ("\0cb\0\0ge", 0, NPOS),
TEST ("x@4096", 0, NPOS),
TEST ("last test", "test", 4)
};
/**************************************************************************/
// used to exercise
// find_last_not_of (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +---------------------- sequence to be found
// | | +------ find_last_not_of() off argument
// | | | +-- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "c", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "", 1, 0),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, 0),
TEST ("\0", "a", 0, 0),
TEST ("bbcdefghij", "a", 9, 9),
TEST ("bcdefghija", "a", 9, 8),
TEST ("bbcdefghij", "a", 0, 0),
TEST ("bcadefghij", "a", 2, 1),
TEST ("aaadefghij", "a", 2, NPOS),
TEST ("abcdeaaaij", "a", 7, 4),
TEST ("edfcbbhjig", "cba", 9, 9),
TEST ("edfcbacbag", "cba", 7, 2),
TEST ("ebccbahjig", "cba", 4, 0),
TEST ("edfcbahcba", "cba", 9, 6),
TEST ("cbacbahcba", "cba", 5, NPOS),
TEST ("edfcbahcba", "cba", 3, 2),
TEST ("cbahbahabc", "cba", 9, 6),
TEST ("e\0cb\0\0g", "b\0\0g", 5, 5),
TEST ("b\0bc\0\0g", "b\0\0g", 2, 1),
TEST ("e\0cb\0\0g", "ecb", 7, 6),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 6),
TEST ("b\0\0\0gec", "cb\0", 0, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 1, 0),
TEST ("\0cb\0\0ge", "cb\0", 2, 0),
TEST ("e\0cbg\0\0", "bg", 4, 2),
TEST ("e\0\0\0bbg", "bg", 5, 3),
TEST ("a\0b", "b\0gbg\0\0", 3, 1),
TEST ("\0ba", "ab\0gg\0\0", 3, 0),
TEST ("ab\0", "ba\0d\0\0a", 1, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 4, NPOS),
TEST ("aaaaabaaaa", "ccccccccca", 8, 5),
TEST ("aabaabaaaa", "ccccccccca", 9, 5),
TEST ("aabaabaaaa", "ccccccccca", 3, 2),
TEST ("bbb", "aaaaaaaaba", 2, NPOS),
TEST ("cab", "aaaaaaaaba", 0, 0),
TEST ("bbb", "aaaaaaaaaa", 3, 2),
TEST ("x@4096", "", 4096, 4095),
TEST ("x@4096", "a", 4096, 4095),
TEST ("x@4096", "x", 4096, NPOS),
TEST ("x@4096", "xxx", 4095, NPOS),
TEST ("x@4096", "xxx", 0, NPOS),
TEST ("x@4096", "xxx", 4087, NPOS),
TEST ("x@4096", "aax", 4087, NPOS),
TEST ("abc", "x@4096", 2, 2),
TEST ("xxxxxxxxxx", "x@4096", 6, NPOS),
TEST ("xxxxaxxxxx", "x@4096", 9, 4),
TEST ("x@4096", "xxx", 3, NPOS),
TEST ("x@4096", "xxx", 2, NPOS),
TEST ("xxax@2048", "x@4096", 2052, 2),
TEST ("abcdefghij", 0, 0, NPOS),
TEST ("abcdefghij", 0, 9, NPOS),
TEST ("\0cb\0\0ge", 0, 5, 5),
TEST ("x@4096", 0, 0, NPOS),
TEST ("x@4096", 0, 1, NPOS),
TEST ("", "", 1, NPOS),
TEST ("defghijabc", "abc", 15, 6),
TEST ("defgabcabc", "cba", 15, 3),
TEST ("last test", "test", 9, 4)
};
/**************************************************************************/
// used to exercise
// find_last_not_of (const value_type*, size_type, size_type)
static const StringTestCase
cptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, size, res, bthrow) \
{ __LINE__, off, size, int (NPOS), -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, bthrow \
}
// +----------------------------------- controlled sequence
// | +---------------------- sequence to be found
// | | +------ find_last_not_of() off argument
// | | | +-- find_last_not_of() n argument
// | | | | +-- expected result
// | | | | | exception info
// | | | | | | 0 - no exception
// | | | | | | 1 - length_error
// | | | | | |
// | | | | | +----+
// V V V V V V
TEST ("ab", "c", 0, 1, 0, 0),
TEST ("", "", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 1, NPOS, 0),
TEST ("", "a", 0, 0, NPOS, 0),
TEST ("", "a", 0, 1, NPOS, 0),
TEST ("\0", "", 0, 0, 0, 0),
TEST ("\0", "\0", 0, 1, NPOS, 0),
TEST ("\0", "\0", 1, 1, NPOS, 0),
TEST ("\0\0", "\0\0", 1, 1, NPOS, 0),
TEST ("\0", "a", 0, 1, 0, 0),
TEST ("a", "\0", 0, 1, 0, 0),
TEST ("adfcbbhjig", "cba", 0, 3, NPOS, 0),
TEST ("bdfcbbhjig", "cba", 0, 2, NPOS, 0),
TEST ("edfhjabcbb", "cba", 9, 2, 5, 0),
TEST ("edacbdcbag", "cba", 8, 3, 5, 0),
TEST ("edfcbaabcg", "cba", 8, 3, 2, 0),
TEST ("cccfehjigb", "cba", 2, 1, NPOS, 0),
TEST ("edfcbahcba", "cba", 9, 3, 6, 0),
TEST ("edfcbehcba", "cab", 9, 2, 8, 0),
TEST ("edfcbacbah", "cba", 9, 3, 9, 0),
TEST ("cbacbahjig", "cba", 5, 3, NPOS, 0),
TEST ("accacbahji", "cba", 2, 1, 0, 0),
TEST ("cbacbaccdg", "cba", 7, 1, 5, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 6, 4, 2, 0),
TEST ("eg\0b\0\0g", "b\0\0g", 7, 4, 0, 0),
TEST ("e\0cb\0\0b", "b\0\0g", 4, 1, 4, 0),
TEST ("g\0b\0\0b\0","b\0\0g", 7, 2, 0, 0),
TEST ("\0bg\0\0b\0","b\0\0g", 2, 2, 2, 0),
TEST ("\0b\0\0b\0g","b\0g\0", 7, 3, NPOS, 0),
TEST ("e\0cbg\0\0", "ecb", 7, 2, 6, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 4, 2, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 2, 0, 2, 0),
TEST ("\0cb\0\0ge", "cb\0", 4, 3, NPOS, 0),
TEST ("e\0bcg\0\0", "bg", 1, 2, 1, 0),
TEST ("e\0bcg\0\0", "bg", 6, 2, 6, 0),
TEST ("a\0b", "a\0gbg\0\0", 2, 1, 2, 0),
TEST ("\0ba", "ab\0gg\0\0", 1, 2, 0, 0),
TEST ("ba\0", "e\0gg\0\0a", 3, 7, 0, 0),
TEST ("a\0b", "e\0gg\0\0a", 0, 7, NPOS, 0),
TEST ("a\0b", "eb\0gg\0\0", 1, 3, 0, 0),
TEST ("e\0a\0", "e\0a\0\0", 2, 4, NPOS, 0),
TEST ("e\0a\0", "e\0a\0\0", 3, 5, NPOS, 0),
TEST ("ee\0a\0", "b\0c\0\0", 3, 4, 3, 0),
TEST ("e\0\0cb", "fdbcb\0a", 3, 5, 2, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, 10, NPOS, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 8, 10, NPOS, 0),
TEST ("aaaaabaaaa", "ccccccccca", 9, 10, 5, 0),
TEST ("aabaabaaab", "cccacccccc", 8, 4, 5, 0),
TEST ("aaaabaaaab", "cccca", 9, 5, 9, 0),
TEST ("aabaabaaaa", "cacccccccb", 7, 5, 5, 0),
TEST ("bbb", "aaaaaaaaba", 1, 2, 1, 0),
TEST ("bbb", "aaaaaaaaab", 1, 9, 1, 0),
TEST ("bab", "aaaaaaaaba", 0, 0, 0, 0),
TEST ("bab", "ccccccccba", 1, 10, NPOS, 0),
TEST ("abcdefghij", "jihgfedcba", 9, 10, NPOS, 0),
TEST ("abcdefghij", "jihgfedcba", 9, 9, 0, 0),
TEST ("x@4096", "", 4096, 0, 4095, 0),
TEST ("x@4096", "a", 4096, 1, 4095, 0),
TEST ("x@4096", "x", 4096, 1, NPOS, 0),
TEST ("x@4096", "xxx", 4088, 3, NPOS, 0),
TEST ("x@4096", "aax", 4088, 2, 4088, 0),
TEST ("abc", "x@4096", 2, 10, 2, 0),
TEST ("xxxxxxxxxx", "x@4096", 9, 4096, NPOS, 0),
TEST ("xxxxxxxxxx", "x@4096", 2, 4, NPOS, 0),
TEST ("x@4096", "xxx", 4093, 3, NPOS, 0),
TEST ("x@4096", "xxx", 4094, 0, 4094, 0),
TEST ("xxax@2048", "x@4096a", 2052, 4096, 2, 0),
TEST ("abcdefghij", 0, 9, 10, NPOS, 0),
TEST ("abcdefghij", 0, 8, 6, 8, 0),
TEST ("\0cb\0\0ge", 0, 5, 7, NPOS, 0),
TEST ("\0cb\0ge\0", 0, 6, 1, 5, 0),
TEST ("\0c\0eg\0c", 0, 6, 2, 4, 0),
TEST ("x@4096", 0, 0, 4096, NPOS, 0),
TEST ("x@4096", 0, 1, 4096, NPOS, 0),
TEST ("x@4096", 0, 4091, 0, 4091, 0),
TEST ("", "", 1, 0, NPOS, 0),
TEST ("defghijabc", "abc", 15, 3, 6, 0),
TEST ("defghijabc", "cba", 15, 1, 8, 0),
TEST ("", "cba", 0, -1, NPOS, 0),
TEST ("last test", "test", 9, 4, 4, 0)
};
/**************************************************************************/
// used to exercise
// find_last_not_of (const basic_string&, size_type)
static const StringTestCase
cstr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +------ find_last_not_of() off argument
// | | | +-- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "c", 1, 1),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "", 1, 0),
TEST ("\0", "\0", 0, NPOS),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0\0", "\0", 1, NPOS),
TEST ("\0", "a", 0, 0),
TEST ("a", "\0", 1, 0),
TEST ("bbcdefghij", "a", 9, 9),
TEST ("bcdefghija", "a", 9, 8),
TEST ("bbcdefghij", "a", 0, 0),
TEST ("bcadefghij", "a", 2, 1),
TEST ("aaadefghij", "a", 2, NPOS),
TEST ("abcdeaaaij", "a", 7, 4),
TEST ("edfcbbhjig", "cba", 9, 9),
TEST ("edfcbacbag", "cba", 7, 2),
TEST ("ebccbahjig", "cba", 4, 0),
TEST ("edfcbahcba", "cba", 9, 6),
TEST ("cbacbahcba", "cba", 5, NPOS),
TEST ("edfcbahcba", "cba", 3, 2),
TEST ("cbahbahabc", "cba", 9, 6),
TEST ("e\0cb\0\0g", "b\0\0g", 5, 2),
TEST ("c\0bg\0\0g", "b\0\0g", 2, 0),
TEST ("e\0cb\0\0g", "ecb", 7, 6),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 2),
TEST ("b\0\0\0gec", "cb\0", 2, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 1, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 6, 6),
TEST ("e\0cbg\0\0", "bg", 4, 2),
TEST ("e\0\0\0bbg", "bg", 5, 3),
TEST ("a\0b", "b\0gbg\0\0", 3, 0),
TEST ("\0ba", "ab\0gg\0\0", 3, NPOS),
TEST ("ab\0", "ba\0d\0\0a", 2, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 4, NPOS),
TEST ("aaaaabaaaa", "ccccccccca", 8, 5),
TEST ("aabaabaaaa", "ccccccccca", 9, 5),
TEST ("aabaabaaaa", "ccccccccca", 3, 2),
TEST ("bbb", "aaaaaaaaba", 2, NPOS),
TEST ("cab", "aaaaaaaaba", 0, 0),
TEST ("bbb", "aaaaaaaaaa", 3, 2),
TEST ("x@4096", "", 4096, 4095),
TEST ("x@4096", "a", 4096, 4095),
TEST ("x@4096", "x", 4096, NPOS),
TEST ("x@4096", "xxx", 4095, NPOS),
TEST ("x@4096", "xxx", 0, NPOS),
TEST ("x@4096", "xxx", 4087, NPOS),
TEST ("x@4096", "aax", 4087, NPOS),
TEST ("abc", "x@4096", 2, 2),
TEST ("xxxxxxxxxx", "x@4096", 6, NPOS),
TEST ("xxxxaxxxxx", "x@4096", 9, 4),
TEST ("xxax@2048", "x@4096", 2050, 2),
TEST ("x@4096", "xxx", 3, NPOS),
TEST ("x@4096", "xxx", 2, NPOS),
TEST ("abcdefghij", 0, 0, NPOS),
TEST ("abcdefghij", 0, 9, NPOS),
TEST ("\0cb\0\0ge", 0, 5, NPOS),
TEST ("x@4096", 0, 0, NPOS),
TEST ("x@4096", 0, 1, NPOS),
TEST ("", "", 1, NPOS),
TEST ("defghijabc", "abc", 15, 6),
TEST ("defgabcabc", "cba", 15, 3),
TEST ("last test", "test", 9, 4)
};
/**************************************************************************/
// used to exercise
// find_last_not_of (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res) \
{ __LINE__, -1, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +----------------------------- controlled sequence
// | +-------------- character to be found
// | | +------ expected result
// | | |
// | | |
// V V V
TEST ("ab", 'c', 1),
TEST ("", 'a', NPOS),
TEST ("", '\0', NPOS),
TEST ("\0", '\0', NPOS),
TEST ("\0\0", '\0', NPOS),
TEST ("\0", 'a', 0),
TEST ("a\0", '\0', 0),
TEST ("e\0cbg\0\0", '\0', 4),
TEST ("e\0cgg\0\0", '\0', 4),
TEST ("e\0cb\0\0b", 'b', 5),
TEST ("\0cbge\0\0", '\0', 4),
TEST ("\0cbgb\0\0", 'b', 6),
TEST ("aaaaaaaaaa", 'a', NPOS),
TEST ("\0aaaaaaaa", 'a', 0),
TEST ("x@4096", 'x', NPOS),
TEST ("x@4096", '\0', 4095),
TEST ("x@4096", 'a', 4095),
TEST ("xxax@2048", 'x', 2),
TEST ("last test", 't', 7)
};
/**************************************************************************/
// used to exercise
// find_last_not_of (value_type, size_type)
static const StringTestCase
val_size_test_cases [] = {
#undef TEST
#define TEST(str, val, off, res) \
{ __LINE__, off, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +------------------------------ controlled sequence
// | +--------------- character to be found
// | | +--------- find_last_not_of() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", 'c', 1, 1),
TEST ("", 'a', 0, NPOS),
TEST ("", '\0', 0, NPOS),
TEST ("\0", '\0', 1, NPOS),
TEST ("\0", 'a', 0, 0),
TEST ("\0\0", '\0', 2, NPOS),
TEST ("\0\0", 'a', 3, 1),
TEST ("\0\0", '\0', 3, NPOS),
TEST ("e\0cb\0\0g", '\0', 1, 0),
TEST ("e\0cb\0\0g", '\0', 5, 3),
TEST ("\0ecb\0\0g", '\0', 0, NPOS),
TEST ("e\0cb\0\0b", 'b', 7, 5),
TEST ("e\0cb\0\0g", 'b', 4, 4),
TEST ("e\0cbg\0\0", 'a', 6, 6),
TEST ("\0cbee\0\0", '\0', 0, NPOS),
TEST ("\0cbee\0\0", '\0', 6, 4),
TEST ("\0cb\0\0\0", '\0', 9, 2),
TEST ("aaaaaaaaaa", 'a', 6, NPOS),
TEST ("\0aaaaaaaa", 'a', 6, 0),
TEST ("x@4096", 'x', 0, NPOS),
TEST ("x@4096", 'x', 4096, NPOS),
TEST ("x@4096", '\0', 4096, 4095),
TEST ("x@4096", 'a', 4094, 4094),
TEST ("x@4096", 'x', 4106, NPOS),
TEST ("xxax@2048", 'x', 2050, 2),
TEST ("last test", 't', 9, 7)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_find_last_not_of (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object and the argument string
const String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 0;
if (1 == tcase.bthrow)
expected = exceptions [2];
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
std::size_t res = 0;
switch (func.which_) {
case FindLastNotOf (cptr):
res = s_str.find_last_not_of (arg_ptr);
break;
case FindLastNotOf (cstr):
res = s_str.find_last_not_of (arg_str);
break;
case FindLastNotOf (cptr_size):
res = s_str.find_last_not_of (arg_ptr, tcase.off);
break;
case FindLastNotOf (cptr_size_size):
res = s_str.find_last_not_of (arg_ptr, tcase.off, size);
break;
case FindLastNotOf (cstr_size):
res = s_str.find_last_not_of (arg_str, tcase.off);
break;
case FindLastNotOf (val):
res = s_str.find_last_not_of (arg_val);
break;
case FindLastNotOf (val_size):
res = s_str.find_last_not_of (arg_val, tcase.off);
break;
default:
RW_ASSERT ("test logic error: unknown find_last_not_of overload");
return;
}
const std::size_t exp_res =
NPOS != tcase.nres ? tcase.nres : String::npos;
// verify the returned value
rw_assert (exp_res == res, 0, tcase.line,
"line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
"got %{?}%zu%{;}%{?}npos%{;}",
__LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres,
String::npos != res, res, String::npos == res);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_find_last_not_of);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
FindLastNotOf (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cptr_size_size),
TEST (cstr_size),
TEST (val),
TEST (val_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.find.last.not.of",
test_find_last_not_of, tests, test_count);
}

View File

@@ -0,0 +1,824 @@
/***************************************************************************
*
* 21.string.find.last.of.cpp - test exercising lib.string.find.last.of
*
* $Id: 21.string.find.last.of.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for size_t
#include <stdexcept> // for length_error
#include <21.strings.h> // for StringIds
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define FindLastOf(sig) StringIds::find_last_of_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// find_last_of (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +---- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", NPOS),
TEST ("\0", "\0", NPOS),
TEST ("\0", "a", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", 5),
TEST ("edfcbahjig", "bca", 5),
TEST ("edfcbahcba", "cba", 9),
TEST ("cbacbbhjig", "cab", 5),
TEST ("e\0cb\0\0g", "b\0\0g", 3),
TEST ("e\0cb\0\0g", "ecb", 3),
TEST ("\0cb\0\0ge", "\0\0ge", NPOS),
TEST ("\0cb\0\0ge", "bc\0", 2),
TEST ("e\0cbg\0\0", "eg\0", 4),
TEST ("e\0cdg\0\0", "abc", 2),
TEST ("a\0b", "e\0gbg\0\0", NPOS),
TEST ("a\0b", "eb\0gg\0\0", 2),
TEST ("a\0b", "e\0gg\0\0a", NPOS),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 6),
TEST ("bcedfaajih", "a", 6),
TEST ("bcaaedfaji", "a", 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9),
TEST ("aaaaabaaaa", "cccccccccb", 5),
TEST ("aabaabaaaa", "cccccccccb", 5),
TEST ("bbb", "aaaaaaaaba", 2),
TEST ("bbb", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", NPOS),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 4095),
TEST ("x@4096", "xxx", 4095),
TEST ("x@4096", "aax", 4095),
TEST ("abc", "x@4096", NPOS),
TEST ("xxxxxxxxxx", "x@4096", 9),
TEST ("xxax@2048", "y@4096a", 2),
TEST ("abcdefghij", 0, 9),
TEST ("\0cb\0\0ge", 0, NPOS),
TEST ("x@4096", 0, 4095),
TEST ("last test", "test", 8)
};
/**************************************************************************/
// used to exercise
// find_last_of (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------ controlled sequence
// | +---------------------- sequence to be found
// | | +----- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", NPOS),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", NPOS),
TEST ("\0", "\0", 0),
TEST ("\0", "a", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", 5),
TEST ("edfcbahjig", "bca", 5),
TEST ("edfcbahcba", "cba", 9),
TEST ("cbacbbhjig", "cab", 5),
TEST ("e\0cb\0\0g", "b\0\0g", 6),
TEST ("e\0cb\0\0g", "ecb", 3),
TEST ("\0cb\0\0ge", "\0\0ge", 6),
TEST ("\0cb\0\0ge", "bc\0", 4),
TEST ("e\0cbg\0\0", "eg\0", 6),
TEST ("\0cbdaaaaa", "eg\0", 0),
TEST ("e\0cdg\0\0", "abc", 2),
TEST ("a\0b", "e\0gbg\0\0", 2),
TEST ("a\0b", "ea\0gg\0\0", 1),
TEST ("\0ab", "e\0gg\0\0a", 1),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 6),
TEST ("bcedfaajih", "a", 6),
TEST ("bcaaedfaji", "a", 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9),
TEST ("aaaaabaaaa", "cccccccccb", 5),
TEST ("aabaabaaaa", "cccccccccb", 5),
TEST ("bbb", "aaaaaaaaba", 2),
TEST ("bbb", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", NPOS),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 4095),
TEST ("x@4096", "xxx", 4095),
TEST ("x@4096", "aax", 4095),
TEST ("abc", "x@4096", NPOS),
TEST ("xxxxxxxxxx", "x@4096", 9),
TEST ("xxax@2048", "y@4096a", 2),
TEST ("abcdefghij", 0, 9),
TEST ("\0cb\0\0ge", 0, 6),
TEST ("x@4096", 0, 4095),
TEST ("last test", "test", 8)
};
/**************************************************************************/
// used to exercise
// find_last_of (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) { \
/* int .line = */ __LINE__, \
/* int .off = */ off, \
/* int .size = */ -1, \
/* int .off2 = */ -1, \
/* int .size2 = */ -1, \
/* int .val = */ -1, \
/* const char* .str = */ str, \
/* size_t .str_len = */ sizeof str - 1, \
/* const char* .arg = */ arg, \
/* size_t .arg_len = */ sizeof arg - 1, \
/* const char* .res = */ 0, \
/* size_t .nres = */ res, \
/* int .bthrow = */ 0 \
}
// +-------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +--------- find_last_of() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, NPOS),
TEST ("\0", "", 1, NPOS),
TEST ("\0", "\0", 0, NPOS),
TEST ("\0", "\0", 1, NPOS),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, 0),
TEST ("abcdefghij", "f", 2, NPOS),
TEST ("abcdefghij", "f", 7, 5),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 9, 5),
TEST ("edfcbahjag", "cba", 7, 5),
TEST ("edfcbahjig", "cba", 4, 4),
TEST ("edfcbahcba", "cba", 1, NPOS),
TEST ("edfcbahcba", "cba", 9, 9),
TEST ("edfcbahcba", "cba", 3, 3),
TEST ("cbacbahjig", "cba", 4, 4),
TEST ("e\0cb\0\0g", "b\0\0g", 5, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 2, NPOS),
TEST ("e\0cb\0\0g", "ecb", 7, 3),
TEST ("\0cb\0\0ge", "\0\0ge", 6, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 0, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 1, 1),
TEST ("\0cb\0\0ge", "cb\0", 2, 2),
TEST ("e\0cbg\0\0", "bg", 1, NPOS),
TEST ("e\0cbg\0\0", "bg", 5, 4),
TEST ("a\0b", "e\0gbg\0\0", 3, NPOS),
TEST ("a\0b", "eb\0gg\0\0", 3, 2),
TEST ("a\0b", "e\0gg\0\0a", 3, NPOS),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 8, 6),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 8, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, 9),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 4, 4),
TEST ("aaaaabaaaa", "cccccccccb", 8, 5),
TEST ("aabaabaaaa", "cccccccccb", 9, 5),
TEST ("aabaabaaaa", "cccccccccb", 3, 2),
TEST ("bbb", "aaaaaaaaba", 2, 2),
TEST ("bab", "aaaaaaaaba", 0, 0),
TEST ("bbb", "aaaaaaaaaa", 3, NPOS),
TEST ("x@4096", "", 4096, NPOS),
TEST ("x@4096", "a", 4096, NPOS),
TEST ("x@4096", "x", 4096, 4095),
TEST ("x@4096", "xxx", 4095, 4095),
TEST ("x@4096", "xxx", 0, 0),
TEST ("x@4096", "xxx", 4087, 4087),
TEST ("x@4096", "aax", 4087, 4087),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 6, 6),
TEST ("xxax@2048", "y@4096a", 2050, 2),
TEST ("x@4096", "xxx", 3, 3),
TEST ("x@4096", "xxx", 2, 2),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 9, 9),
TEST ("\0cb\0\0ge", 0, 5, NPOS),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 1, 1),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, 2),
TEST ("abcdefghij", "cba", 10, 2),
TEST ("last test", "test", 9, 8)
};
/**************************************************************************/
// used to exercise
// find_last_of (const value_type*, size_type, size_type)
static const StringTestCase
cptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, size, res, bthrow) \
{ __LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, bthrow \
}
// +--------------------------------------- controlled sequence
// | +-------------------------- sequence to be found
// | | +---------- find_last_of() off argument
// | | | +------ find_last_of() n argument
// | | | | +-- expected result
// | | | | | exception info
// | | | | | | 0 - no exception
// | | | | | | 1 - length_error
// | | | | | |
// | | | | | +----+
// V V V V V V
TEST ("ab", "a", 0, 1, 0, 0),
TEST ("", "", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 0, NPOS, 0),
TEST ("", "\0", 0, 1, NPOS, 0),
TEST ("", "a", 0, 0, NPOS, 0),
TEST ("", "a", 0, 1, NPOS, 0),
TEST ("\0", "", 0, 0, NPOS, 0),
TEST ("\0", "\0", 0, 1, 0, 0),
TEST ("\0", "\0", 1, 1, 0, 0),
TEST ("\0\0", "\0\0", 1, 1, 1, 0),
TEST ("\0", "a", 0, 1, NPOS, 0),
TEST ("edfcbbhjig", "cba", 0, 3, NPOS, 0),
TEST ("edfcbbhjig", "cba", 0, 2, NPOS, 0),
TEST ("edfcbbhjig", "cba", 9, 2, 5, 0),
TEST ("edfcbahjig", "cba", 8, 3, 5, 0),
TEST ("edfcbahjig", "cba", 2, 3, NPOS, 0),
TEST ("edfcbahjig", "cba", 2, 1, NPOS, 0),
TEST ("edfcbahcba", "cba", 8, 3, 8, 0),
TEST ("edfcbehcba", "cab", 8, 2, 7, 0),
TEST ("edfcbahcba", "cba", 9, 3, 9, 0),
TEST ("cbacbahjig", "cba", 5, 3, 5, 0),
TEST ("cbacbahjig", "cba", 2, 1, 0, 0),
TEST ("cbacbahjcg", "cba", 7, 1, 3, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 4, NPOS, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 7, 4, 6, 0),
TEST ("e\0cb\0\0b", "b\0\0g", 4, 1, 3, 0),
TEST ("\0b\0\0gb\0","b\0\0g", 7, 2, 6, 0),
TEST ("\0b\0\0gb\0","b\0\0g", 2, 2, 2, 0),
TEST ("\0b\0\0b\0g","b\0g\0", 7, 3, 6, 0),
TEST ("e\0cb\0\0g", "ecb", 7, 2, 2, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 4, 6, 0),
TEST ("\0cb\0\0ge", "\0\0ge", 2, 0, NPOS, 0),
TEST ("\0cb\0\0ge", "cb\0", 1, 3, 1, 0),
TEST ("e\0cbg\0\0", "bg", 1, 2, NPOS, 0),
TEST ("a\0b", "e\0gbg\0\0", 2, 1, NPOS, 0),
TEST ("a\0b", "eb\0gg\0\0", 1, 2, NPOS, 0),
TEST ("a\0b", "e\0gg\0\0a", 3, 6, 1, 0),
TEST ("a\0b", "e\0gg\0\0a", 0, 7, 0, 0),
TEST ("a\0b", "eb\0gg\0\0", 1, 3, 1, 0),
TEST ("e\0a\0", "e\0a\0\0", 2, 4, 2, 0),
TEST ("e\0a\0", "e\0a\0\0", 3, 5, 3, 0),
TEST ("ee\0a\0", "b\0c\0\0", 3, 4, 2, 0),
TEST ("e\0a\0b", "fdbcb\0a", 3, 5, NPOS, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, 10, 9, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 8, 10, 8, 0),
TEST ("aaaaabaaaa", "cccccccccc", 9, 10, NPOS, 0),
TEST ("aaaaabaaaa", "cccbcccccc", 8, 4, 5, 0),
TEST ("aaaabaaaaa", "cccca", 9, 5, 9, 0),
TEST ("aabaabaaaa", "cbccccccca", 7, 5, 5, 0),
TEST ("bbb", "aaaaaaaaba", 1, 2, NPOS, 0),
TEST ("bbb", "aaaaaaaaaa", 0, 9, NPOS, 0),
TEST ("bab", "aaaaaaaaba", 0, 0, NPOS, 0),
TEST ("bab", "ccccccccba", 1, 10, 1, 0),
TEST ("x@4096", "", 4096, 0, NPOS, 0),
TEST ("x@4096", "a", 4096, 1, NPOS, 0),
TEST ("x@4096", "x", 4096, 1, 4095, 0),
TEST ("x@4096", "xxx", 4088, 3, 4088, 0),
TEST ("x@4096", "axa", 4088, 3, 4088, 0),
TEST ("abc", "x@4096", 2, 10, NPOS, 0),
TEST ("xxxxxxxxxx", "x@4096", 0,4096, 0, 0),
TEST ("xxxxxxxxxx", "x@4096", 2, 4, 2, 0),
TEST ("xxax@2048", "y@4096a", 2050,4097, 2, 0),
TEST ("x@4096", "xxx", 4093, 3, 4093, 0),
TEST ("x@4096", "xxx", 4094, 3, 4094, 0),
TEST ("x@4096", "xxx", 4094, 2, 4094, 0),
TEST ("abcdefghij", 0, 0, 9, 0, 0),
TEST ("abcdefghij", 0, 8, 9, 8, 0),
TEST ("\0cb\0\0ge", 0, 5, 7, 5, 0),
TEST ("\0cb\0ge\0", 0, 6, 1, 6, 0),
TEST ("\0c\0e\0cg", 0, 6, 2, 5, 0),
TEST ("x@4096", 0, 0, 4096, 0, 0),
TEST ("x@4096", 0, 1, 4096, 1, 0),
TEST ("x@4096", 0, 5, 4091, 5, 0),
TEST ("x@4096", 0, 4091, 1, 4091, 0),
TEST ("", "", 1, 0, NPOS, 0),
TEST ("abcdefghij", "abc", 10, 3, 2, 0),
TEST ("abcdefghij", "cba", 10, 1, 2, 0),
TEST ("", "cba", 0, -1, NPOS, 0),
TEST ("abcdefghij", "cbaj", 9, -1, 9, 0),
TEST ("x@4096", "xxx", 4095, -1, 4095, 0),
TEST ("abcdefghij", "jx@4096", 9, -1, 9, 0),
TEST ("last test", "test", 9, 4, 8, 0)
};
/**************************************************************************/
// used to exercise
// find_last_of (const basic_string&, size_type)
static const StringTestCase
cstr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +---------- find_last_of() off argument
// | | | +---- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, NPOS),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, NPOS),
TEST ("\0", "", 1, NPOS),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, 0),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, 0),
TEST ("abcdefghij", "f", 2, NPOS),
TEST ("abcdefghij", "f", 7, 5),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 9, 5),
TEST ("edfcbahjag", "cba", 7, 5),
TEST ("edfcbahjig", "cba", 4, 4),
TEST ("edfcbahcba", "cba", 1, NPOS),
TEST ("edfcbahcba", "cba", 9, 9),
TEST ("edfcbahcba", "cba", 3, 3),
TEST ("cbacbahjig", "cba", 4, 4),
TEST ("e\0cb\0\0g", "b\0\0g", 5, 5),
TEST ("e\0cb\0\0g", "b\0\0g", 2, 1),
TEST ("e\0cb\0\0g", "ecb", 7, 3),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 6),
TEST ("\0cb\0\0ge", "cb\0", 0, 0),
TEST ("\0cb\0\0ge", "cb\0", 1, 1),
TEST ("\0cb\0\0ge", "cb\0", 2, 2),
TEST ("e\0cbg\0\0", "bg", 1, NPOS),
TEST ("e\0cbg\0\0", "bg", 5, 4),
TEST ("a\0b", "e\0gbg\0\0", 2, 2),
TEST ("a\0b", "eb\0gg\0\0", 2, 2),
TEST ("a\0b", "e\0gg\0\0a", 3, 1),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 8, 6),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 8, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, 9),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 4, 4),
TEST ("aaaaabaaaa", "cccccccccb", 8, 5),
TEST ("aabaabaaaa", "cccccccccb", 9, 5),
TEST ("aabaabaaaa", "cccccccccb", 3, 2),
TEST ("bbb", "aaaaaaaaba", 2, 2),
TEST ("bab", "aaaaaaaaba", 0, 0),
TEST ("bbb", "aaaaaaaaaa", 3, NPOS),
TEST ("x@4096", "", 4096, NPOS),
TEST ("x@4096", "a", 4096, NPOS),
TEST ("x@4096", "x", 4096, 4095),
TEST ("x@4096", "xxx", 4095, 4095),
TEST ("x@4096", "xxx", 0, 0),
TEST ("x@4096", "xxx", 4087, 4087),
TEST ("x@4096", "aax", 4087, 4087),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 6, 6),
TEST ("xxax@2048", "y@4096a", 2050, 2),
TEST ("x@4096", "xxx", 3, 3),
TEST ("x@4096", "xxx", 2, 2),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 9, 9),
TEST ("\0cb\0\0ge", 0, 5, 5),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 1, 1),
TEST ("", "", 1, NPOS),
TEST ("abcdefghij", "abc", 10, 2),
TEST ("abcdefghij", "cba", 10, 2),
TEST ("last test", "test", 9, 8)
};
/**************************************************************************/
// used to exercise
// find_last_of (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res) \
{ __LINE__, -1, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +----------------------------- controlled sequence
// | +-------------- character to be found
// | | +------ expected result
// | | |
// | | |
// V V V
TEST ("ab", 'a', 0),
TEST ("", 'a', NPOS),
TEST ("", '\0', NPOS),
TEST ("\0", '\0', 0),
TEST ("\0\0", '\0', 1),
TEST ("\0", 'a', NPOS),
TEST ("e\0cb\0\0g", '\0', 5),
TEST ("e\0cb\0\0g", 'b', 3),
TEST ("e\0cb\0\0g", 'a', NPOS),
TEST ("\0cbge\0\0", '\0', 6),
TEST ("\0cbge\0\0", 'b', 2),
TEST ("\0cbge\0\0", 'a', NPOS),
TEST ("x@4096", 'x', 4095),
TEST ("x@4096", '\0', NPOS),
TEST ("x@4096", 'a', NPOS),
TEST ("xxax@2048", 'a', 2),
TEST ("last test", 't', 8)
};
/**************************************************************************/
// used to exercise
// find_last_of (value_type, size_type)
static const StringTestCase
val_size_test_cases [] = {
#undef TEST
#define TEST(str, val, off, res) \
{ __LINE__, off, -1, -1, -1, \
val, str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +------------------------------ controlled sequence
// | +--------------- character to be found
// | | +--------- find_last_of() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", 'a', 0, 0),
TEST ("", 'a', 0, NPOS),
TEST ("", '\0', 0, NPOS),
TEST ("\0", '\0', 1, 0),
TEST ("\0", 'a', 0, NPOS),
TEST ("\0\0", '\0', 2, 1),
TEST ("\0\0", 'a', 3, NPOS),
TEST ("\0\0", '\0', 3, 1),
TEST ("e\0cb\0\0g", '\0', 1, 1),
TEST ("e\0cb\0\0g", '\0', 5, 5),
TEST ("e\0cb\0\0g", '\0', 0, NPOS),
TEST ("e\0cb\0\0g", 'b', 1, NPOS),
TEST ("e\0cb\0\0g", 'b', 4, 3),
TEST ("e\0cb\0\0g", 'a', 6, NPOS),
TEST ("\0cbge\0\0", '\0', 0, 0),
TEST ("\0cbge\0\0", '\0', 5, 5),
TEST ("\0cbge\0\0", '\0', 9, 6),
TEST ("\0cbge\0\0", 'b', 5, 2),
TEST ("\0bgeb\0\0", 'b', 5, 4),
TEST ("\0cbge\0\0", 'a', 6, NPOS),
TEST ("x@4096", 'x', 0, 0),
TEST ("x@4096", 'x', 5, 5),
TEST ("x@4096", 'x', 4096, 4095),
TEST ("x@4096", '\0', 4096, NPOS),
TEST ("x@4096", 'a', 4094, NPOS),
TEST ("x@4096", 'x', 4095, 4095),
TEST ("x@4096", 'x', 4106, 4095),
TEST ("xxax@2048", 'a', 2050, 2),
TEST ("last test", 't', 9, 8)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_find_last_of (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object and the argument string
const String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 0;
if (1 == tcase.bthrow)
expected = exceptions [2];
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
std::size_t res = 0;
switch (func.which_) {
case FindLastOf (cptr):
res = s_str.find_last_of (arg_ptr);
break;
case FindLastOf (cstr): {
res = s_str.find_last_of (arg_str);
break;
}
case FindLastOf (cptr_size): {
res = s_str.find_last_of (arg_ptr, tcase.off);
break;
}
case FindLastOf (cptr_size_size): {
res = s_str.find_last_of (arg_ptr, tcase.off, size);
break;
}
case FindLastOf (cstr_size): {
res = s_str.find_last_of (arg_str, tcase.off);
break;
}
case FindLastOf (val): {
res = s_str.find_last_of (arg_val);
break;
}
case FindLastOf (val_size): {
res = s_str.find_last_of (arg_val, tcase.off);
break;
}
default:
RW_ASSERT ("test logic error: unknown find_last_of overload");
return;
}
std::size_t exp_res =
NPOS != tcase.nres ? tcase.nres : String::npos;
// verify the returned value
rw_assert (exp_res == res, 0, tcase.line,
"line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
"got %{?}%zu%{;}%{?}npos%{;}",
__LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres,
String::npos != res, res, String::npos == res);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_find_last_of);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
FindLastOf (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cptr_size_size),
TEST (cstr_size),
TEST (val),
TEST (val_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.find.last.of",
test_find_last_of, tests, test_count);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,556 @@
/***************************************************************************
*
* 21.string.iterators.cpp - string test exercising lib.string.iterators
*
* $Id: 21.string.iterators.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <stdexcept> // for out_of_range, length_error
#include <cstddef> // for size_t
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
static const char* const exceptions[] = {
"unknown exception", "bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// begin () and rend ()
static const StringTestCase
begin_void_test_cases [] = {
#undef TEST
#define TEST(str, res) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof (str) - 1, \
0, 0, 0, res, 0 \
}
// +--------------------------------- controlled sequence
// | +--------------- expected result
// | |
// V V
TEST ("a", 'a' ),
TEST ("<U0>", '\0'),
TEST ("abc", 'a' ),
TEST ("<U0>ab<U0>@2c", '\0'),
TEST ("a<U0>b<U0>@2c", 'a' ),
TEST ("a<U0>bc<U0>@2", 'a' ),
TEST ("x@4096", 'x' ),
TEST ("last", 'l' )
};
/**************************************************************************/
// used to exercise
// end () and rbegin ()
static const StringTestCase
end_void_test_cases [] = {
#undef TEST
#define TEST(str, res) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof (str) - 1, \
0, 0, 0, res, 0 \
}
// +--------------------------------- controlled sequence
// | +--------------- expected result
// | |
// V V
TEST ("a", 'a' ),
TEST ("<U0>", '\0'),
TEST ("abc", 'c' ),
TEST ("<U0>ab<U0>@2c", 'c' ),
TEST ("a<U0>b<U0>@2c", 'c' ),
TEST ("a<U0>bc<U0>@2", '\0'),
TEST ("x@4096", 'x' ),
TEST ("last", 't' )
};
/**************************************************************************/
// exercises:
// c_str() and data ()
static const StringTestCase
c_str_void_test_cases [] = {
#undef TEST
#define TEST(str) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof (str) - 1, 0, 0, \
str, sizeof (str) - 1, 0 \
}
// +-------------------------------- controlled sequence
// |
// |
// |
// |
// |
// |
// |
// V
TEST ("ab" ),
TEST ("" ),
TEST ("<U0>" ),
TEST ("abcdefghij" ),
TEST ("abcdefghi" ),
TEST ("abbdefghij" ),
TEST ("abcdeeghij" ),
TEST ("abcdefghii" ),
TEST ("bbcdefghij" ),
TEST ("eeeeeeghij" ),
TEST ("a" ),
TEST ("aeeee" ),
TEST ("bbcdefghij" ),
TEST ("abcdffghij" ),
TEST ("abcdefghjj" ),
TEST ("a<U0>b<U0>@2c" ),
TEST ("abc<U0>@3" ),
TEST ("<U0>ab<U0>@2c" ),
TEST ("a<U0>b" ),
TEST ("ab<U0>" ),
TEST ("<U0>ab" ),
TEST ("x@4096" ),
TEST ("xx" ),
TEST ("a@2048b@2048" ),
TEST ("a@2048cb@2047" ),
TEST ("last" )
};
/**************************************************************************/
// exercises:
// get_allocator ()
static const StringTestCase
get_allocator_void_test_cases [] = {
#undef TEST
#define TEST(str) { \
__LINE__, -1, -1, -1, -1, -1, \
str, sizeof (str) - 1, \
0, 0, 0, 0, 0 \
}
// +------------------------------------------ controlled sequence
// |
// |
// |
// |
// |
// |
// |
// V
TEST ("ab" ),
TEST ("" ),
TEST ("<U0>" ),
TEST ("x@4096" ),
TEST ("a<U0>b" ),
TEST ("a@2048cb@2047" ),
TEST ("last" )
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_iterators (charT*, Traits*, Allocator*,
const StringTestCaseData<charT> &tdata)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename String::iterator StringIter;
typedef typename String::const_iterator StringCIter;
typedef typename String::reverse_iterator StringRIter;
typedef typename String::const_reverse_iterator StringCRIter;
const StringFunc &func = tdata.func_;
const StringTestCase &tcase = tdata.tcase_;
const bool test_iters = func.which_ == StringIds::begin_void
|| func.which_ == StringIds::begin_const_void
|| func.which_ == StringIds::end_void
|| func.which_ == StringIds::end_const_void
|| func.which_ == StringIds::rbegin_void
|| func.which_ == StringIds::rbegin_const_void
|| func.which_ == StringIds::rend_void
|| func.which_ == StringIds::rend_const_void;
const bool test_const_iters = func.which_ == StringIds::begin_const_void
|| func.which_ == StringIds::end_const_void
|| func.which_ == StringIds::rbegin_const_void
|| func.which_ == StringIds::rend_const_void;
const bool test_end_iters = func.which_ == StringIds::end_void
|| func.which_ == StringIds::end_const_void
|| func.which_ == StringIds::rend_void
|| func.which_ == StringIds::rend_const_void;
// allocator object for test get_allocator
Allocator alloc;
// construct the string object
String str (tdata.str_, tdata.strlen_, alloc);
// construct the constant string object
const String cstr (tdata.str_, tdata.strlen_, alloc);
const std::size_t s_size = test_const_iters ? cstr.size () : str.size ();
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [1]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
#endif // _RWSTD_NO_EXCEPTIONS
// start checking for memory leaks
rw_check_leaks (str.get_allocator ());
// for data () and c_str ()
const charT* ret_ptr = 0;
// methods result
charT res;
// for begin () and end ()
StringIter it;
// for begin () const and end () const
StringCIter cit;
// for rbegin () and rend ()
StringRIter rit;
// for rbegin () const and rend () const
StringCRIter crit;
// for get_allocator ()
Allocator resalloc;
try {
bool it_relations = true;
switch (func.which_) {
case StringIds::begin_void:
it = str.begin();
res = s_size ? *it : charT ();
it_relations = it == str.rend ().base ();
break;
case StringIds::begin_const_void:
cit = cstr.begin();
res = s_size ? *cit : charT ();
it_relations = cit == cstr.rend ().base ();
break;
case StringIds::end_void:
it = str.end();
res = s_size ? *(it - 1) : charT ();
it_relations = it == str.rbegin ().base ();
break;
case StringIds::end_const_void:
cit = cstr.end();
res = s_size ? *(cit - 1) : charT ();
it_relations = cit == cstr.rbegin ().base ();
break;
case StringIds::rbegin_void:
rit = str.rbegin();
res = s_size ? *rit : charT ();
it_relations = rit.base () == str.end ();
break;
case StringIds::rbegin_const_void:
crit = cstr.rbegin();
res = s_size ? *crit : charT ();
it_relations = crit.base () == cstr.end ();
break;
case StringIds::rend_void:
rit = str.rend();
res = s_size ? *(rit - 1) : charT ();
it_relations = rit.base () == str.begin ();
break;
case StringIds::rend_const_void:
crit = cstr.rend();
res = s_size ? *(crit - 1) : charT ();
it_relations = crit.base () == cstr.begin ();
break;
case StringIds::c_str_void:
ret_ptr = cstr.c_str ();
break;
case StringIds::data_void:
ret_ptr = cstr.data ();
break;
case StringIds::get_allocator_void:
resalloc = cstr.get_allocator ();
break;
default:
RW_ASSERT ("test logic error: unknown iterators overload");
return;
}
// for convenience
static const int cwidth = sizeof (charT);
if ( func.which_ == StringIds::data_void
|| func.which_ == StringIds::c_str_void) {
// 21.3.6
// the member returns a non-null pointer
rw_assert(0 != ret_ptr, 0, tcase.line,
"line %d. %{$FUNCALL} expected non null, got null",
__LINE__);
if (ret_ptr) {
// 21.3.6.1
// if size() is nonzero, the member returns a pointer to the
// initial element of an array whose first size() elements
// equal the corresponding elements of the string controlled
// by *this
// 21.3.6.3
// if size() is nonzero, the member returns a pointer to the
// initial element of an array whose first size() elements
// equal the corresponding elements of the string controlled
// by *this
const std::size_t match =
rw_match (tcase.res, ret_ptr, tdata.reslen_);
rw_assert (match == tdata.reslen_, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, differ at pos %zu",
__LINE__, int (tdata.reslen_), tdata.res_,
cwidth, int (s_size), ret_ptr, match);
if (func.which_ == StringIds::c_str_void) {
// check the last element is equal to char ()
const char null = char ();
const bool success =
(1 == rw_match (&null, &ret_ptr[s_size], 1));
rw_assert(success, 0, tcase.line,
"line %d. %{$FUNCALL} expected last element "
"is a null character %{#c}, got %{#c}",
__LINE__, null, ret_ptr[s_size]);
}
}
}
if (test_iters) {
if (s_size) {
const char exp_res =
(NPOS != tcase.nres ? char (tcase.nres) : char ());
const bool success = (1 == rw_match (&exp_res, &res, 1));
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL}%{?} - 1%{;} expected "
"%{#c}, got %{#c}", __LINE__,
test_end_iters, exp_res, res);
}
else {
bool success = true;
if ( func.which_ == StringIds::begin_void
|| func.which_ == StringIds::end_void)
success = it == str.begin () && it == str.end ();
if ( func.which_ == StringIds::begin_const_void
|| func.which_ == StringIds::end_const_void)
success = cit == cstr.begin () && cit == cstr.end ();
if ( func.which_ == StringIds::rbegin_void
|| func.which_ == StringIds::rend_void)
success = rit == str.rbegin () && rit == str.rend ();
if ( func.which_ == StringIds::rbegin_const_void
|| func.which_ == StringIds::rend_const_void)
success =
crit == cstr.rbegin () && crit == cstr.rend ();
// check the begin () == end (), rbegin () == rend ()
rw_assert(success, 0, tcase.line,
"line %d. %{$FUNCALL} returned iterator is not "
"equal to begin and end for an empty string",
__LINE__);
}
// check the iterators relationship
rw_assert(it_relations, 0, tcase.line,
"line %d. %{$FUNCALL} iterators "
"relationship is broken", __LINE__);
}
if (func.which_ == StringIds::get_allocator_void) {
// verify that the allocator returned from the function
// equal to allocator passed to the ctor
const bool success = (alloc == resalloc);
rw_assert(success, 0, tcase.line,
"line %d. %{$FUNCALL} expected equal to allocator "
"passed to the ctor", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::bad_alloc &ex) {
caught = exceptions [1];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [2];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
break;
}
rw_assert (0 == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected 0 %s exceptions, got %zu",
__LINE__, exceptions [1], throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
}
/**************************************************************************/
DEFINE_STRING_TEST_FUNCTIONS (test_iterators);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(gsig, sig) { \
gsig, sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (StringIds::begin_void, begin_void),
TEST (StringIds::begin_const_void, begin_void),
TEST (StringIds::end_void, end_void),
TEST (StringIds::end_const_void, end_void),
TEST (StringIds::rbegin_void, end_void),
TEST (StringIds::rbegin_const_void, end_void),
TEST (StringIds::rend_void, begin_void),
TEST (StringIds::rend_const_void, begin_void),
TEST (StringIds::c_str_void, c_str_void),
TEST (StringIds::data_void, c_str_void),
TEST (StringIds::get_allocator_void, get_allocator_void)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.iterators",
test_iterators_func_array, tests, test_count);
}

View File

@@ -0,0 +1,617 @@
/***************************************************************************
*
* 21.string.op.plus.cpp - test exercising [lib.string::op+]
*
* $Id: 21.string.op.plus.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <stdexcept> // for out_of_range, length_error
#include <cstddef> // for size_t
#include <21.strings.h> // for StringMembers
#include <alg_test.h> // for InputIter
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define OpPlus(which) StringIds::op_plus_ ## which
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// operator + (const value_type*, const basic_string&)
static const StringTestCase
cptr_cstr_test_cases [] = {
#undef TEST
#define TEST(str, src, res, bthrow) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, src, sizeof src - 1, \
res, sizeof res - 1, bthrow \
}
// +----------------------------------------- first sequence
// | +------------------------ second sequence
// | | +------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | |
// | | | +---------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "a", "a", 0),
TEST ("a", "", "a", 0),
TEST ("<U0>", "", "", 0),
TEST ("", "<U0>", "<U0>", 0),
TEST ("<U0>", "<U0>", "<U0>", 0),
TEST ("abcdefg", "jih", "abcdefgjih", 0),
TEST ("jih", "abcdefg", "jihabcdefg", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "e<U0>", 0),
TEST ("e<U0>", "<U0>ab<U0>@2c", "e<U0>ab<U0>@2c", 0),
TEST ("ab<U0>@2c<U0>", "e<U0>", "abe<U0>", 0),
TEST ("e<U0>", "ab<U0>@2c<U0>", "eab<U0>@2c<U0>", 0),
TEST ("x@2048", "x@2048", "x@4096", 0),
TEST ("a@2048", "b@2048", "a@2048b@2048", 0),
TEST ("a@2048<U0>", "b@2048", "a@2048b@2048", 0),
TEST ("a@2048", "b@2048<U0>", "a@2048b@2048<U0>", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST (0, "abc", "abcabc", 0),
TEST (0, "<U0>ab<U0>", "<U0>ab<U0>", 0),
TEST (0, "x@2048", "x@4096", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// operator + (const basic_string&, const basic_string&)
static const StringTestCase
cstr_cstr_test_cases [] = {
#undef TEST
#define TEST(str, src, res, bthrow) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, src, sizeof src - 1, \
res, sizeof res - 1, bthrow \
}
// +----------------------------------------- first sequence
// | +------------------------ second sequence
// | | +---------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | |
// | | | +-------------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "a", "a", 0),
TEST ("a", "", "a", 0),
TEST ("<U0>", "", "<U0>", 0),
TEST ("", "<U0>", "<U0>", 0),
TEST ("<U0>", "<U0>", "<U0>@2", 0),
TEST ("abcdefg", "jih", "abcdefgjih", 0),
TEST ("jih", "abcdefg", "jihabcdefg", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce<U0>", 0),
TEST ("e<U0>", "<U0>ab<U0>@2c", "e<U0>@2ab<U0>@2c", 0),
TEST ("ab<U0>@2c<U0>", "e<U0>", "ab<U0>@2c<U0>e<U0>", 0),
TEST ("e<U0>", "ab<U0>@2c<U0>", "e<U0>ab<U0>@2c<U0>", 0),
TEST ("x@2048", "x@2048", "x@4096", 0),
TEST ("a@2048", "b@2048", "a@2048b@2048", 0),
TEST ("a@2048<U0>", "b@2048", "a@2048<U0>b@2048", 0),
TEST ("a@2048", "b@2048<U0>", "a@2048b@2048<U0>", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST (0, "abc", "abcabc", 0),
TEST (0, "<U0>ab<U0>", "<U0>ab<U0>@2ab<U0>", 0),
TEST (0, "x@2048", "x@4096", 0),
TEST ("abc", 0, "abcabc", 0),
TEST ("<U0>ab<U0>", 0, "<U0>ab<U0>@2ab<U0>", 0),
TEST ("x@2048", 0, "x@4096", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// operator + (const basic_string&, const value_type*)
static const StringTestCase
cstr_cptr_test_cases [] = {
#undef TEST
#define TEST(str, src, res, bthrow) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, src, sizeof src - 1, \
res, sizeof res - 1, bthrow \
}
// +----------------------------------------- first sequence
// | +------------------------ second sequence
// | | +---------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | |
// | | | +----------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "a", "a", 0),
TEST ("a", "", "a", 0),
TEST ("<U0>", "", "<U0>", 0),
TEST ("", "<U0>", "", 0),
TEST ("<U0>", "<U0>", "<U0>", 0),
TEST ("abcdefg", "jih", "abcdefgjih", 0),
TEST ("jih", "abcdefg", "jihabcdefg", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce", 0),
TEST ("e<U0>", "<U0>ab<U0>@2c", "e<U0>", 0),
TEST ("ab<U0>@2c<U0>", "e<U0>", "ab<U0>@2c<U0>e", 0),
TEST ("e<U0>", "ab<U0>@2c<U0>", "e<U0>ab", 0),
TEST ("x@2048", "x@2048", "x@4096", 0),
TEST ("a@2048", "b@2048", "a@2048b@2048", 0),
TEST ("a@2048<U0>", "b@2048", "a@2048<U0>b@2048", 0),
TEST ("a@2048", "b@2048<U0>", "a@2048b@2048", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST ("abc", 0, "abcabc", 0),
TEST ("<U0>ab<U0>", 0, "<U0>ab<U0>", 0),
TEST ("x@2048", 0, "x@4096", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// operator + (const basic_string&, value_type)
static const StringTestCase
cstr_val_test_cases [] = {
#undef TEST
#define TEST(arg, val, res) \
{ __LINE__, -1, -1, -1, -1, val, \
0, 0, arg, sizeof arg - 1, \
res, sizeof res - 1, 0 \
}
// +----------------------------------------- first sequence
// | +----------------------- character to be added
// | | +--------- expected result sequence
// | | |
// | | |
// V V V
TEST ("ab", 'c', "abc"),
TEST ("", 'a', "a"),
TEST ("", '\0', "<U0>"),
TEST ("<U0>", 'a', "<U0>a"),
TEST ("<U0>", '\0', "<U0>@2"),
TEST ("<U0>ab<U0>@2c", 'e', "<U0>ab<U0>@2ce"),
TEST ("<U0>ab<U0>@2c", '\0', "<U0>ab<U0>@2c<U0>"),
TEST ("ab<U0>@2c<U0>", 'e', "ab<U0>@2c<U0>e"),
TEST ("ab<U0>@2c<U0>", '\0', "ab<U0>@2c<U0>@2"),
TEST ("abcdefghj", 'i', "abcdefghji"),
TEST ("x@4095", 'x', "x@4096"),
TEST ("x@4095", '\0', "x@4095<U0>"),
TEST ("x@127", 'x', "x@128"),
TEST ("x@206", 'x', "x@207"),
TEST ("x@333", 'x', "x@334"),
TEST ("x@539", 'x', "x@540"),
TEST ("x@1411", 'x', "x@1412"),
TEST ("x@2283", 'x', "x@2284"),
TEST ("x@3694", 'x', "x@3695"),
TEST ("x@540", 'x', "x@541"),
TEST ("last", 't', "lastt")
};
/**************************************************************************/
// exercises:
// operator + (value_type, const basic_string&)
static const StringTestCase
val_cstr_test_cases [] = {
#undef TEST
#define TEST(val, arg, res) \
{ __LINE__, -1, -1, -1, -1, val, \
"", 0, arg, sizeof arg - 1, \
res, sizeof res - 1, 0 \
}
// +----------------------------------------- first sequence
// | +--------------------------- character to be added
// | | +--------- expected result sequence
// | | |
// | | |
// V V V
TEST ('c', "ab", "cab"),
TEST ('a', "", "a"),
TEST ('\0', "", "<U0>"),
TEST ('a', "<U0>", "a<U0>"),
TEST ('\0', "<U0>", "<U0>@2"),
TEST ('e', "<U0>ab<U0>@2c", "e<U0>ab<U0>@2c"),
TEST ('\0', "<U0>ab<U0>@2c", "<U0>@2ab<U0>@2c"),
TEST ('e', "ab<U0>@2c<U0>", "eab<U0>@2c<U0>"),
TEST ('\0', "ab<U0>@2c<U0>", "<U0>ab<U0>@2c<U0>"),
TEST ('i', "abcdefghj", "iabcdefghj"),
TEST ('x', "x@4095", "x@4096"),
TEST ('\0', "x@4095", "<U0>x@4095"),
TEST ('x', "x@127", "x@128"),
TEST ('x', "x@206", "x@207"),
TEST ('x', "x@333", "x@334"),
TEST ('x', "x@539", "x@540"),
TEST ('x', "x@1411", "x@1412"),
TEST ('x', "x@2283", "x@2284"),
TEST ('x', "x@3694", "x@3695"),
TEST ('x', "x@540", "x@541"),
TEST ('t', "last", "tlast")
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_op_plus (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename UserTraits<charT>::MemFun UTMemFun;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
static charT wres_buf [BUFSIZE];
std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
// construct the string object to be modified
// and the (possibly unused) argument string
/* const */ String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
String s_res;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_res));
const charT* const arg1_ptr = tcase.str ? s_str.c_str () : s_arg.c_str ();
const String& arg1_str = tcase.str ? s_str : s_arg;
const charT* const arg2_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg2_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t total_length_calls = 0;
std::size_t n_length_calls = 0;
std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls)
total_length_calls = rg_calls [UTMemFun::length];
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
else {
// exceptions disabled for this test case
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
// start checking for memory leaks
rw_check_leaks (s_res.get_allocator ());
try {
switch (func.which_) {
case OpPlus (cptr_cstr):
s_res = arg1_ptr + arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpPlus (cstr_cstr):
s_res = arg1_str + arg2_str;
break;
case OpPlus (cstr_cptr):
s_res = arg1_str + arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpPlus (cstr_val):
s_res = arg1_str + arg_val;
break;
case OpPlus (val_cstr):
s_res = arg_val + arg2_str;
break;
default:
RW_ASSERT ("test logic error: unknown operator+ overload");
return;
}
// verfiy that strings length are equal
rw_assert (res_len == s_res.size (), 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s} "
"with length %zu, got %{/*.*Gs} with length %zu",
__LINE__, int (tcase.nres), tcase.res, res_len,
int (sizeof (charT)), int (s_res.size ()),
s_res.c_str (), s_res.size ());
if (res_len == s_res.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the modified
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, s_res.c_str(), s_res.size ());
rw_assert (match == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (s_res.size ()),
s_res.c_str (), match);
}
// verify that Traits::length was used
if ((OpPlus (cptr_cstr) == func.which_
|| OpPlus (cstr_cptr) == func.which_) && rg_calls) {
rw_assert (n_length_calls - total_length_calls > 0,
0, tcase.line, "line %d. %{$FUNCALL} doesn't "
"use traits::length()", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::bad_alloc &ex) {
caught = exceptions [3];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (s_res.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_res),
__LINE__, tcase.line, caught);
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
// verify that if exceptions are enabled and when capacity changes
// at least one exception is thrown
const std::size_t expect_throws = str_state.capacity_ < s_res.capacity ();
#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
const std::size_t expect_throws =
(StringIds::UserAlloc == func.alloc_id_)
? str_state.capacity_ < s_res.capacity () : 0;
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
// we may got no more 2 bad_allocs
rw_assert (expect_throws <= throw_count && throw_count <= 2, 0, tcase.line,
"line %d: %{$FUNCALL}: expected at least 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, s_res.capacity (), throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
if (wres != wres_buf)
delete[] wres;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_op_plus);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(tag) { \
StringIds::op_plus_ ## tag, tag ## _test_cases, \
sizeof tag ## _test_cases / sizeof *tag ## _test_cases \
}
TEST (cptr_cstr),
TEST (cstr_cptr),
TEST (cstr_cstr),
TEST (cstr_val),
TEST (val_cstr)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string::op+",
test_op_plus, tests, test_count);
}

View File

@@ -0,0 +1,517 @@
/***************************************************************************
*
* 21.string.plus.equal.cpp - test exercising [lib.string.op+=]
*
* $Id: 21.string.op.plus.equal.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <stdexcept> // for out_of_range, length_error
#include <cstddef> // for size_t
#include <21.strings.h> // for StringIds
#include <alg_test.h> // for InputIter
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define OpPlusEq(sig) StringIds::op_plus_eq_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// operator += (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, src, res, bthrow) \
{ __LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, src, \
sizeof src - 1, res, sizeof res - 1, bthrow }
// +----------------------------------------- controlled sequence
// | +----------------------- sequence to be appended
// | | +--------- expected result sequence
// | | | +---- exception info
// | | | | 0 - no exception
// | | | | 1 - length_error
// | | | |
// | | | +--------------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "<U0>", "", 0),
TEST ("", "abc", "abc", 0),
TEST ("<U0>", "", "<U0>", 0),
TEST ("<U0>", "a", "<U0>a", 0),
TEST ("<U0>", "<U0>@2", "<U0>", 0),
TEST ("ab", "cd", "abcd", 0),
TEST ("bcd", "a", "bcda", 0),
TEST ("cde", "ab", "cdeab", 0),
TEST ("abc", "", "abc", 0),
TEST ("ab", "c<U0>e", "abc", 0),
TEST ("<U0>@2ab", "cdefghij", "<U0>@2abcdefghij", 0),
TEST ("a<U0>@2b", "cdefghij", "a<U0>@2bcdefghij", 0),
TEST ("ab<U0>@2", "cdefghij", "ab<U0>@2cdefghij", 0),
TEST ("a<U0>b<U0>@2c", "e<U0>", "a<U0>b<U0>@2ce", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce", 0),
TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
TEST ("", "x@4096", "x@4096", 0),
TEST ("x@4096", "", "x@4096", 0),
TEST ("x@2048", "y@2048", "x@2048y@2048", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST ("", 0, "", 0),
TEST ("abc", 0, "abcabc", 0),
TEST ("a<U0>@2bc", 0, "a<U0>@2bca", 0),
TEST ("<U0>@2abc", 0, "<U0>@2abc", 0),
TEST ("abc<U0>@2", 0, "abc<U0>@2abc", 0),
TEST ("x@2048", 0, "x@4096", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// operator += (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, src, res, bthrow) \
{ __LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, src, \
sizeof src - 1, res, sizeof res - 1, bthrow }
// +----------------------------------------- controlled sequence
// | +----------------------- sequence to be appended
// | | +--------- expected result sequence
// | | | +---- exception info
// | | | | 0 - no exception
// | | | | 1 - length_error
// | | | |
// | | | +--------------+
// V V V V
TEST ("ab", "c", "abc", 0),
TEST ("", "", "", 0),
TEST ("", "<U0>", "<U0>", 0),
TEST ("", "abc", "abc", 0),
TEST ("<U0>", "", "<U0>", 0),
TEST ("<U0>", "a", "<U0>a", 0),
TEST ("<U0>", "<U0>@2", "<U0>@3", 0),
TEST ("ab", "cd", "abcd", 0),
TEST ("bcd", "a", "bcda", 0),
TEST ("cde", "ab", "cdeab", 0),
TEST ("abc", "", "abc", 0),
TEST ("ab", "c<U0>e", "abc<U0>e", 0),
TEST ("<U0>@2ab", "cdefghij", "<U0>@2abcdefghij", 0),
TEST ("a<U0>@2b", "cdefghij", "a<U0>@2bcdefghij", 0),
TEST ("ab<U0>@2", "cdefghij", "ab<U0>@2cdefghij", 0),
TEST ("a<U0>b<U0>@2c", "e<U0>", "a<U0>b<U0>@2ce<U0>", 0),
TEST ("<U0>ab<U0>@2c", "e<U0>", "<U0>ab<U0>@2ce<U0>", 0),
TEST ("ab<U0>@2c<U0>", "<U0>e", "ab<U0>@2c<U0>@2e", 0),
TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
TEST ("", "x@4096", "x@4096", 0),
TEST ("x@4096", "", "x@4096", 0),
TEST ("x@2048", "y@2048", "x@2048y@2048", 0),
TEST ("x@10", "x@118", "x@128", 0),
TEST ("x@128", "x@79", "x@207", 0),
TEST ("x@207", "x@127", "x@334", 0),
TEST ("x@334", "x@206", "x@540", 0),
TEST ("x@540", "x@333", "x@873", 0),
TEST ("x@539", "x@873", "x@1412", 0),
TEST ("x@872", "x@1412", "x@2284", 0),
TEST ("x@1411", "x@2284", "x@3695", 0),
TEST ("x@1412", "x@2284", "x@3696", 0),
TEST ("", 0, "", 0),
TEST ("abc", 0, "abcabc", 0),
TEST ("a<U0>@2bc", 0, "a<U0>@2bca<U0>@2bc", 0),
TEST ("<U0>@2abc", 0, "<U0>@2abc<U0>@2abc", 0),
TEST ("abc<U0>@2", 0, "abc<U0>@2abc<U0>@2", 0),
TEST ("x@2048", 0, "x@4096", 0),
TEST ("last", "test", "lasttest", 0)
};
/**************************************************************************/
// exercises:
// operator+= (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res, bthrow) \
{ __LINE__, -1, -1, -1, -1, val, str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, bthrow }
// +---------------------------------- controlled sequence
// | +----------------- character to be appended
// | | +------------- expected result sequence
// | | | +- exception info
// | | | | 0 - no exception
// | | | | 1 - length_error
// | | | |
// | | | +----+
// V V V V
TEST ("ab", 'c', "abc", 0),
TEST ("", 'a', "a", 0),
TEST ("", '\0', "<U0>", 0),
TEST ("<U0>", 'a', "<U0>a", 0),
TEST ("<U0>", '\0', "<U0>@2", 0),
TEST ("cde", 'a', "cdea", 0),
TEST ("abc", '\0', "abc<U0>", 0),
TEST ("a<U0>b<U0>@2c", '\0', "a<U0>b<U0>@2c<U0>", 0),
TEST ("<U0>ab<U0>@2c", '\0', "<U0>ab<U0>@2c<U0>", 0),
TEST ("a<U0>bc<U0>@2", 'a', "a<U0>bc<U0>@2a", 0),
TEST ("x@127", 'x', "x@128", 0),
TEST ("x@206", 'x', "x@207", 0),
TEST ("x@333", 'x', "x@334", 0),
TEST ("x@539", 'x', "x@540", 0),
TEST ("x@1411", 'x', "x@1412", 0),
TEST ("x@2283", 'x', "x@2284", 0),
TEST ("x@3694", 'x', "x@3695", 0),
TEST ("x@540", 'x', "x@541", 0),
TEST ("last", 't', "lastt", 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_op_plus_eq (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename String::iterator StringIter;
typedef typename UserTraits<charT>::MemFun UTMemFun;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
static charT wres_buf [BUFSIZE];
std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
// construct the string object to be modified
// and the (possibly unused) argument string
/* const */ String str (wstr, str_len);
const String arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
const charT* const arg_ptr = tcase.arg ? arg.c_str () : str.c_str ();
const String& arg_str = tcase.arg ? arg : str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t total_length_calls = 0;
std::size_t n_length_calls = 0;
std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls)
total_length_calls = rg_calls [UTMemFun::length];
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (1 == tcase.bthrow)
expected = exceptions [2]; // length_error
else if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
else {
// exceptions disabled for this test case
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
// start checking for memory leaks
rw_check_leaks (str.get_allocator ());
try {
// pointer to the returned reference
const String* ret_ptr = 0;
switch (func.which_) {
case OpPlusEq (cptr):
ret_ptr = &str.operator+= (arg_ptr);
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpPlusEq (cstr):
ret_ptr = &str.operator+= (arg_str);
break;
case OpPlusEq (val):
ret_ptr = &str.operator+= (arg_val);
break;
default:
RW_ASSERT ("test logic error: unknown operator += overload");
return;
}
// verify that the reference returned from the function
// refers to the modified string object (i.e., *this
// within the function)
const std::ptrdiff_t ret_off = ret_ptr - &str;
// verify the returned value
rw_assert (0 == ret_off, 0, tcase.line,
"line %d. %{$FUNCALL} returned invalid reference, "
"offset is %td", __LINE__, ret_off);
// verfiy that strings length are equal
rw_assert (res_len == str.size (), 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s} "
"with length %zu, got %{/*.*Gs} with length %zu",
__LINE__, int (tcase.nres), tcase.res, res_len,
int (sizeof (charT)), int (str.size ()),
str.c_str (), str.size ());
if (res_len == str.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the modified
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, str.c_str(), str.size ());
rw_assert (match == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (str.size ()),
str.c_str (), match);
}
// verify that Traits::length was used
if (OpPlusEq (cptr) == func.which_ && rg_calls) {
rw_assert (n_length_calls - total_length_calls > 0,
0, tcase.line, "line %d. %{$FUNCALL} doesn't "
"use traits::length()", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::length_error &ex) {
caught = exceptions [2];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::bad_alloc &ex) {
caught = exceptions [3];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
// verify that if exceptions are enabled and when capacity changes
// at least one exception is thrown
const std::size_t expect_throws = str_state.capacity_ < str.capacity ();
#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
const std::size_t expect_throws =
(StringIds::UserAlloc == func.alloc_id_)
? str_state.capacity_ < str.capacity (): 0;
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
rw_assert (expect_throws == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected exactly 1 %s exception "
"while changing capacity from %zu to %zu, got %zu",
__LINE__, exceptions [3],
str_state.capacity_, str.capacity (), throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
if (wres != wres_buf)
delete[] wres;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_op_plus_eq);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
OpPlusEq (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (val)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.op+=",
test_op_plus_eq, tests, test_count);
}

View File

@@ -0,0 +1,630 @@
/***************************************************************************
*
* 21.string.operators.cpp - test exercising [lib.string.nonmembers]
* except lib.string::op+ and lib.string.io
*
* $Id: 21.string.operators.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <stdexcept> // for out_of_range, length_error
#include <cstddef> // for size_t
#include <21.strings.h> // for StringMembers
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define OpEqual(which) StringIds::op_equal_ ## which
#define OpNotEqual(which) StringIds::op_not_equal_ ## which
#define OpLess(which) StringIds::op_less_ ## which
#define OpLessEqual(which) StringIds::op_less_equal_ ## which
#define OpGreater(which) StringIds::op_greater_ ## which
#define OpGreaterEqual(which) StringIds::op_greater_equal_ ## which
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// operator == (const value_type*, const basic_string&)
// operator != (const value_type*, const basic_string&)
// operator < (const value_type*, const basic_string&)
// operator <= (const value_type*, const basic_string&)
// operator > (const value_type*, const basic_string&)
// operator >= (const value_type*, const basic_string&)
static const StringTestCase
cptr_cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, sizeof arg - 1, \
0, (std::size_t) res, 0 \
}
// +----------------------------------------- first sequence
// | +----------------------- second sequence
// | | +---- expected result
// | | | -1 - first is less
// | | | 0 - equal
// | | | 1 - first is greater
// | | |
// | | |
// V V V
TEST ("ab", "c", -1),
TEST ("", "", 0),
TEST ("", "a", -1),
TEST ("a", "", 1),
TEST ("a", "a", 0),
TEST ("<U0>", "", 0),
TEST ("", "<U0>", -1),
TEST ("<U0>", "<U0>", -1),
TEST ("abcdefgjih", "abcdefgji", 1),
TEST ("abcdefgjih", "abcdefgjih", 0),
TEST ("abcdefgji", "abcdefgjih", -1),
TEST ("abcefgjih", "abcdefgjih", 1),
TEST ("abcdefgjih", "abcefgjih", -1),
TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2c", -1),
TEST ("ab<U0>@2c<U0>", "ab", 0),
TEST ("e<U0>", "ab<U0>@2c<U0>", 1),
TEST ("x@2048", "x@2048", 0),
TEST ("x@2048", "x@2049", -1),
TEST ("x@2048", "x@2047", 1),
TEST ("a@2048", "b@2048", -1),
TEST ("b@2048", "a@2048", 1),
TEST ("a@2048<U0>", "a@2048", 0),
TEST ("a@2048", "a@2048<U0>", -1),
TEST ("x@128", "x@207", -1),
TEST ("x@334", "x@334", 0),
TEST ("x@873", "x@540", 1),
TEST ("x@1412", "x@2284", -1),
TEST ("x@3695", "x@3695", 0),
TEST ("x@4096", "x@3695", 1),
TEST (0, "abc", 0),
TEST (0, "<U0>ab<U0>", -1),
TEST (0, "x@2048", 0),
TEST ("last", "last", 0)
};
/**************************************************************************/
// exercises:
// operator == (const basic_string&, const basic_string&)
// operator != (const basic_string&, const basic_string&)
// operator < (const basic_string&, const basic_string&)
// operator <= (const basic_string&, const basic_string&)
// operator > (const basic_string&, const basic_string&)
// operator >= (const basic_string&, const basic_string&)
static const StringTestCase
cstr_cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, sizeof arg - 1, \
0, (std::size_t) res, 0 \
}
// +----------------------------------------- first sequence
// | +----------------------- second sequence
// | | +---- expected result
// | | | -1 - first is less
// | | | 0 - equal
// | | | 1 - first is greater
// | | |
// | | |
// V V V
TEST ("ab", "c", -1),
TEST ("", "", 0),
TEST ("", "a", -1),
TEST ("a", "", 1),
TEST ("a", "a", 0),
TEST ("<U0>", "", 1),
TEST ("", "<U0>", -1),
TEST ("<U0>", "<U0>", 0),
TEST ("abcdefgjih", "abcdefgji", 1),
TEST ("abcdefgjih", "abcdefgjih", 0),
TEST ("abcdefgji", "abcdefgjih", -1),
TEST ("abcefgjih", "abcdefgjih", 1),
TEST ("abcdefgjih", "abcefgjih", -1),
TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2c", 0),
TEST ("ab<U0>@2c<U0>", "<U0>ab<U0>@2c", 1),
TEST ("ab<U0>@2c<U0>", "ab<U0>@2c<U0>", 0),
TEST ("ab<U0>@2c<U0>", "ab", 1),
TEST ("ab", "ab<U0>@2c<U0>", -1),
TEST ("ab<U0>@3", "ab<U0>@2c<U0>", -1),
TEST ("ab<U0>@3", "ab<U0>@3", 0),
TEST ("e<U0>", "ab<U0>@2c<U0>", 1),
TEST ("ab<U0>@2c<U0>", "e<U0>", -1),
TEST ("x@2048", "x@2048", 0),
TEST ("x@2048", "x@2049", -1),
TEST ("x@2048", "x@2047", 1),
TEST ("a@2048", "b@2048", -1),
TEST ("b@2048", "a@2048", 1),
TEST ("<U0>a@2048", "a@2048<U0>", -1),
TEST ("a@2048<U0>", "<U0>a@2048", 1),
TEST ("a@2048<U0>", "a@2048", 1),
TEST ("a@2048", "a@2048<U0>", -1),
TEST ("a@2048<U0>", "a@2048<U0>", 0),
TEST ("x@128", "x@207", -1),
TEST ("x@334", "x@334", 0),
TEST ("x@873", "x@540", 1),
TEST ("x@1412", "x@2284", -1),
TEST ("x@3695", "x@3695", 0),
TEST ("x@4096", "x@3695", 1),
TEST (0, "abc", 0),
TEST (0, "<U0>ab<U0>", 0),
TEST (0, "x@2048", 0),
TEST ("abc", 0, 0),
TEST ("<U0>ab<U0>", 0, 0),
TEST ("x@2048", 0, 0),
TEST ("last", "last", 0)
};
/**************************************************************************/
// exercises:
// operator == (const basic_string&, const value_type*)
// operator != (const basic_string&, const value_type*)
// operator < (const basic_string&, const value_type*)
// operator <= (const basic_string&, const value_type*)
// operator > (const basic_string&, const value_type*)
// operator >= (const basic_string&, const value_type*)
static const StringTestCase
cstr_cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, sizeof arg - 1, \
0, (std::size_t) res, 0 \
}
// +----------------------------------------- first sequence
// | +----------------------- second sequence
// | | +---- expected result
// | | | -1 - first is less
// | | | 0 - equal
// | | | 1 - first is greater
// | | |
// | | |
// V V V
TEST ("ab", "c", -1),
TEST ("", "", 0),
TEST ("", "a", -1),
TEST ("a", "", 1),
TEST ("a", "a", 0),
TEST ("<U0>", "", 1),
TEST ("", "<U0>", 0),
TEST ("<U0>", "<U0>", 1),
TEST ("abcdefgjih", "abcdefgji", 1),
TEST ("abcdefgjih", "abcdefgjih", 0),
TEST ("abcdefgji", "abcdefgjih", -1),
TEST ("abcefgjih", "abcdefgjih", 1),
TEST ("abcdefgjih", "abcefgjih", -1),
TEST ("<U0>ab<U0>@2c", "<U0>ab<U0>@2c", 1),
TEST ("ab", "ab<U0>@2c<U0>", 0),
TEST ("e<U0>", "ab<U0>@2c<U0>", 1),
TEST ("ab<U0>@2c<U0>", "e<U0>", -1),
TEST ("x@2048", "x@2048", 0),
TEST ("x@2048", "x@2049", -1),
TEST ("x@2048", "x@2047", 1),
TEST ("a@2048", "b@2048", -1),
TEST ("b@2048", "a@2048", 1),
TEST ("a@2048", "a@2048<U0>", 0),
TEST ("a@2048<U0>", "a@2048<U0>", 1),
TEST ("x@128", "x@207", -1),
TEST ("x@334", "x@334", 0),
TEST ("x@873", "x@540", 1),
TEST ("x@1412", "x@2284", -1),
TEST ("x@3695", "x@3695", 0),
TEST ("x@4096", "x@3695", 1),
TEST ("abc", 0, 0),
TEST ("<U0>ab<U0>", 0, 1),
TEST ("x@2048", 0, 0),
TEST ("last", "last", 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_operators (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef typename UserTraits<charT>::MemFun UTMemFun;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object to be modified
// and the (possibly unused) argument string
/* const */ String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
const charT* const arg1_ptr = tcase.str ? s_str.c_str () : s_arg.c_str ();
const String& arg1_str = tcase.str ? s_str : s_arg;
const charT* const arg2_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg2_str = tcase.arg ? s_arg : s_str;
std::size_t total_length_calls = 0;
std::size_t n_length_calls = 0;
std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls)
total_length_calls = rg_calls [UTMemFun::length];
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_after' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
// (name of) expected and caught exception
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
else {
// exceptions disabled for this test case
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
try {
bool res = false;
switch (func.which_) {
// exercise cptr_cstr cases
case OpEqual (cptr_cstr):
res = arg1_ptr == arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpNotEqual (cptr_cstr):
res = arg1_ptr != arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpLess (cptr_cstr):
res = arg1_ptr < arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpLessEqual (cptr_cstr):
res = arg1_ptr <= arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpGreater (cptr_cstr):
res = arg1_ptr > arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpGreaterEqual (cptr_cstr):
res = arg1_ptr >= arg2_str;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
// exercise cstr_cstr cases
case OpEqual (cstr_cstr):
res = arg1_str == arg2_str;
break;
case OpNotEqual (cstr_cstr):
res = arg1_str != arg2_str;
break;
case OpLess (cstr_cstr):
res = arg1_str < arg2_str;
break;
case OpLessEqual (cstr_cstr):
res = arg1_str <= arg2_str;
break;
case OpGreater (cstr_cstr):
res = arg1_str > arg2_str;
break;
case OpGreaterEqual (cstr_cstr):
res = arg1_str >= arg2_str;
break;
// exercise cstr_cptr cases
case OpEqual (cstr_cptr):
res = arg1_str == arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpNotEqual (cstr_cptr):
res = arg1_str != arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpLess (cstr_cptr):
res = arg1_str < arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpLessEqual (cstr_cptr):
res = arg1_str <= arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpGreater (cstr_cptr):
res = arg1_str > arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
case OpGreaterEqual (cstr_cptr):
res = arg1_str >= arg2_ptr;
if (rg_calls)
n_length_calls = rg_calls [UTMemFun::length];
break;
default:
RW_ASSERT ("test logic error: unknown operator overload");
return;
}
// form the expected result
bool exp_res = false;
switch (StringIds::fid_mask & int (func.which_)) {
case StringIds::fid_op_equal:
exp_res = 0 == tcase.nres;
break;
case StringIds::fid_op_not_equal:
exp_res = 0 != tcase.nres;
break;
case StringIds::fid_op_less:
exp_res = NPOS == tcase.nres;
break;
case StringIds::fid_op_less_equal:
exp_res = 1 != tcase.nres;
break;
case StringIds::fid_op_greater:
exp_res = 1 == tcase.nres;
break;
case StringIds::fid_op_greater_equal:
exp_res = NPOS != tcase.nres;
break;
}
// verify the result
rw_assert (res == exp_res, 0, tcase.line,
"line %d. %{$FUNCALL} expected %b, got %b",
__LINE__, exp_res, res);
// verify that Traits::length was used
std::size_t exp_len_used =
(StringIds::arg_cstr << int (StringIds::fid_bits))
| (StringIds::arg_cstr << int (StringIds::arg_bits)
<< int (StringIds::fid_bits));
std::size_t verlen =
func.which_ & ~StringIds::fid_mask & ~exp_len_used;
if (verlen && rg_calls) {
rw_assert (n_length_calls - total_length_calls > 0,
0, tcase.line, "line %d. %{$FUNCALL} doesn't "
"use traits::length()", __LINE__);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::bad_alloc &ex) {
caught = exceptions [3];
rw_assert (0 == tcase.bthrow, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
const std::size_t expect_throws = 0;
rw_assert (expect_throws == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected no %s exceptions, got %zu",
__LINE__, exceptions [3], throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_operators);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(oper, tag) { \
StringIds::op_ ## oper ## _ ## tag, tag ## _test_cases, \
sizeof tag ## _test_cases / sizeof *tag ## _test_cases \
}
TEST (equal, cptr_cstr),
TEST (equal, cstr_cptr),
TEST (equal, cstr_cstr),
TEST (not_equal, cptr_cstr),
TEST (not_equal, cstr_cptr),
TEST (not_equal, cstr_cstr),
TEST (less, cptr_cstr),
TEST (less, cstr_cptr),
TEST (less, cstr_cstr),
TEST (less_equal, cptr_cstr),
TEST (less_equal, cstr_cptr),
TEST (less_equal, cstr_cstr),
TEST (greater, cptr_cstr),
TEST (greater, cstr_cptr),
TEST (greater, cstr_cstr),
TEST (greater_equal, cptr_cstr),
TEST (greater_equal, cstr_cptr),
TEST (greater_equal, cstr_cstr)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.nonmembers",
test_operators, tests, test_count);
}

View File

@@ -0,0 +1,151 @@
/***************************************************************************
*
* 21.string.push.back.mt.cpp - test exercising the therad safety
* of the push_back member function
*
* $Id: 21.string.push_back.mt.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2005-2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for size_t
#include <driver.h> // for rw_test()
#include <rw_thread.h> // for rw_thread_pool(), ...
#include <valcmp.h> // for rw_strncmp()
/**************************************************************************/
#define MAX_THREADS 32
#define MAX_LOOPS 100000
const char to_append [] = {
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
};
const std::string shared0;
const std::string shared1 (64, '_');
/**************************************************************************/
#ifdef _RWSTD_REENTRANT
int rw_opt_nthreads = 4;
#else // if !defined (_RWSTD_REENTRANT)
// in non-threaded builds use just one thread
int rw_opt_nthreads = 1;
#endif // _RWSTD_REENTRANT
int rw_opt_nloops = MAX_LOOPS;
extern "C" {
static void*
thread_func (void *arg)
{
const rw_thread_t* const pthread = (rw_thread_t*)arg;
// compute an index unique to this thread
const std::size_t thr_inx = std::size_t (pthread->threadno) % MAX_THREADS;
RW_ASSERT (thr_inx < sizeof to_append);
// compute the expected strings unique to this thread
const std::string expect0 = shared0 + to_append [thr_inx];
const std::string expect1 = shared1 + to_append [thr_inx];
// get the data pointer and the length of each string
// in order to avoid referencin the string objects below
const char* const expect0_data = expect0.data ();
const std::size_t expect0_len = expect0.length ();
const char* const expect1_data = expect1.data ();
const std::size_t expect1_len = expect1.length ();
for (std::size_t i = 0; i != std::size_t (rw_opt_nloops); ++i) {
// create copies of global strings
std::string local0 (shared0);
std::string local1 (shared1);
// modify the local copies
local0.push_back (to_append [thr_inx]);
local1.push_back (to_append [thr_inx]);
// verify that the local copies have the expected length
RW_ASSERT (expect0_len == local0.length ());
RW_ASSERT (expect1_len == local1.length ());
// verify that the local copies have the expected data
RW_ASSERT (0 == rw_strncmp (expect0_data, local0.data ()));
RW_ASSERT (0 == rw_strncmp (expect1_data, local1.data ()));
}
return 0;
}
} // extern "C"
/**************************************************************************/
static int
run_test (int, char**)
{
rw_info (0, 0, 0, "running %d thread%{?}s%{;}, %d iteration%{?}s%{;} each",
rw_opt_nthreads, 1 != rw_opt_nthreads,
rw_opt_nloops, 1 != rw_opt_nloops);
// create and start a pool of threads and wait for them to finish
const int result = rw_thread_pool (0, std::size_t (rw_opt_nthreads),
0, thread_func, 0);
rw_error (result == 0, 0, __LINE__,
"rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
rw_opt_nthreads, thread_func);
rw_assert (0 == shared0.size (), 0, 0,
"shared empty string modifed: expected \"\", got %{#S}",
&shared0);
const std::string expect (64, '_');
rw_assert (64 == shared1.size () && std::string (64, '_') == shared1,
0, 0, "shared non-empty string modifed: "
"expected %{#S}, got %{#S}",
&expect, &shared1);
return result;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.string.push_back",
"thread safety", run_test,
"|-nloops#0 " // must be non-negative
"|-nthreads#0-*", // must be in [0, MAX_THREADS]
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,786 @@
/***************************************************************************
*
* 21.string.rfind.cpp - string test exercising lib.string.rfind
*
* $Id: 21.string.rfind.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstdlib> // for free(), size_t
#include <exception> // for exception
#include <21.strings.h> // for StringIds
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define RFind(sig) StringIds::rfind_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// rfind (const value_type*)
static const StringTestCase
cptr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +----------------------------------- controlled sequence
// | +--------------------- sequence to be found
// | | +---- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", 0),
TEST ("", "\0", 0),
TEST ("", "a", NPOS),
TEST ("\0", "", 1),
TEST ("\0", "\0", 1),
TEST ("\0", "a", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", NPOS),
TEST ("edfcbahjig", "cba", 3),
TEST ("edfcbahcba", "cba", 7),
TEST ("cbacbahjig", "cba", 3),
TEST ("e\0cb\0\0g", "b\0\0g", 3),
TEST ("e\0cb\0\0g", "ecb", NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 7),
TEST ("\0cb\0\0ge", "cb\0", 1),
TEST ("e\0cbg\0\0", "bg", 3),
TEST ("e\0cbg\0\0", "cba", NPOS),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 6),
TEST ("bcedfaajih", "a", 6),
TEST ("bcaaedfaji", "a", 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0),
TEST ("aaaaabaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaaabaaaa", "aaaaa", 0),
TEST ("aaaabaaaaa", "aaaaa", 5),
TEST ("aaaabaaaaa", "aaaa", 6),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 1),
TEST ("aaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", 4096),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 4095),
TEST ("x@4096", "xxx", 4093),
TEST ("x@4096", "xxa", NPOS),
TEST ("abc", "x@4096", NPOS),
TEST ("xxxxxxxxxx", "x@4096", NPOS),
TEST ("abcdefghij", 0, 0),
TEST ("\0cb\0\0ge", 0, 7),
TEST ("x@4096", 0, 0),
TEST ("last test", "test", 5)
};
/**************************************************************************/
// used to exercise
// rfind (const basic_string&)
static const StringTestCase
cstr_test_cases [] = {
#undef TEST
#define TEST(str, arg, res) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +------------------------------------ controlled sequence
// | +---------------------- sequence to be found
// | | +----- expected result
// | | |
// | | |
// V V V
TEST ("ab", "a", 0),
TEST ("", "", 0),
TEST ("", "\0", NPOS),
TEST ("", "a", NPOS),
TEST ("\0", "", 1),
TEST ("\0", "\0", 0),
TEST ("\0", "\0\0", NPOS),
TEST ("\0", "a", NPOS),
TEST ("\0a", "a\0", NPOS),
TEST ("bbcdefghij", "a", NPOS),
TEST ("abcdefghij", "a", 0),
TEST ("abcdefghij", "f", 5),
TEST ("abcdefghij", "j", 9),
TEST ("edfcbbhjig", "cba", NPOS),
TEST ("edfcbahjig", "cba", 3),
TEST ("edfcbahcba", "cba", 7),
TEST ("cbacbahjig", "cba", 3),
TEST ("e\0cb\0\0g", "b\0\0g", 3),
TEST ("e\0cb\0\0g", "ecb", NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 3),
TEST ("\0cb\0\0ge", "cb\0", 1),
TEST ("\0cb\0\0ge", "cb\0a", NPOS),
TEST ("e\0cbg\0\0", "bg", 3),
TEST ("e\0cbg\0\0", "\0\0", 5),
TEST ("\0\0cg\0\0", "\0\0", 4),
TEST ("e\0cbg\0\0", "\0\0a", NPOS),
TEST ("e\0cbg\0\0", "cba", NPOS),
TEST ("bcbedfbjih", "a", NPOS),
TEST ("bcaedfajih", "a", 6),
TEST ("bcedfaajih", "a", 6),
TEST ("bcaaedfaji", "a", 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0),
TEST ("aaaaabaaaa", "aaaaaaaaaa", NPOS),
TEST ("aaaabaaaaa", "aaaaa", 5),
TEST ("aaaaabaaaa", "aaaa", 6),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 1),
TEST ("aaaaaaaaa", "aaaaaaaaaa", NPOS),
TEST ("x@4096", "", 4096),
TEST ("x@4096", "a", NPOS),
TEST ("x@4096", "x", 4095),
TEST ("x@4096", "xxx", 4093),
TEST ("x@4096", "xxa", NPOS),
TEST ("abc", "x@4096", NPOS),
TEST ("xxxxxxxxxx", "x@4096", NPOS),
TEST ("abcdefghij", 0, 0),
TEST ("\0cb\0\0ge", 0, 0),
TEST ("x@4096", 0, 0),
TEST ("last test", "test", 5)
};
/**************************************************************************/
// used to exercise
// rfind (const value_type*, size_type)
static const StringTestCase
cptr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +-------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +--------- rfind() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, 0),
TEST ("", "\0", 0, 0),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "", 1, 1),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, 1),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 2, 0),
TEST ("abcdefghij", "f", 2, NPOS),
TEST ("abcdefghij", "f", 7, 5),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 0, NPOS),
TEST ("edfcbahjig", "cba", 1, NPOS),
TEST ("edfcbahjig", "cba", 5, 3),
TEST ("edfcbahcba", "cba", 1, NPOS),
TEST ("edfcbahcba", "cba", 9, 7),
TEST ("edfcbahcba", "cba", 5, 3),
TEST ("cbacbahjig", "cba", 5, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 5, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 4, 3),
TEST ("e\0cb\0\0g", "ecb", 7, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 6),
TEST ("\0cb\0\0ge", "cb\0", 0, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 1, 1),
TEST ("\0cb\0\0ge", "cb\0", 2, 1),
TEST ("e\0cbg\0\0", "bg", 1, NPOS),
TEST ("e\0cbg\0\0", "bg", 5, 3),
TEST ("e\0cbg\0\0", "cba", 7, NPOS),
TEST ("bcbedfbjih", "a", 0, NPOS),
TEST ("bcaedfajih", "a", 8, 6),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 8, 7),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 8, 0),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 9, NPOS),
TEST ("aaaabaaaaa", "aaaaa", 9, 5),
TEST ("aaaabaaaaa", "aaaaa", 6, 5),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 9, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 8, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 7, 1),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 8, NPOS),
TEST ("x@4096", "", 4096, 4096),
TEST ("x@4096", "a", 0, NPOS),
TEST ("x@4096", "x", 4096, 4095),
TEST ("x@4096", "xxx", 4095, 4093),
TEST ("x@4096", "xxx", 0, 0),
TEST ("x@4096", "xxx", 4087, 4087),
TEST ("x@4096", "xxa", 4087, NPOS),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 6, NPOS),
TEST ("x@4096", "xxx", 3, 3),
TEST ("x@4096", "xxx", 2, 2),
TEST ("abcdefghij", 0, 0, 0),
TEST ("abcdefghij", 0, 1, 0),
TEST ("\0cb\0\0ge", 0, 5, 5),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 1, 0),
TEST ("", "", 1, 0),
TEST ("abcdefghij", "abc", 10, 0),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 9, 5)
};
/**************************************************************************/
// used to exercise
// rfind (const value_type*, size_type, size_type)
static const StringTestCase
cptr_size_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, size, res) { \
__LINE__, off, size, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +-------------------------- sequence to be found
// | | +---------- rfind() off argument
// | | | +------ rfind() n argument
// | | | | +-- expected result
// | | | | |
// | | | | |
// V V V V V
TEST ("ab", "a", 0, 1, 0),
TEST ("", "", 0, 0, 0),
TEST ("", "\0", 0, 0, 0),
TEST ("", "\0", 0, 1, NPOS),
TEST ("", "a", 0, 0, 0),
TEST ("", "a", 0, 1, NPOS),
TEST ("\0", "", 0, 0, 0),
TEST ("\0", "\0", 0, 1, 0),
TEST ("\0", "\0", 1, 1, 0),
TEST ("\0\0", "\0\0", 1, 1, 1),
TEST ("\0", "a", 0, 1, NPOS),
TEST ("edfcbbhjig", "cba", 0, 3, NPOS),
TEST ("edfcbbhjig", "cba", 0, 2, NPOS),
TEST ("edfcbbhjig", "cba", 9, 2, 3),
TEST ("edfcbahjig", "cba", 8, 3, 3),
TEST ("edfcbahjig", "cba", 2, 3, NPOS),
TEST ("edfcbahjig", "cba", 2, 1, NPOS),
TEST ("edfcbahcba", "cba", 8, 3, 7),
TEST ("edfcbehcba", "cba", 8, 2, 7),
TEST ("edfcbahcba", "cba", 9, 3, 7),
TEST ("cbacbahjig", "cba", 5, 3, 3),
TEST ("cbacbahjig", "cba", 2, 3, 0),
TEST ("cbacbahjcg", "cba", 2, 1, 0),
TEST ("e\0cb\0\0g", "b\0\0g", 0, 4, NPOS),
TEST ("e\0cb\0\0g", "b\0\0g", 7, 4, 3),
TEST ("e\0cb\0\0b", "b\0\0g", 4, 1, 3),
TEST ("\0b\0\0gb\0","b\0\0g", 7, 2, 5),
TEST ("\0b\0\0gb\0","b\0\0g", 2, 2, 1),
TEST ("\0b\0\0gb\0","b\0\0g", 7, 3, 1),
TEST ("e\0cb\0\0g", "ecb", 7, 2, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 4, 3),
TEST ("\0cb\0\0ge", "\0\0ge", 2, 0, 2),
TEST ("\0cb\0\0ge", "cb\0", 1, 3, 1),
TEST ("e\0cbg\0\0", "bg", 1, 2, NPOS),
TEST ("e\0cbg\0\0", "cba", 7, 3, NPOS),
TEST ("e\0cbg\0\0", "cba", 7, 2, 2),
TEST ("e\0a\0", "e\0a\0\0", 3, 4, 0),
TEST ("e\0a\0", "e\0a\0\0", 3, 5, NPOS),
TEST ("ee\0a\0", "e\0a\0\0", 4, 4, 1),
TEST ("ee\0a\0", "e\0a\0\0", 4, 5, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, 10, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, 10, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 1, 9, 1),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 0, 10, NPOS),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 1, 4, 1),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 7, 4, 6),
TEST ("aaaabaaaaa", "aaaaa", 0, 5, NPOS),
TEST ("aaaabaaaaa", "aaaaa", 0, 4, 0),
TEST ("aaaabaaaaa", "aaaaa", 6, 5, 5),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0, 9, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 1, 9, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 2, 9, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 7, 8, 2),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 9, 10, NPOS),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 8, 7, 2),
TEST ("x@4096", "", 4096, 0, 4096),
TEST ("x@4096", "a", 4096, 1, NPOS),
TEST ("x@4096", "x", 4096, 1, 4095),
TEST ("x@4096", "xxx", 4087, 3, 4087),
TEST ("x@4096", "xxa", 4087, 3, NPOS),
TEST ("x@4096", "xxa", 4096, 2, 4094),
TEST ("abc", "x@4096", 2, 10, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 0, 4096, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 2, 4, 2),
TEST ("x@4096", "xxx", 4093, 3, 4093),
TEST ("x@4096", "xxx", 4094, 3, 4093),
TEST ("x@4096", "xxx", 4094, 2, 4094),
TEST ("abcdefghij", 0, 0, 9, 0),
TEST ("abcdefghij", 0, 1, 9, 0),
TEST ("\0cb\0\0ge", 0, 5, 7, 0),
TEST ("\0cb\0ge\0", 0, 6, 1, 6),
TEST ("x@4096", 0, 0, 4096, 0),
TEST ("x@4096", 0, 1, 4096, 0),
TEST ("x@4096", 0, 5, 4091, 5),
TEST ("", "", 1, 0, 0),
TEST ("abcdefghij", "abc", 10, 3, 0),
TEST ("abcdefghij", "cba", 10, 1, 2),
// exercised invalid arguments (undefined behavior)
TEST ("", "cba", 0, -1, NPOS),
TEST ("abcdefghij", "cba", 0, -1, NPOS),
TEST ("x@4096", "xxx", 0, -1, NPOS),
TEST ("abcdefghij", "x@4096", 0, -1, NPOS),
TEST ("last test", "test", 9, 4, 5)
};
/**************************************************************************/
// used to exercise
// rfind (const basic_string&, size_type)
static const StringTestCase
cstr_size_test_cases [] = {
#undef TEST
#define TEST(str, arg, off, res) \
{ __LINE__, off, -1, -1, -1, -1, \
str, sizeof str - 1, arg, \
sizeof arg - 1, 0, res, 0 \
}
// +--------------------------------------- controlled sequence
// | +------------------------- sequence to be found
// | | +---------- rfind() off argument
// | | | +---- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", "a", 0, 0),
TEST ("", "", 0, 0),
TEST ("", "\0", 0, NPOS),
TEST ("", "a", 0, NPOS),
TEST ("\0", "", 0, 0),
TEST ("\0", "\0", 0, 0),
TEST ("\0", "\0", 1, 0),
TEST ("\0\0", "\0", 2, 1),
TEST ("\0", "a", 0, NPOS),
TEST ("bbcdefghij", "a", 0, NPOS),
TEST ("abcdefghij", "a", 0, 0),
TEST ("abcdefghij", "a", 9, 0),
TEST ("abcdefghij", "f", 2, NPOS),
TEST ("abcdefghij", "f", 7, 5),
TEST ("abcdefghij", "j", 9, 9),
TEST ("edfcbbhjig", "cba", 9, NPOS),
TEST ("edfcbahjig", "cba", 1, NPOS),
TEST ("edfcbahjig", "cba", 4, 3),
TEST ("edfcbahcba", "cba", 9, 7),
TEST ("edfcbahcba", "cba", 6, 3),
TEST ("cbacbahjig", "cba", 5, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 7, 3),
TEST ("e\0cb\0\0g", "b\0\0g", 2, NPOS),
TEST ("e\0cb\0\0g", "ecb", 7, NPOS),
TEST ("\0cb\0\0ge", "\0\0ge", 6, 3),
TEST ("\0cb\0\0ge", "\0\0ge", 1, NPOS),
TEST ("\0cb\0\0ge", "cb\0", 2, 1),
TEST ("\0cbg\0\0e", "cb\0", 0, NPOS),
TEST ("e\0cbg\0\0", "bg", 6, 3),
TEST ("e\0cbg\0\0", "cba", 7, NPOS),
TEST ("bcbedfbjih", "a", 9, NPOS),
TEST ("bcaedfajih", "a", 9, 6),
TEST ("bcedfaajih", "a", 6, 6),
TEST ("bcaaedfaji", "a", 5, 3),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 0, 0),
TEST ("aaaaaaaaaa", "aaaaaaaaaa", 9, 0),
TEST ("aaaaabaaaa", "aaaaaaaaaa", 9, NPOS),
TEST ("aaaabaaaaa", "aaaaa", 9, 5),
TEST ("aaaabaaaaa", "aaaaa", 3, NPOS),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 9, 1),
TEST ("aaaaaaaaaa", "aaaaaaaaa", 0, 0),
TEST ("aaaaaaaaa", "aaaaaaaaaa", 8, NPOS),
TEST ("x@4096", "", 4096, 4096),
TEST ("x@4096", "a", 4096, NPOS),
TEST ("x@4096", "x", 4096, 4095),
TEST ("x@4096", "xxx", 4087, 4087),
TEST ("x@4096", "xxa", 4087, NPOS),
TEST ("abc", "x@4096", 2, NPOS),
TEST ("xxxxxxxxxx", "x@4096", 4096, NPOS),
TEST ("x@4096", "xxx", 4096, 4093),
TEST ("x@4096", "xxx", 4091, 4091),
TEST ("abcdefghij", 0, 9, 0),
TEST ("abcdefghij", 0, 1, 0),
TEST ("\0cb\0\0ge", 0, 5, 0),
TEST ("x@4096", 0, 0, 0),
TEST ("x@4096", 0, 1, 0),
TEST ("", "", 1, 0),
TEST ("abcdefghij", "abc", 10, 0),
TEST ("abcdefghij", "cba", 10, NPOS),
TEST ("last test", "test", 9, 5)
};
/**************************************************************************/
// used to exercise
// rfind (value_type)
static const StringTestCase
val_test_cases [] = {
#undef TEST
#define TEST(str, val, res) \
{ __LINE__, -1, -1, -1, -1, val, \
str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +----------------------------- controlled sequence
// | +-------------- character to be found
// | | +------ expected result
// | | |
// | | |
// V V V
TEST ("ab", 'a', 0),
TEST ("", 'a', NPOS),
TEST ("", '\0', NPOS),
TEST ("\0", '\0', 0),
TEST ("\0\0", '\0', 1),
TEST ("\0", 'a', NPOS),
TEST ("e\0cb\0\0g", '\0', 5),
TEST ("e\0cb\0\0g", 'b', 3),
TEST ("e\0cb\0\0g", 'a', NPOS),
TEST ("\0cbge\0\0", '\0', 6),
TEST ("\0cbge\0\0", 'b', 2),
TEST ("\0cbge\0\0", 'a', NPOS),
TEST ("x@4096", 'x', 4095),
TEST ("x@4096", '\0', NPOS),
TEST ("x@4096", 'a', NPOS),
TEST ("last test", 't', 8)
};
/**************************************************************************/
// used to exercise
// rfind (value_type, size_type)
static const StringTestCase
val_size_test_cases [] = {
#undef TEST
#define TEST(str, val, off, res) \
{ __LINE__, off, -1, -1, -1, val, \
str, sizeof str - 1, \
0, 0, 0, res, 0 \
}
// +------------------------------ controlled sequence
// | +--------------- character to be found
// | | +--------- rfind() off argument
// | | | +--- expected result
// | | | |
// | | | |
// V V V V
TEST ("ab", 'a', 0, 0),
TEST ("", 'a', 0, NPOS),
TEST ("", '\0', 0, NPOS),
TEST ("\0", '\0', 1, 0),
TEST ("\0", 'a', 0, NPOS),
TEST ("\0\0", '\0', 2, 1),
TEST ("\0\0", 'a', 3, NPOS),
TEST ("\0\0", '\0', 3, 1),
TEST ("e\0cb\0\0g", '\0', 1, 1),
TEST ("e\0cb\0\0g", '\0', 5, 5),
TEST ("e\0cb\0\0g", '\0', 0, NPOS),
TEST ("e\0cb\0\0g", 'b', 1, NPOS),
TEST ("e\0cb\0\0g", 'b', 4, 3),
TEST ("e\0cb\0\0g", 'a', 6, NPOS),
TEST ("\0cbge\0\0", '\0', 0, 0),
TEST ("\0cbge\0\0", '\0', 5, 5),
TEST ("\0cbge\0\0", '\0', 9, 6),
TEST ("\0cbge\0\0", 'b', 5, 2),
TEST ("\0bgeb\0\0", 'b', 5, 4),
TEST ("\0cbge\0\0", 'a', 6, NPOS),
TEST ("x@4096", 'x', 0, 0),
TEST ("x@4096", 'x', 5, 5),
TEST ("x@4096", 'x', 4096, 4095),
TEST ("x@4096", '\0', 4096, NPOS),
TEST ("x@4096", 'a', 4094, NPOS),
TEST ("x@4096", 'x', 4095, 4095),
TEST ("x@4096", 'x', 4106, 4095),
TEST ("last test", 't', 9, 8)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_rfind (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
static charT warg_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
// construct the string object and the argument string
const String s_str (wstr, str_len);
const String s_arg (warg, arg_len);
if (wstr != wstr_buf)
delete[] wstr;
if (warg != warg_buf)
delete[] warg;
wstr = 0;
warg = 0;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
const String& arg_str = tcase.arg ? s_arg : s_str;
const charT arg_val = make_char (char (tcase.val), (charT*)0);
std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected ?
const char* expected = 0;
if (1 == tcase.bthrow)
expected = exceptions [2];
const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
std::size_t res = 0;
switch (func.which_) {
case RFind (cptr):
res = s_str.rfind (arg_ptr);
break;
case RFind (cstr):
res = s_str.rfind (arg_str);
break;
case RFind (cptr_size):
res = s_str.rfind (arg_ptr, tcase.off);
break;
case RFind (cptr_size_size):
res = s_str.rfind (arg_ptr, tcase.off, size);
break;
case RFind (cstr_size):
res = s_str.rfind (arg_str, tcase.off);
break;
case RFind (val):
res = s_str.rfind (arg_val);
break;
case RFind (val_size):
res = s_str.rfind (arg_val, tcase.off);
break;
default:
RW_ASSERT ("test logic error: unknown rfind overload");
return;
}
const std::size_t exp_res =
NPOS != tcase.nres ? tcase.nres : String::npos;
// verify the returned value
rw_assert (exp_res == res, 0, tcase.line,
"line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
"got %{?}%zu%{;}%{?}npos%{;}",
__LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres,
String::npos != res, res, String::npos == res);
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
}
else if (-1 != tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_rfind);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
RFind (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (cptr),
TEST (cstr),
TEST (cptr_size),
TEST (cptr_size_size),
TEST (cstr_size),
TEST (val),
TEST (val_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.rfind",
test_rfind, tests, test_count);
}

View File

@@ -0,0 +1,366 @@
/***************************************************************************
*
* 21.string.substr.cpp - string test exercising [lib.string::substr]
*
* $Id: 21.string.substr.cpp 590052 2007-10-30 12:44:14Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // for size_t
#include <stdexcept> // for out_of_range
#include <21.strings.h> // for StringIds
#include <driver.h> // for rw_test()
#include <rw_allocator.h> // for UserAlloc
#include <rw_char.h> // for rw_expand()
/**************************************************************************/
// for convenience and brevity
#define Substr(sig) StringIds::substr_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// used to exercise
// substr ()
static const StringTestCase
void_test_cases [] = {
#undef TEST
#define TEST(str, res) \
{ __LINE__, -1, -1, -1, -1, -1, str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, 0 }
// +------------------------------------- controlled sequence
// | +----------------- expected result sequence
// | |
// V V
TEST ("abc", "abc"),
TEST ("", ""),
TEST ("<U0>", "<U0>"),
TEST ("a<U0>", "a<U0>"),
TEST ("<U0>a", "<U0>a"),
TEST ("a<U0>@2bcd<U0>", "a<U0>@2bcd<U0>"),
TEST ("<U0>@2abcd<U0>", "<U0>@2abcd<U0>"),
TEST ("<U0>@2ab<U0>@2", "<U0>@2ab<U0>@2"),
TEST ("x@4096", "x@4096"),
TEST ("last", "last")
};
/**************************************************************************/
// used to exercise
// substr (size_type)
static const StringTestCase
size_test_cases [] = {
#undef TEST
#define TEST(str, off, res, bthrow) \
{ __LINE__, off, -1, -1, -1, -1, str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, bthrow }
// +--------------------------------------- controlled sequence
// | +----------------- substr() off argument
// | | +------------- expected result sequence
// | | | +--- exception info:
// | | | | 0 - no exception
// | | | | 1 - out_of_range
// V V V V
TEST ("abc", 0, "abc", 0),
TEST ("", 0, "", 0),
TEST ("<U0>", 0, "<U0>", 0),
TEST ("<U0>", 1, "", 0),
TEST ("a<U0>", 0, "a<U0>", 0),
TEST ("a<U0>", 1, "<U0>", 0),
TEST ("<U0>a", 0, "<U0>a", 0),
TEST ("<U0>a", 1, "a", 0),
TEST ("a<U0>@2bcd<U0>", 0, "a<U0>@2bcd<U0>", 0),
TEST ("a<U0>@2bcd<U0>", 1, "<U0>@2bcd<U0>", 0),
TEST ("a<U0>@2bcd<U0>", 6, "<U0>", 0),
TEST ("a<U0>@2bcd<U0>", 7, "", 0),
TEST ("<U0>@2abcd<U0>", 0, "<U0>@2abcd<U0>", 0),
TEST ("<U0>@2abcd<U0>", 1, "<U0>abcd<U0>", 0),
TEST ("<U0>@2abcd<U0>", 2, "abcd<U0>", 0),
TEST ("<U0>@2ab<U0>@2", 0, "<U0>@2ab<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 1, "<U0>ab<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 4, "<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 6, "", 0),
TEST ("x@4096", 0, "x@4096", 0),
TEST ("x@4096", 4094, "xx", 0),
TEST ("x@4096", 4088, "xxxxxxxx", 0),
TEST ("x@4096", 4096, "", 0),
TEST ("abx@4096", 2, "x@4096", 0),
TEST ("x@4096ab", 2048, "x@2048ab", 0),
TEST ("<U0>", 2, "", 1),
TEST ("a", 10, "", 1),
TEST ("x@4096", 4106, "", 1),
TEST ("last", 0, "last", 0)
};
/**************************************************************************/
// used to exercise
// substr (size_type, size_type)
static const StringTestCase
size_size_test_cases [] = {
#undef TEST
#define TEST(str, off, size, res, bthrow) \
{ __LINE__, off, size, -1, -1, -1, str, sizeof str - 1, 0, 0, \
res, sizeof res - 1, bthrow }
// +------------------------------------------ controlled sequence
// | +-------------------- substr() off argument
// | | +---------------- substr() n argument
// | | | +------------- expected result sequence
// | | | | +--- exception info:
// | | | | | 0 - no exception
// | | | | | 1 - out_of_range
// | | | | |
// | | | | +-------+
// V V V V V
TEST ("abc", 0, 3, "abc", 0),
TEST ("", 0, 0, "", 0),
TEST ("<U0>", 0, 1, "<U0>", 0),
TEST ("<U0>", 0, 0, "", 0),
TEST ("<U0>", 1, 1, "", 0),
TEST ("a<U0>", 0, 2, "a<U0>", 0),
TEST ("a<U0>", 1, 2, "<U0>", 0),
TEST ("a<U0>", 0, 1, "a", 0),
TEST ("a<U0>", 1, 1, "<U0>", 0),
TEST ("a<U0>", 1, 0, "", 0),
TEST ("<U0>a", 0, 2, "<U0>a", 0),
TEST ("<U0>a", 0, 1, "<U0>", 0),
TEST ("<U0>a", 1, 2, "a", 0),
TEST ("a<U0>@2bcd<U0>", 0, 7, "a<U0>@2bcd<U0>", 0),
TEST ("a<U0>@2bcd<U0>", 1, 7, "<U0>@2bcd<U0>", 0),
TEST ("a<U0>@2bcd<U0>", 0, 3, "a<U0>@2", 0),
TEST ("a<U0>@2bcd<U0>", 1, 2, "<U0>@2", 0),
TEST ("a<U0>@2bcd<U0>", 6, 7, "<U0>", 0),
TEST ("a<U0>@2bcd<U0>", 7, 7, "", 0),
TEST ("<U0>@2abcd<U0>", 0, 7, "<U0>@2abcd<U0>", 0),
TEST ("<U0>@2abcd<U0>", 1, 7, "<U0>abcd<U0>", 0),
TEST ("<U0>@2abcd<U0>", 0, 3, "<U0>@2a", 0),
TEST ("<U0>@2abcd<U0>", 1, 1, "<U0>", 0),
TEST ("<U0>@2abcd<U0>", 6, 3, "<U0>", 0),
TEST ("<U0>@2abcd<U0>", 1, 6, "<U0>abcd<U0>", 0),
TEST ("<U0>@2abcd<U0>", 0, 0, "", 0),
TEST ("<U0>@2abcd<U0>", 2, 7, "abcd<U0>", 0),
TEST ("<U0>@2ab<U0>@2", 0, 6, "<U0>@2ab<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 1, 6, "<U0>ab<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 0, 2, "<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 4, 6, "<U0>@2", 0),
TEST ("<U0>@2ab<U0>@2", 2, 3, "ab<U0>", 0),
TEST ("<U0>@2ab<U0>@2", 6, 6, "", 0),
TEST ("x@4096", 0, 4096, "x@4096", 0),
TEST ("x@4096", 4095, 4096, "x", 0),
TEST ("x@4096", 4088, 2, "xx", 0),
TEST ("x@4096", 4093, 5, "xxx", 0),
TEST ("x@4096", 4088, 8, "xxxxxxxx", 0),
TEST ("x@4096", 4096, 1, "", 0),
TEST ("ax@4096b", 1, 4094, "x@4094", 0),
TEST ("<U0>", 2, 0, "", 1),
TEST ("a", 10, 0, "", 1),
TEST ("x@4096", 4106, 0, "", 1),
TEST ("last", 0, 4, "last", 0)
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_substr (charT, Traits*, Allocator*,
const StringFunc &func,
const StringTestCase &tcase)
{
typedef std::basic_string <charT, Traits, Allocator> String;
static const std::size_t BUFSIZE = 256;
static charT wstr_buf [BUFSIZE];
std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
static charT wres_buf [BUFSIZE];
std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
// construct the string object
const String str (wstr, str_len);
if (wstr != wstr_buf)
delete[] wstr;
wstr = 0;
String s_res;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (str));
#ifndef _RWSTD_NO_EXCEPTIONS
// is some exception expected?
const char* const expected = tcase.bthrow ? exceptions [1] : 0;
const char* caught = 0;
#else
if (tcase.bthrow) {
if (wres != wres_buf)
delete[] wres;
return;
}
#endif // _RWSTD_NO_EXCEPTIONS
try {
switch (func.which_) {
case Substr (void):
s_res = str.substr ();
break;
case Substr (size):
s_res = str.substr (tcase.off);
break;
case Substr (size_size):
s_res = str.substr (tcase.off, tcase.size);
break;
default:
RW_ASSERT (!"logic error: unknown substr overload");
return;
}
// verfiy that strings length are equal
rw_assert (res_len == s_res.size (), 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s} with length "
"%zu, got %{/*.*Gs} with length %zu",
__LINE__, int (tcase.nres), tcase.res,
res_len, int (sizeof (charT)),
int (s_res.size ()), s_res.c_str (), s_res.size ());
if (res_len == s_res.size ()) {
// if the result length matches the expected length
// (and only then), also verify that the resulted
// string matches the expected result
const std::size_t match =
rw_match (tcase.res, s_res.c_str(), s_res.size ());
rw_assert (match == res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, "
"got %{/*.*Gs}, difference at offset %zu",
__LINE__, int (tcase.nres), tcase.res,
int (sizeof (charT)), int (s_res.size ()),
s_res.c_str (), match);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::out_of_range &ex) {
caught = exceptions [1];
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (str),
__LINE__, tcase.line, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
if (wres != wres_buf)
delete[] wres;
}
/**************************************************************************/
DEFINE_STRING_TEST_DISPATCH (test_substr);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Substr (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
}
TEST (void),
TEST (size),
TEST (size_size)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
return rw_run_string_test (argc, argv, __FILE__,
"lib.string.substr",
test_substr, tests, test_count);
}

View File

@@ -0,0 +1,391 @@
/***************************************************************************
*
* 21.string.swap.cpp - string test exercising [lib.string::swap]
*
* $Id: 21.string.swap.cpp 590064 2007-10-30 13:16:44Z faridz $
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2006 Rogue Wave Software.
*
**************************************************************************/
#include <string> // for string
#include <cstddef> // size_t
#include <exception> // for exception
#include <21.strings.h> // for StringIds
#include <driver.h> // for rw_assert()
#include <rw_allocator.h> // foir UserAlloc
#include <rw_char.h> // for rw_expand()
#include <rw_new.h> // for bad_alloc, replacement operator new
/**************************************************************************/
// for convenience and brevity
#define Swap(sig) StringIds::swap_ ## sig
static const char* const exceptions[] = {
"unknown exception", "out_of_range", "length_error",
"bad_alloc", "exception"
};
/**************************************************************************/
// exercises:
// swap (basic_string&)
static const StringTestCase
str_test_cases [] = {
#undef TEST
#define TEST(str, arg) \
{ __LINE__, -1, -1, -1, -1, -1, \
str, sizeof str - 1, arg, sizeof arg - 1, \
0, 0, 0 \
}
// +------------------------- controlled "destination" (str) sequence
// | +-------- controlled "source" (arg) sequence
// | |
// V V
TEST ("", ""),
TEST ("", "a"),
TEST ("a", ""),
TEST ("", "<U0>"),
TEST ("<U0>", ""),
TEST ("a", "b"),
TEST ("a", "bc"),
TEST ("ab", "c"),
TEST ("a<U0>b<U0>@2c", "<U0>b<U0>@2c"),
TEST ("<U0>b<U0>@2c", "a<U0>b<U0>@2c"),
TEST ("a<U0>b<U0>@2c", "<U0>@2"),
TEST ("<U0>@2", "a<U0>b<U0>@2c"),
TEST ("x@4096", ""),
TEST ("", "x@4096"),
TEST ("x@4096", "<U0>@3"),
TEST ("<U0>@3", "x@4096"),
TEST ("x@4096", "x@4096"),
TEST ("", "x@128"),
TEST ("x@207", "x@128"),
TEST ("x@128", "x@334"),
TEST ("x@873", "x@334"),
TEST ("x@1412", "x@540"),
TEST ("x@540", "x@2284"),
TEST ("x@3695", "x@2284"),
TEST ("x@3695", "x@128"),
TEST ("", 0),
TEST ("<U0>", 0),
TEST ("abc", 0),
TEST ("a<U0>b<U0>@2c", 0),
TEST ("x@4096", 0),
TEST (0, ""),
TEST (0, "<U0>"),
TEST (0, "abc@1024"),
TEST (0, "a<U0>b<U0>@2c"),
TEST (0, "x@4096"),
TEST ("last", "test")
};
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_swap (charT*, Traits*,
Allocator &a1,
Allocator &a2,
const StringTestCaseData<charT> &tdata)
{
typedef std::basic_string <charT, Traits, Allocator> String;
typedef UserTraits<UserChar>::MemFun UTMemFun;
const StringTestCase &tcase = tdata.tcase_;
// construct the string object to be modified
// and the argument string
String s_str (tdata.str_, tdata.strlen_, a1);
String s_arg (tdata.arg_, tdata.arglen_, a2);
const charT* const p1 = s_str.data ();
const charT* const p2 = tcase.arg ? s_arg.data () : s_str.data ();
const char* const src = tcase.arg ? tcase.arg : tcase.str;
const std::size_t src_len = tcase.arg ? tcase.arg_len : tcase.str_len;
const std::size_t srclen_ = tcase.arg ? tdata.arglen_ : tdata.strlen_;
String& arg_str = tcase.arg ? s_arg : s_str;
// save the state of the string object before the call
// to detect wxception safety violations (changes to
// the state of the object after an exception)
const StringState str_state (rw_get_string_state (s_str));
const StringState arg_str_state (rw_get_string_state (arg_str));
std::size_t n_total_op_assign = 0;
std::size_t n_total_op_assign2 = 0;
std::size_t n_total_op_copy = 0;
std::size_t n_total_op_move = 0;
std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
if (rg_calls) {
n_total_op_assign = rg_calls[UTMemFun::assign];
n_total_op_assign2 = rg_calls[UTMemFun::assign2];
n_total_op_copy = rg_calls[UTMemFun::copy];
n_total_op_move = rg_calls[UTMemFun::move];
}
rwt_free_store* const pst = rwt_get_free_store (0);
SharedAlloc* const pal = SharedAlloc::instance ();
// iterate for`throw_count' starting at the next call to operator new,
// forcing each call to throw an exception, until the function finally
// succeeds (i.e, no exception is thrown)
std::size_t throw_count;
for (throw_count = 0; ; ++throw_count) {
const char* expected = 0;
const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
// no exceptions expected
if (0 == tcase.bthrow) {
// by default excercise the exception safety of the function
// by iteratively inducing an exception at each call to operator
// new or Allocator::allocate() until the call succeeds
expected = exceptions [3]; // bad_alloc
*pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
pal->throw_at_calls_ [pal->m_allocate] =
pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
}
#else // if defined (_RWSTD_NO_EXCEPTIONS)
if (tcase.bthrow)
return;
#endif // _RWSTD_NO_EXCEPTIONS
try {
// start checking for memory leaks
rw_check_leaks (s_str.get_allocator ());
rw_check_leaks (arg_str.get_allocator ());
if (0 == tcase.str)
String ().swap (arg_str);
else
s_str.swap (arg_str);
if (rg_calls) {
std::size_t n_op_assign =
rg_calls[UTMemFun::assign] - n_total_op_assign;
std::size_t n_op_assign2 =
rg_calls[UTMemFun::assign2] - n_total_op_assign2;
std::size_t n_op_copy =
rg_calls[UTMemFun::copy] - n_total_op_copy;
std::size_t n_op_move =
rg_calls[UTMemFun::move] - n_total_op_move;
bool success =
0 == (n_op_assign | n_op_assign2 | n_op_copy | n_op_move);
rw_assert (success, 0, tcase.line,
"line %d. %{$FUNCALL}: complexity: %zu assigns, "
"%zu assign2s, %zu copies, %zu moves", __LINE__,
n_op_assign, n_op_assign2, n_op_copy, n_op_move);
}
if (0 == tcase.str) {
rw_assert (0 == arg_str.capacity (), 0, tcase.line,
"line %d. %{$FUNCALL}: expected 0 capacity, "
"got %zu", __LINE__, arg_str.capacity ());
}
else {
const charT* const res_p1 = s_str.data ();
const charT* const res_p2 =
tcase.arg ? s_arg.data () : s_str.data ();
const std::size_t res1_len = s_str.size ();
const std::size_t res2_len =
tcase.arg ? s_arg.size () : s_str.size ();
rw_assert (res_p1 == p2 && res_p2 == p1, 0, tcase.line,
"line %d. %{$FUNCALL}: got offset %td from "
"expected value, arg.data (): got offset %td "
"from expected value",
__LINE__, p2 - res_p1, p1 - res_p2);
std::size_t match =
rw_match (tcase.str, res_p2, res2_len);
rw_assert (match == tdata.strlen_, 0, tcase.line,
"line %d. %{$FUNCALL}: this == %{#*s}, got this = "
"%{/*.*Gs}, differs at pos %zu",
__LINE__, int (src_len), src, int (sizeof (charT)),
int (res1_len), res_p1, match);
match = rw_match (src, res_p1, res1_len);
rw_assert (match == srclen_, 0, tcase.line,
"line %d. %{$FUNCALL}: str == %{#*s}, got str = "
"%{/*.*Gs}, differs at pos %zu",
__LINE__, int (tcase.str_len), tcase.str,
int (sizeof (charT)), int (res2_len),
res_p2, match);
}
}
#ifndef _RWSTD_NO_EXCEPTIONS
catch (const std::exception &ex) {
caught = exceptions [4];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught std::%s(%#s)",
__LINE__, 0 != expected, expected, caught, ex.what ());
}
catch (...) {
caught = exceptions [0];
rw_assert (0, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
"unexpectedly%{;} caught %s",
__LINE__, 0 != expected, expected, caught);
}
#endif // _RWSTD_NO_EXCEPTIONS
// FIXME: verify the number of blocks the function call
// is expected to allocate and detect any memory leaks
rw_check_leaks (s_str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
rw_check_leaks (arg_str.get_allocator (), tcase.line,
std::size_t (-1), std::size_t (-1));
if (caught) {
// verify that an exception thrown during allocation
// didn't cause a change in the state of the object
str_state.assert_equal (rw_get_string_state (s_str),
__LINE__, tcase.line, caught);
arg_str_state.assert_equal (rw_get_string_state (arg_str),
__LINE__, tcase.line, caught);
if (0 == tcase.bthrow) {
// allow this call to operator new to succeed and try
// to make the next one to fail during the next call
// to the same function again
continue;
}
}
else if (0 < tcase.bthrow) {
rw_assert (caught == expected, 0, tcase.line,
"line %d. %{$FUNCALL} %{?}expected %s, caught %s"
"%{:}unexpectedly caught %s%{;}",
__LINE__, 0 != expected, expected, caught, caught);
}
break;
}
// no exception expected
const std::size_t expect_throws = 0;
rw_assert (expect_throws == throw_count, 0, tcase.line,
"line %d: %{$FUNCALL}: expected exactly 0 %s exception "
"while the swap, got %zu",
__LINE__, exceptions [3], throw_count);
// disable bad_alloc exceptions
*pst->throw_at_calls_ [0] = 0;
pal->throw_at_calls_ [pal->m_allocate] = 0;
}
/**************************************************************************/
template <class charT>
std::allocator<charT>
make_alloc (SharedAlloc&, std::allocator<charT>*) {
return std::allocator<charT>();
}
template <class charT, class Types>
UserAlloc<charT, Types>
make_alloc (SharedAlloc &shal, UserAlloc<charT, Types>*) {
return UserAlloc<charT, Types>(&shal);
}
/**************************************************************************/
template <class charT, class Traits, class Allocator>
void test_swap (charT*, Traits*, Allocator*,
const StringTestCaseData<charT> &tdata)
{
SharedAlloc sa1;
Allocator a1 = make_alloc(sa1, (Allocator*)0);
// test swap using the same allocator objects
test_swap ((charT*)0, (Traits*)0, a1, a1, tdata);
SharedAlloc sa2;
Allocator a2 = make_alloc(sa2, (Allocator*)0);
if (a1 != a2) {
// test swap using different allocator objects
test_swap ((charT*)0, (Traits*)0, a1, a2, tdata);
}
}
/**************************************************************************/
DEFINE_STRING_TEST_FUNCTIONS (test_swap);
int main (int argc, char** argv)
{
static const StringTest
tests [] = {
#undef TEST
#define TEST(sig) { \
Swap (sig), sig ## _test_cases, \
sizeof sig ## _test_cases / sizeof *sig ## _test_cases, \
}
TEST (str)
};
const std::size_t test_count = sizeof tests / sizeof *tests;
const int status =
rw_run_string_test (argc, argv, __FILE__,
"lib.string.swap",
test_swap_func_array, tests, test_count);
return status;
}