first commit
This commit is contained in:
832
extern/stdcxx/4.2.1/tests/strings/21.string.exceptions.cpp
vendored
Normal file
832
extern/stdcxx/4.2.1/tests/strings/21.string.exceptions.cpp
vendored
Normal file
@@ -0,0 +1,832 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* 21.string.exceptions.cpp - test string members that throw exceptions
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 1994-2008 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <driver.h>
|
||||
|
||||
// uses setjmp() and longjmp() to verify correct function if exception
|
||||
// exception support is disabled
|
||||
#ifdef _RWSTD_NO_EXCEPTIONS
|
||||
# include <csetjmp>
|
||||
|
||||
int id; // "thrown" from user_throw () defined below
|
||||
jmp_buf env; // used to implement fake exception handling
|
||||
|
||||
# undef try
|
||||
# define try if (0 == (id = setjmp (env)))
|
||||
|
||||
# undef catch
|
||||
# define catch(ignore) else if (0 != id)
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
|
||||
// use a type that string isn't instantiated/specialized on by the library
|
||||
// also use a native type to avoid having to specialize char_traits
|
||||
typedef int Char;
|
||||
|
||||
typedef std::char_traits<Char> CharTraits;
|
||||
typedef std::allocator<Char> CharAllocator;
|
||||
|
||||
typedef std::basic_string<Char, CharTraits, CharAllocator> String;
|
||||
|
||||
|
||||
_RWSTD_NAMESPACE (std) {
|
||||
|
||||
// specialize in order to easily induce exceptional conditions
|
||||
_RWSTD_SPECIALIZED_CLASS
|
||||
String::size_type String::max_size () const
|
||||
{
|
||||
return _RWSTD_NEW_CAPACITY (String, this, 0);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
||||
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
|
||||
# include <rw_new.h>
|
||||
#else
|
||||
// can't check for memory leaks using the replacement
|
||||
// operators new and delete
|
||||
# define rwt_check_leaks(psize, ignore) \
|
||||
((psize) ? *(std::size_t*)(psize) = 0 : 0)
|
||||
#endif
|
||||
|
||||
|
||||
/* static */ void
|
||||
user_throw (int ex_id, char *what)
|
||||
{
|
||||
delete[] what;
|
||||
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
throw ex_id;
|
||||
|
||||
#else // if defined (_RWSTD_NO_EXCEPTIONS)
|
||||
|
||||
longjmp (env, ex_id);
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static void
|
||||
test_simple_throw ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "exception handling test setup");
|
||||
|
||||
// establish a chekpoint for memory leaks
|
||||
rwt_check_leaks (0, 0);
|
||||
|
||||
#ifdef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
// prevent library from aborting if exception support is disabled
|
||||
_RW::__rw_throw_proc = user_throw;
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// throw and catch a bogus exception in order to initialize
|
||||
// data structures internal to the library to prevent any
|
||||
// memory allocation from throwing off memory leak detection
|
||||
_RWSTD_REQUIRES (0, (_RWSTD_ERROR_OUT_OF_RANGE,
|
||||
_RWSTD_FUNC ("test_simple_throw ()"), 0, 0));
|
||||
}
|
||||
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (std::out_of_range&) {
|
||||
thrown = 1;
|
||||
}
|
||||
|
||||
#else // if defined (_RWSTD_NO_EXCEPTIONS)
|
||||
|
||||
catch (int id) {
|
||||
thrown = id == _RWSTD_ERROR_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (...) {
|
||||
thrown = -1;
|
||||
}
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"_RWSTD_REQUIRES (_RWSTD_ERROR_OUT_OF_RANGE) failed to "
|
||||
"throw std::out_of_range");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// const objects used throughout remaining test cases
|
||||
|
||||
const Char s[] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', '\0'
|
||||
};
|
||||
|
||||
const String s0 (s);
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// constructor tests
|
||||
|
||||
static void
|
||||
test_size_ctor ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.1, p4 (size)");
|
||||
|
||||
// establish a chekpoint for memory leaks
|
||||
rwt_check_leaks (0, 0);
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > str.size ()
|
||||
String s1 (s0, s0.size () + 1);
|
||||
}
|
||||
#ifndef _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (std::out_of_range&) {
|
||||
thrown = 1;
|
||||
}
|
||||
|
||||
#else // if defined (_RWSTD_NO_EXCEPTIONS)
|
||||
|
||||
catch (int id) {
|
||||
thrown = id == _RWSTD_ERROR_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_EXCEPTIONS
|
||||
|
||||
catch (...) {
|
||||
thrown = -1;
|
||||
}
|
||||
|
||||
std::size_t nbytes; /* uninitialized */
|
||||
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
|
||||
_RWSTD_UNUSED (nblocks);
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
("string::string (const string&, size_type, size_type, "
|
||||
"const allocator_type&) failed to throw std::out_of_range"));
|
||||
|
||||
rw_assert (s == s0, __FILE__, __LINE__,
|
||||
"original const string modified");
|
||||
|
||||
rw_assert (0 == nbytes, __FILE__, __LINE__,
|
||||
"string::string (const string&, size_type, size_type, "
|
||||
"const allocator_type&) leaked %u bytes", nbytes);
|
||||
}
|
||||
|
||||
static void
|
||||
test_npos_ctor ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.1, p4 (npos)");
|
||||
|
||||
_RW::__rw_throw_proc = user_throw;
|
||||
|
||||
// establish a chekpoint for memory leaks
|
||||
rwt_check_leaks (0, 0);
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > str.size ()
|
||||
String s1 (s0, String::npos);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
std::size_t nbytes; /* uninitialized */
|
||||
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
|
||||
_RWSTD_UNUSED (nblocks);
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::string (const string&, size_type, size_type, "
|
||||
"const allocator_type&) failed to use __rw::__rw_throw()");
|
||||
|
||||
rw_assert (0 == nbytes, __FILE__, __LINE__,
|
||||
"string::string (const string&, size_type, size_type, "
|
||||
"const allocator_type&) leaked %u bytes", nbytes);
|
||||
|
||||
rw_assert (s == s0, __FILE__, __LINE__,
|
||||
"original const string modified");
|
||||
}
|
||||
|
||||
static void
|
||||
test_max_size_ctor1 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.1, p7");
|
||||
|
||||
// establish a chekpoint for memory leaks
|
||||
rwt_check_leaks (0, 0);
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if n > max_size () (*)
|
||||
// (*) see also lwg issue 83
|
||||
String s1 (s0.data (), s0.max_size () + 1);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
std::size_t nbytes; /* uninitialized */
|
||||
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
|
||||
_RWSTD_UNUSED (nblocks);
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::string (const char_type*, size_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
rw_assert (0 == nbytes, __FILE__, __LINE__,
|
||||
"string::string (const char_type*, size_type)"
|
||||
"leaked %u bytes", nbytes);
|
||||
|
||||
rw_assert (s == s0, __FILE__, __LINE__,
|
||||
"original const string modified");
|
||||
}
|
||||
|
||||
static void
|
||||
test_max_size_ctor2 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.1, p13");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// throws std::length_error if n > max_size () (*)
|
||||
// (*) see also lwg issue 83
|
||||
String s1 (s0.max_size () + 1, Char ());
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::string (size_type, char_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
}
|
||||
|
||||
static void
|
||||
test_len_ctor ()
|
||||
{
|
||||
#ifndef _RWSTD_NO_MEMBER_TEMPLATES
|
||||
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.1, p15");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// same as 21.3.1, p13 for integral arguments
|
||||
String s1 = String (long (String::npos), long (' '));
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::string (InputIterator, InputIterator)"
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
#endif // _RWSTD_NO_MEMBER_TEMPLATES
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
// member functions
|
||||
|
||||
static void
|
||||
test_resize ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.3, p6");
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
// save data, size and capacity of a constructed string
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
rw_assert (s1.size () == s0.size () && s1 == s0, __FILE__, __LINE__,
|
||||
"std::string::string (const string&)");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
try {
|
||||
// throws std::length_error if n > max_size ()
|
||||
s1.resize (s1.max_size () + 1U /* , char () */);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::resize (size_type, char_type)"
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::resize (size_type, char_type) modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_reserve ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.3, p12");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::length_error if n > max_size ()
|
||||
s1.reserve (s1.max_size () + 1U);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_LENGTH_ERROR == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::reserve (size_type)"
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::reserve (size_type) modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_at ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.4, p3");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > size ()
|
||||
s1.at (s1.size ());
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::at (size_type) failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::at (size_type) modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_append ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.2, p3");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > size ()
|
||||
s1.append (s1, s1.size () + 1, 0);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::append (const string&, size_type, size_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::append (const string&, size_type, size_type) "
|
||||
"modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_assign ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.3, p3");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > size ()
|
||||
s1.assign (s1, s1.size () + 1, 0);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::assign (const string&, size_type, size_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::assign (const string&, size_type, size_type) "
|
||||
"modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_insert1 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.4, p3 (pos1 > size ())");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if:
|
||||
// 1) pos1 > size () <-- testing
|
||||
// 2) or pos2 > str.size ()
|
||||
s1.insert (s1.size () + 1, s1, 0, 0);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::insert (size_type, const string&, size_type, "
|
||||
"size_type) failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::insert (size_type, const string&, size_type, "
|
||||
"modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_insert2 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.4, p3 (pos2 > str.size ())");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if:
|
||||
// 1) pos1 > size ()
|
||||
// 2) or pos2 > str.size () <-- testing
|
||||
s1.insert (s1.size (), s1, s1.size () + 1, 0);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::insert (size_type, const string&, size_type, "
|
||||
"size_type) failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::insert (size_type, const string&, size_type, "
|
||||
"modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_erase ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.5, p2");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > size ()
|
||||
s1.erase (s1.size () + 1 /* , String::npos */);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::erase (size_type, size_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::erase (size_type, size_type) modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_replace1 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.6, p3 (pos1 > size ())");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if:
|
||||
// 1) pos1 > size () <-- testing
|
||||
// 2) or pos2 > str.size ()
|
||||
s1.replace (s1.size () + 1, 0, s0, s0.size (), 0);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_replace2 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.6, p3 (pos2 > str.size ())");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if:
|
||||
// 1) pos1 > size ()
|
||||
// 2) or pos2 > str.size () <-- testing
|
||||
s1.replace (s1.size (), 0, s1, s1.size () + 1, 0);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) modified *this");
|
||||
}
|
||||
|
||||
static void
|
||||
test_replace3 ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.6, p5");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
const String::const_pointer s1_data = s1.data ();
|
||||
const String::size_type s1_size = s1.size ();
|
||||
const String::size_type s1_cap = s1.capacity ();
|
||||
|
||||
// establish a chekpoint for memory leaks
|
||||
rwt_check_leaks (0, 0);
|
||||
|
||||
try {
|
||||
// make sure max_size() isn't too big
|
||||
assert (s1.max_size () == _RWSTD_NEW_CAPACITY (String, &s1, 0));
|
||||
|
||||
thrown = -1;
|
||||
|
||||
// must not throw
|
||||
String s2 (s1.max_size () - s1.size () + 2, Char ());
|
||||
|
||||
thrown = 0;
|
||||
|
||||
// throws std::length_error if:
|
||||
// size () - xlen >= max_size () - rlen (*)
|
||||
// where xlen = min (n1, this->size () - pos1)
|
||||
// and rlen = min (n2, str.size () - pos2)
|
||||
// (*) see also lwg issue 86
|
||||
s1.replace (0, 1, s2, 0, s2.size ());
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = 0 == thrown && _RWSTD_ERROR_LENGTH_ERROR == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
std::size_t nbytes; /* uninitialized */
|
||||
std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
|
||||
_RWSTD_UNUSED (nblocks);
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that string wasn't modified
|
||||
rw_assert (s1_data == s1.data () && s1_size == s1.size ()
|
||||
&& s1_cap == s1.capacity (), __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) modified *this");
|
||||
|
||||
// tests not only replace() but also string ctor (s2 above)
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::replace (size_type, size_type, const string&, "
|
||||
"size_type, size_type) leaked %u bytes", nbytes);
|
||||
}
|
||||
|
||||
static void
|
||||
test_copy ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.5.7, p2");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
Char c = '\1';
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > size ()
|
||||
s1.copy (&c, 1, s1.size () + 1);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::copy (pointer, size_type, size_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
|
||||
// verify that destination buffer wasn't modified
|
||||
rw_assert ('\1' == c, __FILE__, __LINE__,
|
||||
"string::copy (pointer, size_type, size_type) "
|
||||
"modified buffer");
|
||||
}
|
||||
|
||||
static void
|
||||
test_substr ()
|
||||
{
|
||||
rw_info (0, __FILE__, __LINE__, "21.3.6.7, p2");
|
||||
|
||||
int thrown = 0;
|
||||
|
||||
String s1 (s0);
|
||||
|
||||
try {
|
||||
// throws std::out_of_range if pos > size ()
|
||||
s1.substr (s1.size () + 1 /* , String::npos */);
|
||||
}
|
||||
catch (int id) {
|
||||
thrown = _RWSTD_ERROR_OUT_OF_RANGE == id;
|
||||
}
|
||||
catch (...) { /* empty */ }
|
||||
|
||||
rw_assert (1 == thrown, __FILE__, __LINE__,
|
||||
"string::substr (size_type, size_type) "
|
||||
"failed to use __rw::__rw_throw()");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static int
|
||||
run_test (int /*unused*/, char* /*unused*/ [])
|
||||
{
|
||||
test_simple_throw ();
|
||||
|
||||
// constructors
|
||||
test_size_ctor ();
|
||||
test_npos_ctor ();
|
||||
|
||||
test_max_size_ctor1 ();
|
||||
test_max_size_ctor2 ();
|
||||
|
||||
test_len_ctor ();
|
||||
|
||||
// member functions
|
||||
test_resize ();
|
||||
test_reserve ();
|
||||
test_at ();
|
||||
test_append ();
|
||||
test_assign ();
|
||||
|
||||
test_insert1 ();
|
||||
test_insert2 ();
|
||||
|
||||
test_erase ();
|
||||
|
||||
test_replace1 ();
|
||||
test_replace2 ();
|
||||
test_replace3 ();
|
||||
|
||||
test_copy ();
|
||||
test_substr ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*extern*/ int
|
||||
main (int argc, char* argv [])
|
||||
{
|
||||
return rw_test (argc, argv, __FILE__,
|
||||
"lib.basic.string",
|
||||
"exception saftety",
|
||||
run_test, "", 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user