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
26int 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

source code of boost/libs/format/test/format_test_exceptions.cpp