stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r396952 - /incubator/stdcxx/trunk/tests/strings/21.string.op.plus.equal.cpp
Date Tue, 25 Apr 2006 19:01:36 GMT
Author: sebor
Date: Tue Apr 25 12:01:26 2006
New Revision: 396952

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

	STDCXX-4
	* 21.string.plus_equal.cpp: Enhanced and ported to new test driver.

Modified:
    incubator/stdcxx/trunk/tests/strings/21.string.op.plus.equal.cpp

Modified: incubator/stdcxx/trunk/tests/strings/21.string.op.plus.equal.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/strings/21.string.op.plus.equal.cpp?rev=396952&r1=396951&r2=396952&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.op.plus.equal.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.op.plus.equal.cpp Tue Apr 25 12:01:26 2006
@@ -6,292 +6,476 @@
  *
  ***************************************************************************
  *
- * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
- * Software division. Licensed 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 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2006 Rogue Wave Software.
+ *
+ * Licensed 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>
-
-#include <cmdopt.h>
-#include <driver.h>
+#include <string>       // for string
+#include <cstdlib>      // for free(), size_t
+#include <stdexcept>    // for out_of_range, length_error
+
+#include <cmdopt.h>     // for rw_enabled()
+#include <driver.h>     // for rw_test()
+
+#include <rw_printf.h>  // for rw_asnprintf()
+#include <rw_char.h>    // for rw_widen()
+#include <alg_test.h>   // for InputIter<>
+
+#include <21.strings.h>
+
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+#  include <rw_new.h>   // for bad_alloc, replacement operator new
+#else
+#  include <new>        // for bad_alloc
+#endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+#define OpPlusEqOverload   StringMembers::OverloadId
+#define OpPlusEq(which)    StringMembers::op_plus_eq_ ## which
+
+typedef StringMembers::TestCase TestCase;
+typedef StringMembers::Test     Test;
+typedef StringMembers::Function MemFun;
 
 /**************************************************************************/
 
-template <class _CharT>
-class Lit { };
+// for convenience and brevity
+#define LSTR      long_string
+#define LLEN      long_string_len
+
+static const std::size_t long_string_len = 4096;
+static char long_string [long_string_len];
+
+static const char* const exceptions[] = {
+    "unknown exception", "out_of_range", "length_error",
+    "bad_alloc", "exception"
+};
 
-_RWSTD_SPECIALIZED_CLASS
-class Lit<char>
-{
-public:
-    static const char null[];
-    static const char abcdefg[];
-    static const char dummy[];
-    static const char testString[];
-    static const char differentString[];
-    static const char veryLongTestString[];
-    static const char a[];
-    static const char b[];
-    static const char longTestString[];
-    static const char anotherTestString[];
-    static const char testStringAnotherTestString[];
-    static const char reallyLong[];
-    static const char t[];
-    static const char s[];
-    static const char testStrings[];
+// used to exercise
+// operator += (const charT* s)
+static const TestCase
+ptr_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
+    //    |             |             |        |        -1 - exc. safety
+    //    |             |             |        |
+    //    |             |             |        +--------------+
+    //    V             V             V                       V
+    TEST ("ab",         "c",          "abc",                  0),
+
+    TEST ("",           "",           "",                     0),
+    TEST ("",           "\0",         "",                     0),
+    TEST ("",           "abc",        "abc",                  0),
+
+    TEST ("\0",         "",           "\0",                   0),
+    TEST ("\0",         "a",          "\0a",                  0),
+    TEST ("\0",         "\0\0",       "\0",                   0),
+
+    TEST ("ab",         "cd",         "abcd",                 0),
+    TEST ("bcd",        "a",          "bcda",                 0),
+    TEST ("cde",        "ab",         "cdeab",                0),
+    TEST ("abc",        "",           "abc",                  0),
+    TEST ("ab",         "c\0e",       "abc",                  0),
+
+    TEST ("\0\0ab",     "cdefghij",   "\0\0abcdefghij",       0),
+    TEST ("a\0\0b",     "cdefghij",   "a\0\0bcdefghij",       0),
+    TEST ("ab\0\0",     "cdefghij",   "ab\0\0cdefghij",       0),
+    TEST ("a\0b\0\0c",  "e\0",        "a\0b\0\0ce",           0),
+    TEST ("\0ab\0\0c",  "e\0",        "\0ab\0\0ce",           0),
+    TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
+
+    TEST ("",           LSTR,         LSTR,                   0),
+    TEST (LSTR,         "",           LSTR,                   0),
+
+    TEST ("",           0,            "",                     0),
+    TEST ("abc",        0,            "abcabc",               0),
+    TEST ("a\0\0bc",    0,            "a\0\0bca",             0),
+    TEST ("\0\0abc",    0,            "\0\0abc",              0),
+    TEST ("abc\0\0",    0,            "abc\0\0abc",           0),
 
-};
+    TEST ("",           LSTR,         LSTR,                  -1),
 
