$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: Frank.Birbacher_at_[hidden]
Date: 2007-08-28 19:18:41
Author: birbacher
Date: 2007-08-28 19:18:41 EDT (Tue, 28 Aug 2007)
New Revision: 39046
URL: http://svn.boost.org/trac/boost/changeset/39046
Log:
extended test for more error checking on iostreams::stream
Text files modified: 
   sandbox-branches/birbacher/fix_iostreams/libs/iostreams/test/error_test.cpp |   130 ++++++++++++++++++++++++++++----------- 
   1 files changed, 94 insertions(+), 36 deletions(-)
Modified: sandbox-branches/birbacher/fix_iostreams/libs/iostreams/test/error_test.cpp
==============================================================================
--- sandbox-branches/birbacher/fix_iostreams/libs/iostreams/test/error_test.cpp	(original)
+++ sandbox-branches/birbacher/fix_iostreams/libs/iostreams/test/error_test.cpp	2007-08-28 19:18:41 EDT (Tue, 28 Aug 2007)
@@ -15,6 +15,22 @@
 namespace bio = boost::iostreams;
 using boost::unit_test::test_suite;
 
+/* This test unit uses a custom device to trigger errors. The device supports
+ * input, output, and seek according to the SeekableDevice concept. And each
+ * of the required functions throw a special detail::bad_xxx exception. This
+ * should trigger the iostreams::stream to set the badbit status flag.
+ * Additionally the exception can be propagated to the caller if the exception
+ * mask of the stream allows exceptions.
+ *
+ * The stream offers four different functions: read, write, seekg, and seekp.
+ * Each of them is tested with three different error reporting concepts:
+ * test by reading status flags, test by propagated exception, and test by
+ * calling std::ios_base::exceptions when badbit is already set.
+ *
+ * In each case all of the status checking functions of a stream are checked.
+ */
+
+// error device ***************************************************************
 struct error_device
 {
     typedef char   char_type;
@@ -25,7 +41,6 @@
     std::streamsize read(char_type* s, std::streamsize n);
     std::streamsize write(const char_type* s, std::streamsize n);
     std::streampos seek(bio::stream_offset off, BOOST_IOS::seekdir way);
-    
 };
 
 std::streamsize error_device::read(char_type*, std::streamsize)
@@ -43,57 +58,100 @@
     throw bio::detail::bad_seek();
 }
 
+// helping definitions ********************************************************
 typedef bio::stream<error_device> test_stream;
 
-void test_read()
+void check_stream_for_badbit(std::iostream& stream)
 {
-    test_stream stream("foo");
-    char data[10];
-    try{
-        stream.read(data, 10);
-        BOOST_CHECK_MESSAGE(stream.fail(), "stream did not fail");
-    }catch(...){
-        BOOST_CHECK(false);
-    }
+    BOOST_CHECK_MESSAGE(!stream.good(), "stream still good");
+    BOOST_CHECK_MESSAGE(!stream.eof(), "eofbit set but not expected");
+    BOOST_CHECK_MESSAGE(stream.bad(), "stream did not set badbit");
+    BOOST_CHECK_MESSAGE(stream.fail(), "stream did not fail");
+    BOOST_CHECK_MESSAGE(stream.operator ! (),
+            "stream does not report failure by operator !");
+    BOOST_CHECK_MESSAGE(0 == stream.operator void* (),
+            "stream does not report failure by operator void*");
 }
-void test_write()
+
+// error checking concepts ****************************************************
+template<void (*const function)(std::iostream&)>
+void wrap_nothrow()
 {
     test_stream stream("foo");
-    char data[10] = {0};
-    try{
-        stream.write(data, 10);
-        BOOST_CHECK_MESSAGE(stream.fail(), "stream did not fail");
-    }catch(...){
-        BOOST_CHECK(false);
-    }
+    BOOST_CHECK_NO_THROW( function(stream) );
+    check_stream_for_badbit(stream);
 }
-void test_seekg()
+
+template<void (*const function)(std::iostream&)>
+void wrap_throw()
 {
+    typedef std::ios_base ios;
     test_stream stream("foo");
-    try{
-        stream.seekg(10);
-        BOOST_CHECK_MESSAGE(stream.fail(), "stream did not fail");
-    }catch(...){
-        BOOST_CHECK(false);
-    }
+    
+    stream.exceptions(ios::failbit | ios::badbit);
+    BOOST_CHECK_THROW( function(stream), std::exception );
+    
+    check_stream_for_badbit(stream);
 }
-void test_seekp()
+
+template<void (*const function)(std::iostream&)>
+void wrap_throw_delayed()
 {
+    typedef std::ios_base ios;
     test_stream stream("foo");
-    try{
-        stream.seekp(10);
-        BOOST_CHECK_MESSAGE(stream.fail(), "stream did not fail");
-    }catch(...){
-        BOOST_CHECK(false);
-    }
+    
+    function(stream);
+    BOOST_CHECK_THROW(
+            stream.exceptions(ios::failbit | ios::badbit),
+            ios::failure
+        );
+    
+    check_stream_for_badbit(stream);
+}
+
+// error raising **************************************************************
+void test_read(std::iostream& stream)
+{
+    char data[10];
+    stream.read(data, 10);
 }
 
+void test_write(std::iostream& stream)
+{
+    char data[10] = {0};
+    stream.write(data, 10);
+}
+
+void test_seekg(std::iostream& stream)
+{
+    stream.seekg(10);
+}
+
+void test_seekp(std::iostream& stream)
+{
+    stream.seekp(10);
+}
+
+// test registration function *************************************************
 test_suite* init_unit_test_suite(int, char* []) 
 {
     test_suite* test = BOOST_TEST_SUITE("error test");
-    test->add(BOOST_TEST_CASE(&test_read));
-    test->add(BOOST_TEST_CASE(&test_write));
-    test->add(BOOST_TEST_CASE(&test_seekg));
-    test->add(BOOST_TEST_CASE(&test_seekp));
+    
+    test->add(BOOST_TEST_CASE(&wrap_nothrow      <&test_read>));
+    test->add(BOOST_TEST_CASE(&wrap_throw        <&test_read>));
+    test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_read>));
+    
+    test->add(BOOST_TEST_CASE(&wrap_nothrow      <&test_write>));
+    test->add(BOOST_TEST_CASE(&wrap_throw        <&test_write>));
+    test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_write>));
+    
+    test->add(BOOST_TEST_CASE(&wrap_nothrow      <&test_seekg>));
+    test->add(BOOST_TEST_CASE(&wrap_throw        <&test_seekg>));
+    test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_seekg>));
+    
+    test->add(BOOST_TEST_CASE(&wrap_nothrow      <&test_seekp>));
+    test->add(BOOST_TEST_CASE(&wrap_throw        <&test_seekp>));
+    test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_seekp>));
+    
     return test;
 }