You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/04/25 03:32:13 UTC

svn commit: r396754 - /incubator/stdcxx/trunk/tests/strings/21.string.append.cpp

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  <se...@roguewave.com>

	* 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);
 }
 
 /**************************************************************************/



Re: svn commit: r396754 - /incubator/stdcxx/trunk/tests/strings/21.string.append.cpp

Posted by Martin Sebor <se...@roguewave.com>.
sebor@apache.org wrote:
> 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  <se...@roguewave.com>
> 
> 	* 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.

Hey Anton, this change eliminates code duplication between the
test_exceptions() and test_append() functions. Could you please
incorporate it into all new tests? Also, when you have a chance,
it would be good to go back to the existing tests and do the same
thing there as well.

Btw., after this change the test fails 6 assertions, all on line
336, one for each specialization of the test template (see below).
I'm having trouble understanding that test case. What is the
meaning of the expected result (the TestCase::res member) being
null? (I don't think the case was being handled in the test prior
to the change which is why I suspect the test had been passing.)

# ASSERTION (S7) (4 lines):
# TEXT: line 609. std::string ({ 'x' <repeats 4095 times> }).append 
(*this, 0, 0) expected (null), length 3, got { 'x' <repeats 4095 times> 
}, length 4095
# CLAUSE: lib.string.append
# LINE: 336

Martin

PS Btw., shouldn't this test fail for the same reason as the
replace test does, i.e., because of STDCXX-170:
http://issues.apache.org/jira/browse/STDCXX-170