-const char Lit<char>:: null[] = "\0";
-const char Lit<char>:: abcdefg[] = "abcdefg";
-const char Lit<char>:: dummy[] = "dummy";
-const char Lit<char>:: testString[] = "test string";
-const char Lit<char>:: differentString[]= "different string";
-const char Lit<char>:: veryLongTestString[] = "very long test string";
-const char Lit<char>:: a[] = "a";
-const char Lit<char>:: b[] = "b";
-const char Lit<char>:: longTestString[] = "long test string";
-const char Lit<char>:: anotherTestString[] = "another test string";
-const char Lit<char>:: testStringAnotherTestString[] = "test stringanother test string";
-
-const char Lit<char>:: reallyLong[] = "Really, really long test string that seems to
never stop";
-const char Lit<char>:: t[] = "t";
-const char Lit<char>:: s[] = "s";
-const char Lit<char>:: testStrings[] = "test strings";
-
-
-#ifndef _RWSTD_NO_WCHAR_T
-_RWSTD_SPECIALIZED_CLASS
-class Lit<wchar_t>
-{
-public:
-    static const wchar_t null[];
-    static const wchar_t abcdefg[];
-    static const wchar_t dummy[];
-    static const wchar_t testString[];
-    static const wchar_t differentString[];
-    static const wchar_t veryLongTestString[];
-    static const wchar_t a[];
-    static const wchar_t b[];
-    static const wchar_t longTestString[];
-    static const wchar_t anotherTestString[];
-    static const wchar_t testStringAnotherTestString[];
-    static const wchar_t reallyLong[];
-    static const wchar_t t[];
-    static const wchar_t s[];
-    static const wchar_t testStrings[];
+    TEST ("last",       "test",       "lasttest",             0)
 };
 
-const wchar_t Lit<wchar_t>:: null[] = L"\0";
-const wchar_t Lit<wchar_t>:: abcdefg[] = L"abcdefg";
-const wchar_t Lit<wchar_t>:: dummy[] = L"dummy";
-const wchar_t Lit<wchar_t>:: testString[] = L"test string";
-const wchar_t Lit<wchar_t>:: differentString[] = L"different string";
-const wchar_t Lit<wchar_t>:: veryLongTestString[] = L"very long test string";
-const wchar_t Lit<wchar_t>:: a[] = L"a";
-const wchar_t Lit<wchar_t>:: b[] = L"b";
-const wchar_t Lit<wchar_t>:: longTestString[] = L"long test string";
-const wchar_t Lit<wchar_t>:: anotherTestString[] = L"another test string";
-const wchar_t Lit<wchar_t>:: testStringAnotherTestString[] = L"test stringanother test
string";
-const wchar_t Lit<wchar_t>:: reallyLong[] = L"Really, really long test string that
seems to never stop";
-const wchar_t Lit<wchar_t>:: t[] = L"t";
-const wchar_t Lit<wchar_t>:: s[] = L"s";
-const wchar_t Lit<wchar_t>:: testStrings[] = L"test strings";
-#endif
-
 /**************************************************************************/
 
