1 // Boost.Range library
2 //
3 //  Copyright Neil Groves 2009. 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/algorithm/find_end.hpp>
12 
13 #include <boost/test/test_tools.hpp>
14 #include <boost/test/unit_test.hpp>
15 
16 #include <boost/assign.hpp>
17 #include "../test_driver/range_return_test_driver.hpp"
18 #include <algorithm>
19 #include <functional>
20 #include <vector>
21 #include <set>
22 #include <list>
23 
24 namespace boost_range_test_algorithm_find_end
25 {
26     template<class Container2>
27     class find_end_test_policy
28     {
29         typedef Container2 container2_t;
30     public:
find_end_test_policy(const Container2 & cont)31         explicit find_end_test_policy(const Container2& cont)
32             :   m_cont(cont)
33         {
34         }
35 
cont()36         container2_t cont() { return m_cont; }
37 
38         template<class Container>
39         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
test_iter(Container & cont)40         test_iter(Container& cont)
41         {
42             typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type iter_t;
43             iter_t result = boost::find_end(cont, m_cont);
44             BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), m_cont) );
45             BOOST_CHECK( result == boost::find_end(cont, boost::make_iterator_range(m_cont)) );
46             BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), boost::make_iterator_range(m_cont)) );
47             return result;
48         }
49 
50         template<boost::range_return_value return_type>
51         struct test_range
52         {
53             template<class Container, class Policy>
54             BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type
operator ()boost_range_test_algorithm_find_end::find_end_test_policy::test_range55             operator()(Policy& policy, Container& cont)
56             {
57                 typedef BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type result_t;
58                 result_t result = boost::find_end<return_type>(cont, policy.cont());
59                 BOOST_CHECK( result == boost::find_end<return_type>(boost::make_iterator_range(cont), policy.cont()) );
60                 BOOST_CHECK( result == boost::find_end<return_type>(cont, boost::make_iterator_range(policy.cont())) );
61                 BOOST_CHECK( result == boost::find_end<return_type>(boost::make_iterator_range(cont),
62                                                                     boost::make_iterator_range(policy.cont())) );
63                 return result;
64             }
65         };
66 
67         template<class Container>
68         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
reference(Container & cont)69         reference(Container& cont)
70         {
71             return std::find_end(cont.begin(), cont.end(),
72                                  m_cont.begin(), m_cont.end());
73         }
74 
75     private:
76         Container2 m_cont;
77     };
78 
79     template<class Container2, class BinaryPredicate>
80     class find_end_pred_test_policy
81     {
82         typedef Container2 container2_t;
83     public:
find_end_pred_test_policy(const Container2 & cont)84         explicit find_end_pred_test_policy(const Container2& cont)
85             :   m_cont(cont)
86         {
87         }
88 
cont()89         container2_t& cont() { return m_cont; }
pred()90         BinaryPredicate& pred() { return m_pred; }
91 
92         template<class Container>
93         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
test_iter(Container & cont)94         test_iter(Container& cont)
95         {
96             typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type iter_t;
97             iter_t it = boost::find_end(cont, m_cont, m_pred);
98             BOOST_CHECK( it == boost::find_end(boost::make_iterator_range(cont), m_cont, m_pred) );
99             BOOST_CHECK( it == boost::find_end(cont, boost::make_iterator_range(m_cont), m_pred) );
100             BOOST_CHECK( it == boost::find_end(boost::make_iterator_range(cont), boost::make_iterator_range(m_cont), m_pred) );
101             return it;
102         }
103 
104         template<boost::range_return_value return_type>
105         struct test_range
106         {
107             template<class Container, class Policy>
108             BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type
operator ()boost_range_test_algorithm_find_end::find_end_pred_test_policy::test_range109             operator()(Policy& policy, Container& cont)
110             {
111                 typedef BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type result_t;
112                 result_t result = boost::find_end<return_type>(cont, policy.cont(), policy.pred());
113                 BOOST_CHECK( result == boost::find_end<return_type>(boost::make_iterator_range(cont), policy.cont(), policy.pred()) );
114                 BOOST_CHECK( result == boost::find_end<return_type>(cont, boost::make_iterator_range(policy.cont()), policy.pred()) );
115                 BOOST_CHECK( result == boost::find_end<return_type>(boost::make_iterator_range(cont),
116                                                                     boost::make_iterator_range(policy.cont()), policy.pred()) );
117                 return boost::find_end<return_type>(cont, policy.cont(), policy.pred());
118             }
119         };
120 
121         template<class Container>
122         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
reference(Container & cont)123         reference(Container& cont)
124         {
125             return std::find_end(cont.begin(), cont.end(),
126                                  m_cont.begin(), m_cont.end(),
127                                  m_pred);
128         }
129 
130     private:
131         Container2      m_cont;
132         BinaryPredicate m_pred;
133     };
134 
135     template<class Container1, class Container2>
run_tests(Container1 & cont1,Container2 & cont2)136     void run_tests(Container1& cont1, Container2& cont2)
137     {
138         boost::range_test::range_return_test_driver test_driver;
139         test_driver(cont1, find_end_test_policy<Container2>(cont2));
140         test_driver(cont1, find_end_pred_test_policy<Container2, std::less<int> >(cont2));
141         test_driver(cont2, find_end_pred_test_policy<Container2, std::greater<int> >(cont2));
142     }
143 
144     template<class Container1, class Container2>
test_find_end_impl()145     void test_find_end_impl()
146     {
147         using namespace boost::assign;
148 
149         typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container1>::type container1_t;
150         typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container2>::type container2_t;
151 
152         container1_t mcont1;
153         Container1& cont1 = mcont1;
154         container2_t mcont2;
155         Container2& cont2 = mcont2;
156 
157         run_tests(cont1, cont2);
158 
159         mcont1 += 1;
160         run_tests(cont1, cont2);
161 
162         mcont2 += 1;
163         run_tests(cont1, cont2);
164 
165         mcont1 += 2,3,4,5,6,7,8,9;
166         mcont2 += 2,3,4;
167         run_tests(cont1, cont2);
168 
169         mcont2.clear();
170         mcont2 += 7,8,9;
171         run_tests(cont1, cont2);
172     }
173 
test_find_end()174     void test_find_end()
175     {
176         test_find_end_impl< std::vector<int>, std::vector<int> >();
177         test_find_end_impl< std::list<int>, std::list<int> >();
178         test_find_end_impl< std::deque<int>, std::deque<int> >();
179         test_find_end_impl< const std::vector<int>, const std::vector<int> >();
180         test_find_end_impl< const std::list<int>, const std::list<int> >();
181         test_find_end_impl< const std::deque<int>, const std::deque<int> >();
182         test_find_end_impl< const std::vector<int>, const std::list<int> >();
183         test_find_end_impl< const std::list<int>, const std::vector<int> >();
184         test_find_end_impl< const std::vector<int>, std::list<int> >();
185         test_find_end_impl< const std::list<int>, std::vector<int> >();
186         test_find_end_impl< std::vector<int>, std::list<int> >();
187         test_find_end_impl< std::list<int>, std::vector<int> >();
188     }
189 }
190 
191 boost::unit_test::test_suite*
init_unit_test_suite(int argc,char * argv[])192 init_unit_test_suite(int argc, char* argv[])
193 {
194     boost::unit_test::test_suite* test
195         = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.find_end" );
196 
197     test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_find_end::test_find_end ) );
198 
199     return test;
200 }
201