test_case_template.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. /// Defines template_test_case_gen
  9. // ***************************************************************************
  10. #ifndef BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER
  11. #define BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER
  12. // Boost.Test
  13. #include <boost/test/detail/config.hpp>
  14. #include <boost/test/detail/global_typedef.hpp>
  15. #include <boost/test/detail/fwd_decl.hpp>
  16. #include <boost/test/tree/test_unit.hpp>
  17. #include <boost/test/utils/class_properties.hpp>
  18. #include <boost/test/tree/observer.hpp>
  19. #include <boost/test/utils/algorithm.hpp>
  20. // Boost
  21. #include <boost/shared_ptr.hpp>
  22. #include <boost/mpl/for_each.hpp>
  23. #include <boost/mpl/identity.hpp>
  24. #include <boost/type.hpp>
  25. #include <boost/type_traits/is_const.hpp>
  26. #include <boost/type_traits/is_volatile.hpp>
  27. #include <boost/type_traits/is_lvalue_reference.hpp>
  28. #include <boost/type_traits/is_rvalue_reference.hpp>
  29. #include <boost/type_traits/remove_reference.hpp>
  30. #include <boost/function/function0.hpp>
  31. #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
  32. # include <boost/current_function.hpp>
  33. #else
  34. # include <boost/core/demangle.hpp>
  35. #endif
  36. // STL
  37. #include <string> // for std::string
  38. #include <list> // for std::list
  39. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  40. !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
  41. #include <type_traits>
  42. #include <boost/mpl/is_sequence.hpp>
  43. #endif
  44. #include <boost/test/detail/suppress_warnings.hpp>
  45. //____________________________________________________________________________//
  46. namespace boost {
  47. namespace unit_test {
  48. namespace ut_detail {
  49. // ************************************************************************** //
  50. // ************** test_case_template_invoker ************** //
  51. // ************************************************************************** //
  52. template<typename TestCaseTemplate,typename TestType>
  53. class test_case_template_invoker {
  54. public:
  55. void operator()() { TestCaseTemplate::run( (boost::type<TestType>*)0 ); }
  56. };
  57. // ************************************************************************** //
  58. // ************** generate_test_case_4_type ************** //
  59. // ************************************************************************** //
  60. template<typename Generator, typename TestCaseTemplate>
  61. struct generate_test_case_4_type {
  62. explicit generate_test_case_4_type( const_string tc_name, const_string tc_file, std::size_t tc_line, Generator& G )
  63. : m_test_case_name( tc_name )
  64. , m_test_case_file( tc_file )
  65. , m_test_case_line( tc_line )
  66. , m_holder( G )
  67. {}
  68. template<typename TestType>
  69. void operator()( mpl::identity<TestType> )
  70. {
  71. std::string full_name;
  72. assign_op( full_name, m_test_case_name, 0 );
  73. full_name += '<';
  74. #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
  75. full_name += boost::core::demangle(typeid(TestType).name()); // same as execution_monitor.ipp
  76. #else
  77. full_name += BOOST_CURRENT_FUNCTION;
  78. #endif
  79. // replacing ',' by ', ' first, and then removing any double space
  80. static const std::string to_replace[] = { "class ", "struct ", ",", " ", " <", " >"};
  81. static const std::string replacement[] = { "", "" , ", ", " ", "<" , ">"};
  82. full_name = unit_test::utils::replace_all_occurrences_of(
  83. full_name,
  84. to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
  85. replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
  86. typedef typename boost::remove_reference<TestType>::type TestTypewoRef;
  87. if( boost::is_const<TestTypewoRef>::value )
  88. full_name += "_const";
  89. if( boost::is_volatile<TestTypewoRef>::value )
  90. full_name += "_volatile";
  91. if( boost::is_rvalue_reference<TestType>::value )
  92. full_name += "_refref";
  93. else if( boost::is_lvalue_reference<TestType>::value )
  94. full_name += "_ref";
  95. full_name += '>';
  96. m_holder.m_test_cases.push_back( new test_case( ut_detail::normalize_test_case_name( full_name ),
  97. m_test_case_file,
  98. m_test_case_line,
  99. test_case_template_invoker<TestCaseTemplate,TestType>() ) );
  100. }
  101. private:
  102. // Data members
  103. const_string m_test_case_name;
  104. const_string m_test_case_file;
  105. std::size_t m_test_case_line;
  106. Generator& m_holder;
  107. };
  108. // ************************************************************************** //
  109. // ************** test_case_template ************** //
  110. // ************************************************************************** //
  111. class template_test_case_gen_base : public test_unit_generator {
  112. public:
  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. // Data members
  122. mutable std::list<test_unit*> m_test_cases;
  123. };
  124. template<typename TestCaseTemplate,typename TestTypesList, typename enabler = void>
  125. class template_test_case_gen : public template_test_case_gen_base {
  126. public:
  127. // Constructor
  128. template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
  129. {
  130. typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,TestCaseTemplate> single_test_gen;
  131. mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, tc_file, tc_line, *this ) );
  132. }
  133. };
  134. // Describing template test cases with tuples
  135. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  136. !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && \
  137. !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  138. template<typename TestCaseTemplate,
  139. template <class ...> class C,
  140. typename... parameter_pack>
  141. class template_test_case_gen<
  142. TestCaseTemplate,
  143. C<parameter_pack...>,
  144. typename std::enable_if<!boost::mpl::is_sequence<C<parameter_pack...>>::value>::type >
  145. : public template_test_case_gen_base {
  146. template<typename F>
  147. void for_each(F &f)
  148. {
  149. auto l = { (f(mpl::identity<parameter_pack>()), 0)... };
  150. (void)l; // silence warning
  151. }
  152. public:
  153. // Constructor
  154. template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
  155. {
  156. using this_type = template_test_case_gen<
  157. TestCaseTemplate,
  158. C<parameter_pack...>,
  159. typename std::enable_if<!boost::mpl::is_sequence<C<parameter_pack...>>::value>::type>;
  160. using single_test_gen = generate_test_case_4_type<this_type, TestCaseTemplate>;
  161. single_test_gen op( tc_name, tc_file, tc_line, *this );
  162. this->for_each(op);
  163. }
  164. };
  165. #endif /* C++11 variadic, type alias */
  166. } // namespace ut_detail
  167. } // unit_test
  168. } // namespace boost
  169. #include <boost/test/detail/enable_warnings.hpp>
  170. #endif // BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER