| /* |
| * 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 |
| * used with chains and streams. |
| * |
| * File: libs/iostreams/test/close_test.cpp |
| * Date: Sun Dec 09 16:12:23 MST 2007 |
| * Copyright: 2007 CodeRage |
| * Author: Jonathan Turkanis |
| */ |
| |
| #include <boost/iostreams/chain.hpp> |
| #include <boost/iostreams/filtering_streambuf.hpp> |
| #include <boost/iostreams/stream.hpp> |
| #include <boost/test/test_tools.hpp> |
| #include <boost/test/unit_test.hpp> |
| #include "detail/closable.hpp" |
| #include "detail/operation_sequence.hpp" |
| |
| using namespace std; |
| using namespace boost; |
| using namespace boost::iostreams; |
| using namespace boost::iostreams::test; |
| using boost::unit_test::test_suite; |
| namespace io = boost::iostreams; |
| |
| void input_chain_test() |
| { |
| // Test input filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<input>(seq.new_operation(2))); |
| ch.push(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test bidirectional filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| |
| // Test chain::pop() |
| ch.push( |
| closable_filter<bidirectional>( |
| seq.new_operation(2), |
| seq.new_operation(3) |
| ) |
| ); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test seekable filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<seekable>(seq.new_operation(1))); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test dual-user filter |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| operation dummy; |
| |
| // Test chain::pop() |
| ch.push( |
| closable_filter<dual_use>( |
| seq.new_operation(2), |
| dummy |
| ) |
| ); |
| ch.push(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct source |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<input>(seq.new_operation(2))); |
| ch.push(closable_device<direct_input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<direct_input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<direct_input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct bidirectional device |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<input>(seq.new_operation(2))); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(3) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(3) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(3) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct seekable device |
| { |
| operation_sequence seq; |
| filtering_streambuf<input> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<input>(seq.new_operation(1))); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| } |
| |
| void output_chain_test() |
| { |
| // Test output filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<output>(seq.new_operation(1))); |
| ch.push(closable_device<output>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<output>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<output>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test bidirectional filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| |
| // Test chain::pop() |
| ch.push( |
| closable_filter<bidirectional>( |
| seq.new_operation(2), |
| seq.new_operation(3) |
| ) |
| ); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test seekable filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<seekable>(seq.new_operation(1))); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test dual-user filter |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| operation dummy; |
| |
| // Test chain::pop() |
| ch.push( |
| closable_filter<dual_use>( |
| dummy, |
| seq.new_operation(1) |
| ) |
| ); |
| ch.push(closable_device<output>(seq.new_operation(3))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<output>(seq.new_operation(3))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<output>(seq.new_operation(3))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct sink |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<output>(seq.new_operation(1))); |
| ch.push(closable_device<direct_output>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<direct_output>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<direct_output>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct bidirectional device |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<output>(seq.new_operation(2))); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(3) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(3) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(3) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct seekable device |
| { |
| operation_sequence seq; |
| filtering_streambuf<output> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<output>(seq.new_operation(1))); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| } |
| |
| void bidirectional_chain_test() |
| { |
| // Test bidirectional filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<bidirectional> ch; |
| |
| // Test chain::pop() |
| ch.push( |
| closable_filter<bidirectional>( |
| seq.new_operation(2), |
| seq.new_operation(3) |
| ) |
| ); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct bidirectional device |
| { |
| operation_sequence seq; |
| filtering_streambuf<bidirectional> ch; |
| |
| // Test chain::pop() |
| ch.push( |
| closable_filter<bidirectional>( |
| seq.new_operation(2), |
| seq.new_operation(3) |
| ) |
| ); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push( |
| closable_device<direct_bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(4) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| } |
| |
| void seekable_chain_test() |
| { |
| // Test seekable filter and device |
| { |
| operation_sequence seq; |
| filtering_streambuf<seekable> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<seekable>(seq.new_operation(1))); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test direct seekable device |
| { |
| operation_sequence seq; |
| filtering_streambuf<seekable> ch; |
| |
| // Test chain::pop() |
| ch.push(closable_filter<seekable>(seq.new_operation(1))); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.pop()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and io::close() |
| seq.reset(); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(io::close(ch)); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| |
| // Test filter reuse and chain::reset() |
| seq.reset(); |
| ch.push(closable_device<direct_seekable>(seq.new_operation(2))); |
| BOOST_CHECK_NO_THROW(ch.reset()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| } |
| |
| void stream_test() |
| { |
| // Test source |
| { |
| operation_sequence seq; |
| stream< closable_device<input> > str; |
| str.open(closable_device<input>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(str.close()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test sink |
| { |
| operation_sequence seq; |
| stream< closable_device<output> > str; |
| str.open(closable_device<output>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(str.close()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test bidirectional device |
| { |
| operation_sequence seq; |
| stream< closable_device<bidirectional> > str; |
| str.open( |
| closable_device<bidirectional>( |
| seq.new_operation(1), |
| seq.new_operation(2) |
| ) |
| ); |
| BOOST_CHECK_NO_THROW(str.close()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| |
| // Test seekable device |
| { |
| operation_sequence seq; |
| stream< closable_device<seekable> > str; |
| str.open(closable_device<seekable>(seq.new_operation(1))); |
| BOOST_CHECK_NO_THROW(str.close()); |
| BOOST_CHECK_OPERATION_SEQUENCE(seq); |
| } |
| } |
| |
| test_suite* init_unit_test_suite(int, char* []) |
| { |
| test_suite* test = BOOST_TEST_SUITE("execute test"); |
| test->add(BOOST_TEST_CASE(&input_chain_test)); |
| test->add(BOOST_TEST_CASE(&output_chain_test)); |
| test->add(BOOST_TEST_CASE(&bidirectional_chain_test)); |
| test->add(BOOST_TEST_CASE(&seekable_chain_test)); |
| test->add(BOOST_TEST_CASE(&stream_test)); |
| return test; |
| } |