• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
make_string(T x)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>
make_string(T1 x,T2 y)33     std::string make_string(T1 x, T2 y)
34     {
35         std::ostringstream result;
36         result << x << y;
37         return result.str();
38     }
39 
reference_result(const std::vector<boost::int32_t> & v,const std::string & separator,const std::string & prefix,const std::string & postfix)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(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 
test_formatted_0args_impl(const std::vector<boost::int32_t> & v)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(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(v);
77     BOOST_CHECK_EQUAL(out4.str(), reference_result(v, ",", "{", "}"));
78 }
79 
80 template<typename Sep>
test_formatted_1arg_impl(const std::vector<boost::int32_t> & v,const Sep & 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 
test_formatted_1arg_impl(const std::vector<boost::int32_t> & v)104 void test_formatted_1arg_impl(const std::vector<boost::int32_t>& v)
105 {
106     test_formatted_1arg_impl(v, ',');
107     test_formatted_1arg_impl(v, ' ');
108     test_formatted_1arg_impl<const char[3]>(v, ":?");
109 }
110 
111 template<typename Sep, typename Prefix>
test_formatted_2args_impl(const std::vector<boost::int32_t> & v,const Sep & sep,const Prefix & 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 
test_formatted_2args_impl(const std::vector<boost::int32_t> & v)145 void test_formatted_2args_impl(const std::vector<boost::int32_t>& v)
146 {
147     test_formatted_2args_impl(v, ',', '{');
148     test_formatted_2args_impl(v, ':', '(');
149     test_formatted_2args_impl<char, const char[3]>(v, ',', "{!");
150     test_formatted_2args_impl<const char[3], char>(v, "#$", '{');
151     test_formatted_2args_impl<const char[3], const char[3]>(v, "#$", "{!");
152 }
153 
154 template<typename Sep, typename Prefix, typename Postfix>
test_formatted_3args_impl(const std::vector<boost::int32_t> & v,const Sep & sep,const Prefix & prefix,const Postfix & 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 
test_formatted_3args_impl(const std::vector<boost::int32_t> & v)173 void test_formatted_3args_impl(const std::vector<boost::int32_t>& v)
174 {
175     test_formatted_3args_impl(v, ',', '{', '}');
176     test_formatted_3args_impl(v, ':', '(', ')');
177     test_formatted_3args_impl<char, char, const char[3]>(v, ',', '{', "!}");
178     test_formatted_3args_impl<char, const char[3], char>(v, ',', "{!", '}');
179     test_formatted_3args_impl<const char[3], char, char>(v, "#$", '{', '}');
180     test_formatted_3args_impl<
181             const char[3], const char[3], const char[3]
182     >(v, "#$", "{!", "!}");
183 }
184 
test_formatted_impl(const std::vector<boost::int32_t> & v)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 
test_formatted1()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(i);
198 
199     test_formatted_impl(v);
200 }
201 
test_formatted2()202 void test_formatted2()
203 {
204     std::vector<boost::int32_t> v;
205     v.push_back(3);
206 
207     test_formatted_impl(v);
208 }
209 
test_formatted3()210 void test_formatted3()
211 {
212     std::vector<boost::int32_t> v;
213 
214     test_formatted_impl(v);
215 }
216 
test_formatted4()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(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>&
operator <<(std::basic_ostream<Char,Traits> & out,udt_separator)232 operator<<(std::basic_ostream<Char,Traits>& out, udt_separator)
233 {
234     return out << "[sep]";
235 }
236 
test_formatted5()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(i);
242 
243     std::ostringstream out1;
244     out1 << (v | boost::adaptors::formatted(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(v, 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.
test_formatted_empty()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(v);
267     BOOST_CHECK_EQUAL(out2.str(), "{}");
268 
269     std::ostringstream out3;
270     out3 << (v | boost::adaptors::formatted(','));
271     BOOST_CHECK_EQUAL(out3.str(), "{}");
272 
273     std::ostringstream out4;
274     out4 << boost::adaptors::format(v, ',');
275     BOOST_CHECK_EQUAL(out4.str(), "{}");
276 
277     std::ostringstream out5;
278     out5 << (v | boost::adaptors::formatted("#$"));
279     BOOST_CHECK_EQUAL(out5.str(), "{}");
280 
281     std::ostringstream out6;
282     out6 << boost::adaptors::format(v, "#$");
283     BOOST_CHECK_EQUAL(out6.str(), "{}");
284 
285     std::ostringstream out7;
286     out7 << (v | boost::adaptors::formatted("", "12", "34"));
287     BOOST_CHECK_EQUAL(out7.str(), "1234");
288 
289     std::ostringstream out8;
290     out8 << boost::adaptors::format(v, "", "12", "34");
291     BOOST_CHECK_EQUAL(out8.str(), "1234");
292 }
293 
294     } // anonymous namespace
295 } // namespace boost_range_test
296 
init_unit_test_suite(int,char * [])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