]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost ios_state_test.cpp test file --------------------------------------// |
2 | ||
3 | // Copyright 2002, 2003 Daryle Walker. Use, modification, and distribution are | |
4 | // subject to the Boost Software License, Version 1.0. (See accompanying file | |
5 | // LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) | |
6 | ||
7 | // See <http://www.boost.org/libs/io/> for the library's home page. | |
8 | ||
9 | // Revision History | |
10 | // 15 Jun 2003 Adjust to changes in Boost.Test (Daryle Walker) | |
11 | // 26 Feb 2002 Initial version (Daryle Walker) | |
12 | ||
b32b8144 | 13 | #include <boost/config.hpp> |
7c673cae FG |
14 | #include <boost/test/minimal.hpp> // main, BOOST_CHECK, etc. |
15 | ||
16 | #include <boost/cstdlib.hpp> // for boost::exit_success | |
17 | #include <boost/io/ios_state.hpp> // for boost::io::ios_flags_saver, etc. | |
18 | ||
19 | #include <cstddef> // for std::size_t | |
20 | #include <iomanip> // for std::setw | |
21 | #include <ios> // for std::ios_base, std::streamsize, etc. | |
22 | #include <iostream> // for std::cout, etc. | |
23 | #include <istream> // for std::istream | |
24 | #include <locale> // for std::numpunct, std::locale | |
25 | #include <ostream> // for std::endl, std::ostream | |
26 | #include <streambuf> // for std::streambuf | |
27 | #include <string> // for std::string | |
b32b8144 FG |
28 | #if defined(BOOST_GCC) || (defined(BOOST_CLANG) && defined(BOOST_GNU_STDLIB)) |
29 | #include <stdexcept> | |
30 | #endif | |
7c673cae FG |
31 | |
32 | // Facet with the bool names spelled backwards | |
33 | class backward_bool_names | |
34 | : public std::numpunct<char> | |
35 | { | |
36 | typedef std::numpunct<char> base_type; | |
37 | ||
38 | public: | |
39 | explicit backward_bool_names( std::size_t refs = 0 ) | |
40 | : base_type( refs ) | |
41 | {} | |
42 | ||
43 | protected: | |
44 | virtual ~backward_bool_names() {} | |
45 | ||
46 | virtual base_type::string_type do_truename() const | |
47 | { return "eurt"; } | |
48 | virtual base_type::string_type do_falsename() const | |
49 | { return "eslaf"; } | |
50 | }; | |
51 | ||
52 | ||
53 | // Index to test custom storage | |
54 | int const my_index = std::ios_base::xalloc(); | |
55 | ||
56 | // Test data | |
57 | char const test_string[] = "Hello world"; | |
58 | int const test_num1 = -16; | |
59 | double const test_num2 = 34.5678901234; | |
60 | bool const test_bool = true; | |
61 | ||
62 | ||
63 | // Function prototypes | |
64 | void saver_tests_1( std::istream &input, std::ostream &output, | |
65 | std::ostream &err ); | |
66 | void saver_tests_2( std::istream &input, std::ostream &output, | |
67 | std::ostream &err ); | |
68 | ||
69 | ||
70 | // Test program | |
71 | int | |
72 | test_main | |
73 | ( | |
74 | int , // "argc" is unused | |
75 | char * [] // "argv" is unused | |
76 | ) | |
77 | { | |
78 | using std::cout; | |
79 | using std::ios_base; | |
80 | using std::streamsize; | |
81 | using std::cin; | |
82 | ||
83 | cout << "The original data is:\n"; | |
84 | cout << '\t' << test_string << '\n'; | |
85 | cout << '\t' << test_num1 << '\n'; | |
86 | cout << '\t' << test_num2 << '\n'; | |
87 | cout << '\t' << std::boolalpha << test_bool << std::endl; | |
88 | ||
89 | // Save states for comparison later | |
90 | ios_base::fmtflags const cout_flags = cout.flags(); | |
91 | streamsize const cout_precision = cout.precision(); | |
92 | streamsize const cout_width = cout.width(); | |
93 | ios_base::iostate const cout_iostate = cout.rdstate(); | |
94 | ios_base::iostate const cout_exceptions = cout.exceptions(); | |
95 | std::ostream * const cin_tie = cin.tie(); | |
96 | std::streambuf * const cout_sb = cout.rdbuf(); | |
97 | char const cout_fill = cout.fill(); | |
98 | std::locale const cout_locale = cout.getloc(); | |
99 | ||
100 | cout.iword( my_index ) = 42L; | |
101 | cout.pword( my_index ) = &cin; | |
102 | ||
103 | // Run saver tests with changing separate from saving | |
104 | saver_tests_1( cin, cout, std::cerr ); | |
105 | ||
106 | // Check if states are back to normal | |
107 | BOOST_CHECK( &cin == cout.pword(my_index) ); | |
108 | BOOST_CHECK( 42L == cout.iword(my_index) ); | |
109 | BOOST_CHECK( cout_locale == cout.getloc() ); | |
110 | BOOST_CHECK( cout_fill == cout.fill() ); | |
111 | BOOST_CHECK( cout_sb == cout.rdbuf() ); | |
112 | BOOST_CHECK( cin_tie == cin.tie() ); | |
113 | BOOST_CHECK( cout_exceptions == cout.exceptions() ); | |
114 | BOOST_CHECK( cout_iostate == cout.rdstate() ); | |
115 | BOOST_CHECK( cout_width == cout.width() ); | |
116 | BOOST_CHECK( cout_precision == cout.precision() ); | |
117 | BOOST_CHECK( cout_flags == cout.flags() ); | |
118 | ||
119 | // Run saver tests with combined saving and changing | |
120 | saver_tests_2( cin, cout, std::cerr ); | |
121 | ||
122 | // Check if states are back to normal | |
123 | BOOST_CHECK( &cin == cout.pword(my_index) ); | |
124 | BOOST_CHECK( 42L == cout.iword(my_index) ); | |
125 | BOOST_CHECK( cout_locale == cout.getloc() ); | |
126 | BOOST_CHECK( cout_fill == cout.fill() ); | |
127 | BOOST_CHECK( cout_sb == cout.rdbuf() ); | |
128 | BOOST_CHECK( cin_tie == cin.tie() ); | |
129 | BOOST_CHECK( cout_exceptions == cout.exceptions() ); | |
130 | BOOST_CHECK( cout_iostate == cout.rdstate() ); | |
131 | BOOST_CHECK( cout_width == cout.width() ); | |
132 | BOOST_CHECK( cout_precision == cout.precision() ); | |
133 | BOOST_CHECK( cout_flags == cout.flags() ); | |
134 | ||
135 | return boost::exit_success; | |
136 | } | |
137 | ||
138 | // Save, change, and restore stream properties | |
139 | void | |
140 | saver_tests_1 | |
141 | ( | |
142 | std::istream & input, | |
143 | std::ostream & output, | |
144 | std::ostream & err | |
145 | ) | |
146 | { | |
147 | using std::locale; | |
148 | using std::ios_base; | |
149 | using std::setw; | |
150 | ||
151 | boost::io::ios_flags_saver const ifls( output ); | |
152 | boost::io::ios_precision_saver const iprs( output ); | |
153 | boost::io::ios_width_saver const iws( output ); | |
154 | boost::io::ios_tie_saver const its( input ); | |
155 | boost::io::ios_rdbuf_saver const irs( output ); | |
156 | boost::io::ios_fill_saver const ifis( output ); | |
157 | boost::io::ios_locale_saver const ils( output ); | |
158 | boost::io::ios_iword_saver const iis( output, my_index ); | |
159 | boost::io::ios_pword_saver const ipws( output, my_index ); | |
160 | ||
161 | locale loc( locale::classic(), new backward_bool_names ); | |
162 | ||
163 | input.tie( &err ); | |
164 | output.rdbuf( err.rdbuf() ); | |
165 | output.iword( my_index ) = 69L; | |
166 | output.pword( my_index ) = &err; | |
167 | ||
168 | output << "The data is (again):\n"; | |
169 | output.setf( ios_base::showpos | ios_base::boolalpha ); | |
170 | output.setf( ios_base::internal, ios_base::adjustfield ); | |
171 | output.fill( '@' ); | |
172 | output.precision( 9 ); | |
173 | output << '\t' << test_string << '\n'; | |
174 | output << '\t' << setw( 10 ) << test_num1 << '\n'; | |
175 | output << '\t' << setw( 15 ) << test_num2 << '\n'; | |
176 | output.imbue( loc ); | |
177 | output << '\t' << test_bool << '\n'; | |
178 | ||
179 | BOOST_CHECK( &err == output.pword(my_index) ); | |
180 | BOOST_CHECK( 69L == output.iword(my_index) ); | |
181 | ||
182 | try | |
183 | { | |
184 | boost::io::ios_exception_saver const ies( output ); | |
185 | boost::io::ios_iostate_saver const iis( output ); | |
186 | ||
b32b8144 | 187 | output.exceptions( ios_base::eofbit | ios_base::badbit ); |
7c673cae FG |
188 | output.setstate( ios_base::eofbit ); |
189 | BOOST_ERROR( "previous line should have thrown" ); | |
190 | } | |
b32b8144 FG |
191 | #if defined(BOOST_GCC) || (defined(BOOST_CLANG) && defined(BOOST_GNU_STDLIB)) |
192 | catch ( std::exception &f ) | |
193 | #else | |
7c673cae | 194 | catch ( ios_base::failure &f ) |
b32b8144 | 195 | #endif |
7c673cae FG |
196 | { |
197 | err << "Got the expected I/O failure: \"" << f.what() << "\".\n"; | |
198 | BOOST_CHECK( output.exceptions() == ios_base::goodbit ); | |
199 | } | |
200 | catch ( ... ) | |
201 | { | |
202 | err << "Got an unknown error when doing exception test!\n"; | |
203 | throw; | |
204 | } | |
205 | } | |
206 | ||
207 | // Save & change and restore stream properties | |
208 | void | |
209 | saver_tests_2 | |
210 | ( | |
211 | std::istream & input, | |
212 | std::ostream & output, | |
213 | std::ostream & err | |
214 | ) | |
215 | { | |
216 | using std::locale; | |
217 | using std::ios_base; | |
218 | ||
219 | boost::io::ios_tie_saver const its( input, &err ); | |
220 | boost::io::ios_rdbuf_saver const irs( output, err.rdbuf() ); | |
221 | boost::io::ios_iword_saver const iis( output, my_index, 69L ); | |
222 | boost::io::ios_pword_saver const ipws( output, my_index, &err ); | |
223 | output << "The data is (a third time; adding the numbers):\n"; | |
224 | ||
225 | boost::io::ios_flags_saver const ifls( output, (output.flags() | |
226 | & ~ios_base::adjustfield) | ios_base::showpos | ios_base::boolalpha | |
227 | | (ios_base::internal & ios_base::adjustfield) ); | |
228 | boost::io::ios_precision_saver const iprs( output, 9 ); | |
229 | boost::io::ios_fill_saver const ifis( output, '@' ); | |
230 | output << '\t' << test_string << '\n'; | |
231 | ||
232 | boost::io::ios_width_saver const iws( output, 12 ); | |
233 | output.put( '\t' ); | |
234 | output << test_num1 + test_num2; | |
235 | output.put( '\n' ); | |
236 | ||
237 | locale loc( locale::classic(), | |
238 | new backward_bool_names ); | |
239 | boost::io::ios_locale_saver const ils( output, loc ); | |
240 | output << '\t' << test_bool << '\n'; | |
241 | ||
242 | BOOST_CHECK( &err == output.pword(my_index) ); | |
243 | BOOST_CHECK( 69L == output.iword(my_index) ); | |
244 | ||
245 | try | |
246 | { | |
247 | boost::io::ios_exception_saver const ies( output, ios_base::eofbit ); | |
248 | boost::io::ios_iostate_saver const iis( output, output.rdstate() | |
249 | | ios_base::eofbit ); | |
250 | ||
251 | BOOST_ERROR( "previous line should have thrown" ); | |
252 | } | |
b32b8144 FG |
253 | #if defined(BOOST_GCC) || (defined(BOOST_CLANG) && defined(BOOST_GNU_STDLIB)) |
254 | catch ( std::exception &f ) | |
255 | #else | |
7c673cae | 256 | catch ( ios_base::failure &f ) |
b32b8144 | 257 | #endif |
7c673cae FG |
258 | { |
259 | err << "Got the expected I/O failure: \"" << f.what() << "\".\n"; | |
260 | BOOST_CHECK( output.exceptions() == ios_base::goodbit ); | |
261 | } | |
262 | catch ( ... ) | |
263 | { | |
264 | err << "Got an unknown error when doing exception test!\n"; | |
265 | throw; | |
266 | } | |
267 | } |