stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r396912 [1/2] - in /incubator/stdcxx/trunk/tests/strings: 21.string.append.cpp 21.string.assign.cpp 21.string.insert.cpp 21.string.replace.cpp
Date Tue, 25 Apr 2006 16:30:12 GMT
Author: sebor
Date: Tue Apr 25 09:30:04 2006
New Revision: 396912

URL: http://svn.apache.org/viewcvs?rev=396912&view=rev
Log:
2006-04-25 Anton Pevtsov <antonp@moscow.vdiweb.com>

	* 21.string.append.cpp (range_test_cases): Bug in test case
	description fixed.
	(test_append_range): Typo bug fixed.
	* 21.string.assign.cpp (exceptions): Added elements and renamed
	from exp_exceptions for clarity.
	(test_exceptions): Merged the body of the function into the
	test_assign function and removed the declaration of the former.
	(test_assign): Exercised both the function exception safety and
	the behavior of the function under normal conditions.
	* 21.string.insert.cpp: Same.
	* 21.string.replace.cpp (exceptions): Added elements and renamed
	from exp_exceptions for clarity.
	(size_size_ptr_test_cases, size_size_str_test_cases, etc): Merged
	with equal iterator version arrays.
	(test_exceptions): Merged the body of the function into the
	test_assign function and removed the declaration of the former.
	(test_replace): 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
    incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp
    incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp
    incubator/stdcxx/trunk/tests/strings/21.string.replace.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=396912&r1=396911&r2=396912&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.append.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.append.cpp Tue Apr 25 09:30:04 2006
@@ -42,6 +42,10 @@
    // disabled for compilers such as IBM VAC++ or MSVC
    // that can't reliably replace the operators
 #  include <rw_new.h>
+
+#else
+#  include <new>
+
 #endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
 
@@ -333,7 +337,7 @@
     TEST ("",          "a",         2, 0,  "",                1),
     TEST ("",          LSTR,LLEN + 10, 0,  "",                1),
 
-    TEST (LSTR,        0,           0, 0, 0,                 -1),
+    TEST (LSTR,        0,           0, 0,  LSTR,             -1),
 
     TEST ("last",      "test",      0, 4, "lasttest",         0)
 };
@@ -421,7 +425,7 @@
     std::size_t off_last = tcase.off + tcase.size;
 
     if (tcase.arg) {
-        if (off_last < s_arg.size ())
+        if (off_last > s_arg.size ())
             off_last = s_arg.size ();
 
         const charT* const beg = wsrc + tcase.off;

Modified: incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp?rev=396912&r1=396911&r2=396912&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp Tue Apr 25 09:30:04 2006
@@ -43,6 +43,10 @@
    // disabled for compilers such as IBM VAC++ or MSVC
    // that can't reliably replace the operators
 #  include <rw_new.h>
+
+#else
+#  include <new>
+
 #endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
 
@@ -62,8 +66,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"
+};
 
 /**************************************************************************/
 
@@ -400,152 +406,6 @@
 
 /**************************************************************************/
 
