test_case_template.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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/detail/workaround.hpp>
  17. #include <boost/test/utils/class_properties.hpp>
  18. #include <boost/test/tree/observer.hpp>
  19. // Boost
  20. #include <boost/shared_ptr.hpp>
  21. #include <boost/mpl/for_each.hpp>
  22. #include <boost/mpl/identity.hpp>
  23. #include <boost/type.hpp>
  24. #include <boost/type_traits/is_const.hpp>
  25. #include <boost/function/function0.hpp>
  26. #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
  27. # include <boost/current_function.hpp>
  28. #else
  29. # include <boost/core/demangle.hpp>
  30. #endif
  31. // STL
  32. #include <string> // for std::string
  33. #include <list> // for std::list
  34. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  35. !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
  36. !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
  37. #include <tuple>
  38. #endif
  39. #include <boost/test/detail/suppress_warnings.hpp>
  40. //____________________________________________________________________________//
  41. namespace boost {
  42. namespace unit_test {
  43. namespace ut_detail {
  44. // ************************************************************************** //
  45. // ************** test_case_template_invoker ************** //
  46. // ************************************************************************** //
  47. template<typename TestCaseTemplate,typename TestType>
  48. class test_case_template_invoker {
  49. public:
  50. void operator()() { TestCaseTemplate::run( (boost::type<TestType>*)0 ); }
  51. };
  52. // ************************************************************************** //
  53. // ************** generate_test_case_4_type ************** //
  54. // ************************************************************************** //
  55. template<typename Generator, typename TestCaseTemplate>
  56. struct generate_test_case_4_type {
  57. explicit generate_test_case_4_type( const_string tc_name, const_string tc_file, std::size_t tc_line, Generator& G )
  58. : m_test_case_name( tc_name )
  59. , m_test_case_file( tc_file )
  60. , m_test_case_line( tc_line )
  61. , m_holder( G )
  62. {}
  63. template<typename TestType>
  64. void operator()( mpl::identity<TestType> )
  65. {
  66. std::string full_name;
  67. assign_op( full_name, m_test_case_name, 0 );
  68. full_name += '<';
  69. #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
  70. full_name += boost::core::demangle(typeid(TestType).name()); // same as execution_monitor.ipp
  71. #else
  72. full_name += BOOST_CURRENT_FUNCTION;
  73. #endif
  74. if( boost::is_const<TestType>::value )
  75. full_name += "_const";
  76. full_name += '>';
  77. m_holder.m_test_cases.push_back( new test_case( ut_detail::normalize_test_case_name( full_name ),
  78. m_test_case_file,
  79. m_test_case_line,
  80. test_case_template_invoker<TestCaseTemplate,TestType>() ) );
  81. }
  82. private:
  83. // Data members
  84. const_string m_test_case_name;
  85. const_string m_test_case_file;
  86. std::size_t m_test_case_line;
  87. Generator& m_holder;
  88. };
  89. // ************************************************************************** //
  90. // ************** test_case_template ************** //
  91. // ************************************************************************** //
  92. class template_test_case_gen_base : public test_unit_generator {
  93. public:
  94. virtual test_unit* next() const
  95. {
  96. if( m_test_cases.empty() )
  97. return 0;
  98. test_unit* res = m_test_cases.front();
  99. m_test_cases.pop_front();
  100. return res;
  101. }
  102. // Data members
  103. mutable std::list<test_unit*> m_test_cases;
  104. };
  105. template<typename TestCaseTemplate,typename TestTypesList>
  106. class template_test_case_gen : public template_test_case_gen_base {
  107. public:
  108. // Constructor
  109. template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
  110. {
  111. typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,TestCaseTemplate> single_test_gen;
  112. mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, tc_file, tc_line, *this ) );
  113. }
  114. };
  115. // Describing template test cases with tuples
  116. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
  117. !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
  118. !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && \
  119. !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  120. template<typename TestCaseTemplate, typename... tuple_parameter_pack>
  121. class template_test_case_gen<TestCaseTemplate, std::tuple<tuple_parameter_pack...> > : public template_test_case_gen_base {
  122. template<int... Is>
  123. struct seq { };
  124. template<int N, int... Is>
  125. struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
  126. template<int... Is>
  127. struct gen_seq<0, Is...> : seq<Is...> { };
  128. template<typename tuple_t, typename F, int... Is>
  129. void for_each(F &f, seq<Is...>)
  130. {
  131. auto l = { (f(mpl::identity<typename std::tuple_element<Is, tuple_t>::type>()), 0)... };
  132. (void)l; // silence warning
  133. }
  134. public:
  135. // Constructor
  136. template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
  137. {
  138. using tuple_t = std::tuple<tuple_parameter_pack...>;
  139. using this_type = template_test_case_gen<TestCaseTemplate, tuple_t >;
  140. using single_test_gen = generate_test_case_4_type<this_type, TestCaseTemplate>;
  141. single_test_gen op( tc_name, tc_file, tc_line, *this );
  142. this->for_each<tuple_t>(op, gen_seq<sizeof...(tuple_parameter_pack)>());
  143. }
  144. };
  145. #endif /* C++11 variadic, tuples and type alias */
  146. } // namespace ut_detail
  147. } // unit_test
  148. } // namespace boost
  149. #include <boost/test/detail/enable_warnings.hpp>
  150. #endif // BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER