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