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