test_tree.ipp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  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. // STL
  26. #include <algorithm>
  27. #include <vector>
  28. #include <set>
  29. #include <boost/test/detail/suppress_warnings.hpp>
  30. //____________________________________________________________________________//
  31. namespace boost {
  32. namespace unit_test {
  33. // ************************************************************************** //
  34. // ************** test_unit ************** //
  35. // ************************************************************************** //
  36. test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
  37. : p_type( t )
  38. , p_type_name( t == TUT_CASE ? "case" : "suite" )
  39. , p_file_name( file_name )
  40. , p_line_num( line_num )
  41. , p_id( INV_TEST_UNIT_ID )
  42. , p_parent_id( INV_TEST_UNIT_ID )
  43. , p_name( std::string( name.begin(), name.size() ) )
  44. , p_timeout( 0 )
  45. , p_expected_failures( 0 )
  46. , p_default_status( RS_INHERIT )
  47. , p_run_status( RS_INVALID )
  48. , p_sibling_rank(0)
  49. {
  50. }
  51. //____________________________________________________________________________//
  52. test_unit::test_unit( const_string module_name )
  53. : p_type( TUT_SUITE )
  54. , p_type_name( "module" )
  55. , p_line_num( 0 )
  56. , p_id( INV_TEST_UNIT_ID )
  57. , p_parent_id( INV_TEST_UNIT_ID )
  58. , p_name( std::string( module_name.begin(), module_name.size() ) )
  59. , p_timeout( 0 )
  60. , p_expected_failures( 0 )
  61. , p_default_status( RS_INHERIT )
  62. , p_run_status( RS_INVALID )
  63. , p_sibling_rank(0)
  64. {
  65. }
  66. //____________________________________________________________________________//
  67. test_unit::~test_unit()
  68. {
  69. framework::deregister_test_unit( this );
  70. }
  71. //____________________________________________________________________________//
  72. void
  73. test_unit::depends_on( test_unit* tu )
  74. {
  75. BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id,
  76. "Can't add dependency to the master test suite" );
  77. p_dependencies.value.push_back( tu->p_id );
  78. }
  79. //____________________________________________________________________________//
  80. void
  81. test_unit::add_precondition( precondition_t const& pc )
  82. {
  83. p_preconditions.value.push_back( pc );
  84. }
  85. //____________________________________________________________________________//
  86. test_tools::assertion_result
  87. test_unit::check_preconditions() const
  88. {
  89. BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
  90. test_unit const& dep = framework::get( dep_id, TUT_ANY );
  91. if( !dep.is_enabled() ) {
  92. test_tools::assertion_result res(false);
  93. res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
  94. return res;
  95. }
  96. test_results const& test_rslt = unit_test::results_collector.results( dep_id );
  97. if( !test_rslt.passed() ) {
  98. test_tools::assertion_result res(false);
  99. res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << (test_rslt.skipped() ? "\" was skipped":"\" has failed");
  100. return res;
  101. }
  102. if( test_rslt.p_test_cases_skipped > 0 ) {
  103. test_tools::assertion_result res(false);
  104. res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
  105. return res;
  106. }
  107. }
  108. BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
  109. test_tools::assertion_result res = precondition( p_id );
  110. if( !res ) {
  111. test_tools::assertion_result res_out(false);
  112. res_out.message() << "precondition failed";
  113. if( !res.has_empty_message() )
  114. res_out.message() << ": " << res.message();
  115. return res_out;
  116. }
  117. }
  118. return true;
  119. }
  120. //____________________________________________________________________________//
  121. void
  122. test_unit::increase_exp_fail( counter_t num )
  123. {
  124. p_expected_failures.value += num;
  125. if( p_parent_id != INV_TEST_UNIT_ID )
  126. framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
  127. }
  128. //____________________________________________________________________________//
  129. std::string
  130. test_unit::full_name() const
  131. {
  132. if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
  133. return p_name;
  134. std::string res = framework::get<test_suite>( p_parent_id ).full_name();
  135. res.append("/");
  136. res.append( p_name );
  137. return res;
  138. }
  139. //____________________________________________________________________________//
  140. void
  141. test_unit::add_label( const_string l )
  142. {
  143. p_labels.value.push_back( std::string() + l );
  144. }
  145. //____________________________________________________________________________//
  146. bool
  147. test_unit::has_label( const_string l ) const
  148. {
  149. return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
  150. }
  151. //____________________________________________________________________________//
  152. // ************************************************************************** //
  153. // ************** test_case ************** //
  154. // ************************************************************************** //
  155. test_case::test_case( const_string name, boost::function<void ()> const& test_func )
  156. : test_unit( name, "", 0, static_cast<test_unit_type>(type) )
  157. , p_test_func( test_func )
  158. {
  159. framework::register_test_unit( this );
  160. }
  161. //____________________________________________________________________________//
  162. test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
  163. : test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
  164. , p_test_func( test_func )
  165. {
  166. framework::register_test_unit( this );
  167. }
  168. //____________________________________________________________________________//
  169. // ************************************************************************** //
  170. // ************** test_suite ************** //
  171. // ************************************************************************** //
  172. //____________________________________________________________________________//
  173. test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
  174. : test_unit( ut_detail::normalize_test_case_name( name ), file_name, line_num, static_cast<test_unit_type>(type) )
  175. {
  176. framework::register_test_unit( this );
  177. }
  178. //____________________________________________________________________________//
  179. test_suite::test_suite( const_string module_name )
  180. : test_unit( module_name )
  181. {
  182. framework::register_test_unit( this );
  183. }
  184. //____________________________________________________________________________//
  185. void
  186. test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
  187. {
  188. tu->p_timeout.value = timeout;
  189. m_children.push_back( tu->p_id );
  190. tu->p_parent_id.value = p_id;
  191. if( tu->p_expected_failures != 0 )
  192. increase_exp_fail( tu->p_expected_failures );
  193. if( expected_failures )
  194. tu->increase_exp_fail( expected_failures );
  195. }
  196. //____________________________________________________________________________//
  197. void
  198. test_suite::add( test_unit_generator const& gen, unsigned timeout )
  199. {
  200. test_unit* tu;
  201. while((tu = gen.next()) != 0)
  202. add( tu, 0, timeout );
  203. }
  204. //____________________________________________________________________________//
  205. void
  206. test_suite::add( test_unit_generator const& gen, decorator::collector_t& decorators )
  207. {
  208. test_unit* tu;
  209. while((tu = gen.next()) != 0) {
  210. decorators.store_in( *tu );
  211. add( tu, 0 );
  212. }
  213. decorators.reset();
  214. }
  215. //____________________________________________________________________________//
  216. void
  217. test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
  218. {
  219. std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
  220. m_generators.push_back(tmp_p);
  221. decorators.reset();
  222. }
  223. //____________________________________________________________________________//
  224. void
  225. test_suite::generate( )
  226. {
  227. typedef std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > element_t;
  228. for(std::vector<element_t>::iterator it(m_generators.begin()), ite(m_generators.end());
  229. it < ite;
  230. ++it)
  231. {
  232. test_unit* tu;
  233. while((tu = it->first->next()) != 0) {
  234. tu->p_decorators.value.insert( tu->p_decorators.value.end(), it->second.begin(), it->second.end() );
  235. //it->second.store_in( *tu );
  236. add( tu, 0 );
  237. }
  238. }
  239. m_generators.clear();
  240. #if 0
  241. test_unit* tu;
  242. while((tu = gen.next()) != 0) {
  243. decorators.store_in( *tu );
  244. add( tu, 0 );
  245. }
  246. #endif
  247. }
  248. //____________________________________________________________________________//
  249. void
  250. test_suite::check_for_duplicate_test_cases() {
  251. // check for clashing names #12597
  252. std::set<std::string> names;
  253. for( test_unit_id_list::const_iterator it(m_children.begin()), ite(m_children.end());
  254. it < ite;
  255. ++it) {
  256. std::string name = framework::get(*it, TUT_ANY).p_name;
  257. std::pair<std::set<std::string>::iterator, bool> ret = names.insert(name);
  258. BOOST_TEST_SETUP_ASSERT(ret.second,
  259. "test unit with name '"
  260. + name
  261. + std::string("' registered multiple times in the test suite '")
  262. + this->p_name.value
  263. + "'");
  264. }
  265. return;
  266. }
  267. //____________________________________________________________________________//
  268. void
  269. test_suite::remove( test_unit_id id )
  270. {
  271. test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
  272. if( it != m_children.end() )
  273. m_children.erase( it );
  274. }
  275. //____________________________________________________________________________//
  276. test_unit_id
  277. test_suite::get( const_string tu_name ) const
  278. {
  279. BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
  280. if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
  281. return id;
  282. }
  283. return INV_TEST_UNIT_ID;
  284. }
  285. //____________________________________________________________________________//
  286. // ************************************************************************** //
  287. // ************** master_test_suite ************** //
  288. // ************************************************************************** //
  289. master_test_suite_t::master_test_suite_t()
  290. : test_suite( "Master Test Suite" )
  291. , argc( 0 )
  292. , argv( 0 )
  293. {
  294. p_default_status.value = RS_ENABLED;
  295. }
  296. // ************************************************************************** //
  297. // ************** traverse_test_tree ************** //
  298. // ************************************************************************** //
  299. void
  300. traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
  301. {
  302. if( tc.is_enabled() || ignore_status )
  303. V.visit( tc );
  304. }
  305. //____________________________________________________________________________//
  306. void
  307. traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
  308. {
  309. // skip disabled test suite unless we asked to ignore this condition
  310. if( !ignore_status && !suite.is_enabled() )
  311. return;
  312. // Invoke test_suite_start callback
  313. if( !V.test_suite_start( suite ) )
  314. return;
  315. // Recurse into children
  316. std::size_t total_children = suite.m_children.size();
  317. for( std::size_t i=0; i < total_children; ) {
  318. // this statement can remove the test unit from this list
  319. traverse_test_tree( suite.m_children[i], V, ignore_status );
  320. if( total_children > suite.m_children.size() )
  321. total_children = suite.m_children.size();
  322. else
  323. ++i;
  324. }
  325. // Invoke test_suite_finish callback
  326. V.test_suite_finish( suite );
  327. }
  328. //____________________________________________________________________________//
  329. void
  330. traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
  331. {
  332. if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
  333. traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
  334. else
  335. traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
  336. }
  337. //____________________________________________________________________________//
  338. // ************************************************************************** //
  339. // ************** object generators ************** //
  340. // ************************************************************************** //
  341. namespace ut_detail {
  342. std::string
  343. normalize_test_case_name( const_string name )
  344. {
  345. std::string norm_name( name.begin(), name.size() );
  346. if( name[0] == '&' )
  347. norm_name = norm_name.substr( 1 );
  348. // trim spaces
  349. std::size_t first_not_space = norm_name.find_first_not_of(' ');
  350. if( first_not_space ) {
  351. norm_name.erase(0, first_not_space);
  352. }
  353. std::size_t last_not_space = norm_name.find_last_not_of(' ');
  354. if( last_not_space !=std::string::npos ) {
  355. norm_name.erase(last_not_space + 1);
  356. }
  357. // sanitize all chars that might be used in runtime filters
  358. static const char to_replace[] = { ':', '*', '@', '+', '!', '/', ',' };
  359. for(std::size_t index = 0;
  360. index < sizeof(to_replace)/sizeof(to_replace[0]);
  361. index++) {
  362. std::replace(norm_name.begin(), norm_name.end(), to_replace[index], '_');
  363. }
  364. return norm_name;
  365. }
  366. //____________________________________________________________________________//
  367. // ************************************************************************** //
  368. // ************** auto_test_unit_registrar ************** //
  369. // ************************************************************************** //
  370. auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail )
  371. {
  372. framework::current_auto_test_suite().add( tc, exp_fail );
  373. decorators.store_in( *tc );
  374. decorators.reset();
  375. }
  376. //____________________________________________________________________________//
  377. 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 )
  378. {
  379. test_unit_id id = framework::current_auto_test_suite().get( ts_name );
  380. test_suite* ts;
  381. if( id != INV_TEST_UNIT_ID ) {
  382. ts = &framework::get<test_suite>( id );
  383. BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
  384. }
  385. else {
  386. ts = new test_suite( ts_name, ts_file, ts_line );
  387. framework::current_auto_test_suite().add( ts );
  388. }
  389. decorators.store_in( *ts );
  390. decorators.reset();
  391. framework::current_auto_test_suite( ts );
  392. }
  393. //____________________________________________________________________________//
  394. auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector_t& decorators )
  395. {
  396. framework::current_auto_test_suite().add( tc_gen, decorators );
  397. }
  398. //____________________________________________________________________________//
  399. auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector_t& decorators )
  400. {
  401. framework::current_auto_test_suite().add( tc_gen, decorators );
  402. }
  403. //____________________________________________________________________________//
  404. auto_test_unit_registrar::auto_test_unit_registrar( int )
  405. {
  406. framework::current_auto_test_suite( 0, false );
  407. }
  408. //____________________________________________________________________________//
  409. } // namespace ut_detail
  410. // ************************************************************************** //
  411. // ************** global_fixture ************** //
  412. // ************************************************************************** //
  413. global_fixture::global_fixture(): registered(false)
  414. {
  415. framework::register_global_fixture( *this );
  416. registered = true;
  417. }
  418. void global_fixture::unregister_from_framework() {
  419. // not accessing the framework singleton after deregistering -> release
  420. // of the observer from the framework
  421. if(registered) {
  422. framework::deregister_global_fixture( *this );
  423. }
  424. registered = false;
  425. }
  426. global_fixture::~global_fixture()
  427. {
  428. this->unregister_from_framework();
  429. }
  430. // ************************************************************************** //
  431. // ************** global_configuration ************** //
  432. // ************************************************************************** //
  433. global_configuration::global_configuration(): registered(false)
  434. {
  435. framework::register_observer( *this );
  436. registered = true;
  437. }
  438. void global_configuration::unregister_from_framework()
  439. {
  440. // not accessing the framework singleton after deregistering -> release
  441. // of the observer from the framework
  442. if(registered) {
  443. framework::deregister_observer( *this );
  444. }
  445. registered = false;
  446. }
  447. global_configuration::~global_configuration()
  448. {
  449. this->unregister_from_framework();
  450. }
  451. //____________________________________________________________________________//
  452. } // namespace unit_test
  453. } // namespace boost
  454. #include <boost/test/detail/enable_warnings.hpp>
  455. #endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER