incubator-stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Sebor <se...@roguewave.com>
Subject Re: string methods thread safety
Date Wed, 26 Jul 2006 21:23:35 GMT
Farid Zaripov wrote:

>  > -----Original Message-----
>  > From: Martin Sebor [mailto:sebor@roguewave.com]
>  > Sent: Friday, July 21, 2006 4:00 AM
>  > To: stdcxx-dev@incubator.apache.org
>  > Subject: RE: string methods thread safety
>  >
>  > Could you please post your proposed ChangeLog entry for all
>  > nontrivial changes? It will make it easier for me to
>  > understand what's going on.
>  > Thanks! :)
>  >
> 
>   The test exercising string thread safety (21.string.mt.cpp).
> The test file and 21.string.*.diff are attached.
> The test requires the files rw_process.h and process.cpp (I have sent
> this files in the separate letter).

Sorry, I meant just the standard ChangeLog entry -- see the GNU
coding standards for a detailed description of ChangeLog concepts:
http://www.gnu.org/prep/standards/html_node/Change-Logs.html

Here are a couple of examples:
http://svn.apache.org/viewvc?view=rev&revision=423407
http://svn.apache.org/viewvc?view=rev&revision=418318

Martin

PS Thanks for detailed description of the test :)

> 
>   At first the test checks were option --overload_id=xxx is specified.
> If the option is not specified it executes the self copy with
> the all own and the three additional parameters:
> 1) --overload_id={one of the exercising StringIds::OverloadId};
> 2) --no-stdout to prevent the output of the copy process to the
> test driver console;
> 3) --no-UserAlloc to prevent UserAlloc allocator using
> due to SharedAlloc (used by UserAlloc) is not a thread safe.
> 
>   The child copy is executed for each overload id from overloads array.
> When the parameter --overload_id=xxx is specified the test performs the 
> thread safety test of the specified overload. If shared string is 
> modified after the test, the global variable _rw_status is set to 1 (to 
> detect the string modification I had to slightly modify the 
> StringState::assert_equal() method). This variable is a return code of 
> the child process to transfer the success of the overload test to the 
> driver (parent process). I used the global variable because the callback 
> for rw_run_string_test() returns void.
> 
>   For the range overloads (append_range, assign_range, 
> insert_iter_range, replace_iter_iter_range) the 
> basic_string<>::const_iterator overloads tested only. I am not sure that 
> it's enough, but I can add testing of the other overloads later.
> 
>   When the parent process receives the return code it checks this by 
> rw_assert(). To print the method signature I used _rw_setvars from 
> 21.strings.cpp. For this I renamed it to rw_setvars due to naming 
> conventions. I don't like it too, but I have no the better idea yet.
> 
>  > The only thing I'm not quite happy with so far is making
>  > _rw_setvars extern. According to the (still unwritten, my
>  > bad) naming convention, names that start with _rw_ have
>  > internal linkage, and shouldn't be exposed to the world
>  > (i.e., to the tests or other objects). If it turns out that
>  > the function is helpful elsewhere besides the TU where it's
>  > declared static we should rename it (and drop the leading
>  > underscore). The burden that should come with doing it is
>  > writing a test for the function.
> 
> Farid.
> 
> 
> ------------------------------------------------------------------------
> 
> /***************************************************************************
>  *
>  * 21.string.mt.cpp - string test exercising string methods thread safety
>  *
>  * $Id: 21.string.mt.cpp $
>  *
>  ***************************************************************************
>  *
>  * Licensed to the Apache Software  Foundation (ASF) under one or more
>  * contributor  license agreements.  See  the NOTICE  file distributed
>  * with  this  work  for  additional information  regarding  copyright
>  * ownership.   The ASF  licenses this  file to  you 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 <istream>          // for istream
> #include <locale>           // for locale
> 
> #include <stddef.h>         // for size_t
> #include <stdlib.h>         // for malloc()
> #include <stdio.h>          // for sprintf()
> #include <string.h>         // for memcpy()
> #include <limits.h>         // for CHARBIT
> 
> #include <21.strings.h>     // for StringMembers
> #include <driver.h>         // for rw_test()
> #include <rw_process.h>     // for rw_process_create(), rw_process_join()
> #include <rw_thread.h>      // for rw_thread_pool()
> #include <rw_allocator.h>   // for UserAlloc
> #include <cmdopt.h>         // for rw_setops(), rw_runopts()
> #include <rw_printf.h>      // for rw_fprintf()
> #include <rw_ctype.h>       // for UserCtype
> #include <rw_streambuf.h>   // for MyStreambuf
> 
> /**************************************************************************/
> 
> #define MAX_THREADS      32
> #define MAX_LOOPS     10000
> 
> /**************************************************************************/
> 
> int rw_opt_overload_id = -1;
> int rw_opt_nthreads    = 4;
> int rw_opt_nloops      = MAX_LOOPS;
> int rw_opt_dummy;
> 
> static int _rw_status  = 0;
> 
> static char param2[] = "--no-stdout";
> static char param3[] = "--no-UserAlloc";
> 
> /**************************************************************************/
> 
> static const StringIds::OverloadId overloads [] = {
> 
> #undef TEST
> #define TEST(sig) StringIds:: sig
> 
>     TEST (append_cptr),
>     TEST (append_cstr),
>     TEST (append_cptr_size),
>     TEST (append_cstr_size_size),
>     TEST (append_size_val),
>     TEST (append_range),
> 
>     TEST (assign_cptr),
>     TEST (assign_cstr),
>     TEST (assign_cptr_size),
>     TEST (assign_cstr_size_size),
>     TEST (assign_size_val),
>     TEST (assign_range),
> 
>     TEST (erase_void),
>     TEST (erase_size),
>     TEST (erase_size_size),
>     TEST (erase_iter),
>     TEST (erase_iter_iter),
> 
>     TEST (insert_size_cptr),
>     TEST (insert_size_cstr),
>     TEST (insert_size_cptr_size),
>     TEST (insert_size_cstr_size_size),
>     TEST (insert_size_size_val),
>     TEST (insert_iter_val),
>     TEST (insert_iter_size_val),
>     TEST (insert_iter_range),
> 
>     TEST (replace_size_size_cptr),
>     TEST (replace_size_size_cstr),
>     TEST (replace_size_size_cptr_size),
>     TEST (replace_size_size_cstr_size_size),
>     TEST (replace_size_size_size_val),
>     TEST (replace_iter_iter_cptr),
>     TEST (replace_iter_iter_cstr),
>     TEST (replace_iter_iter_cptr_size),
>     TEST (replace_iter_iter_size_val),
>     TEST (replace_iter_iter_range),
> 
>     TEST (op_plus_eq_cptr),
>     TEST (op_plus_eq_cstr),
>     TEST (op_plus_eq_val),
> 
>     TEST (substr_void),
>     TEST (substr_size),
>     TEST (substr_size_size),
> 
>     TEST (op_index_size),
>     TEST (at_size),
> 
>     TEST (swap_str),
> 
>     TEST (push_back_val),
> 
>     TEST (resize_size_val),
>     TEST (resize_size),
> 
>     TEST (reserve_size),
>     TEST (reserve_void),
> 
>     TEST (clear_void),
> 
>     TEST (begin_void),
>     TEST (end_void),
> 
>     TEST (rbegin_void),
>     TEST (rend_void),
> 
>     TEST (extractor_istream_str),
>     TEST (getline_istream_str),
>     TEST (getline_istream_str_val)
> };
> 
> static const size_t test_count = sizeof (overloads) / sizeof (*overloads);
> 
> static const char param_name[] = "--overload_id=";
> static const size_t param_len  = sizeof (param_name) - 1;
> 
> /**************************************************************************/
> 
> extern void
> rw_setvars (const StringFunc     &func,
>              const StringTestCase *pcase);
> 
> /**************************************************************************/
> 
> template <class charT, class Traits, class Allocator>
> struct MtTestCaseDataT
> {
>     typedef std::basic_string <charT, Traits, Allocator> String;
>     typedef StringTestCaseData<charT>                    TestCaseData;
> 
>     const String         &str_;
>     const TestCaseData   &tdata_;
> };
> 
> template <class charT, class Traits, class Allocator>
> static void*
> thread_func (void *th_arg)
> {
>     typedef MtTestCaseDataT<charT, Traits, Allocator> MtTestCaseData;
>     typedef typename MtTestCaseData::String           String;
>     typedef typename String::iterator                 StringIter;
>     typedef typename MtTestCaseData::TestCaseData     TestCaseData;
> 
>     typedef MyStreambuf<charT, Traits>                Streambuf;
>     typedef std::basic_ios<charT, Traits>             BasicIos;
>     typedef std::basic_istream<charT, Traits>         Istream;
> 
>     const MtTestCaseData &mt_tdata =
>         *_RWSTD_STATIC_CAST (MtTestCaseData*, th_arg);
> 
>     const TestCaseData   &tdata    = mt_tdata.tdata_;
>     const StringFunc     &func     = tdata.func_;
>     const StringTestCase &tcase    = tdata.tcase_;
> 
>     String arg (tdata.arg_, tdata.arglen_);
> 
>     const charT arg_val = (make_char (char (tcase.val), (charT*)0));
> 
>     for (size_t i = 0; i != size_t (rw_opt_nloops); ++i) {
> 
>         String str (mt_tdata.str_);
> 
>         const charT* const arg_ptr = tcase.arg ? arg.c_str () : str.c_str ();
>         String&            arg_str = tcase.arg ? arg : str;
> 
>         const size_t size1 = str.length ();
>         const size_t off1 =
>             size_t (tcase.off) < size1 ? size_t (tcase.off) : size1;
>         const size_t ext1 =
>             off1 + tcase.size < size1 ? tcase.size : size1 - off1;
> 
>         // create a pair of iterators into the string object being
>         // modified (used only by the iterator overloads)
>         const StringIter it_first (str.begin () + off1);
>         const StringIter it_last  (it_first + ext1);
> 
>         switch (func.which_) {
> 
>         case StringIds::append_cptr:
>             str.append (arg_ptr);
>             break;
>         case StringIds::append_cstr:
>             str.append (arg_str);
>             break;
>         case StringIds::append_cptr_size:
>             str.append (arg_ptr, tcase.size);
>             break;
>         case StringIds::append_cstr_size_size:
>             str.append (arg_str, tcase.off2, tcase.size2);
>             break;
>         case StringIds::append_size_val:
>             str.append (tcase.size, arg_val);
>             break;
>         case StringIds::append_range:
>             str.append (it_first, it_last);
>             break;
> 
>         case StringIds::assign_cptr:
>             str.assign (arg_ptr);
>             break;
>         case StringIds::assign_cstr:
>             str.assign (arg_str);
>             break;
>         case StringIds::assign_cptr_size:
>             str.assign (arg_ptr, tcase.size);
>             break;
>         case StringIds::assign_cstr_size_size:
>             str.assign (arg_str, tcase.off2, tcase.size2);
>             break;
>         case StringIds::assign_size_val:
>             str.assign (tcase.size, arg_val);
>             break;
>         case StringIds::assign_range:
>             str.assign (it_first, it_last);
>             break;
> 
>         case StringIds::erase_void:
>             str.erase ();
>             break;
>         case StringIds::erase_size:
>             str.erase (tcase.off);
>             break;
>         case StringIds::erase_size_size:
>             str.erase (tcase.off, tcase.size);
>             break;
>         case StringIds::erase_iter:
>             str.erase (it_first);
>             break;
>         case StringIds::erase_iter_iter:
>             str.erase (it_first, it_last);
>             break;
> 
>         case StringIds::insert_size_cptr:
>             str.insert (tcase.off, arg_ptr);
>             break;
>         case StringIds::insert_size_cstr:
>             str.insert (tcase.off, arg_str);
>             break;
>         case StringIds::insert_size_cptr_size:
>             str.insert (tcase.off, arg_ptr, tcase.size2);
>             break;
>         case StringIds::insert_size_cstr_size_size:
>             str.insert (tcase.off, arg_str, tcase.off2, tcase.size2);
>             break;
>         case StringIds::insert_size_size_val:
>             str.insert (tcase.off, tcase.size2, arg_val);
>             break;
>         case StringIds::insert_iter_val:
>             str.insert (it_first, arg_val);
>             break;
>         case StringIds::insert_iter_size_val:
>             str.insert (it_first, tcase.size2, arg_val);
>             break;
>         case StringIds::insert_iter_range:
>             str.insert (it_first, it_first, it_last);
>             break;
> 
>         case StringIds::replace_size_size_cptr:
>             str.replace (tcase.off, tcase.size, arg_ptr);
>             break;
>         case StringIds::replace_size_size_cstr:
>             str.replace (tcase.off, tcase.size, arg_str);
>             break;
>         case StringIds::replace_size_size_cptr_size:
>             str.replace (tcase.off, tcase.size, arg_ptr, tcase.size);
>             break;
>         case StringIds::replace_size_size_cstr_size_size:
>             str.replace (tcase.off, tcase.size, arg_str, tcase.off2, tcase.size);
>             break;
>         case StringIds::replace_size_size_size_val:
>             str.replace (tcase.off, tcase.size, tcase.size2, arg_val);
>             break;
>         case StringIds::replace_iter_iter_cptr:
>             str.replace (it_first, it_last, arg_ptr);
>             break;
>         case StringIds::replace_iter_iter_cstr:
>             str.replace (it_first, it_last, arg_str);
>             break;
>         case StringIds::replace_iter_iter_cptr_size:
>             str.replace (it_first, it_last, arg_ptr, tcase.size2);
>             break;
>         case StringIds::replace_iter_iter_size_val:
>             str.replace (it_first, it_last, tcase.size2, arg_val);
>             break;
>         case StringIds::replace_iter_iter_range:
>             str.replace (it_first, it_first + 1, it_first, it_last);
>             break;
> 
>         case StringIds::op_plus_eq_cptr:
>             str.operator+= (arg_ptr);
>             break;
>         case StringIds::op_plus_eq_cstr:
>             str.operator+= (arg_str);
>             break;
>         case StringIds::op_plus_eq_val:
>             str.operator+= (arg_val);
>             break;
> 
>         case StringIds::substr_void:
>             str.substr ();
>             break;
>         case StringIds::substr_size:
>             str.substr (tcase.off);
>             break;
>         case StringIds::substr_size_size:
>             str.substr (tcase.off, tcase.size);
>             break;
> 
>         case StringIds::op_index_size:
>             str [tcase.off] = arg_val;
>             break;
>         case StringIds::at_size:
>             str.at (tcase.off) = arg_val;
>             break;
> 
>         case StringIds::swap_str:
>             str.swap (arg_str);
>             break;
> 
>         case StringIds::push_back_val:
>             str.push_back (arg_val);
>             break;
> 
>         case StringIds::resize_size_val:
>             str.resize (tcase.size, arg_val);
>             break;
>         case StringIds::resize_size:
>             str.resize (tcase.size);
>            break;
> 
>         case StringIds::reserve_size:
>             str.reserve (tcase.size);
>             break;
>         case StringIds::reserve_void:
>             str.reserve ();
>             break;
> 
>         case StringIds::clear_void:
>             str.clear ();
>             break;
> 
>         case StringIds::begin_void:
>             *str.begin () = arg_val;
>             break;
>         case StringIds::end_void:
>             *(str.end () - 1) = arg_val;
>             break;
> 
>         case StringIds::rbegin_void:
>             *str.rbegin () = arg_val;
>             break;
>         case StringIds::rend_void:
>             *(str.rend () - 1) = arg_val;
>             break;
> 
>         case StringIds::extractor_istream_str:
>         case StringIds::getline_istream_str:
>         case StringIds::getline_istream_str_val:
>             {
>                 const UserCtype<charT> ctyp (1);
>                 Streambuf inbuf (tcase.arg, tcase.arg_len, -1, -1);
>                 Istream is (&inbuf);
>                 is.imbue (std::locale (is.getloc (), &ctyp));
> 
>                 if (StringIds::extractor_istream_str == func.which_)
>                     is >> str;
>                 else if (StringIds::getline_istream_str == func.which_)
>                     std::getline (is, str);
>                 else if (StringIds::getline_istream_str_val == func.which_)
>                     std::getline (is, str, arg_val);
>             }
>             break;
> 
>         default:
>             RW_ASSERT (!"test logic error: unknown mt overload");
>         }
>     }
> 
>     return 0;
> }
> 
> /**************************************************************************/
> 
> template <class charT, class Traits, class Allocator>
> void test_mt (charT*, Traits*, Allocator*, 
>               const StringTestCaseData<charT> &tdata)
> {
>     typedef std::basic_string <charT, Traits, Allocator> String;
>     typedef MtTestCaseDataT<charT, Traits, Allocator>    MtTestCaseData;
> 
>     if (  StringIds::None          != tdata.func_.iter_id_
>        && StringIds::ConstIterator != tdata.func_.iter_id_ )
>     {
>         // for range methods overloads test the StringIds::ConstIterator only
>         return;
>     }
> 
>     const String cstr (tdata.str_, tdata.strlen_);
> 
>     // save the state of the const string object before the call
>     // to any (changes to the state of the object after a call)
>     const StringState cstr_state (rw_get_string_state (cstr));
> 
>     MtTestCaseData tdata_ = { cstr, tdata };
> 
>     void* args [MAX_THREADS];
>     for (size_t i = 0; i < sizeof (args) / sizeof (*args); ++i)
>         args [i] = _RWSTD_STATIC_CAST(void*, &tdata_);
> 
>     // create and start a pool of threads and wait for them to finish
>     rw_thread_pool (0, size_t (rw_opt_nthreads),
>         0, &thread_func<charT, Traits, Allocator>, args);
> 
>     // verify that const string object was not modified
>     int res = cstr_state.assert_equal (rw_get_string_state (cstr),
>         __LINE__, tdata.tcase_.line, "call");
> 
>     if (0 == res)
>         _rw_status = 1;
> }
> 
> /**************************************************************************/
> 
> DEFINE_STRING_TEST_FUNCTIONS (test_mt);
> 
> static int
> run_test (int argc, char** argv)
> {
>     RW_ASSERT (0 < argc);
> 
>     rw_info (0, 0, 0, "running %d thread%{?}s%{;}, %zu iteration%{?}s%{;} each",
>              rw_opt_nthreads, 1 != rw_opt_nthreads,
>              rw_opt_nloops, 1 != rw_opt_nloops);
> 
>     // allocate argv_ buffer + additional 4 elements:
>     // 1) --overload_id=xxx
>     // 2) --no-stdout
>     // 3) --no-UserAlloc
>     // 4) terminating NUL
>     char ** argv_ = _RWSTD_STATIC_CAST (char**,
>         malloc ((argc + 4) * sizeof (*argv_)));
>     if (!argv_)
>         return 1;
> 
>     // path
>     argv_ [0] = argv [0];
>     // leave the argv_[1] .. argv_[3] to init later
>     memcpy (argv_ + 4, argv + 1, (argc - 1) * sizeof (*argv_));
>     argv_ [2] = param2;
>     argv_ [3] = param3;
>     // terminating NUL 
>     argv_ [argc + 3] = 0;
> 
>     int fails = 0;
> 
>     char overload_id [sizeof (param_name) +
>         (CHAR_BIT * sizeof (unsigned)) * 301L / 1000 + 1];
> 
>     memcpy (overload_id, param_name, param_len);
> 
>     char* const pos = overload_id + param_len;
> 
>     for (size_t i = 0; i < test_count; ++i) {
> 
>         typedef StringIds Ids;
> 
>         const Ids::OverloadId which = overloads [i];
> 
>         sprintf (pos, "%u", unsigned (which));
>         argv_ [1] = overload_id;
> 
>         const bool is_range =
>                Ids::append_range            == which
>             || Ids::assign_range            == which
>             || Ids::insert_iter_range       == which
>             || Ids::replace_iter_iter_range == which;
> 
>         const StringFunc func = {
>             Ids::Char,
>             Ids::DefaultTraits,
>             Ids::DefaultAlloc,
>             is_range ? Ids::ConstIterator : Ids::None,
>             which
>         };
> 
>         // sets the {CLASS}, {FUNCSIG} environment variables
>         rw_setvars (func, 0);
> 
>         // determine whether the function is a member function
>         const bool is_member = 0 != (Ids::bit_member & which);
> 
>         rw_info (0, 0, 0,
>             "exercising the %{?}%{$CLASS}::%{;}%{$FUNCSIG}"
>                  " (overload_id = %d)",
>                  is_member, int (which));
> 
>         const rw_pid_t pid = rw_process_create (argv_ [0], argv_);
>         if (-1 == pid) {
>             rw_assert (0, 0, 0,
>                        "failed to create process to exercise"
>                        " %{?}%{$CLASS}::%{;}%{$FUNCSIG}"
>                        " (overload_id = %d)",
>                        is_member, int (which));
>         }
>         else {
>             int result = 1;
>             rw_waitpid (pid, &result);
> 
>             if (0 != result)
>                 ++fails;
> 
>             rw_assert (0 == result, 0, 0,
>                        "the test of %{?}%{$CLASS}::%{;}%{$FUNCSIG}"
>                        " (overload_id = %d) failed",
>                        is_member, int (which));
>         }
>     }
> 
>     free (argv_);
> 
>     return fails;
> }
> 
> /**************************************************************************/
> 
> static int
> _rw_setopts_mt ()
> {
>     const int nopts =
>         rw_setopts (
>                     "|-overload_id#0 "  // must be non-negative
>                     "|-nloops#0 "       // must be non-negative
>                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
>                     "|-stdout~ "        // to prevent "unknown option" output
>                     "|-UserAlloc~",     // to prevent "unknown option" output
>                     &rw_opt_overload_id,
>                     &rw_opt_nloops,
>                     int (MAX_THREADS),
>                     &rw_opt_nthreads,
>                     &rw_opt_dummy,
>                     &rw_opt_dummy,
>                     0 /* detect missing handlers */);
> 
>     if (5 > nopts) {
>         rw_fprintf (rw_stderr,
>                     "%s:%d: rw_setopts() failed\n",
>                     __FILE__, __LINE__);
>         abort ();
>         return 1;
>     }
> 
>     return 0;
> }
> 
> /**************************************************************************/
> 
> int main (int argc, char *argv[])
> {
>     // set the additional options
>     _rw_setopts_mt ();
> 
>     rw_runopts (argc, argv);
> 
>     if (0 <= rw_opt_overload_id) {
> 
>         // overload_id is specified
> 
>         const StringIds::OverloadId which =
>             _RWSTD_STATIC_CAST (StringIds::OverloadId, rw_opt_overload_id);
> 
>         // check that specified overload_id is present in overloads
>         size_t i = 0;
>         for (; i < test_count; ++i)
>             if (which == overloads [i])
>                 break;
> 
>         if (i >= test_count) {
>             // using rw_fprintf() because driver is not
>             // initialized at this point
>             rw_fprintf (rw_stderr,
>                         "%s:%d: invalid overload_id: %d\n",
>                         __FILE__, __LINE__, rw_opt_overload_id);
>             return 1;
>         }
> 
>         // test the specified overload_id
>         static const StringTestCase dummy_cases [1] = {
> #undef TEST
> #define TEST(str, arg, off, size, off2, size2, val) { \
>     __LINE__, off, size, off2, size2, val,            \
>     str, sizeof (str) - 1, arg, sizeof (arg) - 1,     \
>     0, 0, 0                                           \
> }
> 
>             TEST ("x@256", "abcd", 1, 2, 1, 2, 'y')
>         };
> 
>         const StringTest test = { which, dummy_cases, 1 };
> 
>         int res = rw_run_string_test (argc, argv, __FILE__,
>                                       "lib.string.mt",
>                                       test_mt_func_array,
>                                       &test, 1);
> 
>         return (0 == res) ? _rw_status : res;
>     }
> 
>     // test the all methods
>     return rw_test (argc, argv, __FILE__,
>                     "lib.string",
>                     "thread safety", run_test,
>                     "",
>                     0 /*sentinel*/);
> }
> 
> 
> ------------------------------------------------------------------------
> 
> Index: 21.strings.cpp
> ===================================================================
> --- 21.strings.cpp	(revision 425643)
> +++ 21.strings.cpp	(working copy)
> @@ -153,7 +153,7 @@
>  
>  /**************************************************************************/
>  
> -void StringState::
> +int StringState::
>  assert_equal (const StringState &state, int line, int case_line,
>                const char *when) const
>  {
> @@ -169,6 +169,8 @@
>                 line, data_, size_, capacity_,
>                 state.data_, state.size_, state.capacity_,
>                 when);
> +
> +    return equal;
>  }
>  
>  /**************************************************************************/
> @@ -414,9 +416,9 @@
>  // FUNCALL: a string describing the call to the basic_string function
>  //          with function with function arguments expanded (as specified
>  //          by the TestCase argument)
> -static void
> -_rw_setvars (const StringFunc     &func,
> -             const StringTestCase *pcase = 0)
> +void
> +rw_setvars (const StringFunc     &func,
> +            const StringTestCase *pcase = 0)
>  {
>      char*  buf     = 0;
>      size_t bufsize = 0;
> @@ -1296,7 +1298,7 @@
>  
>          // set the {FUNCALL} environment variable to describe
>          // the function call specified by this test case
> -        _rw_setvars (func, &tcase);
> +        rw_setvars (func, &tcase);
>  
>          if (test_callback) {
>              // invoke the test callback function
> @@ -1329,7 +1331,7 @@
>      // set the {CLASS}, {FUNC}, and {FUNCSIG} environment
>      // variable to the name of the basic_string specializaton
>      // and the string function being exercised
> -    _rw_setvars (func);
> +    rw_setvars (func);
>  
>      // determine whether the function is a member function
>      const bool is_member = 0 != (StringIds::bit_member & test.which);
> 
> 
> ------------------------------------------------------------------------
> 
> Index: 21.strings.h
> ===================================================================
> --- 21.strings.h	(revision 425643)
> +++ 21.strings.h	(working copy)
> @@ -408,7 +408,7 @@
>  
>          //////////////////////////////////////////////////////////////
>          // substr (void) const
> -        MEMBER_1 (substr, cstr, void),
> +        MEMBER_0 (substr, cstr),
>          // substr (size_type) const
>          MEMBER_1 (substr, cstr, size),
>          // substr (size_type, size_type) const
> @@ -541,15 +541,15 @@
>          NON_MEMBER_2 (op_greater_equal, cstr, cptr),
>  
>          //////////////////////////////////////////////////////////////
> -        // size ()
> +        // size () const
>          MEMBER_0 (size, cstr),
>  
>          //////////////////////////////////////////////////////////////
> -        // length ()
> +        // length () const
>          MEMBER_0 (length, cstr),
>  
>          //////////////////////////////////////////////////////////////
> -        // max_size ()
> +        // max_size () const
>          MEMBER_0 (max_size, cstr),
>  
>          //////////////////////////////////////////////////////////////
> @@ -559,7 +559,7 @@
>          MEMBER_1 (resize, str, size),
>  
>          //////////////////////////////////////////////////////////////
> -        // capacity ()
> +        // capacity () const
>          MEMBER_0 (capacity, cstr),
>  
>          //////////////////////////////////////////////////////////////
> @@ -573,7 +573,7 @@
>          MEMBER_0 (clear, str),
>  
>          //////////////////////////////////////////////////////////////
> -        // empty ()
> +        // empty () const
>          MEMBER_0 (empty, cstr),
>  
>          //////////////////////////////////////////////////////////////
> @@ -818,7 +818,7 @@
>      _RWSTD_SIZE_T capacity_;
>  
>      // invokes rw_assert() to verify that two states are the same
> -    void assert_equal (const StringState&, int, int, const char*) const;
> +    int assert_equal (const StringState&, int, int, const char*) const;
>  };
>  
>  



Mime
View raw message