Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/test/impl/framework.ipp @ 44

Last change on this file since 44 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 13.7 KB
Line 
1//  (C) Copyright Gennadiy Rozental 2005.
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: framework.ipp,v $
9//
10//  Version     : $Revision: 1.10 $
11//
12//  Description : implements framework API - main driver for the test
13// ***************************************************************************
14
15#ifndef BOOST_TEST_FRAMEWORK_IPP_021005GER
16#define BOOST_TEST_FRAMEWORK_IPP_021005GER
17
18// Boost.Test
19#include <boost/test/framework.hpp>
20#include <boost/test/execution_monitor.hpp>
21#include <boost/test/unit_test_suite_impl.hpp>
22#include <boost/test/unit_test_log.hpp>
23#include <boost/test/unit_test_monitor.hpp>
24#include <boost/test/test_observer.hpp>
25#include <boost/test/results_collector.hpp>
26#include <boost/test/progress_monitor.hpp>
27#include <boost/test/results_reporter.hpp>
28#include <boost/test/test_tools.hpp>
29
30#include <boost/test/detail/unit_test_parameters.hpp>
31#include <boost/test/detail/global_typedef.hpp>
32
33#include <boost/test/utils/foreach.hpp>
34
35// Boost
36#include <boost/timer.hpp>
37
38// STL
39#include <map>
40#include <set>
41#include <cstdlib>
42#include <ctime>
43
44#ifdef BOOST_NO_STDC_NAMESPACE
45namespace std { using ::time; using ::srand; }
46#endif
47
48#include <boost/test/detail/suppress_warnings.hpp>
49
50//____________________________________________________________________________//
51
52#ifndef BOOST_TEST_DYN_LINK
53
54// prototype for user's unit test init function
55#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
56extern bool init_unit_test();
57#else
58extern boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] );
59#endif
60
61#endif
62
63namespace boost {
64
65namespace unit_test {
66
67// ************************************************************************** //
68// **************            test_start calls wrapper          ************** //
69// ************************************************************************** //
70
71namespace ut_detail {
72
73struct test_start_caller {
74    test_start_caller( test_observer* to, counter_t tc_amount )
75    : m_to( to )
76    , m_tc_amount( tc_amount )
77    {}
78
79    int operator()()
80    {
81        m_to->test_start( m_tc_amount );
82        return 0;
83    }
84
85private:
86    // Data members
87    test_observer*  m_to;
88    counter_t       m_tc_amount;
89};
90
91}
92
93// ************************************************************************** //
94// **************                   framework                  ************** //
95// ************************************************************************** //
96
97class framework_impl : public test_tree_visitor {
98public:
99    framework_impl()
100    : m_master_test_suite( 0 )
101    , m_curr_test_case( INV_TEST_UNIT_ID )
102    , m_next_test_case_id( MIN_TEST_CASE_ID )
103    , m_next_test_suite_id( MIN_TEST_SUITE_ID )
104    , m_test_in_progress( false )
105    {}
106
107    ~framework_impl()
108    {
109        BOOST_TEST_FOREACH( test_unit_store::value_type const&, tu, m_test_units ) {
110            if( test_id_2_unit_type( tu.second->p_id ) == tut_suite )
111                delete  (test_suite const*)tu.second;
112            else
113                delete  (test_case const*)tu.second;
114        }
115    }
116
117    void            set_tu_id( test_unit& tu, test_unit_id id ) { tu.p_id.value = id; }
118
119    // test_tree_visitor interface implementation
120    void            visit( test_case const& tc )
121    {
122        if( !tc.check_dependencies() ) {
123            BOOST_TEST_FOREACH( test_observer*, to, m_observers )
124                to->test_unit_skipped( tc );
125
126            return;
127        }
128
129        BOOST_TEST_FOREACH( test_observer*, to, m_observers )
130            to->test_unit_start( tc );
131
132        boost::timer tc_timer;
133        test_unit_id bkup = m_curr_test_case;
134        m_curr_test_case = tc.p_id;
135        unit_test_monitor_t::error_level run_result = unit_test_monitor.execute_and_translate( tc );
136
137        unsigned long elapsed = static_cast<unsigned long>( tc_timer.elapsed() * 1e6 );
138
139        if( unit_test_monitor.is_critical_error( run_result ) ) {
140            BOOST_TEST_FOREACH( test_observer*, to, m_observers )
141                to->test_aborted();
142        }
143
144        BOOST_TEST_FOREACH( test_observer*, to, m_observers )
145            to->test_unit_finish( tc, elapsed );
146
147        m_curr_test_case = bkup;
148
149        if( unit_test_monitor.is_critical_error( run_result ) )
150            throw test_being_aborted();
151    }
152
153    bool            test_suite_start( test_suite const& ts )
154    {
155        if( !ts.check_dependencies() ) {
156            BOOST_TEST_FOREACH( test_observer*, to, m_observers )
157                to->test_unit_skipped( ts );
158
159            return false;
160        }
161
162        BOOST_TEST_FOREACH( test_observer*, to, m_observers )
163            to->test_unit_start( ts );
164
165        return true;
166    }
167
168    void            test_suite_finish( test_suite const& ts )
169    {
170        BOOST_TEST_FOREACH( test_observer*, to, m_observers )
171            to->test_unit_finish( ts, 0 );
172    }
173
174    //////////////////////////////////////////////////////////////////
175    struct priority_order {
176        bool operator()( test_observer* lhs, test_observer* rhs ) const
177        {
178            return (lhs->priority() < rhs->priority()) || (lhs->priority() == rhs->priority()) && (lhs < rhs);
179        }
180    };
181
182    typedef std::map<test_unit_id,test_unit const*> test_unit_store;
183    typedef std::set<test_observer*,priority_order> observer_store;
184
185    master_test_suite_t* m_master_test_suite;
186    test_unit_id    m_curr_test_case;
187    test_unit_store m_test_units;
188
189    test_unit_id    m_next_test_case_id;
190    test_unit_id    m_next_test_suite_id;
191
192    bool            m_test_in_progress;
193
194    observer_store  m_observers;
195};
196
197//____________________________________________________________________________//
198
199namespace {
200
201framework_impl& s_frk_impl() { static framework_impl the_inst; return the_inst; }
202
203} // local namespace
204
205//____________________________________________________________________________//
206
207namespace framework {
208
209void
210init( int argc, char* argv[] )
211{
212    runtime_config::init( &argc, argv );
213
214    // set the log level nad format
215    unit_test_log.set_threshold_level( runtime_config::log_level() );
216    unit_test_log.set_format( runtime_config::log_format() );
217
218    // set the report level nad format
219    results_reporter::set_level( runtime_config::report_level() );
220    results_reporter::set_format( runtime_config::report_format() );
221
222    register_observer( results_collector );
223    register_observer( unit_test_log );
224
225    if( runtime_config::show_progress() )
226        register_observer( progress_monitor );
227
228    if( runtime_config::detect_memory_leaks() > 0 ) {
229        detect_memory_leaks( true );
230        break_memory_alloc( runtime_config::detect_memory_leaks() );
231    }
232
233    // init master unit test suite
234    master_test_suite().argc = argc;
235    master_test_suite().argv = argv;
236
237#ifndef BOOST_TEST_DYN_LINK
238
239#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
240    if( !init_unit_test() )
241        throw setup_error( BOOST_TEST_L("test tree initialization error" ) );
242#else
243    test_suite* s = init_unit_test_suite( argc, argv );
244    if( s )
245        master_test_suite().add( s );
246#endif
247
248#endif
249
250}
251
252//____________________________________________________________________________//
253
254void
255register_test_unit( test_case* tc )
256{
257    if( tc->p_id != INV_TEST_UNIT_ID )
258        throw setup_error( BOOST_TEST_L( "test case already registered" ) );
259
260    test_unit_id new_id = s_frk_impl().m_next_test_case_id;
261
262    if( new_id == MAX_TEST_CASE_ID )
263        throw setup_error( BOOST_TEST_L( "too many test cases" ) );
264
265    typedef framework_impl::test_unit_store::value_type map_value_type;
266
267    s_frk_impl().m_test_units.insert( map_value_type( new_id, tc ) );
268    s_frk_impl().m_next_test_case_id++;
269
270    s_frk_impl().set_tu_id( *tc, new_id );
271}
272
273//____________________________________________________________________________//
274
275void
276register_test_unit( test_suite* ts )
277{
278    if( ts->p_id != INV_TEST_UNIT_ID )
279        throw setup_error( BOOST_TEST_L( "test suite already registered" ) );
280
281    test_unit_id new_id = s_frk_impl().m_next_test_suite_id;
282
283    if( new_id == MAX_TEST_SUITE_ID )
284        throw setup_error( BOOST_TEST_L( "too many test suites" ) );
285
286    typedef framework_impl::test_unit_store::value_type map_value_type;
287    s_frk_impl().m_test_units.insert( map_value_type( new_id, ts ) );
288    s_frk_impl().m_next_test_suite_id++;
289
290    s_frk_impl().set_tu_id( *ts, new_id );
291}
292
293//____________________________________________________________________________//
294
295void
296register_observer( test_observer& to )
297{
298    s_frk_impl().m_observers.insert( &to );
299}
300
301//____________________________________________________________________________//
302
303void
304deregister_observer( test_observer& to )
305{
306    s_frk_impl().m_observers.erase( &to );
307}
308
309//____________________________________________________________________________//
310
311void
312reset_observers()
313{
314    s_frk_impl().m_observers.clear();
315}
316
317//____________________________________________________________________________//
318
319master_test_suite_t&
320master_test_suite()
321{
322    if( !s_frk_impl().m_master_test_suite )
323        s_frk_impl().m_master_test_suite = new master_test_suite_t;
324
325    return *s_frk_impl().m_master_test_suite;
326}
327
328//____________________________________________________________________________//
329
330test_case const&
331current_test_case()
332{
333    return get<test_case>( s_frk_impl().m_curr_test_case );
334}
335
336//____________________________________________________________________________//
337
338test_unit const&
339get( test_unit_id id, test_unit_type t )
340{
341    test_unit const* res = s_frk_impl().m_test_units[id];
342
343    if( (res->p_type & t) == 0 )
344        throw internal_error( "Invalid test unit type" );
345
346    return *res;
347}
348
349//____________________________________________________________________________//
350
351void
352run( test_unit_id id, bool continue_test )
353{
354    if( id == INV_TEST_UNIT_ID )
355        id = master_test_suite().p_id;
356
357    test_case_counter tcc;
358    traverse_test_tree( id, tcc );
359
360    if( tcc.m_count == 0 )
361        throw setup_error( BOOST_TEST_L( "test tree is empty" ) );
362
363    bool    call_start_finish   = !continue_test || !s_frk_impl().m_test_in_progress;
364    bool    was_in_progress     = s_frk_impl().m_test_in_progress;
365
366    s_frk_impl().m_test_in_progress = true;
367
368    if( call_start_finish ) {
369        BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers ) {
370            boost::execution_monitor em;
371
372            try {
373                em.execute( ut_detail::test_start_caller( to, tcc.m_count ) );
374            }
375            catch( execution_exception const& ex )  {
376                throw setup_error( ex.what() );
377            }
378        }
379    }
380
381    switch( runtime_config::random_seed() ) {
382    case 0:
383        break;
384    case 1: {
385        unsigned int seed = (unsigned int)std::time( 0 );
386        BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << seed );
387        std::srand( seed );
388        break;
389    }
390    default:
391        BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << runtime_config::random_seed() );
392        std::srand( runtime_config::random_seed() );
393    }
394
395    try {
396        traverse_test_tree( id, s_frk_impl() );
397    }
398    catch( test_being_aborted const& ) {
399        // abort already reported
400    }
401
402    if( call_start_finish ) {
403        BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
404            to->test_finish();
405    }
406
407    s_frk_impl().m_test_in_progress = was_in_progress;
408}
409
410//____________________________________________________________________________//
411
412void
413run( test_unit const* tu, bool continue_test )
414{
415    run( tu->p_id, continue_test );
416}
417
418//____________________________________________________________________________//
419
420void
421assertion_result( bool passed )
422{
423    BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
424        to->assertion_result( passed );
425}
426
427//____________________________________________________________________________//
428
429void
430exception_caught( execution_exception const& ex )
431{
432    BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
433        to->exception_caught( ex );
434}
435
436//____________________________________________________________________________//
437
438void
439test_unit_aborted( test_unit const& tu )
440{
441    BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
442        to->test_unit_aborted( tu );
443}
444
445//____________________________________________________________________________//
446
447} // namespace framework
448
449} // namespace unit_test
450
451} // namespace boost
452
453//____________________________________________________________________________//
454
455#include <boost/test/detail/enable_warnings.hpp>
456
457// ***************************************************************************
458//  Revision History :
459//
460//  $Log: framework.ipp,v $
461//  Revision 1.10  2006/03/19 07:27:52  rogeeff
462//  streamline test setup error message
463//
464//  Revision 1.9  2006/01/30 07:29:49  rogeeff
465//  split memory leaks detection API in two to get more functions with better defined roles
466//
467//  Revision 1.8  2005/12/17 02:34:11  rogeeff
468//  *** empty log message ***
469//
470//  Revision 1.7  2005/12/14 05:35:57  rogeeff
471//  DLL support implemented
472//  Alternative init API introduced
473//
474//  Revision 1.6  2005/05/08 08:55:09  rogeeff
475//  typos and missing descriptions fixed
476//
477//  Revision 1.5  2005/04/05 07:23:20  rogeeff
478//  restore default
479//
480//  Revision 1.4  2005/04/05 06:11:37  rogeeff
481//  memory leak allocation point detection\nextra help with _WIN32_WINNT
482//
483//  Revision 1.3  2005/03/23 21:02:19  rogeeff
484//  Sunpro CC 5.3 fixes
485//
486//  Revision 1.2  2005/02/21 10:12:18  rogeeff
487//  Support for random order of test cases implemented
488//
489//  Revision 1.1  2005/02/20 08:27:07  rogeeff
490//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
491//
492// ***************************************************************************
493
494#endif // BOOST_TEST_FRAMEWORK_IPP_021005GER
Note: See TracBrowser for help on using the repository browser.