-template<typename T>
-void test_plus_equal (T, const char*)
-{
-    typedef std::char_traits<T>                     Traits;
-    typedef std::allocator<T>                       Allocator;
-    typedef std::basic_string<T, Traits, Allocator> String;
-
-    rw_info (0, 0, 0, "Plus-equal operator with string parameter");
-
-    {
-        String t1;
-        String t2;
-
-        // Assigning nullString plus-equal nullString
-        t1 += t2;
-
-        rw_assert ((t1 == Lit<T>::null), 0, __LINE__, "B27");
-
-        // Correctly references nullString
-        rw_assert (t1.data () == String ().data (), 0, __LINE__, "B28");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == 0), 0, __LINE__, "B29");
-    }
-
-    {
-        String t1;
-        String t2(Lit<T>::testString);
-
-
-        t1 += t2;
-
-        // Assigning nullString plus-equal char string
-        rw_assert ((t1 == t2), 0, __LINE__, "B30");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == t2.length()), 0, __LINE__, "B31");
-    }
-
-    {
-        String t1(Lit<T>::testString);
-        String t2;
-
-        t1 += t2;
+// used to exercise
+// operator += (const basic_string& str)
+static const TestCase
+str_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
+    //    |             |             |        |        -1 - exc. safety
+    //    |             |             |        |
+    //    |             |             |        +--------------+
+    //    V             V             V                       V
+    TEST ("ab",         "c",          "abc",                  0),
+
+    TEST ("",           "",           "",                     0),
+    TEST ("",           "\0",         "\0",                   0),
+    TEST ("",           "abc",        "abc",                  0),
+
+    TEST ("\0",         "",           "\0",                   0),
+    TEST ("\0",         "a",          "\0a",                  0),
+    TEST ("\0",         "\0\0",       "\0\0\0",               0),
+
+    TEST ("ab",         "cd",         "abcd",                 0),
+    TEST ("bcd",        "a",          "bcda",                 0),
+    TEST ("cde",        "ab",         "cdeab",                0),
+    TEST ("abc",        "",           "abc",                  0),
+    TEST ("ab",         "c\0e",       "abc\0e",               0),
+
+    TEST ("\0\0ab",     "cdefghij",   "\0\0abcdefghij",       0),
+    TEST ("a\0\0b",     "cdefghij",   "a\0\0bcdefghij",       0),
+    TEST ("ab\0\0",     "cdefghij",   "ab\0\0cdefghij",       0),
+    TEST ("a\0b\0\0c",  "e\0",        "a\0b\0\0ce\0",         0),
+    TEST ("\0ab\0\0c",  "e\0",        "\0ab\0\0ce\0",         0),
+    TEST ("ab\0\0c\0",  "\0e",        "ab\0\0c\0\0e",         0),
+    TEST ("abcdefghij", "abcdefghij", "abcdefghijabcdefghij", 0),
+
+    TEST ("",           LSTR,         LSTR,                   0),
+    TEST (LSTR,         "",           LSTR,                   0),
+
+    TEST ("",           0,            "",                     0),
+    TEST ("abc",        0,            "abcabc",               0),
+    TEST ("a\0\0bc",    0,            "a\0\0bca\0\0bc",       0),
+    TEST ("\0\0abc",    0,            "\0\0abc\0\0abc",       0),
+    TEST ("abc\0\0",    0,            "abc\0\0abc\0\0",       0),
 
-        // Assigning char string plus-equal nullString
-        rw_assert ((t1==Lit<T>::testString), 0, __LINE__, "B32");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == 11), 0, __LINE__, "B33");
-    }
-
-    {
-        String t1 (Lit<T>::testString);
-        String t2 (Lit<T>::anotherTestString);
-
-        typename String::size_type t1_len = t1.length ();
-        typename String::size_type t2_len = t2.length ();
-
-        t1 += t2;
-
-        // Assigning char string plus-equal char string
-        rw_assert ((t1 == Lit<T>::testStringAnotherTestString),
-                   0, __LINE__, "B34");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == (t1_len+t2_len)), 0, __LINE__, "B35");
-    }
+    TEST ("",           LSTR,         LSTR,                  -1),
 
-    rw_info (0, 0, 0, "Plus-equal operator with const char pointer");
-
-    {
-        String t1;
-
-        t1 += Lit<T>::null;
-
-        // Assigning nullString plus-equal nullString
-        rw_assert ((t1 == Lit<T>::null), 0, __LINE__, "B36");
-
-        // Correctly references nullString
-        rw_assert (t1.data () == String ().data (), 0, __LINE__, "B37");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == 0), 0, __LINE__, "B38");
-    }
-
-    {
-        String t1;
-        t1 += Lit<T>::testString;
-
-        // Assigning nullString plus-equal char string
-        rw_assert ((t1==Lit<T>::testString), 0, __LINE__, "B39");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == 11), 0, __LINE__, "B40");
-    }
-
-    {
-        String t1(Lit<T>::testString);
-        t1 += Lit<T>::null;
-
-        // Assigning char string plus-equal nullString
-        rw_assert ((t1 == Lit<T>::testString), 0, __LINE__, "B41");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == 11), 0, __LINE__, "B42");
-    }
-
-    {
-        String t1(Lit<T>::testString);
-
-        typename String::size_type t1_len = t1.length();
-        typename String::size_type t2_len =
-            std::char_traits<T>::length(Lit<T>::anotherTestString);
+    TEST ("last",       "test",       "lasttest",             0)
+};
 
