unit_test_main.ipp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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 : $RCSfile$
  8. //
  9. // Version : $Revision$
  10. //
  11. // Description : main function implementation for Unit Test Framework
  12. // ***************************************************************************
  13. #ifndef BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
  14. #define BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
  15. // Boost.Test
  16. #include <boost/test/framework.hpp>
  17. #include <boost/test/results_collector.hpp>
  18. #include <boost/test/results_reporter.hpp>
  19. #include <boost/test/tree/visitor.hpp>
  20. #include <boost/test/tree/test_unit.hpp>
  21. #include <boost/test/tree/traverse.hpp>
  22. #include <boost/test/unit_test_parameters.hpp>
  23. #include <boost/test/utils/foreach.hpp>
  24. #include <boost/test/utils/basic_cstring/io.hpp>
  25. // Boost
  26. #include <boost/core/ignore_unused.hpp>
  27. #include <boost/cstdlib.hpp>
  28. // STL
  29. #include <cstdio>
  30. #include <stdexcept>
  31. #include <iostream>
  32. #include <iomanip>
  33. #include <iterator>
  34. #include <set>
  35. #include <boost/test/detail/suppress_warnings.hpp>
  36. //____________________________________________________________________________//
  37. namespace boost {
  38. namespace unit_test {
  39. namespace ut_detail {
  40. // ************************************************************************** //
  41. // ************** hrf_content_reporter ************** //
  42. // ************************************************************************** //
  43. struct hrf_content_reporter : test_tree_visitor {
  44. explicit hrf_content_reporter( std::ostream& os ) : m_os( os ), m_indent( -4 ) {} // skip master test suite
  45. private:
  46. void report_test_unit( test_unit const& tu )
  47. {
  48. m_os << std::setw( m_indent ) << "" << tu.p_name;
  49. m_os << (tu.p_default_status == test_unit::RS_ENABLED ? "*" : " ");
  50. //m_os << '[' << tu.p_sibling_rank << ']';
  51. if( !tu.p_description->empty() )
  52. m_os << ": " << tu.p_description;
  53. m_os << "\n";
  54. }
  55. void visit( test_case const& tc ) BOOST_OVERRIDE { report_test_unit( tc ); }
  56. bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
  57. {
  58. if( m_indent >= 0 )
  59. report_test_unit( ts );
  60. m_indent += 4;
  61. return true;
  62. }
  63. void test_suite_finish( test_suite const& ) BOOST_OVERRIDE
  64. {
  65. m_indent -= 4;
  66. }
  67. // Data members
  68. std::ostream& m_os;
  69. int m_indent;
  70. };
  71. // ************************************************************************** //
  72. // ************** dot_content_reporter ************** //
  73. // ************************************************************************** //
  74. struct dot_content_reporter : test_tree_visitor {
  75. explicit dot_content_reporter( std::ostream& os ) : m_os( os ) {}
  76. private:
  77. void report_test_unit( test_unit const& tu )
  78. {
  79. bool master_ts = tu.p_parent_id == INV_TEST_UNIT_ID;
  80. m_os << "tu" << tu.p_id;
  81. m_os << (master_ts ? "[shape=ellipse,peripheries=2" : "[shape=Mrecord" );
  82. m_os << ",fontname=Helvetica";
  83. m_os << (tu.p_default_status == test_unit::RS_ENABLED ? ",color=green" : ",color=yellow");
  84. if( master_ts )
  85. m_os << ",label=\"" << tu.p_name << "\"];\n";
  86. else {
  87. m_os << ",label=\"" << tu.p_name << "|" << tu.p_file_name << "(" << tu.p_line_num << ")";
  88. if( tu.p_timeout > 0 )
  89. m_os << "|timeout=" << tu.p_timeout;
  90. if( tu.p_expected_failures != 0 )
  91. m_os << "|expected failures=" << tu.p_expected_failures;
  92. if( !tu.p_labels->empty() ) {
  93. m_os << "|labels:";
  94. BOOST_TEST_FOREACH( std::string const&, l, tu.p_labels.get() )
  95. m_os << " @" << l;
  96. }
  97. m_os << "\"];\n";
  98. }
  99. if( !master_ts )
  100. m_os << "tu" << tu.p_parent_id << " -> " << "tu" << tu.p_id << ";\n";
  101. BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
  102. test_unit const& dep = framework::get( dep_id, TUT_ANY );
  103. m_os << "tu" << tu.p_id << " -> " << "tu" << dep.p_id << "[color=red,style=dotted,constraint=false];\n";
  104. }
  105. }
  106. void visit( test_case const& tc ) BOOST_OVERRIDE
  107. {
  108. report_test_unit( tc );
  109. }
  110. bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
  111. {
  112. if( ts.p_parent_id == INV_TEST_UNIT_ID )
  113. m_os << "digraph G {rankdir=LR;\n";
  114. report_test_unit( ts );
  115. m_os << "{\n";
  116. return true;
  117. }
  118. void test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
  119. {
  120. m_os << "}\n";
  121. if( ts.p_parent_id == INV_TEST_UNIT_ID )
  122. m_os << "}\n";
  123. }
  124. std::ostream& m_os;
  125. };
  126. // ************************************************************************** //
  127. // ************** labels_collector ************** //
  128. // ************************************************************************** //
  129. struct labels_collector : test_tree_visitor {
  130. std::set<std::string> const& labels() const { return m_labels; }
  131. private:
  132. bool visit( test_unit const& tu ) BOOST_OVERRIDE
  133. {
  134. m_labels.insert( tu.p_labels->begin(), tu.p_labels->end() );
  135. return true;
  136. }
  137. // Data members
  138. std::set<std::string> m_labels;
  139. };
  140. struct framework_shutdown_helper {
  141. ~framework_shutdown_helper() {
  142. try {
  143. framework::shutdown();
  144. }
  145. catch(...) {
  146. std::cerr << "Boost.Test shutdown exception caught" << std::endl;
  147. }
  148. }
  149. };
  150. } // namespace ut_detail
  151. // ************************************************************************** //
  152. // ************** unit_test_main ************** //
  153. // ************************************************************************** //
  154. int BOOST_TEST_DECL
  155. unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
  156. {
  157. int result_code = 0;
  158. ut_detail::framework_shutdown_helper shutdown_helper;
  159. boost::ignore_unused(shutdown_helper);
  160. BOOST_TEST_I_TRY {
  161. framework::init( init_func, argc, argv );
  162. if( runtime_config::get<bool>( runtime_config::btrt_wait_for_debugger ) ) {
  163. results_reporter::get_stream() << "Press any key to continue..." << std::endl;
  164. // getchar is defined as a macro in uClibc. Use parenthesis to fix
  165. // gcc bug 58952 for gcc <= 4.8.2.
  166. (std::getchar)();
  167. results_reporter::get_stream() << "Continuing..." << std::endl;
  168. }
  169. framework::finalize_setup_phase();
  170. output_format list_cont = runtime_config::get<output_format>( runtime_config::btrt_list_content );
  171. if( list_cont != unit_test::OF_INVALID ) {
  172. if( list_cont == unit_test::OF_DOT ) {
  173. ut_detail::dot_content_reporter reporter( results_reporter::get_stream() );
  174. traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
  175. }
  176. else {
  177. ut_detail::hrf_content_reporter reporter( results_reporter::get_stream() );
  178. traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
  179. }
  180. return boost::exit_success;
  181. }
  182. if( runtime_config::get<bool>( runtime_config::btrt_list_labels ) ) {
  183. ut_detail::labels_collector collector;
  184. traverse_test_tree( framework::master_test_suite().p_id, collector, true );
  185. results_reporter::get_stream() << "Available labels:\n ";
  186. std::copy( collector.labels().begin(), collector.labels().end(),
  187. std::ostream_iterator<std::string>( results_reporter::get_stream(), "\n " ) );
  188. results_reporter::get_stream() << "\n";
  189. return boost::exit_success;
  190. }
  191. framework::run();
  192. result_code = !runtime_config::get<bool>( runtime_config::btrt_result_code )
  193. ? boost::exit_success
  194. : results_collector.results( framework::master_test_suite().p_id ).result_code();
  195. }
  196. BOOST_TEST_I_CATCH( framework::nothing_to_test, ex ) {
  197. result_code = ex.m_result_code;
  198. }
  199. BOOST_TEST_I_CATCH( framework::internal_error, ex ) {
  200. results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl;
  201. result_code = boost::exit_exception_failure;
  202. }
  203. BOOST_TEST_I_CATCH( framework::setup_error, ex ) {
  204. results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
  205. result_code = boost::exit_exception_failure;
  206. }
  207. BOOST_TEST_I_CATCH( std::logic_error, ex ) {
  208. results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
  209. result_code = boost::exit_exception_failure;
  210. }
  211. BOOST_TEST_I_CATCHALL() {
  212. results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
  213. result_code = boost::exit_exception_failure;
  214. }
  215. return result_code;
  216. }
  217. } // namespace unit_test
  218. } // namespace boost
  219. #if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
  220. // ************************************************************************** //
  221. // ************** main function for tests using lib ************** //
  222. // ************************************************************************** //
  223. int BOOST_TEST_CALL_DECL
  224. main( int argc, char* argv[] )
  225. {
  226. // prototype for user's unit test init function
  227. #ifdef BOOST_TEST_ALTERNATIVE_INIT_API
  228. extern bool init_unit_test();
  229. boost::unit_test::init_unit_test_func init_func = &init_unit_test;
  230. #else
  231. extern ::boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] );
  232. boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite;
  233. #endif
  234. return ::boost::unit_test::unit_test_main( init_func, argc, argv );
  235. }
  236. #endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
  237. //____________________________________________________________________________//
  238. #include <boost/test/detail/enable_warnings.hpp>
  239. #endif // BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER