test_tree.ipp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. /// @file
  8. /// Provides core implementation for Unit Test Framework.
  9. /// Extensions can be provided in separate files
  10. // ***************************************************************************
  11. #ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
  12. #define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
  13. // Boost.Test
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/test/framework.hpp>
  16. #include <boost/test/results_collector.hpp>
  17. #include <boost/test/tree/test_unit.hpp>
  18. #include <boost/test/tree/visitor.hpp>
  19. #include <boost/test/tree/traverse.hpp>
  20. #include <boost/test/tree/auto_registration.hpp>
  21. #include <boost/test/tree/global_fixture.hpp>
  22. #include <boost/test/utils/foreach.hpp>
  23. #include <boost/test/utils/basic_cstring/io.hpp>
  24. #include <boost/test/unit_test_parameters.hpp>
  25. // Boost
  26. #include <boost/timer.hpp>
  27. // STL
  28. #include <algorithm>
  29. #include <vector>
  30. #include <boost/test/detail/suppress_warnings.hpp>
  31. //____________________________________________________________________________//
  32. namespace boost {
  33. namespace unit_test {
  34. // ************************************************************************** //
  35. // ************** test_unit ************** //
  36. // ************************************************************************** //
  37. test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
  38. : p_type( t )
  39. , p_type_name( t == TUT_CASE ? "case" : "suite" )
  40. , p_file_name( file_name )
  41. , p_line_num( line_num )
  42. , p_id( INV_TEST_UNIT_ID )
  43. , p_parent_id( INV_TEST_UNIT_ID )
  44. , p_name( std::string( name.begin(), name.size() ) )
  45. , p_timeout( 0 )
  46. , p_expected_failures( 0 )
  47. , p_default_status( RS_INHERIT )
  48. , p_run_status( RS_INVALID )
  49. , p_sibling_rank(0)
  50. {
  51. }
  52. //____________________________________________________________________________//
  53. test_unit::test_unit( const_string module_name )
  54. : p_type( TUT_SUITE )
  55. , p_type_name( "module" )
  56. , p_line_num( 0 )
  57. , p_id( INV_TEST_UNIT_ID )
  58. , p_parent_id( INV_TEST_UNIT_ID )
  59. , p_name( std::string( module_name.begin(), module_name.size() ) )
  60. , p_timeout( 0 )
  61. , p_expected_failures( 0 )
  62. , p_default_status( RS_INHERIT )
  63. , p_run_status( RS_INVALID )
  64. , p_sibling_rank(0)
  65. {
  66. }
  67. //____________________________________________________________________________//
  68. test_unit::~test_unit()
  69. {
  70. framework::deregister_test_unit( this );
  71. }
  72. //____________________________________________________________________________//
  73. void
  74. test_unit::depends_on( test_unit* tu )
  75. {
  76. BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id,
  77. "Can't add dependency to the master test suite" );
  78. p_dependencies.value.push_back( tu->p_id );
  79. }
  80. //____________________________________________________________________________//
  81. void
  82. test_unit::add_precondition( precondition_t const& pc )
  83. {
  84. p_preconditions.value.push_back( pc );
  85. }
  86. //____________________________________________________________________________//
  87. test_tools::assertion_result
  88. test_unit::check_preconditions() const
  89. {
  90. BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
  91. test_unit const& dep = framework::get( dep_id, TUT_ANY );
  92. if( !dep.is_enabled() ) {
  93. test_tools::assertion_result res(false);
  94. res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
  95. return res;
  96. }
  97. test_results const& test_rslt = unit_test::results_collector.results( dep_id );
  98. if( !test_rslt.passed() ) {
  99. test_tools::assertion_result res(false);
  100. res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has failed";
  101. return res;
  102. }
  103. if( test_rslt.p_test_cases_skipped > 0 ) {
  104. test_tools::assertion_result res(false);
  105. res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
  106. return res;
  107. }
  108. }
  109. BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
  110. test_tools::assertion_result res = precondition( p_id );
  111. if( !res ) {
  112. test_tools::assertion_result res_out(false);
  113. res_out.message() << "precondition failed";
  114. if( !res.has_empty_message() )
  115. res_out.message() << ": " << res.message();
  116. return res_out;
  117. }
  118. }
  119. return true;
  120. }
  121. //____________________________________________________________________________//
  122. void
  123. test_unit::increase_exp_fail( counter_t num )
  124. {
  125. p_expected_failures.value += num;
  126. if( p_parent_id != INV_TEST_UNIT_ID )
  127. framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
  128. }
  129. //____________________________________________________________________________//
  130. std::string
  131. test_unit::full_name() const
  132. {
  133. if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
  134. return p_name;
  135. std::string res = framework::get<test_suite>( p_parent_id ).full_name();
  136. res.append("/");
  137. res.append( p_name );
  138. return res;
  139. }
  140. //____________________________________________________________________________//
  141. void
  142. test_unit::add_label( const_string l )
  143. {
  144. p_labels.value.push_back( std::string() + l );
  145. }
  146. //____________________________________________________________________________//
  147. bool
  148. test_unit::has_label( const_string l ) const
  149. {
  150. return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
  151. }
  152. //____________________________________________________________________________//
  153. // ************************************************************************** //
  154. // ************** test_case ************** //
  155. // ************************************************************************** //
  156. test_case::test_case( const_string name, boost::function<void ()> const& test_func )
  157. : test_unit( name, "", 0, static_cast<test_unit_type>(type) )
  158. , p_test_func( test_func )
  159. {
  160. framework::register_test_unit( this );
  161. }
  162. //____________________________________________________________________________//
  163. test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
  164. : test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
  165. , p_test_func( test_func )
  166. {
  167. framework::register_test_unit( this );
  168. }
  169. //____________________________________________________________________________//
  170. // ************************************************************************** //
  171. // ************** test_suite ************** //
  172. // ************************************************************************** //
  173. //____________________________________________________________________________//
  174. test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
  175. : test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
  176. {
  177. framework::register_test_unit( this );
  178. }
  179. //____________________________________________________________________________//
  180. test_suite::test_suite( const_string module_name )
  181. : test_unit( module_name )
  182. {
  183. framework::register_test_unit( this );
  184. }
  185. //____________________________________________________________________________//
  186. void
  187. test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
  188. {
  189. tu->p_timeout.value = timeout;
  190. m_children.push_back( tu->p_id );
  191. tu->p_parent_id.value = p_id;
  192. if( tu->p_expected_failures != 0 )
  193. increase_exp_fail( tu->p_expected_failures );
  194. if( expected_failures )
  195. tu->increase_exp_fail( expected_failures );
  196. }
  197. //____________________________________________________________________________//
  198. void
  199. test_suite::add( test_unit_generator const& gen, unsigned timeout )
  200. {
  201. test_unit* tu;
  202. while((tu = gen.next()) != 0)
  203. add( tu, 0, timeout );
  204. }
  205. //____________________________________________________________________________//
  206. void
  207. test_suite::add( test_unit_generator const& gen, decorator::collector& decorators )
  208. {
  209. test_unit* tu;
  210. while((tu = gen.next()) != 0) {
  211. decorators.store_in( *tu );
  212. add( tu, 0 );
  213. }
  214. decorators.reset();
  215. }
  216. //____________________________________________________________________________//
  217. void
  218. test_suite::remove( test_unit_id id )
  219. {
  220. test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
  221. if( it != m_children.end() )
  222. m_children.erase( it );
  223. }
  224. //____________________________________________________________________________//
  225. test_unit_id
  226. test_suite::get( const_string tu_name ) const
  227. {
  228. BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
  229. if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
  230. return id;
  231. }
  232. return INV_TEST_UNIT_ID;
  233. }
  234. //____________________________________________________________________________//
  235. // ************************************************************************** //
  236. // ************** master_test_suite ************** //
  237. // ************************************************************************** //
  238. master_test_suite_t::master_test_suite_t()
  239. : test_suite( "Master Test Suite" )
  240. , argc( 0 )
  241. , argv( 0 )
  242. {
  243. p_default_status.value = RS_ENABLED;
  244. }
  245. // ************************************************************************** //
  246. // ************** traverse_test_tree ************** //
  247. // ************************************************************************** //
  248. void
  249. traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
  250. {
  251. if( tc.is_enabled() || ignore_status )
  252. V.visit( tc );
  253. }
  254. //____________________________________________________________________________//
  255. void
  256. traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
  257. {
  258. // skip disabled test suite unless we asked to ignore this condition
  259. if( !ignore_status && !suite.is_enabled() )
  260. return;
  261. // Invoke test_suite_start callback
  262. if( !V.test_suite_start( suite ) )
  263. return;
  264. // Recurse into children
  265. std::size_t total_children = suite.m_children.size();
  266. for( std::size_t i=0; i < total_children; ) {
  267. // this statement can remove the test unit from this list
  268. traverse_test_tree( suite.m_children[i], V, ignore_status );
  269. if( total_children > suite.m_children.size() )
  270. total_children = suite.m_children.size();
  271. else
  272. ++i;
  273. }
  274. // Invoke test_suite_finish callback
  275. V.test_suite_finish( suite );
  276. }
  277. //____________________________________________________________________________//
  278. void
  279. traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
  280. {
  281. if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
  282. traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
  283. else
  284. traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
  285. }
  286. //____________________________________________________________________________//
  287. // ************************************************************************** //
  288. // ************** object generators ************** //
  289. // ************************************************************************** //
  290. namespace ut_detail {
  291. std::string
  292. normalize_test_case_name( const_string name )
  293. {
  294. std::string norm_name( name.begin(), name.size() );
  295. if( name[0] == '&' )
  296. norm_name = norm_name.substr( 1 );
  297. std::replace(norm_name.begin(), norm_name.end(), ' ', '_');
  298. return norm_name;
  299. }
  300. //____________________________________________________________________________//
  301. // ************************************************************************** //
  302. // ************** auto_test_unit_registrar ************** //
  303. // ************************************************************************** //
  304. auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector& decorators, counter_t exp_fail )
  305. {
  306. framework::current_auto_test_suite().add( tc, exp_fail );
  307. decorators.store_in( *tc );
  308. decorators.reset();
  309. }
  310. //____________________________________________________________________________//
  311. auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector& decorators )
  312. {
  313. test_unit_id id = framework::current_auto_test_suite().get( ts_name );
  314. test_suite* ts;
  315. if( id != INV_TEST_UNIT_ID ) {
  316. ts = &framework::get<test_suite>( id );
  317. BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
  318. }
  319. else {
  320. ts = new test_suite( ts_name, ts_file, ts_line );
  321. framework::current_auto_test_suite().add( ts );
  322. }
  323. decorators.store_in( *ts );
  324. decorators.reset();
  325. framework::current_auto_test_suite( ts );
  326. }
  327. //____________________________________________________________________________//
  328. auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector& decorators )
  329. {
  330. framework::current_auto_test_suite().add( tc_gen, decorators );
  331. }
  332. //____________________________________________________________________________//
  333. auto_test_unit_registrar::auto_test_unit_registrar( int )
  334. {
  335. framework::current_auto_test_suite( 0, false );
  336. }
  337. //____________________________________________________________________________//
  338. } // namespace ut_detail
  339. // ************************************************************************** //
  340. // ************** global_fixture ************** //
  341. // ************************************************************************** //
  342. global_fixture::global_fixture()
  343. {
  344. framework::register_observer( *this );
  345. }
  346. //____________________________________________________________________________//
  347. } // namespace unit_test
  348. } // namespace boost
  349. #include <boost/test/detail/enable_warnings.hpp>
  350. #endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER