1// (C) Copyright Gennadiy Rozental 2005-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) 5 6// See http://www.boost.org/libs/test for the library home page. 7// 8// File : $RCSfile$ 9// 10// Version : $Revision: 54633 $ 11// 12// Description : privides core implementation for Unit Test Framework. 13// Extensions can be provided in separate files 14// *************************************************************************** 15 16#ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER 17#define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER 18 19// Boost.Test 20#include <boost/detail/workaround.hpp> 21#include <boost/test/unit_test_suite_impl.hpp> 22#include <boost/test/framework.hpp> 23#include <boost/test/utils/foreach.hpp> 24#include <boost/test/results_collector.hpp> 25#include <boost/test/detail/unit_test_parameters.hpp> 26 27// Boost 28#include <boost/timer.hpp> 29 30// STL 31#include <algorithm> 32#include <vector> 33 34#include <boost/test/detail/suppress_warnings.hpp> 35 36#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \ 37 BOOST_WORKAROUND(_STLPORT_VERSION, <= 0x450) \ 38 /**/ 39 using std::rand; // rand is in std and random_shuffle is in _STL 40#endif 41 42//____________________________________________________________________________// 43 44namespace boost { 45 46namespace unit_test { 47 48// ************************************************************************** // 49// ************** test_unit ************** // 50// ************************************************************************** // 51 52test_unit::test_unit( const_string name, test_unit_type t ) 53: p_type( t ) 54, p_type_name( t == tut_case ? "case" : "suite" ) 55, p_id( INV_TEST_UNIT_ID ) 56, p_name( std::string( name.begin(), name.size() ) ) 57, p_enabled( true ) 58{ 59} 60 61//____________________________________________________________________________// 62 63test_unit::~test_unit() 64{ 65 framework::deregister_test_unit( this ); 66} 67 68//____________________________________________________________________________// 69 70void 71test_unit::depends_on( test_unit* tu ) 72{ 73 m_dependencies.push_back( tu->p_id ); 74} 75 76//____________________________________________________________________________// 77 78bool 79test_unit::check_dependencies() const 80{ 81 BOOST_TEST_FOREACH( test_unit_id, tu_id, m_dependencies ) { 82 if( !unit_test::results_collector.results( tu_id ).passed() ) 83 return false; 84 } 85 86 return true; 87} 88 89//____________________________________________________________________________// 90 91void 92test_unit::increase_exp_fail( unsigned num ) 93{ 94 p_expected_failures.value += num; 95 96 if( p_parent_id != 0 ) 97 framework::get<test_suite>( p_parent_id ).increase_exp_fail( num ); 98} 99 100//____________________________________________________________________________// 101 102// ************************************************************************** // 103// ************** test_case ************** // 104// ************************************************************************** // 105 106test_case::test_case( const_string name, callback0<> const& test_func ) 107: test_unit( name, static_cast<test_unit_type>(type) ) 108, m_test_func( test_func ) 109{ 110 // !! weirdest MSVC BUG; try to remove this statement; looks like it eats first token of next statement 111#if BOOST_WORKAROUND(BOOST_MSVC,<1300) 112 0; 113#endif 114 framework::register_test_unit( this ); 115} 116 117//____________________________________________________________________________// 118 119// ************************************************************************** // 120// ************** test_suite ************** // 121// ************************************************************************** // 122 123//____________________________________________________________________________// 124 125test_suite::test_suite( const_string name ) 126: test_unit( name, static_cast<test_unit_type>(type) ) 127{ 128 framework::register_test_unit( this ); 129} 130 131//____________________________________________________________________________// 132 133void 134test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout ) 135{ 136 if( timeout != 0 ) 137 tu->p_timeout.value = timeout; 138 139 m_members.push_back( tu->p_id ); 140 tu->p_parent_id.value = p_id; 141 142 if( tu->p_expected_failures ) 143 increase_exp_fail( tu->p_expected_failures ); 144 145 if( expected_failures ) 146 tu->increase_exp_fail( expected_failures ); 147} 148 149//____________________________________________________________________________// 150 151void 152test_suite::add( test_unit_generator const& gen, unsigned timeout ) 153{ 154 test_unit* tu; 155 while((tu = gen.next(), tu)) 156 add( tu, 0, timeout ); 157} 158 159//____________________________________________________________________________// 160 161void 162test_suite::remove( test_unit_id id ) 163{ 164 std::vector<test_unit_id>::iterator it = std::find( m_members.begin(), m_members.end(), id ); 165 166 if( it != m_members.end() ) 167 m_members.erase( it ); 168} 169 170//____________________________________________________________________________// 171 172test_unit_id 173test_suite::get( const_string tu_name ) const 174{ 175 BOOST_TEST_FOREACH( test_unit_id, id, m_members ) { 176 if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() ) 177 return id; 178 } 179 180 return INV_TEST_UNIT_ID; 181} 182 183//____________________________________________________________________________// 184 185// ************************************************************************** // 186// ************** traverse_test_tree ************** // 187// ************************************************************************** // 188 189void 190traverse_test_tree( test_case const& tc, test_tree_visitor& V ) 191{ 192 if( tc.p_enabled ) 193 V.visit( tc ); 194} 195 196//____________________________________________________________________________// 197 198void 199traverse_test_tree( test_suite const& suite, test_tree_visitor& V ) 200{ 201 if( !suite.p_enabled || !V.test_suite_start( suite ) ) 202 return; 203 204 try { 205 if( runtime_config::random_seed() == 0 ) { 206 BOOST_TEST_FOREACH( test_unit_id, id, suite.m_members ) 207 traverse_test_tree( id, V ); 208 } 209 else { 210 std::vector<test_unit_id> members( suite.m_members ); 211 std::random_shuffle( members.begin(), members.end() ); 212 BOOST_TEST_FOREACH( test_unit_id, id, members ) 213 traverse_test_tree( id, V ); 214 } 215 216 } catch( test_being_aborted const& ) { 217 V.test_suite_finish( suite ); 218 framework::test_unit_aborted( suite ); 219 220 throw; 221 } 222 223 V.test_suite_finish( suite ); 224} 225 226//____________________________________________________________________________// 227 228void 229traverse_test_tree( test_unit_id id, test_tree_visitor& V ) 230{ 231 if( ut_detail::test_id_2_unit_type( id ) == tut_case ) 232 traverse_test_tree( framework::get<test_case>( id ), V ); 233 else 234 traverse_test_tree( framework::get<test_suite>( id ), V ); 235} 236 237//____________________________________________________________________________// 238 239// ************************************************************************** // 240// ************** test_case_counter ************** // 241// ************************************************************************** // 242 243void 244test_case_counter::visit( test_case const& tc ) 245{ 246 if( tc.p_enabled ) 247 ++p_count.value; 248} 249 250//____________________________________________________________________________// 251 252// ************************************************************************** // 253// ************** object generators ************** // 254// ************************************************************************** // 255 256namespace ut_detail { 257 258std::string 259normalize_test_case_name( const_string name ) 260{ 261 return ( name[0] == '&' 262 ? std::string( name.begin()+1, name.size()-1 ) 263 : std::string( name.begin(), name.size() ) ); 264} 265 266//____________________________________________________________________________// 267 268// ************************************************************************** // 269// ************** auto_test_unit_registrar ************** // 270// ************************************************************************** // 271 272auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, counter_t exp_fail ) 273{ 274 curr_ts_store().back()->add( tc, exp_fail ); 275} 276 277//____________________________________________________________________________// 278 279auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name ) 280{ 281 test_unit_id id = curr_ts_store().back()->get( ts_name ); 282 283 test_suite* ts; 284 285 if( id != INV_TEST_UNIT_ID ) { 286 ts = &framework::get<test_suite>( id ); // !! test for invalid tu type 287 BOOST_ASSERT( ts->p_parent_id == curr_ts_store().back()->p_id ); 288 } 289 else { 290 ts = new test_suite( ts_name ); 291 curr_ts_store().back()->add( ts ); 292 } 293 294 curr_ts_store().push_back( ts ); 295} 296 297//____________________________________________________________________________// 298 299auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen ) 300{ 301 curr_ts_store().back()->add( tc_gen ); 302} 303 304//____________________________________________________________________________// 305 306auto_test_unit_registrar::auto_test_unit_registrar( int ) 307{ 308 if( curr_ts_store().size() == 0 ) 309 return; // report error? 310 311 curr_ts_store().pop_back(); 312} 313 314//____________________________________________________________________________// 315 316std::list<test_suite*>& 317auto_test_unit_registrar::curr_ts_store() 318{ 319 static std::list<test_suite*> inst( 1, &framework::master_test_suite() ); 320 return inst; 321} 322 323//____________________________________________________________________________// 324 325} // namespace ut_detail 326 327// ************************************************************************** // 328// ************** global_fixture ************** // 329// ************************************************************************** // 330 331global_fixture::global_fixture() 332{ 333 framework::register_observer( *this ); 334} 335 336//____________________________________________________________________________// 337 338} // namespace unit_test 339 340} // namespace boost 341 342//____________________________________________________________________________// 343 344#include <boost/test/detail/enable_warnings.hpp> 345 346#endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER 347