range_return_test_driver.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. // Copyright Neil Groves 2009. Use, modification and
  2. // distribution is subject to the Boost Software License, Version
  3. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. //
  7. // For more information, see http://www.boost.org/libs/range/
  8. //
  9. #ifndef BOOST_RANGE_TEST_TEST_DRIVER_RANGE_RETURN_TEST_DRIVER_HPP_INCLUDED
  10. #define BOOST_RANGE_TEST_TEST_DRIVER_RANGE_RETURN_TEST_DRIVER_HPP_INCLUDED
  11. #include <boost/assert.hpp>
  12. #include <boost/test/test_tools.hpp>
  13. #include <boost/test/unit_test.hpp>
  14. namespace boost
  15. {
  16. namespace range_test
  17. {
  18. // check the results of an algorithm that returns
  19. // a range_return.
  20. //
  21. // This version is the general version. It should never be called.
  22. // All calls should invoke specialized implementations.
  23. template< range_return_value return_type >
  24. struct check_results
  25. {
  26. template< class Container, class Iterator >
  27. static void test(
  28. Container& test,
  29. Container& reference,
  30. Iterator test_it,
  31. Iterator reference_it
  32. )
  33. {
  34. BOOST_ASSERT( false );
  35. }
  36. };
  37. // check the results of an algorithm that returns
  38. // a 'found' iterator
  39. template< >
  40. struct check_results<return_found>
  41. {
  42. template< class Container, class Iterator >
  43. static void test(
  44. Container& test,
  45. Container& reference,
  46. Iterator test_it,
  47. Iterator reference_it
  48. )
  49. {
  50. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  51. test.begin(), test.end() );
  52. BOOST_CHECK_EQUAL( std::distance(test.begin(), test_it),
  53. std::distance(reference.begin(), reference_it) );
  54. }
  55. };
  56. // check the results of an algorithm that returns
  57. // a 'next(found)' iterator
  58. template< >
  59. struct check_results<return_next>
  60. {
  61. template< class Container, class Iterator >
  62. static void test(
  63. Container& test,
  64. Container& reference,
  65. Iterator test_it,
  66. Iterator reference_it
  67. )
  68. {
  69. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  70. test.begin(), test.end() );
  71. if (reference_it == reference.end())
  72. {
  73. BOOST_CHECK( test_it == test.end() );
  74. }
  75. else
  76. {
  77. BOOST_CHECK_EQUAL(
  78. std::distance(test.begin(), test_it),
  79. std::distance(reference.begin(), reference_it) + 1);
  80. }
  81. }
  82. };
  83. // check the results of an algorithm that returns
  84. // a 'prior(found)' iterator
  85. template< >
  86. struct check_results<return_prior>
  87. {
  88. template< class Container, class Iterator >
  89. static void test(
  90. Container& test,
  91. Container& reference,
  92. Iterator test_it,
  93. Iterator reference_it
  94. )
  95. {
  96. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  97. test.begin(), test.end() );
  98. if (reference_it == reference.begin())
  99. {
  100. BOOST_CHECK( test_it == test.begin() );
  101. }
  102. else
  103. {
  104. BOOST_CHECK_EQUAL(
  105. std::distance(test.begin(), test_it) + 1,
  106. std::distance(reference.begin(), reference_it));
  107. }
  108. }
  109. };
  110. // check the results of an algorithm that returns
  111. // a '[begin, found)' range
  112. template< >
  113. struct check_results<return_begin_found>
  114. {
  115. template< class Container, class Iterator >
  116. static void test(
  117. Container& test,
  118. Container& reference,
  119. iterator_range<Iterator> test_rng,
  120. Iterator reference_it
  121. )
  122. {
  123. BOOST_CHECK_EQUAL_COLLECTIONS(
  124. reference.begin(), reference.end(),
  125. test.begin(), test.end()
  126. );
  127. BOOST_CHECK( test_rng.begin() == test.begin() );
  128. BOOST_CHECK_EQUAL_COLLECTIONS(
  129. reference.begin(), reference_it,
  130. boost::begin(test_rng), boost::end(test_rng)
  131. );
  132. }
  133. };
  134. // check the results of an algorithm that returns
  135. // a '[begin, next(found))' range
  136. template< >
  137. struct check_results<return_begin_next>
  138. {
  139. template< class Container, class Iterator >
  140. static void test(
  141. Container& test,
  142. Container& reference,
  143. iterator_range<Iterator> test_rng,
  144. Iterator reference_it
  145. )
  146. {
  147. BOOST_CHECK_EQUAL_COLLECTIONS(
  148. reference.begin(), reference.end(),
  149. test.begin(), test.end()
  150. );
  151. BOOST_CHECK( test_rng.begin() == test.begin() );
  152. if (reference_it == reference.end())
  153. {
  154. BOOST_CHECK( test_rng.end() == test.end() );
  155. }
  156. else
  157. {
  158. BOOST_CHECK_EQUAL_COLLECTIONS(
  159. reference.begin(), boost::next(reference_it),
  160. test_rng.begin(), test_rng.end());
  161. }
  162. }
  163. };
  164. // check the results of an algorithm that returns
  165. // a '[begin, prior(found))' range
  166. template< >
  167. struct check_results<return_begin_prior>
  168. {
  169. template< class Container, class Iterator >
  170. static void test(
  171. Container& test,
  172. Container& reference,
  173. iterator_range<Iterator> test_rng,
  174. Iterator reference_it
  175. )
  176. {
  177. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  178. test.begin(), test.end() );
  179. BOOST_CHECK( test_rng.begin() == test.begin() );
  180. if (reference_it == reference.begin())
  181. {
  182. BOOST_CHECK( boost::end(test_rng) == test.begin() );
  183. }
  184. else
  185. {
  186. BOOST_CHECK_EQUAL( std::distance(boost::begin(test_rng), boost::end(test_rng)) + 1,
  187. std::distance(reference.begin(), reference_it) );
  188. }
  189. }
  190. };
  191. // check the results of an algorithm that returns
  192. // a '[found, end)' range
  193. template< >
  194. struct check_results<return_found_end>
  195. {
  196. template< class Container, class Iterator >
  197. static void test(
  198. Container& test,
  199. Container& reference,
  200. iterator_range<Iterator> test_rng,
  201. Iterator reference_it
  202. )
  203. {
  204. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  205. test.begin(), test.end() );
  206. BOOST_CHECK_EQUAL(
  207. std::distance(test.begin(), boost::begin(test_rng)),
  208. std::distance(reference.begin(), reference_it));
  209. BOOST_CHECK( boost::end(test_rng) == test.end() );
  210. }
  211. };
  212. // check the results of an algorithm that returns
  213. // a '[next(found), end)' range
  214. template< >
  215. struct check_results<return_next_end>
  216. {
  217. template< class Container, class Iterator >
  218. static void test(
  219. Container& test,
  220. Container& reference,
  221. iterator_range<Iterator> test_rng,
  222. Iterator reference_it
  223. )
  224. {
  225. BOOST_CHECK_EQUAL_COLLECTIONS(
  226. reference.begin(), reference.end(),
  227. test.begin(), test.end()
  228. );
  229. BOOST_CHECK( test_rng.end() == test.end() );
  230. if (reference_it == reference.end())
  231. {
  232. BOOST_CHECK( test_rng.begin() == test.end() );
  233. }
  234. else
  235. {
  236. BOOST_CHECK_EQUAL_COLLECTIONS(
  237. boost::next(reference_it), reference.end(),
  238. test_rng.begin(), test_rng.end()
  239. );
  240. }
  241. }
  242. };
  243. // check the results of an algorithm that returns
  244. // a 'prior(found), end)' range
  245. template< >
  246. struct check_results<return_prior_end>
  247. {
  248. template< class Container, class Iterator >
  249. static void test(
  250. Container& test,
  251. Container& reference,
  252. iterator_range<Iterator> test_rng,
  253. Iterator reference_it
  254. )
  255. {
  256. BOOST_CHECK_EQUAL_COLLECTIONS(
  257. reference.begin(), reference.end(),
  258. test.begin(), test.end()
  259. );
  260. BOOST_CHECK( test_rng.end() == test.end() );
  261. if (reference_it == reference.begin())
  262. {
  263. BOOST_CHECK( test_rng.begin() == test.begin() );
  264. }
  265. else
  266. {
  267. BOOST_CHECK_EQUAL_COLLECTIONS(
  268. boost::prior(reference_it), reference.end(),
  269. test_rng.begin(), test_rng.end()
  270. );
  271. }
  272. }
  273. };
  274. // check the results of an algorithm that returns
  275. // a '[begin, end)' range
  276. template< >
  277. struct check_results<return_begin_end>
  278. {
  279. template< class Container, class Iterator >
  280. static void test(
  281. Container& test,
  282. Container& reference,
  283. iterator_range<Iterator> test_rng,
  284. Iterator reference_it
  285. )
  286. {
  287. BOOST_CHECK_EQUAL_COLLECTIONS(
  288. reference.begin(), reference.end(),
  289. test.begin(), test.end()
  290. );
  291. BOOST_CHECK( test_rng.begin() == test.begin() );
  292. BOOST_CHECK( test_rng.end() == test.end() );
  293. }
  294. };
  295. // A test driver to exercise a test through all of the range_return
  296. // combinations.
  297. //
  298. // The test driver also contains the code required to check the
  299. // return value correctness.
  300. //
  301. // The TestPolicy needs to implement two functions:
  302. //
  303. // - perform the boost range version of the algorithm that returns
  304. // a range_return<Container,return_type>::type
  305. // template<range_return_value return_type, class Container>
  306. // BOOST_DEDUCED_TYPENAME range_return<Container,return_type>::type
  307. // test(Container& cont);
  308. //
  309. // - perform the reference std version of the algorithm that
  310. // returns the standard iterator result
  311. // template<class Container>
  312. // BOOST_DEDUCED_TYPENAME range_iterator<Container>::type
  313. // reference(Container& cont);
  314. class range_return_test_driver
  315. {
  316. public:
  317. template< class Container,
  318. class TestPolicy >
  319. void operator()(Container& cont, TestPolicy policy)
  320. {
  321. test_range_iter (cont, policy);
  322. test_range<return_found,Container,TestPolicy> ()(cont, policy);
  323. test_range<return_next,Container,TestPolicy> ()(cont, policy);
  324. test_range<return_prior,Container,TestPolicy> ()(cont, policy);
  325. test_range<return_begin_found,Container,TestPolicy>()(cont, policy);
  326. test_range<return_begin_next,Container,TestPolicy> ()(cont, policy);
  327. test_range<return_begin_prior,Container,TestPolicy>()(cont, policy);
  328. test_range<return_found_end,Container,TestPolicy> ()(cont, policy);
  329. test_range<return_next_end,Container,TestPolicy> ()(cont, policy);
  330. test_range<return_prior_end,Container,TestPolicy> ()(cont, policy);
  331. test_range<return_begin_end,Container,TestPolicy> ()(cont, policy);
  332. }
  333. private:
  334. template< class Container, class TestPolicy >
  335. void test_range_iter(
  336. Container& cont,
  337. TestPolicy policy
  338. )
  339. {
  340. typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
  341. Container reference(cont);
  342. Container test(cont);
  343. iterator_t range_result = policy.test_iter(test);
  344. iterator_t reference_it = policy.reference(reference);
  345. check_results<return_found>::test(test, reference,
  346. range_result, reference_it);
  347. }
  348. template< range_return_value result_type, class Container, class TestPolicy >
  349. struct test_range
  350. {
  351. void operator()(Container& cont, TestPolicy policy)
  352. {
  353. typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
  354. typedef BOOST_DEDUCED_TYPENAME range_return<Container, result_type>::type range_return_t;
  355. typedef BOOST_DEDUCED_TYPENAME TestPolicy::template test_range<result_type> test_range_t;
  356. Container reference(cont);
  357. Container test_cont(cont);
  358. test_range_t test_range_fn;
  359. range_return_t range_result = test_range_fn(policy, test_cont);
  360. iterator_t reference_it = policy.reference(reference);
  361. check_results<result_type>::test(test_cont, reference,
  362. range_result, reference_it);
  363. }
  364. };
  365. };
  366. }
  367. }
  368. #endif // include guard