Author: sebor
Date: Mon Apr 24 18:32:10 2006
New Revision: 396754
URL: http://svn.apache.org/viewcvs?rev=396754&view=rev
Log:
2006-04-24 Martin Sebor <[EMAIL PROTECTED]>
* 21.string.append.cpp (exceptions): Added elements and renamed
from exp_exceptions for clarity.
(test_exceptions): Merged the body of the function into the
test_append function and removed the declaration of the former.
(test_append_range): Constified locals wherever appropriate
and introduced new helper variables to simplify expressions.
(test_append): Exercised both the function exception safety
and the behavior of the function under normal conditions.
Modified:
incubator/stdcxx/trunk/tests/strings/21.string.append.cpp
Modified: incubator/stdcxx/trunk/tests/strings/21.string.append.cpp
URL:
http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/strings/21.string.append.cpp?rev=396754&r1=396753&r2=396754&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.append.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.append.cpp Mon Apr 24
18:32:10 2006
@@ -61,8 +61,10 @@
static const std::size_t long_string_len = 4096;
static char long_string [long_string_len];
-static const char* const exp_exceptions[] =
- { "unknown exception", "out_of_range", "length_error" };
+static const char* const exceptions[] = {
+ "unknown exception", "out_of_range", "length_error",
+ "bad_alloc", "exception"
+};
/**************************************************************************/
@@ -399,133 +401,6 @@
/**************************************************************************/
-template <class charT, class Traits>
-void test_exceptions (charT, Traits*,
- AppendOverload which,
- const TestCase &tcase)
-{
- typedef std::basic_string <charT, Traits,
- std::allocator<charT> > TestString;
- typedef typename TestString::iterator StringIter;
- typedef typename TestString::const_iterator ConstStringIter;
-
- static charT wstr [LLEN];
- static charT wsrc [LLEN];
-
- rw_widen (wstr, tcase.str, tcase.str_len);
- rw_widen (wsrc, tcase.arg, tcase.arg_len);
-
- TestString s_str (wstr, tcase.str_len);
- TestString s_arg (wsrc, tcase.arg_len);
-
- std::size_t throw_after = 0;
-
- const std::size_t size = s_str.size ();
- const std::size_t capacity = s_str.capacity ();
- const ConstStringIter begin = s_str.begin ();
-
-#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
-
- rwt_free_store* const pst = rwt_get_free_store (0);
-
-#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
-
- // iterate for`n=throw_after' starting at the next call to operator
- // new, forcing each call to throw an exception, until the appendion
- // finally succeeds (i.e, no exception is thrown)
- for ( ; ; ) {
-
-#ifndef _RWSTD_NO_EXCEPTIONS
-# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
-
- *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
-
-# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
-#endif // _RWSTD_NO_EXCEPTIONS
-
- _TRY {
- if (Append (ptr) == which)
- s_str.append (tcase.arg ? wsrc : s_str.c_str ());
-
- else if (Append (str) == which)
- s_str.append (tcase.arg ? s_arg : s_str);
-
- else if (Append (ptr_size) == which)
- s_str.append (tcase.arg ? wsrc : s_str.c_str (), tcase.size);
-
- else if (Append (str_size_size) == which)
- s_str.append (tcase.arg ? s_arg : s_str, tcase.off,
tcase.size);
-
- else if (Append (size_val) == which)
- s_str.append (tcase.size, make_char (char (tcase.val),
(charT*)0));
-
- else if (Append (range) == which)
- s_str.append (s_arg.begin (), s_arg.end ());
-
- break;
- }
- _CATCH (...) {
-
-#ifndef _RWSTD_NO_EXCEPTIONS
-
- // verify that an exception thrown during allocation
- // doesn't cause a change in the state of the vector
-
- rw_assert (s_str.size () == size, 0, tcase.line,
- "line %d: %{$FUNCALL}: size unexpectedly changed "
- "from %zu to %zu after an exception",
- __LINE__, size, s_str.size ());
-
- rw_assert (s_str.capacity () == capacity, 0, tcase.line,
- "line %d: %{$FUNCALL}: capacity unexpectedly "
- "changed from %zu to %zu after an exception",
- __LINE__, capacity, s_str.capacity ());
-
-
- rw_assert (s_str.begin () == begin, 0, tcase.line,
- "line %d: %{$FUNCALL}: begin() unexpectedly "
- "changed from after an exception by %d",
- __LINE__, s_str.begin () - begin);
-
-
- // increment to allow this call to operator new to succeed
- // and force the next one to fail, and try to append again
- ++throw_after;
-
-#endif // _RWSTD_NO_EXCEPTIONS
-
- } // catch
- } // for
-
-#ifndef _RWSTD_NO_EXCEPTIONS
-# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
-
- // verify that if exceptions are enabled and when capacity changes
- // at least one exception is thrown
- rw_assert ( *pst->throw_at_calls_ [0] == std::size_t (-1)
- || throw_after,
- 0, tcase.line,
- "line %d: %{$FUNCALL}: failed to throw an expected exception",
- __LINE__);
-
-# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
-#else // if defined (_RWSTD_NO_EXCEPTIONS)
-
- _RWSTD_UNUSED (size);
- _RWSTD_UNUSED (capacity);
- _RWSTD_UNUSED (throw_after);
-
-#endif // _RWSTD_NO_EXCEPTIONS
-
-#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
-
- *pst->throw_at_calls_ [0] = std::size_t (-1);
-
-#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
-}
-
-/**************************************************************************/
-
template <class charT, class Traits, class Iterator>
void test_append_range (charT *wstr,
charT *wsrc,
@@ -533,42 +408,45 @@
const Iterator &it,
const TestCase &tcase)
{
- typedef std::basic_string <charT, Traits,
- std::allocator<charT> > String;
- typedef typename String::iterator StringIter;
+ typedef std::allocator<charT> Allocator;
+ typedef std::basic_string <charT, Traits, Allocator> String;
+ typedef typename String::iterator StringIter;
const char* const itname =
tcase.arg ? type_name (it, (charT*)0) : "basic_string::iterator";
- String s_str (wstr, tcase.str_len);
- String s_arg (wsrc, tcase.arg_len);
+ /* const */ String s_str (wstr, tcase.str_len);
+ const String s_arg (wsrc, tcase.arg_len);
std::size_t off_last = tcase.off + tcase.size;
if (tcase.arg) {
- off_last = off_last > s_arg.size () ? s_arg.size () : off_last;
+ if (off_last < s_arg.size ())
+ off_last = s_arg.size ();
- const Iterator first = make_iter (wsrc + tcase.off,
- wsrc + tcase.off, wsrc + off_last, Iterator (0, 0, 0));
- const Iterator last = make_iter (wsrc + off_last,
- wsrc + tcase.off, wsrc + off_last, Iterator (0, 0, 0));
+ const charT* const beg = wsrc + tcase.off;
+ const charT* const end = wsrc + off_last;
+
+ const Iterator first (beg, beg, end);
+ const Iterator last (end, beg, end);
s_str.append (first, last);
}
else {
- StringIter first (s_str.begin () + tcase.off);
- StringIter last (off_last > s_str.size () ?
- s_str.end ()
- : s_str.begin () + off_last);
+ const StringIter first (s_str.begin () + tcase.off);
+ const StringIter last (s_str.size () < off_last ?
+ s_str.end ()
+ : s_str.begin () + off_last);
s_str.append (first, last);
}
- const std::size_t match = rw_match (tcase.res, s_str.c_str(),
tcase.res_len);
+ const std::size_t match =
+ rw_match (tcase.res, s_str.c_str(), tcase.res_len);
rw_assert (match == tcase.res_len, 0, tcase.line,
"line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
- "difference at off %zu for %s",
+ "difference at offset %zu for %s",
__LINE__, int (tcase.res_len), tcase.res,
int (sizeof (charT)), int (s_str.size ()), s_str.c_str (),
match, itname);
@@ -613,11 +491,7 @@
typedef std::allocator<charT> Allocator;
typedef std::basic_string <charT, Traits, Allocator> TestString;
typedef typename TestString::iterator StringIter;
-
- if (-1 == tcase.bthrow) {
- test_exceptions (charT (), (Traits*)0, which, tcase);
- return;
- }
+ typedef typename TestString::const_iterator ConstStringIter;
static charT wstr [LLEN];
static charT wsrc [LLEN];
@@ -631,113 +505,230 @@
return;
}
- TestString s_str (wstr, tcase.str_len);
- TestString s_arg (wsrc, tcase.arg_len);
+ /* const */ TestString s_str (wstr, tcase.str_len);
+ const TestString s_arg (wsrc, tcase.arg_len);
- std::size_t res_off = 0;
+ std::size_t res_off = 0;
+ std::size_t throw_after = 0;
+
+ const std::size_t size = s_str.size ();
+ const std::size_t capacity = s_str.capacity ();
+ const ConstStringIter begin = s_str.begin ();
+
+ const charT* const ptr_arg = tcase.arg ? wsrc : s_str.c_str ();
+ const TestString& str_arg = tcase.arg ? s_arg : s_str;
+
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ rwt_free_store* const pst = rwt_get_free_store (0);
+
+#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // iterate for`n=throw_after' starting at the next call to operator
+ // new, forcing each call to throw an exception, until the appendion
+ // finally succeeds (i.e, no exception is thrown)
+ for ( ; ; ) {
#ifndef _RWSTD_NO_EXCEPTIONS
+# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
- // is some exception expected ?
- const char* expected = 0;
- if (1 == tcase.bthrow && Append (str_size_size) == which)
- expected = exp_exceptions [1];
- if (2 == tcase.bthrow)
- expected = exp_exceptions [2];
+ if (-1 == tcase.bthrow)
+ *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
- const char* caught = 0;
+# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+#endif // _RWSTD_NO_EXCEPTIONS
+
+#ifndef _RWSTD_NO_EXCEPTIONS
- try {
+ // is some exception expected?
+ const char* expected = 0;
+ if (1 == tcase.bthrow && Append (str_size_size) == which)
+ expected = exceptions [1]; // out_of_range
+ else if (2 == tcase.bthrow)
+ expected = exceptions [2]; // length_error
+ else if (-1 == tcase.bthrow)
+ expected = exceptions [3]; // bad_alloc
+
+ const char* caught = 0;
#else // if defined (_RWSTD_NO_EXCEPTIONS)
- if (tcase.bthrow)
- return;
+ if (tcase.bthrow)
+ return;
#endif // _RWSTD_NO_EXCEPTIONS
- switch (which) {
- case Append (ptr): {
- TestString& s_res = s_str.append (tcase.arg ? wsrc : s_str.c_str ());
- res_off = &s_res - &s_str;
- break;
- }
+ try {
- case Append (str): {
- TestString& s_res = s_str.append (tcase.arg ? s_arg : s_str);
- res_off = &s_res - &s_str;
- break;
- }
+ switch (which) {
+ case Append (ptr): {
+ const TestString& s_res = s_str.append (ptr_arg);
+ res_off = &s_res - &s_str;
+ break;
+ }
+
+ case Append (str): {
+ const TestString& s_res = s_str.append (str_arg);
+ res_off = &s_res - &s_str;
+ break;
+ }
+
+ case Append (ptr_size): {
+ const TestString& s_res = s_str.append (ptr_arg, tcase.size);
+ res_off = &s_res - &s_str;
+ break;
+ }
+
+ case Append (str_size_size): {
+ const TestString& s_res =
+ s_str.append (str_arg, tcase.off, tcase.size);
+ res_off = &s_res - &s_str;
+ break;
+ }
+
+ case Append (size_val): {
+ const charT ch (make_char (char (tcase.val), (charT*)0));
+ const TestString& s_res = s_str.append (tcase.size, ch);
+ res_off = &s_res - &s_str;
+ break;
+ }
+
+ default:
+ RW_ASSERT (!"test logic error: unknown append overload");
+ }
+
+ // verify the returned value
+ rw_assert (0 == res_off, 0, tcase.line,
+ "line %d. %{$FUNCALL} returned invalid reference, "
+ "offset is %zu", __LINE__, res_off);
+
+ // verify that strings are of equal length
+ rw_assert (tcase.res_len == s_str.size (), 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{#*s}, "
+ "length %zu, got %{/*.*Gs}, length %zu",
+ __LINE__, int (tcase.res_len), tcase.res,
+ tcase.res_len, int (sizeof (charT)),
+ int (s_str.size ()), s_str.c_str (), s_str.size ());
+
+ if (tcase.res_len == s_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, s_str.c_str(), tcase.res_len);
+
+ rw_assert (match == tcase.res_len, 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{#*s}, "
+ "got %{/*.*Gs}, difference at offset %zu",
+ __LINE__, int (tcase.res_len), tcase.res,
+ int (sizeof (charT)), int (s_str.size ()),
+ s_str.c_str (), match);
+ }
+ }
- case Append (ptr_size): {
- TestString& s_res =
- s_str.append (tcase.arg ? wsrc : s_str.c_str (), tcase.size);
- res_off = &s_res - &s_str;
- break;
- }
+#ifndef _RWSTD_NO_EXCEPTIONS
- case Append (str_size_size): {
- TestString& s_res =
- s_str.append (tcase.arg ? s_arg : s_str, tcase.off, tcase.size);
- res_off = &s_res - &s_str;
- break;
- }
+ 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 (-1 == 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);
+ }
- case Append (size_val): {
- TestString& s_res =
- s_str.append (tcase.size, make_char (char (tcase.val), (charT*)0));
- res_off = &s_res - &s_str;
- break;
- }
+#else // if defined (_RWSTD_NO_EXCEPTIONS)
- default:
- RW_ASSERT (!"test logic error: unknown append overload");
- }
+ _RWSTD_UNUSED (should_throw);
- // verify the returned value
- rw_assert (0 == res_off, 0, tcase.line,
- "line %d. %{$FUNCALL} returned invalid reference, offset is
%zu",
- __LINE__, res_off);
-
- // verfiy that strings length are equal
- rw_assert (tcase.res_len == s_str.size (), 0, tcase.line,
- "line %d. %{$FUNCALL} expected %{#*s} with length %zu, "
- "got %{/*.*Gs} with length %zu", __LINE__, int (tcase.res_len),
- tcase.res, tcase.res_len, int (sizeof (charT)),
- int (s_str.size ()), s_str.c_str (), s_str.size ());
+#endif // _RWSTD_NO_EXCEPTIONS
- // verfiy that append results match expected result
- const std::size_t match =
- rw_match (tcase.res, s_str.c_str(), tcase.res_len);
+ if (caught) {
+ // verify that an exception thrown during allocation
+ // didn't cause a change in the state of the object
- rw_assert (match == tcase.res_len, 0, tcase.line,
- "line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
- "difference at off %zu",
- __LINE__, int (tcase.res_len), tcase.res,
- int (sizeof (charT)), int (s_str.size ()), s_str.c_str (),
- match);
+ rw_assert (s_str.size () == size, 0, tcase.line,
+ "line %d: %{$FUNCALL}: size unexpectedly changed "
+ "from %zu to %zu after an exception",
+ __LINE__, size, s_str.size ());
-#ifndef _RWSTD_NO_EXCEPTIONS
+ rw_assert (s_str.capacity () == capacity, 0, tcase.line,
+ "line %d: %{$FUNCALL}: capacity unexpectedly "
+ "changed from %zu to %zu after an exception",
+ __LINE__, capacity, s_str.capacity ());
+ rw_assert (s_str.begin () == begin, 0, tcase.line,
+ "line %d: %{$FUNCALL}: begin() unexpectedly "
+ "changed from after an exception by %d",
+ __LINE__, s_str.begin () - begin);
+
+ if (-1 == tcase.bthrow) {
+ // increment to allow this call to operator new to succeed
+ // and force the next one to fail, and try calling the same
+ // function again
+ ++throw_after;
+ continue;
+ }
+ }
+ 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);
+ }
+
+ break;
}
- catch (std::out_of_range) {
- caught = exp_exceptions[1];
- }
- catch (std::length_error) {
- caught = exp_exceptions[2];
- }
- catch (...) {
- caught = exp_exceptions[0];
- }
+#ifndef _RWSTD_NO_EXCEPTIONS
+# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // verify that if exceptions are enabled and when capacity changes
+ // at least one exception is thrown
+ rw_assert ( *pst->throw_at_calls_ [0] == std::size_t (-1)
+ || throw_after,
+ 0, tcase.line,
+ "line %d: %{$FUNCALL}: failed to throw an expected exception",
+ __LINE__);
+
+ *pst->throw_at_calls_ [0] = std::size_t (-1);
+
+# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
#else // if defined (_RWSTD_NO_EXCEPTIONS)
- _RWSTD_UNUSED (should_throw);
+
+ _RWSTD_UNUSED (size);
+ _RWSTD_UNUSED (capacity);
+ _RWSTD_UNUSED (throw_after);
+
#endif // _RWSTD_NO_EXCEPTIONS
- rw_assert (caught == expected, 0, tcase.line,
- "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
- "%{:}unexpectedly caught %s%{;}",
- __LINE__, 0 != expected, expected, caught, caught);
}
/**************************************************************************/