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 #include <boost/range/algorithm/equal_range.hpp>
10 
11 #include <boost/test/test_tools.hpp>
12 #include <boost/test/unit_test.hpp>
13 
14 #include <boost/assign.hpp>
15 #include <algorithm>
16 #include <functional>
17 #include <list>
18 #include <numeric>
19 #include <deque>
20 #include <vector>
21 
22 namespace boost
23 {
24     namespace
25     {
26         template<class Container, class Pair>
check_result(const Container & reference,Pair reference_pair,const Container & test,Pair test_pair)27         void check_result(
28             const Container& reference,
29             Pair             reference_pair,
30             const Container& test,
31             Pair             test_pair
32             )
33         {
34             typedef BOOST_DEDUCED_TYPENAME range_iterator<const Container>::type
35                 const_iterator_t;
36 
37             BOOST_CHECK_EQUAL_COLLECTIONS(
38                 reference.begin(), reference.end(),
39                 test.begin(), test.end()
40                 );
41 
42             BOOST_CHECK_EQUAL(
43                 std::distance<const_iterator_t>(reference.begin(), reference_pair.first),
44                 std::distance<const_iterator_t>(test.begin(), test_pair.first)
45                 );
46 
47             BOOST_CHECK_EQUAL(
48                 std::distance<const_iterator_t>(reference.begin(), reference_pair.second),
49                 std::distance<const_iterator_t>(test.begin(), test_pair.second)
50                 );
51 
52             BOOST_CHECK_EQUAL_COLLECTIONS(
53                 reference_pair.first, reference_pair.second,
54                 test_pair.first, test_pair.second
55                 );
56         }
57 
58         template<class Container>
test(Container & cont)59         void test(Container& cont)
60         {
61             Container reference(cont);
62             Container test(cont);
63 
64             typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
65             typedef std::pair<iterator_t, iterator_t> pair_t;
66 
67             pair_t reference_result
68                 = std::equal_range(reference.begin(), reference.end(), 5);
69 
70             pair_t test_result = boost::equal_range(test, 5);
71 
72             check_result(reference, reference_result, test, test_result);
73 
74             pair_t test_result2 = boost::equal_range(boost::make_iterator_range(test), 5);
75 
76             check_result(reference, reference_result, test, test_result2);
77         }
78 
79         template<class Container, class BinaryPredicate>
sort_container(Container & cont,BinaryPredicate pred)80         void sort_container(Container& cont, BinaryPredicate pred)
81         {
82             typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
83 
84             std::vector<value_t> temp(cont.begin(), cont.end());
85             std::sort(temp.begin(), temp.end(), pred);
86             cont.assign(temp.begin(), temp.end());
87         }
88 
89         template<class Container, class BinaryPredicate>
test_pred(Container & cont,BinaryPredicate pred)90         void test_pred(Container& cont, BinaryPredicate pred)
91         {
92             typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container>::type container_t;
93 
94             container_t reference_temp(cont);
95             container_t test_temp(cont);
96 
97             sort_container(reference_temp, pred);
98             sort_container(test_temp, pred);
99 
100             Container reference(reference_temp);
101             Container test(test_temp);
102 
103             typedef BOOST_DEDUCED_TYPENAME range_iterator<Container>::type iterator_t;
104             typedef std::pair<iterator_t, iterator_t> pair_t;
105 
106             pair_t reference_result
107                 = std::equal_range(reference.begin(), reference.end(), 5,
108                                     BinaryPredicate());
109 
110             pair_t test_result = boost::equal_range(test, 5, BinaryPredicate());
111 
112             check_result(reference, reference_result, test, test_result);
113 
114             pair_t test_result2 = boost::equal_range(boost::make_iterator_range(test), 5, BinaryPredicate());
115 
116             check_result(reference, reference_result, test, test_result2);
117         }
118 
119         template<class Container>
test_driver(const Container & cont)120         void test_driver(const Container& cont)
121         {
122             Container mutable_cont(cont);
123             test(mutable_cont);
124 
125             test(cont);
126         }
127 
128         template<class Container, class BinaryPredicate>
test_pred_driver(const Container & cont,BinaryPredicate pred)129         void test_pred_driver(const Container& cont, BinaryPredicate pred)
130         {
131             Container mutable_cont(cont);
132             test_pred(mutable_cont, pred);
133 
134             test_pred(cont, pred);
135         }
136 
137         template<class Container>
test_equal_range_impl()138         void test_equal_range_impl()
139         {
140             using namespace boost::assign;
141 
142             Container cont;
143 
144             test_driver(cont);
145             test_pred_driver(cont, std::less<int>());
146             test_pred_driver(cont, std::greater<int>());
147 
148             cont.clear();
149             cont += 1;
150             test_driver(cont);
151             test_pred_driver(cont, std::less<int>());
152             test_pred_driver(cont, std::greater<int>());
153 
154             cont.clear();
155             cont += 1,2,3,4,5,6,7,8,9;
156             test_driver(cont);
157             test_pred_driver(cont, std::less<int>());
158             test_pred_driver(cont, std::greater<int>());
159         }
160 
test_equal_range()161         void test_equal_range()
162         {
163             test_equal_range_impl< std::vector<int> >();
164             test_equal_range_impl< std::list<int> >();
165             test_equal_range_impl< std::deque<int> >();
166         }
167     }
168 }
169 
170 
171 boost::unit_test::test_suite*
init_unit_test_suite(int argc,char * argv[])172 init_unit_test_suite(int argc, char* argv[])
173 {
174     boost::unit_test::test_suite* test
175         = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.equal_range" );
176 
177     test->add( BOOST_TEST_CASE( &boost::test_equal_range ) );
178 
179     return test;
180 }
181