ios_state_test.cpp 8.7 KB

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