Return-Path: Delivered-To: apmail-incubator-stdcxx-commits-archive@www.apache.org Received: (qmail 77206 invoked from network); 7 Jun 2006 09:53:41 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 7 Jun 2006 09:53:41 -0000 Received: (qmail 42609 invoked by uid 500); 7 Jun 2006 09:53:41 -0000 Delivered-To: apmail-incubator-stdcxx-commits-archive@incubator.apache.org Received: (qmail 42593 invoked by uid 500); 7 Jun 2006 09:53:41 -0000 Mailing-List: contact stdcxx-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-commits@incubator.apache.org Received: (qmail 42582 invoked by uid 99); 7 Jun 2006 09:53:40 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 07 Jun 2006 02:53:40 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 07 Jun 2006 02:53:39 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 199771A983A; Wed, 7 Jun 2006 02:53:19 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r412349 - /incubator/stdcxx/trunk/tests/strings/21.string.swap.cpp Date: Wed, 07 Jun 2006 09:53:18 -0000 To: stdcxx-commits@incubator.apache.org From: antonp@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060607095319.199771A983A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: antonp Date: Wed Jun 7 02:53:18 2006 New Revision: 412349 URL: http://svn.apache.org/viewvc?rev=412349&view=rev Log: 2006-06-07 Anton Pevtsov * 21.string.swap.cpp (str_test_cases): Added test cases with special strings length. (test_swap): Added two Allocator parameters, migrated to use StringTestCaseData structure, exception safety testing loop added. (main): rw_run_string_test call updated according to test driver changes. Modified: incubator/stdcxx/trunk/tests/strings/21.string.swap.cpp Modified: incubator/stdcxx/trunk/tests/strings/21.string.swap.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/strings/21.string.swap.cpp?rev=412349&r1=412348&r2=412349&view=diff ============================================================================== --- incubator/stdcxx/trunk/tests/strings/21.string.swap.cpp (original) +++ incubator/stdcxx/trunk/tests/strings/21.string.swap.cpp Wed Jun 7 02:53:18 2006 @@ -85,6 +85,15 @@ TEST ("\0\0\0", "x@4096"), TEST ("x@4096", "x@4096"), + TEST ("", "x@128"), + TEST ("x@207", "x@128"), + TEST ("x@128", "x@334"), + TEST ("x@873", "x@334"), + TEST ("x@1412", "x@540"), + TEST ("x@540", "x@2284"), + TEST ("x@3695", "x@2284"), + TEST ("x@3695", "x@128"), + TEST ("", 0), TEST ("\0", 0), TEST ("abc", 0), @@ -104,52 +113,35 @@ /**************************************************************************/ template -void test_swap (charT, Traits*, Allocator*, - const StringFunc&, - const StringTestCase &tcase) +void test_swap (charT*, Traits*, + Allocator &a1, + Allocator &a2, + const StringTestCaseData &tdata) { typedef std::basic_string String; typedef UserTraits::MemFun UTMemFun; - static const std::size_t BUFSIZE = 256; - - static charT wstr_buf [BUFSIZE]; - static charT warg_buf [BUFSIZE]; - - std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf; - std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf; - - charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len); - charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len); - - // construct the string object and the argument string - String s_str (wstr, str_len); - String s_arg (warg, arg_len); - - if (wstr != wstr_buf) - delete[] wstr; + const StringTestCase &tcase = tdata.tcase_; - if (warg != warg_buf) - delete[] warg; - - wstr = 0; - warg = 0; - - if (0 == tcase.arg) - arg_len = str_len; - - // save the state of the string object before the call - // to detect wxception safety violations (changes to - // the state of the object after an exception) - const StringState str_state (rw_get_string_state (s_str)); + // construct the string object to be modified + // and the argument string + String s_str (tdata.str_, tdata.strlen_, a1); + String s_arg (tdata.arg_, tdata.arglen_, a2); const charT* const p1 = s_str.data (); const charT* const p2 = tcase.arg ? s_arg.data () : s_str.data (); const char* const src = tcase.arg ? tcase.arg : tcase.str; const std::size_t src_len = tcase.arg ? tcase.arg_len : tcase.str_len; + const std::size_t srclen_ = tcase.arg ? tdata.arglen_ : tdata.strlen_; String& arg_str = tcase.arg ? s_arg : s_str; + // save the state of the string object before the call + // to detect wxception safety violations (changes to + // the state of the object after an exception) + const StringState str_state (rw_get_string_state (s_str)); + const StringState arg_str_state (rw_get_string_state (arg_str)); + std::size_t n_total_op_assign = 0; std::size_t n_total_op_assign2 = 0; std::size_t n_total_op_copy = 0; @@ -163,135 +155,215 @@ n_total_op_move = rg_calls[UTMemFun::move]; } -#ifndef _RWSTD_NO_EXCEPTIONS + rwt_free_store* const pst = rwt_get_free_store (0); + SharedAlloc* const pal = SharedAlloc::instance (); - // no exceptions expected - const char* expected = 0; - const char* caught = 0; + // iterate for`throw_count' starting at the next call to operator new, + // forcing each call to throw an exception, until the function finally + // succeeds (i.e, no exception is thrown) + std::size_t throw_count; + for (throw_count = 0; ; ++throw_count) { -#else // if defined (_RWSTD_NO_EXCEPTIONS) + const char* expected = 0; + const char* caught = 0; - if (tcase.bthrow) - return; +#ifndef _RWSTD_NO_EXCEPTIONS -#endif // _RWSTD_NO_EXCEPTIONS + // no exceptions expected + if (0 == tcase.bthrow) { + // by default excercise the exception safety of the function + // by iteratively inducing an exception at each call to operator + // new or Allocator::allocate() until the call succeeds + expected = exceptions [3]; // bad_alloc + *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1; + pal->throw_at_calls_ [pal->m_allocate] = + pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1; + } - try { +#else // if defined (_RWSTD_NO_EXCEPTIONS) - // start checking for memory leaks - rwt_check_leaks (0, 0); + if (tcase.bthrow) + return; - if (0 == tcase.str) - String ().swap (arg_str); - else - s_str.swap (arg_str); +#endif // _RWSTD_NO_EXCEPTIONS - if (rg_calls) { + try { - std::size_t n_op_assign = - rg_calls[UTMemFun::assign] - n_total_op_assign; - std::size_t n_op_assign2 = - rg_calls[UTMemFun::assign2] - n_total_op_assign2; - std::size_t n_op_copy = - rg_calls[UTMemFun::copy] - n_total_op_copy; - std::size_t n_op_move = - rg_calls[UTMemFun::move] - n_total_op_move; + // start checking for memory leaks + rw_check_leaks (s_str.get_allocator ()); + rw_check_leaks (arg_str.get_allocator ()); + + if (0 == tcase.str) + String ().swap (arg_str); + else + s_str.swap (arg_str); + + if (rg_calls) { + + std::size_t n_op_assign = + rg_calls[UTMemFun::assign] - n_total_op_assign; + std::size_t n_op_assign2 = + rg_calls[UTMemFun::assign2] - n_total_op_assign2; + std::size_t n_op_copy = + rg_calls[UTMemFun::copy] - n_total_op_copy; + std::size_t n_op_move = + rg_calls[UTMemFun::move] - n_total_op_move; + + bool success = + 0 == (n_op_assign | n_op_assign2 | n_op_copy | n_op_move); + + rw_assert (success, 0, tcase.line, + "line %d. %{$FUNCALL}: complexity: %zu assigns, " + "%zu assign2s, %zu copies, %zu moves", __LINE__, + n_op_assign, n_op_assign2, n_op_copy, n_op_move); + } + + if (0 == tcase.str) { + + rw_assert (0 == arg_str.capacity (), 0, tcase.line, + "line %d. %{$FUNCALL}: expected 0 capacity, " + "got %zu", __LINE__, arg_str.capacity ()); + } + else { + + const charT* const res_p1 = s_str.data (); + const charT* const res_p2 = + tcase.arg ? s_arg.data () : s_str.data (); + + const std::size_t res1_len = s_str.size (); + const std::size_t res2_len = + tcase.arg ? s_arg.size () : s_str.size (); + + rw_assert (res_p1 == p2 && res_p2 == p1, 0, tcase.line, + "line %d. %{$FUNCALL}: got offset %td from " + "expected value, arg.data (): got offset %td " + "from expected value", + __LINE__, p2 - res_p1, p1 - res_p2); + + std::size_t match = + rw_match (tcase.str, res_p2, tcase.str_len); + + rw_assert (match == tdata.strlen_, 0, tcase.line, + "line %d. %{$FUNCALL}: this == %{#*s}, got this = " + "%{/*.*Gs}, differs at pos %zu", + __LINE__, int (src_len), src, int (sizeof (charT)), + int (res1_len), res_p1, match); + + match = rw_match (src, res_p1, src_len); + + rw_assert (match == srclen_, 0, tcase.line, + "line %d. %{$FUNCALL}: str == %{#*s}, got str = " + "%{/*.*Gs}, differs at pos %zu", + __LINE__, int (tcase.str_len), tcase.str, + int (sizeof (charT)), int (res2_len), + res_p2, match); + } + } - bool success = - 0 == (n_op_assign | n_op_assign2 | n_op_copy | n_op_move); +#ifndef _RWSTD_NO_EXCEPTIONS - rw_assert (success, 0, tcase.line, - "line %d. %{$FUNCALL}: complexity: %zu assigns, " - "%zu assign2s, %zu copies, %zu moves", __LINE__, - n_op_assign, n_op_assign2, n_op_copy, n_op_move); + 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); } - if (0 == tcase.str) { +#endif // _RWSTD_NO_EXCEPTIONS - rw_assert (0 == arg_str.capacity (), 0, tcase.line, - "line %d. %{$FUNCALL}: expected 0 capacity, got %zu", - __LINE__, arg_str.capacity ()); + // FIXME: verify the number of blocks the function call + // is expected to allocate and detect any memory leaks + rw_check_leaks (s_str.get_allocator (), tcase.line, + std::size_t (-1), std::size_t (-1)); + + rw_check_leaks (arg_str.get_allocator (), tcase.line, + std::size_t (-1), std::size_t (-1)); + + if (caught) { + // verify that an exception thrown during allocation + // didn't cause a change in the state of the object + str_state.assert_equal (rw_get_string_state (s_str), + __LINE__, tcase.line, caught); + + arg_str_state.assert_equal (rw_get_string_state (arg_str), + __LINE__, tcase.line, caught); + + if (0 == tcase.bthrow) { + // allow this call to operator new to succeed and try + // to make the next one to fail during the next call + // to the same function again + continue; + } + } + else if (0 < 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); } - else { - - const charT* const res_p1 = s_str.data (); - const charT* const res_p2 = - tcase.arg ? s_arg.data () : s_str.data (); - const std::size_t res1_len = s_str.size (); - const std::size_t res2_len = - tcase.arg ? s_arg.size () : s_str.size (); + break; + } - rw_assert (res_p1 == p2 && res_p2 == p1, 0, tcase.line, - "line %d. %{$FUNCALL}: got offset %td from expected value," - " arg.data (): got offset %td from expected value", - __LINE__, p2 - res_p1, p1 - res_p2); + // no exception expected + const std::size_t expect_throws = 0; - std::size_t match = rw_match (tcase.str, res_p2, tcase.str_len); + rw_assert (expect_throws == throw_count, 0, tcase.line, + "line %d: %{$FUNCALL}: expected exactly 0 %s exception " + "while the swap, got %zu", + __LINE__, exceptions [3], throw_count); + + // disable bad_alloc exceptions + *pst->throw_at_calls_ [0] = 0; + pal->throw_at_calls_ [pal->m_allocate] = 0; +} - rw_assert (match == str_len, 0, tcase.line, - "line %d. %{$FUNCALL}: this == %{#*s}, got this = " - "%{/*.*Gs}, differs at pos %zu", - __LINE__, int (src_len), src, int (sizeof (charT)), - int (res1_len), res_p1, match); +/**************************************************************************/ - match = rw_match (src, res_p1, src_len); +template +std::allocator +make_alloc (SharedAlloc&, std::allocator*) { + return std::allocator(); +} - rw_assert (match == arg_len, 0, tcase.line, - "line %d. %{$FUNCALL}: str == %{#*s}, got str = " - "%{/*.*Gs}, differs at pos %zu", - __LINE__, int (tcase.str_len), tcase.str, - int (sizeof (charT)), int (res2_len), res_p2, match); - } - } +template +UserAlloc +make_alloc (SharedAlloc &shal, UserAlloc*) { + return UserAlloc(&shal); +} -#ifndef _RWSTD_NO_EXCEPTIONS +/**************************************************************************/ - 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); - } +template +void test_swap (charT*, Traits*, Allocator*, + const StringTestCaseData &tdata) +{ + SharedAlloc sa1; + Allocator a1 = make_alloc(sa1, (Allocator*)0); -#endif // _RWSTD_NO_EXCEPTIONS + // test swap using the same allocator objects + test_swap ((charT*)0, (Traits*)0, a1, a1, tdata); - /* const */ std::size_t nbytes; - const std::size_t nblocks = rwt_check_leaks (&nbytes, 0); + SharedAlloc sa2; + Allocator a2 = make_alloc(sa2, (Allocator*)0); - // FIXME: verify the number of blocks the function call - // is expected to allocate and detect any memory leaks - const std::size_t expect_blocks = nblocks; - - rw_assert (nblocks == expect_blocks, 0, tcase.line, - "line %d. %{$FUNCALL} allocated %td bytes in %td blocks", - __LINE__, nbytes, expect_blocks); - - if (caught) { - // verify that an exception thrown during allocation - // didn't cause a change in the state of the object - str_state.assert_equal (rw_get_string_state (s_str), - __LINE__, tcase.line, caught); - } - 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); + if (a1 != a2) { + // test swap using different allocator objects + test_swap ((charT*)0, (Traits*)0, a1, a2, tdata); } } /**************************************************************************/ -DEFINE_STRING_TEST_DISPATCH (test_swap); +DEFINE_STRING_TEST_FUNCTIONS (test_swap); int main (int argc, char** argv) { @@ -301,7 +373,7 @@ #undef TEST #define TEST(sig) { \ Swap (sig), sig ## _test_cases, \ - sizeof sig ## _test_cases / sizeof *sig ## _test_cases \ + sizeof sig ## _test_cases / sizeof *sig ## _test_cases, \ } TEST (str) @@ -309,7 +381,10 @@ const std::size_t test_count = sizeof tests / sizeof *tests; - return rw_run_string_test (argc, argv, __FILE__, - "lib.string.swap", - test_swap, tests, test_count); + const int status = + rw_run_string_test (argc, argv, __FILE__, + "lib.string.swap", + test_swap_func_array, tests, test_count); + + return status; }