1 // (C) Copyright Gennadiy Rozental 2001-2008.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 // See http://www.boost.org/libs/test for the library home page.
10 // Version : $Revision$
12 // Description : defines test_unit, test_case, test_case_results, test_suite and test_tree_visitor
13 // ***************************************************************************
15 #ifndef BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
16 #define BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
19 #include <boost/test/detail/config.hpp>
20 #include <boost/test/detail/global_typedef.hpp>
21 #include <boost/test/utils/class_properties.hpp>
22 #include <boost/test/utils/callback.hpp>
23 #include <boost/test/detail/fwd_decl.hpp>
24 #include <boost/test/detail/workaround.hpp>
25 #include <boost/test/test_observer.hpp>
28 #include <boost/shared_ptr.hpp>
29 #include <boost/mpl/for_each.hpp>
30 #include <boost/mpl/identity.hpp>
31 #include <boost/type.hpp>
32 #include <boost/type_traits/is_const.hpp>
35 #include <typeinfo> // for typeid
36 #include <string> // for std::string
37 #include <list> // for std::list
38 #include <vector> // for std::vector
40 #include <boost/test/detail/suppress_warnings.hpp>
42 //____________________________________________________________________________//
48 // ************************************************************************** //
49 // ************** test_unit ************** //
50 // ************************************************************************** //
52 class BOOST_TEST_DECL test_unit
{
54 enum { type
= tut_any
};
57 test_unit( const_string tu_name
, test_unit_type t
);
59 // dependencies management
60 void depends_on( test_unit
* tu
);
61 bool check_dependencies() const;
63 // Public r/o properties
64 typedef BOOST_READONLY_PROPERTY(test_unit_id
,(framework_impl
)) id_t
;
65 typedef BOOST_READONLY_PROPERTY(test_unit_id
,(test_suite
)) parent_id_t
;
66 readonly_property
<test_unit_type
> p_type
; // type for this test unit
67 readonly_property
<const_string
> p_type_name
; // "case"/"suite"
68 id_t p_id
; // unique id for this test unit
69 parent_id_t p_parent_id
; // parent test suite id
71 // Public r/w properties
72 readwrite_property
<std::string
> p_name
; // name for this test unit
73 readwrite_property
<unsigned> p_timeout
; // timeout for the test unit execution
74 readwrite_property
<counter_t
> p_expected_failures
; // number of expected failures in this test unit
75 mutable readwrite_property
<bool> p_enabled
; // enabled status for this unit
77 void increase_exp_fail( unsigned num
);
84 std::list
<test_unit_id
> m_dependencies
;
87 // ************************************************************************** //
88 // ************** test_case_generator ************** //
89 // ************************************************************************** //
91 class BOOST_TEST_DECL test_unit_generator
{
93 virtual test_unit
* next() const = 0;
96 BOOST_TEST_PROTECTED_VIRTUAL
~test_unit_generator() {}
99 // ************************************************************************** //
100 // ************** test_case ************** //
101 // ************************************************************************** //
103 class BOOST_TEST_DECL test_case
: public test_unit
{
105 enum { type
= tut_case
};
108 test_case( const_string tc_name
, callback0
<> const& test_func
);
111 callback0
<> const& test_func() const { return m_test_func
; }
114 friend class framework_impl
;
117 // BOOST_MSVC <= 1200 have problems with callback as property
119 callback0
<> m_test_func
;
122 // ************************************************************************** //
123 // ************** test_suite ************** //
124 // ************************************************************************** //
126 class BOOST_TEST_DECL test_suite
: public test_unit
{
128 enum { type
= tut_suite
};
131 explicit test_suite( const_string ts_name
);
133 // test unit list management
134 void add( test_unit
* tu
, counter_t expected_failures
= 0, unsigned timeout
= 0 );
135 void add( test_unit_generator
const& gen
, unsigned timeout
= 0 );
136 void remove( test_unit_id id
);
139 test_unit_id
get( const_string tu_name
) const;
140 std::size_t size() const { return m_members
.size(); }
143 friend BOOST_TEST_DECL
144 void traverse_test_tree( test_suite
const&, test_tree_visitor
& );
145 friend class framework_impl
;
146 virtual ~test_suite() {}
149 std::vector
<test_unit_id
> m_members
;
152 // ************************************************************************** //
153 // ************** master_test_suite ************** //
154 // ************************************************************************** //
156 class BOOST_TEST_DECL master_test_suite_t
: public test_suite
{
158 master_test_suite_t() : test_suite( "Master Test Suite" )
169 // ************************************************************************** //
170 // ************** test_tree_visitor ************** //
171 // ************************************************************************** //
173 class BOOST_TEST_DECL test_tree_visitor
{
175 // test tree visitor interface
176 virtual void visit( test_case
const& ) {}
177 virtual bool test_suite_start( test_suite
const& ) { return true; }
178 virtual void test_suite_finish( test_suite
const& ) {}
181 BOOST_TEST_PROTECTED_VIRTUAL
~test_tree_visitor() {}
184 // ************************************************************************** //
185 // ************** traverse_test_tree ************** //
186 // ************************************************************************** //
188 BOOST_TEST_DECL
void traverse_test_tree( test_case
const&, test_tree_visitor
& );
189 BOOST_TEST_DECL
void traverse_test_tree( test_suite
const&, test_tree_visitor
& );
190 BOOST_TEST_DECL
void traverse_test_tree( test_unit_id
, test_tree_visitor
& );
192 //____________________________________________________________________________//
195 traverse_test_tree( test_unit
const& tu
, test_tree_visitor
& V
)
197 if( tu
.p_type
== tut_case
)
198 traverse_test_tree( static_cast<test_case
const&>( tu
), V
);
200 traverse_test_tree( static_cast<test_suite
const&>( tu
), V
);
203 //____________________________________________________________________________//
205 // ************************************************************************** //
206 // ************** test_case_counter ************** //
207 // ************************************************************************** //
209 class test_case_counter
: public test_tree_visitor
{
212 test_case_counter() : p_count( 0 ) {}
214 BOOST_READONLY_PROPERTY( counter_t
, (test_case_counter
)) p_count
;
216 // test tree visitor interface
217 virtual void visit( test_case
const& );
218 virtual bool test_suite_start( test_suite
const& ts
) { return ts
.p_enabled
; }
221 // ************************************************************************** //
222 // ************** test_being_aborted ************** //
223 // ************************************************************************** //
225 struct BOOST_TEST_DECL test_being_aborted
{};
227 // ************************************************************************** //
228 // ************** object generators ************** //
229 // ************************************************************************** //
231 namespace ut_detail
{
233 BOOST_TEST_DECL
std::string
normalize_test_case_name( const_string tu_name
);
235 template<typename InstanceType
,typename UserTestCase
>
236 struct user_tc_method_invoker
{
237 typedef void (UserTestCase::*TestMethod
)();
239 user_tc_method_invoker( shared_ptr
<InstanceType
> inst
, TestMethod test_method
)
240 : m_inst( inst
), m_test_method( test_method
) {}
242 void operator()() { ((*m_inst
).*m_test_method
)(); }
244 shared_ptr
<InstanceType
> m_inst
;
245 TestMethod m_test_method
;
248 } // namespace ut_detail
250 //____________________________________________________________________________//
253 make_test_case( callback0
<> const& test_func
, const_string tc_name
)
255 return new test_case( ut_detail::normalize_test_case_name( tc_name
), test_func
);
258 //____________________________________________________________________________//
260 template<typename UserTestCase
, typename InstanceType
>
262 make_test_case( void (UserTestCase::* test_method
)(),
263 const_string tc_name
,
264 boost::shared_ptr
<InstanceType
> user_test_case
)
266 return new test_case( ut_detail::normalize_test_case_name( tc_name
),
267 ut_detail::user_tc_method_invoker
<InstanceType
,UserTestCase
>( user_test_case
, test_method
) );
270 //____________________________________________________________________________//
272 // ************************************************************************** //
273 // ************** auto_test_unit_registrar ************** //
274 // ************************************************************************** //
276 namespace ut_detail
{
278 struct BOOST_TEST_DECL auto_test_unit_registrar
281 auto_test_unit_registrar( test_case
* tc
, counter_t exp_fail
);
282 explicit auto_test_unit_registrar( const_string ts_name
);
283 explicit auto_test_unit_registrar( test_unit_generator
const& tc_gen
);
284 explicit auto_test_unit_registrar( int );
287 static std::list
<test_suite
*>& curr_ts_store();
290 //____________________________________________________________________________//
293 struct auto_tc_exp_fail
{
294 auto_tc_exp_fail() : m_value( 0 ) {}
296 explicit auto_tc_exp_fail( unsigned v
)
302 static auto_tc_exp_fail
*& instance()
304 static auto_tc_exp_fail inst
;
305 static auto_tc_exp_fail
* inst_ptr
= &inst
;
310 unsigned value() const { return m_value
; }
317 //____________________________________________________________________________//
319 } // namespace ut_detail
321 // ************************************************************************** //
322 // ************** global_fixture ************** //
323 // ************************************************************************** //
325 class BOOST_TEST_DECL global_fixture
: public test_observer
{
331 //____________________________________________________________________________//
333 namespace ut_detail
{
336 struct global_fixture_impl
: public global_fixture
{
338 global_fixture_impl(): m_fixure( 0 ) {}
340 // test observer interface
341 virtual void test_start( counter_t
) { m_fixure
= new F
; }
342 virtual void test_finish() { delete m_fixure
; m_fixure
= 0; }
343 virtual void test_aborted() { delete m_fixure
; m_fixure
= 0; }
350 // ************************************************************************** //
351 // ************** test_case_template_invoker ************** //
352 // ************************************************************************** //
354 template<typename TestCaseTemplate
,typename TestType
>
355 class test_case_template_invoker
{
357 void operator()() { TestCaseTemplate::run( (boost::type
<TestType
>*)0 ); }
360 // ************************************************************************** //
361 // ************** generate_test_case_4_type ************** //
362 // ************************************************************************** //
364 template<typename Generator
,typename TestCaseTemplate
>
365 struct generate_test_case_4_type
{
366 explicit generate_test_case_4_type( const_string tc_name
, Generator
& G
)
367 : m_test_case_name( tc_name
)
371 template<typename TestType
>
372 void operator()( mpl::identity
<TestType
> )
374 std::string full_name
;
375 assign_op( full_name
, m_test_case_name
, 0 );
377 full_name
+= typeid(TestType
).name();
378 if( boost::is_const
<TestType
>::value
)
379 full_name
+= " const";
382 m_holder
.m_test_cases
.push_back(
383 new test_case( full_name
, test_case_template_invoker
<TestCaseTemplate
,TestType
>() ) );
388 const_string m_test_case_name
;
392 // ************************************************************************** //
393 // ************** test_case_template ************** //
394 // ************************************************************************** //
396 template<typename TestCaseTemplate
,typename TestTypesList
>
397 class template_test_case_gen
: public test_unit_generator
{
400 template_test_case_gen( const_string tc_name
)
402 typedef generate_test_case_4_type
<template_test_case_gen
<TestCaseTemplate
,TestTypesList
>,
405 mpl::for_each
<TestTypesList
,mpl::make_identity
<mpl::_
> >( single_test_gen( tc_name
, *this ) );
408 virtual test_unit
* next() const
410 if( m_test_cases
.empty() )
413 test_unit
* res
= m_test_cases
.front();
414 m_test_cases
.pop_front();
420 mutable std::list
<test_unit
*> m_test_cases
;
423 //____________________________________________________________________________//
425 } // namespace ut_detail
431 #include <boost/test/detail/enable_warnings.hpp>
433 #endif // BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER