Commit 162c7cd9 by Stephen M. Webb Committed by Benjamin Kosnik

testsuite_allocator.h: New file.


2002-11-25  Stephen M. Webb  <stephen@bregmasoft.com>

        * testsuite/testsuite_allocator.h: New file.
        * testsuite/testsuite_allocator.cc: New file.
        * testsuite/Makefile.am: Added testsuite_allocator to test library.
        * testsuite/testsuite_hooks.h: Added more detailed tracker objects
        gnu_copy_constructor, gnu_assignment_operator, and gnu_destructor.
        * testsuite/testsuite_hooks.cc: Added new static objects definitions.
        * testsuite/23_containers/vector_capacity.cc: Added reserve() tests.
        * testsuite/23_containers/vector_ctor.cc: Added a plethora of tests.
        * testsuite/23_containers/deque_ctor.cc: Added a slew of new tests.

From-SVN: r59484
parent 83bbd9b6
2002-11-25 Stephen M. Webb <stephen@bregmasoft.com>
* testsuite/testsuite_allocator.h: New file.
* testsuite/testsuite_allocator.cc: New file.
* testsuite/Makefile.am: Added testsuite_allocator to test library.
* testsuite/testsuite_hooks.h: Added more detailed tracker objects
gnu_copy_constructor, gnu_assignment_operator, and gnu_destructor.
* testsuite/testsuite_hooks.cc: Added new static objects definitions.
* testsuite/23_containers/vector_capacity.cc: Added reserve() tests.
* testsuite/23_containers/vector_ctor.cc: Added a plethora of tests.
* testsuite/23_containers/deque_ctor.cc: Added a slew of new tests.
2002-11-25 Mark Mitchell <mark@codesourcery.com> 2002-11-25 Mark Mitchell <mark@codesourcery.com>
* libsupc++/Makefile.am (sources): Add guard.cc. * libsupc++/Makefile.am (sources): Add guard.cc.
......
dnl aclocal.m4 generated automatically by aclocal 1.4-p6 dnl aclocal.m4 generated automatically by aclocal 1.4-p5
dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation dnl This file is free software; the Free Software Foundation
...@@ -2262,7 +2262,7 @@ AC_MSG_RESULT($enable_symvers) ...@@ -2262,7 +2262,7 @@ AC_MSG_RESULT($enable_symvers)
]) ])
# isc-posix.m4 serial 2 (gettext-0.11.2) # isc-posix.m4 serial 1 (gettext-0.10.40)
dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General dnl General Public License. As a special exception to the GNU General
...@@ -2270,8 +2270,6 @@ dnl Public License, this file may be distributed as part of a program ...@@ -2270,8 +2270,6 @@ dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program. dnl the same distribution terms as the rest of that program.
# This file is not needed with autoconf-2.53 and newer. Remove it in 2005.
# This test replaces the one in autoconf. # This test replaces the one in autoconf.
# Currently this macro should have the same name as the autoconf macro # Currently this macro should have the same name as the autoconf macro
# because gettext's gettext.m4 (distributed in the automake package) # because gettext's gettext.m4 (distributed in the automake package)
...@@ -2332,8 +2330,7 @@ dnl Usage: ...@@ -2332,8 +2330,7 @@ dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define]) dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN([AM_INIT_AUTOMAKE], AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl [AC_REQUIRE([AC_PROG_INSTALL])
AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1] PACKAGE=[$1]
AC_SUBST(PACKAGE) AC_SUBST(PACKAGE)
VERSION=[$2] VERSION=[$2]
...@@ -2349,42 +2346,13 @@ AC_REQUIRE([AM_SANITY_CHECK]) ...@@ -2349,42 +2346,13 @@ AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM]) AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross. dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd` missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}, $missing_dir) AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])]) AC_REQUIRE([AC_PROG_MAKE_SET])])
# Copyright 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.4"])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION so it can be traced.
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.4-p6])])
# #
# Check to make sure that the build environment is sane. # Check to make sure that the build environment is sane.
# #
......
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
/* Define if you have a working `mmap' system call. */ /* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP #undef HAVE_MMAP
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
// Define if GCC supports weak symbols. // Define if GCC supports weak symbols.
#undef _GLIBCPP_SUPPORTS_WEAK #undef _GLIBCPP_SUPPORTS_WEAK
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <vector> #include <vector>
#include <stdexcept> #include <stdexcept>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
template<typename T> template<typename T>
...@@ -119,10 +120,72 @@ void test03() ...@@ -119,10 +120,72 @@ void test03()
VERIFY( test ); VERIFY( test );
} }
// Verifies basic functionality of reserve() with forced reallocation.
void
test_reserve()
{
typedef gnu_copy_tracker T;
typedef std::vector<T, gnu_new_allocator<T> > X;
gnu_allocator_tracker::resetCounts();
{
X a(3);
const X::size_type old_size = a.size();
const X::size_type old_capacity = a.capacity();
const X::size_type new_capacity = old_capacity + 10;
T::reset();
a.reserve(new_capacity);
// [23.2.4.1 (2)]
VERIFY(new_capacity <= a.capacity());
// [23.2.4.1 (3)]
VERIFY(old_size == a.size());
VERIFY(gnu_copy_constructor::count() <= old_size);
VERIFY(gnu_destructor::count() <= old_size);
}
// check for memory leaks
VERIFY(gnu_allocator_tracker::allocationTotal() == gnu_allocator_tracker::deallocationTotal());
}
// Verifies that reserve() with reallocation offers the strong
// exception guarantee.
void
test_reserve_exception_guarantee()
{
typedef gnu_copy_tracker T;
typedef std::vector<T, gnu_new_allocator<T> > X;
gnu_allocator_tracker::resetCounts();
{
X a(7);
const X::size_type old_size = a.size();
const X::size_type old_capacity = a.capacity();
const X::size_type new_capacity = old_capacity + 10;
T::reset();
gnu_copy_constructor::throw_on(3);
try
{
a.reserve(new_capacity);
VERIFY(("no exception thrown", false));
}
catch (...)
{
}
VERIFY(old_capacity == a.capacity());
VERIFY(gnu_copy_constructor::count() == gnu_destructor::count()+1);
}
VERIFY(gnu_allocator_tracker::allocationTotal() == gnu_allocator_tracker::deallocationTotal());
}
int main() int main()
{ {
test01(); test01();
test02(); test02();
test03(); test03();
test_reserve();
test_reserve_exception_guarantee();
return 0; return 0;
} }
...@@ -51,7 +51,7 @@ INCLUDES = \ ...@@ -51,7 +51,7 @@ INCLUDES = \
## Build support library. ## Build support library.
noinst_LIBRARIES = libv3test.a noinst_LIBRARIES = libv3test.a
libv3test_a_SOURCES = testsuite_hooks.cc libv3test_a_SOURCES = testsuite_hooks.cc testsuite_allocator.cc
## Build support utilities. ## Build support utilities.
## Only build this as native, as need to find startup files and libc to link. ## Only build this as native, as need to find startup files and libc to link.
......
...@@ -162,7 +162,7 @@ INCLUDES = \ ...@@ -162,7 +162,7 @@ INCLUDES = \
noinst_LIBRARIES = libv3test.a noinst_LIBRARIES = libv3test.a
libv3test_a_SOURCES = testsuite_hooks.cc libv3test_a_SOURCES = testsuite_hooks.cc testsuite_allocator.cc
@GLIBCPP_BUILD_ABI_CHECK_TRUE@noinst_PROGRAMS = @GLIBCPP_BUILD_ABI_CHECK_TRUE@abi_check @GLIBCPP_BUILD_ABI_CHECK_TRUE@noinst_PROGRAMS = @GLIBCPP_BUILD_ABI_CHECK_TRUE@abi_check
@GLIBCPP_BUILD_ABI_CHECK_FALSE@noinst_PROGRAMS = @GLIBCPP_BUILD_ABI_CHECK_FALSE@noinst_PROGRAMS =
abi_check_SOURCES = abi_check.cc abi_check_SOURCES = abi_check.cc
...@@ -177,7 +177,8 @@ CPPFLAGS = @CPPFLAGS@ ...@@ -177,7 +177,8 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
libv3test_a_LIBADD = libv3test_a_LIBADD =
libv3test_a_OBJECTS = testsuite_hooks.$(OBJEXT) libv3test_a_OBJECTS = testsuite_hooks.$(OBJEXT) \
testsuite_allocator.$(OBJEXT)
@GLIBCPP_BUILD_ABI_CHECK_FALSE@noinst_PROGRAMS = @GLIBCPP_BUILD_ABI_CHECK_FALSE@noinst_PROGRAMS =
PROGRAMS = $(noinst_PROGRAMS) PROGRAMS = $(noinst_PROGRAMS)
......
//
// Copyright (C) 2002 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <testsuite_allocator.h>
gnu_allocator_tracker::size_type gnu_allocator_tracker::allocationTotal_ = 0;
gnu_allocator_tracker::size_type gnu_allocator_tracker::deallocationTotal_ = 0;
int gnu_allocator_tracker::constructCount_ = 0;
int gnu_allocator_tracker::destructCount_ = 0;
// Testing allocator for the C++ library testsuite.
//
// Copyright (C) 2002 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// This file provides an test instrumentation allocator that can be
// used to verify allocation functionality of standard library
// containers. 2002.11.25 smw
#ifndef _GLIBCPP_TESTSUITE_ALLOCATOR_H
#define _GLIBCPP_TESTSUITE_ALLOCATOR_H
#include <cstddef>
#include <limits>
class gnu_allocator_tracker
{
public:
typedef std::size_t size_type;
static void*
allocate(size_type blocksize)
{
allocationTotal_ += blocksize;
return ::operator new(blocksize);
}
static void
construct()
{ constructCount_++; }
static void
destroy()
{ destructCount_++; }
static void
deallocate(void* p, size_type blocksize)
{
::operator delete(p);
deallocationTotal_ += blocksize;
}
static size_type
allocationTotal()
{ return allocationTotal_; }
static size_type
deallocationTotal()
{ return deallocationTotal_; }
static int
constructCount()
{ return constructCount_; }
static int
destructCount()
{ return destructCount_; }
static void
resetCounts()
{
allocationTotal_ = 0;
deallocationTotal_ = 0;
constructCount_ = 0;
destructCount_ = 0;
}
private:
static size_type allocationTotal_;
static size_type deallocationTotal_;
static int constructCount_;
static int destructCount_;
};
// A simple basic allocator that just forwards to the
// gnu_allocator_tracker to fulfill memory requests. This class is
// templated on the target object type, but gnu_allocator_tracker
// isn't.
template<class T>
class gnu_new_allocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<class U> struct rebind { typedef gnu_new_allocator<U> other; };
pointer
address(reference value) const
{ return &value; }
const_pointer
address(const_reference value) const
{ return &value; }
gnu_new_allocator() throw()
{ }
gnu_new_allocator(const gnu_new_allocator&) throw()
{ }
template<class U>
gnu_new_allocator(const gnu_new_allocator<U>&) throw()
{ }
~gnu_new_allocator() throw()
{ }
size_type
max_size() const throw()
{ return std::numeric_limits<std::size_t>::max() / sizeof(T); }
pointer
allocate(size_type num, const void* = 0)
{
return static_cast<pointer>(gnu_allocator_tracker::allocate(num *
sizeof(T)));
}
void
construct(pointer p, const T& value)
{
new (p) T(value);
gnu_allocator_tracker::construct();
}
void
destroy(pointer p)
{
p->~T();
gnu_allocator_tracker::destroy();
}
void
deallocate(pointer p, size_type num)
{ gnu_allocator_tracker::deallocate(p, num * sizeof(T)); }
};
template<class T1, class T2>
bool
operator==(const gnu_new_allocator<T1>&,
const gnu_new_allocator<T2>&) throw()
{ return true; }
template<class T1, class T2>
bool
operator!=(const gnu_new_allocator<T1>&,
const gnu_new_allocator<T2>&) throw()
{ return false; }
#endif // _GLIBCPP_TESTSUITE_ALLOCATOR_H
...@@ -78,6 +78,10 @@ __set_testsuite_memlimit(float) { } ...@@ -78,6 +78,10 @@ __set_testsuite_memlimit(float) { }
gnu_counting_struct::size_type gnu_counting_struct::count = 0; gnu_counting_struct::size_type gnu_counting_struct::count = 0;
int gnu_copy_tracker::itsCopyCount = 0; unsigned int gnu_copy_constructor::count_ = 0;
int gnu_copy_tracker::itsDtorCount = 0; unsigned int gnu_copy_constructor::throw_on_ = 0;
unsigned int gnu_assignment_operator::count_ = 0;
unsigned int gnu_assignment_operator::throw_on_ = 0;
unsigned int gnu_destructor::count_ = 0;
int gnu_copy_tracker::next_id_ = 0;
...@@ -100,58 +100,177 @@ struct gnu_counting_struct ...@@ -100,58 +100,177 @@ struct gnu_counting_struct
#define assert_count(n) VERIFY(gnu_counting_struct::count == n) #define assert_count(n) VERIFY(gnu_counting_struct::count == n)
// A (static) class for counting copy constructors and possibly throwing an
// exception on a desired count.
class gnu_copy_constructor
{
public:
static unsigned int
count()
{ return count_; }
static void
mark_call()
{
count_++;
if (count_ == throw_on_)
{
__throw_exception_again "copy constructor exception";
}
}
static void
reset()
{
count_ = 0;
throw_on_ = 0;
}
static void
throw_on(unsigned int count)
{ throw_on_ = count; }
private:
static unsigned int count_;
static unsigned int throw_on_;
};
// A (static) class for counting assignment operator calls and possibly
// throwing an exception on a desired count.
class gnu_assignment_operator
{
public:
static unsigned int
count()
{ return count_; }
static void
mark_call()
{
count_++;
if (count_ == throw_on_)
{
__throw_exception_again "assignment operator exception";
}
}
static void
reset()
{
count_ = 0;
throw_on_ = 0;
}
static void
throw_on(unsigned int count)
{ throw_on_ = count; }
private:
static unsigned int count_;
static unsigned int throw_on_;
};
// A (static) class for tracking calls to an object's destructor.
class gnu_destructor
{
public:
static unsigned int
count()
{ return count_; }
static void
mark_call()
{ count_++; }
static void
reset()
{ count_ = 0; }
private:
static unsigned int count_;
};
// An class of objects that can be used for validating various behaviours and
// guarantees of containers and algorithms defined in the standard library.
class gnu_copy_tracker class gnu_copy_tracker
{ {
public: public:
// Cannot be explicit. Conversion ctor used by list_modifiers.cc's // Creates a copy-tracking object with the given ID number.
// test03(), "range fill at beginning". // If "throw_on_copy" is set, an exception will be thrown if
gnu_copy_tracker (int anId, bool throwOnDemand = false) // an attempt is made to copy this object.
: itsId(anId), willThrow(throwOnDemand) gnu_copy_tracker(int id = next_id_--, bool throw_on_copy = false)
{} : id_(id)
, throw_on_copy_(throw_on_copy)
gnu_copy_tracker (const gnu_copy_tracker& rhs)
: itsId(rhs.id()), willThrow(rhs.willThrow)
{ {
++itsCopyCount;
if (willThrow)
__throw_exception_again "copy tracker exception";
} }
gnu_copy_tracker& operator=(const gnu_copy_tracker& rhs) // Copy-constructs the object, marking a call to the copy
// constructor and forcing an exception if indicated.
gnu_copy_tracker(const gnu_copy_tracker& rhs)
: id_(rhs.id()), throw_on_copy_(rhs.throw_on_copy_)
{ {
itsId = rhs.id(); int kkk = throw_on_copy_;
// willThrow must obviously already be false to get this far if (throw_on_copy_)
{
gnu_copy_constructor::throw_on(gnu_copy_constructor::count() + 1);
}
gnu_copy_constructor::mark_call();
} }
~gnu_copy_tracker() { ++itsDtorCount; } // Assigns the value of another object to this one, tracking the
// number of times this member function has been called and if the
// other object is supposed to throw an exception when it is
// copied, well, make it so.
gnu_copy_tracker&
operator=(const gnu_copy_tracker& rhs)
{
id_ = rhs.id();
if (rhs.throw_on_copy_)
{
gnu_assignment_operator::throw_on(gnu_assignment_operator::count()
+ 1);
}
gnu_assignment_operator::mark_call();
}
~gnu_copy_tracker()
{ gnu_destructor::mark_call(); }
int int
id() const id() const
{ return itsId; } { return id_; }
private: private:
int itsId; int id_;
const bool willThrow; const bool throw_on_copy_;
public: public:
static void static void
reset() reset()
{ itsCopyCount = 0; itsDtorCount = 0; } {
gnu_copy_constructor::reset();
gnu_assignment_operator::reset();
gnu_destructor::reset();
}
// for backwards-compatibility
static int static int
copyCount() copyCount()
{ return itsCopyCount; } { return gnu_copy_constructor::count(); }
// for backwards-compatibility
static int static int
dtorCount() dtorCount()
{ return itsDtorCount; } { return gnu_destructor::count(); }
private: private:
static int itsCopyCount; static int next_id_;
static int itsDtorCount;
}; };
inline bool
operator==(const gnu_copy_tracker& lhs, const gnu_copy_tracker& rhs)
{ return lhs.id() == rhs.id(); }
struct gnu_char struct gnu_char
{ {
unsigned long c; unsigned long c;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment