/Src/Dependencies/Boost/libs/range/test/join.cpp

http://hadesmem.googlecode.com/ · C++ · 273 lines · 174 code · 37 blank · 62 comment · 10 complexity · 8eaafeac958d772f8551af0c8b762736 MD5 · raw file

  1. // Boost.Range library
  2. //
  3. // Copyright Neil Groves 2010. Use, modification and
  4. // distribution is subject to the Boost Software License, Version
  5. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. //
  9. // For more information, see http://www.boost.org/libs/range/
  10. //
  11. #include <boost/range/join.hpp>
  12. #include <boost/foreach.hpp>
  13. #include <boost/test/test_tools.hpp>
  14. #include <boost/test/unit_test.hpp>
  15. #include <boost/assign.hpp>
  16. #include <boost/range/algorithm_ext.hpp>
  17. #include <boost/range/irange.hpp>
  18. #include <boost/iterator/iterator_facade.hpp>
  19. #include <algorithm>
  20. #include <deque>
  21. #include <list>
  22. #include <vector>
  23. namespace boost
  24. {
  25. namespace
  26. {
  27. // This function is a helper function that writes integers
  28. // of increasing value into a range. It is used to test
  29. // that joined ranged may be written to.
  30. //
  31. // Requires:
  32. // - Range uses shallow copy semantics.
  33. template< typename Range >
  34. void fill_with_ints(Range rng)
  35. {
  36. typedef typename range_iterator<Range>::type iterator;
  37. iterator target = boost::begin(rng);
  38. const int count = boost::distance(rng);
  39. for (int i = 0; i < count; ++i)
  40. {
  41. *target = i;
  42. ++target;
  43. }
  44. }
  45. // The test_join_traversal function is used to provide additional
  46. // tests based upon the underlying join iterator traversal.
  47. // The join iterator takes care of the appropriate demotion, and
  48. // this demotion.
  49. // test_join_traversal - additional tests for input and forward
  50. // traversal iterators. This is of course a no-op.
  51. template< typename Range1, typename Range2, typename TraversalTag >
  52. void test_join_traversal(Range1& rng1, Range2& rng2, TraversalTag)
  53. {
  54. }
  55. // test_join_traversal - additional tests for bidirectional
  56. // traversal iterators.
  57. template< typename Range1, typename Range2 >
  58. void test_join_traversal(Range1& rng1, Range2& rng2, boost::bidirectional_traversal_tag)
  59. {
  60. typedef typename range_value<Range1>::type value_type;
  61. std::vector<value_type> reference(boost::begin(rng1), boost::end(rng1));
  62. boost::push_back(reference, rng2);
  63. std::reverse(reference.begin(), reference.end());
  64. std::vector<value_type> test_result;
  65. BOOST_REVERSE_FOREACH( value_type x, join(rng1, rng2) )
  66. {
  67. test_result.push_back(x);
  68. }
  69. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  70. test_result.begin(), test_result.end() );
  71. }
  72. // Test helper function to implement the additional tests for random
  73. // access traversal iterators. This is used by the test_join_traversal
  74. // function for random access iterators. The reason that the test
  75. // implementation is put into this function is to utilise
  76. // template parameter type deduction for the joined range type.
  77. template< typename Range1, typename Range2, typename JoinedRange >
  78. void test_random_access_join(Range1& rng1, Range2& rng2, JoinedRange joined)
  79. {
  80. BOOST_CHECK_EQUAL( boost::end(joined) - boost::begin(joined), boost::distance(joined) );
  81. BOOST_CHECK( boost::end(joined) <= boost::begin(joined) );
  82. BOOST_CHECK( boost::begin(joined) >= boost::end(joined) );
  83. if (boost::empty(joined))
  84. {
  85. BOOST_CHECK(!(boost::begin(joined) < boost::end(joined)));
  86. BOOST_CHECK(!(boost::end(joined) > boost::begin(joined)));
  87. }
  88. else
  89. {
  90. BOOST_CHECK(boost::begin(joined) < boost::end(joined));
  91. BOOST_CHECK(boost::end(joined) < boost::begin(joined));
  92. }
  93. typedef typename boost::range_difference<JoinedRange>::type difference_t;
  94. const difference_t count = boost::distance(joined);
  95. BOOST_CHECK( boost::begin(joined) + count == boost::end(joined) );
  96. BOOST_CHECK( boost::end(joined) - count == boost::begin(joined) );
  97. typedef typename boost::range_iterator<JoinedRange>::type iterator_t;
  98. iterator_t it = boost::begin(joined);
  99. it += count;
  100. BOOST_CHECK( it == boost::end(joined) );
  101. it = boost::end(joined);
  102. it -= count;
  103. BOOST_CHECK( it == boost::begin(joined) );
  104. }
  105. // test_join_traversal function for random access traversal joined
  106. // ranges.
  107. template< typename Range1, typename Range2 >
  108. void test_join_traversal(Range1& rng1, Range2& rng2, boost::random_access_traversal_tag)
  109. {
  110. test_join_traversal(rng1, rng2, boost::bidirectional_traversal_tag());
  111. test_random_access_join(rng1, rng2, join(rng1, rng2));
  112. }
  113. // Test the ability to write values into a joined range. This is
  114. // achieved by copying the constant collections, altering them
  115. // and then checking the result. Hence this relies upon both
  116. // rng1 and rng2 having value copy semantics.
  117. template< typename Collection1, typename Collection2 >
  118. void test_write_to_joined_range(const Collection1& rng1, const Collection2& rng2)
  119. {
  120. Collection1 c1(rng1);
  121. Collection2 c2(rng2);
  122. typedef typename boost::range_value<Collection1>::type value_t;
  123. fill_with_ints(boost::join(c1,c2));
  124. // Ensure that the size of the written range has not been
  125. // altered.
  126. BOOST_CHECK_EQUAL( boost::distance(c1), boost::distance(rng1) );
  127. BOOST_CHECK_EQUAL( boost::distance(c2), boost::distance(rng2) );
  128. // For each element x, in c1 ensure that it has been written to
  129. // with incrementing integers
  130. int x = 0;
  131. typedef typename range_iterator<Collection1>::type iterator1;
  132. iterator1 it1 = boost::begin(c1);
  133. for (; it1 != boost::end(c1); ++it1)
  134. {
  135. BOOST_CHECK_EQUAL( x, *it1 );
  136. ++x;
  137. }
  138. // For each element y, in c2 ensure that it has been written to
  139. // with incrementing integers
  140. typedef typename range_iterator<Collection2>::type iterator2;
  141. iterator2 it2 = boost::begin(c2);
  142. for (; it2 != boost::end(c2); ++it2)
  143. {
  144. BOOST_CHECK_EQUAL( x, *it2 );
  145. ++x;
  146. }
  147. }
  148. // Perform a unit test of a Boost.Range join() comparing
  149. // it to a reference that is populated by appending
  150. // elements from both source ranges into a vector.
  151. template< typename Collection1, typename Collection2 >
  152. void test_join_impl(Collection1& rng1, Collection2& rng2)
  153. {
  154. typedef typename range_value<Collection1>::type value_type;
  155. std::vector<value_type> reference(boost::begin(rng1), boost::end(rng1));
  156. boost::push_back(reference, rng2);
  157. std::vector<value_type> test_result;
  158. boost::push_back(test_result, join(rng1, rng2));
  159. BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
  160. test_result.begin(), test_result.end() );
  161. typedef boost::range_detail::join_iterator<
  162. typename boost::range_iterator<Collection1>::type,
  163. typename boost::range_iterator<Collection2>::type
  164. > join_iterator_t;
  165. typedef boost::iterator_traversal< join_iterator_t > tag_t;
  166. test_join_traversal(rng1, rng2, tag_t());
  167. test_write_to_joined_range(rng1, rng2);
  168. }
  169. // Make a collection filling it with items from the source
  170. // range. This is used to build collections of various
  171. // sizes populated with various values designed to optimize
  172. // the code coverage exercised by the core test function
  173. // test_join_impl.
  174. template<typename Collection, typename Range>
  175. boost::shared_ptr<Collection> makeCollection(const Range& source)
  176. {
  177. boost::shared_ptr<Collection> c(new Collection);
  178. c->insert(c->end(), boost::begin(source), boost::end(source));
  179. return c;
  180. }
  181. // This templatised version of the test_join_impl function
  182. // generates and populates collections which are later
  183. // used as input to the core test function.
  184. // The caller of this function explicitly provides the
  185. // template parameters. This supports the generation
  186. // of testing a large combination of range types to be
  187. // joined. It is of particular importance to remember
  188. // to combine a random_access range with a bidirectional
  189. // range to determine that the correct demotion of
  190. // types occurs in the join_iterator.
  191. template< typename Collection1, typename Collection2 >
  192. void test_join_impl()
  193. {
  194. typedef boost::shared_ptr<Collection1> collection1_ptr;
  195. typedef boost::shared_ptr<Collection2> collection2_ptr;
  196. typedef boost::shared_ptr<const Collection1> collection1_cptr;
  197. typedef boost::shared_ptr<const Collection2> collection2_cptr;
  198. std::vector< collection1_cptr > left_containers;
  199. std::vector< collection2_cptr > right_containers;
  200. left_containers.push_back(collection1_ptr(new Collection1));
  201. left_containers.push_back(makeCollection<Collection1>(irange(0,1)));
  202. left_containers.push_back(makeCollection<Collection1>(irange(0,100)));
  203. right_containers.push_back(collection2_ptr(new Collection2));
  204. right_containers.push_back(makeCollection<Collection2>(irange(0,1)));
  205. right_containers.push_back(makeCollection<Collection2>(irange(0,100)));
  206. BOOST_FOREACH( collection1_cptr left_container, left_containers )
  207. {
  208. BOOST_FOREACH( collection2_cptr right_container, right_containers )
  209. {
  210. test_join_impl(*left_container, *right_container);
  211. }
  212. }
  213. }
  214. // entry-point into the unit test for the join() function
  215. // this tests a representative sample of combinations of
  216. // source range type.
  217. void join_test()
  218. {
  219. test_join_impl< std::vector<int>, std::vector<int> >();
  220. test_join_impl< std::list<int>, std::list<int> >();
  221. test_join_impl< std::deque<int>, std::deque<int> >();
  222. test_join_impl< std::vector<int>, std::list<int> >();
  223. test_join_impl< std::list<int>, std::vector<int> >();
  224. test_join_impl< std::vector<int>, std::deque<int> >();
  225. test_join_impl< std::deque<int>, std::vector<int> >();
  226. }
  227. }
  228. }
  229. boost::unit_test::test_suite*
  230. init_unit_test_suite(int argc, char* argv[])
  231. {
  232. boost::unit_test::test_suite* test
  233. = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.joined" );
  234. test->add( BOOST_TEST_CASE( &boost::join_test ) );
  235. return test;
  236. }