1 // (C) Copyright Gennadiy Rozental 2001.
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.
9 /// Provides core implementation for Unit Test Framework.
10 /// Extensions can be provided in separate files
11 // ***************************************************************************
13 #ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
14 #define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
17 #include <boost/detail/workaround.hpp>
19 #include <boost/test/framework.hpp>
20 #include <boost/test/results_collector.hpp>
22 #include <boost/test/tree/test_unit.hpp>
23 #include <boost/test/tree/visitor.hpp>
24 #include <boost/test/tree/traverse.hpp>
25 #include <boost/test/tree/auto_registration.hpp>
26 #include <boost/test/tree/global_fixture.hpp>
28 #include <boost/test/utils/foreach.hpp>
29 #include <boost/test/utils/basic_cstring/io.hpp>
31 #include <boost/test/unit_test_parameters.hpp>
38 #include <boost/test/detail/suppress_warnings.hpp>
40 //____________________________________________________________________________//
45 // ************************************************************************** //
46 // ************** test_unit ************** //
47 // ************************************************************************** //
49 test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
51 , p_type_name( t == TUT_CASE ? "case" : "suite" )
52 , p_file_name( file_name )
53 , p_line_num( line_num )
54 , p_id( INV_TEST_UNIT_ID )
55 , p_parent_id( INV_TEST_UNIT_ID )
56 , p_name( std::string( name.begin(), name.size() ) )
58 , p_expected_failures( 0 )
59 , p_default_status( RS_INHERIT )
60 , p_run_status( RS_INVALID )
65 //____________________________________________________________________________//
67 test_unit::test_unit( const_string module_name )
69 , p_type_name( "module" )
71 , p_id( INV_TEST_UNIT_ID )
72 , p_parent_id( INV_TEST_UNIT_ID )
73 , p_name( std::string( module_name.begin(), module_name.size() ) )
75 , p_expected_failures( 0 )
76 , p_default_status( RS_INHERIT )
77 , p_run_status( RS_INVALID )
82 //____________________________________________________________________________//
84 test_unit::~test_unit()
86 framework::deregister_test_unit( this );
89 //____________________________________________________________________________//
92 test_unit::depends_on( test_unit* tu )
94 BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id,
95 "Can't add dependency to the master test suite" );
97 p_dependencies.value.push_back( tu->p_id );
100 //____________________________________________________________________________//
103 test_unit::add_precondition( precondition_t const& pc )
105 p_preconditions.value.push_back( pc );
108 //____________________________________________________________________________//
110 test_tools::assertion_result
111 test_unit::check_preconditions() const
113 BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
114 test_unit const& dep = framework::get( dep_id, TUT_ANY );
116 if( !dep.is_enabled() ) {
117 test_tools::assertion_result res(false);
118 res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
122 test_results const& test_rslt = unit_test::results_collector.results( dep_id );
123 if( !test_rslt.passed() ) {
124 test_tools::assertion_result res(false);
125 res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << (test_rslt.skipped() ? "\" was skipped":"\" has failed");
129 if( test_rslt.p_test_cases_skipped > 0 ) {
130 test_tools::assertion_result res(false);
131 res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
136 BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
137 test_tools::assertion_result res = precondition( p_id );
139 test_tools::assertion_result res_out(false);
140 res_out.message() << "precondition failed";
141 if( !res.has_empty_message() )
142 res_out.message() << ": " << res.message();
150 //____________________________________________________________________________//
153 test_unit::increase_exp_fail( counter_t num )
155 p_expected_failures.value += num;
157 if( p_parent_id != INV_TEST_UNIT_ID )
158 framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
161 //____________________________________________________________________________//
164 test_unit::full_name() const
166 if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
169 std::string res = framework::get<test_suite>( p_parent_id ).full_name();
172 res.append( p_name );
177 //____________________________________________________________________________//
180 test_unit::add_label( const_string l )
182 p_labels.value.push_back( std::string() + l );
185 //____________________________________________________________________________//
188 test_unit::has_label( const_string l ) const
190 return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
193 //____________________________________________________________________________//
195 // ************************************************************************** //
196 // ************** test_case ************** //
197 // ************************************************************************** //
199 test_case::test_case( const_string name, boost::function<void ()> const& test_func )
200 : test_unit( name, "", 0, static_cast<test_unit_type>(type) )
201 , p_test_func( test_func )
203 framework::register_test_unit( this );
206 //____________________________________________________________________________//
208 test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
209 : test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
210 , p_test_func( test_func )
212 framework::register_test_unit( this );
215 //____________________________________________________________________________//
217 // ************************************************************************** //
218 // ************** test_suite ************** //
219 // ************************************************************************** //
221 //____________________________________________________________________________//
223 test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
224 : test_unit( ut_detail::normalize_test_case_name( name ), file_name, line_num, static_cast<test_unit_type>(type) )
226 framework::register_test_unit( this );
229 //____________________________________________________________________________//
231 test_suite::test_suite( const_string module_name )
232 : test_unit( module_name )
234 framework::register_test_unit( this );
237 //____________________________________________________________________________//
240 test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
242 tu->p_timeout.value = timeout;
244 m_children.push_back( tu->p_id );
245 tu->p_parent_id.value = p_id;
247 if( tu->p_expected_failures != 0 )
248 increase_exp_fail( tu->p_expected_failures );
250 if( expected_failures )
251 tu->increase_exp_fail( expected_failures );
254 //____________________________________________________________________________//
257 test_suite::add( test_unit_generator const& gen, unsigned timeout )
260 while((tu = gen.next()) != 0)
261 add( tu, 0, timeout );
264 //____________________________________________________________________________//
267 test_suite::add( test_unit_generator const& gen, decorator::collector_t& decorators )
270 while((tu = gen.next()) != 0) {
271 decorators.store_in( *tu );
277 //____________________________________________________________________________//
280 test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
282 std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
283 m_generators.push_back(tmp_p);
287 //____________________________________________________________________________//
290 test_suite::generate( )
292 typedef std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > element_t;
294 for(std::vector<element_t>::iterator it(m_generators.begin()), ite(m_generators.end());
299 while((tu = it->first->next()) != 0) {
300 tu->p_decorators.value.insert( tu->p_decorators.value.end(), it->second.begin(), it->second.end() );
301 //it->second.store_in( *tu );
306 m_generators.clear();
310 while((tu = gen.next()) != 0) {
311 decorators.store_in( *tu );
317 //____________________________________________________________________________//
320 test_suite::check_for_duplicate_test_cases() {
321 // check for clashing names #12597
322 std::set<std::string> names;
323 for( test_unit_id_list::const_iterator it(m_children.begin()), ite(m_children.end());
326 std::string name = framework::get(*it, TUT_ANY).p_name;
327 std::pair<std::set<std::string>::iterator, bool> ret = names.insert(name);
328 BOOST_TEST_SETUP_ASSERT(ret.second,
329 "test unit with name '"
331 + std::string("' registered multiple times in the test suite '")
339 //____________________________________________________________________________//
342 test_suite::remove( test_unit_id id )
344 test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
346 if( it != m_children.end() )
347 m_children.erase( it );
350 //____________________________________________________________________________//
353 test_suite::get( const_string tu_name ) const
355 BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
356 if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
360 return INV_TEST_UNIT_ID;
363 //____________________________________________________________________________//
365 // ************************************************************************** //
366 // ************** master_test_suite ************** //
367 // ************************************************************************** //
369 master_test_suite_t::master_test_suite_t()
370 : test_suite( "Master Test Suite" )
374 p_default_status.value = RS_ENABLED;
377 // ************************************************************************** //
378 // ************** traverse_test_tree ************** //
379 // ************************************************************************** //
382 traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
384 if( tc.is_enabled() || ignore_status )
388 //____________________________________________________________________________//
391 traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
393 // skip disabled test suite unless we asked to ignore this condition
394 if( !ignore_status && !suite.is_enabled() )
397 // Invoke test_suite_start callback
398 if( !V.test_suite_start( suite ) )
401 // Recurse into children
402 std::size_t total_children = suite.m_children.size();
403 for( std::size_t i=0; i < total_children; ) {
404 // this statement can remove the test unit from this list
405 traverse_test_tree( suite.m_children[i], V, ignore_status );
406 if( total_children > suite.m_children.size() )
407 total_children = suite.m_children.size();
412 // Invoke test_suite_finish callback
413 V.test_suite_finish( suite );
416 //____________________________________________________________________________//
419 traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
421 if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
422 traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
424 traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
427 //____________________________________________________________________________//
429 // ************************************************************************** //
430 // ************** object generators ************** //
431 // ************************************************************************** //
433 namespace ut_detail {
436 normalize_test_case_name( const_string name )
438 std::string norm_name( name.begin(), name.size() );
441 norm_name = norm_name.substr( 1 );
444 std::size_t first_not_space = norm_name.find_first_not_of(' ');
445 if( first_not_space ) {
446 norm_name.erase(0, first_not_space);
449 std::size_t last_not_space = norm_name.find_last_not_of(' ');
450 if( last_not_space !=std::string::npos ) {
451 norm_name.erase(last_not_space + 1);
454 // sanitize all chars that might be used in runtime filters
455 static const char to_replace[] = { ':', '*', '@', '+', '!', '/', ',' };
456 for(std::size_t index = 0;
457 index < sizeof(to_replace)/sizeof(to_replace[0]);
459 std::replace(norm_name.begin(), norm_name.end(), to_replace[index], '_');
465 //____________________________________________________________________________//
467 // ************************************************************************** //
468 // ************** auto_test_unit_registrar ************** //
469 // ************************************************************************** //
471 auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail )
473 framework::current_auto_test_suite().add( tc, exp_fail );
475 decorators.store_in( *tc );
479 //____________________________________________________________________________//
481 auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector_t& decorators )
483 test_unit_id id = framework::current_auto_test_suite().get( ts_name );
487 if( id != INV_TEST_UNIT_ID ) {
488 ts = &framework::get<test_suite>( id );
489 BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
492 ts = new test_suite( ts_name, ts_file, ts_line );
493 framework::current_auto_test_suite().add( ts );
496 decorators.store_in( *ts );
499 framework::current_auto_test_suite( ts );
502 //____________________________________________________________________________//
504 auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector_t& decorators )
506 framework::current_auto_test_suite().add( tc_gen, decorators );
509 //____________________________________________________________________________//
511 auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector_t& decorators )
513 framework::current_auto_test_suite().add( tc_gen, decorators );
517 //____________________________________________________________________________//
519 auto_test_unit_registrar::auto_test_unit_registrar( int )
521 framework::current_auto_test_suite( 0, false );
524 //____________________________________________________________________________//
526 } // namespace ut_detail
528 // ************************************************************************** //
529 // ************** global_fixture ************** //
530 // ************************************************************************** //
532 global_fixture::global_fixture(): registered(false)
534 framework::register_global_fixture( *this );
538 void global_fixture::unregister_from_framework() {
539 // not accessing the framework singleton after deregistering -> release
540 // of the observer from the framework
542 framework::deregister_global_fixture( *this );
547 global_fixture::~global_fixture()
549 this->unregister_from_framework();
552 // ************************************************************************** //
553 // ************** global_configuration ************** //
554 // ************************************************************************** //
556 global_configuration::global_configuration(): registered(false)
558 framework::register_observer( *this );
562 void global_configuration::unregister_from_framework()
564 // not accessing the framework singleton after deregistering -> release
565 // of the observer from the framework
567 framework::deregister_observer( *this );
572 global_configuration::~global_configuration()
574 this->unregister_from_framework();
577 //____________________________________________________________________________//
579 } // namespace unit_test
582 #include <boost/test/detail/enable_warnings.hpp>
584 #endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER