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 /// Defines @ref boost::unit_test::test_unit "test_unit", @ref boost::unit_test::test_case "test_case",
10 /// @ref boost::unit_test::test_suite "test_suite" and @ref boost::unit_test::master_test_suite_t "master_test_suite_t"
11 // ***************************************************************************
12
13 #ifndef BOOST_TEST_TREE_TEST_UNIT_HPP_100211GER
14 #define BOOST_TEST_TREE_TEST_UNIT_HPP_100211GER
15
16 // Boost.Test
17 #include <boost/test/detail/config.hpp>
18 #include <boost/test/detail/global_typedef.hpp>
19 #include <boost/test/detail/fwd_decl.hpp>
20
21 #include <boost/test/tree/decorator.hpp>
22 #include <boost/test/tree/fixture.hpp>
23 #include <boost/test/framework.hpp>
24
25 #include <boost/test/tools/assertion_result.hpp>
26
27 #include <boost/test/utils/class_properties.hpp>
28
29 // Boost
30 #include <boost/function/function0.hpp>
31 #include <boost/function/function1.hpp>
32
33 // STL
34 #include <vector>
35 #include <string>
36 #include <map>
37
38 #include <boost/test/detail/suppress_warnings.hpp>
39
40 //____________________________________________________________________________//
41
42 namespace boost {
43 namespace unit_test {
44
45 namespace framework {
46 class state;
47 }
48
49 // ************************************************************************** //
50 // ************** test_unit ************** //
51 // ************************************************************************** //
52
53 typedef std::vector<test_unit_id> test_unit_id_list;
54
55 class BOOST_TEST_DECL test_unit {
56 public:
57 enum { type = TUT_ANY };
58 enum run_status { RS_DISABLED, RS_ENABLED, RS_INHERIT, RS_INVALID };
59
60 typedef std::vector<test_unit_id> id_list;
61 typedef std::vector<test_unit_fixture_ptr> fixture_list_t;
62 typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework::state)) id_t;
63 typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite)) parent_id_t;
64 typedef BOOST_READONLY_PROPERTY(id_list,(test_unit)) id_list_t;
65 typedef std::vector<decorator::base_ptr> decor_list_t;
66 typedef BOOST_READONLY_PROPERTY(std::vector<std::string>,(test_unit)) label_list_t;
67
68 typedef boost::function<test_tools::assertion_result (test_unit_id)> precondition_t;
69 typedef BOOST_READONLY_PROPERTY(std::vector<precondition_t>,(test_unit)) precond_list_t;
70
71 // preconditions management
72 void depends_on( test_unit* tu );
73 void add_precondition( precondition_t const& );
74 test_tools::assertion_result check_preconditions() const;
75
76 // labels management
77 void add_label( const_string l );
78 bool has_label( const_string l ) const;
79
80 // helper access methods
81 void increase_exp_fail( counter_t num );
is_enabled() const82 bool is_enabled() const { return p_run_status == RS_ENABLED; }
83 std::string full_name() const;
84
85 // Public r/o properties
86 test_unit_type const p_type; ///< type for this test unit
87 const_string const p_type_name; ///< "case"/"suite"/"module"
88 const_string const p_file_name;
89 std::size_t const p_line_num;
90 id_t p_id; ///< unique id for this test unit
91 parent_id_t p_parent_id; ///< parent test suite id
92 label_list_t p_labels; ///< list of labels associated with this test unit
93
94 id_list_t p_dependencies; ///< list of test units this one depends on
95 precond_list_t p_preconditions; ///< user supplied preconditions for this test unit;
96
97 // Public r/w properties
98 readwrite_property<std::string> p_name; ///< name for this test unit
99 readwrite_property<std::string> p_description; ///< description for this test unit
100 readwrite_property<unsigned> p_timeout; ///< timeout for the test unit execution in seconds
101 readwrite_property<counter_t> p_expected_failures; ///< number of expected failures in this test unit
102
103 readwrite_property<run_status> p_default_status; ///< run status obtained by this unit during setup phase
104 readwrite_property<run_status> p_run_status; ///< run status assigned to this unit before execution phase after applying all filters
105
106 readwrite_property<counter_t> p_sibling_rank; ///< rank of this test unit amoung siblings of the same parent
107
108 readwrite_property<decor_list_t> p_decorators; ///< automatically assigned decorators; execution is delayed till framework::finalize_setup_phase function
109 readwrite_property<fixture_list_t> p_fixtures; ///< fixtures associated with this test unit
110
111 protected:
112 ~test_unit();
113 // Constructor
114 test_unit( const_string tu_name, const_string tc_file, std::size_t tc_line, test_unit_type t );
115 // Master test suite constructor
116 explicit test_unit( const_string module_name );
117 };
118
119 // ************************************************************************** //
120 // ************** test_unit_generator ************** //
121 // ************************************************************************** //
122
123 class BOOST_TEST_DECL test_unit_generator {
124 public:
125 virtual test_unit* next() const = 0;
126
127 protected:
~test_unit_generator()128 BOOST_TEST_PROTECTED_VIRTUAL ~test_unit_generator() {}
129 };
130
131 // ************************************************************************** //
132 // ************** test_case ************** //
133 // ************************************************************************** //
134
135 class BOOST_TEST_DECL test_case : public test_unit {
136 public:
137 enum { type = TUT_CASE };
138
139 // Constructor
140 test_case( const_string tc_name, boost::function<void ()> const& test_func );
141 test_case( const_string tc_name, const_string tc_file, std::size_t tc_line, boost::function<void ()> const& test_func );
142
143 // Public property
144 typedef BOOST_READONLY_PROPERTY(boost::function<void ()>,(test_case)) test_func;
145
146 test_func p_test_func;
147
148 private:
149 friend class framework::state;
~test_case()150 ~test_case() {}
151 };
152
153 // ************************************************************************** //
154 // ************** test_suite ************** //
155 // ************************************************************************** //
156
157 //! Class representing test suites
158 class BOOST_TEST_DECL test_suite : public test_unit {
159 public:
160 enum { type = TUT_SUITE };
161
162 // Constructor
163 explicit test_suite( const_string ts_name, const_string ts_file, std::size_t ts_line );
164
165 // test unit list management
166
167 /*!@brief Adds a test unit to a test suite.
168 *
169 * It is possible to specify the timeout and the expected failures.
170 */
171 void add( test_unit* tu, counter_t expected_failures = 0, unsigned timeout = 0 );
172
173 /// @overload
174 void add( test_unit_generator const& gen, unsigned timeout = 0 );
175
176 /// @overload
177 void add( test_unit_generator const& gen, decorator::collector_t& decorators );
178
179 /// @overload
180 void add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators );
181
182 //! Removes a test from the test suite.
183 void remove( test_unit_id id );
184
185 //! Generates all the delayed test_units from the generators
186 void generate( );
187
188 //! Check for duplicates name in test cases
189 //!
190 //! Raises a setup_error if there are duplicates
191 void check_for_duplicate_test_cases();
192
193 // access methods
194 test_unit_id get( const_string tu_name ) const;
size() const195 std::size_t size() const { return m_children.size(); }
196
197 protected:
198 // Master test suite constructor
199 explicit test_suite( const_string module_name );
200
201 friend BOOST_TEST_DECL
202 void traverse_test_tree( test_suite const&, test_tree_visitor&, bool );
203 friend class framework::state;
~test_suite()204 virtual ~test_suite() {}
205
206 typedef std::multimap<counter_t,test_unit_id> children_per_rank;
207 // Data members
208
209 test_unit_id_list m_children;
210 children_per_rank m_ranked_children; ///< maps child sibling rank to list of children with that rank
211
212 std::vector< std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > > m_generators; /// lazy evaluation
213 };
214
215 // ************************************************************************** //
216 // ************** master_test_suite ************** //
217 // ************************************************************************** //
218
219 class BOOST_TEST_DECL master_test_suite_t : public test_suite {
220 private:
221 master_test_suite_t();
222 master_test_suite_t(const master_test_suite_t&); // undefined
223 master_test_suite_t& operator=(master_test_suite_t const &); // undefined
224
225 public:
226 // Data members
227 int argc;
228 char** argv;
229
230 friend BOOST_TEST_DECL master_test_suite_t& boost::unit_test::framework::master_test_suite();
231 };
232
233 // ************************************************************************** //
234 // ************** user_tc_method_invoker ************** //
235 // ************************************************************************** //
236
237 namespace ut_detail {
238
239 BOOST_TEST_DECL std::string normalize_test_case_name( const_string tu_name );
240
241 //____________________________________________________________________________//
242
243 template<typename InstanceType,typename UserTestCase>
244 struct user_tc_method_invoker {
245 typedef void (UserTestCase::*TestMethod )();
246
user_tc_method_invokerboost::unit_test::ut_detail::user_tc_method_invoker247 user_tc_method_invoker( shared_ptr<InstanceType> inst, TestMethod test_method )
248 : m_inst( inst ), m_test_method( test_method ) {}
249
operator ()boost::unit_test::ut_detail::user_tc_method_invoker250 void operator()() { ((*m_inst).*m_test_method)(); }
251
252 shared_ptr<InstanceType> m_inst;
253 TestMethod m_test_method;
254 };
255
256 } // namespace ut_detail
257
258 // ************************************************************************** //
259 // ************** make_test_case ************** //
260 // ************************************************************************** //
261
262 inline test_case*
make_test_case(boost::function<void ()> const & test_func,const_string tc_name,const_string tc_file,std::size_t tc_line)263 make_test_case( boost::function<void ()> const& test_func, const_string tc_name, const_string tc_file, std::size_t tc_line )
264 {
265 return new test_case( ut_detail::normalize_test_case_name( tc_name ), tc_file, tc_line, test_func );
266 }
267
268 //____________________________________________________________________________//
269
270 template<typename UserTestCase, typename InstanceType>
271 inline test_case*
make_test_case(void (UserTestCase::* test_method)(),const_string tc_name,const_string tc_file,std::size_t tc_line,boost::shared_ptr<InstanceType> user_test_case)272 make_test_case( void (UserTestCase::* test_method )(),
273 const_string tc_name,
274 const_string tc_file,
275 std::size_t tc_line,
276 boost::shared_ptr<InstanceType> user_test_case )
277 {
278 return new test_case( ut_detail::normalize_test_case_name( tc_name ),
279 tc_file,
280 tc_line,
281 ut_detail::user_tc_method_invoker<InstanceType,UserTestCase>( user_test_case, test_method ) );
282 }
283
284 //____________________________________________________________________________//
285
286 } // namespace unit_test
287 } // namespace boost
288
289 #include <boost/test/detail/enable_warnings.hpp>
290
291 #endif // BOOST_TEST_TREE_TEST_UNIT_HPP_100211GER
292