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/irange.hpp>
12 #include <boost/range/algorithm_ext.hpp>
13 #include <boost/range/begin.hpp>
14 #include <boost/range/end.hpp>
15 #include <boost/test/test_tools.hpp>
16 #include <boost/test/unit_test.hpp>
17 #include <vector>
18 
19 namespace boost
20 {
21     // Test an integer range with a step size of 1.
22     template<typename Integer>
test_irange_impl(Integer last)23     void test_irange_impl(Integer last)
24     {
25         std::vector<Integer> reference;
26         for (Integer i = static_cast<Integer>(0); i < last; ++i)
27         {
28             reference.push_back(i);
29         }
30 
31         std::vector<Integer> test;
32         boost::push_back(test, boost::irange(last));
33 
34         BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
35                                        reference.begin(), reference.end() );
36     }
37 
38     // Test an integer range with a step size of 1.
39     template<typename Integer>
test_irange_impl(Integer first,Integer last)40     void test_irange_impl(Integer first, Integer last)
41     {
42         std::vector<Integer> reference;
43         for (Integer i = first; i < last; ++i)
44         {
45             reference.push_back(i);
46         }
47 
48         std::vector<Integer> test;
49         boost::push_back(test, boost::irange(first, last));
50 
51         BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
52                                        reference.begin(), reference.end() );
53     }
54 
55     // Test an integer range with a runtime specified step size.
56     template<typename Integer, typename IntegerInput>
test_irange_impl(IntegerInput first,IntegerInput last,int step)57     void test_irange_impl(IntegerInput first, IntegerInput last, int step)
58     {
59         BOOST_ASSERT( step != 0 );
60 
61         // Skip tests that have negative values if the type is
62         // unsigned
63         if ((static_cast<IntegerInput>(static_cast<Integer>(first)) != first)
64         ||  (static_cast<IntegerInput>(static_cast<Integer>(last)) != last))
65             return;
66 
67         std::vector<Integer> reference;
68 
69         const std::ptrdiff_t first_p = static_cast<std::ptrdiff_t>(first);
70         const std::ptrdiff_t last_p = static_cast<std::ptrdiff_t>(last);
71         const std::ptrdiff_t step_p = static_cast<std::ptrdiff_t>(step);
72         for (std::ptrdiff_t current_value = first_p;
73              step_p >= 0 ? current_value < last_p : current_value > last_p;
74              current_value += step_p)
75             reference.push_back(current_value);
76 
77         std::vector<Integer> test;
78         boost::push_back(test, boost::irange(first, last, step));
79 
80         BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(),
81                                        reference.begin(), reference.end() );
82     }
83 
84     // Test driver function that for an integer range [first, last)
85     // drives the test implementation through various integer
86     // types.
test_irange(int last)87     void test_irange(int last)
88     {
89         test_irange_impl<signed char>(last);
90         test_irange_impl<unsigned char>(last);
91         test_irange_impl<signed short>(last);
92         test_irange_impl<unsigned short>(last);
93         test_irange_impl<signed int>(last);
94         test_irange_impl<unsigned int>(last);
95         test_irange_impl<signed long>(last);
96         test_irange_impl<unsigned long>(last);
97     }
98 
99 
100     // Test driver function that for an integer range [first, last)
101     // drives the test implementation through various integer
102     // types.
test_irange(int first,int last)103     void test_irange(int first, int last)
104     {
105         test_irange_impl<signed char>(first,last);
106         test_irange_impl<unsigned char>(first, last);
107         test_irange_impl<signed short>(first, last);
108         test_irange_impl<unsigned short>(first, last);
109         test_irange_impl<signed int>(first, last);
110         test_irange_impl<unsigned int>(first, last);
111         test_irange_impl<signed long>(first, last);
112         test_irange_impl<unsigned long>(first, last);
113     }
114 
115     // Test driver function that for an integer range [first, last)
116     // drives the test implementation through various integer
117     // types step_size items at a time.
test_irange(int first,int last,int step_size)118     void test_irange(int first, int last, int step_size)
119     {
120         BOOST_ASSERT( step_size != 0 );
121         test_irange_impl<signed char>(first, last, step_size);
122         test_irange_impl<unsigned char>(first, last, step_size);
123         test_irange_impl<signed short>(first, last, step_size);
124         test_irange_impl<unsigned short>(first, last, step_size);
125         test_irange_impl<signed int>(first, last, step_size);
126         test_irange_impl<unsigned int>(first, last, step_size);
127         test_irange_impl<signed long>(first, last, step_size);
128         test_irange_impl<unsigned long>(first, last, step_size);
129     }
130 
131     // Implementation of the unit test for the integer range
132     // function.
133     // This starts the test drivers to drive a set of integer types
134     // for a combination of range values chosen to exercise a large
135     // number of implementation branches.
irange_unit_test()136     void irange_unit_test()
137     {
138         // Test the single-step version of irange(last)
139         test_irange(0);
140         test_irange(1);
141         test_irange(10);
142 
143         // Test the single-step version of irange(first, last)
144         test_irange(0, 0);
145         test_irange(0, 1);
146         test_irange(0, 10);
147         test_irange(1, 1);
148         test_irange(1, 2);
149         test_irange(1, 11);
150 
151         // Test the n-step version of irange(first, last, step-size)
152         test_irange(0, 0, 1);
153         test_irange(0, 0, -1);
154         test_irange(0, 10, 1);
155         test_irange(10, 0, -1);
156         test_irange(0, 2, 2);
157         test_irange(2, 0, -2);
158         test_irange(0, 9, 2);
159         test_irange(9, 0, -2);
160         test_irange(-9, 0, 2);
161         test_irange(-9, 9, 2);
162         test_irange(9, -9, -2);
163         test_irange(10, 20, 5);
164         test_irange(20, 10, -5);
165 
166         test_irange(0, 0, 3);
167         test_irange(0, 1, 3);
168         test_irange(0, 2, 3);
169         test_irange(0, 3, 3);
170         test_irange(0, 4, 3);
171         test_irange(0, 10, 3);
172 
173         test_irange(0, 0, -3);
174         test_irange(0, -1, -3);
175         test_irange(0, -2, -3);
176         test_irange(0, -3, -3);
177         test_irange(0, -4, -3);
178         test_irange(0, -10, -3);
179     }
180 } // namespace boost
181 
182 boost::unit_test::test_suite*
init_unit_test_suite(int argc,char * argv[])183 init_unit_test_suite(int argc, char* argv[])
184 {
185     boost::unit_test::test_suite* test
186         = BOOST_TEST_SUITE( "RangeTestSuite.irange" );
187 
188     test->add(BOOST_TEST_CASE( &boost::irange_unit_test ));
189 
190     return test;
191 }
192