1 | // ------------------------------------------------------------------------------ |
2 | // format_test_exceptions.cpp : exception handling |
3 | // ------------------------------------------------------------------------------ |
4 | |
5 | // Copyright 2017 James E. King, III - Use, modification, and distribution are |
6 | // subject to the Boost Software License, Version 1.0. (See accompanying |
7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
8 | |
9 | // see http://www.boost.org/libs/format for library home page |
10 | |
11 | // ------------------------------------------------------------------------------ |
12 | |
13 | #include <boost/algorithm/string.hpp> |
14 | #include <boost/detail/lightweight_test.hpp> |
15 | #include <boost/format.hpp> |
16 | #include <iomanip> |
17 | #include <iostream> |
18 | |
19 | #define CHECK_INVALID_0(FMT, EX) { BOOST_TEST_THROWS((boost::format(FMT)).str(), EX); \ |
20 | boost::format safe; safe.exceptions(boost::io::no_error_bits); safe.parse(FMT); (safe).str(); } |
21 | #define CHECK_INVALID_1(FMT, _1, EX) { BOOST_TEST_THROWS((boost::format(FMT) % _1).str(), EX); \ |
22 | boost::format safe; safe.exceptions(boost::io::no_error_bits); safe.parse(FMT); (safe % _1).str(); } |
23 | #define CHECK_INVALID_2(FMT, _1, _2, EX) { BOOST_TEST_THROWS((boost::format(FMT) % _1 % _2).str(), EX); \ |
24 | boost::format safe; safe.exceptions(boost::io::no_error_bits); safe.parse(FMT); (safe % _1 % _2).str(); } |
25 | |
26 | int main(int, char* []) |
27 | { |
28 | using namespace boost::io; |
29 | |
30 | // https://svn.boost.org/trac10/ticket/8735 |
31 | |
32 | CHECK_INVALID_0("%" , bad_format_string); // no conversion specifier |
33 | CHECK_INVALID_0("%|" , bad_format_string); // truncated |
34 | CHECK_INVALID_0("%|%" , bad_format_string); // mismatched bars |
35 | CHECK_INVALID_0("%|2%" , bad_format_string); // mismatched bars |
36 | CHECK_INVALID_0("%'" , bad_format_string); // flag ' is ignored, no conversion specifier |
37 | CHECK_INVALID_0("%2" , bad_format_string); // no terminating percent |
38 | CHECK_INVALID_0("%*" , bad_format_string); // truncated |
39 | CHECK_INVALID_1("%$2" , 1, bad_format_string); // no conversion specifier |
40 | CHECK_INVALID_1("%$2.*" , 1, bad_format_string); // no conversion specifier |
41 | CHECK_INVALID_0("%0%" , bad_format_string); // positional arguments start at 1 |
42 | CHECK_INVALID_2("%1%" , 1, 2, too_many_args); |
43 | CHECK_INVALID_1("%1% %2%" , 1, too_few_args); |
44 | |
45 | CHECK_INVALID_0("%I" , bad_format_string); |
46 | CHECK_INVALID_0("%I2" , bad_format_string); |
47 | CHECK_INVALID_0("%I2d" , bad_format_string); |
48 | CHECK_INVALID_0("%I3" , bad_format_string); |
49 | CHECK_INVALID_0("%I3d" , bad_format_string); |
50 | CHECK_INVALID_0("%I32" , bad_format_string); |
51 | CHECK_INVALID_0("%I33" , bad_format_string); |
52 | CHECK_INVALID_0("%I6" , bad_format_string); |
53 | CHECK_INVALID_0("%I62" , bad_format_string); |
54 | CHECK_INVALID_0("%I63" , bad_format_string); |
55 | CHECK_INVALID_0("%I63d" , bad_format_string); |
56 | CHECK_INVALID_0("%I64" , bad_format_string); |
57 | CHECK_INVALID_0("%I128d" , bad_format_string); |
58 | CHECK_INVALID_0("%3.*4d" , bad_format_string); |
59 | |
60 | // mixing positional and non-positional |
61 | CHECK_INVALID_2("%1% %2d" , 1, 2, bad_format_string); |
62 | CHECK_INVALID_2("%2d %2%" , 1, 2, bad_format_string); |
63 | |
64 | // found while improving coverage - a number following the * for width |
65 | // or precision was being eaten instead of being treated as an error |
66 | CHECK_INVALID_0("%1$*4d" , bad_format_string); |
67 | CHECK_INVALID_0("%1$05.*32d" , bad_format_string); |
68 | CHECK_INVALID_0("%1$05.*6" , bad_format_string); |
69 | |
70 | // found while improving coverage, this caused an unhandled exception |
71 | // the "T" conversion specifier didn't handle the exception flags properly |
72 | CHECK_INVALID_0("%1$T" , bad_format_string); // missing fill character |
73 | |
74 | // test what() on exceptions |
75 | format_error base_err; |
76 | BOOST_TEST_GT(strlen(base_err.what()), 0u); |
77 | |
78 | bad_format_string bfs(2, 3); |
79 | BOOST_TEST(boost::contains(bfs.what(), "bad_format_string" )); |
80 | |
81 | too_few_args tfa(5, 4); |
82 | BOOST_TEST(boost::contains(tfa.what(), "format-string" )); |
83 | |
84 | too_many_args tma(4, 5); |
85 | BOOST_TEST(boost::contains(tma.what(), "format-string" )); |
86 | |
87 | boost::io::out_of_range oor(1, 2, 3); |
88 | BOOST_TEST(boost::contains(oor.what(), "out_of_range" )); |
89 | |
90 | // bind and unbind |
91 | boost::format two("%1%, %2%" ); |
92 | two.bind_arg(argN: 1, val: 1); |
93 | two.bind_arg(argN: 2, val: 2); |
94 | BOOST_TEST_EQ(two.str(), "1, 2" ); |
95 | |
96 | two.clear_bind(argN: 1); |
97 | BOOST_TEST_THROWS(two.str(), too_few_args); |
98 | BOOST_TEST_THROWS(two.clear_bind(1), boost::io::out_of_range); |
99 | two.exceptions(newexcept: no_error_bits); |
100 | two.clear_bind(argN: 1); |
101 | two.str(); |
102 | |
103 | return boost::report_errors(); |
104 | } |
105 | |
106 | |