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
9 : /// Provides core implementation for Unit Test Framework.
10 : /// Extensions can be provided in separate files
11 : // ***************************************************************************
12 :
13 : #ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
14 : #define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
15 :
16 : // Boost.Test
17 : #include <boost/detail/workaround.hpp>
18 :
19 : #include <boost/test/framework.hpp>
20 : #include <boost/test/results_collector.hpp>
21 :
22 : #include <boost/test/tree/test_unit.hpp>
23 : #include <boost/test/tree/visitor.hpp>
24 : #include <boost/test/tree/traverse.hpp>
25 : #include <boost/test/tree/auto_registration.hpp>
26 : #include <boost/test/tree/global_fixture.hpp>
27 :
28 : #include <boost/test/utils/foreach.hpp>
29 : #include <boost/test/utils/basic_cstring/io.hpp>
30 :
31 : #include <boost/test/unit_test_parameters.hpp>
32 :
33 : // STL
34 : #include <algorithm>
35 : #include <vector>
36 : #include <set>
37 :
38 : #include <boost/test/detail/suppress_warnings.hpp>
39 :
40 : //____________________________________________________________________________//
41 :
42 : namespace boost {
43 : namespace unit_test {
44 :
45 : // ************************************************************************** //
46 : // ************** test_unit ************** //
47 : // ************************************************************************** //
48 :
49 491728 : test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
50 122932 : : p_type( t )
51 122932 : , p_type_name( t == TUT_CASE ? "case" : "suite" )
52 122932 : , p_file_name( file_name )
53 122932 : , p_line_num( line_num )
54 122932 : , p_id( INV_TEST_UNIT_ID )
55 122932 : , p_parent_id( INV_TEST_UNIT_ID )
56 122932 : , p_name( std::string( name.begin(), name.size() ) )
57 122932 : , p_timeout( 0 )
58 122932 : , p_expected_failures( 0 )
59 122932 : , p_default_status( RS_INHERIT )
60 122932 : , p_run_status( RS_INVALID )
61 122932 : , p_sibling_rank(0)
62 0 : {
63 122932 : }
64 :
65 : //____________________________________________________________________________//
66 :
67 730 : test_unit::test_unit( const_string module_name )
68 146 : : p_type( TUT_SUITE )
69 146 : , p_type_name( "module" )
70 146 : , p_line_num( 0 )
71 146 : , p_id( INV_TEST_UNIT_ID )
72 146 : , p_parent_id( INV_TEST_UNIT_ID )
73 146 : , p_name( std::string( module_name.begin(), module_name.size() ) )
74 146 : , p_timeout( 0 )
75 146 : , p_expected_failures( 0 )
76 146 : , p_default_status( RS_INHERIT )
77 146 : , p_run_status( RS_INVALID )
78 146 : , p_sibling_rank(0)
79 0 : {
80 146 : }
81 :
82 : //____________________________________________________________________________//
83 :
84 0 : test_unit::~test_unit()
85 0 : {
86 0 : framework::deregister_test_unit( this );
87 0 : }
88 :
89 : //____________________________________________________________________________//
90 :
91 : void
92 0 : test_unit::depends_on( test_unit* tu )
93 : {
94 0 : BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id,
95 : "Can't add dependency to the master test suite" );
96 :
97 0 : p_dependencies.value.push_back( tu->p_id );
98 0 : }
99 :
100 : //____________________________________________________________________________//
101 :
102 : void
103 0 : test_unit::add_precondition( precondition_t const& pc )
104 : {
105 0 : p_preconditions.value.push_back( pc );
106 0 : }
107 :
108 : //____________________________________________________________________________//
109 :
110 : test_tools::assertion_result
111 1023 : test_unit::check_preconditions() const
112 : {
113 1023 : BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
114 0 : test_unit const& dep = framework::get( dep_id, TUT_ANY );
115 :
116 0 : if( !dep.is_enabled() ) {
117 0 : test_tools::assertion_result res(false);
118 0 : res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
119 0 : return res;
120 0 : }
121 :
122 0 : test_results const& test_rslt = unit_test::results_collector.results( dep_id );
123 0 : if( !test_rslt.passed() ) {
124 0 : test_tools::assertion_result res(false);
125 0 : res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << (test_rslt.skipped() ? "\" was skipped":"\" has failed");
126 0 : return res;
127 0 : }
128 :
129 0 : if( test_rslt.p_test_cases_skipped > 0 ) {
130 0 : test_tools::assertion_result res(false);
131 0 : res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
132 0 : return res;
133 0 : }
134 0 : }
135 :
136 1023 : BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
137 0 : test_tools::assertion_result res = precondition( p_id );
138 0 : if( !res ) {
139 0 : test_tools::assertion_result res_out(false);
140 0 : res_out.message() << "precondition failed";
141 0 : if( !res.has_empty_message() )
142 0 : res_out.message() << ": " << res.message();
143 0 : return res_out;
144 0 : }
145 0 : }
146 :
147 1023 : return true;
148 1023 : }
149 :
150 : //____________________________________________________________________________//
151 :
152 : void
153 0 : test_unit::increase_exp_fail( counter_t num )
154 : {
155 0 : p_expected_failures.value += num;
156 :
157 0 : if( p_parent_id != INV_TEST_UNIT_ID )
158 0 : framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
159 0 : }
160 :
161 : //____________________________________________________________________________//
162 :
163 : std::string
164 21008 : test_unit::full_name() const
165 : {
166 21008 : if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
167 21005 : return p_name;
168 :
169 3 : std::string res = framework::get<test_suite>( p_parent_id ).full_name();
170 3 : res.append("/");
171 :
172 3 : res.append( p_name );
173 :
174 3 : return res;
175 21011 : }
176 :
177 : //____________________________________________________________________________//
178 :
179 : void
180 0 : test_unit::add_label( const_string l )
181 : {
182 0 : p_labels.value.push_back( std::string() + l );
183 0 : }
184 :
185 : //____________________________________________________________________________//
186 :
187 : bool
188 0 : test_unit::has_label( const_string l ) const
189 : {
190 0 : return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
191 : }
192 :
193 : //____________________________________________________________________________//
194 :
195 : // ************************************************************************** //
196 : // ************** test_case ************** //
197 : // ************************************************************************** //
198 :
199 0 : test_case::test_case( const_string name, boost::function<void ()> const& test_func )
200 0 : : test_unit( name, "", 0, static_cast<test_unit_type>(type) )
201 0 : , p_test_func( test_func )
202 0 : {
203 0 : framework::register_test_unit( this );
204 0 : }
205 :
206 : //____________________________________________________________________________//
207 :
208 203524 : test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
209 101762 : : test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
210 101762 : , p_test_func( test_func )
211 101762 : {
212 101762 : framework::register_test_unit( this );
213 203524 : }
214 :
215 : //____________________________________________________________________________//
216 :
217 : // ************************************************************************** //
218 : // ************** test_suite ************** //
219 : // ************************************************************************** //
220 :
221 : //____________________________________________________________________________//
222 :
223 63510 : test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
224 21170 : : test_unit( ut_detail::normalize_test_case_name( name ), file_name, line_num, static_cast<test_unit_type>(type) )
225 63510 : {
226 21170 : framework::register_test_unit( this );
227 42340 : }
228 :
229 : //____________________________________________________________________________//
230 :
231 292 : test_suite::test_suite( const_string module_name )
232 146 : : test_unit( module_name )
233 292 : {
234 146 : framework::register_test_unit( this );
235 146 : }
236 :
237 : //____________________________________________________________________________//
238 :
239 : void
240 122932 : test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
241 : {
242 122932 : tu->p_timeout.value = timeout;
243 :
244 122932 : m_children.push_back( tu->p_id );
245 122932 : tu->p_parent_id.value = p_id;
246 :
247 122932 : if( tu->p_expected_failures != 0 )
248 0 : increase_exp_fail( tu->p_expected_failures );
249 :
250 122932 : if( expected_failures )
251 0 : tu->increase_exp_fail( expected_failures );
252 122932 : }
253 :
254 : //____________________________________________________________________________//
255 :
256 : void
257 0 : test_suite::add( test_unit_generator const& gen, unsigned timeout )
258 : {
259 : test_unit* tu;
260 0 : while((tu = gen.next()) != 0)
261 0 : add( tu, 0, timeout );
262 0 : }
263 :
264 : //____________________________________________________________________________//
265 :
266 : void
267 0 : test_suite::add( test_unit_generator const& gen, decorator::collector_t& decorators )
268 : {
269 : test_unit* tu;
270 0 : while((tu = gen.next()) != 0) {
271 0 : decorators.store_in( *tu );
272 0 : add( tu, 0 );
273 : }
274 0 : decorators.reset();
275 0 : }
276 :
277 : //____________________________________________________________________________//
278 :
279 : void
280 0 : test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
281 : {
282 0 : std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
283 0 : m_generators.push_back(tmp_p);
284 0 : decorators.reset();
285 0 : }
286 :
287 : //____________________________________________________________________________//
288 :
289 : void
290 21316 : test_suite::generate( )
291 : {
292 : typedef std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > element_t;
293 :
294 21316 : for(std::vector<element_t>::iterator it(m_generators.begin()), ite(m_generators.end());
295 21316 : it < ite;
296 0 : ++it)
297 : {
298 : test_unit* tu;
299 0 : while((tu = it->first->next()) != 0) {
300 0 : tu->p_decorators.value.insert( tu->p_decorators.value.end(), it->second.begin(), it->second.end() );
301 : //it->second.store_in( *tu );
302 0 : add( tu, 0 );
303 : }
304 :
305 0 : }
306 21316 : m_generators.clear();
307 :
308 : #if 0
309 : test_unit* tu;
310 : while((tu = gen.next()) != 0) {
311 : decorators.store_in( *tu );
312 : add( tu, 0 );
313 : }
314 : #endif
315 21316 : }
316 :
317 : //____________________________________________________________________________//
318 :
319 : void
320 21316 : test_suite::check_for_duplicate_test_cases() {
321 : // check for clashing names #12597
322 21316 : std::set<std::string> names;
323 144248 : for( test_unit_id_list::const_iterator it(m_children.begin()), ite(m_children.end());
324 144248 : it < ite;
325 122932 : ++it) {
326 122932 : std::string name = framework::get(*it, TUT_ANY).p_name;
327 122932 : std::pair<std::set<std::string>::iterator, bool> ret = names.insert(name);
328 122932 : BOOST_TEST_SETUP_ASSERT(ret.second,
329 : "test unit with name '"
330 : + name
331 : + std::string("' registered multiple times in the test suite '")
332 : + this->p_name.value
333 : + "'");
334 122932 : }
335 :
336 : return;
337 21316 : }
338 :
339 : //____________________________________________________________________________//
340 :
341 : void
342 0 : test_suite::remove( test_unit_id id )
343 : {
344 0 : test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
345 :
346 0 : if( it != m_children.end() )
347 0 : m_children.erase( it );
348 0 : }
349 :
350 : //____________________________________________________________________________//
351 :
352 : test_unit_id
353 21170 : test_suite::get( const_string tu_name ) const
354 : {
355 3069650 : BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
356 1524240 : if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
357 0 : return id;
358 1524240 : }
359 :
360 21170 : return INV_TEST_UNIT_ID;
361 21170 : }
362 :
363 : //____________________________________________________________________________//
364 :
365 : // ************************************************************************** //
366 : // ************** master_test_suite ************** //
367 : // ************************************************************************** //
368 :
369 292 : master_test_suite_t::master_test_suite_t()
370 146 : : test_suite( "Master Test Suite" )
371 146 : , argc( 0 )
372 146 : , argv( 0 )
373 292 : {
374 146 : p_default_status.value = RS_ENABLED;
375 292 : }
376 :
377 : // ************************************************************************** //
378 : // ************** traverse_test_tree ************** //
379 : // ************************************************************************** //
380 :
381 : void
382 307405 : traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
383 : {
384 307405 : if( tc.is_enabled() || ignore_status )
385 307405 : V.visit( tc );
386 307405 : }
387 :
388 : //____________________________________________________________________________//
389 :
390 : void
391 149043 : traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
392 : {
393 : // skip disabled test suite unless we asked to ignore this condition
394 149043 : if( !ignore_status && !suite.is_enabled() )
395 42048 : return;
396 :
397 : // Invoke test_suite_start callback
398 106995 : if( !V.test_suite_start( suite ) )
399 42195 : return;
400 :
401 : // Recurse into children
402 64800 : std::size_t total_children = suite.m_children.size();
403 499080 : for( std::size_t i=0; i < total_children; ) {
404 : // this statement can remove the test unit from this list
405 434280 : traverse_test_tree( suite.m_children[i], V, ignore_status );
406 434280 : if( total_children > suite.m_children.size() )
407 0 : total_children = suite.m_children.size();
408 : else
409 434280 : ++i;
410 : }
411 :
412 : // Invoke test_suite_finish callback
413 64800 : V.test_suite_finish( suite );
414 149043 : }
415 :
416 : //____________________________________________________________________________//
417 :
418 : void
419 435156 : traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
420 : {
421 435156 : if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
422 307405 : traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
423 : else
424 127751 : traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
425 435156 : }
426 :
427 : //____________________________________________________________________________//
428 :
429 : // ************************************************************************** //
430 : // ************** object generators ************** //
431 : // ************************************************************************** //
432 :
433 : namespace ut_detail {
434 :
435 : std::string
436 122932 : normalize_test_case_name( const_string name )
437 : {
438 122932 : std::string norm_name( name.begin(), name.end() );
439 :
440 122932 : if( name[0] == '&' )
441 0 : norm_name = norm_name.substr( 1 );
442 :
443 : // trim spaces
444 122932 : std::size_t first_not_space = norm_name.find_first_not_of(' ');
445 122932 : if( first_not_space ) {
446 0 : norm_name.erase(0, first_not_space);
447 0 : }
448 :
449 122932 : std::size_t last_not_space = norm_name.find_last_not_of(' ');
450 122932 : if( last_not_space !=std::string::npos ) {
451 122932 : norm_name.erase(last_not_space + 1);
452 122932 : }
453 :
454 : // sanitize all chars that might be used in runtime filters
455 : static const char to_replace[] = { ':', '*', '@', '+', '!', '/', ',' };
456 983456 : for(std::size_t index = 0;
457 983456 : index < sizeof(to_replace)/sizeof(to_replace[0]);
458 860524 : index++) {
459 860524 : std::replace(norm_name.begin(), norm_name.end(), to_replace[index], '_');
460 860524 : }
461 :
462 122932 : return norm_name;
463 122932 : }
464 :
465 : //____________________________________________________________________________//
466 :
467 : // ************************************************************************** //
468 : // ************** auto_test_unit_registrar ************** //
469 : // ************************************************************************** //
470 :
471 203524 : auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail )
472 101762 : {
473 101762 : framework::current_auto_test_suite().add( tc, exp_fail );
474 :
475 101762 : decorators.store_in( *tc );
476 101762 : decorators.reset();
477 203524 : }
478 :
479 : //____________________________________________________________________________//
480 :
481 42340 : 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 )
482 21170 : {
483 21170 : test_unit_id id = framework::current_auto_test_suite().get( ts_name );
484 :
485 : test_suite* ts;
486 :
487 21170 : if( id != INV_TEST_UNIT_ID ) {
488 0 : ts = &framework::get<test_suite>( id );
489 0 : BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
490 0 : }
491 : else {
492 21170 : ts = new test_suite( ts_name, ts_file, ts_line );
493 21170 : framework::current_auto_test_suite().add( ts );
494 : }
495 :
496 21170 : decorators.store_in( *ts );
497 21170 : decorators.reset();
498 :
499 21170 : framework::current_auto_test_suite( ts );
500 42340 : }
501 :
502 : //____________________________________________________________________________//
503 :
504 0 : auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_generator, decorator::collector_t& decorators )
505 0 : {
506 0 : framework::current_auto_test_suite().add( tc_generator, decorators );
507 0 : }
508 :
509 : //____________________________________________________________________________//
510 :
511 0 : auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_generator, decorator::collector_t& decorators )
512 0 : {
513 0 : framework::current_auto_test_suite().add( tc_generator, decorators );
514 0 : }
515 :
516 :
517 : //____________________________________________________________________________//
518 :
519 42340 : auto_test_unit_registrar::auto_test_unit_registrar( int )
520 21170 : {
521 21170 : framework::current_auto_test_suite( 0, false );
522 42340 : }
523 :
524 : //____________________________________________________________________________//
525 :
526 : } // namespace ut_detail
527 :
528 : // ************************************************************************** //
529 : // ************** global_fixture ************** //
530 : // ************************************************************************** //
531 :
532 0 : global_fixture::global_fixture(): registered(false)
533 0 : {
534 0 : framework::register_global_fixture( *this );
535 0 : registered = true;
536 0 : }
537 :
538 0 : void global_fixture::unregister_from_framework() {
539 : // not accessing the framework singleton after deregistering -> release
540 : // of the observer from the framework
541 0 : if(registered) {
542 0 : framework::deregister_global_fixture( *this );
543 0 : }
544 0 : registered = false;
545 0 : }
546 :
547 0 : global_fixture::~global_fixture()
548 0 : {
549 0 : this->unregister_from_framework();
550 0 : }
551 :
552 : // ************************************************************************** //
553 : // ************** global_configuration ************** //
554 : // ************************************************************************** //
555 :
556 0 : global_configuration::global_configuration(): registered(false)
557 0 : {
558 0 : framework::register_observer( *this );
559 0 : registered = true;
560 0 : }
561 :
562 0 : void global_configuration::unregister_from_framework()
563 : {
564 : // not accessing the framework singleton after deregistering -> release
565 : // of the observer from the framework
566 0 : if(registered) {
567 0 : framework::deregister_observer( *this );
568 0 : }
569 0 : registered = false;
570 0 : }
571 :
572 0 : global_configuration::~global_configuration()
573 0 : {
574 0 : this->unregister_from_framework();
575 0 : }
576 :
577 : //____________________________________________________________________________//
578 :
579 : } // namespace unit_test
580 : } // namespace boost
581 :
582 : #include <boost/test/detail/enable_warnings.hpp>
583 :
584 : #endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
|