-        t1 += Lit<T>::anotherTestString;
+/**************************************************************************/
 
-        // Assigning char string plus-equal char string
-        rw_assert ((t1 == Lit<T>::testStringAnotherTestString),
-                   0, __LINE__, "B43");
+// used to exercise
+// operator+= (value_type c)
+static const TestCase
+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
+    //    |            |   |           |       -1 - exc. safety
+    //    |            |   |           |
+    //    |            |   |           +----+
+    //    V            V   V                V
+    TEST ("ab",        'c', "abc",          0),
+
+    TEST ("",          'a',  "a",           0),
+    TEST ("",          '\0', "\0",          0),
+
+    TEST ("\0",        'a',  "\0a",         0),
+    TEST ("\0",        '\0', "\0\0",        0),
+
+    TEST ("cde",       'a',  "cdea",        0),
+    TEST ("abc",       '\0', "abc\0",       0),
+
+    TEST ("a\0b\0\0c", '\0', "a\0b\0\0c\0", 0),
+    TEST ("\0ab\0\0c", '\0', "\0ab\0\0c\0", 0),
+    TEST ("a\0bc\0\0", 'a',  "a\0bc\0\0a",  0),
 
-        // Correctly returns length
-        rw_assert ((t1.length() == (t1_len+t2_len)), 0, __LINE__, "B44");
-    }
+    TEST ("last",      't', "lastt",        0)
+};
 
