$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: technews_at_[hidden]
Date: 2008-01-06 13:26:47
Author: turkanis
Date: 2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
New Revision: 42543
URL: http://svn.boost.org/trac/boost/changeset/42543
Log:
copy.hpp: 
    fix for Visual Age: std::min was passed arguments of different types; replaced std:: min with conditional
detail/streambuf/indirect_streambuf.hpp: 
    removed trailing comma in enum definition
test/combine_test.cpp:
test/symmetric_filter_test.cpp:
test/compose_test.cpp:
test/close_test.cpp:
test/invert_test.cpp:
test/tee_test.cpp:
test/restrict_test.cpp:
test/Jamfile.v2:
    moved tests for close() into the test files for various adapters
Added:
   branches/iostreams_dev/libs/iostreams/test/combine_test.cpp   (contents, props changed)
Text files modified: 
   branches/iostreams_dev/boost/iostreams/copy.hpp                                |     7                                         
   branches/iostreams_dev/boost/iostreams/detail/streambuf/indirect_streambuf.hpp |     2                                         
   branches/iostreams_dev/libs/iostreams/test/Jamfile.v2                          |     1                                         
   branches/iostreams_dev/libs/iostreams/test/close_test.cpp                      |   909 --------------------------------------- 
   branches/iostreams_dev/libs/iostreams/test/compose_test.cpp                    |   391 ++++++++++++++++                        
   branches/iostreams_dev/libs/iostreams/test/invert_test.cpp                     |    32 +                                       
   branches/iostreams_dev/libs/iostreams/test/restrict_test.cpp                   |   117 +++++                                   
   branches/iostreams_dev/libs/iostreams/test/symmetric_filter_test.cpp           |    43 +                                       
   branches/iostreams_dev/libs/iostreams/test/tee_test.cpp                        |   228 +++++++++                               
   9 files changed, 801 insertions(+), 929 deletions(-)
Modified: branches/iostreams_dev/boost/iostreams/copy.hpp
==============================================================================
--- branches/iostreams_dev/boost/iostreams/copy.hpp	(original)
+++ branches/iostreams_dev/boost/iostreams/copy.hpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -94,19 +94,20 @@
                            std::streamsize buffer_size,
                            mpl::false_, mpl::true_ )
 {
-    using namespace std;
     typedef typename char_type_of<Source>::type  char_type;
     typedef std::pair<char_type*, char_type*>    pair_type;
     detail::basic_buffer<char_type>  buf(buffer_size);
     pair_type                        p = snk.output_sequence();
     std::streamsize                  total = 0;
-    ptrdiff_t                        capacity = p.second - p.first;
+    std::ptrdiff_t                   capacity = p.second - p.first;
     while (true) {
         std::streamsize amt = 
             iostreams::read(
                 src, 
                 buf.data(),
-                (std::min)(buffer_size, capacity - total)
+                buffer_size < capacity - total ?
+                    buffer_size :
+                    static_cast<std::streamsize>(capacity - total)
             );
         if (amt == -1)
             break;
Modified: branches/iostreams_dev/boost/iostreams/detail/streambuf/indirect_streambuf.hpp
==============================================================================
--- branches/iostreams_dev/boost/iostreams/detail/streambuf/indirect_streambuf.hpp	(original)
+++ branches/iostreams_dev/boost/iostreams/detail/streambuf/indirect_streambuf.hpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -124,7 +124,7 @@
     enum flag_type {
         f_open             = 1,
         f_output_buffered  = f_open << 1,
-        f_auto_close       = f_output_buffered << 1,
+        f_auto_close       = f_output_buffered << 1
     };
 
     optional<wrapper>           storage_;
Modified: branches/iostreams_dev/libs/iostreams/test/Jamfile.v2
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/Jamfile.v2	(original)
+++ branches/iostreams_dev/libs/iostreams/test/Jamfile.v2	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -39,6 +39,7 @@
           [ test-iostreams 
                 code_converter_test.cpp    
                 detail/utf8_codecvt_facet.cpp ]
+          [ test-iostreams combine_test.cpp ]
           [ test-iostreams compose_test.cpp ]
           [ test-iostreams component_access_test.cpp ]
           [ test-iostreams copy_test.cpp ]
Modified: branches/iostreams_dev/libs/iostreams/test/close_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/close_test.cpp	(original)
+++ branches/iostreams_dev/libs/iostreams/test/close_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -6,7 +6,7 @@
  *
  * Verifies that the close() member functions of filters and devices
  * are called with the correct arguments in the correct order when 
- * they are combined using chains or adapters.
+ * used with chains and streams.
  *
  * File:        libs/iostreams/test/close_test.cpp
  * Date:        Sun Dec 09 16:12:23 MST 2007
@@ -506,905 +506,6 @@
     }
 }
 
