1 /*
2 Copyright 2003 Daryle Walker
3
4 Copyright 2019 Glen Joseph Fernandes
5 (glenjofe@gmail.com)
6
7 Distributed under the Boost Software License, Version 1.0.
8 (http://www.boost.org/LICENSE_1_0.txt)
9 */
10 #include <boost/io/ios_state.hpp>
11 #include <boost/core/lightweight_test.hpp>
12 #include <boost/config.hpp>
13 #include <iomanip>
14 #include <ios>
15 #include <iostream>
16 #include <istream>
17 #include <locale>
18 #if defined(BOOST_GCC) || (defined(BOOST_CLANG) && defined(BOOST_GNU_STDLIB))
19 #include <stdexcept>
20 #endif
21 #include <sstream>
22 #include <cstddef>
23
24 class backward_bool_names
25 : public std::numpunct<char> {
26 typedef std::numpunct<char> base_type;
27
28 public:
backward_bool_names(std::size_t refs=0)29 explicit backward_bool_names(std::size_t refs = 0)
30 : base_type(refs) { }
31
32 protected:
~backward_bool_names()33 ~backward_bool_names() { }
34
do_truename() const35 base_type::string_type do_truename() const {
36 return "eurt";
37 }
38
do_falsename() const39 base_type::string_type do_falsename() const {
40 return "eslaf";
41 }
42 };
43
44 void
ios_flags_saver_unit_test()45 ios_flags_saver_unit_test()
46 {
47 std::stringstream ss;
48 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
49 {
50 boost::io::ios_flags_saver ifs(ss);
51 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
52 ss << std::noskipws << std::fixed << std::boolalpha;
53 BOOST_TEST_EQ(std::ios_base::boolalpha |
54 std::ios_base::dec |
55 std::ios_base::fixed, ss.flags());
56 }
57 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
58 {
59 boost::io::ios_flags_saver ifs(ss,
60 std::ios_base::showbase | std::ios_base::internal);
61 BOOST_TEST_EQ(std::ios_base::showbase |
62 std::ios_base::internal, ss.flags());
63 ss << std::setiosflags(std::ios_base::unitbuf);
64 BOOST_TEST_EQ(std::ios_base::showbase |
65 std::ios_base::internal |
66 std::ios_base::unitbuf, ss.flags());
67 }
68 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
69 }
70
71 void
ios_precision_saver_unit_test()72 ios_precision_saver_unit_test()
73 {
74 std::stringstream ss;
75 BOOST_TEST_EQ(6, ss.precision());
76 {
77 boost::io::ios_precision_saver ips(ss);
78 BOOST_TEST_EQ(6, ss.precision());
79 ss << std::setprecision(4);
80 BOOST_TEST_EQ(4, ss.precision());
81 }
82 BOOST_TEST_EQ(6, ss.precision());
83 {
84 boost::io::ios_precision_saver ips(ss, 8);
85 BOOST_TEST_EQ(8, ss.precision());
86 ss << std::setprecision(10);
87 BOOST_TEST_EQ(10, ss.precision());
88 }
89 BOOST_TEST_EQ(6, ss.precision());
90 }
91
92 void
ios_width_saver_unit_test()93 ios_width_saver_unit_test()
94 {
95 std::stringstream ss;
96 BOOST_TEST_EQ(0, ss.width());
97 {
98 boost::io::ios_width_saver iws(ss);
99 BOOST_TEST_EQ(0, ss.width());
100 ss << std::setw(4);
101 BOOST_TEST_EQ(4, ss.width());
102 }
103 BOOST_TEST_EQ(0, ss.width());
104 {
105 boost::io::ios_width_saver iws(ss, 8);
106 BOOST_TEST_EQ(8, ss.width());
107 ss << std::setw(10);
108 BOOST_TEST_EQ(10, ss.width());
109 }
110 BOOST_TEST_EQ(0, ss.width());
111 }
112
113 void
ios_iostate_saver_unit_test()114 ios_iostate_saver_unit_test()
115 {
116 std::stringstream ss;
117 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
118 BOOST_TEST(ss.good());
119 {
120 boost::io::ios_iostate_saver iis(ss);
121 char c;
122 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
123 BOOST_TEST(ss.good());
124 ss >> c;
125 BOOST_TEST_EQ(std::ios_base::eofbit | std::ios_base::failbit,
126 ss.rdstate());
127 BOOST_TEST(ss.eof());
128 BOOST_TEST(ss.fail());
129 BOOST_TEST(!ss.bad());
130 }
131 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
132 BOOST_TEST(ss.good());
133 {
134 boost::io::ios_iostate_saver iis(ss, std::ios_base::eofbit);
135 BOOST_TEST_EQ(std::ios_base::eofbit, ss.rdstate());
136 BOOST_TEST(ss.eof());
137 ss.setstate(std::ios_base::badbit);
138 BOOST_TEST_EQ(std::ios_base::eofbit | std::ios_base::badbit,
139 ss.rdstate());
140 BOOST_TEST(ss.eof());
141 BOOST_TEST(ss.fail());
142 BOOST_TEST(ss.bad());
143 }
144 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
145 BOOST_TEST(ss.good());
146 }
147
148 void
ios_exception_saver_unit_test()149 ios_exception_saver_unit_test()
150 {
151 std::stringstream ss;
152 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
153 {
154 boost::io::ios_exception_saver ies(ss);
155 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
156 ss.exceptions(std::ios_base::failbit);
157 BOOST_TEST_EQ(std::ios_base::failbit, ss.exceptions());
158 {
159 boost::io::ios_iostate_saver iis(ss);
160 ss.exceptions(std::ios_base::failbit | std::ios_base::badbit);
161 char c;
162 #if defined(BOOST_GCC) || (defined(BOOST_CLANG) && defined(BOOST_GNU_STDLIB))
163 BOOST_TEST_THROWS(ss >> c, std::exception);
164 #else
165 BOOST_TEST_THROWS(ss >> c, std::ios_base::failure);
166 #endif
167 }
168 }
169 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
170 {
171 boost::io::ios_exception_saver ies(ss, std::ios_base::eofbit);
172 BOOST_TEST_EQ(std::ios_base::eofbit, ss.exceptions());
173 ss.exceptions(std::ios_base::badbit);
174 BOOST_TEST_EQ(std::ios_base::badbit, ss.exceptions());
175 {
176 boost::io::ios_iostate_saver iis(ss);
177 char c;
178 BOOST_TEST_NOT(ss >> c);
179 }
180 }
181 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
182 }
183
184 void
ios_tie_saver_unit_test()185 ios_tie_saver_unit_test()
186 {
187 BOOST_TEST(NULL == std::cout.tie());
188 {
189 boost::io::ios_tie_saver its(std::cout);
190 BOOST_TEST(NULL == std::cout.tie());
191 std::cout.tie(&std::clog);
192 BOOST_TEST_EQ(&std::clog, std::cout.tie());
193 }
194 BOOST_TEST(NULL == std::cout.tie());
195 {
196 boost::io::ios_tie_saver its(std::cout, &std::clog);
197 BOOST_TEST_EQ(&std::clog, std::cout.tie());
198 std::cout.tie(&std::cerr);
199 BOOST_TEST_EQ(&std::cerr, std::cout.tie());
200 }
201 BOOST_TEST(NULL == std::cout.tie());
202 }
203
204 void
ios_rdbuf_saver_unit_test()205 ios_rdbuf_saver_unit_test()
206 {
207 std::iostream s(NULL);
208 BOOST_TEST(NULL == s.rdbuf());
209 {
210 std::stringbuf sb;
211 boost::io::ios_rdbuf_saver irs(s);
212 BOOST_TEST(NULL == s.rdbuf());
213 s.rdbuf(&sb);
214 BOOST_TEST_EQ(&sb, s.rdbuf());
215 }
216 BOOST_TEST(NULL == s.rdbuf());
217 {
218 std::stringbuf sb1, sb2("Hi there");
219 boost::io::ios_rdbuf_saver irs(s, &sb1);
220 BOOST_TEST_EQ(&sb1, s.rdbuf());
221 s.rdbuf(&sb2);
222 BOOST_TEST_EQ(&sb2, s.rdbuf());
223 }
224 BOOST_TEST(NULL == s.rdbuf());
225 }
226
227 void
ios_fill_saver_unit_test()228 ios_fill_saver_unit_test()
229 {
230 std::stringstream ss;
231 BOOST_TEST_EQ(' ', ss.fill());
232 {
233 boost::io::ios_fill_saver ifs(ss);
234 BOOST_TEST_EQ(' ', ss.fill());
235 ss.fill('x');
236 BOOST_TEST_EQ('x', ss.fill());
237 }
238 BOOST_TEST_EQ(' ', ss.fill());
239 {
240 boost::io::ios_fill_saver ifs(ss, '3');
241 BOOST_TEST_EQ('3', ss.fill());
242 ss.fill('+');
243 BOOST_TEST_EQ('+', ss.fill());
244 }
245 BOOST_TEST_EQ(' ', ss.fill());
246 }
247
248 void
ios_locale_saver_unit_test()249 ios_locale_saver_unit_test()
250 {
251 typedef std::numpunct<char> npc_type;
252 std::stringstream ss;
253 BOOST_TEST(std::locale() == ss.getloc());
254 BOOST_TEST(!std::has_facet<npc_type>(ss.getloc()) ||
255 !dynamic_cast<const backward_bool_names*>(&
256 std::use_facet<npc_type>(ss.getloc())));
257 {
258 boost::io::ios_locale_saver ils(ss);
259 BOOST_TEST(std::locale() == ss.getloc());
260 ss.imbue(std::locale::classic());
261 BOOST_TEST(std::locale::classic() == ss.getloc());
262 }
263 BOOST_TEST(std::locale() == ss.getloc());
264 BOOST_TEST(!std::has_facet<npc_type>(ss.getloc()) ||
265 !dynamic_cast<const backward_bool_names*>(&
266 std::use_facet<npc_type>(ss.getloc())));
267 {
268 boost::io::ios_locale_saver ils(ss, std::locale::classic());
269 BOOST_TEST(std::locale::classic() == ss.getloc());
270 BOOST_TEST(!std::has_facet<npc_type>(ss.getloc()) ||
271 !dynamic_cast<const backward_bool_names*>(&
272 std::use_facet<npc_type>(ss.getloc())));
273 ss.imbue(std::locale(std::locale::classic(), new backward_bool_names));
274 BOOST_TEST(std::locale::classic() != ss.getloc());
275 BOOST_TEST(std::has_facet<npc_type>(ss.getloc()) &&
276 dynamic_cast<const backward_bool_names*>(&
277 std::use_facet<npc_type>(ss.getloc())));
278 }
279 BOOST_TEST(std::locale() == ss.getloc());
280 BOOST_TEST(!std::has_facet<npc_type>(ss.getloc()) ||
281 !dynamic_cast<const backward_bool_names*>(&
282 std::use_facet<npc_type>(ss.getloc())));
283 }
284
285 void
ios_iword_saver_unit_test(int index)286 ios_iword_saver_unit_test(int index)
287 {
288 std::stringstream ss;
289 BOOST_TEST_EQ(0, ss.iword(index));
290 {
291 boost::io::ios_iword_saver iis(ss, index);
292 BOOST_TEST_EQ(0, ss.iword(index));
293 ss.iword(index) = 6;
294 BOOST_TEST_EQ(6, ss.iword(index));
295 }
296 BOOST_TEST_EQ(0, ss.iword(index));
297 {
298 boost::io::ios_iword_saver iis(ss, index, 100);
299 BOOST_TEST_EQ(100, ss.iword(index));
300 ss.iword(index) = -2000;
301 BOOST_TEST_EQ(-2000, ss.iword(index));
302 }
303 BOOST_TEST_EQ(0, ss.iword(index));
304 }
305
306 void
ios_pword_saver_unit_test(int index)307 ios_pword_saver_unit_test(int index)
308 {
309 std::stringstream ss;
310 BOOST_TEST(NULL == ss.pword(index));
311 {
312 boost::io::ios_pword_saver ips(ss, index);
313 BOOST_TEST(NULL == ss.pword(index));
314 ss.pword(index) = &ss;
315 BOOST_TEST_EQ(&ss, ss.pword(index));
316 }
317 BOOST_TEST(NULL == ss.pword(index));
318 {
319 boost::io::ios_pword_saver ips(ss, index, ss.rdbuf());
320 BOOST_TEST_EQ(ss.rdbuf(), ss.pword(index));
321 ss.pword(index) = &ss;
322 BOOST_TEST_EQ(&ss, ss.pword(index));
323 }
324 BOOST_TEST(NULL == ss.pword(index));
325 }
326
327 void
ios_base_all_saver_unit_test()328 ios_base_all_saver_unit_test()
329 {
330 std::stringstream ss;
331 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
332 BOOST_TEST_EQ(6, ss.precision());
333 BOOST_TEST_EQ(0, ss.width());
334 {
335 boost::io::ios_base_all_saver ibas(ss);
336 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
337 BOOST_TEST_EQ(6, ss.precision());
338 BOOST_TEST_EQ(0, ss.width());
339 ss << std::hex << std::unitbuf << std::setprecision(5) << std::setw(7);
340 BOOST_TEST_EQ(std::ios_base::unitbuf |
341 std::ios_base::hex |
342 std::ios_base::skipws, ss.flags());
343 BOOST_TEST_EQ(5, ss.precision());
344 BOOST_TEST_EQ(7, ss.width());
345 }
346 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
347 BOOST_TEST_EQ(6, ss.precision());
348 BOOST_TEST_EQ(0, ss.width());
349 }
350
351 void
ios_all_saver_unit_test()352 ios_all_saver_unit_test()
353 {
354 typedef std::numpunct<char> npc_type;
355 std::stringbuf sb;
356 std::iostream ss(&sb);
357 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
358 BOOST_TEST_EQ(6, ss.precision());
359 BOOST_TEST_EQ(0, ss.width());
360 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
361 BOOST_TEST(ss.good());
362 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
363 BOOST_TEST(NULL == ss.tie());
364 BOOST_TEST(&sb == ss.rdbuf());
365 BOOST_TEST_EQ(' ', ss.fill());
366 BOOST_TEST(std::locale() == ss.getloc());
367 {
368 boost::io::ios_all_saver ias(ss);
369 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
370 BOOST_TEST_EQ(6, ss.precision());
371 BOOST_TEST_EQ(0, ss.width());
372 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
373 BOOST_TEST(ss.good());
374 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
375 BOOST_TEST(NULL == ss.tie());
376 BOOST_TEST(&sb == ss.rdbuf());
377 BOOST_TEST_EQ(' ', ss.fill());
378 BOOST_TEST(std::locale() == ss.getloc());
379 ss << std::oct << std::showpos << std::noskipws;
380 BOOST_TEST_EQ(std::ios_base::showpos | std::ios_base::oct, ss.flags());
381 ss << std::setprecision(3);
382 BOOST_TEST_EQ(3, ss.precision());
383 ss << std::setw(9);
384 BOOST_TEST_EQ(9, ss.width());
385 ss.setstate(std::ios_base::eofbit);
386 BOOST_TEST_EQ(std::ios_base::eofbit, ss.rdstate());
387 BOOST_TEST(ss.eof());
388 ss.exceptions(std::ios_base::failbit);
389 BOOST_TEST_EQ(std::ios_base::failbit, ss.exceptions());
390 {
391 boost::io::ios_iostate_saver iis(ss);
392 ss.exceptions(std::ios_base::failbit | std::ios_base::badbit);
393 char c;
394 #if defined(BOOST_GCC) || (defined(BOOST_CLANG) && defined(BOOST_GNU_STDLIB))
395 BOOST_TEST_THROWS(ss >> c, std::exception);
396 #else
397 BOOST_TEST_THROWS(ss >> c, std::ios_base::failure);
398 #endif
399 }
400 ss.tie(&std::clog);
401 BOOST_TEST_EQ(&std::clog, ss.tie());
402 ss.rdbuf(std::cerr.rdbuf());
403 BOOST_TEST_EQ(std::cerr.rdbuf(), ss.rdbuf());
404 ss << std::setfill('x');
405 BOOST_TEST_EQ('x', ss.fill());
406 ss.imbue(std::locale(std::locale::classic(), new backward_bool_names));
407 BOOST_TEST(std::locale() != ss.getloc());
408 BOOST_TEST(std::has_facet<npc_type>(ss.getloc()) &&
409 dynamic_cast<const backward_bool_names*>(&
410 std::use_facet<npc_type>(ss.getloc())));
411 }
412 BOOST_TEST_EQ(std::ios_base::skipws | std::ios_base::dec, ss.flags());
413 BOOST_TEST_EQ(6, ss.precision());
414 BOOST_TEST_EQ(0, ss.width());
415 BOOST_TEST_EQ(std::ios_base::goodbit, ss.rdstate());
416 BOOST_TEST(ss.good());
417 BOOST_TEST_EQ(std::ios_base::goodbit, ss.exceptions());
418 BOOST_TEST(NULL == ss.tie());
419 BOOST_TEST(&sb == ss.rdbuf());
420 BOOST_TEST_EQ(' ', ss.fill());
421 BOOST_TEST(std::locale() == ss.getloc());
422 }
423
424 void
ios_word_saver_unit_test(int index)425 ios_word_saver_unit_test(int index)
426 {
427 std::stringstream ss;
428 BOOST_TEST_EQ(0, ss.iword(index));
429 BOOST_TEST(NULL == ss.pword(index));
430 {
431 boost::io::ios_all_word_saver iaws(ss, index);
432 BOOST_TEST_EQ(0, ss.iword(index));
433 BOOST_TEST(NULL == ss.pword(index));
434 ss.iword(index) = -11;
435 ss.pword(index) = ss.rdbuf();
436 BOOST_TEST_EQ(-11, ss.iword(index));
437 BOOST_TEST_EQ(ss.rdbuf(), ss.pword(index));
438 }
439 BOOST_TEST_EQ(0, ss.iword(index));
440 BOOST_TEST(NULL == ss.pword(index));
441 }
442
main()443 int main()
444 {
445 int index = std::ios_base::xalloc();
446 ios_flags_saver_unit_test();
447 ios_precision_saver_unit_test();
448 ios_width_saver_unit_test();
449 ios_iostate_saver_unit_test();
450 ios_exception_saver_unit_test();
451 ios_tie_saver_unit_test();
452 ios_rdbuf_saver_unit_test();
453 ios_fill_saver_unit_test();
454 ios_locale_saver_unit_test();
455 ios_iword_saver_unit_test(index);
456 ios_pword_saver_unit_test(index);
457 ios_base_all_saver_unit_test();
458 ios_all_saver_unit_test();
459 ios_word_saver_unit_test(index);
460 return boost::report_errors();
461 }
462