formatted.cpp 8.9 KB

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