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
19namespace 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
40std::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
61void 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
80template<typename Sep>
81void 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
104void 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
111template<typename Sep, typename Prefix>
112void 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
145void 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
154template<typename Sep, typename Prefix, typename Postfix>
155void 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
173void 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
185void 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
193void 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
202void test_formatted2()
203{
204 std::vector<boost::int32_t> v;
205 v.push_back(x: 3);
206
207 test_formatted_impl(v);
208}
209
210void test_formatted3()
211{
212 std::vector<boost::int32_t> v;
213
214 test_formatted_impl(v);
215}
216
217void 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
226struct udt_separator
227{
228};
229
230template<typename Char, typename Traits>
231inline std::basic_ostream<Char,Traits>&
232operator<<(std::basic_ostream<Char,Traits>& out, udt_separator)
233{
234 return out << "[sep]";
235}
236
237void 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.
257void 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
297boost::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

source code of boost/libs/range/test/adaptor_test/formatted.cpp