You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by an...@apache.org on 2006/03/17 10:03:55 UTC

svn commit: r386577 - /incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp

Author: antonp
Date: Fri Mar 17 01:03:54 2006
New Revision: 386577

URL: http://svn.apache.org/viewcvs?rev=386577&view=rev
Log:
2006-03-17  Anton Pevtsov  <an...@moscow.vdiweb.com>

	STDCXX-4
	* 21.string.replace.cpp: New test exercising lib.string.replace.

Added:
    incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp

Added: incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp?rev=386577&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp (added)
+++ incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp Fri Mar 17 01:03:54 2006
@@ -0,0 +1,755 @@
+/***************************************************************************
+ *
+ * string.replace.cpp - string test exercising [lib.string::replace]
+ *
+ * $Id$ 
+ *
+ ***************************************************************************
+ *
+ * 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>       // for string
+#include <cstddef>      // for size_t
+#include <stdexcept>    // for out_of_range, length_error
+
+#include <cmdopt.h>     // for rw_enabled()
+#include <driver.h>     // for rw_test()
+
+#include <rw_char.h>    // for rw_widen()
+#include <alg_test.h>   // for InputIter<>
+
+/**************************************************************************/
+
+struct MemFun
+{
+    enum charT  { Char, WChar, UChar };
+    enum Traits { DefaultTraits, UserTraits };
+
+    MemFun (charT cid, const char *cname,
+          Traits tid, const char *tname)
+        : cid_ (cid), tid_ (tid), 
+          cname_ (cname), tname_ (tname), aname_ ("allocator"),
+          fname_ ("replace") { /* empty */ }
+
+    charT       cid_;     // character type id (char or wchar_t)
+    Traits      tid_;     // traits type id (default or user-defined)
+    const char *cname_;   // character type name
+    const char *tname_;   // traits name
+    const char *aname_;   // allocator name
+    const char *fname_;   // function name
+};
+
+/**************************************************************************/
+
+static const int long_string_len = 4096;
+static char long_string [long_string_len];
+
+static const char* exp_exceptions[] = 
+    { "unknown exception", "out_of_range", "length_error" };
+
+/**************************************************************************/
+
+struct ReplaceData
+{
+    ReplaceData (char* str, std::size_t str_len, int pos1, int num1, 
+                 char* src, std::size_t src_len, int pos2, int num2, 
+                 int cnt, char ch, char* res, std::size_t res_len,
+                 char* it_res, std::size_t it_res_len) :
+        pos1_ (pos1), num1_ (num1), pos2_ (pos2), num2_ (num2),
+        cnt_ (cnt), ch_ (ch), str_ (str), str_len_ (str_len), src_ (src), 
+        src_len_ (src_len), res_ (res), res_len_ (res_len), it_res_ (it_res), 
+        it_res_len_ (it_res_len) {
+    }
+
+    int pos1_;
+    int num1_;
+    int pos2_;
+    int num2_;
+    int cnt_;
+    char ch_;
+
+    char* str_;
+    std::size_t str_len_;
+
+    char* src_;
+    std::size_t src_len_;
+
+    char* res_;
+    std::size_t res_len_;
+
+    char* it_res_;
+    std::size_t it_res_len_;
+};
+
+/**************************************************************************/
+
+template <class String>
+String& test_replace (int                          which,
+                      const ReplaceData           &rd, 
+                      String                      &str, 
+                      typename String::value_type *wsrc, 
+                      bool                         test,
+                      std::size_t                 *exp_len)
+{
+    *exp_len = 0;
+
+    if (!test && (4 == which || 7 == which))
+        return str;
+
+    const String& ref_src = String (wsrc, rd.src_len_);
+
+    // construct iterators
+    int first = std::size_t (rd.pos1_) > str.size () ? 0 : rd.pos1_;
+    int last  = rd.pos1_ + rd.num1_;
+
+    typename String::iterator it_first (str.begin () + first);
+
+    typename String::iterator it_last (std::size_t (last) >= rd.str_len_ ?
+        str.end () : str.begin () + last);
+
+    switch (which) {
+        case 1: {
+            if (test)
+                return str.replace (rd.pos1_, rd.num1_, wsrc);
+            else
+                return str.replace (rd.pos1_, rd.num1_, 
+                                    String (wsrc));
+        }
+        case 2: {
+            if (test)
+                return str.replace (rd.pos1_, rd.num1_, ref_src);
+            else
+                return str.replace (rd.pos1_, rd.num1_, ref_src, 
+                                    0, String::npos);
+        }
+        case 3: {
+            if (test)
+                return str.replace (rd.pos1_, rd.num1_, wsrc, rd.num2_);
+            else
+                return str.replace (rd.pos1_, rd.num1_, 
+                                    String (wsrc, rd.num2_));
+        }
+        case 4: {
+            if (test)
+                return str.replace (rd.pos1_, rd.num1_, ref_src, 
+                                    rd.pos2_, rd.num2_);
+            else
+                return str;
+        }
+        case 5: {
+            if (test)
+                return str.replace (rd.pos1_, rd.num1_, rd.cnt_, 
+                                    make_char (rd.ch_, 
+                                    (typename  String::value_type*)0)); 
+            else
+                return str.replace (rd.pos1_, rd.num1_, 
+                                    String (rd.cnt_, make_char (rd.ch_, 
+                                    (typename String::value_type*)0)));
+        }
+        case 6: {
+            *exp_len = str.length () + String::traits_type::length (wsrc) -
+               (it_last - it_first);
+
+            if (test)
+                return str.replace (it_first, it_last, wsrc);
+            else
+                return str.replace (it_first, it_last, String (wsrc));
+        }
+        case 7: {
+            *exp_len = str.length () + ref_src.length () - 
+               (it_last - it_first);
+
+            if (test)
+                return str.replace (it_first, it_last, ref_src);
+            else
+                return str;
+        }
+        case 8: {
+            *exp_len = str.length () + rd.num2_ - (it_last - it_first);
+
+            if (test)
+                return str.replace (it_first, it_last, wsrc, rd.num2_);
+            else
+                return str.replace (it_first, it_last, 
+                                    String (wsrc, rd.num2_));
+        }
+        case 9: {
+            *exp_len = str.length () + rd.cnt_ - (it_last - it_first);
+
+            if (test)
+                return str.replace (it_first, it_last, rd.cnt_, 
+                                    make_char (rd.ch_, 
+                                    (typename String::value_type*)0));
+            else
+                return str.replace (it_first, it_last, 
+                                    String (rd.cnt_, make_char (rd.ch_, 
+                                    (typename String::value_type*)0)));
+        }
+        case 10: {
+            // construct iterators
+            int last2 = rd.pos2_ + rd.num2_;
+
+            InputIter<typename String::value_type> src_first = 
+                make_iter (wsrc + rd.pos2_, wsrc + rd.pos2_, wsrc + last2, 
+                        InputIter<typename String::value_type> (0, 0, 0));
+
+            InputIter<typename String::value_type> src_last  = 
+                make_iter (wsrc + last2, wsrc + rd.pos2_, wsrc + last2, 
+                        InputIter<typename String::value_type> (0, 0, 0));
+
+            *exp_len = str.length () + (src_last.cur_ - src_first.cur_) - 
+                (it_last - it_first);
+
+            if (test)
+                return str.replace (it_first, it_last, src_first, src_last);
+            else
+                return str.replace (it_first, it_last, 
+                                    String (src_first, src_last));
+        }
+    }
+
+    return str;
+}
+
+/**************************************************************************/
+
+template <class charT, class Traits>
+void test_replace (charT, Traits*, 
+                   int                line,
+                   int                which,
+                   MemFun            *pfid, 
+                   const ReplaceData &rd,
+                   int                should_throw)
+{
+    typedef std::basic_string <charT, Traits, 
+                               std::allocator<charT> > TestString;
+
+    static charT wstr [long_string_len];
+    static charT wsrc [long_string_len];
+    static charT wres [long_string_len];
+
+    // construct strings
+    bool use_res = (4 == which || 7 == which);
+    bool use_iters = (6 <= which);
+
+    char* pstrres = use_res ? 
+        use_iters ? rd.it_res_ : rd.res_ 
+      : rd.str_;
+
+    std::size_t res_len = use_res ? 
+        use_iters ? rd.it_res_len_ : rd.res_len_ 
+      : rd.str_len_;
+
+    rw_widen (wstr, rd.str_, rd.str_len_);
+    rw_widen (wsrc, rd.src_, rd.src_len_);
+    rw_widen (wres, pstrres, res_len);
+
+    TestString s_str (wstr, rd.str_len_);
+    TestString s_src (wsrc, rd.src_len_);
+    TestString s_res (wres, res_len);
+
+    // used to workaround the problem with empty UserChar strings output
+    static charT wempty [10]; 
+    rw_widen (wempty, "<empty>", 7);
+    TestString s_empty (wempty, 7);
+    bool src_use_empty = 
+        0 == s_src.size () && sizeof (charT) > sizeof (wchar_t);
+
+    int first1_off = rd.pos1_;
+    int last1_off  = rd.pos1_ + rd.num1_; 
+
+    int first2_off = rd.pos2_;
+    int last2_off  = rd.pos2_ + rd.num2_;
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+    // is some exception expected ?
+    const char* expected = 0;
+    if (!use_iters) {
+        if (1 == should_throw || 2 == should_throw && 4 == which)
+            expected = exp_exceptions[1];
+        else if (3 == should_throw)
+            expected = exp_exceptions[2];
+    }
+
+    const char* caught = 0;
+
+    try {
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+    // do replace
+    std::size_t exp_len = 0;
+    std::size_t dummy_len = 0;
+
+    TestString& res_str = 
+        test_replace (which, rd, s_str, wsrc, true, &exp_len);
+    TestString& ctl_str = 
+        test_replace (which, rd, s_res, wsrc, false, &dummy_len);
+
+#define CALLFMAT                                                             \
+    "line %d. std::basic_string<%s, %s<%2$s>, %s<%2$s>>(%{#*s})."            \
+    "replace (%{?}%zu%{;}%{?}begin + %zu%{;}"                                \
+    "%{?}, %zu%{;}%{?}, begin + %zu%{;}"                                     \
+    "%{?}, %{#*s}%{;}%{?}, %{#*S}%{;}"                                       \
+    "%{?}, %zu%{;}%{?}, %zu%{;}"                                             \
+    "%{?}, %zu%{;}%{?}, %#c%{;}"                                             \
+    "%{?}, begin + %zu%{;}%{?}, begin + %zu%{;})"
+
+#define CALLARGS                                                             \
+    __LINE__, pfid->cname_, pfid->tname_, pfid->aname_, int (rd.str_len_),   \
+    rd.str_, 5 >= which, rd.pos1_, 6 <= which, first1_off,                   \
+    5 >= which, rd.num1_, 6 <= which, last1_off,                             \
+    1 == which || 3 == which || 6 == which || 8 == which,                    \
+    int (rd.src_len_), rd.src_, 2 == which || 4 == which || 7 == which,      \
+    int (sizeof (charT)), src_use_empty ? &s_empty : &s_src,                 \
+    5 == which || 9 == which, rd.cnt_, 4 == which, rd.pos2_,                 \
+    3 == which || 4 == which || 8 == which, rd.num2_,                        \
+    5 == which || 9 == which, rd.ch_, 10 == which, first2_off,               \
+    10 == which, last2_off
+
+    // verify the results
+    if (4 == which || 7 == which) {
+        // verify the returned value
+        rw_assert (&res_str == &s_str, 0, line,
+                   CALLFMAT " : the returned reference is invalid", CALLARGS);
+    }
+
+    // verify the result string length for iterator versions
+    if (use_iters) {
+        // verify the length
+        std::size_t len = res_str.length ();
+        rw_assert (len == exp_len, 0, line,
+                   CALLFMAT " : result length is %zu, %zu expected",
+                   CALLARGS, len, exp_len);
+    }
+
+    bool success = !TestString::traits_type::compare (res_str.c_str(), 
+                        ctl_str.c_str(), ctl_str.size ());
+
+    // to workaround UserChar's empty string output problem
+    bool use_empty_res = 
+        0 == res_str.size () && sizeof (charT) > sizeof (wchar_t);
+    bool use_empty_ctl = 
+        0 == ctl_str.size () && sizeof (charT) > sizeof (wchar_t);
+
+    rw_assert (success, 0, line,
+               CALLFMAT " == %{#*S}, %{#*S} expected", CALLARGS, 
+               int (sizeof (charT)), use_empty_res ? &s_empty : &res_str, 
+               int (sizeof (charT)), use_empty_ctl ? &s_empty : &ctl_str);
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+    }
+    catch (std::out_of_range) {
+        caught = exp_exceptions[1];
+    }
+    catch (std::length_error) {
+        caught = exp_exceptions[2];
+    }
+    catch (...) {
+        caught = exp_exceptions[0];
+    }
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+    _RWSTD_UNUSED (should_throw);
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+    rw_assert (caught == expected, 0, line,
+               CALLFMAT " %{?}expected %s, caught %s"
+               "%{:}unexpectedly caught %s%{;}",
+               CALLARGS, 0 != expected, expected, caught, caught);
+}
+
+/**************************************************************************/
+
+void test_replace (MemFun            *pfid,
+                   int                line,
+                   int                which,
+                   const ReplaceData &rd,
+                   int                should_throw)
+{
+#undef TEST
+#define TEST(charT, Traits)	 \
+    test_replace (charT(), (Traits*)0, line, which, pfid, rd, should_throw)
+
+    if (!rw_enabled (line)) {
+        rw_note (0, 0, __LINE__, "test on line %d disabled", line);
+        return;
+    }
+
+    if (MemFun:: DefaultTraits == pfid->tid_) {
+        if (MemFun::Char == pfid->cid_)
+            TEST (char, std::char_traits<char>);
+
+#ifndef _RWSTD_NO_WCHAR_T
+        else
+            TEST (wchar_t, std::char_traits<wchar_t>);
+#endif   // _RWSTD_NO_WCHAR_T
+
+    }
+    else {
+        if (MemFun::Char == pfid->cid_)
+            TEST (char, UserTraits<char>);
+
+#ifndef _RWSTD_NO_WCHAR_T
+        else if (MemFun::WChar == pfid->cid_)
+            TEST (wchar_t, UserTraits<wchar_t>);
+#endif   // _RWSTD_NO_WCHAR_T
+
+        else
+            TEST (UserChar, UserTraits<UserChar>);
+    }
+}
+
+/**************************************************************************/
+
+static int rw_opt_no_char_traits;              // for --no-char_traits
+static int rw_opt_no_user_traits;              // for --no-user_traits
+
+static int rw_opt_no_user_chars;               // for --no-user_chars
+static int rw_opt_no_exceptions;               // for --no-exceptions
+
+static int rw_opt_no_replace_ptr;              // for --no-replace-ptr
+static int rw_opt_no_replace_str;              // for --no-replace-str
+static int rw_opt_no_replace_num_ptr;          // for --no-replace-num-ptr
+static int rw_opt_no_replace_num_str;          // for --no-replace-num-str
+static int rw_opt_no_replace_char;             // for --no-replace-char
+static int rw_opt_no_replace_iters_ptr;        // for --no-replace-iters-ptr
+static int rw_opt_no_replace_iters_str;        // for --no-replace-iters-str
+static int rw_opt_no_replace_iters_num_ptr;    // for --no-replace-iters-num-ptr
+static int rw_opt_no_replace_iters_char;       // for --no-replace-iters-char
+static int rw_opt_no_replace_iters_range;      // for --no-replace-iters-range
+
+/**************************************************************************/
+
+void test_replace (MemFun* pfid, int which)
+{
+    rw_info (0, 0, 0, "std::basic_string<%s, %s<%1$s>, %s<%1$s>>::"
+             "replace (%{?}size_type pos1%{;}%{?}iterator i1%{;}"
+             "%{?}, size_type n1%{;}%{?}, iterator i2%{;}"
+             "%{?}, const charT* s%{;}%{?}, const basic_string& str%{;}"
+             "%{?}, size_type n%{;}%{?}, size_type pos2%{;}"
+             "%{?}, size_type n2%{;}%{?}, const charT c%{;}"
+             "%{?}, InputIterator j1%{;}%{?}, InputIterator j2%{;})",
+             pfid->cname_, pfid->tname_, pfid->aname_, 
+             5 >= which, 6 <= which, 5 >= which, 6 <= which, 
+             1 == which || 3 == which || 6 == which || 8 == which,
+             2 == which || 4 == which || 7 == which, 5 == which || 9 == which, 
+             4 == which, 3 == which || 4 == which || 8 == which,
+             5 == which || 9 == which, 10 == which, 10 == which);
+
+    std::size_t long_parity_len = (long_string_len - 1) & 0x01 ? 
+        (long_string_len - 1) / 2 : (long_string_len - 2) / 2;
+
+#undef TEST
+#define TEST(str, pos1, num1, src, pos2, num2, cnt, ch, res, it_res, bthrow)   \
+    test_replace (pfid, __LINE__, which, ReplaceData ((char*) str,             \
+                  sizeof str - 1, pos1, num1, (char*) src,                     \
+                  sizeof src - 1, pos2, num2, cnt, ch, (char*) res,            \
+                  sizeof res - 1, (char*) it_res, sizeof it_res - 1), bthrow)                       
+
+    //    +----------------------------------------- controlled sequence
+    //    |      +---------------------------------- replace() pos1 argument
+    //    |      |  +------------------------------- replace() n1 argument
+    //    |      |  |  +---------------------------- replace with sequence
+    //    |      |  |  |          +----------------- replace() pos2 argument 
+    //    |      |  |  |          |  +-------------- replace() n2 argument 
+    //    |      |  |  |          |  |  +----------- replace() count argument 
+    //    |      |  |  |          |  |  |  +-------- replace() with character
+    //    |      |  |  |          |  |  |  |    +--- expected result sequence
+    //    |      |  |  |          |  |  |  |    |  + expected result sequence 
+    //    |      |  |  |          |  |  |  |    |  | for iterators
+    //    |      |  |  |          |  |  |  |    |  |    exception info ----+ 
+    //    |      |  |  |          |  |  |  |    |  |    0 - no exception   |   
+    //    |      |  |  |          |  |  |  |    |  |    1,2 - out_of_range |   
+    //    |      |  |  |          |  |  |  |    |  |    3 - length_error   |   
+    //    |      |  |  |          |  |  |  |    |  |                       |
+    //    |      |  |  |          |  |  |  |    |  +----------+            |
+    //    V      V  V  V          V  V  V  V    V             V            V
+    TEST ("ab",  0, 1, "c",       0, 1, 2, 'c', "cb",         "cb",        0);
+
+    TEST ("",    0, 0, "",        0, 0, 0, 'c', "",           "",          0);
+    TEST ("",    0, 0, "abc",     0, 3, 3, 'c', "abc",        "abc",       0);
+
+    TEST ("ab",  0, 2, "",        0, 0, 0, 'c', "",           "",          0);
+    TEST ("ab",  0, 1, "",        0, 0, 0, 'c', "b",          "b",         0);
+
+    TEST ("\0",  0, 1, "",        0, 0, 0, ' ', "",           "",          0);
+    TEST ("\0",  0, 1, "a",       0, 1, 1, 'a', "a",          "a",         0);
+    TEST ("\0",  0, 1, "\0\0",    1, 1, 1, '\0', "\0",        "\0",        0);
+    TEST ("\0",  0, 1, "\0\0",    0, 2, 2, '\0', "\0\0",      "\0\0",      0);
+
+    TEST ("ah",  0, 1, "bcdefg",  0, 3, 1, 'c',  "bcdh",      "bcdefgh",   0);
+    TEST ("ah",  1, 1, "bcdefg",  0, 3, 1, 'c',  "abcd",      "abcdefg",   0);
+    TEST ("ah",  0, 1, "bcdefg",  1, 3, 4, 'c',  "cdeh",      "bcdefgh",   0);
+    TEST ("ah",  1, 1, "bcdefg",  1, 3, 4, 'c',  "acde",      "abcdefg",   0);
+    TEST ("ah",  0, 1, "bcdefg",  0, 6, 1, 'c',  "bcdefgh",   "bcdefgh",   0);
+    TEST ("ah",  1, 1, "bcdefg",  0, 6, 1, 'c',  "abcdefg",   "abcdefg",   0);
+
+    TEST ("abc", 0, 2, "cc",      0, 2, 2, 'c',  "ccc",       "ccc",       0);
+    TEST ("abc", 1, 2, "cc",      0, 2, 2, 'c',  "acc",       "acc",       0);
+
+    TEST ("abc", 0, 3, "d",       0, 1, 1, 'c',  "d",         "d",         0);
+    TEST ("abc", 0, 3, "def",     0, 3, 3, 'c',  "def",       "def",       0);
+    TEST ("abc", 0, 3, "defgh",   0, 5, 5, 'c',  "defgh",     "defgh",     0);
+    TEST ("abc", 2, 1, "defgh",   4, 1, 1, 'c',  "abh",       "abdefgh",   0);
+    TEST ("abc", 2, 1, "de\0gh",  2, 1, 1, 'c',  "ab\0",      "abde\0gh",  0);
+    TEST ("abc", 2, 1, "",        0, 0, 0, 'c',  "ab",        "ab",        0);
+
+    TEST ("abc", 1, 1, "defgh",   1, 2, 5, 'c',  "aefc",      "adefghc",   0);
+    TEST ("abc", 0, 0, "ee",      0, 2, 2, 'c',  "eeab",      "eeab",      0);
+    TEST ("abc", 0, 0, "\0\0e\0", 0, 4, 4, '\0', "\0\0e\0ab", "\0\0e\0ab", 0);
+    TEST ("abc", 2, 0, "ee",      0, 2, 2, 'c',  "abee",      "abee",      0);
+    TEST ("abc", 2, 0, "\0e\0\0", 0, 4, 4, '\0', "ab\0e\0\0", "ab\0e\0\0", 0);
+    TEST ("abc", 1, 0, "ee",      0, 2, 2, 'c',  "aeebc",     "aeebc",     0);
+
+    TEST ("abc", 1, 0, "\0e\0\0", 0, 4, 4, '\0', "a\0e\0\0bc", 
+                                                             "a\0e\0\0bc", 0);
+
+    TEST ("a\0b\0\0c", 0, 3, "",    0, 0, 1, '\0', "\0\0c",    "\0\0c",    0);
+    TEST ("\0ab\0\0c", 0, 3, "",    0, 0, 1, '\0', "\0\0c",    "\0\0c",    0);
+    TEST ("a\0b\0\0c", 0, 3, "\0e", 0, 2, 1, '\0', "\0e\0\0c", "\0e\0\0c", 0);
+
+    TEST ("a\0b\0\0c", 2, 3, "\0e", 0, 2, 1, '\0', "a\0\0ec",  "a\0\0ec",  0);
+    TEST ("a\0b\0\0c", 2, 3, "\0e", 1, 1, 1, '\0', "a\0ec",    "a\0\0ec",  0);
+    TEST ("\0ab\0\0c", 2, 3, "\0e", 0, 2, 1, '\0', "\0a\0ec",  "\0a\0ec",  0);
+    TEST ("\0ab\0\0c", 2, 3, "\0e\0\0", 
+                                    1, 3, 5, '\0', "\0ae\0\0c", 
+                                                            "\0a\0e\0\0c", 0);
+
+    TEST ("a\0b\0\0c", 0, 6, "\0e", 0, 2, 2, '\0', "\0e",      "\0e",      0);
+    TEST ("a\0b\0\0c", 0, 6, "\0e", 0, 1, 2, '\0', "\0",       "\0e",      0);
+
+    TEST ("\0ab\0\0c", 0, 0, "\0e", 0, 2, 2, '\0', "\0e\0ab\0\0c", 
+                                                           "\0e\0ab\0\0c", 0);
+    TEST ("a\0b\0c\0", 6, 0, "e\0", 0, 2, 2, '\0', "a\0b\0c\0e\0", 
+                                                           "a\0b\0c\0e\0", 0);
+    TEST ("\0ab\0\0c", 5, 0, "\0e", 0, 2, 2, '\0', "\0ab\0\0\0ec", 
+                                                           "\0ab\0\0\0ec", 0);
+
+    TEST (long_string, 0, long_string_len - 1, "ab", 
+                                      0, 2, 2, 'a',  "ab",      "ab",      0);
+    TEST (long_string, 1, long_string_len - 2, "ab", 
+                                      0, 2, 2, 'a',  "xab",     "xab",     0);
+    TEST (long_string, 0, long_string_len - 2, "ab", 
+                                      0, 2, 2, 'a',  "abx",     "abx",     0);
+    TEST (long_string, 1, long_string_len - 3, "", 
+                                      0, 0, 0, 'a',  "xx",      "xx",      0);
+    TEST (long_string, 1, long_string_len - 4, "\0\0", 
+                                      0, 2, 1, '\0', "x\0\0xx", "x\0\0xx", 0);
+
+    TEST ("a", 0, 1, long_string, 0, long_string_len - 1, long_string_len - 1, 
+                                            'a', long_string, long_string, 0);
+
+    TEST (long_string, 0, long_string_len - 1, long_string, 0, 
+                                 long_string_len - 1, long_string_len - 1, 
+                                            'a', long_string, long_string, 0);
+
+    TEST (long_string, 0, long_parity_len, long_string, 0, 
+                                 long_parity_len, long_parity_len, 
+                                            'a', long_string, long_string, 0);
+
+    TEST (long_string, long_parity_len, long_string_len - 1 - long_parity_len, 
+       long_string, 0, long_string_len - 1 - long_parity_len, 
+                       long_string_len - 1 - long_parity_len, 
+                                            'a', long_string, long_string, 0);
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+    if (! rw_opt_no_exceptions) {
+        TEST ("\0", 2, 0, "",   0, 0, 0, ' ', "", "", 1);
+        TEST ("\0", 0, 0, "\0", 2, 0, 0, ' ', "", "", 2);
+
+        TEST ("a", 10, 0, "",   0, 0, 0, ' ', "", "", 1);
+        TEST ("a",  0, 0, "a", 10, 0, 0, ' ', "", "", 2);
+
+        TEST (long_string, long_string_len + 10, 0, "",
+                                0, 0, 0, ' ', "", "", 1);
+        TEST (long_string, 0, 0, long_string, long_string_len + 10, 
+                                   0, 0, ' ', "", "", 2);
+    }
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+}
+
+/**************************************************************************/
+
+static void 
+note_test_disabled (MemFun *pfid, int which)
+{
+    rw_note (0, 0, 0, "std::basic_string<%s, %s<%1$s>, %s<%1$s>>::"
+             "replace (%{?}size_type pos1%{;}%{?}iterator i1%{;}"
+             "%{?}, size_type n1%{;}%{?}, iterator i2%{;}"
+             "%{?}, const charT* s%{;}%{?}, const basic_string& str%{;}"
+             "%{?}, size_type n%{;}%{?}, size_type pos2%{;}"
+             "%{?}, size_type n2%{;}%{?}, const charT c%{;}"
+             "%{?}, InputIterator j1%{;}%{?}, InputIterator j2%{;})"
+             " test disabled",
+             pfid->cname_, pfid->tname_, pfid->aname_, 
+             5 >= which, 6 <= which, 5 >= which, 6 <= which, 
+             1 == which || 3 == which || 6 == which || 8 == which,
+             2 == which || 4 == which || 7 == which, 5 == which || 9 == which, 
+             4 == which, 3 == which || 4 == which || 8 == which,
+             5 == which || 9 == which, 10 == which, 10 == which);
+}
+
+static void
+run_test (MemFun *pfid)
+{
+    if (MemFun::UserTraits == pfid->tid_ && rw_opt_no_user_traits) {
+        rw_note (1 < rw_opt_no_user_traits++, 0, 0,
+                 "user defined traits test disabled");
+    }
+    else if (MemFun::DefaultTraits == pfid->tid_  && rw_opt_no_char_traits) {
+        rw_note (1 < rw_opt_no_char_traits++, 0, 0,
+                 "char_traits test disabled");
+    }
+    else {
+
+        if (rw_opt_no_exceptions)
+            rw_note (1 < rw_opt_no_exceptions++, 0, 0,
+                     "string::replace exceptions tests disabled");
+
+        // exercise all replace overloads
+#undef TEST
+#define TEST(option, n)                         \
+        if (option)                             \
+            note_test_disabled (pfid, n);       \
+        else                                    \
+            test_replace (pfid, n);               
+
+    // replace (size_type pos1, size_type n1, const charT* p)
+    TEST (rw_opt_no_replace_ptr,           1);         
+    // replace (size_type pos1, size_type n1, basic_string& s)
+    TEST (rw_opt_no_replace_str,           2);      
+    // replace (size_type pos1, size_type n1, charT* p, size_type n2)
+    TEST (rw_opt_no_replace_num_ptr,       3);          
+    // replace (pos1, n1, basic_string& s, size_type pos2, size_type n2)
+    TEST (rw_opt_no_replace_num_str,       4);  
+    // replace (size_type pos1, size_type n1, size_type n, charT c)
+    TEST (rw_opt_no_replace_char,          5);     
+    // replace (iterator i1, iterator i2, const charT* p)
+    TEST (rw_opt_no_replace_iters_ptr,     6);   
+    // replace (iterator i1, iterator i2, basic_string& s)
+    TEST (rw_opt_no_replace_iters_str,     7);    
+    // replace (iterator i1, iterator i2, charT* p, size_type n2)
+    TEST (rw_opt_no_replace_iters_num_ptr, 8);    
+    // replace (iterator i1, iterator i2, size_type n, charT c)
+    TEST (rw_opt_no_replace_iters_char,    9);    
+    // replace (iterator i1, iterator i2, InputIterator j1, InputIterator j2)
+    TEST (rw_opt_no_replace_iters_range,  10);           
+    }
+}
+
+/**************************************************************************/
+
+int run_test (int, char*[])
+{
+    if ('\0' == long_string [0]) {
+        // initialize long_string
+        for (std::size_t i = 0; i != sizeof long_string - 1; ++i)
+            long_string [i] = 'x';
+    }
+
+    if (rw_enabled ("char")) {
+
+        MemFun fid (MemFun::Char, "char", MemFun::DefaultTraits, 0);
+
+        fid.tname_ = "char_traits";
+
+        run_test (&fid);
+
+        fid.tid_   = MemFun::UserTraits;
+        fid.tname_ = "UserTraits";
+
+        run_test (&fid);
+    }
+    else
+        rw_note (0, 0, 0, "string::replace char tests disabled");
+
+    if (rw_enabled ("wchar_t")) {
+
+        MemFun fid (MemFun::WChar, "wchar_t", MemFun::DefaultTraits, 0);
+
+        fid.tname_ = "char_traits";
+
+        run_test (&fid);
+
+        fid.tid_   = MemFun::UserTraits;
+        fid.tname_ = "UserTraits";
+
+        run_test (&fid);
+    }
+    else
+        rw_note (0, 0, 0, "string::replace wchar tests disabled");
+
+    if (rw_opt_no_user_chars) {
+        rw_note (0, 0, 0, "user defined chars test disabled");
+    }
+    else {
+        MemFun fid (MemFun::UChar, "UserChar", MemFun::UserTraits, 0);
+        fid.tname_ = "UserTraits";
+        run_test (&fid);
+    }
+
+    // silence a bogus EDG eccp remark #550-D:
+    // variable "exp_exceptions" was set but never used
+    _RWSTD_UNUSED (exp_exceptions);
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char** argv)
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.string.replace",
+                    0 /* no comment */, run_test,
+                    "|-no-char_traits# "
+                    "|-no-user_traits# "
+                    "|-no-user_chars# "
+                    "|-no-exceptions# "
+                    "|-no-replace-ptr# "
+                    "|-no-replace-str# "
+                    "|-no-replace-num-ptr# "
+                    "|-no-replace-num-str# "
+                    "|-no-replace-char# "
+                    "|-no-replace-iters_ptr# "
+                    "|-no-replace-iters_str# "
+                    "|-no-replace-iters_num-ptr# "
+                    "|-no-replace-iters-char# "
+                    "|-no-replace-iters-range#",
+                    &rw_opt_no_char_traits,
+                    &rw_opt_no_user_traits,
+                    &rw_opt_no_user_chars,
+                    &rw_opt_no_exceptions,
+                    &rw_opt_no_replace_ptr,
+                    &rw_opt_no_replace_str,
+                    &rw_opt_no_replace_num_ptr,
+                    &rw_opt_no_replace_num_str,
+                    &rw_opt_no_replace_char,
+                    &rw_opt_no_replace_iters_ptr,
+                    &rw_opt_no_replace_iters_str,
+                    &rw_opt_no_replace_iters_num_ptr,
+                    &rw_opt_no_replace_iters_char,
+                    &rw_opt_no_replace_iters_range);
+}