Commit 53179144 by Benjamin Kosnik Committed by Benjamin Kosnik

PR libstdc++/21772 part 2

2009-12-16  Benjamin Kosnik  <bkoz@redhat.com>

	PR libstdc++/21772 part 2
	* doc/xml/manual/test.xml: Add documentation about testing details.
	* testsuite/util/exception/safety.h: New. Functor objects for
	testing C++0x container classes.
	* testsuite/util/testsuite_container_traits.h: Add traits.

	* testsuite/23_containers/list/requirements/exception/
	basic.cc: New.
	generation_prohibited.cc: New.
	propagation_consistent.cc: New.

From-SVN: r155306
parent ccfd7296
2009-12-16 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/21772 part 2
* doc/xml/manual/test.xml: Add documentation about testing details.
* testsuite/util/exception/safety.h: New. Functor objects for
testing C++0x container classes.
* testsuite/util/testsuite_container_traits.h: Add traits.
* testsuite/23_containers/list/requirements/exception/
basic.cc: New.
generation_prohibited.cc: New.
propagation_consistent.cc: New.
2009-12-15 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/21772 part 1
......
......@@ -65,6 +65,9 @@ regressions, ABI, and performance.
25_algorithms
26_numerics
27_io
28_regex
29_atomics
30_threads
</programlisting>
<para>
......@@ -77,7 +80,6 @@ backward Tests for backwards compatibility and deprecated features.
demangle Tests for __cxa_demangle, the IA 64 C++ ABI demangler
ext Tests for extensions.
performance Tests for performance analysis, and performance regressions.
thread Tests for threads.
</programlisting>
<para>
......@@ -801,4 +803,230 @@ only default variables.
</sect3>
</sect2>
<sect2 id="test.special">
<title>Special Topics</title>
<sect3 id="test.exception.safety">
<title>
Qualifying Exception Safety Guarantees
<indexterm>
<primary>Test</primary>
<secondary>Exception Safety</secondary>
</indexterm>
</title>
<sect4 id="test.exception.safety.overview">
<title>Overview</title>
<para>
Testing is composed of running a particular test sequence,
and looking at what happens to the surrounding code when
exceptions are thrown. Each test is composed of measuring
initial state, executing a particular sequence of code under
some instrumented conditions, measuring a final state, and
then examining the differences between the two states.
</para>
<para>
Test sequences are composed of constructed code sequences
that exercise a particular function or member function, and
either confirm no exceptions were generated, or confirm the
consistency/coherency of the test subject in the event of a
thrown exception.
</para>
<para>
Random code paths can be constructed using the the basic test
sequences and instrumentation as above, only combined in a
random or pseudo-random way.
</para>
<para> To compute the code paths that throw, test instruments
are used that throw on allocation events
(<classname>__gnu_cxx::throw_allocator_random</classname>
and <classname>__gnu_cxx::throw_allocator_limit</classname>)
and copy, assignment, comparison, increment, swap, and
various operators
(<classname>__gnu_cxx::throw_type_random</classname>
and <classname>__gnu_cxx::throw_type_limit</classname>). Looping
through a given test sequence and conditionally throwing in
all instrumented places. Then, when the test sequence
completes without an exception being thrown, assume all
potential error paths have been exercised in a sequential
manner.
</para>
</sect4>
<sect4 id="test.exception.safety.status">
<title>
Existing tests
</title>
<itemizedlist>
<listitem>
<para>
Ad Hoc
</para>
<para>
For example,
<filename>testsuite/23_containers/list/modifiers/3.cc</filename>.
</para>
</listitem>
<listitem>
<para>
Policy Based Data Structures
</para>
<para>
For example, take the test
functor <classname>rand_reg_test</classname> in
in <filename>testsuite/ext/pb_ds/regression/tree_no_data_map_rand.cc</filename>. This uses <classname>container_rand_regression_test</classname> in
<filename>testsuite/util/regression/rand/assoc/container_rand_regression_test.h</filename>.
</para>
<para>
Which has several tests for container member functions,
Includes control and test container objects. Configuration includes
random seed, iterations, number of distinct values, and the
probability that and exception will be thrown. Assumes instantiating
container uses an extension
allocator, <classname>__gnu_cxx::throw_allocator_random</classname>,
as the allocator type.
</para>
</listitem>
<listitem>
<para>
C++0x Container Requirements.
</para>
<para>
Coverage is currently limited to testing container
requirements for exception safety,
although <classname>__gnu_cxx::throw_type</classname> meets
the additional type requirements for testing numeric data
structures and instantiating algorithms.
</para>
<para>
Of particular interest is extending testing to algorithms and
then to parallel algorithms. Also io, and locales.
</para>
</listitem>
</itemizedlist>
</sect4>
<sect4 id="test.exception.safety.containers">
<title>
C++0x Requirements Test Sequence Descriptions
</title>
<itemizedlist>
<listitem>
<para>
Basic
</para>
<para>
Basic consistency on exception propagation tests. For
each container, an object of that container is constructed,
a specific member function is exercised in
a <literal>try</literal> block, and then any thrown
exceptions lead to error checking in the appropriate
<literal>catch</literal> block. The container's use of
resources is compared to the container's use prior to the
test block. Resource monitoring is limited to allocations
made through the container's <type>allocator_type</type>,
which should be sufficient for container data
structures. Included in these tests are member functions
are <type>iterator</type> and <type>const_iterator</type>
operations, <function>pop_front</function>, <function>pop_back</function>, <function>push_front</function>, <function>push_back</function>, <function>insert</function>, <function>erase</function>, <function>swap</function>, <function>clear</function>,
and <function>rehash</function>. The container in question is
instantiated with two instrumented template arguments,
with <classname>__gnu_cxx::throw_allocator_limit</classname>
as the allocator type, and
with <classname>__gnu_cxx::throw_type_limit</classname> as
the value type. This allows the test to loop through
conditional throw points.
</para>
<para>
The general form is demonstrated in
<filename>testsuite/23_containers/list/requirements/exception/basic.cc
</filename>. The instantiating test object is <classname>__gnu_test::basic_safety</classname> and is detailed in <filename>testsuite/util/exception/safety.h</filename>.
</para>
</listitem>
<listitem>
<para>
Generation Prohibited
</para>
<para>
Exception generation tests. For each container, an object of
that container is constructed and all member functions
required to not throw exceptions are exercised. Included in
these tests are member functions
are <type>iterator</type> and <type>const_iterator</type> operations, <function>erase</function>, <function>pop_front</function>, <function>pop_back</function>, <function>swap</function>,
and <function>clear</function>. The container in question is
instantiated with two instrumented template arguments,
with <classname>__gnu_cxx::throw_allocator_random</classname>
as the allocator type, and
with <classname>__gnu_cxx::throw_type_random</classname> as
the value type. This test does not loop, an instead is sudden
death: first error fails.
</para>
<para>
The general form is demonstrated in
<filename>testsuite/23_containers/list/requirements/exception/generation_prohibited.cc
</filename>. The instantiating test object is <classname>__gnu_test::generation_prohibited</classname> and is detailed in <filename>testsuite/util/exception/safety.h</filename>.
</para>
</listitem>
<listitem>
<para>
Propagation Consistent
</para>
<para>
Container rollback on exception propagation tests. For
each container, an object of that container is constructed,
a specific member function that requires rollback to a previous
known good state is exercised in
a <literal>try</literal> block, and then any thrown
exceptions lead to error checking in the appropriate
<literal>catch</literal> block. The container is compared to
the container's last known good state using such parameters
as size, contents, and iterator references. Included in these
tests are member functions
are <function>push_front</function>, <function>push_back</function>, <function>insert</function>,
and <function>rehash</function>. The container in question is
instantiated with two instrumented template arguments,
with <classname>__gnu_cxx::throw_allocator_limit</classname>
as the allocator type, and
with <classname>__gnu_cxx::throw_type_limit</classname> as
the value type. This allows the test to loop through
conditional throw points.
</para>
<para>
The general form demonstrated in
<filename>testsuite/23_containers/list/requirements/exception/propagation_coherent.cc
</filename>. The instantiating test object is <classname>__gnu_test::propagation_coherent</classname> and is detailed in <filename>testsuite/util/exception/safety.h</filename>.
</para>
</listitem>
</itemizedlist>
</sect4>
</sect3>
</sect2>
</sect1>
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
// 2009-11-30 Benjamin Kosnik <benjamin@redhat.com>
// Copyright (C) 2009 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <list>
#include <exception/safety.h>
void
value()
{
typedef __gnu_cxx::throw_value_limit value_type;
typedef __gnu_cxx::throw_allocator_limit<value_type> allocator_type;
typedef std::list<value_type, allocator_type> test_type;
__gnu_test::basic_safety<test_type> test;
}
// Container requirement testing, exceptional behavior
int main()
{
value();
return 0;
}
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
// 2009-09-09 Benjamin Kosnik <benjamin@redhat.com>
// Copyright (C) 2009 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <list>
#include <exception/safety.h>
// Container requirement testing, exceptional behavior
int main()
{
typedef __gnu_cxx::throw_value_random value_type;
typedef __gnu_cxx::throw_allocator_random<value_type> allocator_type;
typedef std::list<value_type, allocator_type> test_type;
__gnu_test::generation_prohibited<test_type> test;
return 0;
}
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
// 2009-09-09 Benjamin Kosnik <benjamin@redhat.com>
// Copyright (C) 2009 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 3, 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 COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <list>
#include <exception/safety.h>
// Container requirement testing, exceptional behavior
int main()
{
typedef __gnu_cxx::throw_value_limit value_type;
typedef __gnu_cxx::throw_allocator_limit<value_type> allocator_type;
typedef std::list<value_type, allocator_type> test_type;
__gnu_test::propagation_consistent<test_type> test;
return 0;
}
......@@ -26,6 +26,7 @@
namespace __gnu_test
{
// Container traits.
// Base class with default false values for all traits.
struct traits_base
{
// Type, nested type, and typedef related traits.
......@@ -37,6 +38,11 @@ namespace __gnu_test
typedef std::false_type is_associative;
typedef std::false_type is_unordered;
typedef std::false_type is_mapped;
typedef std::false_type has_erase;
typedef std::false_type has_insert;
typedef std::false_type has_push_pop;
typedef std::false_type has_size_type_constructor;
};
// Primary template does nothing. Specialize on each type under
......@@ -46,40 +52,55 @@ namespace __gnu_test
// Specialize for each container.
template<typename _Tp, size_t _Np>
struct traits<std::array<_Tp, _Np> > : public traits_base
struct traits<std::array<_Tp, _Np>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
};
template<typename _Tp>
struct traits<std::deque<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::deque<_Tp1, _Tp2>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_push_pop;
typedef std::true_type has_size_type_constructor;
};
template<typename _Tp>
struct traits<std::forward_list<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::forward_list<_Tp1, _Tp2>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_push_pop;
typedef std::true_type has_size_type_constructor;
};
template<typename _Tp>
struct traits<std::list<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::list<_Tp1, _Tp2>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_push_pop;
typedef std::true_type has_size_type_constructor;
};
template<typename _Kp, typename _Tp>
struct traits<std::map<_Kp, _Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
struct traits<std::map<_Tp1, _Tp2, _Tp3, _Tp4>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
......@@ -87,10 +108,12 @@ namespace __gnu_test
typedef std::true_type is_pointer_aware;
typedef std::true_type is_associative;
typedef std::true_type is_mapped;
typedef std::true_type has_insert;
};
template<typename _Kp, typename _Tp>
struct traits<std::multimap<_Kp, _Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
struct traits<std::multimap<_Tp1, _Tp2, _Tp3, _Tp4>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
......@@ -100,107 +123,141 @@ namespace __gnu_test
typedef std::true_type is_mapped;
};
template<typename _Tp>
struct traits<std::multiset<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3>
struct traits<std::multiset<_Tp1, _Tp2, _Tp3>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type is_associative;
typedef std::true_type has_insert;
};
template<typename _Tp>
struct traits<std::priority_queue<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::priority_queue<_Tp1, _Tp2>> : public traits_base
{
typedef std::true_type is_adaptor;
};
template<typename _Tp>
struct traits<std::queue<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::queue<_Tp1, _Tp2>> : public traits_base
{
typedef std::true_type is_adaptor;
};
template<typename _Tp>
struct traits<std::set<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3>
struct traits<std::set<_Tp1, _Tp2, _Tp3>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type is_associative;
typedef std::true_type has_insert;
};
template<typename _Tp>
struct traits<std::stack<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::stack<_Tp1, _Tp2> > : public traits_base
{
typedef std::true_type is_adaptor;
};
template<typename _Kp, typename _Tp>
struct traits<std::unordered_map<_Kp, _Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3,
typename _Tp4, typename _Tp5>
struct traits<std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>>
: public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type is_unordered;
typedef std::true_type is_mapped;
typedef std::true_type has_size_type_constructor;
typedef std::true_type has_insert;
};
template<typename _Kp, typename _Tp>
struct traits<std::unordered_multimap<_Kp, _Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3,
typename _Tp4, typename _Tp5>
struct traits<std::unordered_multimap<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>>
: public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type is_unordered;
typedef std::true_type is_mapped;
typedef std::true_type has_size_type_constructor;
};
template<typename _Tp>
struct traits<std::unordered_multiset<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
struct traits<std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>>
: public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type is_unordered;
typedef std::true_type has_insert;
};
template<typename _Tp>
struct traits<std::unordered_set<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
struct traits<std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>>
: public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type is_unordered;
typedef std::true_type has_size_type_constructor;
typedef std::true_type has_insert;
};
template<typename _Tp>
struct traits<std::vector<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2>
struct traits<std::vector<_Tp1, _Tp2>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_size_type_constructor;
};
template<typename _Tp>
struct traits<std::basic_string<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3>
struct traits<std::basic_string<_Tp1, _Tp2, _Tp3>> : public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type has_erase;
typedef std::true_type has_insert;
};
template<typename _Tp>
struct traits<__gnu_cxx::__versa_string<_Tp> > : public traits_base
template<typename _Tp1, typename _Tp2, typename _Tp3,
template <typename, typename, typename> class _Tp4>
struct traits<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
: public traits_base
{
typedef std::true_type is_container;
typedef std::true_type is_reversible;
typedef std::true_type is_allocator_aware;
typedef std::true_type is_pointer_aware;
typedef std::true_type has_erase;
// XXX no vstring<rc>::insert
// typedef std::true_type has_insert;
};
} // namespace __gnu_test
......
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