Chris@16
|
1 // (C) Copyright Gennadiy Rozental 2001-2008.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
3 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 // See http://www.boost.org/libs/test for the library home page.
|
Chris@16
|
7 //
|
Chris@16
|
8 // File : $RCSfile$
|
Chris@16
|
9 //
|
Chris@101
|
10 // Version : $Revision$
|
Chris@16
|
11 //
|
Chris@16
|
12 // Description : defines test_unit, test_case, test_case_results, test_suite and test_tree_visitor
|
Chris@16
|
13 // ***************************************************************************
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
|
Chris@16
|
16 #define BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
|
Chris@16
|
17
|
Chris@16
|
18 // Boost.Test
|
Chris@16
|
19 #include <boost/test/detail/config.hpp>
|
Chris@16
|
20 #include <boost/test/detail/global_typedef.hpp>
|
Chris@16
|
21 #include <boost/test/utils/class_properties.hpp>
|
Chris@16
|
22 #include <boost/test/utils/callback.hpp>
|
Chris@16
|
23 #include <boost/test/detail/fwd_decl.hpp>
|
Chris@16
|
24 #include <boost/test/detail/workaround.hpp>
|
Chris@16
|
25 #include <boost/test/test_observer.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 // Boost
|
Chris@16
|
28 #include <boost/shared_ptr.hpp>
|
Chris@16
|
29 #include <boost/mpl/for_each.hpp>
|
Chris@16
|
30 #include <boost/mpl/identity.hpp>
|
Chris@16
|
31 #include <boost/type.hpp>
|
Chris@16
|
32 #include <boost/type_traits/is_const.hpp>
|
Chris@16
|
33
|
Chris@16
|
34 // STL
|
Chris@16
|
35 #include <typeinfo> // for typeid
|
Chris@16
|
36 #include <string> // for std::string
|
Chris@16
|
37 #include <list> // for std::list
|
Chris@16
|
38 #include <vector> // for std::vector
|
Chris@16
|
39
|
Chris@16
|
40 #include <boost/test/detail/suppress_warnings.hpp>
|
Chris@16
|
41
|
Chris@16
|
42 //____________________________________________________________________________//
|
Chris@16
|
43
|
Chris@16
|
44 namespace boost {
|
Chris@16
|
45
|
Chris@16
|
46 namespace unit_test {
|
Chris@16
|
47
|
Chris@16
|
48 // ************************************************************************** //
|
Chris@16
|
49 // ************** test_unit ************** //
|
Chris@16
|
50 // ************************************************************************** //
|
Chris@16
|
51
|
Chris@16
|
52 class BOOST_TEST_DECL test_unit {
|
Chris@16
|
53 public:
|
Chris@16
|
54 enum { type = tut_any };
|
Chris@16
|
55
|
Chris@16
|
56 // Constructor
|
Chris@16
|
57 test_unit( const_string tu_name, test_unit_type t );
|
Chris@16
|
58
|
Chris@16
|
59 // dependencies management
|
Chris@16
|
60 void depends_on( test_unit* tu );
|
Chris@16
|
61 bool check_dependencies() const;
|
Chris@16
|
62
|
Chris@16
|
63 // Public r/o properties
|
Chris@16
|
64 typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework_impl)) id_t;
|
Chris@16
|
65 typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite)) parent_id_t;
|
Chris@16
|
66 readonly_property<test_unit_type> p_type; // type for this test unit
|
Chris@16
|
67 readonly_property<const_string> p_type_name; // "case"/"suite"
|
Chris@16
|
68 id_t p_id; // unique id for this test unit
|
Chris@16
|
69 parent_id_t p_parent_id; // parent test suite id
|
Chris@16
|
70
|
Chris@16
|
71 // Public r/w properties
|
Chris@16
|
72 readwrite_property<std::string> p_name; // name for this test unit
|
Chris@16
|
73 readwrite_property<unsigned> p_timeout; // timeout for the test unit execution
|
Chris@16
|
74 readwrite_property<counter_t> p_expected_failures; // number of expected failures in this test unit
|
Chris@16
|
75 mutable readwrite_property<bool> p_enabled; // enabled status for this unit
|
Chris@16
|
76
|
Chris@16
|
77 void increase_exp_fail( unsigned num );
|
Chris@16
|
78
|
Chris@16
|
79 protected:
|
Chris@16
|
80 ~test_unit();
|
Chris@16
|
81
|
Chris@16
|
82 private:
|
Chris@16
|
83 // Data members
|
Chris@16
|
84 std::list<test_unit_id> m_dependencies;
|
Chris@16
|
85 };
|
Chris@16
|
86
|
Chris@16
|
87 // ************************************************************************** //
|
Chris@16
|
88 // ************** test_case_generator ************** //
|
Chris@16
|
89 // ************************************************************************** //
|
Chris@16
|
90
|
Chris@16
|
91 class BOOST_TEST_DECL test_unit_generator {
|
Chris@16
|
92 public:
|
Chris@16
|
93 virtual test_unit* next() const = 0;
|
Chris@16
|
94
|
Chris@16
|
95 protected:
|
Chris@16
|
96 BOOST_TEST_PROTECTED_VIRTUAL ~test_unit_generator() {}
|
Chris@16
|
97 };
|
Chris@16
|
98
|
Chris@16
|
99 // ************************************************************************** //
|
Chris@16
|
100 // ************** test_case ************** //
|
Chris@16
|
101 // ************************************************************************** //
|
Chris@16
|
102
|
Chris@16
|
103 class BOOST_TEST_DECL test_case : public test_unit {
|
Chris@16
|
104 public:
|
Chris@16
|
105 enum { type = tut_case };
|
Chris@16
|
106
|
Chris@16
|
107 // Constructor
|
Chris@16
|
108 test_case( const_string tc_name, callback0<> const& test_func );
|
Chris@16
|
109
|
Chris@16
|
110 // Access methods
|
Chris@16
|
111 callback0<> const& test_func() const { return m_test_func; }
|
Chris@16
|
112
|
Chris@16
|
113 private:
|
Chris@16
|
114 friend class framework_impl;
|
Chris@16
|
115 ~test_case() {}
|
Chris@16
|
116
|
Chris@16
|
117 // BOOST_MSVC <= 1200 have problems with callback as property
|
Chris@16
|
118 // Data members
|
Chris@16
|
119 callback0<> m_test_func;
|
Chris@16
|
120 };
|
Chris@16
|
121
|
Chris@16
|
122 // ************************************************************************** //
|
Chris@16
|
123 // ************** test_suite ************** //
|
Chris@16
|
124 // ************************************************************************** //
|
Chris@16
|
125
|
Chris@16
|
126 class BOOST_TEST_DECL test_suite : public test_unit {
|
Chris@16
|
127 public:
|
Chris@16
|
128 enum { type = tut_suite };
|
Chris@16
|
129
|
Chris@16
|
130 // Constructor
|
Chris@16
|
131 explicit test_suite( const_string ts_name );
|
Chris@16
|
132
|
Chris@16
|
133 // test unit list management
|
Chris@16
|
134 void add( test_unit* tu, counter_t expected_failures = 0, unsigned timeout = 0 );
|
Chris@16
|
135 void add( test_unit_generator const& gen, unsigned timeout = 0 );
|
Chris@16
|
136 void remove( test_unit_id id );
|
Chris@16
|
137
|
Chris@16
|
138 // access methods
|
Chris@16
|
139 test_unit_id get( const_string tu_name ) const;
|
Chris@16
|
140 std::size_t size() const { return m_members.size(); }
|
Chris@16
|
141
|
Chris@16
|
142 protected:
|
Chris@16
|
143 friend BOOST_TEST_DECL
|
Chris@16
|
144 void traverse_test_tree( test_suite const&, test_tree_visitor& );
|
Chris@16
|
145 friend class framework_impl;
|
Chris@16
|
146 virtual ~test_suite() {}
|
Chris@16
|
147
|
Chris@16
|
148 // Data members
|
Chris@16
|
149 std::vector<test_unit_id> m_members;
|
Chris@16
|
150 };
|
Chris@16
|
151
|
Chris@16
|
152 // ************************************************************************** //
|
Chris@16
|
153 // ************** master_test_suite ************** //
|
Chris@16
|
154 // ************************************************************************** //
|
Chris@16
|
155
|
Chris@16
|
156 class BOOST_TEST_DECL master_test_suite_t : public test_suite {
|
Chris@16
|
157 public:
|
Chris@16
|
158 master_test_suite_t() : test_suite( "Master Test Suite" )
|
Chris@16
|
159 , argc( 0 )
|
Chris@16
|
160 , argv( 0 )
|
Chris@16
|
161 {}
|
Chris@16
|
162
|
Chris@16
|
163 // Data members
|
Chris@16
|
164 int argc;
|
Chris@16
|
165 char** argv;
|
Chris@16
|
166 };
|
Chris@16
|
167
|
Chris@16
|
168
|
Chris@16
|
169 // ************************************************************************** //
|
Chris@16
|
170 // ************** test_tree_visitor ************** //
|
Chris@16
|
171 // ************************************************************************** //
|
Chris@16
|
172
|
Chris@16
|
173 class BOOST_TEST_DECL test_tree_visitor {
|
Chris@16
|
174 public:
|
Chris@16
|
175 // test tree visitor interface
|
Chris@16
|
176 virtual void visit( test_case const& ) {}
|
Chris@16
|
177 virtual bool test_suite_start( test_suite const& ) { return true; }
|
Chris@16
|
178 virtual void test_suite_finish( test_suite const& ) {}
|
Chris@16
|
179
|
Chris@16
|
180 protected:
|
Chris@16
|
181 BOOST_TEST_PROTECTED_VIRTUAL ~test_tree_visitor() {}
|
Chris@16
|
182 };
|
Chris@16
|
183
|
Chris@16
|
184 // ************************************************************************** //
|
Chris@16
|
185 // ************** traverse_test_tree ************** //
|
Chris@16
|
186 // ************************************************************************** //
|
Chris@16
|
187
|
Chris@16
|
188 BOOST_TEST_DECL void traverse_test_tree( test_case const&, test_tree_visitor& );
|
Chris@16
|
189 BOOST_TEST_DECL void traverse_test_tree( test_suite const&, test_tree_visitor& );
|
Chris@16
|
190 BOOST_TEST_DECL void traverse_test_tree( test_unit_id , test_tree_visitor& );
|
Chris@16
|
191
|
Chris@16
|
192 //____________________________________________________________________________//
|
Chris@16
|
193
|
Chris@16
|
194 inline void
|
Chris@16
|
195 traverse_test_tree( test_unit const& tu, test_tree_visitor& V )
|
Chris@16
|
196 {
|
Chris@16
|
197 if( tu.p_type == tut_case )
|
Chris@16
|
198 traverse_test_tree( static_cast<test_case const&>( tu ), V );
|
Chris@16
|
199 else
|
Chris@16
|
200 traverse_test_tree( static_cast<test_suite const&>( tu ), V );
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 //____________________________________________________________________________//
|
Chris@16
|
204
|
Chris@16
|
205 // ************************************************************************** //
|
Chris@16
|
206 // ************** test_case_counter ************** //
|
Chris@16
|
207 // ************************************************************************** //
|
Chris@16
|
208
|
Chris@16
|
209 class test_case_counter : public test_tree_visitor {
|
Chris@16
|
210 public:
|
Chris@16
|
211 // Constructor
|
Chris@16
|
212 test_case_counter() : p_count( 0 ) {}
|
Chris@16
|
213
|
Chris@16
|
214 BOOST_READONLY_PROPERTY( counter_t, (test_case_counter)) p_count;
|
Chris@16
|
215 private:
|
Chris@16
|
216 // test tree visitor interface
|
Chris@16
|
217 virtual void visit( test_case const& );
|
Chris@16
|
218 virtual bool test_suite_start( test_suite const& ts ) { return ts.p_enabled; }
|
Chris@16
|
219 };
|
Chris@16
|
220
|
Chris@16
|
221 // ************************************************************************** //
|
Chris@16
|
222 // ************** test_being_aborted ************** //
|
Chris@16
|
223 // ************************************************************************** //
|
Chris@16
|
224
|
Chris@16
|
225 struct BOOST_TEST_DECL test_being_aborted {};
|
Chris@16
|
226
|
Chris@16
|
227 // ************************************************************************** //
|
Chris@16
|
228 // ************** object generators ************** //
|
Chris@16
|
229 // ************************************************************************** //
|
Chris@16
|
230
|
Chris@16
|
231 namespace ut_detail {
|
Chris@16
|
232
|
Chris@16
|
233 BOOST_TEST_DECL std::string normalize_test_case_name( const_string tu_name );
|
Chris@16
|
234
|
Chris@16
|
235 template<typename InstanceType,typename UserTestCase>
|
Chris@16
|
236 struct user_tc_method_invoker {
|
Chris@16
|
237 typedef void (UserTestCase::*TestMethod )();
|
Chris@16
|
238
|
Chris@16
|
239 user_tc_method_invoker( shared_ptr<InstanceType> inst, TestMethod test_method )
|
Chris@16
|
240 : m_inst( inst ), m_test_method( test_method ) {}
|
Chris@16
|
241
|
Chris@16
|
242 void operator()() { ((*m_inst).*m_test_method)(); }
|
Chris@16
|
243
|
Chris@16
|
244 shared_ptr<InstanceType> m_inst;
|
Chris@16
|
245 TestMethod m_test_method;
|
Chris@16
|
246 };
|
Chris@16
|
247
|
Chris@16
|
248 } // namespace ut_detail
|
Chris@16
|
249
|
Chris@16
|
250 //____________________________________________________________________________//
|
Chris@16
|
251
|
Chris@16
|
252 inline test_case*
|
Chris@16
|
253 make_test_case( callback0<> const& test_func, const_string tc_name )
|
Chris@16
|
254 {
|
Chris@16
|
255 return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func );
|
Chris@16
|
256 }
|
Chris@16
|
257
|
Chris@16
|
258 //____________________________________________________________________________//
|
Chris@16
|
259
|
Chris@16
|
260 template<typename UserTestCase, typename InstanceType>
|
Chris@16
|
261 inline test_case*
|
Chris@16
|
262 make_test_case( void (UserTestCase::* test_method )(),
|
Chris@16
|
263 const_string tc_name,
|
Chris@16
|
264 boost::shared_ptr<InstanceType> user_test_case )
|
Chris@16
|
265 {
|
Chris@16
|
266 return new test_case( ut_detail::normalize_test_case_name( tc_name ),
|
Chris@16
|
267 ut_detail::user_tc_method_invoker<InstanceType,UserTestCase>( user_test_case, test_method ) );
|
Chris@16
|
268 }
|
Chris@16
|
269
|
Chris@16
|
270 //____________________________________________________________________________//
|
Chris@16
|
271
|
Chris@16
|
272 // ************************************************************************** //
|
Chris@16
|
273 // ************** auto_test_unit_registrar ************** //
|
Chris@16
|
274 // ************************************************************************** //
|
Chris@16
|
275
|
Chris@16
|
276 namespace ut_detail {
|
Chris@16
|
277
|
Chris@16
|
278 struct BOOST_TEST_DECL auto_test_unit_registrar
|
Chris@16
|
279 {
|
Chris@16
|
280 // Constructors
|
Chris@16
|
281 auto_test_unit_registrar( test_case* tc, counter_t exp_fail );
|
Chris@16
|
282 explicit auto_test_unit_registrar( const_string ts_name );
|
Chris@16
|
283 explicit auto_test_unit_registrar( test_unit_generator const& tc_gen );
|
Chris@16
|
284 explicit auto_test_unit_registrar( int );
|
Chris@16
|
285
|
Chris@16
|
286 private:
|
Chris@16
|
287 static std::list<test_suite*>& curr_ts_store();
|
Chris@16
|
288 };
|
Chris@16
|
289
|
Chris@16
|
290 //____________________________________________________________________________//
|
Chris@16
|
291
|
Chris@16
|
292 template<typename T>
|
Chris@16
|
293 struct auto_tc_exp_fail {
|
Chris@16
|
294 auto_tc_exp_fail() : m_value( 0 ) {}
|
Chris@16
|
295
|
Chris@16
|
296 explicit auto_tc_exp_fail( unsigned v )
|
Chris@16
|
297 : m_value( v )
|
Chris@16
|
298 {
|
Chris@16
|
299 instance() = this;
|
Chris@16
|
300 }
|
Chris@16
|
301
|
Chris@16
|
302 static auto_tc_exp_fail*& instance()
|
Chris@16
|
303 {
|
Chris@16
|
304 static auto_tc_exp_fail inst;
|
Chris@16
|
305 static auto_tc_exp_fail* inst_ptr = &inst;
|
Chris@16
|
306
|
Chris@16
|
307 return inst_ptr;
|
Chris@16
|
308 }
|
Chris@16
|
309
|
Chris@16
|
310 unsigned value() const { return m_value; }
|
Chris@16
|
311
|
Chris@16
|
312 private:
|
Chris@16
|
313 // Data members
|
Chris@16
|
314 unsigned m_value;
|
Chris@16
|
315 };
|
Chris@16
|
316
|
Chris@16
|
317 //____________________________________________________________________________//
|
Chris@16
|
318
|
Chris@16
|
319 } // namespace ut_detail
|
Chris@16
|
320
|
Chris@16
|
321 // ************************************************************************** //
|
Chris@16
|
322 // ************** global_fixture ************** //
|
Chris@16
|
323 // ************************************************************************** //
|
Chris@16
|
324
|
Chris@16
|
325 class BOOST_TEST_DECL global_fixture : public test_observer {
|
Chris@16
|
326 public:
|
Chris@16
|
327 // Constructor
|
Chris@16
|
328 global_fixture();
|
Chris@16
|
329 };
|
Chris@16
|
330
|
Chris@16
|
331 //____________________________________________________________________________//
|
Chris@16
|
332
|
Chris@16
|
333 namespace ut_detail {
|
Chris@16
|
334
|
Chris@16
|
335 template<typename F>
|
Chris@16
|
336 struct global_fixture_impl : public global_fixture {
|
Chris@16
|
337 // Constructor
|
Chris@16
|
338 global_fixture_impl(): m_fixure( 0 ) {}
|
Chris@16
|
339
|
Chris@16
|
340 // test observer interface
|
Chris@16
|
341 virtual void test_start( counter_t ) { m_fixure = new F; }
|
Chris@16
|
342 virtual void test_finish() { delete m_fixure; m_fixure = 0; }
|
Chris@16
|
343 virtual void test_aborted() { delete m_fixure; m_fixure = 0; }
|
Chris@16
|
344
|
Chris@16
|
345 private:
|
Chris@16
|
346 // Data members
|
Chris@16
|
347 F* m_fixure;
|
Chris@16
|
348 };
|
Chris@16
|
349
|
Chris@16
|
350 // ************************************************************************** //
|
Chris@16
|
351 // ************** test_case_template_invoker ************** //
|
Chris@16
|
352 // ************************************************************************** //
|
Chris@16
|
353
|
Chris@16
|
354 template<typename TestCaseTemplate,typename TestType>
|
Chris@16
|
355 class test_case_template_invoker {
|
Chris@16
|
356 public:
|
Chris@16
|
357 void operator()() { TestCaseTemplate::run( (boost::type<TestType>*)0 ); }
|
Chris@16
|
358 };
|
Chris@16
|
359
|
Chris@16
|
360 // ************************************************************************** //
|
Chris@16
|
361 // ************** generate_test_case_4_type ************** //
|
Chris@16
|
362 // ************************************************************************** //
|
Chris@16
|
363
|
Chris@16
|
364 template<typename Generator,typename TestCaseTemplate>
|
Chris@16
|
365 struct generate_test_case_4_type {
|
Chris@16
|
366 explicit generate_test_case_4_type( const_string tc_name, Generator& G )
|
Chris@16
|
367 : m_test_case_name( tc_name )
|
Chris@16
|
368 , m_holder( G )
|
Chris@16
|
369 {}
|
Chris@16
|
370
|
Chris@16
|
371 template<typename TestType>
|
Chris@16
|
372 void operator()( mpl::identity<TestType> )
|
Chris@16
|
373 {
|
Chris@16
|
374 std::string full_name;
|
Chris@16
|
375 assign_op( full_name, m_test_case_name, 0 );
|
Chris@16
|
376 full_name += '<';
|
Chris@16
|
377 full_name += typeid(TestType).name();
|
Chris@16
|
378 if( boost::is_const<TestType>::value )
|
Chris@16
|
379 full_name += " const";
|
Chris@16
|
380 full_name += '>';
|
Chris@16
|
381
|
Chris@16
|
382 m_holder.m_test_cases.push_back(
|
Chris@16
|
383 new test_case( full_name, test_case_template_invoker<TestCaseTemplate,TestType>() ) );
|
Chris@16
|
384 }
|
Chris@16
|
385
|
Chris@16
|
386 private:
|
Chris@16
|
387 // Data members
|
Chris@16
|
388 const_string m_test_case_name;
|
Chris@16
|
389 Generator& m_holder;
|
Chris@16
|
390 };
|
Chris@16
|
391
|
Chris@16
|
392 // ************************************************************************** //
|
Chris@16
|
393 // ************** test_case_template ************** //
|
Chris@16
|
394 // ************************************************************************** //
|
Chris@16
|
395
|
Chris@16
|
396 template<typename TestCaseTemplate,typename TestTypesList>
|
Chris@16
|
397 class template_test_case_gen : public test_unit_generator {
|
Chris@16
|
398 public:
|
Chris@16
|
399 // Constructor
|
Chris@16
|
400 template_test_case_gen( const_string tc_name )
|
Chris@16
|
401 {
|
Chris@16
|
402 typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,
|
Chris@16
|
403 TestCaseTemplate
|
Chris@16
|
404 > single_test_gen;
|
Chris@16
|
405 mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, *this ) );
|
Chris@16
|
406 }
|
Chris@16
|
407
|
Chris@16
|
408 virtual test_unit* next() const
|
Chris@16
|
409 {
|
Chris@16
|
410 if( m_test_cases.empty() )
|
Chris@16
|
411 return 0;
|
Chris@16
|
412
|
Chris@16
|
413 test_unit* res = m_test_cases.front();
|
Chris@16
|
414 m_test_cases.pop_front();
|
Chris@16
|
415
|
Chris@16
|
416 return res;
|
Chris@16
|
417 }
|
Chris@16
|
418
|
Chris@16
|
419 // Data members
|
Chris@16
|
420 mutable std::list<test_unit*> m_test_cases;
|
Chris@16
|
421 };
|
Chris@16
|
422
|
Chris@16
|
423 //____________________________________________________________________________//
|
Chris@16
|
424
|
Chris@16
|
425 } // namespace ut_detail
|
Chris@16
|
426
|
Chris@16
|
427 } // unit_test
|
Chris@16
|
428
|
Chris@16
|
429 } // namespace boost
|
Chris@16
|
430
|
Chris@16
|
431 #include <boost/test/detail/enable_warnings.hpp>
|
Chris@16
|
432
|
Chris@16
|
433 #endif // BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
|
Chris@16
|
434
|