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> |
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> |
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> |
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. |
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. |
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. |
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: step_size); |
122 | test_irange_impl<unsigned char>(first, last, step: step_size); |
123 | test_irange_impl<signed short>(first, last, step: step_size); |
124 | test_irange_impl<unsigned short>(first, last, step: step_size); |
125 | test_irange_impl<signed int>(first, last, step: step_size); |
126 | test_irange_impl<unsigned int>(first, last, step: step_size); |
127 | test_irange_impl<signed long>(first, last, step: step_size); |
128 | test_irange_impl<unsigned long>(first, last, step: 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. |
136 | void irange_unit_test() |
137 | { |
138 | // Test the single-step version of irange(last) |
139 | test_irange(last: 0); |
140 | test_irange(last: 1); |
141 | test_irange(last: 10); |
142 | |
143 | // Test the single-step version of irange(first, last) |
144 | test_irange(first: 0, last: 0); |
145 | test_irange(first: 0, last: 1); |
146 | test_irange(first: 0, last: 10); |
147 | test_irange(first: 1, last: 1); |
148 | test_irange(first: 1, last: 2); |
149 | test_irange(first: 1, last: 11); |
150 | |
151 | // Test the n-step version of irange(first, last, step-size) |
152 | test_irange(first: 0, last: 0, step_size: 1); |
153 | test_irange(first: 0, last: 0, step_size: -1); |
154 | test_irange(first: 0, last: 10, step_size: 1); |
155 | test_irange(first: 10, last: 0, step_size: -1); |
156 | test_irange(first: 0, last: 2, step_size: 2); |
157 | test_irange(first: 2, last: 0, step_size: -2); |
158 | test_irange(first: 0, last: 9, step_size: 2); |
159 | test_irange(first: 9, last: 0, step_size: -2); |
160 | test_irange(first: -9, last: 0, step_size: 2); |
161 | test_irange(first: -9, last: 9, step_size: 2); |
162 | test_irange(first: 9, last: -9, step_size: -2); |
163 | test_irange(first: 10, last: 20, step_size: 5); |
164 | test_irange(first: 20, last: 10, step_size: -5); |
165 | |
166 | test_irange(first: 0, last: 0, step_size: 3); |
167 | test_irange(first: 0, last: 1, step_size: 3); |
168 | test_irange(first: 0, last: 2, step_size: 3); |
169 | test_irange(first: 0, last: 3, step_size: 3); |
170 | test_irange(first: 0, last: 4, step_size: 3); |
171 | test_irange(first: 0, last: 10, step_size: 3); |
172 | |
173 | test_irange(first: 0, last: 0, step_size: -3); |
174 | test_irange(first: 0, last: -1, step_size: -3); |
175 | test_irange(first: 0, last: -2, step_size: -3); |
176 | test_irange(first: 0, last: -3, step_size: -3); |
177 | test_irange(first: 0, last: -4, step_size: -3); |
178 | test_irange(first: 0, last: -10, step_size: -3); |
179 | } |
180 | } // namespace boost |
181 | |
182 | boost::unit_test::test_suite* |
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 | |