-template <class charT, class Traits>
-void test_exceptions (charT, Traits*,
-                      AssignOverload  which,
-                      const TestCase &tcase)
-{
-    typedef std::allocator<charT>                        Allocator;
-    typedef std::basic_string <charT, Traits, Allocator> 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);
-
-    /* const */ TestString s_str (wstr, tcase.str_len);
-    const       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
-
-    const charT* const arg_ptr = tcase.arg ? wsrc : s_str.c_str ();
-    const TestString&  arg_str = tcase.arg ? s_arg : s_str;
-    const charT        arg_val = make_char (char (tcase.val), (charT*)0);
-
-    // iterate for`n=throw_after' starting at the next call to operator
-    // new, forcing each call to throw an exception, until the assignion
-    // 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 {
-            switch (which) {
-            case Assign (ptr):
-                s_str.assign (arg_ptr);
-                break;
-
-            case Assign (str):
-                s_str.assign (arg_str);
-                break;
-
-            case Assign (ptr_size):
-                s_str.assign (arg_ptr, tcase.size);
-                break;
-
-            case Assign (str_size_size):
-                s_str.assign (arg_str, tcase.off, tcase.size);
-                break;
-
-            case Assign (size_val):
-                s_str.assign (tcase.size, arg_val);
-                break;
-
-            case Assign (range): {
-                const ConstStringIter first = s_arg.begin ();
-                const ConstStringIter last  = s_arg.end ();
-                s_str.assign (first, last);
-                break;
-            }
-
-            default:
-                RW_ASSERT (!"test logic error: unknown assign overload");
-            }
-
-            break;   // out of for loop
-        }
-        _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 assign 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_assign_range (charT          *wstr,
                         charT          *wsrc,
@@ -555,6 +415,7 @@
 {
     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";
@@ -565,7 +426,8 @@
     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 (wsrc + tcase.off, wsrc + tcase.off, wsrc + off_last);
@@ -575,7 +437,6 @@
         s_str.assign (first, last);
     }
     else {
-        typedef typename String::iterator StringIter;
 
         const StringIter first (s_str.begin () + tcase.off);
         const StringIter last  (off_last > s_str.size () ?
@@ -635,11 +496,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];
@@ -657,108 +514,228 @@
     const       TestString s_arg (wsrc, tcase.arg_len);
 
     std::size_t res_off = 0;
+    std::size_t throw_after = 0;
     std::size_t size = tcase.size >= 0 ? tcase.size : s_str.max_size () + 1;
 
+    const std::size_t     ssize    = s_str.size ();
+    const std::size_t     capacity = s_str.capacity ();
+    const ConstStringIter begin    = s_str.begin ();
+
     // first function argument
     const charT* const arg_ptr = tcase.arg ? wsrc : s_str.c_str ();
     const TestString&  arg_str = tcase.arg ? s_arg : s_str;
 
-    // address of returned reference
-    const TestString* res_ptr = 0;
+#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 && Assign (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;
+
+#  endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+#ifndef _RWSTD_NO_EXCEPTIONS
 
-    const char* caught = 0;
+        // is some exception expected ?
+        const char* expected = 0;
+        if (1 == tcase.bthrow && Assign (str_size_size) == which)
+            expected = exceptions [1];   // out_of_range
+        if (2 == tcase.bthrow)
+            expected = exceptions [2];   // length_error
+        if (-1 == tcase.bthrow)
+            expected = exceptions [3];   // bad_alloc
 
-    try {
+        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 Assign (ptr):
-        res_ptr = &s_str.assign (arg_ptr);
-        break;
+        try {
+            switch (which) {
+            case Assign (ptr): {
+                const TestString& s_res = s_str.assign (arg_ptr);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    case Assign (str):
-        res_ptr = &s_str.assign (arg_str);
-        break;
+            case Assign (str): {
+                const TestString& s_res = s_str.assign (arg_str);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    case Assign (ptr_size):
-        res_ptr = &s_str.assign (arg_ptr, size);
-        break;
+            case Assign (ptr_size): {
+                const TestString& s_res = s_str.assign (arg_ptr, size);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    case Assign (str_size_size):
-        res_ptr = &s_str.assign (arg_str, tcase.off, size);
-        break;
+            case Assign (str_size_size): {
+                const TestString& s_res = 
+                    s_str.assign (arg_str, tcase.off, size);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    case Assign (size_val): {
-        const charT val = make_char (char (tcase.val), (charT*)0);
-        res_ptr = &s_str.assign (size, val);
-        break;
-    }
+            case Assign (size_val): {
+                const charT val = make_char (char (tcase.val), (charT*)0);
+                const TestString& s_res = s_str.assign (size, val);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    default:
-        RW_ASSERT (!"test logic error: unknown assign overload");
-    }
+            default:
+                RW_ASSERT (!"test logic error: unknown assign overload");
+            }
 
-    res_off = res_ptr - &s_str;
 
-    // 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 ());
+            // 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 ());
+
+            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 off %zu",
+                           __LINE__, int (tcase.res_len), tcase.res,
+                           int (sizeof (charT)), int (s_str.size ()), 
+                           s_str.c_str (), match);
+            }
+        }
 
-    // verfiy that assign results match expected result
-    const std::size_t match =
-        rw_match (tcase.res, s_str.c_str(), tcase.res_len);
+#ifndef _RWSTD_NO_EXCEPTIONS
 
-    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);
+        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);
+        }
 
-#ifndef _RWSTD_NO_EXCEPTIONS
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
 
+    _RWSTD_UNUSED (should_throw);
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+        if (caught) {
+            // verify that an exception thrown during allocation
+            // didn't cause a change in the state of the object
+
+            rw_assert (s_str.size () == ssize, 0, tcase.line,
+                       "line %d: %{$FUNCALL}: size unexpectedly changed "
+                       "from %zu to %zu after an exception",
+                       __LINE__, ssize, 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);
+
+            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);
 }
 
 /**************************************************************************/

Modified: incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp?rev=396912&r1=396911&r2=396912&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp Tue Apr 25 09:30:04 2006
@@ -43,6 +43,10 @@
    // disabled for compilers such as IBM VAC++ or MSVC
    // that can't reliably replace the operators
 #  include <rw_new.h>
+
+#else
+#  include <new>
+
 #endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
 #define InsertOverload    StringMembers::OverloadId
@@ -62,8 +66,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"
+};
 
 /**************************************************************************/
 
