1 | // Boost.Range library |
2 | // |
3 | // Copyright Neil Groves 2014. 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 | // For more information, see http://www.boost.org/libs/range/ |
9 | // |
10 | #include <boost/range/adaptor/formatted.hpp> |
11 | #include <boost/cstdint.hpp> |
12 | #include <boost/test/test_tools.hpp> |
13 | #include <boost/test/unit_test.hpp> |
14 | #include <iostream> |
15 | #include <string> |
16 | #include <sstream> |
17 | #include <vector> |
18 | |
19 | namespace boost_range_test |
20 | { |
21 | namespace |
22 | { |
23 | |
24 | template<typename T> |
25 | std::string make_string(T x) |
26 | { |
27 | std::ostringstream result; |
28 | result << x; |
29 | return result.str(); |
30 | } |
31 | |
32 | template<typename T1, typename T2> |
33 | std::string make_string(T1 x, T2 y) |
34 | { |
35 | std::ostringstream result; |
36 | result << x << y; |
37 | return result.str(); |
38 | } |
39 | |
40 | std::string reference_result(const std::vector<boost::int32_t>& v, |
41 | const std::string& separator, |
42 | const std::string& prefix, |
43 | const std::string& postfix) |
44 | { |
45 | std::ostringstream out; |
46 | out << prefix; |
47 | if (!v.empty()) |
48 | { |
49 | out << v.at(n: 0); |
50 | std::vector<boost::int32_t>::const_iterator it = v.begin(); |
51 | for (++it; it != v.end(); ++it) |
52 | { |
53 | out << separator << *it; |
54 | } |
55 | } |
56 | out << postfix; |
57 | |
58 | return out.str(); |
59 | } |
60 | |
61 | void test_formatted_0args_impl(const std::vector<boost::int32_t>& v) |
62 | { |
63 | std::ostringstream out1; |
64 | out1 << '[' << (v | boost::adaptors::formatted()) << ']'; |
65 | BOOST_CHECK_EQUAL(out1.str(), reference_result(v, "," , "[{" , "}]" )); |
66 | |
67 | std::ostringstream out2; |
68 | out2 << '[' << boost::adaptors::format(rng: v) << ']'; |
69 | BOOST_CHECK_EQUAL(out2.str(), reference_result(v, "," , "[{" , "}]" )); |
70 | |
71 | std::ostringstream out3; |
72 | out3 << (v | boost::adaptors::formatted()); |
73 | BOOST_CHECK_EQUAL(out3.str(), reference_result(v, "," , "{" , "}" )); |
74 | |
75 | std::ostringstream out4; |
76 | out4 << boost::adaptors::format(rng: v); |
77 | BOOST_CHECK_EQUAL(out4.str(), reference_result(v, "," , "{" , "}" )); |
78 | } |
79 | |
80 | template<typename Sep> |
81 | void test_formatted_1arg_impl( |
82 | const std::vector<boost::int32_t>& v, |
83 | const Sep& sep) |
84 | { |
85 | const std::string ref_sep = make_string(sep); |
86 | std::ostringstream out1; |
87 | out1 << '[' << (v | boost::adaptors::formatted(sep)) << ']'; |
88 | |
89 | BOOST_CHECK_EQUAL(out1.str(), reference_result(v, ref_sep, "[{" , "}]" )); |
90 | |
91 | std::ostringstream out2; |
92 | out2 << '[' << boost::adaptors::format(v, sep) << ']'; |
93 | BOOST_CHECK_EQUAL(out2.str(), reference_result(v, ref_sep, "[{" , "}]" )); |
94 | |
95 | std::ostringstream out3; |
96 | out3 << (v | boost::adaptors::formatted(sep)); |
97 | BOOST_CHECK_EQUAL(out3.str(), reference_result(v, ref_sep, "{" , "}" )); |
98 | |
99 | std::ostringstream out4; |
100 | out4 << boost::adaptors::format(v, sep); |
101 | BOOST_CHECK_EQUAL(out4.str(), reference_result(v, ref_sep, "{" , "}" )); |
102 | } |
103 | |
104 | void test_formatted_1arg_impl(const std::vector<boost::int32_t>& v) |
105 | { |
106 | test_formatted_1arg_impl(v, sep: ','); |
107 | test_formatted_1arg_impl(v, sep: ' '); |
108 | test_formatted_1arg_impl<const char[3]>(v, sep: ":?" ); |
109 | } |
110 | |
111 | template<typename Sep, typename Prefix> |
112 | void test_formatted_2args_impl( |
113 | const std::vector<boost::int32_t>& v, |
114 | const Sep& sep, |
115 | const Prefix& prefix |
116 | ) |
117 | { |
118 | const std::string ref_sep = make_string(sep); |
119 | |
120 | std::ostringstream out1; |
121 | out1 << '[' << (v | boost::adaptors::formatted(sep, prefix)) << ']'; |
122 | BOOST_CHECK_EQUAL( |
123 | out1.str(), |
124 | reference_result(v, ref_sep, make_string('[', prefix), "}]" )); |
125 | |
126 | std::ostringstream out2; |
127 | out2 << '[' << boost::adaptors::format(v, sep, prefix) << ']'; |
128 | BOOST_CHECK_EQUAL( |
129 | out2.str(), |
130 | reference_result(v, ref_sep, make_string('[', prefix), "}]" )); |
131 | |
132 | std::ostringstream out3; |
133 | out3 << (v | boost::adaptors::formatted(sep, prefix)); |
134 | BOOST_CHECK_EQUAL( |
135 | out3.str(), |
136 | reference_result(v, ref_sep, make_string(prefix), "}" )); |
137 | |
138 | std::ostringstream out4; |
139 | out4 << boost::adaptors::format(v, sep, prefix); |
140 | BOOST_CHECK_EQUAL( |
141 | out4.str(), |
142 | reference_result(v, ref_sep, make_string(prefix), "}" )); |
143 | } |
144 | |
145 | void test_formatted_2args_impl(const std::vector<boost::int32_t>& v) |
146 | { |
147 | test_formatted_2args_impl(v, sep: ',', prefix: '{'); |
148 | test_formatted_2args_impl(v, sep: ':', prefix: '('); |
149 | test_formatted_2args_impl<char, const char[3]>(v, sep: ',', prefix: "{!" ); |
150 | test_formatted_2args_impl<const char[3], char>(v, sep: "#$" , prefix: '{'); |
151 | test_formatted_2args_impl<const char[3], const char[3]>(v, sep: "#$" , prefix: "{!" ); |
152 | } |
153 | |
154 | template<typename Sep, typename Prefix, typename Postfix> |
155 | void test_formatted_3args_impl( |
156 | const std::vector<boost::int32_t>& v, |
157 | const Sep& sep, |
158 | const Prefix& prefix, |
159 | const Postfix& postfix |
160 | ) |
161 | { |
162 | const std::string ref_sep = make_string(sep); |
163 | |
164 | std::ostringstream out1; |
165 | out1 << '[' << (v | boost::adaptors::formatted(sep, prefix, postfix)) |
166 | << ']'; |
167 | BOOST_CHECK_EQUAL( |
168 | out1.str(), |
169 | reference_result(v, ref_sep, make_string('[', prefix), |
170 | make_string(postfix, ']'))); |
171 | } |
172 | |
173 | void test_formatted_3args_impl(const std::vector<boost::int32_t>& v) |
174 | { |
175 | test_formatted_3args_impl(v, sep: ',', prefix: '{', postfix: '}'); |
176 | test_formatted_3args_impl(v, sep: ':', prefix: '(', postfix: ')'); |
177 | test_formatted_3args_impl<char, char, const char[3]>(v, sep: ',', prefix: '{', postfix: "!}" ); |
178 | test_formatted_3args_impl<char, const char[3], char>(v, sep: ',', prefix: "{!" , postfix: '}'); |
179 | test_formatted_3args_impl<const char[3], char, char>(v, sep: "#$" , prefix: '{', postfix: '}'); |
180 | test_formatted_3args_impl< |
181 | const char[3], const char[3], const char[3] |
182 | >(v, sep: "#$" , prefix: "{!" , postfix: "!}" ); |
183 | } |
184 | |
185 | void test_formatted_impl(const std::vector<boost::int32_t>& v) |
186 | { |
187 | test_formatted_0args_impl(v); |
188 | test_formatted_1arg_impl(v); |
189 | test_formatted_2args_impl(v); |
190 | test_formatted_3args_impl(v); |
191 | } |
192 | |
193 | void test_formatted1() |
194 | { |
195 | std::vector<boost::int32_t> v; |
196 | for (boost::int32_t i = 0; i < 10; ++i) |
197 | v.push_back(x: i); |
198 | |
199 | test_formatted_impl(v); |
200 | } |
201 | |
202 | void test_formatted2() |
203 | { |
204 | std::vector<boost::int32_t> v; |
205 | v.push_back(x: 3); |
206 | |
207 | test_formatted_impl(v); |
208 | } |
209 | |
210 | void test_formatted3() |
211 | { |
212 | std::vector<boost::int32_t> v; |
213 | |
214 | test_formatted_impl(v); |
215 | } |
216 | |
217 | void test_formatted4() |
218 | { |
219 | std::vector<boost::int32_t> v; |
220 | for (boost::int32_t i = 0; i < 5; ++i) |
221 | v.push_back(x: i); |
222 | |
223 | test_formatted_impl(v); |
224 | } |
225 | |
226 | struct udt_separator |
227 | { |
228 | }; |
229 | |
230 | template<typename Char, typename Traits> |
231 | inline std::basic_ostream<Char,Traits>& |
232 | operator<<(std::basic_ostream<Char,Traits>& out, udt_separator) |
233 | { |
234 | return out << "[sep]" ; |
235 | } |
236 | |
237 | void test_formatted5() |
238 | { |
239 | std::vector<boost::int32_t> v; |
240 | for (boost::int32_t i = 0; i < 5; ++i) |
241 | v.push_back(x: i); |
242 | |
243 | std::ostringstream out1; |
244 | out1 << (v | boost::adaptors::formatted(sep: udt_separator())); |
245 | BOOST_CHECK_EQUAL(out1.str(), "{0[sep]1[sep]2[sep]3[sep]4}" ); |
246 | |
247 | std::ostringstream out2; |
248 | out2 << boost::adaptors::format(rng: v, sep: udt_separator()); |
249 | BOOST_CHECK_EQUAL(out2.str(), "{0[sep]1[sep]2[sep]3[sep]4}" ); |
250 | } |
251 | |
252 | // This test is already covered by the more complex code above. This |
253 | // code duplicates coverage to ensure that char literal arrays are handled |
254 | // correctly. I was particularly concerned that my test code above may pass |
255 | // erroneously by decaying a char literal to a pointer. This function makes |
256 | // it very plain that character literal strings work. |
257 | void test_formatted_empty() |
258 | { |
259 | std::vector<boost::int32_t> v; |
260 | |
261 | std::ostringstream out1; |
262 | out1 << (v | boost::adaptors::formatted()); |
263 | BOOST_CHECK_EQUAL(out1.str(), "{}" ); |
264 | |
265 | std::ostringstream out2; |
266 | out2 << boost::adaptors::format(rng: v); |
267 | BOOST_CHECK_EQUAL(out2.str(), "{}" ); |
268 | |
269 | std::ostringstream out3; |
270 | out3 << (v | boost::adaptors::formatted(sep: ',')); |
271 | BOOST_CHECK_EQUAL(out3.str(), "{}" ); |
272 | |
273 | std::ostringstream out4; |
274 | out4 << boost::adaptors::format(rng: v, sep: ','); |
275 | BOOST_CHECK_EQUAL(out4.str(), "{}" ); |
276 | |
277 | std::ostringstream out5; |
278 | out5 << (v | boost::adaptors::formatted(sep: "#$" )); |
279 | BOOST_CHECK_EQUAL(out5.str(), "{}" ); |
280 | |
281 | std::ostringstream out6; |
282 | out6 << boost::adaptors::format(rng: v, sep: "#$" ); |
283 | BOOST_CHECK_EQUAL(out6.str(), "{}" ); |
284 | |
285 | std::ostringstream out7; |
286 | out7 << (v | boost::adaptors::formatted(sep: "" , prefix: "12" , postfix: "34" )); |
287 | BOOST_CHECK_EQUAL(out7.str(), "1234" ); |
288 | |
289 | std::ostringstream out8; |
290 | out8 << boost::adaptors::format(rng: v, sep: "" , prefix: "12" , postfix: "34" ); |
291 | BOOST_CHECK_EQUAL(out8.str(), "1234" ); |
292 | } |
293 | |
294 | } // anonymous namespace |
295 | } // namespace boost_range_test |
296 | |
297 | boost::unit_test::test_suite* init_unit_test_suite(int, char*[] ) |
298 | { |
299 | boost::unit_test::test_suite* test = |
300 | BOOST_TEST_SUITE( "Boost.Range formatted test suite" ); |
301 | |
302 | test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted1)); |
303 | test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted2)); |
304 | test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted3)); |
305 | test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted4)); |
306 | test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted5)); |
307 | |
308 | test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted_empty)); |
309 | |
310 | return test; |
311 | } |
312 | |