1 //  (C) Copyright Gennadiy Rozental 2001-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 //!@brief generators and helper macros for parameterized tests
10 // ***************************************************************************
11 
12 #ifndef BOOST_TEST_PARAMETERIZED_TEST_HPP_021102GER
13 #define BOOST_TEST_PARAMETERIZED_TEST_HPP_021102GER
14 
15 // Boost.Test
16 #include <boost/test/unit_test_suite.hpp>
17 
18 // Boost
19 #include <boost/type_traits/remove_reference.hpp>
20 #include <boost/type_traits/remove_const.hpp>
21 
22 #include <boost/bind.hpp>
23 #include <boost/function/function1.hpp>
24 
25 #include <boost/test/detail/suppress_warnings.hpp>
26 
27 //____________________________________________________________________________//
28 
29 #define BOOST_PARAM_TEST_CASE( function, begin, end )                      \
30 boost::unit_test::make_test_case( function,                                \
31                                   BOOST_TEST_STRINGIZE( function ),        \
32                                   __FILE__, __LINE__,                      \
33                                   (begin), (end) )                         \
34 /**/
35 
36 #define BOOST_PARAM_CLASS_TEST_CASE( function, tc_instance, begin, end )   \
37 boost::unit_test::make_test_case( function,                                \
38                                   BOOST_TEST_STRINGIZE( function ),        \
39                                   __FILE__, __LINE__,                      \
40                                   (tc_instance),                           \
41                                   (begin), (end) )                         \
42 /**/
43 
44 namespace boost {
45 namespace unit_test {
46 
47 namespace ut_detail {
48 
49 // ************************************************************************** //
50 // **************           param_test_case_generator          ************** //
51 // ************************************************************************** //
52 
53 template<typename ParamType, typename ParamIter>
54 class param_test_case_generator : public test_unit_generator {
55 public:
param_test_case_generator(boost::function<void (ParamType)> const & test_func,const_string tc_name,const_string tc_file,std::size_t tc_line,ParamIter par_begin,ParamIter par_end)56     param_test_case_generator( boost::function<void (ParamType)> const& test_func,
57                                const_string                             tc_name,
58                                const_string                             tc_file,
59                                std::size_t                              tc_line,
60                                ParamIter                                par_begin,
61                                ParamIter                                par_end )
62     : m_test_func( test_func )
63     , m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
64     , m_tc_file( tc_file )
65     , m_tc_line( tc_line )
66     , m_par_begin( par_begin )
67     , m_par_end( par_end )
68     {}
69 
next() const70     virtual test_unit* next() const
71     {
72         if( m_par_begin == m_par_end )
73             return (test_unit*)0;
74 
75         test_unit* res = new test_case( m_tc_name, m_tc_file, m_tc_line, boost::bind( m_test_func, *m_par_begin ) );
76 
77         ++m_par_begin;
78 
79         return res;
80     }
81 
82 private:
83     // Data members
84     boost::function<void (ParamType)>    m_test_func;
85     std::string             m_tc_name;
86     const_string            m_tc_file;
87     std::size_t             m_tc_line;
88     mutable ParamIter       m_par_begin;
89     ParamIter               m_par_end;
90 };
91 
92 //____________________________________________________________________________//
93 
94 template<typename UserTestCase,typename ParamType>
95 struct user_param_tc_method_invoker {
96     typedef void (UserTestCase::*test_method)( ParamType );
97 
98     // Constructor
user_param_tc_method_invokerboost::unit_test::ut_detail::user_param_tc_method_invoker99     user_param_tc_method_invoker( shared_ptr<UserTestCase> inst, test_method test_method )
100     : m_inst( inst ), m_test_method( test_method ) {}
101 
operator ()boost::unit_test::ut_detail::user_param_tc_method_invoker102     void operator()( ParamType p ) { ((*m_inst).*m_test_method)( p ); }
103 
104     // Data members
105     shared_ptr<UserTestCase> m_inst;
106     test_method              m_test_method;
107 };
108 
109 //____________________________________________________________________________//
110 
111 } // namespace ut_detail
112 
113 template<typename ParamType, typename ParamIter>
114 inline ut_detail::param_test_case_generator<ParamType,ParamIter>
make_test_case(boost::function<void (ParamType)> const & test_func,const_string tc_name,const_string tc_file,std::size_t tc_line,ParamIter par_begin,ParamIter par_end)115 make_test_case( boost::function<void (ParamType)> const& test_func,
116                 const_string                             tc_name,
117                 const_string                             tc_file,
118                 std::size_t                              tc_line,
119                 ParamIter                                par_begin,
120                 ParamIter                                par_end )
121 {
122     return ut_detail::param_test_case_generator<ParamType,ParamIter>( test_func, tc_name, tc_file, tc_line, par_begin, par_end );
123 }
124 
125 //____________________________________________________________________________//
126 
127 template<typename ParamType, typename ParamIter>
128 inline ut_detail::param_test_case_generator<
129     BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type,ParamIter>
make_test_case(void (* test_func)(ParamType),const_string tc_name,const_string tc_file,std::size_t tc_line,ParamIter par_begin,ParamIter par_end)130 make_test_case( void (*test_func)( ParamType ),
131                 const_string  tc_name,
132                 const_string  tc_file,
133                 std::size_t   tc_line,
134                 ParamIter     par_begin,
135                 ParamIter     par_end )
136 {
137     typedef BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type param_value_type;
138     return ut_detail::param_test_case_generator<param_value_type,ParamIter>( test_func, tc_name, tc_file, tc_line, par_begin, par_end );
139 }
140 
141 //____________________________________________________________________________//
142 
143 template<typename UserTestCase,typename ParamType, typename ParamIter>
144 inline ut_detail::param_test_case_generator<
145     BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type,ParamIter>
make_test_case(void (UserTestCase::* test_method)(ParamType),const_string tc_name,const_string tc_file,std::size_t tc_line,boost::shared_ptr<UserTestCase> const & user_test_case,ParamIter par_begin,ParamIter par_end)146 make_test_case( void (UserTestCase::*test_method )( ParamType ),
147                 const_string                           tc_name,
148                 const_string                           tc_file,
149                 std::size_t                            tc_line,
150                 boost::shared_ptr<UserTestCase> const& user_test_case,
151                 ParamIter                              par_begin,
152                 ParamIter                              par_end )
153 {
154     typedef BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type param_value_type;
155     return ut_detail::param_test_case_generator<param_value_type,ParamIter>(
156                ut_detail::user_param_tc_method_invoker<UserTestCase,ParamType>( user_test_case, test_method ),
157                tc_name,
158                tc_file,
159                tc_line,
160                par_begin,
161                par_end );
162 }
163 
164 //____________________________________________________________________________//
165 
166 } // unit_test
167 } // namespace boost
168 
169 #include <boost/test/detail/enable_warnings.hpp>
170 
171 #endif // BOOST_TEST_PARAMETERIZED_TEST_HPP_021102GER
172 
173