From 38c84588c0f64ef204a7625648e8ae3642e1ab67 Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Mon, 23 Jun 2003 08:34:06 +0000 Subject: [PATCH] Added new (unit) tests for I/O-state saving classes [SVN r18854] --- test/ios_state_unit_test.cpp | 670 +++++++++++++++++++++++++++++++++++ 1 file changed, 670 insertions(+) create mode 100644 test/ios_state_unit_test.cpp diff --git a/test/ios_state_unit_test.cpp b/test/ios_state_unit_test.cpp new file mode 100644 index 0000000..0f8f2ed --- /dev/null +++ b/test/ios_state_unit_test.cpp @@ -0,0 +1,670 @@ +// Boost ios_state_unit_test.cpp test file ---------------------------------// + +// (C) Copyright Daryle Walker 2003. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// Revision History +// 23 Jun 2003 Initial version (Daryle Walker) + +#include // for boost::io::ios_flags_saver, etc. +#include // for main, BOOST_CHECK, etc. + +#include // for NULL +#include // for std::setiosflags, etc. +#include // for std::ios_base +#include // for std::wcout, std::wcin, etc. +#include // for std::iostream +#include // for std::locale, std::numpunct +#include // for std::stringstream, etc. + + +// Global constants +int const word_index = std::ios_base::xalloc(); + + +// Facet with the (classic) bool names spelled backwards +class backward_bool_names + : public std::numpunct +{ + typedef std::numpunct base_type; + +public: + explicit backward_bool_names( std::size_t refs = 0 ) + : base_type( refs ) + {} + +protected: + virtual ~backward_bool_names() {} + + virtual base_type::string_type do_truename() const + { return "eurt"; } + virtual base_type::string_type do_falsename() const + { return "eslaf"; } +}; + + +// Unit test for format-flag saving +void +ios_flags_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + + { + boost::io::ios_flags_saver ifs( ss ); + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + + ss << noskipws << fixed << boolalpha; + BOOST_CHECK_EQUAL( (ios_base::boolalpha | ios_base::dec + | ios_base::fixed), ss.flags() ); + } + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + + { + boost::io::ios_flags_saver ifs( ss, (ios_base::showbase + | ios_base::internal) ); + + BOOST_CHECK_EQUAL( (ios_base::showbase | ios_base::internal), + ss.flags() ); + + ss << setiosflags( ios_base::unitbuf ); + BOOST_CHECK_EQUAL( (ios_base::showbase | ios_base::internal + | ios_base::unitbuf), ss.flags() ); + } + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); +} + +// Unit test for precision saving +void +ios_precision_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( 6, ss.precision() ); + + { + boost::io::ios_precision_saver ips( ss ); + + BOOST_CHECK_EQUAL( 6, ss.precision() ); + + ss << setprecision( 4 ); + BOOST_CHECK_EQUAL( 4, ss.precision() ); + } + + BOOST_CHECK_EQUAL( 6, ss.precision() ); + + { + boost::io::ios_precision_saver ips( ss, 8 ); + + BOOST_CHECK_EQUAL( 8, ss.precision() ); + + ss << setprecision( 10 ); + BOOST_CHECK_EQUAL( 10, ss.precision() ); + } + + BOOST_CHECK_EQUAL( 6, ss.precision() ); +} + +// Unit test for width saving +void +ios_width_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( 0, ss.width() ); + + { + boost::io::ios_width_saver iws( ss ); + + BOOST_CHECK_EQUAL( 0, ss.width() ); + + ss << setw( 4 ); + BOOST_CHECK_EQUAL( 4, ss.width() ); + } + + BOOST_CHECK_EQUAL( 0, ss.width() ); + + { + boost::io::ios_width_saver iws( ss, 8 ); + + BOOST_CHECK_EQUAL( 8, ss.width() ); + + ss << setw( 10 ); + BOOST_CHECK_EQUAL( 10, ss.width() ); + } + + BOOST_CHECK_EQUAL( 0, ss.width() ); +} + +// Unit test for I/O-state saving +void +ios_iostate_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); + + { + boost::io::ios_iostate_saver iis( ss ); + char c; + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); + + ss >> c; + BOOST_CHECK_EQUAL( (ios_base::eofbit | ios_base::failbit), + ss.rdstate() ); + BOOST_CHECK( ss.eof() ); + BOOST_CHECK( ss.fail() ); + BOOST_CHECK( !ss.bad() ); + } + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); + + { + boost::io::ios_iostate_saver iis( ss, ios_base::eofbit ); + + BOOST_CHECK_EQUAL( ios_base::eofbit, ss.rdstate() ); + BOOST_CHECK( ss.eof() ); + + ss.setstate( ios_base::badbit ); + BOOST_CHECK_EQUAL( (ios_base::eofbit | ios_base::badbit), + ss.rdstate() ); + BOOST_CHECK( ss.eof() ); + BOOST_CHECK( ss.fail() ); + BOOST_CHECK( ss.bad() ); + } + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); +} + +// Unit test for exception-flag saving +void +ios_exception_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); + + { + boost::io::ios_exception_saver ies( ss ); + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); + + ss.exceptions( ios_base::failbit ); + BOOST_CHECK_EQUAL( ios_base::failbit, ss.exceptions() ); + + { + boost::io::ios_iostate_saver iis( ss ); + char c; + + BOOST_CHECK_THROW( ss >> c, std::ios_base::failure ); + } + } + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); + + { + boost::io::ios_exception_saver ies( ss, ios_base::eofbit ); + + BOOST_CHECK_EQUAL( ios_base::eofbit, ss.exceptions() ); + + ss.exceptions( ios_base::badbit ); + BOOST_CHECK_EQUAL( ios_base::badbit, ss.exceptions() ); + + { + boost::io::ios_iostate_saver iis( ss ); + char c; + + BOOST_CHECK_NO_THROW( ss >> c ); + } + } + + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); +} + +// Unit test for tied-stream saving +void +ios_tie_saver_unit_test +( +) +{ + using namespace std; + + BOOST_CHECK_EQUAL( &wcout, wcin.tie() ); + + { + boost::io::wios_tie_saver its( wcin ); + + BOOST_CHECK_EQUAL( &wcout, wcin.tie() ); + + wcin.tie( &wclog ); + BOOST_CHECK_EQUAL( &wclog, wcin.tie() ); + } + + BOOST_CHECK_EQUAL( &wcout, wcin.tie() ); + + { + boost::io::wios_tie_saver its( wcin, &wcerr ); + + BOOST_CHECK_EQUAL( &wcerr, wcin.tie() ); + + wcin.tie( NULL ); + BOOST_CHECK( NULL == wcin.tie() ); + } + + BOOST_CHECK_EQUAL( &wcout, wcin.tie() ); +} + +// Unit test for connected-streambuf saving +void +ios_rdbuf_saver_unit_test +( +) +{ + using namespace std; + + wiostream ws( NULL ); + + BOOST_CHECK( NULL == ws.rdbuf() ); + + { + wstringbuf wsb; + boost::io::wios_rdbuf_saver irs( ws ); + + BOOST_CHECK( NULL == ws.rdbuf() ); + + ws.rdbuf( &wsb ); + BOOST_CHECK_EQUAL( &wsb, ws.rdbuf() ); + } + + BOOST_CHECK( NULL == ws.rdbuf() ); + + { + wstringbuf wsb1, wsb2( L"Hi there" ); + boost::io::wios_rdbuf_saver irs( ws, &wsb1 ); + + BOOST_CHECK_EQUAL( &wsb1, ws.rdbuf() ); + + ws.rdbuf( &wsb2 ); + BOOST_CHECK_EQUAL( &wsb2, ws.rdbuf() ); + } + + BOOST_CHECK( NULL == ws.rdbuf() ); +} + +// Unit test for fill-character saving +void +ios_fill_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( ' ', ss.fill() ); + + { + boost::io::ios_fill_saver ifs( ss ); + + BOOST_CHECK_EQUAL( ' ', ss.fill() ); + + ss.fill( 'x' ); + BOOST_CHECK_EQUAL( 'x', ss.fill() ); + } + + BOOST_CHECK_EQUAL( ' ', ss.fill() ); + + { + boost::io::ios_fill_saver ifs( ss, '3' ); + + BOOST_CHECK_EQUAL( '3', ss.fill() ); + + ss.fill( '+' ); + BOOST_CHECK_EQUAL( '+', ss.fill() ); + } + + BOOST_CHECK_EQUAL( ' ', ss.fill() ); +} + +// Unit test for locale saving +void +ios_locale_saver_unit_test +( +) +{ + using namespace std; + + typedef numpunct npc_type; + + stringstream ss; + + BOOST_CHECK( locale() == ss.getloc() ); + // locales are unprintable, so no BOOST_CHECK_EQUAL + BOOST_CHECK( !has_facet(ss.getloc()) || (NULL + == dynamic_cast( + &use_facet(ss.getloc()) )) ); + // my implementation of has_facet just checks IDs, but doesn't do dynamic + // cast (therefore if a specifc facet type is missing, but its base class + // is available, has_facet will mistakenly[?] match), so I have to do it + // here. I wanted: "BOOST_CHECK( ! has_facet< backward_bool_names >( + // ss.getloc() ) )" + { + boost::io::ios_locale_saver ils( ss ); + + BOOST_CHECK( locale() == ss.getloc() ); + + ss.imbue( locale::classic() ); + BOOST_CHECK( locale::classic() == ss.getloc() ); + } + + BOOST_CHECK( locale() == ss.getloc() ); + BOOST_CHECK( !has_facet(ss.getloc()) || (NULL + == dynamic_cast( + &use_facet(ss.getloc()) )) ); + + { + boost::io::ios_locale_saver ils( ss, locale::classic() ); + + BOOST_CHECK( locale::classic() == ss.getloc() ); + BOOST_CHECK( !has_facet(ss.getloc()) || (NULL + == dynamic_cast( + &use_facet(ss.getloc()) )) ); + + ss.imbue( locale(locale::classic(), new backward_bool_names) ); + BOOST_CHECK( locale::classic() != ss.getloc() ); + BOOST_CHECK( has_facet(ss.getloc()) && (NULL + != dynamic_cast( + &use_facet(ss.getloc()) )) ); + //BOOST_CHECK( has_facet(ss.getloc()) ); + } + + BOOST_CHECK( locale() == ss.getloc() ); + BOOST_CHECK( !has_facet(ss.getloc()) || (NULL + == dynamic_cast( + &use_facet(ss.getloc()) )) ); +} + +// Unit test for user-defined integer data saving +void +ios_iword_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); + + { + boost::io::ios_iword_saver iis( ss, word_index ); + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); + + ss.iword( word_index ) = 6; + BOOST_CHECK_EQUAL( 6, ss.iword(word_index) ); + } + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); + + { + boost::io::ios_iword_saver iis( ss, word_index, 100 ); + + BOOST_CHECK_EQUAL( 100, ss.iword(word_index) ); + + ss.iword( word_index ) = -2000; + BOOST_CHECK_EQUAL( -2000, ss.iword(word_index) ); + } + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); +} + +// Unit test for user-defined pointer data saving +void +ios_pword_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK( NULL == ss.pword(word_index) ); + + { + boost::io::ios_pword_saver ips( ss, word_index ); + + BOOST_CHECK( NULL == ss.pword(word_index) ); + + ss.pword( word_index ) = &ss; + BOOST_CHECK_EQUAL( &ss, ss.pword(word_index) ); + } + + BOOST_CHECK( NULL == ss.pword(word_index) ); + + { + boost::io::ios_pword_saver ips( ss, word_index, ss.rdbuf() ); + + BOOST_CHECK_EQUAL( ss.rdbuf(), ss.pword(word_index) ); + + ss.pword( word_index ) = &ss; + BOOST_CHECK_EQUAL( &ss, ss.pword(word_index) ); + } + + BOOST_CHECK( NULL == ss.pword(word_index) ); +} + +// Unit test for all ios_base data saving +void +ios_base_all_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + BOOST_CHECK_EQUAL( 6, ss.precision() ); + BOOST_CHECK_EQUAL( 0, ss.width() ); + + { + boost::io::ios_base_all_saver ibas( ss ); + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + BOOST_CHECK_EQUAL( 6, ss.precision() ); + BOOST_CHECK_EQUAL( 0, ss.width() ); + + ss << hex << unitbuf << setprecision( 5 ) << setw( 7 ); + BOOST_CHECK_EQUAL( (ios_base::unitbuf | ios_base::hex + | ios_base::skipws), ss.flags() ); + BOOST_CHECK_EQUAL( 5, ss.precision() ); + BOOST_CHECK_EQUAL( 7, ss.width() ); + } + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + BOOST_CHECK_EQUAL( 6, ss.precision() ); + BOOST_CHECK_EQUAL( 0, ss.width() ); +} + +// Unit test for all basic_ios data saving +void +ios_all_saver_unit_test +( +) +{ + using namespace std; + + typedef numpunct npc_type; + + stringbuf sb; + iostream ss( &sb ); + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + BOOST_CHECK_EQUAL( 6, ss.precision() ); + BOOST_CHECK_EQUAL( 0, ss.width() ); + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); + BOOST_CHECK( NULL == ss.tie() ); + BOOST_CHECK( &sb == ss.rdbuf() ); + BOOST_CHECK_EQUAL( ' ', ss.fill() ); + BOOST_CHECK( locale() == ss.getloc() ); + + { + boost::io::ios_all_saver ias( ss ); + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + BOOST_CHECK_EQUAL( 6, ss.precision() ); + BOOST_CHECK_EQUAL( 0, ss.width() ); + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); + BOOST_CHECK( NULL == ss.tie() ); + BOOST_CHECK( &sb == ss.rdbuf() ); + BOOST_CHECK_EQUAL( ' ', ss.fill() ); + BOOST_CHECK( locale() == ss.getloc() ); + + ss << oct << showpos << noskipws; + BOOST_CHECK_EQUAL( (ios_base::showpos | ios_base::oct), ss.flags() ); + + ss << setprecision( 3 ); + BOOST_CHECK_EQUAL( 3, ss.precision() ); + + ss << setw( 9 ); + BOOST_CHECK_EQUAL( 9, ss.width() ); + + ss.setstate( ios_base::eofbit ); + BOOST_CHECK_EQUAL( ios_base::eofbit, ss.rdstate() ); + BOOST_CHECK( ss.eof() ); + + ss.exceptions( ios_base::failbit ); + BOOST_CHECK_EQUAL( ios_base::failbit, ss.exceptions() ); + + { + boost::io::ios_iostate_saver iis( ss ); + char c; + + BOOST_CHECK_THROW( ss >> c, std::ios_base::failure ); + } + + ss.tie( &clog ); + BOOST_CHECK_EQUAL( &clog, ss.tie() ); + + ss.rdbuf( cerr.rdbuf() ); + BOOST_CHECK_EQUAL( cerr.rdbuf(), ss.rdbuf() ); + + ss << setfill( 'x' ); + BOOST_CHECK_EQUAL( 'x', ss.fill() ); + + ss.imbue( locale(locale::classic(), new backward_bool_names) ); + BOOST_CHECK( locale() != ss.getloc() ); + BOOST_CHECK( has_facet(ss.getloc()) && (NULL + != dynamic_cast( + &use_facet(ss.getloc()) )) ); + } + + BOOST_CHECK_EQUAL( (ios_base::skipws | ios_base::dec), ss.flags() ); + BOOST_CHECK_EQUAL( 6, ss.precision() ); + BOOST_CHECK_EQUAL( 0, ss.width() ); + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.rdstate() ); + BOOST_CHECK( ss.good() ); + BOOST_CHECK_EQUAL( ios_base::goodbit, ss.exceptions() ); + BOOST_CHECK( NULL == ss.tie() ); + BOOST_CHECK( &sb == ss.rdbuf() ); + BOOST_CHECK_EQUAL( ' ', ss.fill() ); + BOOST_CHECK( locale() == ss.getloc() ); +} + +// Unit test for user-defined data saving +void +ios_word_saver_unit_test +( +) +{ + using namespace std; + + stringstream ss; + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); + BOOST_CHECK( NULL == ss.pword(word_index) ); + + { + boost::io::ios_all_word_saver iaws( ss, word_index ); + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); + BOOST_CHECK( NULL == ss.pword(word_index) ); + + ss.iword( word_index ) = -11; + ss.pword( word_index ) = ss.rdbuf(); + BOOST_CHECK_EQUAL( -11, ss.iword(word_index) ); + BOOST_CHECK_EQUAL( ss.rdbuf(), ss.pword(word_index) ); + } + + BOOST_CHECK_EQUAL( 0, ss.iword(word_index) ); + BOOST_CHECK( NULL == ss.pword(word_index) ); +} + + +// Unit test program +boost::unit_test_framework::test_suite * +init_unit_test_suite +( + int , // "argc" is unused + char * [] // "argv" is unused +) +{ + boost::unit_test_framework::test_suite * test + = BOOST_TEST_SUITE( "I/O state saver test" ); + + test->add( BOOST_TEST_CASE(ios_flags_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_precision_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_width_saver_unit_test) ); + + test->add( BOOST_TEST_CASE(ios_iostate_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_exception_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_tie_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_rdbuf_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_fill_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_locale_saver_unit_test) ); + + test->add( BOOST_TEST_CASE(ios_iword_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_pword_saver_unit_test) ); + + test->add( BOOST_TEST_CASE(ios_base_all_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_all_saver_unit_test) ); + test->add( BOOST_TEST_CASE(ios_word_saver_unit_test) ); + + return test; +}