@@ -202,93 +208,14 @@
 
 /**************************************************************************/
 
-// used to exercise
-// insert (size_type off, basic_string& str, size_type off2, size_type n)
-static const TestCase size_str_size_size_test_cases [] = {
-
-#undef TEST
-#define TEST(str, off, arg, off2, size2, res, bthrow) {                 \
-        __LINE__, off, -1, off2, size2, -1, str, sizeof str - 1,        \
-        arg, sizeof arg - 1, res, sizeof res - 1, bthrow                \
-    }
-
-    //    +----------------------------------------- controlled sequence
-    //    |            +---------------------------- insert() pos argument
-    //    |            |  +------------------------- sequence to be inserted
-    //    |            |  |            +------------ insert() off2 argument
-    //    |            |  |            |  +--------- insert() num 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                   V
-    TEST ("ab",        0, "c",         0, 1, "cab",              0),
-
-    TEST ("",          0, "",          0, 0,  "",                0),
-    TEST ("",          0, "abc",       1, 1,  "b",               0),
-    TEST ("",          0, "\0",        0, 1,  "\0",              0),
-
-    TEST ("\0",        0, "",          0, 0,  "\0",              0),
-    TEST ("\0",        1, "",          0, 0,  "\0",              0),
-
-    TEST ("abc",       0, "",          0, 0,  "abc",             0),
-    TEST ("abc",       1, "",          0, 0,  "abc",             0),
-    TEST ("abc",       3, "",          0, 0,  "abc",             0),
-
-    TEST ("\0",        0, "a",         0, 1,  "a\0",             0),
-    TEST ("\0",        1, "a",         0, 1,  "\0a",             0),
-    TEST ("\0",        0, "\0\0",      1, 1,  "\0\0",            0),
-    TEST ("\0",        1, "\0\0",      0, 2,  "\0\0\0",          0),
-    TEST ("\0",        1, "\0\0",      1, 5,  "\0\0",            0),
-
-    TEST ("cde",       0, "ab",        0, 2,  "abcde",           0),
-    TEST ("cde",       1, "ab",        0, 1,  "cade",            0),
-    TEST ("cde",       2, "ab",        1, 5,  "cdbe",            0),
-    TEST ("cde",       3, "ab",        1, 1,  "cdeb",            0),
-
-    TEST ("ab",        0, "c\0e",      0, 3,  "c\0eab",          0),
-    TEST ("ab",        1, "c\0e",      1, 2,  "a\0eb",           0),
-    TEST ("ab",        2, "c\0e",      0, 2,  "abc\0",           0),
-
-    TEST ("\0e\0",     1, "\0ab\0\0c", 0, 9,  "\0\0ab\0\0ce\0",  0),
-    TEST ("\0e\0",     1, "\0ab\0\0c", 0, 3,  "\0\0abe\0",       0),
-    TEST ("a\0b\0\0c", 3, "\0e\0",     0, 3,  "a\0b\0e\0\0\0c",  0),
-    TEST ("a\0b\0\0c", 2, "\0\0e\0",   0, 2,  "a\0\0\0b\0\0c",   0),
-    TEST ("\0ab\0\0c", 0, "\0e\0",     2, 1,  "\0\0ab\0\0c",     0),
-    TEST ("a\0bc\0\0", 6, "\0e",       0, 2,  "a\0bc\0\0\0e",    0),
-
-    TEST ("abc",       0, 0,           1, 1,  "babc",            0),
-    TEST ("abc",       2, 0,           0, 2,  "ababc",           0),
-    TEST ("a\0bc\0\0", 0, 0,           4, 2,  "\0\0a\0bc\0\0",   0),
-    TEST ("a\0bc\0\0", 6, 0,           1, 3,  "a\0bc\0\0\0bc",   0),
-    TEST ("abcdef",    0, 0,           1, 2,  "bcabcdef",        0),
-
-    TEST ("",          0, LSTR,        0, LLEN, LSTR,            0),
-    TEST (LSTR,        0, "",          0, 0,    LSTR,            0),
-
-    TEST ("\0",        2, "",          0, 0,  "",                1),
-    TEST ("",          0, "\0",        2, 0,  "",                2),
-
-    TEST ("a",         2, "",          0, 0,  "",                1),
-    TEST ("",          0, "a",         2, 0,  "",                2),
-
-    TEST (LSTR,LLEN + 10, "",          0, 0,  "",                1),
-    TEST ("",          0, LSTR,LLEN + 10, 0,  "",                2),
-
-    TEST (LSTR,        0, 0,           0, 0, 0,                 -1),
-
-    TEST ("last",      4, "test",      0, 4,  "lasttest",        0)
-};
-
-/**************************************************************************/
 // exrcises