-void combine_test()
-{
-    // Combine a source and a sink
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_device<input>(seq.new_operation(1)),
-                closable_device<output>(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Combine two bidirectional devices
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_device<bidirectional>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                closable_device<bidirectional>(
-                    seq.new_operation(3),
-                    seq.new_operation(4)
-                )
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Combine two seekable devices
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_device<seekable>(seq.new_operation(1)),
-                closable_device<seekable>(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Combine an input filter and an output filter
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_filter<input>(seq.new_operation(2)),
-                closable_filter<output>(seq.new_operation(3))
-            )
-        );
-        ch.push(
-            closable_device<bidirectional>(
-                seq.new_operation(1),
-                seq.new_operation(4)
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Combine two bidirectional filters
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_filter<bidirectional>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                closable_filter<bidirectional>(
-                    seq.new_operation(4),
-                    seq.new_operation(5)
-                )
-            )
-        );
-        ch.push(
-            closable_device<bidirectional>(
-                seq.new_operation(1),
-                seq.new_operation(6)
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Combine two seekable filters
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_filter<seekable>(seq.new_operation(2)),
-                closable_filter<seekable>(seq.new_operation(3))
-            )
-        );
-        ch.push(
-            closable_device<bidirectional>(
-                seq.new_operation(1),
-                seq.new_operation(4)
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Combine two dual-use filters
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::combine(
-                closable_filter<dual_use>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                closable_filter<dual_use>(
-                    seq.new_operation(4),
-                    seq.new_operation(5)
-                )
-            )
-        );
-        ch.push(
-            closable_device<bidirectional>(
-                seq.new_operation(1),
-                seq.new_operation(6)
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void composite_device_test()
-{
-    // Compose an input filter with a source
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<input>(seq.new_operation(2)),
-                closable_device<input>(seq.new_operation(1))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a bidirectional filter with a source
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<bidirectional>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                closable_device<input>(seq.new_operation(1))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a seekable filter with a source
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<seekable>(seq.new_operation(2)),
-                closable_device<input>(seq.new_operation(1))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a dual-use filter with a source
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<dual_use>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                closable_device<input>(seq.new_operation(1))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose an output filter with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<output>(seq.new_operation(1)),
-                closable_device<output>(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a bidirectional filter with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<bidirectional>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                closable_device<output>(seq.new_operation(3))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a seekable filter with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<seekable>(seq.new_operation(1)),
-                closable_device<output>(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a dual-use filter with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<dual_use>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                closable_device<output>(seq.new_operation(3))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a bidirectional filter with a bidirectional device
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::compose(
-                closable_filter<bidirectional>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                closable_device<bidirectional>(
-                    seq.new_operation(1),
-                    seq.new_operation(4)
-                )
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a seekable filter with a seekable device
-    {
-        operation_sequence  seq;
-        chain<seekable>     ch;
-        ch.push(
-            io::compose(
-                closable_filter<seekable>(seq.new_operation(1)),
-                closable_device<seekable>(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void composite_filter_test()
-{
-    // Compose two input filters
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<input>(seq.new_operation(3)),
-                closable_filter<input>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a bidirectional filter with an input filter
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<bidirectional>(
-                    seq.new_operation(3),
-                    seq.new_operation(4)
-                ),
-                closable_filter<input>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_MESSAGE(seq.is_success(), seq.message());
-    }
-
-    // Compose a seekable filter with an input filter
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<seekable>(seq.new_operation(3)),
-                closable_filter<input>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a dual-use filter with an input filter
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<dual_use>(
-                    seq.new_operation(3),
-                    seq.new_operation(4)
-                ),
-                closable_filter<input>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose two output filters
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<output>(seq.new_operation(1)),
-                closable_filter<output>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a bidirectional filter with an output filter
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<bidirectional>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                closable_filter<output>(seq.new_operation(3))
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(4)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a seekable filter with an output filter
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<seekable>(seq.new_operation(1)),
-                closable_filter<output>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose a dual-use filter with an output filter
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<dual_use>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                closable_filter<output>(seq.new_operation(3))
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(4)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose two bidirectional filters
-    {
-        operation_sequence    seq;
-        chain<bidirectional>  ch;
-        ch.push(
-            io::compose(
-                closable_filter<bidirectional>(
-                    seq.new_operation(3),
-                    seq.new_operation(4)
-                ),
-                closable_filter<bidirectional>(
-                    seq.new_operation(2),
-                    seq.new_operation(5)
-                )
-            )
-        );
-        ch.push(
-            closable_device<bidirectional>(
-                seq.new_operation(1),
-                seq.new_operation(6)
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose two seekable filters
-    {
-        operation_sequence  seq;
-        chain<seekable>     ch;
-        ch.push(
-            io::compose(
-                closable_filter<seekable>(seq.new_operation(1)),
-                closable_filter<seekable>(seq.new_operation(2))
-            )
-        );
-        ch.push(closable_device<seekable>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose two dual-use filters for input
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::compose(
-                closable_filter<dual_use>(
-                    seq.new_operation(3),
-                    seq.new_operation(4)
-                ),
-                closable_filter<dual_use>(
-                    seq.new_operation(2),
-                    seq.new_operation(5)
-                )
-            )
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Compose two dual-use filters for output
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::compose(
-                closable_filter<dual_use>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                closable_filter<dual_use>(
-                    seq.new_operation(1),
-                    seq.new_operation(4)
-                )
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(5)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void invert_test()
-{
-    // Invert an output filter
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(io::invert(closable_filter<output>(seq.new_operation(2))));
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Invert an input filter
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(io::invert(closable_filter<input>(seq.new_operation(1))));
-        ch.push(closable_device<output>(seq.new_operation(2)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void restrict_test()
-{
-    // Restrict a source
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(io::restrict(closable_device<input>(seq.new_operation(1)), 0));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict a seekable device
-    {
-        operation_sequence  seq;
-        chain<seekable>     ch;
-        ch.push(
-            io::restrict(closable_device<seekable>(seq.new_operation(1)), 0)
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict a direct source
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::restrict(closable_device<direct_input>(seq.new_operation(1)), 0)
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict a direct seekable device
-    {
-        operation_sequence  seq;
-        chain<seekable>     ch;
-        ch.push(
-            io::restrict(
-                closable_device<direct_seekable>(seq.new_operation(1)), 
-                0
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict an input filter
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(io::restrict(closable_filter<input>(seq.new_operation(2)), 0));
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict a seekable filter
-    {
-        operation_sequence  seq;
-        chain<seekable>     ch;
-        ch.push(
-            io::restrict(closable_filter<seekable>(seq.new_operation(1)), 0)
-        );
-        ch.push(closable_device<seekable>(seq.new_operation(2)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict a dual_use filter for input
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::restrict(
-                closable_filter<dual_use>(
-                    seq.new_operation(2),
-                    seq.new_operation(3)
-                ),
-                0
-            )
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Restrict a dual_use filter for output
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::restrict(
-                closable_filter<dual_use>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                0
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void symmetric_filter_test()
-{
-    // Test input
-    {
-        operation_sequence  seq;
-        chain<input>        ch;
-        ch.push(
-            io::symmetric_filter<closable_symmetric_filter>
-                (0, seq.new_operation(2))
-        );
-        ch.push(closable_device<input>(seq.new_operation(1)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Test output
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::symmetric_filter<closable_symmetric_filter>
-                (0, seq.new_operation(1))
-        );
-        ch.push(closable_device<output>(seq.new_operation(2)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void tee_test()
-{
-    // Note: The implementation of tee_device closes the first
-    // sink before the second
-
-    // Tee two sinks (Borland <= 5.8.2 needs a little help compiling this case,
-    // but it executes the closing algorithm correctly)
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                closable_device<output>(seq.new_operation(1)),
-                closable_device<
-                    #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
-                        borland_output
-                    #else
-                        output
-                    #endif
-                >(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee two bidirectional devices
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                closable_device<bidirectional>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                ),
-                closable_device<bidirectional>(
-                    seq.new_operation(3),
-                    seq.new_operation(4)
-                )
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee two seekable devices
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                closable_device<seekable>(seq.new_operation(1)),
-                closable_device<seekable>(seq.new_operation(2))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(io::tee(closable_device<output>(seq.new_operation(1))));
-        ch.push(closable_device<output>(seq.new_operation(2)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a bidirectional device
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                closable_device<bidirectional>(
-                    seq.new_operation(1),
-                    seq.new_operation(2)
-                )
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a seekable device
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(io::tee(closable_device<seekable>(seq.new_operation(1))));
-        ch.push(closable_device<seekable>(seq.new_operation(2)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
-void tee_composite_test()
-{
-    // This test is probably redundant, but it verifies that
-    // ticket #1002 is fixed
-
-    // Tee a composite sink with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                io::compose(
-                    closable_filter<output>(seq.new_operation(1)),
-                    closable_device<output>(seq.new_operation(2))
-                ),
-                closable_device<output>(seq.new_operation(3))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a composite bidirectional device with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                io::compose(
-                    closable_filter<bidirectional>(
-                        seq.new_operation(2),
-                        seq.new_operation(3)
-                    ),
-                    closable_device<bidirectional>(
-                        seq.new_operation(1),
-                        seq.new_operation(4)
-                    )
-                ),
-                closable_device<output>(seq.new_operation(5))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a composite composite seekable device with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                io::compose(
-                    closable_filter<seekable>(seq.new_operation(1)),
-                    closable_device<seekable>(seq.new_operation(2))
-                ),
-                closable_device<output>(seq.new_operation(3))
-            )
-        );
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-
-    // Tee a composite sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                io::compose(
-                    closable_filter<output>(seq.new_operation(1)),
-                    closable_device<output>(seq.new_operation(2))
-                )
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a composite bidirectional device with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                io::compose(
-                    closable_filter<bidirectional>(
-                        seq.new_operation(2),
-                        seq.new_operation(3)
-                    ),
-                    closable_device<bidirectional>(
-                        seq.new_operation(1),
-                        seq.new_operation(4)
-                    )
-                )
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(5)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-
-    // Tee a composite composite seekable device with a sink
-    {
-        operation_sequence  seq;
-        chain<output>       ch;
-        ch.push(
-            io::tee(
-                io::compose(
-                    closable_filter<seekable>(seq.new_operation(1)),
-                    closable_device<seekable>(seq.new_operation(2))
-                )
-            )
-        );
-        ch.push(closable_device<output>(seq.new_operation(3)));
-        BOOST_CHECK_NO_THROW(ch.reset());
-        BOOST_CHECK_OPERATION_SEQUENCE(seq);
-    }
-}
-
 test_suite* init_unit_test_suite(int, char* []) 
 {
     test_suite* test = BOOST_TEST_SUITE("execute test");
@@ -1413,13 +514,5 @@
     test->add(BOOST_TEST_CASE(&bidirectional_chain_test));
     test->add(BOOST_TEST_CASE(&seekable_chain_test));
     test->add(BOOST_TEST_CASE(&stream_test));
-    test->add(BOOST_TEST_CASE(&combine_test));
-    test->add(BOOST_TEST_CASE(&composite_device_test));
-    test->add(BOOST_TEST_CASE(&composite_filter_test));
-    test->add(BOOST_TEST_CASE(&invert_test));
-    test->add(BOOST_TEST_CASE(&restrict_test));
-    test->add(BOOST_TEST_CASE(&symmetric_filter_test));
-    test->add(BOOST_TEST_CASE(&tee_test));
-    test->add(BOOST_TEST_CASE(&tee_composite_test));
     return test;
 }
Added: branches/iostreams_dev/libs/iostreams/test/combine_test.cpp
==============================================================================
--- (empty file)
+++ branches/iostreams_dev/libs/iostreams/test/combine_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -0,0 +1,177 @@
+/*
+ * Distributed under the Boost Software License, Version 1.0.(See accompanying 
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
+ * 
+ * See http://www.boost.org/libs/iostreams for documentation.
+ *
+ * Verifies that the close() member functions of filters and devices
+ * are called with the correct arguments in the correct order when 
+ * they are combined using combine().
+ *
+ * File:        libs/iostreams/test/combine_test.cpp
+ * Date:        Sun Jan 06 01:37:37 MST 2008
+ * Copyright:   2007 CodeRage
+ * Author:      Jonathan Turkanis
+ */
+
+#include <boost/iostreams/chain.hpp>
+#include <boost/iostreams/combine.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>  
+#include "detail/closable.hpp"
+#include "detail/operation_sequence.hpp"
+
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
+
+void combine_test()
+{
+    // Combine a source and a sink
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_device<input>(seq.new_operation(1)),
+                closable_device<output>(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Combine two bidirectional devices
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_device<bidirectional>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                closable_device<bidirectional>(
+                    seq.new_operation(3),
+                    seq.new_operation(4)
+                )
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Combine two seekable devices
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_device<seekable>(seq.new_operation(1)),
+                closable_device<seekable>(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Combine an input filter and an output filter
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_filter<input>(seq.new_operation(2)),
+                closable_filter<output>(seq.new_operation(3))
+            )
+        );
+        ch.push(
+            closable_device<bidirectional>(
+                seq.new_operation(1),
+                seq.new_operation(4)
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Combine two bidirectional filters
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_filter<bidirectional>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                closable_filter<bidirectional>(
+                    seq.new_operation(4),
+                    seq.new_operation(5)
+                )
+            )
+        );
+        ch.push(
+            closable_device<bidirectional>(
+                seq.new_operation(1),
+                seq.new_operation(6)
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Combine two seekable filters
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_filter<seekable>(seq.new_operation(2)),
+                closable_filter<seekable>(seq.new_operation(3))
+            )
+        );
+        ch.push(
+            closable_device<bidirectional>(
+                seq.new_operation(1),
+                seq.new_operation(4)
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Combine two dual-use filters
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::combine(
+                closable_filter<dual_use>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                closable_filter<dual_use>(
+                    seq.new_operation(4),
+                    seq.new_operation(5)
+                )
+            )
+        );
+        ch.push(
+            closable_device<bidirectional>(
+                seq.new_operation(1),
+                seq.new_operation(6)
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
+test_suite* init_unit_test_suite(int, char* []) 
+{
+    test_suite* test = BOOST_TEST_SUITE("combine test");
+    test->add(BOOST_TEST_CASE(&combine_test));
+    return test;
+}
Modified: branches/iostreams_dev/libs/iostreams/test/compose_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/compose_test.cpp	(original)
+++ branches/iostreams_dev/libs/iostreams/test/compose_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -10,6 +10,8 @@
 #include <boost/iostreams/filtering_stream.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
+#include "detail/closable.hpp"
+#include "detail/operation_sequence.hpp"
 #include "detail/filters.hpp"
 #include "detail/temp_file.hpp"
 #include "detail/verification.hpp"
@@ -17,13 +19,14 @@
 // Must come last.
 #include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x.
 
+using namespace std;
 using namespace boost::iostreams;
+using namespace boost::iostreams::test;
 using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
 
 void read_composite()
 {
-    using namespace boost::iostreams::test;
-
     test_file          src1, src2;
     filtering_istream  first, second;
 
@@ -56,9 +59,6 @@
 
 void write_composite()
 {
-    using namespace std;
-    using namespace boost::iostreams::test;
-
     temp_file          dest1, dest2;
     filtering_ostream  out1, out2;
 
@@ -105,11 +105,392 @@
     }
 }
 
+void close_composite_device()
+{
+    // Compose an input filter with a source
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<input>(seq.new_operation(2)),
+                closable_device<input>(seq.new_operation(1))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a bidirectional filter with a source
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<bidirectional>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                closable_device<input>(seq.new_operation(1))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a seekable filter with a source
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<seekable>(seq.new_operation(2)),
+                closable_device<input>(seq.new_operation(1))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a dual-use filter with a source
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<dual_use>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                closable_device<input>(seq.new_operation(1))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose an output filter with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<output>(seq.new_operation(1)),
+                closable_device<output>(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a bidirectional filter with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<bidirectional>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                closable_device<output>(seq.new_operation(3))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a seekable filter with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<seekable>(seq.new_operation(1)),
+                closable_device<output>(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a dual-use filter with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<dual_use>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                closable_device<output>(seq.new_operation(3))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a bidirectional filter with a bidirectional device
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::compose(
+                closable_filter<bidirectional>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                closable_device<bidirectional>(
+                    seq.new_operation(1),
+                    seq.new_operation(4)
+                )
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a seekable filter with a seekable device
+    {
+        operation_sequence  seq;
+        chain<seekable>     ch;
+        ch.push(
+            io::compose(
+                closable_filter<seekable>(seq.new_operation(1)),
+                closable_device<seekable>(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
+void close_composite_filter()
+{
+    // Compose two input filters
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<input>(seq.new_operation(3)),
+                closable_filter<input>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a bidirectional filter with an input filter
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<bidirectional>(
+                    seq.new_operation(3),
+                    seq.new_operation(4)
+                ),
+                closable_filter<input>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_MESSAGE(seq.is_success(), seq.message());
+    }
+
+    // Compose a seekable filter with an input filter
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<seekable>(seq.new_operation(3)),
+                closable_filter<input>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a dual-use filter with an input filter
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<dual_use>(
+                    seq.new_operation(3),
+                    seq.new_operation(4)
+                ),
+                closable_filter<input>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose two output filters
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<output>(seq.new_operation(1)),
+                closable_filter<output>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a bidirectional filter with an output filter
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<bidirectional>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                closable_filter<output>(seq.new_operation(3))
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(4)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a seekable filter with an output filter
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<seekable>(seq.new_operation(1)),
+                closable_filter<output>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose a dual-use filter with an output filter
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<dual_use>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                closable_filter<output>(seq.new_operation(3))
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(4)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose two bidirectional filters
+    {
+        operation_sequence    seq;
+        chain<bidirectional>  ch;
+        ch.push(
+            io::compose(
+                closable_filter<bidirectional>(
+                    seq.new_operation(3),
+                    seq.new_operation(4)
+                ),
+                closable_filter<bidirectional>(
+                    seq.new_operation(2),
+                    seq.new_operation(5)
+                )
+            )
+        );
+        ch.push(
+            closable_device<bidirectional>(
+                seq.new_operation(1),
+                seq.new_operation(6)
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose two seekable filters
+    {
+        operation_sequence  seq;
+        chain<seekable>     ch;
+        ch.push(
+            io::compose(
+                closable_filter<seekable>(seq.new_operation(1)),
+                closable_filter<seekable>(seq.new_operation(2))
+            )
+        );
+        ch.push(closable_device<seekable>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose two dual-use filters for input
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::compose(
+                closable_filter<dual_use>(
+                    seq.new_operation(3),
+                    seq.new_operation(4)
+                ),
+                closable_filter<dual_use>(
+                    seq.new_operation(2),
+                    seq.new_operation(5)
+                )
+            )
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Compose two dual-use filters for output
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::compose(
+                closable_filter<dual_use>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                closable_filter<dual_use>(
+                    seq.new_operation(1),
+                    seq.new_operation(4)
+                )
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(5)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
 test_suite* init_unit_test_suite(int, char* [])
 {
     test_suite* test = BOOST_TEST_SUITE("line_filter test");
     test->add(BOOST_TEST_CASE(&read_composite));
     test->add(BOOST_TEST_CASE(&write_composite));
+    test->add(BOOST_TEST_CASE(&close_composite_device));
+    test->add(BOOST_TEST_CASE(&close_composite_filter));
     return test;
 }
 
Modified: branches/iostreams_dev/libs/iostreams/test/invert_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/invert_test.cpp	(original)
+++ branches/iostreams_dev/libs/iostreams/test/invert_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -9,14 +9,17 @@
 #include <boost/iostreams/invert.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
+#include "detail/closable.hpp"
 #include "detail/filters.hpp"
+#include "detail/operation_sequence.hpp"
 #include "detail/temp_file.hpp"
 
 using namespace boost::iostreams;
 using namespace boost::iostreams::test;
-using boost::unit_test::test_suite;  
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
 
-void inverse_test()
+void read_write_test()
 {
 
     test_file       test;
@@ -34,10 +37,33 @@
                     file_source(upper.name(), in_mode) ) );
 }
 
+void close_test()
+{
+    // Invert an output filter
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(io::invert(closable_filter<output>(seq.new_operation(2))));
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Invert an input filter
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(io::invert(closable_filter<input>(seq.new_operation(1))));
+        ch.push(closable_device<output>(seq.new_operation(2)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
 
 test_suite* init_unit_test_suite(int, char* []) 
 {
     test_suite* test = BOOST_TEST_SUITE("reverse test");
-    test->add(BOOST_TEST_CASE(&inverse_test));
+    test->add(BOOST_TEST_CASE(&read_write_test));
+    test->add(BOOST_TEST_CASE(&close_test));
     return test;
 }
Modified: branches/iostreams_dev/libs/iostreams/test/restrict_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/restrict_test.cpp	(original)
+++ branches/iostreams_dev/libs/iostreams/test/restrict_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -17,17 +17,19 @@
 #include <boost/iostreams/restrict.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
+#include "detail/closable.hpp"
 #include "detail/constants.hpp"
 #include "detail/filters.hpp"
+#include "detail/operation_sequence.hpp"
 #include "detail/sequence.hpp"
 #include "detail/temp_file.hpp"
 #include "detail/verification.hpp"
 
 using namespace std;
-using namespace boost;
 using namespace boost::iostreams;
 using namespace boost::iostreams::test;
-using boost::unit_test::test_suite;   
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
 
 const char pad_char = '\n';
 const int small_padding = 50;
@@ -521,6 +523,115 @@
     }
 }
 
+void close_device()
+{
+    // Restrict a source
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(io::restrict(closable_device<input>(seq.new_operation(1)), 0));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Restrict a seekable device
+    {
+        operation_sequence  seq;
+        chain<seekable>     ch;
+        ch.push(
+            io::restrict(closable_device<seekable>(seq.new_operation(1)), 0)
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Restrict a direct source
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::restrict(closable_device<direct_input>(seq.new_operation(1)), 0)
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Restrict a direct seekable device
+    {
+        operation_sequence  seq;
+        chain<seekable>     ch;
+        ch.push(
+            io::restrict(
+                closable_device<direct_seekable>(seq.new_operation(1)), 
+                0
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
+void close_filter()
+{
+    // Restrict an input filter
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(io::restrict(closable_filter<input>(seq.new_operation(2)), 0));
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Restrict a seekable filter
+    {
+        operation_sequence  seq;
+        chain<seekable>     ch;
+        ch.push(
+            io::restrict(closable_filter<seekable>(seq.new_operation(1)), 0)
+        );
+        ch.push(closable_device<seekable>(seq.new_operation(2)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Restrict a dual_use filter for input
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::restrict(
+                closable_filter<dual_use>(
+                    seq.new_operation(2),
+                    seq.new_operation(3)
+                ),
+                0
+            )
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Restrict a dual_use filter for output
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::restrict(
+                closable_filter<dual_use>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                0
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
 test_suite* init_unit_test_suite(int, char* []) 
 {
     test_suite* test = BOOST_TEST_SUITE("restrict test");
@@ -532,5 +643,7 @@
     test->add(BOOST_TEST_CASE(&write_filter));
     test->add(BOOST_TEST_CASE(&seek_device));
     test->add(BOOST_TEST_CASE(&seek_direct_device));
+    test->add(BOOST_TEST_CASE(&close_device));
+    test->add(BOOST_TEST_CASE(&close_filter));
     return test;
 }
Modified: branches/iostreams_dev/libs/iostreams/test/symmetric_filter_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/symmetric_filter_test.cpp	(original)
+++ branches/iostreams_dev/libs/iostreams/test/symmetric_filter_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -10,7 +10,9 @@
 #include <boost/iostreams/filter/test.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
+#include "detail/closable.hpp"
 #include "./detail/constants.hpp"
+#include "detail/operation_sequence.hpp"
 #include "./detail/temp_file.hpp"
 #include "./detail/verification.hpp"
 
@@ -19,7 +21,8 @@
 
 using namespace boost::iostreams;
 using namespace boost::iostreams::test;
-using boost::unit_test::test_suite;   
+using boost::unit_test::test_suite;  
+namespace io = boost::iostreams; 
 
 // Note: The filter is given an internal buffer -- unnecessary in this simple
 // case -- to stress test symmetric_filter.
@@ -77,7 +80,7 @@
 typedef symmetric_filter<toupper_symmetric_filter_impl>
         toupper_symmetric_filter;
 
-void read_symmetric_filter_test()
+void read_symmetric_filter()
 {
     test_file       test;
     uppercase_file  upper;
@@ -88,7 +91,7 @@
     );
 } 
 
-void write_symmetric_filter_test()
+void write_symmetric_filter()
 {
     test_file       test;
     uppercase_file  upper;
@@ -99,11 +102,41 @@
     );
 }
 
+void close_symmetric_filter()
+{
+    // Test input
+    {
+        operation_sequence  seq;
+        chain<input>        ch;
+        ch.push(
+            io::symmetric_filter<closable_symmetric_filter>
+                (0, seq.new_operation(2))
+        );
+        ch.push(closable_device<input>(seq.new_operation(1)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Test output
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::symmetric_filter<closable_symmetric_filter>
+                (0, seq.new_operation(1))
+        );
+        ch.push(closable_device<output>(seq.new_operation(2)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
 test_suite* init_unit_test_suite(int, char* []) 
 {
     test_suite* test = BOOST_TEST_SUITE("symmetric_filter test");
-    test->add(BOOST_TEST_CASE(&read_symmetric_filter_test));
-    test->add(BOOST_TEST_CASE(&write_symmetric_filter_test));
+    test->add(BOOST_TEST_CASE(&read_symmetric_filter));
+    test->add(BOOST_TEST_CASE(&write_symmetric_filter));
+    test->add(BOOST_TEST_CASE(&close_symmetric_filter));
     return test;
 }
 
Modified: branches/iostreams_dev/libs/iostreams/test/tee_test.cpp
==============================================================================
--- branches/iostreams_dev/libs/iostreams/test/tee_test.cpp	(original)
+++ branches/iostreams_dev/libs/iostreams/test/tee_test.cpp	2008-01-06 13:26:45 EST (Sun, 06 Jan 2008)
@@ -5,11 +5,14 @@
 // See http://www.boost.org/libs/iostreams for documentation.
 
 #include <fstream>
+#include <boost/iostreams/compose.hpp>
 #include <boost/iostreams/device/file.hpp>
 #include <boost/iostreams/filtering_stream.hpp>
 #include <boost/iostreams/tee.hpp>
 #include <boost/test/test_tools.hpp>
 #include <boost/test/unit_test.hpp>
+#include "detail/closable.hpp"
+#include "detail/operation_sequence.hpp"
 #include "detail/temp_file.hpp"
 #include "detail/verification.hpp"
 
@@ -18,8 +21,9 @@
 using namespace boost::iostreams;
 using namespace boost::iostreams::test;
 using boost::unit_test::test_suite;  
+namespace io = boost::iostreams;
 
-void tee_test()
+void read_write_test()
 {
     {
         temp_file          dest1;
@@ -78,9 +82,229 @@
     }
 }
 
+void close_test()
+{
+    // Note: The implementation of tee_device closes the first
+    // sink before the second
+
+    // Tee two sinks (Borland <= 5.8.2 needs a little help compiling this case,
+    // but it executes the closing algorithm correctly)
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                closable_device<output>(seq.new_operation(1)),
+                closable_device<
+                    #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+                        borland_output
+                    #else
+                        output
+                    #endif
+                >(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee two bidirectional devices
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                closable_device<bidirectional>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                ),
+                closable_device<bidirectional>(
+                    seq.new_operation(3),
+                    seq.new_operation(4)
+                )
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee two seekable devices
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                closable_device<seekable>(seq.new_operation(1)),
+                closable_device<seekable>(seq.new_operation(2))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(io::tee(closable_device<output>(seq.new_operation(1))));
+        ch.push(closable_device<output>(seq.new_operation(2)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a bidirectional device
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                closable_device<bidirectional>(
+                    seq.new_operation(1),
+                    seq.new_operation(2)
+                )
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a seekable device
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(io::tee(closable_device<seekable>(seq.new_operation(1))));
+        ch.push(closable_device<seekable>(seq.new_operation(2)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
+void tee_composite_test()
+{
+    // This test is probably redundant, given the above test and the tests in
+    // compose_test.cpp, but it verifies that ticket #1002 is fixed
+
+    // Tee a composite sink with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                io::compose(
+                    closable_filter<output>(seq.new_operation(1)),
+                    closable_device<output>(seq.new_operation(2))
+                ),
+                closable_device<output>(seq.new_operation(3))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a composite bidirectional device with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                io::compose(
+                    closable_filter<bidirectional>(
+                        seq.new_operation(2),
+                        seq.new_operation(3)
+                    ),
+                    closable_device<bidirectional>(
+                        seq.new_operation(1),
+                        seq.new_operation(4)
+                    )
+                ),
+                closable_device<output>(seq.new_operation(5))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a composite composite seekable device with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                io::compose(
+                    closable_filter<seekable>(seq.new_operation(1)),
+                    closable_device<seekable>(seq.new_operation(2))
+                ),
+                closable_device<output>(seq.new_operation(3))
+            )
+        );
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+
+    // Tee a composite sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                io::compose(
+                    closable_filter<output>(seq.new_operation(1)),
+                    closable_device<output>(seq.new_operation(2))
+                )
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a composite bidirectional device with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                io::compose(
+                    closable_filter<bidirectional>(
+                        seq.new_operation(2),
+                        seq.new_operation(3)
+                    ),
+                    closable_device<bidirectional>(
+                        seq.new_operation(1),
+                        seq.new_operation(4)
+                    )
+                )
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(5)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+
+    // Tee a composite composite seekable device with a sink
+    {
+        operation_sequence  seq;
+        chain<output>       ch;
+        ch.push(
+            io::tee(
+                io::compose(
+                    closable_filter<seekable>(seq.new_operation(1)),
+                    closable_device<seekable>(seq.new_operation(2))
+                )
+            )
+        );
+        ch.push(closable_device<output>(seq.new_operation(3)));
+        BOOST_CHECK_NO_THROW(ch.reset());
+        BOOST_CHECK_OPERATION_SEQUENCE(seq);
+    }
+}
+
 test_suite* init_unit_test_suite(int, char* []) 
 {
     test_suite* test = BOOST_TEST_SUITE("tee test");
-    test->add(BOOST_TEST_CASE(&tee_test));
+    test->add(BOOST_TEST_CASE(&read_write_test));
+    test->add(BOOST_TEST_CASE(&close_test));
     return test;
 }