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