+// insert (size_type off, basic_string& str, size_type off2, size_type n)
 // insert (iterator p, InputIterator first, InputIterator last)
 static const TestCase range_test_cases [] = {
 
+// range_test_cases serves a double duty
+#define size_str_size_size_test_cases range_test_cases
+
 #undef TEST
 #define TEST(str, off, arg, off2, size2, res, bthrow) {                 \
         __LINE__, off, -1, off2, size2, -1, str, sizeof str - 1,        \
@@ -362,7 +289,7 @@
     TEST (LSTR,LLEN + 10, "",          0, 0,  "",                1),
     TEST ("",          0, LSTR,LLEN + 10, 0,  "",                2),
 
-    TEST (LSTR,        0, 0,           0, 0, 0,                 -1),
+    TEST ("",          0, LSTR, 0, LLEN - 1, LSTR,              -1),
 
     TEST ("last",      4, "test",      0, 4,  "lasttest",        0)
 };
@@ -438,72 +365,14 @@
 
 /**************************************************************************/
 
-// used to exercise
-// insert (size_type pos, size_type n, charT c)
-static const TestCase size_size_val_test_cases [] = {
-
-#undef TEST
-#define TEST(str, off, size2, val, res, bthrow) {               \
-        __LINE__, off, -1, -1, size2, val, str, sizeof str - 1, \
-        0, 0, res, sizeof res - 1, bthrow                       \
-    }
-
-    //    +----------------------------------------- controlled sequence
-    //    |            +---------------------------- insert() pos argument
-    //    |            |  +------------------------- insert() size2 argument
-    //    |            |  |   +--------------------- character to be inserted
-    //    |            |  |   |   +----------------- 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",        0, 1, 'c', "cab",              0),
-
-    TEST ("",          0, 0, ' ',  "",                0),
-    TEST ("",          0, 1, 'b',  "b",               0),
-
-    TEST ("\0",        0, 0, ' ',  "\0",              0),
-    TEST ("\0",        1, 0, ' ',  "\0",              0),
-    TEST ("",          0, 2, '\0', "\0\0",            0),
-
-    TEST ("\0",        0, 1, 'a',  "a\0",             0),
-    TEST ("\0",        1, 1, 'a',  "\0a",             0),
-    TEST ("\0",        0, 1, '\0', "\0\0",            0),
-    TEST ("\0",        1, 2, '\0', "\0\0\0",          0),
-    TEST ("\0",        1, 0, '\0', "\0",              0),
-
-    TEST ("cde",       0, 2, 'a',  "aacde",           0),
-    TEST ("cde",       1, 1, 'a',  "cade",            0),
-    TEST ("cde",       3, 3, 'a',  "cdeaaa",          0),
-    TEST ("cde",       2, 3, 'a',  "cdaaae",          0),
-
-    TEST ("ab",        0, 2, '\0', "\0\0ab",          0),
-    TEST ("ab",        1, 1, '\0', "a\0b",            0),
-    TEST ("ab",        2, 2, '\0', "ab\0\0",          0),
-
-    TEST ("a\0b\0\0c", 3, 2, '\0', "a\0b\0\0\0\0c",   0),
-    TEST ("a\0b\0\0c", 2, 1, '\0', "a\0\0b\0\0c",     0),
-    TEST ("\0ab\0\0c", 0, 3, '\0', "\0\0\0\0ab\0\0c", 0),
-    TEST ("a\0bc\0\0", 6, 2, 'a',  "a\0bc\0\0aa",     0),
-
-    TEST ("",          0, LLEN - 1, 'x', LSTR,        0),
-    TEST (LSTR,        0, 0,        'x', LSTR,        0),
-
-    TEST ("",          0, LLEN - 1, 'x', LSTR,       -1),
-
-    TEST ("last",      4, 4, 't',  "lasttttt",        0)
-};
-
-/**************************************************************************/
-
 // exrecises
