test_case.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. //!@file
  8. //!@brief test case family based on data generator
  9. // ***************************************************************************
  10. #ifndef BOOST_TEST_DATA_TEST_CASE_HPP_102211GER
  11. #define BOOST_TEST_DATA_TEST_CASE_HPP_102211GER
  12. // Boost.Test
  13. #include <boost/test/data/config.hpp>
  14. #include <boost/test/data/dataset.hpp>
  15. #include <boost/test/data/for_each_sample.hpp>
  16. // Boost
  17. #include <boost/preprocessor/repetition/enum_params.hpp>
  18. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  19. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  20. #include <boost/preprocessor/variadic/to_seq.hpp>
  21. #include <boost/preprocessor/variadic/size.hpp>
  22. #include <boost/preprocessor/cat.hpp>
  23. #include <boost/preprocessor/seq/for_each_i.hpp>
  24. #include <boost/preprocessor/seq/for_each.hpp>
  25. #include <boost/preprocessor/seq/enum.hpp>
  26. #include <boost/preprocessor/control/iif.hpp>
  27. #include <boost/preprocessor/comparison/equal.hpp>
  28. #include <boost/bind.hpp>
  29. #include <boost/type_traits/is_copy_constructible.hpp>
  30. #include <boost/test/detail/suppress_warnings.hpp>
  31. #include <boost/test/tools/detail/print_helper.hpp>
  32. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
  33. && !defined(BOOST_TEST_DATASET_MAX_ARITY)
  34. # define BOOST_TEST_DATASET_MAX_ARITY 10
  35. #endif
  36. //____________________________________________________________________________//
  37. namespace boost {
  38. namespace unit_test {
  39. namespace data {
  40. namespace ds_detail {
  41. // ************************************************************************** //
  42. // ************** seed ************** //
  43. // ************************************************************************** //
  44. struct seed {
  45. template<typename DataSet>
  46. typename data::result_of::make<DataSet>::type
  47. operator->*( DataSet&& ds ) const
  48. {
  49. return data::make( std::forward<DataSet>( ds ) );
  50. }
  51. };
  52. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  53. !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
  54. !defined(BOOST_NO_CXX11_DECLTYPE) && \
  55. !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
  56. !defined(BOOST_NO_CXX11_SMART_PTR)
  57. #define BOOST_TEST_DATASET_VARIADIC
  58. template <class T>
  59. struct parameter_holder {
  60. std::shared_ptr<T> value;
  61. parameter_holder(T && value_)
  62. : value(std::make_shared<T>(std::move(value_)))
  63. {}
  64. operator T const&() const {
  65. return *value;
  66. }
  67. };
  68. template <class T>
  69. parameter_holder<typename std::remove_reference<T>::type>
  70. boost_bind_rvalue_holder_helper_impl(T&& value, boost::false_type /* is copy constructible */) {
  71. return parameter_holder<typename std::remove_reference<T>::type>(std::forward<T>(value));
  72. }
  73. template <class T>
  74. T&& boost_bind_rvalue_holder_helper_impl(T&& value, boost::true_type /* is copy constructible */) {
  75. return std::forward<T>(value);
  76. }
  77. template <class T>
  78. auto boost_bind_rvalue_holder_helper(T&& value)
  79. -> decltype(boost_bind_rvalue_holder_helper_impl(
  80. std::forward<T>(value),
  81. typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type()))
  82. {
  83. // need to use boost::is_copy_constructible because std::is_copy_constructible is broken on MSVC12
  84. return boost_bind_rvalue_holder_helper_impl(
  85. std::forward<T>(value),
  86. typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type());
  87. }
  88. #endif
  89. // ************************************************************************** //
  90. // ************** test_case_gen ************** //
  91. // ************************************************************************** //
  92. template<typename TestCase,typename DataSet>
  93. class test_case_gen : public test_unit_generator {
  94. public:
  95. // Constructor
  96. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  97. test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet&& ds )
  98. : m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
  99. {
  100. data::for_each_sample( std::forward<DataSet>( ds ), *this );
  101. }
  102. test_case_gen( test_case_gen&& gen )
  103. : m_tc_name( gen.m_tc_name )
  104. , m_test_cases( std::move(gen.m_test_cases) )
  105. {}
  106. #else
  107. test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
  108. : m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
  109. {
  110. data::for_each_sample( ds, *this );
  111. }
  112. #endif
  113. virtual test_unit* next() const
  114. {
  115. if( m_test_cases.empty() )
  116. return 0;
  117. test_unit* res = m_test_cases.front();
  118. m_test_cases.pop_front();
  119. return res;
  120. }
  121. #if !defined(BOOST_TEST_DATASET_VARIADIC)
  122. /// make this variadic
  123. #define TC_MAKE(z,arity,_) \
  124. template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
  125. void operator()( BOOST_PP_ENUM_BINARY_PARAMS(arity, Arg, const& arg) ) const \
  126. { \
  127. m_test_cases.push_back( new test_case( m_tc_name, m_tc_file, m_tc_line, \
  128. boost::bind( &TestCase::template test_method<BOOST_PP_ENUM_PARAMS(arity,Arg)>, \
  129. BOOST_PP_ENUM_PARAMS(arity, arg) ) ) ); \
  130. } \
  131. BOOST_PP_REPEAT_FROM_TO(1, BOOST_TEST_DATASET_MAX_ARITY, TC_MAKE, _)
  132. #else
  133. template<typename ...Arg>
  134. void operator()(Arg&& ... arg) const
  135. {
  136. m_test_cases.push_back(
  137. new test_case( m_tc_name,
  138. m_tc_file,
  139. m_tc_line,
  140. boost::bind( &TestCase::template test_method<Arg...>,
  141. boost_bind_rvalue_holder_helper(std::forward<Arg>(arg))...)));
  142. }
  143. #endif
  144. private:
  145. // Data members
  146. std::string m_tc_name;
  147. const_string m_tc_file;
  148. std::size_t m_tc_line;
  149. mutable std::list<test_unit*> m_test_cases;
  150. };
  151. //____________________________________________________________________________//
  152. #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
  153. template<typename TestCase,typename DataSet>
  154. test_case_gen<TestCase,DataSet>
  155. make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet&& ds )
  156. {
  157. return test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, std::forward<DataSet>(ds) );
  158. }
  159. #else
  160. template<typename TestCase,typename DataSet>
  161. test_case_gen<TestCase,DataSet>
  162. make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
  163. {
  164. return test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, ds );
  165. }
  166. #endif
  167. //____________________________________________________________________________//
  168. } // namespace ds_detail
  169. // ************************************************************************** //
  170. // ************** BOOST_DATA_TEST_CASE ************** //
  171. // ************************************************************************** //
  172. #define BOOST_DATA_TEST_CASE_PARAM(r, _, i, param) (BOOST_PP_CAT(Arg, i) const& param)
  173. #define BOOST_DATA_TEST_CONTEXT(r, _, param) << BOOST_STRINGIZE(param) << " = " << boost::test_tools::tt_detail::print_helper(param) << "; "
  174. #define BOOST_DATA_TEST_CASE_PARAMS( params ) \
  175. BOOST_PP_SEQ_ENUM( \
  176. BOOST_PP_SEQ_FOR_EACH_I(BOOST_DATA_TEST_CASE_PARAM, _, params)) \
  177. /**/
  178. #define BOOST_DATA_TEST_CASE_IMPL(arity, F, test_name, dataset, params) \
  179. struct test_name : public F { \
  180. template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
  181. static void test_method( BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
  182. { \
  183. BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry.");\
  184. test_name t; \
  185. BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
  186. BOOST_TEST_CONTEXT( "" \
  187. BOOST_PP_SEQ_FOR_EACH(BOOST_DATA_TEST_CONTEXT, _, params)) \
  188. t._impl(BOOST_PP_SEQ_ENUM(params)); \
  189. BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
  190. } \
  191. private: \
  192. template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
  193. void _impl(BOOST_DATA_TEST_CASE_PARAMS( params )); \
  194. }; \
  195. \
  196. BOOST_AUTO_TU_REGISTRAR( test_name )( \
  197. boost::unit_test::data::ds_detail::make_test_case_gen<test_name>( \
  198. BOOST_STRINGIZE( test_name ), \
  199. __FILE__, __LINE__, \
  200. boost::unit_test::data::ds_detail::seed{} ->* dataset ), \
  201. boost::unit_test::decorator::collector::instance() ); \
  202. \
  203. template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
  204. void test_name::_impl( BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
  205. /**/
  206. #define BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, ... ) \
  207. BOOST_DATA_TEST_CASE_IMPL( BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
  208. F, test_name, dataset, \
  209. BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) \
  210. /**/
  211. #define BOOST_DATA_TEST_CASE_NO_PARAMS( F, test_name, dataset ) \
  212. BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, sample ) \
  213. /**/
  214. #if BOOST_PP_VARIADICS_MSVC
  215. #define BOOST_DATA_TEST_CASE( ... ) \
  216. BOOST_PP_CAT( \
  217. BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
  218. BOOST_DATA_TEST_CASE_NO_PARAMS, \
  219. BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
  220. BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__), ) \
  221. /**/
  222. #define BOOST_DATA_TEST_CASE_F( F, ... ) \
  223. BOOST_PP_CAT( \
  224. BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
  225. BOOST_DATA_TEST_CASE_NO_PARAMS, \
  226. BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
  227. F, __VA_ARGS__), ) \
  228. /**/
  229. #else
  230. #define BOOST_DATA_TEST_CASE( ... ) \
  231. BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
  232. BOOST_DATA_TEST_CASE_NO_PARAMS, \
  233. BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
  234. BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__) \
  235. /**/
  236. #define BOOST_DATA_TEST_CASE_F( F, ... ) \
  237. BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
  238. BOOST_DATA_TEST_CASE_NO_PARAMS, \
  239. BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
  240. F, __VA_ARGS__) \
  241. /**/
  242. #endif
  243. } // namespace data
  244. } // namespace unit_test
  245. } // namespace boost
  246. #include <boost/test/detail/enable_warnings.hpp>
  247. #endif // BOOST_TEST_DATA_TEST_CASE_HPP_102211GER