-    rw_info (0, 0, 0, "Plus-equal operator with char parameter");
-    {
-        String t1;
-        t1 += Lit<T>::null[0];
+/**************************************************************************/
 
-        // Assigning nullString plus-equal zero
-        rw_assert ((t1 != Lit<T>::null), 0, __LINE__, "B45");
+template <class charT, class Traits>
+void test_op_plus_eq (charT, Traits*,
+                      OpPlusEqOverload which,
+                      const TestCase  &cs)
+{
+    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 warg [LLEN];
+
+    rw_widen (wstr, cs.str, cs.str_len);
+    rw_widen (warg, cs.arg, cs.arg_len);
+
+    TestString s_str (wstr, cs.str_len);
+    TestString s_arg (warg, cs.arg_len);
+
+    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 arg_ptr = cs.arg ? warg : s_str.c_str ();
+    const TestString&  arg_str = cs.arg ? s_arg : s_str;
+    const charT        arg_val = make_char (char (cs.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 appendion
+    // finally succeeds (i.e, no exception is thrown)
+    for ( ; ; ) {
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+#  ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+        if (-1 == cs.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
+
+        // is some exception expected ?
+        const char* expected = 0;
+        if (1 == cs.bthrow)
+            expected = exceptions [2];      // length_error
+        if (-1 == cs.bthrow)
+            expected = exceptions [3];      // bad_alloc
+
+        const char* caught = 0;
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+        if (cs.bthrow)
+            return;
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+        try {
+            switch (which) {
+            case OpPlusEq (ptr): {
+                const TestString& s_res = s_str += arg_ptr;
+                res_off = &s_res - &s_str;
+                break;
+            }
+
+            case OpPlusEq (str): {
+                const TestString& s_res = s_str += arg_str;
+                res_off = &s_res - &s_str;
+                break;
+            }
+
+            case OpPlusEq (val): {
+                const TestString& s_res = s_str += arg_val;
+                res_off = &s_res - &s_str;
+                break;
+            }
+
+            default:
+                RW_ASSERT ("test logic error: unknown operator += overload");
+                return;
+            }
+
+            // verify the returned value
+            rw_assert (0 == res_off, 0, cs.line,
+                       "line %d. %{$FUNCALL} returned invalid reference, "
+                       "offset is %zu", __LINE__, res_off);
+
+            // verfiy that strings length are equal
+            rw_assert (cs.res_len == s_str.size (), 0, cs.line,
+                       "line %d. %{$FUNCALL} expected %{#*s} "
+                       "with length %zu, got %{/*.*Gs} with length %zu",
+                       __LINE__, int (cs.res_len), cs.res, cs.res_len,
+                       int (sizeof (charT)), int (s_str.size ()),
+                       s_str.c_str (), s_str.size ());
+
+            if (cs.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 (cs.res, s_str.c_str(), cs.res_len);
+
+                rw_assert (match == cs.res_len, 0, cs.line,
+                           "line %d. %{$FUNCALL} expected %{#*s}, "
+                           "got %{/*.*Gs}, difference at offset %zu",
+                           __LINE__, int (cs.res_len), cs.res,
+                           int (sizeof (charT)), int (s_str.size ()),
+                           s_str.c_str (), match);
+            }
+        }
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+        catch (const std::length_error &ex) {
+            caught = exceptions [2];
+            rw_assert (caught == expected, 0, cs.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 == cs.bthrow, 0, cs.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, cs.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, cs.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, cs.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, cs.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, cs.line,
+                       "line %d: %{$FUNCALL}: begin() unexpectedly "
+                       "changed from after an exception by %d",
+                       __LINE__, s_str.begin () - begin);
+
+            if (-1 == cs.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 != cs.bthrow) {
+            rw_assert (caught == expected, 0, cs.line,
+                       "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
+                       "%{:}unexpectedly caught %s%{;}",
+                       __LINE__, 0 != expected, expected, caught, caught);
+        }
+
+        break;
+    }
+
+#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, cs.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 (size);
+    _RWSTD_UNUSED (capacity);
+    _RWSTD_UNUSED (throw_after);
 
-        // Correctly returns length
-        rw_assert ((t1.length() == 1), 0, __LINE__, "B46");
-    }
+#endif   // _RWSTD_NO_EXCEPTIONS
 
-    {
-        String t1;
+}
 
-        t1 += Lit<T>::t[0];
+/**************************************************************************/
 
-        // Assigning nullString plus-equal char
-        rw_assert ((t1 == Lit<T>::t), 0, __LINE__, "B47");
+DEFINE_TEST_DISPATCH (test_op_plus_eq);
 
-        // Correctly returns length
-        rw_assert ((t1.length() == 1), 0, __LINE__, "B48");
+static int
+run_test (int, char*[])
+{
+    if ('\0' == LSTR [0]) {
+        // initialize LSTR
+        for (std::size_t i = 0; i != sizeof LSTR - 1; ++i)
+            LSTR [i] = 'x';
     }
 
-    {
-        String t1(Lit<T>::testString);
-
-        t1 += Lit<T>::s[0];
+    static const StringMembers::Test
+    tests [] = {
 
-        // Assigning char string plus-equal char
-        rw_assert ((t1 == Lit<T>::testStrings), 0, __LINE__, "B49");
-
-        // Correctly returns length
-        rw_assert ((t1.length() == 12), 0, __LINE__, "B50");
+#undef TEST
+#define TEST(tag) {                                             \
+        StringMembers::op_plus_eq_ ## tag, tag ## _test_cases,  \
+        sizeof tag ## _test_cases / sizeof *tag ## _test_cases  \
     }
-}
 
-/**************************************************************************/
+        TEST (ptr),
+        TEST (str),
+        TEST (val)
+    };
 
-int run_test (int, char*[])
-{
-    if (rw_enabled ("char"))
-        test_plus_equal (char (), "char");
-    else
-        rw_note (0, __FILE__, __LINE__, "char test disabled");
-
-#ifndef _RWSTD_NO_WCHAR_T
-
-    if (rw_enabled ("wchar_t"))
-        test_plus_equal (wchar_t (), "wchar_t");
-    else
-        rw_note (0, __FILE__, __LINE__, "wchar_t test disabled");
+    const std::size_t test_count = sizeof tests / sizeof *tests;
 
-#endif   // _RWSTD_NO_WCHAR_T
+    StringMembers::run_test (test_op_plus_eq, tests, test_count);
 
     return 0;
-
 }
 
 /**************************************************************************/
@@ -301,5 +485,26 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.string.op+=",
                     0 /* no comment */, run_test,
-                    0 /* co command line options */);
+                    "|-no-char_traits# "
+                    "|-no-user_traits# "
+                    "|-no-user_char# "
+                    "|-no-exceptions# "
+                    "|-no-exception-safety# "
+
+                    "|-no-op-append-ptr# "
+                    "|-no-op-append-str# "
+                    "|-no-op-append-val#",
+
+                    &StringMembers::opt_no_char_traits,
+                    &StringMembers::opt_no_user_traits,
+                    &StringMembers::opt_no_user_char,
+                    &StringMembers::opt_no_exceptions,
+                    &StringMembers::opt_no_exception_safety,
+
+                    &Disabled (OpPlusEq (ptr)),
+                    &Disabled (OpPlusEq (str)),
+                    &Disabled (OpPlusEq (val)),
+
+                    // sentinel
+                    (void*)0);
 }



Mime
View raw message