+// insert (size_type pos, size_type n, charT c)
 // insert (iterator p, size_type n, charT c)
 static const TestCase size_val_test_cases [] = {
 
+// size_val_test_cases serves a double duty
+#define size_size_val_test_cases size_val_test_cases
+
 #undef TEST
 #define TEST(str, off, size2, val, res, bthrow) {               \
         __LINE__, off, -1, -1, size2, val, str, sizeof str - 1, \
@@ -602,153 +471,15 @@
     TEST ("\0ab\0\0c", 0, '\0', "\0\0ab\0\0c",  0),
     TEST ("a\0bc\0\0", 6,  'a', "a\0bc\0\0a",   0),
 
-    TEST (LSTR,        0,  'c', 0,             -1),
-
-    TEST ("last",      4,  't', "lastt",        0)
-};
-
-/**************************************************************************/
-
-template <class charT, class Traits>
-void test_exceptions (charT, Traits*,
-                      InsertOverload 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 warg [LLEN];
-
-    rw_widen (wstr, tcase.str, tcase.str_len);
-    rw_widen (warg, tcase.arg, tcase.arg_len);
-
-    TestString s_str (wstr, tcase.str_len);
-    TestString s_arg (warg, 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 ();
-
-    const charT* const arg_ptr = tcase.arg ? warg : s_str.c_str ();
-    const TestString&  arg_str = tcase.arg ? s_arg : s_str;
-    const charT        arg_val = make_char (char (tcase.val), (charT*)0);
-
-#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 insertion
-    // 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 (Insert (size_ptr) == which)
-                s_str.insert (tcase.off, arg_ptr);
-
-            else if (Insert (size_str) == which)
-                s_str.insert (tcase.off, arg_str);
-
-            else if (Insert (size_ptr_size) == which)
-                s_str.insert (tcase.off, arg_ptr, tcase.size2);
-
-            else if (Insert (size_str_size_size) == which)
-                s_str.insert (tcase.off, arg_str, tcase.off2, tcase.size2);
-
-            else if (Insert (size_size_val) == which)
-                s_str.insert (tcase.off, tcase.size2, arg_val);
-
-            else if (Insert (size_val) == which) {
-                StringIter it (s_str.begin () + tcase.off);
-                s_str.insert (it, tcase.size2, arg_val);
-            }
-
-            else if (Insert (val) == which) {
-                StringIter it (s_str.begin () + tcase.off);
-                s_str.insert (it, arg_val);
-            }
-
-            else if (Insert (range) == which) {
-                StringIter it (s_str.begin () + tcase.off);
-                s_str.insert (it, 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 insert 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
+#undef TEST
+#define TEST(str, len, off, val, res, bthrow)                           \
+    { __LINE__, off, -1, -1, -1, val, str, len, 0,                      \
+      0, res, sizeof res - 1, bthrow }
 
-    *pst->throw_at_calls_ [0] = std::size_t (-1);
+    TEST (LSTR + 1, LLEN - 2, 0, 'x', LSTR,    -1),
 
-#endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
-}
+    TEST ("last",  4,  4,  't', "lastt",        0)
+};
 
 /**************************************************************************/
 
@@ -784,10 +515,10 @@
         s_str.insert (iter, first, last);
     }
     else {
-        StringIter first (s_str.begin () + tcase.off2);
-        StringIter last  (off_last > s_str.size () ?
-            s_str.end ()
-          : s_str.begin () + off_last);
+        const StringIter first (s_str.begin () + tcase.off2);
+        const StringIter last  (off_last > s_str.size () ?
+                                s_str.end ()
+                              : s_str.begin () + off_last);
 
         s_str.insert (iter, first, last);
     }
@@ -842,11 +573,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;
 
     const bool use_iters = (Insert (val) <= which);
 
@@ -867,125 +594,240 @@
 
     std::size_t res_off = 0;
     std::size_t exp_off = Insert (val) == which ? tcase.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 arg_ptr = tcase.arg ? warg : s_str.c_str ();
     const TestString&  arg_str = tcase.arg ? s_arg : s_str;
     const charT        arg_val = make_char (char (tcase.val), (charT*)0);
 
-    // address of returned reference
-    const TestString* res_ptr = 0;
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
-#ifndef _RWSTD_NO_EXCEPTIONS
+    rwt_free_store* const pst = rwt_get_free_store (0);
 
-    // is some exception expected ?
-    const char* expected = 0;
-    if (1 == tcase.bthrow && !use_iters)
-        expected = exp_exceptions [1];
-    if (2 == tcase.bthrow && Insert (size_str_size_size) == which)
-        expected = exp_exceptions [1];
-    if (3 == tcase.bthrow && !use_iters)
-        expected = exp_exceptions [2];
+#endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
-    const char* caught = 0;
+    // 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 ( ; ; ) {
 
-    try {
+#ifndef _RWSTD_NO_EXCEPTIONS
+#  ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
+        if (-1 == tcase.bthrow)
+            *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
+
+#  endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 #endif   // _RWSTD_NO_EXCEPTIONS
 
-    switch (which)
-    {
-    case Insert (size_ptr): {
-        res_ptr = &s_str.insert (tcase.off, arg_ptr);
-        break;
-    }
+#ifndef _RWSTD_NO_EXCEPTIONS
 
-    case Insert (size_str): {
-        res_ptr = &s_str.insert (tcase.off, arg_str);
-        break;
-    }
+        // is some exception expected ?
+        const char* expected = 0;
+        if (1 == tcase.bthrow && !use_iters)
+            expected = exceptions [1];      // out_of_range
+        if (2 == tcase.bthrow && Insert (size_str_size_size) == which)
+            expected = exceptions [1];      // out_of_range
+        if (3 == tcase.bthrow && !use_iters)
+            expected = exceptions [2];      // length_error
+        if (-1 == tcase.bthrow)
+            expected = exceptions [3];      // bad_alloc
 
-    case Insert (size_ptr_size): {
-        res_ptr = &s_str.insert (tcase.off, arg_ptr, tcase.size2);
-        break;
-    }
+        const char* caught = 0;
 
-    case Insert (size_str_size_size): {
-        res_ptr = &s_str.insert (tcase.off, arg_str, tcase.off2, tcase.size2);
-        break;
-    }
+#endif   // _RWSTD_NO_EXCEPTIONS
 
-    case Insert (size_size_val): {
-        res_ptr = &s_str.insert (tcase.off, tcase.size2, arg_val);
-        break;
-    }
+        try {
+            switch (which) {
+            case Insert (size_ptr): {
+                const TestString& s_res = s_str.insert (tcase.off, arg_ptr);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    case Insert (size_val): {
-        StringIter it (s_str.begin () + tcase.off);
-        s_str.insert (it, tcase.size2, arg_val);
-        break;
-    }
+            case Insert (size_str): {
+                const TestString& s_res = s_str.insert (tcase.off, arg_str);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    case Insert (val): {
-        StringIter it (s_str.begin () + tcase.off);
-        StringIter res_it = s_str.insert (it, arg_val);
-        res_off = res_it - s_str.begin ();
-        break;
-    }
+            case Insert (size_ptr_size): {
+                const TestString& s_res = 
+                    s_str.insert (tcase.off, arg_ptr, tcase.size2);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    default:
-        RW_ASSERT ("test logic error: unknown insert overload");
-        return;
-    }
+            case Insert (size_str_size_size): {
+                const TestString& s_res = 
+                    s_str.insert (tcase.off, arg_str, tcase.off2, tcase.size2);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    if (!use_iters)
-        res_off = res_ptr - &s_str;
+            case Insert (size_size_val): {
+                const TestString& s_res = 
+                    s_str.insert (tcase.off, tcase.size2, arg_val);
+                res_off = &s_res - &s_str;
+                break;
+            }
 
-    // verify the returned value
-    rw_assert (exp_off == res_off, 0, tcase.line,
-               "line %d. %{$FUNCALL} %{?}== %zu, got %zu%{;}"
-               "%{?}returned invalid reference, offset is %zu%{;}",
-               __LINE__, Insert (val) == which, exp_off, res_off,
-               Insert (val) != which, 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 ());
+            case Insert (size_val): {
+                StringIter it (s_str.begin () + tcase.off);
+                s_str.insert (it, tcase.size2, arg_val);
+                break;
+            }
 
-    // verfiy that insert results match expected result
-    const std::size_t match =
-        rw_match (tcase.res, s_str.c_str(), tcase.res_len);
+            case Insert (val): {
+                StringIter it (s_str.begin () + tcase.off);
+                StringIter res_it = s_str.insert (it, arg_val);
+                res_off = res_it - s_str.begin ();
+                break;
+            }
 
-    rw_assert (match == tcase.res_len, 0, tcase.line,
-               "line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
-               "difference at pos %zu",
-               __LINE__, int (tcase.res_len), tcase.res,
-               int (sizeof (charT)), int (s_str.size ()), s_str.c_str (),
-               match);
+            default:
+                RW_ASSERT ("test logic error: unknown insert overload");
+                return;
+            }
+
+            // verify the returned value
+            rw_assert (exp_off == res_off, 0, tcase.line,
+                       "line %d. %{$FUNCALL} %{?}== %zu, got %zu%{;}"
+                       "%{?}returned invalid reference, offset is %zu%{;}",
+                       __LINE__, Insert (val) == which, exp_off, res_off,
+                       Insert (val) != which, 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 ());
+
+            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);
+            }
+        }
 
 #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 (-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);
+        }
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+        _RWSTD_UNUSED (should_throw);
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+        if (caught) {
+            // verify that an exception thrown during allocation
+            // didn't cause a change in the state of the object
+
+            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);
+
+            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);
 }
 
 /**************************************************************************/



Mime
View raw message