summaryrefslogtreecommitdiff
path: root/libs/iostreams/test
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /libs/iostreams/test
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'libs/iostreams/test')
-rw-r--r--libs/iostreams/test/Jamfile.v2152
-rw-r--r--libs/iostreams/test/array_test.cpp99
-rw-r--r--libs/iostreams/test/auto_close_test.cpp184
-rw-r--r--libs/iostreams/test/bool_trait_test.cpp252
-rw-r--r--libs/iostreams/test/buffer_size_test.cpp82
-rw-r--r--libs/iostreams/test/bzip2_test.cpp96
-rw-r--r--libs/iostreams/test/close_test.cpp651
-rw-r--r--libs/iostreams/test/code_converter_test.cpp387
-rw-r--r--libs/iostreams/test/combine_test.cpp227
-rw-r--r--libs/iostreams/test/component_access_test.cpp173
-rw-r--r--libs/iostreams/test/compose_test.cpp504
-rw-r--r--libs/iostreams/test/copy_test.cpp172
-rw-r--r--libs/iostreams/test/counter_test.cpp98
-rw-r--r--libs/iostreams/test/deprecated_file_descriptor_test.cpp243
-rw-r--r--libs/iostreams/test/detail/closable.hpp343
-rw-r--r--libs/iostreams/test/detail/constants.hpp67
-rw-r--r--libs/iostreams/test/detail/file_handle.hpp108
-rw-r--r--libs/iostreams/test/detail/filters.hpp186
-rw-r--r--libs/iostreams/test/detail/null_padded_codecvt.hpp275
-rw-r--r--libs/iostreams/test/detail/operation_sequence.hpp224
-rw-r--r--libs/iostreams/test/detail/sequence.hpp274
-rw-r--r--libs/iostreams/test/detail/temp_file.hpp92
-rw-r--r--libs/iostreams/test/detail/utf8_codecvt_facet.cpp371
-rw-r--r--libs/iostreams/test/detail/utf8_codecvt_facet.hpp200
-rw-r--r--libs/iostreams/test/detail/verification.hpp316
-rw-r--r--libs/iostreams/test/direct_adapter_test.cpp111
-rw-r--r--libs/iostreams/test/example_test.cpp461
-rw-r--r--libs/iostreams/test/execute_test.cpp660
-rw-r--r--libs/iostreams/test/file_descriptor_test.cpp642
-rw-r--r--libs/iostreams/test/file_test.cpp63
-rw-r--r--libs/iostreams/test/filter_test.cpp98
-rw-r--r--libs/iostreams/test/filtering_stream_flush_test.hpp36
-rw-r--r--libs/iostreams/test/filtering_stream_test.cpp52
-rw-r--r--libs/iostreams/test/finite_state_filter_test.cpp182
-rw-r--r--libs/iostreams/test/flush_test.cpp145
-rw-r--r--libs/iostreams/test/grep_test.cpp282
-rw-r--r--libs/iostreams/test/gzip_test.cpp121
-rw-r--r--libs/iostreams/test/invert_test.cpp70
-rw-r--r--libs/iostreams/test/large_file_test.cpp446
-rw-r--r--libs/iostreams/test/line_filter_test.cpp99
-rw-r--r--libs/iostreams/test/mapped_file_test.cpp329
-rw-r--r--libs/iostreams/test/newline_test.cpp486
-rw-r--r--libs/iostreams/test/null_test.cpp44
-rw-r--r--libs/iostreams/test/operation_sequence_test.cpp268
-rw-r--r--libs/iostreams/test/path_test.cpp25
-rw-r--r--libs/iostreams/test/pipeline_test.cpp90
-rw-r--r--libs/iostreams/test/putback_test.hpp167
-rw-r--r--libs/iostreams/test/read_bidir_filter_test.hpp131
-rw-r--r--libs/iostreams/test/read_bidir_streambuf_test.hpp77
-rw-r--r--libs/iostreams/test/read_bidir_test.hpp85
-rw-r--r--libs/iostreams/test/read_input_filter_test.hpp105
-rw-r--r--libs/iostreams/test/read_input_istream_test.hpp76
-rw-r--r--libs/iostreams/test/read_input_seq_test.hpp70
-rw-r--r--libs/iostreams/test/read_input_test.hpp65
-rw-r--r--libs/iostreams/test/read_seekable_seq_test.hpp71
-rw-r--r--libs/iostreams/test/read_seekable_test.hpp69
-rw-r--r--libs/iostreams/test/regex_filter_test.cpp329
-rw-r--r--libs/iostreams/test/restrict_test.cpp690
-rw-r--r--libs/iostreams/test/seek_test.hpp51
-rw-r--r--libs/iostreams/test/seekable_file_test.cpp56
-rw-r--r--libs/iostreams/test/seekable_filter_test.cpp95
-rw-r--r--libs/iostreams/test/sequence_test.cpp24
-rw-r--r--libs/iostreams/test/slice_test.cpp17
-rw-r--r--libs/iostreams/test/stdio_filter_test.cpp144
-rw-r--r--libs/iostreams/test/stream_offset_32bit_test.cpp51
-rw-r--r--libs/iostreams/test/stream_offset_64bit_test.cpp85
-rw-r--r--libs/iostreams/test/stream_state_test.cpp161
-rw-r--r--libs/iostreams/test/symmetric_filter_test.cpp182
-rw-r--r--libs/iostreams/test/tee_test.cpp370
-rw-r--r--libs/iostreams/test/wide_stream_test.cpp145
-rw-r--r--libs/iostreams/test/write_bidir_filter_test.hpp134
-rw-r--r--libs/iostreams/test/write_bidir_streambuf_test.hpp87
-rw-r--r--libs/iostreams/test/write_bidir_test.hpp89
-rw-r--r--libs/iostreams/test/write_output_filter_test.hpp114
-rw-r--r--libs/iostreams/test/write_output_iterator_test.hpp85
-rw-r--r--libs/iostreams/test/write_output_ostream_test.hpp84
-rw-r--r--libs/iostreams/test/write_output_seq_test.hpp78
-rw-r--r--libs/iostreams/test/write_output_test.hpp73
-rw-r--r--libs/iostreams/test/write_seekable_seq_test.hpp79
-rw-r--r--libs/iostreams/test/write_seekable_test.hpp77
-rw-r--r--libs/iostreams/test/zlib_test.cpp60
81 files changed, 14762 insertions, 0 deletions
diff --git a/libs/iostreams/test/Jamfile.v2 b/libs/iostreams/test/Jamfile.v2
new file mode 100644
index 0000000000..794a02de29
--- /dev/null
+++ b/libs/iostreams/test/Jamfile.v2
@@ -0,0 +1,152 @@
+# Boost.Iostreams Library test Jamfile
+
+# (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+# (C) Copyright 2004-2007 Jonathan Turkanis
+# 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.
+
+import stlport ;
+import modules ;
+
+local NO_BZIP2 = [ modules.peek : NO_BZIP2 ] ;
+local NO_ZLIB = [ modules.peek : NO_ZLIB ] ;
+local LARGE_FILE_TEMP = [ modules.peek : LARGE_FILE_TEMP ] ;
+local LARGE_FILE_KEEP = [ modules.peek : LARGE_FILE_KEEP ] ;
+
+rule test-iostreams ( sources * : requirements * : target-name ? ) {
+ return [
+ run
+ $(sources)
+ /boost/test//boost_unit_test_framework/<link>static
+ /boost/filesystem//boost_filesystem/<link>static
+ : # command
+ : # input files
+ : # build requirements
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>cw-9.3,<os>darwin:<runtime-link>static
+ <define>BOOST_IOSTREAMS_NO_LIB
+ <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1
+ $(requirements)
+ : $(target-name)
+ ] ;
+}
+
+rule compile-fail-iostreams ( sources * : requirements * : target-name ? ) {
+ return [
+ compile-fail
+ $(sources)
+ /boost/test//boost_unit_test_framework/<link>static
+ /boost/filesystem//boost_filesystem/<link>static
+ : # build requirements
+ <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
+ <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
+ <toolset>cw-9.3,<os>darwin:<runtime-link>static
+ <define>BOOST_IOSTREAMS_NO_LIB
+ <link>shared:<define>BOOST_IOSTREAMS_DYN_LINK=1
+ $(requirements)
+ : $(target-name)
+ ] ;
+}
+
+
+ local all-tests =
+ [ test-iostreams array_test.cpp ]
+ [ test-iostreams auto_close_test.cpp ]
+ [ test-iostreams buffer_size_test.cpp ]
+ [ test-iostreams close_test.cpp ]
+ [ 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 ]
+ [ test-iostreams counter_test.cpp ]
+ [ test-iostreams direct_adapter_test.cpp ]
+ [ test-iostreams example_test.cpp ]
+ [ test-iostreams execute_test.cpp ]
+ [ test-iostreams file_test.cpp ]
+ [ test-iostreams file_descriptor_test.cpp
+ ../build//boost_iostreams ]
+ [ test-iostreams deprecated_file_descriptor_test.cpp
+ ../build//boost_iostreams
+ : <define>BOOST_IOSTREAMS_USE_DEPRECATED ]
+ [ compile-fail-iostreams deprecated_file_descriptor_test.cpp
+ :
+ : deprecated_file_descriptor_fail ]
+ [ test-iostreams filtering_stream_test.cpp ]
+ [ test-iostreams finite_state_filter_test.cpp ]
+ [ test-iostreams flush_test.cpp ]
+ [ test-iostreams
+ grep_test.cpp
+ /boost/regex//boost_regex ]
+ [ test-iostreams invert_test.cpp ]
+ [ test-iostreams line_filter_test.cpp ]
+ [ test-iostreams mapped_file_test.cpp
+ ../build//boost_iostreams ]
+ [ test-iostreams path_test.cpp
+ : <define>BOOST_FILESYSTEM_VERSION=2
+ : path_test_filesystem2 ]
+ [ test-iostreams path_test.cpp
+ : <define>BOOST_FILESYSTEM_VERSION=3
+ : path_test_filesystem3 ]
+ [ test-iostreams newline_test.cpp ]
+ [ test-iostreams null_test.cpp ]
+ [ test-iostreams operation_sequence_test.cpp ]
+ [ test-iostreams pipeline_test.cpp ]
+ [ test-iostreams
+ regex_filter_test.cpp
+ /boost/regex//boost_regex ]
+ [ test-iostreams restrict_test.cpp ]
+ [ test-iostreams seekable_file_test.cpp ]
+ [ test-iostreams seekable_filter_test.cpp ]
+ [ test-iostreams sequence_test.cpp ]
+ [ test-iostreams slice_test.cpp ]
+ [ test-iostreams stdio_filter_test.cpp ]
+ [ test-iostreams stream_offset_32bit_test.cpp ]
+ [ test-iostreams stream_offset_64bit_test.cpp ]
+ #[ test-iostreams stream_state_test.cpp ]
+ [ test-iostreams symmetric_filter_test.cpp ]
+ [ test-iostreams tee_test.cpp ]
+ [ test-iostreams wide_stream_test.cpp ]
+ ;
+
+ if $(LARGE_FILE_KEEP)
+ {
+ all-tests +=
+ [ test-iostreams
+ large_file_test.cpp
+ ../src/file_descriptor.cpp
+ ../src/mapped_file.cpp
+ : <define>LARGE_FILE_KEEP=$(LARGE_FILE_KEEP)
+ <link>static ] ;
+ }
+ if $(LARGE_FILE_TEMP)
+ {
+ all-tests +=
+ [ test-iostreams
+ large_file_test.cpp
+ ../src/file_descriptor.cpp
+ ../src/mapped_file.cpp
+ : <define>LARGE_FILE_TEMP=$(LARGE_FILE_TEMP)
+ <link>static ] ;
+ }
+ if ! $(NO_BZIP2)
+ {
+ all-tests += [ test-iostreams
+ bzip2_test.cpp ../build//boost_iostreams ] ;
+ }
+ if ! $(NO_ZLIB)
+ {
+ all-tests +=
+ [ test-iostreams
+ gzip_test.cpp ../build//boost_iostreams ]
+ [ test-iostreams
+ zlib_test.cpp ../build//boost_iostreams ] ;
+ }
+
+ test-suite "iostreams" : $(all-tests) ;
+
diff --git a/libs/iostreams/test/array_test.cpp b/libs/iostreams/test/array_test.cpp
new file mode 100644
index 0000000000..0ad62bfa81
--- /dev/null
+++ b/libs/iostreams/test/array_test.cpp
@@ -0,0 +1,99 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/iostreams/detail/fstream.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+using boost::unit_test::test_suite;
+
+void array_test()
+{
+ using namespace std;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ //--------------stream<array_source>-------------------------------//
+
+ {
+ test_sequence<> seq;
+ stream<array_source> first(&seq[0], &seq[0] + seq.size());
+ ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from stream<array_source> in chars"
+ );
+ }
+
+ {
+ test_sequence<> seq;
+ stream<array_source> first(&seq[0], &seq[0] + seq.size());
+ ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from stream<array_source> in chunks"
+ );
+ }
+
+ //--------------stream<array_sink>---------------------------------//
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ stream<array_sink> out(&first[0], &first[0] + first.size());
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to stream<array_sink> in chars"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ stream<array_sink> out(&first[0], &first[0] + first.size());
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to stream<array_sink> in chunks"
+ );
+ }
+
+ //--------------random access---------------------------------------------//
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ stream<array> io(&first[0], &first[0] + first.size());
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within stream<array>, in chars"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ stream<array> io(&first[0], &first[0] + first.size());
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within stream<array>, in chunks"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("array test");
+ test->add(BOOST_TEST_CASE(&array_test));
+ return test;
+}
diff --git a/libs/iostreams/test/auto_close_test.cpp b/libs/iostreams/test/auto_close_test.cpp
new file mode 100644
index 0000000000..fb68022549
--- /dev/null
+++ b/libs/iostreams/test/auto_close_test.cpp
@@ -0,0 +1,184 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <cstdio> // EOF.
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.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;
+
+class closable_source : public source {
+public:
+ closable_source() : open_(new bool(true)) { }
+ std::streamsize read(char*, std::streamsize) { return 0; }
+ void open() { *open_ = true; }
+ void close() { *open_ = false; }
+ bool is_open() const { return *open_; }
+private:
+ boost::shared_ptr<bool> open_;
+};
+
+class closable_input_filter : public input_filter {
+public:
+ closable_input_filter() : open_(new bool(true)) { }
+
+ template<typename Source>
+ int get(Source&) { return EOF; }
+
+ void open() { *open_ = true; }
+
+ template<typename Source>
+ void close(Source&) { *open_ = false; }
+
+ bool is_open() const { return *open_; }
+private:
+ boost::shared_ptr<bool> open_;
+};
+
+void auto_close_source()
+{
+ // Rely on auto_close to close source.
+ closable_source src;
+ {
+ stream<closable_source> in(src);
+ BOOST_CHECK(src.is_open());
+ BOOST_CHECK(in.auto_close());
+ }
+ BOOST_CHECK(!src.is_open());
+
+ // Use close() to close components.
+ src.open();
+ {
+ stream<closable_source> in(src);
+ BOOST_CHECK(src.is_open());
+ BOOST_CHECK(in.auto_close());
+ in.close();
+ BOOST_CHECK(!src.is_open());
+ }
+
+ // Use close() to close components, with auto_close disabled.
+ src.open();
+ {
+ stream<closable_source> in(src);
+ BOOST_CHECK(src.is_open());
+ in.set_auto_close(false);
+ in.close();
+ BOOST_CHECK(!src.is_open());
+ }
+
+ // Disable auto_close.
+ src.open();
+ {
+ stream<closable_source> in(src);
+ BOOST_CHECK(src.is_open());
+ in.set_auto_close(false);
+ BOOST_CHECK(!in.auto_close());
+ }
+ BOOST_CHECK(src.is_open());
+}
+
+void auto_close_filter()
+{
+ closable_source src;
+ closable_input_filter flt;
+
+ // Rely on auto_close to close components.
+ {
+ filtering_istream in;
+ in.push(flt);
+ in.push(src);
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ BOOST_CHECK(in.auto_close());
+ }
+ BOOST_CHECK(!flt.is_open());
+ BOOST_CHECK(!src.is_open());
+
+ // Use reset() to close components.
+ flt.open();
+ src.open();
+ {
+ filtering_istream in;
+ in.push(flt);
+ in.push(src);
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ BOOST_CHECK(in.auto_close());
+ in.reset();
+ BOOST_CHECK(!flt.is_open());
+ BOOST_CHECK(!src.is_open());
+ }
+
+ // Use reset() to close components, with auto_close disabled.
+ flt.open();
+ src.open();
+ {
+ filtering_istream in;
+ in.push(flt);
+ in.push(src);
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ in.set_auto_close(false);
+ in.reset();
+ BOOST_CHECK(!flt.is_open());
+ BOOST_CHECK(!src.is_open());
+ }
+
+ // Disable auto_close.
+ flt.open();
+ src.open();
+ {
+ filtering_istream in;
+ in.push(flt);
+ in.push(src);
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ in.set_auto_close(false);
+ BOOST_CHECK(!in.auto_close());
+ in.pop();
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ }
+ BOOST_CHECK(!flt.is_open());
+ BOOST_CHECK(src.is_open());
+
+ // Disable auto_close; disconnect and reconnect resource.
+ flt.open();
+ src.open();
+ {
+ filtering_istream in;
+ in.push(flt);
+ in.push(src);
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ in.set_auto_close(false);
+ BOOST_CHECK(!in.auto_close());
+ in.pop();
+ BOOST_CHECK(flt.is_open());
+ BOOST_CHECK(src.is_open());
+ in.push(src);
+ }
+ BOOST_CHECK(!flt.is_open());
+ BOOST_CHECK(!src.is_open());
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("auto_close test");
+ test->add(BOOST_TEST_CASE(&auto_close_source));
+ test->add(BOOST_TEST_CASE(&auto_close_filter));
+ return test;
+}
diff --git a/libs/iostreams/test/bool_trait_test.cpp b/libs/iostreams/test/bool_trait_test.cpp
new file mode 100644
index 0000000000..46bca21dd9
--- /dev/null
+++ b/libs/iostreams/test/bool_trait_test.cpp
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ *
+ * Tests the boolean type traits defined in boost/iostreams/traits.hpp.
+ *
+ * File: libs/iostreams/test/bool_trait_test.cpp
+ * Date: Sun Feb 17 17:52:59 MST 2008
+ * Copyright: 2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#include <fstream>
+#include <sstream>
+#include <boost/iostreams/detail/iostream.hpp>
+#include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
+#include <boost/iostreams/detail/iostream.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/filtering_streambuf.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/stream_buffer.hpp>
+#include <boost/iostreams/traits.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost::iostreams;
+namespace io = boost::iostreams;
+using boost::unit_test::test_suite;
+
+typedef stream<array_source> array_istream;
+typedef stream<warray_source> array_wistream;
+typedef stream<array_sink> array_ostream;
+typedef stream<warray_sink> array_wostream;
+typedef stream<array> array_stream;
+typedef stream<warray> array_wstream;
+typedef stream_buffer<array> array_streambuf;
+typedef stream_buffer<warray> array_wstreambuf;
+
+typedef io::filtering_stream<seekable> filtering_iostream;
+typedef io::filtering_stream<seekable, wchar_t> filtering_wiostream;
+
+typedef io::detail::linked_streambuf<char> linkedbuf;
+typedef io::detail::linked_streambuf<wchar_t> wlinkedbuf;
+
+#define BOOST_CHECK_BOOL_TRAIT(trait, type, status) \
+ BOOST_CHECK(trait< type >::value == status)
+ /**/
+
+#define BOOST_CHECK_STREAM_TRAIT( \
+ trait, \
+ istream_, wistream_, ostream_, wostream_, \
+ iostream_, wiostream_, streambuf_, wstreambuf_, \
+ ifstream_, wifstream_, ofstream_, wofstream_, \
+ fstream_, wfstream_, filebuf_, wfilebuf_, \
+ istringstream_, wistringstream_, ostringstream_, wostringstream_, \
+ stringstream_, wstringstream_, stringbuf_, wstringbuf_, \
+ array_istream_, array_wistream_, array_ostream_, array_wostream_, \
+ array_stream_, array_wstream_, array_streambuf_, array_wstreambuf_, \
+ filtering_istream_, filtering_wistream_, \
+ filtering_ostream_, filtering_wostream_, \
+ filtering_iostream_, filtering_wiostream_, \
+ filtering_istreambuf_, filtering_wistreambuf_, \
+ linkedbuf_, wlinkedbuf_ ) \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::istream, istream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wistream, wistream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::ostream, ostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wostream, wostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::iostream, iostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wiostream, wiostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::streambuf, streambuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wstreambuf, wstreambuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wifstream, wifstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::ofstream, ofstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wofstream, wofstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::fstream, fstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wfstream, wfstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::filebuf, filebuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wfilebuf, wfilebuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::istringstream, istringstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wistringstream, wistringstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::ostringstream, ostringstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wostringstream, wostringstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::stringstream, stringstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wstringstream, wstringstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::stringbuf, stringbuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, std::wstringbuf, wstringbuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_istream, array_istream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_wistream, array_wistream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_ostream, array_ostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_wostream, array_wostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_stream, array_stream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_wstream, array_wstream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_streambuf, array_streambuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, array_wstreambuf, array_wstreambuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_istream, filtering_istream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_wistream, filtering_wistream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_ostream, filtering_ostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_wostream, filtering_wostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, filtering_iostream, filtering_iostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, filtering_wiostream, filtering_wiostream_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_istreambuf, filtering_istreambuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::filtering_wistreambuf, filtering_wistreambuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, linkedbuf, linkedbuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, wlinkedbuf, wlinkedbuf_); \
+ BOOST_CHECK_BOOL_TRAIT(trait, io::array, false); \
+ BOOST_CHECK_BOOL_TRAIT(trait, int, false);
+ /**/
+
+void bool_trait_test()
+{
+ // Test is_istream
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_istream,
+ true, true, false, false, true, true, false, false,
+ true, true, false, false, true, true, false, false,
+ true, true, false, false, true, true, false, false,
+ true, true, false, false, true, true, false, false,
+ true, true, false, false, true, true, false, false,
+ false, false
+ );
+
+ // Test is_ostream
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_ostream,
+ false, false, true, true, true, true, false, false,
+ false, false, true, true, true, true, false, false,
+ false, false, true, true, true, true, false, false,
+ false, false, true, true, true, true, false, false,
+ false, false, true, true, true, true, false, false,
+ false, false
+ );
+
+ // Test is_iostream
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_iostream,
+ false, false, false, false, true, true, false, false,
+ false, false, false, false, true, true, false, false,
+ false, false, false, false, true, true, false, false,
+ false, false, false, false, true, true, false, false,
+ false, false, false, false, true, true, false, false,
+ false, false
+ );
+
+ // Test is_streambuf
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_streambuf,
+ false, false, false, false, false, false, true, true,
+ false, false, false, false, false, false, true, true,
+ false, false, false, false, false, false, true, true,
+ false, false, false, false, false, false, true, true,
+ false, false, false, false, false, false, true, true,
+ true, true
+ );
+
+ // Test is_std_io
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_std_io,
+ true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true,
+ true, true
+ );
+
+ // Test is_std_file_device
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_std_file_device,
+ false, false, false, false, false, false, false, false,
+ true, true, true, true, true, true, true, true,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false
+ );
+
+ // Test is_std_string_device
+ BOOST_CHECK_STREAM_TRAIT(
+ io::is_std_string_device,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ true, true, true, true, true, true, true, true,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false
+ );
+
+ // Test is_boost_stream
+ BOOST_CHECK_STREAM_TRAIT(
+ io::detail::is_boost_stream,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ true, true, true, true, true, true, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false
+ );
+
+ // Test is_boost_stream_buffer
+ BOOST_CHECK_STREAM_TRAIT(
+ io::detail::is_boost_stream_buffer,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, true, true,
+ false, false, false, false, false, false, false, false,
+ false, false
+ );
+
+ // Test is_filtering_stream
+ BOOST_CHECK_STREAM_TRAIT(
+ io::detail::is_filtering_stream,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ true, true, true, true, true, true, false, false,
+ false, false
+ );
+
+ // Test is_filtering_streambuf
+ BOOST_CHECK_STREAM_TRAIT(
+ io::detail::is_filtering_streambuf,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, true, true,
+ false, false
+ );
+
+ // Test is_boost
+ BOOST_CHECK_STREAM_TRAIT(
+ io::detail::is_boost,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+ true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true,
+ false, false
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("bool trait test");
+ test->add(BOOST_TEST_CASE(&bool_trait_test));
+ return test;
+}
diff --git a/libs/iostreams/test/buffer_size_test.cpp b/libs/iostreams/test/buffer_size_test.cpp
new file mode 100644
index 0000000000..83be295e1d
--- /dev/null
+++ b/libs/iostreams/test/buffer_size_test.cpp
@@ -0,0 +1,82 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include "detail/filters.hpp" // Must come before operations.hpp for VC6.
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/constants.hpp>
+#include <boost/iostreams/device/null.hpp>
+#include <boost/iostreams/operations.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+struct optimally_buffered_filter {
+ typedef char char_type;
+ struct category
+ : input_filter_tag,
+ optimally_buffered_tag
+ { };
+ std::streamsize optimal_buffer_size() const
+ { return default_filter_buffer_size + 1; }
+};
+
+void buffer_size_test()
+{
+ // Test device buffer sizes.
+
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(null_source()) == default_device_buffer_size,
+ "wrong buffer size for sourcer"
+ );
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(null_sink()) == default_device_buffer_size,
+ "wrong buffer size for sink"
+ );
+
+ // Test filter buffer sizes.
+
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(toupper_filter()) == default_filter_buffer_size,
+ "wrong buffer size for input filter"
+ );
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(tolower_filter()) == default_filter_buffer_size,
+ "wrong buffer size for output filter"
+ );
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(toupper_multichar_filter())
+ ==
+ default_filter_buffer_size,
+ "wrong buffer size for multi-character input filter"
+ );
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(tolower_multichar_filter())
+ ==
+ default_filter_buffer_size,
+ "wrong buffer size for multi-character output filter"
+ );
+
+ // Test custom buffer size.
+
+ BOOST_CHECK_MESSAGE(
+ optimal_buffer_size(optimally_buffered_filter())
+ ==
+ optimally_buffered_filter().optimal_buffer_size(),
+ "wrong buffer size for multi-character output filter"
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("buffer_size test");
+ test->add(BOOST_TEST_CASE(&buffer_size_test));
+ return test;
+}
diff --git a/libs/iostreams/test/bzip2_test.cpp b/libs/iostreams/test/bzip2_test.cpp
new file mode 100644
index 0000000000..88daa01f86
--- /dev/null
+++ b/libs/iostreams/test/bzip2_test.cpp
@@ -0,0 +1,96 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <string>
+#include <boost/iostreams/filter/bzip2.hpp>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/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;
+
+struct bzip2_alloc : std::allocator<char> { };
+
+void bzip2_test()
+{
+ text_sequence data;
+ BOOST_CHECK(
+ test_filter_pair( bzip2_compressor(),
+ bzip2_decompressor(),
+ std::string(data.begin(), data.end()) )
+ );
+ BOOST_CHECK(
+ test_filter_pair( basic_bzip2_compressor<bzip2_alloc>(),
+ basic_bzip2_decompressor<bzip2_alloc>(),
+ std::string(data.begin(), data.end()) )
+ );
+ BOOST_CHECK(
+ test_filter_pair( bzip2_compressor(),
+ bzip2_decompressor(),
+ std::string() )
+ );
+ {
+ filtering_istream strm;
+ strm.push( bzip2_compressor() );
+ strm.push( null_source() );
+ }
+ {
+ filtering_istream strm;
+ strm.push( bzip2_decompressor() );
+ strm.push( null_source() );
+ }
+}
+
+void multiple_member_test()
+{
+ text_sequence data;
+ std::vector<char> temp, dest;
+
+ // Write compressed data to temp, twice in succession
+ filtering_ostream out;
+ out.push(bzip2_compressor());
+ out.push(io::back_inserter(temp));
+ io::copy(make_iterator_range(data), out);
+ out.push(io::back_inserter(temp));
+ io::copy(make_iterator_range(data), out);
+
+ // Read compressed data from temp into dest
+ filtering_istream in;
+ in.push(bzip2_decompressor());
+ in.push(array_source(&temp[0], temp.size()));
+ io::copy(in, io::back_inserter(dest));
+
+ // Check that dest consists of two copies of data
+ BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size());
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin()));
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
+
+ dest.clear();
+ io::copy(
+ array_source(&temp[0], temp.size()),
+ io::compose(bzip2_decompressor(), io::back_inserter(dest)));
+
+ // Check that dest consists of two copies of data
+ BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size());
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin()));
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("bzip2 test");
+ test->add(BOOST_TEST_CASE(&bzip2_test));
+ test->add(BOOST_TEST_CASE(&multiple_member_test));
+ return test;
+}
diff --git a/libs/iostreams/test/close_test.cpp b/libs/iostreams/test/close_test.cpp
new file mode 100644
index 0000000000..4c24057eb7
--- /dev/null
+++ b/libs/iostreams/test/close_test.cpp
@@ -0,0 +1,651 @@
+/*
+ * 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;
+}
diff --git a/libs/iostreams/test/code_converter_test.cpp b/libs/iostreams/test/code_converter_test.cpp
new file mode 100644
index 0000000000..35554a109c
--- /dev/null
+++ b/libs/iostreams/test/code_converter_test.cpp
@@ -0,0 +1,387 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+# error wide streams not supported on this platform
+#endif
+
+#include <algorithm> // equal.
+#include <locale>
+#include <string>
+#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
+#include <boost/iostreams/code_converter.hpp>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/detail/add_facet.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/detail/config/windows_posix.hpp>
+#include <boost/iostreams/device/file.hpp>
+#if !defined(__COMO__) || !defined(BOOST_COMO_STRICT)
+# if defined(BOOST_IOSTREAMS_NO_LIB) || defined(BOOST_ALL_NO_LIB)
+# include "../src/file_descriptor.cpp"
+# else
+# include <boost/iostreams/device/file_descriptor.hpp>
+# endif
+#endif
+#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"
+#include "detail/temp_file.hpp"
+
+ // Include codevct facets
+
+#include "detail/null_padded_codecvt.hpp"
+#include "detail/utf8_codecvt_facet.hpp"
+#ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX
+# include <codecvt/8859_1>
+# include <codecvt/8859_10>
+# include <codecvt/8859_13>
+# include <codecvt/8859_14>
+# include <codecvt/8859_15>
+# include <codecvt/8859_16>
+# include <codecvt/8859_2>
+# include <codecvt/8859_3>
+# include <codecvt/8859_4>
+# include <codecvt/8859_5>
+# include <codecvt/8859_6>
+# include <codecvt/8859_7>
+# include <codecvt/8859_8>
+# include <codecvt/8859_9>
+# include <codecvt/baltic>
+# include <codecvt/big5>
+# include <codecvt/cp037>
+# include <codecvt/cp1006>
+# include <codecvt/cp1026>
+# include <codecvt/cp1250>
+# include <codecvt/cp1251>
+# include <codecvt/cp1252>
+# include <codecvt/cp1253>
+# include <codecvt/cp1254>
+# include <codecvt/cp1255>
+# include <codecvt/cp1256>
+# include <codecvt/cp1257>
+# include <codecvt/cp1258>
+# include <codecvt/cp424>
+# include <codecvt/cp437>
+# include <codecvt/cp500>
+# include <codecvt/cp737>
+# include <codecvt/cp775>
+# include <codecvt/cp850>
+# include <codecvt/cp852>
+# include <codecvt/cp855>
+# include <codecvt/cp856>
+# include <codecvt/cp857>
+# include <codecvt/cp860>
+# include <codecvt/cp861>
+# include <codecvt/cp862>
+# include <codecvt/cp863>
+# include <codecvt/cp864>
+# include <codecvt/cp865>
+# include <codecvt/cp866>
+# include <codecvt/cp869>
+# include <codecvt/cp874>
+# include <codecvt/cp875>
+# include <codecvt/cp932>
+# include <codecvt/cp936>
+# include <codecvt/cp949>
+# include <codecvt/cp950>
+# include <codecvt/cyrillic>
+# include <codecvt/ebcdic>
+# include <codecvt/euc>
+# include <codecvt/euc_0208>
+# include <codecvt/gb12345>
+# include <codecvt/gb2312>
+# include <codecvt/greek>
+# include <codecvt/iceland>
+# include <codecvt/jis>
+# include <codecvt/jis_0208>
+# include <codecvt/jis0201>
+# include <codecvt/ksc5601>
+# include <codecvt/latin2>
+# include <codecvt/one_one>
+# include <codecvt/roman>
+# include <codecvt/sjis>
+# include <codecvt/sjis_0208>
+# include <codecvt/turkish>
+# include <codecvt/utf16>
+# include <codecvt/utf8>
+# include <codecvt/utf8_utf16>
+# include <codecvt/xjis>
+#endif // #ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX]
+
+#include <iostream>
+
+using namespace std;
+using namespace boost::iostreams;
+using namespace boost::iostreams::detail;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
+
+const int max_length = 30;
+const unsigned int pattern_length = 100;
+const unsigned int pattern_reps = 100;
+
+template<typename Codecvt>
+bool valid_char(typename codecvt_intern<Codecvt>::type c)
+{
+ typedef typename codecvt_state<Codecvt>::type state_type;
+ typedef typename codecvt_intern<Codecvt>::type intern_type;
+ Codecvt cvt;
+ state_type state = state_type();
+ const intern_type* nint;
+ char* next;
+ char buf[max_length];
+
+ return cvt.out( state, &c, &c + 1, nint,
+ buf, buf + max_length, next )
+ ==
+ codecvt_base::ok;
+}
+
+template<typename Codecvt>
+basic_string<
+ BOOST_DEDUCED_TYPENAME
+ codecvt_intern<Codecvt>::type
+>
+test_string()
+{
+ typedef typename codecvt_intern<Codecvt>::type intern_type;
+ std::basic_string<intern_type> pattern, result;
+ for (intern_type c = 255; pattern.size() < pattern_length; --c)
+ if (valid_char<Codecvt>(c))
+ pattern += c;
+ result.reserve(pattern.size() * pattern_reps);
+ for (unsigned int w = 0; w < pattern_reps; ++w)
+ result += pattern;
+ return result;
+}
+
+// Como can't compile file_descriptor.cpp in strict mode; this failure
+// is detected by file_descriptor_test.cpp.
+#if !defined(__COMO__) || !defined(BOOST_COMO_STRICT)
+ typedef io::file_descriptor_source classic_file_source;
+ typedef io::file_descriptor_sink classic_file_sink;
+#else
+ struct classic_file_source : io::source {
+ classic_file_source(const std::string& path)
+ : file_(new filebuf)
+ {
+ file_->pubimbue(locale::classic());
+ file_->open(path.c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ }
+ streamsize read(char* s, streamsize n) { return file_->sgetn(s, n); }
+ boost::shared_ptr<filebuf> file_;
+ };
+
+ struct classic_file_sink : io::sink {
+ classic_file_sink(const std::string& path)
+ : file_(new filebuf)
+ {
+ file_->pubimbue(locale::classic());
+ file_->open(path.c_str(), BOOST_IOS::out | BOOST_IOS::binary);
+ }
+ streamsize write(const char* s, streamsize n) { return file_->sputn(s, n); }
+ boost::shared_ptr<filebuf> file_;
+ };
+#endif
+
+template<typename Codecvt>
+bool codecvt_test1()
+{
+ typedef basic_string<
+ BOOST_DEDUCED_TYPENAME
+ codecvt_intern<Codecvt>::type
+ > string_type;
+ typedef code_converter<classic_file_source, Codecvt> wide_file_source;
+ typedef code_converter<classic_file_sink, Codecvt> wide_file_sink;
+
+ BOOST_CHECK(Codecvt().max_length() <= max_length);
+ temp_file temp;
+ string_type test = test_string<Codecvt>();
+ stream<wide_file_sink> out(temp.name());
+ out.write(test.data(), static_cast<streamsize>(test.size()));
+ out.close();
+
+ stream<wide_file_source> in(temp.name());
+ string_type test2;
+ io::copy(in, io::back_inserter(test2));
+
+ return test == test2;
+}
+
+template<typename Codecvt>
+bool codecvt_test2()
+{
+ typedef basic_string<
+ BOOST_DEDUCED_TYPENAME
+ codecvt_intern<Codecvt>::type
+ > string_type;
+ typedef code_converter<classic_file_source> wide_file_source;
+ typedef code_converter<classic_file_sink> wide_file_sink;
+
+ // Set global locale.
+ locale loc = add_facet(locale(), new Codecvt);
+ locale::global(loc);
+
+ temp_file temp;
+ string_type test = test_string<Codecvt>();
+ stream<wide_file_sink> out(temp.name());
+ out.write(test.data(), static_cast<streamsize>(test.size()));
+ out.close();
+
+ stream<wide_file_source> in(temp.name());
+ string_type test2;
+ io::copy(in, io::back_inserter(test2));
+
+ return test == test2;
+}
+
+template<typename Codecvt>
+bool codecvt_test()
+{
+ return codecvt_test1<Codecvt>() && codecvt_test2<Codecvt>();
+}
+
+void code_converter_test()
+{
+ BOOST_CHECK((codecvt_test<utf8_codecvt_facet<wchar_t, char> >()));
+ BOOST_CHECK(codecvt_test<null_padded_codecvt>());
+ BOOST_CHECK(codecvt_test<stateless_null_padded_codecvt>());
+#ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX
+ using namespace Dinkum::conversions;
+ BOOST_CHECK(codecvt_test< codecvt_8859_1<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_10<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_13<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_14<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_15<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_16<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_2<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_3<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_4<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_5<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_6<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_7<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_8<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_8859_9<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_baltic<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_big5<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp037<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1006<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1026<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1250<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1251<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1252<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1253<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1254<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1255<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1256<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1257<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp1258<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp424<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp437<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp500<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp737<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp775<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp850<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp852<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp855<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp856<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp857<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp860<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp861<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp862<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp863<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp864<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp865<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp866<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp869<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp874<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp875<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp932<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp936<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp949<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cp950<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_cyrillic<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_ebcdic<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_euc<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_euc_0208<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_gb12345<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_gb2312<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_greek<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_iceland<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_jis<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_jis_0208<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_jis0201<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_ksc5601<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_latin2<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_one_one<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_roman<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_sjis<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_sjis_0208<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_turkish<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_utf16<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_utf8<wchar_t> >());
+ BOOST_CHECK(codecvt_test< codecvt_utf8_utf16<wchar_t> >());
+#endif
+}
+
+/* Defer pending further testing
+void close_test()
+{
+ typedef utf8_codecvt_facet<wchar_t, char> codecvt_type;
+
+ // Test code converter based on a source
+ {
+ operation_sequence seq;
+ io::wchain<input> ch;
+ ch.push(
+ code_converter<closable_device<input>, codecvt_type>(
+ seq.new_operation(1)
+ )
+ );
+ BOOST_CHECK_NO_THROW(ch.reset());
+ BOOST_CHECK_OPERATION_SEQUENCE(seq);
+ }
+
+ // Test code converter based on a sink
+ {
+ operation_sequence seq;
+ io::wchain<output> ch;
+ ch.push(
+ code_converter<closable_device<output>, codecvt_type>(
+ seq.new_operation(1)
+ )
+ );
+ BOOST_CHECK_NO_THROW(ch.reset());
+ BOOST_CHECK_OPERATION_SEQUENCE(seq);
+ }
+
+ // Test code converter based on a bidirectional device
+ {
+ operation_sequence seq;
+ io::wchain<bidirectional> ch;
+ ch.push(
+ code_converter<closable_device<bidirectional>, codecvt_type>(
+ seq.new_operation(1),
+ 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("code_converter test");
+ test->add(BOOST_TEST_CASE(&code_converter_test));
+ //test->add(BOOST_TEST_CASE(&close_test));
+ return test;
+}
diff --git a/libs/iostreams/test/combine_test.cpp b/libs/iostreams/test/combine_test.cpp
new file mode 100644
index 0000000000..e22f4d59ab
--- /dev/null
+++ b/libs/iostreams/test/combine_test.cpp
@@ -0,0 +1,227 @@
+/*
+ * 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-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#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 a dual-use filter and an input filter
+ {
+ operation_sequence seq;
+ chain<bidirectional> ch;
+ operation dummy;
+ ch.push(
+ io::combine(
+ closable_filter<input>(seq.new_operation(2)),
+ closable_filter<dual_use>(
+ dummy,
+ 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 a dual-use filter and an output filter
+ {
+ operation_sequence seq;
+ chain<bidirectional> ch;
+ operation dummy;
+ ch.push(
+ io::combine(
+ closable_filter<dual_use>(
+ seq.new_operation(2),
+ dummy
+ ),
+ 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 dual-use filters
+ {
+ operation_sequence seq;
+ chain<bidirectional> ch;
+ operation dummy;
+ ch.push(
+ io::combine(
+ closable_filter<dual_use>(
+ seq.new_operation(2),
+ dummy
+ ),
+ closable_filter<dual_use>(
+ dummy,
+ 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);
+ }
+}
+
+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;
+}
diff --git a/libs/iostreams/test/component_access_test.cpp b/libs/iostreams/test/component_access_test.cpp
new file mode 100644
index 0000000000..7298e56e2e
--- /dev/null
+++ b/libs/iostreams/test/component_access_test.cpp
@@ -0,0 +1,173 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <stdexcept> // out_of_range.
+#include <typeinfo>
+#include <utility> // pair.
+#include <boost/config.hpp> // BOOST_MSVC.
+#include <boost/detail/workaround.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/stream_buffer.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/constants.hpp"
+#include "detail/filters.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+namespace io = boost::iostreams;
+using boost::unit_test::test_suite;
+
+#define COMPARE_TYPE_ID(x, y) BOOST_IOSTREAMS_COMPARE_TYPE_ID(x, y)
+
+struct indirect_source : io::source {
+ void foo() { }
+ std::streamsize read(char*, std::streamsize) { return 0; }
+};
+
+struct direct_source {
+ typedef char char_type;
+ struct category
+ : io::input, io::device_tag, io::direct_tag
+ { };
+ void foo() { }
+ std::pair<char*, char*> input_sequence()
+ {
+ return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0));;
+ }
+};
+
+void compile_time_test()
+{
+ using namespace io;
+
+ stream_buffer<indirect_source> indirect_buf;
+ indirect_buf.open(indirect_source());
+ indirect_buf->foo();
+
+ stream_buffer<direct_source> direct_buf;
+ direct_buf.open(direct_source());
+ direct_buf->foo();
+
+ stream<indirect_source> indirect_stream;
+ indirect_stream.open(indirect_source());
+ indirect_stream->foo();
+
+ stream<direct_source> direct_stream;
+ direct_stream.open(direct_source());
+ direct_stream->foo();
+}
+
+void component_type_test()
+{
+ using namespace std;
+ using namespace io;
+ using namespace boost::iostreams::test;
+
+ temp_file dest;
+ lowercase_file lower;
+
+ filtering_ostream out;
+ out.push(tolower_filter());
+ out.push(tolower_multichar_filter());
+ out.push(file_sink(dest.name(), out_mode));
+
+ // Check index 0.
+ BOOST_CHECK(COMPARE_TYPE_ID(
+ out.component_type(0),
+ typeid(tolower_filter)
+ ));
+ BOOST_CHECK(COMPARE_TYPE_ID(
+ BOOST_IOSTREAMS_COMPONENT_TYPE(out, 0),
+ typeid(tolower_filter)
+ ));
+ BOOST_CHECK_NO_THROW((
+ BOOST_IOSTREAMS_COMPONENT(out, 0, tolower_filter)
+ ));
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
+ BOOST_CHECK_NO_THROW((
+ out.component<tolower_filter>(0)
+ ));
+ BOOST_CHECK_NO_THROW((
+ out.component<0, tolower_filter>()
+ ));
+#endif
+
+ // Check index 1.
+ BOOST_CHECK(COMPARE_TYPE_ID(
+ out.component_type(1),
+ typeid(tolower_multichar_filter)
+ ));
+ BOOST_CHECK(COMPARE_TYPE_ID(
+ BOOST_IOSTREAMS_COMPONENT_TYPE(out, 1),
+ typeid(tolower_multichar_filter)
+ ));
+ BOOST_CHECK_NO_THROW((
+ BOOST_IOSTREAMS_COMPONENT(out, 1, tolower_multichar_filter)
+ ));
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
+ BOOST_CHECK_NO_THROW((
+ out.component<tolower_multichar_filter>(1)
+ ));
+ BOOST_CHECK_NO_THROW((
+ out.component<1, tolower_multichar_filter>()
+ ));
+#endif
+
+ // Check index 2.
+ BOOST_CHECK(COMPARE_TYPE_ID(
+ out.component_type(2),
+ typeid(file_sink)
+ ));
+ BOOST_CHECK(COMPARE_TYPE_ID(
+ BOOST_IOSTREAMS_COMPONENT_TYPE(out, 2),
+ typeid(file_sink)
+ ));
+ BOOST_CHECK_NO_THROW((
+ BOOST_IOSTREAMS_COMPONENT(out, 2, file_sink)
+ ));
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310)
+ BOOST_CHECK_NO_THROW((
+ out.component<file_sink>(2)
+ ));
+ BOOST_CHECK_NO_THROW((
+ out.component<2, file_sink>()
+ ));
+#endif
+
+ // Check index 3.
+ BOOST_CHECK_THROW(
+ out.component_type(3),
+ std::out_of_range
+ );
+ BOOST_CHECK_THROW(
+ BOOST_IOSTREAMS_COMPONENT_TYPE(out, 3),
+ std::out_of_range
+ );
+
+ // Check components.
+
+ filtering_ostream out2;
+ out2.push(*(BOOST_IOSTREAMS_COMPONENT(out, 0, tolower_filter)));
+ out2.push(*(BOOST_IOSTREAMS_COMPONENT(out, 1, tolower_multichar_filter)));
+ out2.push(*(BOOST_IOSTREAMS_COMPONENT(out, 2, file_sink)));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed accessing components of chain"
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("component_type test");
+ test->add(BOOST_TEST_CASE(&component_type_test));
+ return test;
+}
diff --git a/libs/iostreams/test/compose_test.cpp b/libs/iostreams/test/compose_test.cpp
new file mode 100644
index 0000000000..9d26d48a78
--- /dev/null
+++ b/libs/iostreams/test/compose_test.cpp
@@ -0,0 +1,504 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <cctype>
+#include <boost/iostreams/compose.hpp>
+#include <boost/iostreams/device/file.hpp>
+#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"
+
+// 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()
+{
+ test_file src1, src2;
+ filtering_istream first, second;
+
+ // Test composite device
+ first.push(toupper_filter());
+ first.push(padding_filter('a'));
+ first.push(file_source(src1.name(), in_mode));
+ second.push( compose( toupper_filter(),
+ compose( padding_filter('a'),
+ file_source(src1.name(), in_mode) ) ) );
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a stdio_filter"
+ );
+
+ // Test composite filter
+ first.reset();
+ second.reset();
+ first.push(toupper_filter());
+ first.push(padding_filter('a'));
+ first.push(file_source(src1.name(), in_mode));
+ second.push( compose( compose( toupper_filter(),
+ padding_filter('a') ),
+ file_source(src1.name(), in_mode) ) );
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a stdio_filter"
+ );
+}
+
+void write_composite()
+{
+ temp_file dest1, dest2;
+ filtering_ostream out1, out2;
+
+ // Test composite device
+ out1.push(tolower_filter());
+ out1.push(padding_filter('a'));
+ out1.push(file_sink(dest1.name(), in_mode));
+ out2.push( compose( tolower_filter(),
+ compose( padding_filter('a'),
+ file_sink(dest2.name(), in_mode) ) ) );
+ write_data_in_chunks(out1);
+ write_data_in_chunks(out2);
+ out1.reset();
+ out2.reset();
+
+ {
+ ifstream first(dest1.name().c_str());
+ ifstream second(dest2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to a stdio_filter"
+ );
+ }
+
+ // Test composite filter
+ out1.push(tolower_filter());
+ out1.push(padding_filter('a'));
+ out1.push(file_sink(dest1.name(), in_mode));
+ out2.push( compose( compose( tolower_filter(),
+ padding_filter('a') ),
+ file_sink(dest2.name(), in_mode) ) );
+ write_data_in_chunks(out1);
+ write_data_in_chunks(out2);
+ out1.reset();
+ out2.reset();
+
+ {
+ ifstream first(dest1.name().c_str());
+ ifstream second(dest2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to a stdio_filter"
+ );
+ }
+}
+
+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;
+ operation dummy;
+ ch.push(
+ io::compose(
+ closable_filter<dual_use>(
+ seq.new_operation(2),
+ dummy
+ ),
+ 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;
+ operation dummy;
+ ch.push(
+ io::compose(
+ closable_filter<dual_use>(
+ dummy,
+ 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 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;
+ operation dummy;
+ ch.push(
+ io::compose(
+ closable_filter<dual_use>(
+ seq.new_operation(3),
+ dummy
+ ),
+ 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;
+ operation dummy;
+ ch.push(
+ io::compose(
+ closable_filter<dual_use>(
+ dummy,
+ 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 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;
+ operation dummy;
+ ch.push(
+ io::compose(
+ closable_filter<dual_use>(
+ seq.new_operation(3),
+ dummy
+ ),
+ closable_filter<dual_use>(
+ seq.new_operation(2),
+ dummy
+ )
+ )
+ );
+ 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;
+ operation dummy;
+ ch.push(
+ io::compose(
+ closable_filter<dual_use>(
+ dummy,
+ seq.new_operation(1)
+ ),
+ closable_filter<dual_use>(
+ dummy,
+ 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("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;
+}
+
+#include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x.
diff --git a/libs/iostreams/test/copy_test.cpp b/libs/iostreams/test/copy_test.cpp
new file mode 100644
index 0000000000..84dda9f5db
--- /dev/null
+++ b/libs/iostreams/test/copy_test.cpp
@@ -0,0 +1,172 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <algorithm> // Equal
+#include <vector>
+#include <boost/config.hpp> // MSVC.
+#include <boost/detail/workaround.hpp>
+#include <boost/iostreams/concepts.hpp> // sink
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "../example/container_device.hpp"
+#include "detail/sequence.hpp"
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::example;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+//------------------Definition of fixed_sink----------------------------------//
+
+/*class fixed_sink : public sink {
+public:
+ fixed_sink(vector<char>& storage)
+ : storage_(storage), pos_(0)
+ { }
+ std::streamsize write(const char_type* s, std::streamsize n)
+ {
+ streamsize capacity = static_cast<streamsize>(storage_.size() - pos_);
+ streamsize result = (min)(n, capacity);
+ std::copy(s, s + result, storage_.begin() + pos_);
+ pos_ += result;
+ return result;
+ }
+private:
+ fixed_sink operator=(const fixed_sink&);
+ typedef vector<char>::size_type size_type;
+ vector<char>& storage_;
+ size_type pos_;
+};*/
+
+//------------------Definition of stream types--------------------------------//
+
+typedef container_source< vector<char> > vector_source;
+typedef container_sink< vector<char> > vector_sink;
+typedef stream<vector_source> vector_istream;
+typedef stream<vector_sink> vector_ostream;
+//typedef stream<fixed_sink> fixed_ostream;
+
+//------------------Definition of copy_test-----------------------------------//
+
+void copy_test()
+{
+ // Stream to stream
+ {
+ test_sequence<> src;
+ vector<char> dest;
+ vector_istream first;
+ vector_ostream second;
+ first.open(vector_source(src));
+ second.open(vector_sink(dest));
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(first, second) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from stream to stream"
+ );
+ }
+
+ // Stream to indirect sink
+ {
+ test_sequence<> src;
+ vector<char> dest;
+ vector_istream in;
+ vector_sink out(dest);
+ in.open(vector_source(src));
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(in, out) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from stream to indirect sink"
+ );
+ }
+
+ // Indirect source to stream
+ {
+ test_sequence<> src;
+ vector<char> dest;
+ vector_source in(src);
+ vector_ostream out;
+ out.open(vector_sink(dest));
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(in, out) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from indirect source to stream"
+ );
+ }
+
+ // Indirect source to indirect sink
+ {
+ test_sequence<> src;
+ vector<char> dest;
+ vector_source in(src);
+ vector_sink out(dest);
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(in, out) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from indirect source to indirect sink"
+ );
+ }
+
+ // Direct source to direct sink
+ {
+ test_sequence<> src;
+ vector<char> dest(src.size(), '?');
+ array_source in(&src[0], &src[0] + src.size());
+ array_sink out(&dest[0], &dest[0] + dest.size());
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(in, out) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from direct source to direct sink"
+ );
+ }
+
+ // Direct source to indirect sink
+ {
+ test_sequence<> src;
+ vector<char> dest;
+ array_source in(&src[0], &src[0] + src.size());
+ vector_ostream out(dest);
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(in, out) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from direct source to indirect sink"
+ );
+ }
+
+ // Indirect source to direct sink
+ {
+ test_sequence<> src;
+ vector<char> dest(src.size(), '?');
+ vector_istream in;
+ array_sink out(&dest[0], &dest[0] + dest.size());
+ in.open(vector_source(src));
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::copy(in, out) ==
+ static_cast<streamsize>(src.size()) &&
+ src == dest,
+ "failed copying from indirect source to direct sink"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("copy test");
+ test->add(BOOST_TEST_CASE(&copy_test));
+ return test;
+}
diff --git a/libs/iostreams/test/counter_test.cpp b/libs/iostreams/test/counter_test.cpp
new file mode 100644
index 0000000000..091dfe9f68
--- /dev/null
+++ b/libs/iostreams/test/counter_test.cpp
@@ -0,0 +1,98 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <cctype>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/device/null.hpp>
+#include <boost/iostreams/filter/counter.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/constants.hpp"
+#include "detail/filters.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;
+
+void read_counter()
+{
+ test_file src;
+ filtering_istream in;
+ in.push(counter());
+ in.push(padding_filter('a'), 0);
+ in.push(counter());
+ in.push(file_source(src.name(), in_mode));
+
+ counter* first_counter = BOOST_IOSTREAMS_COMPONENT(in, 0, counter);
+ counter* second_counter = BOOST_IOSTREAMS_COMPONENT(in, 2, counter);
+ int first_count = 0;
+ int second_count = 0;
+ int line_count = 0;
+ int reps = data_reps < 50 ? data_reps : 25; // Keep test short.
+ for (int w = 0; w < reps; ++w) {
+ int len = data_length();
+ for (int z = 0; z < len; ++z) {
+ in.get();
+ ++first_count;
+ ++second_count;
+ BOOST_CHECK(first_counter->characters() == first_count);
+ BOOST_CHECK(second_counter->characters() == second_count);
+ in.get();
+ ++first_count;
+ BOOST_CHECK(first_counter->characters() == first_count);
+ BOOST_CHECK(second_counter->characters() == second_count);
+ }
+ ++line_count;
+ BOOST_CHECK(first_counter->lines() == line_count);
+ BOOST_CHECK(first_counter->lines() == line_count);
+ }
+}
+
+void write_counter()
+{
+ filtering_ostream out;
+ out.push(counter());
+ out.push(padding_filter('a'), 0);
+ out.push(counter());
+ out.push(null_sink());
+
+ counter* first_counter = BOOST_IOSTREAMS_COMPONENT(out, 0, counter);
+ counter* second_counter = BOOST_IOSTREAMS_COMPONENT(out, 2, counter);
+ int first_count = 0;
+ int second_count = 0;
+ int line_count = 0;
+ int reps = data_reps < 50 ? data_reps : 25; // Keep test short.
+ const char* data = narrow_data();
+ for (int w = 0; w < reps; ++w) {
+ int len = data_length();
+ for (int z = 0; z < len; ++z) {
+ out.put(data[z]);
+ out.flush();
+ ++first_count;
+ second_count += 2;
+ BOOST_CHECK(first_counter->characters() == first_count);
+ BOOST_CHECK(second_counter->characters() == second_count);
+ }
+ ++line_count;
+ BOOST_CHECK(first_counter->lines() == line_count);
+ BOOST_CHECK(first_counter->lines() == line_count);
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("counter test");
+ test->add(BOOST_TEST_CASE(&read_counter));
+ test->add(BOOST_TEST_CASE(&write_counter));
+ return test;
+}
diff --git a/libs/iostreams/test/deprecated_file_descriptor_test.cpp b/libs/iostreams/test/deprecated_file_descriptor_test.cpp
new file mode 100644
index 0000000000..cb23f7d0e5
--- /dev/null
+++ b/libs/iostreams/test/deprecated_file_descriptor_test.cpp
@@ -0,0 +1,243 @@
+// (C) Copyright 2010 Daniel James
+// 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.)
+
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+#include "detail/file_handle.hpp"
+
+// Test file_descriptor with the depreacted constructors.
+
+namespace boost_ios = boost::iostreams;
+namespace ios_test = boost::iostreams::test;
+
+template <class FileDescriptor>
+void file_handle_test_impl(FileDescriptor*)
+{
+ ios_test::test_file test1;
+ ios_test::test_file test2;
+
+ //--------------Deprecated file descriptor constructor--------------------//
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ FileDescriptor device1(handle);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ FileDescriptor device1(handle, false);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ FileDescriptor device1(handle, true);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ FileDescriptor device1(handle);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ FileDescriptor device1(handle, false);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ FileDescriptor device1(handle, true);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ //--------------Deprecated file descriptor open---------------------------//
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ FileDescriptor device1;
+ device1.open(handle);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ FileDescriptor device1;
+ device1.open(handle, false);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ ios_test::close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ {
+ FileDescriptor device1;
+ device1.open(handle, true);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ FileDescriptor device1;
+ device1.open(handle);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ FileDescriptor device1;
+ device1.open(handle, false);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = ios_test::open_file_handle(test1.name());
+ FileDescriptor device1;
+ device1.open(handle, true);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ //--------------Deprecated open with existing descriptor------------------//
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ FileDescriptor device1(handle1);
+ BOOST_CHECK(device1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ device1.open(handle2);
+ BOOST_CHECK(device1.handle() == handle2);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ device1.close();
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+
+ ios_test::close_file_handle(handle1);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ FileDescriptor device1(handle1, true);
+ BOOST_CHECK(device1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ device1.open(handle2);
+ BOOST_CHECK(device1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ device1.close();
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ FileDescriptor device1(handle1, false);
+ BOOST_CHECK(device1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ device1.open(handle2, false);
+ BOOST_CHECK(device1.handle() == handle2);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+
+ ios_test::close_file_handle(handle1);
+ ios_test::close_file_handle(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = ios_test::open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = ios_test::open_file_handle(test1.name());
+
+ {
+ FileDescriptor device1(handle1, true);
+ BOOST_CHECK(device1.handle() == handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ device1.open(handle2, true);
+ BOOST_CHECK(device1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+}
+
+void deprecated_file_descriptor_test()
+{
+ file_handle_test_impl((boost_ios::file_descriptor*) 0);
+ file_handle_test_impl((boost_ios::file_descriptor_sink*) 0);
+ file_handle_test_impl((boost_ios::file_descriptor_source*) 0);
+}
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
+{
+ boost::unit_test::test_suite* test = BOOST_TEST_SUITE("deprecated file_descriptor test");
+ test->add(BOOST_TEST_CASE(&deprecated_file_descriptor_test));
+ return test;
+}
diff --git a/libs/iostreams/test/detail/closable.hpp b/libs/iostreams/test/detail/closable.hpp
new file mode 100644
index 0000000000..182522fa51
--- /dev/null
+++ b/libs/iostreams/test/detail/closable.hpp
@@ -0,0 +1,343 @@
+/*
+ * 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.
+ *
+ * Defines a large collection of closable filters and devices that
+ * execute instances of boost::iostreams::test::operation upon
+ * closre(). Used to verify that filters and devices are closed
+ * correctly by the iostreams library
+ *
+ * File: libs/iostreams/test/detail/closable.hpp
+ * Date: Sun Dec 09 16:12:23 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#ifndef BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED
+
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/char_traits.hpp> // EOF
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/detail/ios.hpp>
+#include "./operation_sequence.hpp"
+
+namespace boost { namespace iostreams { namespace test {
+
+template<typename Category>
+class closable_device { };
+
+// Source
+template<>
+class closable_device<input> : public source {
+public:
+ closable_device(operation close) : close_(close) { }
+ std::streamsize read(char*, std::streamsize) { return -1; }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Sink
+template<>
+class closable_device<output> : public sink {
+public:
+ closable_device(operation close) : close_(close) { }
+ std::streamsize write(const char*, std::streamsize) { return 0; }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+struct borland_output { };
+
+// Copy of closable_device<output>, for Borland <= 5.8.2
+template<>
+class closable_device<borland_output> : public sink {
+public:
+ closable_device(operation close) : close_(close) { }
+ std::streamsize write(const char*, std::streamsize) { return 0; }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Bidirectional device
+template<>
+class closable_device<bidirectional> : public device<bidirectional> {
+public:
+ closable_device(operation close_input, operation close_output)
+ : close_input_(close_input), close_output_(close_output)
+ { }
+ std::streamsize read(char*, std::streamsize) { return -1; }
+ std::streamsize write(const char*, std::streamsize) { return 0; }
+ void close(BOOST_IOS::openmode which)
+ {
+ switch (which) {
+ case BOOST_IOS::in:
+ close_input_.execute();
+ break;
+ case BOOST_IOS::out:
+ close_output_.execute();
+ break;
+ default:
+ break;
+ }
+ }
+private:
+ operation close_input_;
+ operation close_output_;
+};
+
+// Seekable device
+template<>
+class closable_device<seekable> : public device<seekable> {
+public:
+ closable_device(operation close) : close_(close) { }
+ std::streamsize read(char*, std::streamsize) { return -1; }
+ std::streamsize write(const char*, std::streamsize) { return 0; }
+ stream_offset seek(stream_offset, BOOST_IOS::seekdir) { return 0; }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+struct direct_input
+ : input, device_tag, closable_tag, direct_tag
+ { };
+struct direct_output
+ : output, device_tag, closable_tag, direct_tag
+ { };
+struct direct_bidirectional
+ : bidirectional, device_tag, closable_tag, direct_tag
+ { };
+struct direct_seekable
+ : seekable, device_tag, closable_tag, direct_tag
+ { };
+
+// Direct source
+template<>
+class closable_device<direct_input> {
+public:
+ typedef char char_type;
+ typedef direct_input category;
+ closable_device(operation close) : close_(close) { }
+ std::pair<char*, char*> input_sequence()
+ { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Direct sink
+template<>
+class closable_device<direct_output> {
+public:
+ typedef char char_type;
+ typedef direct_output category;
+ closable_device(operation close) : close_(close) { }
+ std::pair<char*, char*> output_sequence()
+ { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Direct bidirectional device
+template<>
+class closable_device<direct_bidirectional> {
+public:
+ typedef char char_type;
+ typedef direct_bidirectional category;
+ closable_device(operation close_input, operation close_output)
+ : close_input_(close_input), close_output_(close_output)
+ { }
+ std::pair<char*, char*> input_sequence()
+ { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
+ std::pair<char*, char*> output_sequence()
+ { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
+ void close(BOOST_IOS::openmode which)
+ {
+ switch (which) {
+ case BOOST_IOS::in:
+ close_input_.execute();
+ break;
+ case BOOST_IOS::out:
+ close_output_.execute();
+ break;
+ default:
+ break;
+ }
+ }
+private:
+ operation close_input_;
+ operation close_output_;
+};
+
+// Direct seekable device
+template<>
+class closable_device<direct_seekable> {
+public:
+ typedef char char_type;
+ typedef direct_seekable category;
+ closable_device(operation close) : close_(close) { }
+ std::pair<char*, char*> input_sequence()
+ { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
+ std::pair<char*, char*> output_sequence()
+ { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+template<typename Mode>
+class closable_filter { };
+
+// Input filter
+template<>
+class closable_filter<input> : public input_filter {
+public:
+ closable_filter(operation close) : close_(close) { }
+
+ template<typename Source>
+ int get(Source&) { return EOF; }
+
+ template<typename Source>
+ void close(Source&) { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Output filter
+template<>
+class closable_filter<output> : public output_filter {
+public:
+ closable_filter(operation close) : close_(close) { }
+
+ template<typename Sink>
+ bool put(Sink&, char) { return true; }
+
+ template<typename Sink>
+ void close(Sink&) { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Bidirectional filter
+template<>
+class closable_filter<bidirectional> : public filter<bidirectional> {
+public:
+ closable_filter(operation close_input, operation close_output)
+ : close_input_(close_input), close_output_(close_output)
+ { }
+
+ template<typename Source>
+ int get(Source&) { return EOF; }
+
+ template<typename Sink>
+ bool put(Sink&, char) { return true; }
+
+ template<typename Device>
+ void close(Device&, BOOST_IOS::openmode which)
+ {
+ switch (which) {
+ case BOOST_IOS::in:
+ close_input_.execute();
+ break;
+ case BOOST_IOS::out:
+ close_output_.execute();
+ break;
+ default:
+ break;
+ }
+ }
+private:
+ operation close_input_;
+ operation close_output_;
+};
+
+// Seekable filter
+template<>
+class closable_filter<seekable> : public filter<seekable> {
+public:
+ closable_filter(operation close) : close_(close) { }
+ std::streamsize read(char*, std::streamsize) { return -1; }
+
+ template<typename Source>
+ int get(Source&) { return EOF; }
+
+ template<typename Sink>
+ bool put(Sink&, char) { return true; }
+
+ template<typename Device>
+ stream_offset seek(Device&, stream_offset, BOOST_IOS::seekdir)
+ {
+ return 0;
+ }
+
+ template<typename Device>
+ void close(Device&) { close_.execute(); }
+private:
+ operation close_;
+};
+
+// Dual-use filter
+template<>
+class closable_filter<dual_use> {
+public:
+ typedef char char_type;
+ struct category
+ : filter_tag,
+ dual_use,
+ closable_tag
+ { };
+ closable_filter(operation close_input, operation close_output)
+ : close_input_(close_input), close_output_(close_output)
+ { }
+
+ template<typename Source>
+ int get(Source&) { return EOF; }
+
+ template<typename Sink>
+ bool put(Sink&, char) { return true; }
+
+ template<typename Device>
+ void close(Device&, BOOST_IOS::openmode which)
+ {
+ switch (which) {
+ case BOOST_IOS::in:
+ close_input_.execute();
+ break;
+ case BOOST_IOS::out:
+ close_output_.execute();
+ break;
+ default:
+ break;
+ }
+ }
+private:
+ operation close_input_;
+ operation close_output_;
+};
+
+// Symmetric filter
+class closable_symmetric_filter {
+public:
+ typedef char char_type;
+ closable_symmetric_filter(operation close) : close_(close) { }
+ bool filter( const char*&, const char*,
+ char*&, char*, bool )
+ {
+ return false;
+ }
+ void close() { close_.execute(); }
+private:
+ operation close_;
+};
+
+} } } // End namespaces test, iostreams, boost.
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/constants.hpp b/libs/iostreams/test/detail/constants.hpp
new file mode 100644
index 0000000000..7705d86e33
--- /dev/null
+++ b/libs/iostreams/test/detail/constants.hpp
@@ -0,0 +1,67 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+// Contains the definitions of several constants used by the test program.
+
+#ifndef BOOST_IOSTREAMS_TEST_CONSTANTS_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_CONSTANTS_HPP_INCLUDED
+
+#include <string.h>
+#include <boost/config.hpp>
+
+namespace boost { namespace iostreams { namespace test {
+
+// Note: openmode could be a class type, so this header must be included
+// by just one TU.
+const BOOST_IOS::openmode in_mode = BOOST_IOS::in | BOOST_IOS::binary;
+const BOOST_IOS::openmode out_mode = BOOST_IOS::out | BOOST_IOS::binary;
+
+// Chunk size for reading or writing in chunks.
+const int chunk_size = 59;
+
+// Chunk size for reading or writing in chunks.
+const int small_buffer_size = 23;
+
+// Number of times data is repeated in test files.
+const int data_reps = 300;
+
+namespace detail {
+
+// Returns string which is used to generate test files.
+inline const char* data(char*)
+{
+ static const char* c =
+ "!\"#$%&'()*+,-./0123456879:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n";
+ return c;
+}
+
+// Returns string which is used to generate test files.
+inline const wchar_t* data(wchar_t*)
+{
+ static const wchar_t* c =
+ L"!\"#$%&'()*+,-./0123456879:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ L"[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n";
+ return c;
+}
+
+} // End namespace detail.
+
+inline const char* narrow_data() { return detail::data((char*)0); }
+
+inline const wchar_t* wide_data() { return detail::data((wchar_t*)0); }
+
+// Length of string returned by data().
+inline int data_length()
+{
+ static int len = (int) strlen(narrow_data());
+ return len;
+}
+
+} } } // End namespaces detail, iostreams, boost.
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_CONSTANTS_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/file_handle.hpp b/libs/iostreams/test/detail/file_handle.hpp
new file mode 100644
index 0000000000..a9bfed52c8
--- /dev/null
+++ b/libs/iostreams/test/detail/file_handle.hpp
@@ -0,0 +1,108 @@
+// (C) Copyright 2010 Daniel James
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2003-2007 Jonathan Turkanis
+// 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.)
+
+// A few methods for getting and manipulating file handles.
+
+#ifndef BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
+
+#include <boost/iostreams/detail/file_handle.hpp>
+#include <boost/iostreams/detail/config/rtl.hpp>
+#include <boost/test/test_tools.hpp>
+#include <string>
+
+#ifdef BOOST_IOSTREAMS_WINDOWS
+# include <io.h> // low-level file i/o.
+# define WINDOWS_LEAN_AND_MEAN
+# include <windows.h>
+#else
+# include <sys/stat.h>
+# include <fcntl.h>
+#endif
+
+namespace boost { namespace iostreams { namespace test {
+
+#ifdef BOOST_IOSTREAMS_WINDOWS
+
+// Windows implementation
+
+boost::iostreams::detail::file_handle open_file_handle(std::string const& name)
+{
+ HANDLE handle =
+ ::CreateFileA( name.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, // lpSecurityAttributes
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL ); // hTemplateFile
+
+ BOOST_REQUIRE (handle != INVALID_HANDLE_VALUE);
+ return handle;
+}
+
+void close_file_handle(boost::iostreams::detail::file_handle handle)
+{
+ BOOST_REQUIRE(::CloseHandle(handle) == 1);
+}
+
+#define BOOST_CHECK_HANDLE_CLOSED(handle)
+#define BOOST_CHECK_HANDLE_OPEN(handle)
+
+#else // BOOST_IOSTREAMS_WINDOWS
+
+// Non-windows implementation
+
+boost::iostreams::detail::file_handle open_file_handle(std::string const& name)
+{
+ int oflag = O_RDWR;
+
+ #ifdef _LARGEFILE64_SOURCE
+ oflag |= O_LARGEFILE;
+ #endif
+
+ // Calculate pmode argument to open.
+
+ mode_t pmode = S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH;
+
+ // Open file.
+
+ int fd = BOOST_IOSTREAMS_FD_OPEN(name.c_str(), oflag, pmode);
+ BOOST_REQUIRE (fd != -1);
+
+ return fd;
+}
+
+void close_file_handle(boost::iostreams::detail::file_handle handle)
+{
+ BOOST_REQUIRE(BOOST_IOSTREAMS_FD_CLOSE(handle) != -1);
+}
+
+// This is pretty dubious. First you must make sure that no other
+// operations that could open a descriptor are called before this
+// check, otherwise it's quite likely that a closed descriptor
+// could be used. Secondly, I'm not sure if it's guaranteed that
+// fcntl will know that the descriptor is closed but this seems
+// to work okay, and I can't see any other convenient way to check
+// that a descripter has been closed.
+bool is_handle_open(boost::iostreams::detail::file_handle handle)
+{
+ return ::fcntl(handle, F_GETFD) != -1;
+}
+
+#define BOOST_CHECK_HANDLE_CLOSED(handle) \
+ BOOST_CHECK(!::boost::iostreams::test::is_handle_open(handle))
+#define BOOST_CHECK_HANDLE_OPEN(handle) \
+ BOOST_CHECK(::boost::iostreams::test::is_handle_open(handle))
+
+
+#endif // BOOST_IOSTREAMS_WINDOWS
+
+}}}
+
+#endif // BOOST_IOSTREAMS_FILE_HANDLE_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/filters.hpp b/libs/iostreams/test/detail/filters.hpp
new file mode 100644
index 0000000000..3d01a4f8e2
--- /dev/null
+++ b/libs/iostreams/test/detail/filters.hpp
@@ -0,0 +1,186 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+// Contains the definitions of several constants used by the test program.
+
+#ifndef BOOST_IOSTREAMS_TEST_FILTERS_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_FILTERS_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <algorithm> // min.
+#include <cctype> // to_upper, to_lower.
+#include <cstdlib> // to_upper, to_lower (VC6).
+#include <cstddef> // ptrdiff_t.
+#include <vector>
+#include <boost/iostreams/char_traits.hpp>
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/constants.hpp>
+#include <boost/iostreams/detail/buffer.hpp>
+#include <boost/iostreams/detail/iostream.hpp> // seekdir, streamsize.
+#include <boost/iostreams/detail/streambuf.hpp>
+#include <boost/iostreams/operations.hpp>
+#include <boost/iostreams/pipeline.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std { using ::toupper; using ::tolower; }
+#endif
+
+// Must come last.
+#include <boost/iostreams/detail/config/disable_warnings.hpp>
+
+namespace boost { namespace iostreams { namespace test {
+
+struct toupper_filter : public input_filter {
+ template<typename Source>
+ int get(Source& s)
+ {
+ int c = boost::iostreams::get(s);
+ return c != EOF && c != WOULD_BLOCK ?
+ std::toupper((unsigned char) c) :
+ c;
+ }
+};
+BOOST_IOSTREAMS_PIPABLE(toupper_filter, 0)
+
+struct tolower_filter : public output_filter {
+ template<typename Sink>
+ bool put(Sink& s, char c)
+ {
+ return boost::iostreams::put(
+ s, (char) std::tolower((unsigned char) c)
+ );
+ }
+};
+BOOST_IOSTREAMS_PIPABLE(tolower_filter, 0)
+
+struct toupper_multichar_filter : public multichar_input_filter {
+ template<typename Source>
+ std::streamsize read(Source& s, char* buf, std::streamsize n)
+ {
+ std::streamsize result = boost::iostreams::read(s, buf, n);
+ if (result == -1)
+ return -1;
+ for (int z = 0; z < result; ++z)
+ buf[z] = (char) std::toupper((unsigned char) buf[z]);
+ return result;
+ }
+};
+BOOST_IOSTREAMS_PIPABLE(toupper_multichar_filter, 0)
+
+struct tolower_multichar_filter : public multichar_output_filter {
+ template<typename Sink>
+ std::streamsize write(Sink& s, const char* buf, std::streamsize n)
+ {
+ std::streamsize result;
+ for (result = 0; result < n; ++result) {
+ char c = (char) std::tolower((unsigned char) buf[result]);
+ if (!boost::iostreams::put(s, c))
+ break;
+ }
+ return result;
+ }
+};
+BOOST_IOSTREAMS_PIPABLE(tolower_multichar_filter, 0)
+
+struct padding_filter : dual_use_filter {
+ explicit padding_filter(char pad_char)
+ : pad_char_(pad_char), use_pad_char_(false), eof_(false)
+ { }
+
+ template<typename Source>
+ int get(Source& src)
+ {
+ int result;
+ if (use_pad_char_) {
+ result = eof_ ? EOF : pad_char_;
+ use_pad_char_ = false;
+ } else {
+ result = boost::iostreams::get(src);
+ if (result != EOF && result != WOULD_BLOCK)
+ use_pad_char_ = true;
+ eof_ = result == EOF;
+ }
+ return result;
+ }
+
+ template<typename Sink>
+ bool put(Sink& s, char c)
+ {
+ if (use_pad_char_) {
+ if (!boost::iostreams::put(s, pad_char_))
+ return false;
+ use_pad_char_ = false;
+ }
+ if (!boost::iostreams::put(s, c))
+ return false;
+ if (!boost::iostreams::put(s, pad_char_))
+ use_pad_char_ = true;
+ return true;
+ }
+
+ char pad_char_;
+ bool use_pad_char_;
+ bool eof_;
+};
+BOOST_IOSTREAMS_PIPABLE(padding_filter, 0)
+
+struct flushable_output_filter {
+ typedef char char_type;
+ struct category
+ : output_filter_tag,
+ flushable_tag
+ { };
+ template<typename Sink>
+ bool put(Sink&, char c)
+ {
+ buf_.push_back(c);
+ return true;
+ }
+ template<typename Sink>
+ bool flush(Sink& s)
+ {
+ if (!buf_.empty()) {
+ boost::iostreams::write(s, &buf_[0], (std::streamsize) buf_.size());
+ buf_.clear();
+ }
+ return true;
+ }
+ std::vector<char> buf_;
+};
+BOOST_IOSTREAMS_PIPABLE(flushable_output_filter, 0)
+
+struct identity_seekable_filter : filter<seekable> {
+ template<typename Source>
+ int get(Source& s) { return boost::iostreams::get(s); }
+
+ template<typename Sink>
+ bool put(Sink& s, char c) { return boost::iostreams::put(s, c); }
+
+ template<typename Device>
+ std::streampos seek(Device& d, stream_offset off, BOOST_IOS::seekdir way)
+ { return boost::iostreams::seek(d, off, way); }
+};
+BOOST_IOSTREAMS_PIPABLE(identity_seekable_filter, 0)
+
+struct identity_seekable_multichar_filter : multichar_filter<seekable> {
+ template<typename Source>
+ std::streamsize read(Source& s, char* buf, std::streamsize n)
+ { return boost::iostreams::read(s, buf, n); }
+ template<typename Sink>
+ std::streamsize write(Sink& s, const char* buf, std::streamsize n)
+ { return boost::iostreams::write(s, buf, n); }
+ template<typename Device>
+ std::streampos seek(Device& d, stream_offset off, BOOST_IOS::seekdir way)
+ { return boost::iostreams::seek(d, off, way); }
+};
+BOOST_IOSTREAMS_PIPABLE(identity_seekable_multichar_filter, 0)
+
+} } } // End namespaces detail, iostreams, boost.
+
+#include <boost/iostreams/detail/config/enable_warnings.hpp>
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_FILTERS_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/null_padded_codecvt.hpp b/libs/iostreams/test/detail/null_padded_codecvt.hpp
new file mode 100644
index 0000000000..6a04e6182b
--- /dev/null
+++ b/libs/iostreams/test/detail/null_padded_codecvt.hpp
@@ -0,0 +1,275 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+// Contains the definitions of two codecvt facets useful for testing code
+// conversion. Both represent the "null padded" character encoding described as
+// follows. A wide character can be represented by the encoding if its value V
+// is within the range of an unsigned char. The first char of the sequence
+// representing V is V % 3 + 1. This is followed by V % 3 null characters, and
+// finally by V itself.
+
+// The first codecvt facet, null_padded_codecvt, is statefull, with state_type
+// equal to int.
+
+// The second codecvt facet, stateless_null_padded_codecvt, is stateless. At
+// each point in a conversion, no characters are consumed unless there is room
+// in the output sequence to write an entire multibyte sequence.
+
+#ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
+
+#include <boost/config.hpp> // NO_STDC_NAMESPACE
+#include <boost/iostreams/detail/codecvt_helper.hpp>
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#include <cstddef> // mbstate_t.
+#include <locale> // codecvt.
+#include <boost/integer_traits.hpp> // const_max.
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+ namespace std { using ::mbstate_t; }
+#endif
+
+namespace boost { namespace iostreams { namespace test {
+
+//------------------Definition of null_padded_codecvt_state-------------------//
+
+class null_padded_codecvt_state {
+public:
+ null_padded_codecvt_state(int val = 0) : val_(val) { }
+ operator int() const { return val_; }
+ int& val() { return val_; }
+ const int& val() const { return val_; }
+private:
+ int val_;
+};
+
+} } }
+
+BOOST_IOSTREAMS_CODECVT_SPEC(boost::iostreams::test::null_padded_codecvt_state)
+
+namespace boost { namespace iostreams { namespace test {
+
+//------------------Definition of null_padded_codevt--------------------------//
+
+//
+// state is initially 0. After a single character is consumed, state is set to
+// the number of characters in the current multibyte sequence and decremented
+// as each character is consumed until its value reaches 0 again.
+//
+class null_padded_codecvt
+ : public iostreams::detail::codecvt_helper<
+ wchar_t, char, null_padded_codecvt_state
+ >
+{
+public:
+ typedef null_padded_codecvt_state state_type;
+private:
+ std::codecvt_base::result
+ do_in( state_type& state, const char* first1, const char* last1,
+ const char*& next1, wchar_t* first2, wchar_t* last2,
+ wchar_t*& next2 ) const
+ {
+ using namespace std;
+ if (state < 0 || state > 3)
+ return codecvt_base::error;
+ next1 = first1;
+ next2 = first2;
+ while (next2 != last2 && next1 != last1) {
+ while (next1 != last1) {
+ if (state == 0) {
+ if (*next1 < 1 || *next1 > 3)
+ return codecvt_base::error;
+ state = *next1++;
+ } else if (state == 1) {
+ *next2++ = (unsigned char) *next1++;
+ state = 0;
+ break;
+ } else {
+ if (*next1++ != 0)
+ return codecvt_base::error;
+ --state.val();
+ }
+ }
+ }
+ return next2 == last2 ?
+ codecvt_base::ok :
+ codecvt_base::partial;
+ }
+
+ std::codecvt_base::result
+ do_out( state_type& state, const wchar_t* first1, const wchar_t* last1,
+ const wchar_t*& next1, char* first2, char* last2,
+ char*& next2 ) const
+ {
+ using namespace std;
+ if (state < 0 || state > 3)
+ return codecvt_base::error;
+ next1 = first1;
+ next2 = first2;
+ while (next1 != last1 && next2 != last2) {
+ while (next2 != last2) {
+ if (state == 0) {
+ if (*next1 > integer_traits<unsigned char>::const_max)
+ return codecvt_base::noconv;
+ state = *next1 % 3 + 1;
+ *next2++ = static_cast<char>(state);
+ } else if (state == 1) {
+ state = 0;
+ *next2++ = static_cast<unsigned char>(*next1++);
+ break;
+ } else {
+ --state.val();
+ *next2++ = 0;
+ }
+ }
+ }
+ return next1 == last1 ?
+ codecvt_base::ok :
+ codecvt_base::partial;
+ }
+
+ std::codecvt_base::result
+ do_unshift( state_type& state,
+ char* /* first2 */,
+ char* last2,
+ char*& next2 ) const
+ {
+ using namespace std;
+ next2 = last2;
+ while (state.val()-- > 0)
+ if (next2 != last2)
+ *next2++ = 0;
+ else
+ return codecvt_base::partial;
+ return codecvt_base::ok;
+ }
+
+ bool do_always_noconv() const throw() { return false; }
+
+ int do_max_length() const throw() { return 4; }
+
+ int do_encoding() const throw() { return -1; }
+
+ int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type& state,
+ const char* first1, const char* last1,
+ std::size_t len2 ) const throw()
+ { // Implementation should follow that of do_in().
+ int st = state;
+ std::size_t result = 0;
+ const char* next1 = first1;
+ while (result < len2 && next1 != last1) {
+ while (next1 != last1) {
+ if (st == 0) {
+ if (*next1 < 1 || *next1 > 3)
+ return static_cast<int>(result); // error.
+ st = *next1++;
+ } else if (st == 1) {
+ ++result;
+ st = 0;
+ break;
+ } else {
+ if (*next1++ != 0)
+ return static_cast<int>(result); // error.
+ --st;
+ }
+ }
+ }
+ return static_cast<int>(result);
+ }
+};
+
+//------------------Definition of stateless_null_padded_codevt----------------//
+
+class stateless_null_padded_codecvt
+ : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+ std::codecvt_base::result
+ do_in( state_type&, const char* first1, const char* last1,
+ const char*& next1, wchar_t* first2, wchar_t* last2,
+ wchar_t*& next2 ) const
+ {
+ using namespace std;
+ for ( next1 = first1, next2 = first2;
+ next1 != last1 && next2 != last2; )
+ {
+ int len = (unsigned char) *next1;
+ if (len < 1 || len > 3)
+ return codecvt_base::error;
+ if (last1 - next1 < len + 1)
+ return codecvt_base::partial;
+ ++next1;
+ while (len-- > 1)
+ if (*next1++ != 0)
+ return codecvt_base::error;
+ *next2++ = (unsigned char) *next1++;
+ }
+ return next1 == last1 && next2 == last2 ?
+ codecvt_base::ok :
+ codecvt_base::partial;
+ }
+
+ std::codecvt_base::result
+ do_out( state_type&, const wchar_t* first1, const wchar_t* last1,
+ const wchar_t*& next1, char* first2, char* last2,
+ char*& next2 ) const
+ {
+ using namespace std;
+ for ( next1 = first1, next2 = first2;
+ next1 != last1 && next2 != last2; )
+ {
+ if (*next1 > integer_traits<unsigned char>::const_max)
+ return codecvt_base::noconv;
+ int skip = *next1 % 3 + 2;
+ if (last2 - next2 < skip)
+ return codecvt_base::partial;
+ *next2++ = static_cast<char>(--skip);
+ while (skip-- > 1)
+ *next2++ = 0;
+ *next2++ = (unsigned char) *next1++;
+ }
+ return codecvt_base::ok;
+ }
+
+ std::codecvt_base::result
+ do_unshift( state_type&,
+ char* /* first2 */,
+ char* /* last2 */,
+ char*& /* next2 */ ) const
+ {
+ return std::codecvt_base::ok;
+ }
+
+ bool do_always_noconv() const throw() { return false; }
+
+ int do_max_length() const throw() { return 4; }
+
+ int do_encoding() const throw() { return -1; }
+
+ int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type&,
+ const char* first1, const char* last1,
+ std::size_t len2 ) const throw()
+ { // Implementation should follow that of do_in().
+ std::size_t result = 0;
+ for ( const char* next1 = first1;
+ next1 != last1 && result < len2; ++result)
+ {
+ int len = (unsigned char) *next1;
+ if (len < 1 || len > 3 || last1 - next1 < len + 1)
+ return static_cast<int>(result); // error.
+ ++next1;
+ while (len-- > 1)
+ if (*next1++ != 0)
+ return static_cast<int>(result); // error.
+ ++next1;
+ }
+ return static_cast<int>(result);
+ }
+};
+
+} } } // End namespaces detail, iostreams, boost.
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/operation_sequence.hpp b/libs/iostreams/test/detail/operation_sequence.hpp
new file mode 100644
index 0000000000..15aaecfc74
--- /dev/null
+++ b/libs/iostreams/test/detail/operation_sequence.hpp
@@ -0,0 +1,224 @@
+/*
+ *
+ * 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.
+ *
+ * Defines the classes operation_sequence and operation, in the namespace
+ * boost::iostreams::test, for verifying that all elements of a sequence of
+ * operations are executed, and that they are executed in the correct order.
+ *
+ * File: libs/iostreams/test/detail/operation_sequence.hpp
+ * Date: Mon Dec 10 18:58:19 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#ifndef BOOST_IOSTREAMS_TEST_OPERATION_SEQUENCE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_OPERATION_SEQUENCE_HPP_INCLUDED
+
+#include <boost/config.hpp> // make sure size_t is in namespace std
+#include <cstddef>
+#include <climits>
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <utility> // pair
+#include <vector>
+#include <boost/lexical_cast.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/weak_ptr.hpp>
+
+#ifndef BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR
+# define BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR 20
+#endif
+
+#define BOOST_CHECK_OPERATION_SEQUENCE(seq) \
+ BOOST_CHECK_MESSAGE(seq.is_success(), seq.message()) \
+ /**/
+
+namespace boost { namespace iostreams { namespace test {
+
+// Simple exception class with error code built in to type
+template<int Code>
+struct operation_error { };
+
+class operation_sequence;
+
+// Represent an operation in a sequence of operations to be executed
+class operation {
+public:
+ friend class operation_sequence;
+ operation() : pimpl_() { }
+ void execute();
+private:
+ static void remove_operation(operation_sequence& seq, int id);
+
+ struct impl {
+ impl(operation_sequence& seq, int id, int error_code = -1)
+ : seq(seq), id(id), error_code(error_code)
+ { }
+ ~impl() { remove_operation(seq, id); }
+ impl& operator=(const impl&); // Supress VC warning 4512
+ operation_sequence& seq;
+ int id;
+ int error_code;
+ };
+ friend struct impl;
+
+ operation(operation_sequence& seq, int id, int error_code = -1)
+ : pimpl_(new impl(seq, id, error_code))
+ { }
+
+ shared_ptr<impl> pimpl_;
+};
+
+// Represents a sequence of operations to be executed in a particular order
+class operation_sequence {
+public:
+ friend class operation;
+ operation_sequence() { reset(); }
+
+ //
+ // Returns a new operation.
+ // Parameters:
+ //
+ // id - The operation id, determining the position
+ // of the new operation in the operation sequence
+ // error_code - If supplied, indicates that the new
+ // operation will throw operation_error<error_code>
+ // when executed. Must be an integer between 0 and
+ // BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR,
+ // inclusive.
+ //
+ operation new_operation(int id, int error_code = INT_MAX);
+
+ bool is_success() const { return success_; }
+ bool is_failure() const { return failed_; }
+ std::string message() const;
+ void reset();
+private:
+ void execute(int id);
+ void remove_operation(int id);
+ operation_sequence(const operation_sequence&);
+ operation_sequence& operator=(const operation_sequence&);
+
+ typedef weak_ptr<operation::impl> ptr_type;
+ typedef std::map<int, ptr_type> map_type;
+
+ map_type operations_;
+ std::vector<int> log_;
+ std::size_t total_executed_;
+ int last_executed_;
+ bool success_;
+ bool failed_;
+};
+
+//--------------Implementation of operation-----------------------------------//
+
+void operation::execute()
+{
+ pimpl_->seq.execute(pimpl_->id);
+ switch (pimpl_->error_code) {
+
+ // Implementation with one or more cleanup operations
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ case n: throw operation_error<n>(); \
+ /**/
+
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR)
+ #include BOOST_PP_LOCAL_ITERATE()
+ #undef BOOST_PP_LOCAL_MACRO
+
+ default:
+ break;
+ }
+}
+
+inline void operation::remove_operation(operation_sequence& seq, int id)
+{
+ seq.remove_operation(id);
+}
+
+//--------------Implementation of operation_sequence--------------------------//
+
+inline operation operation_sequence::new_operation(int id, int error_code)
+{
+ using namespace std;
+ if ( error_code < 0 ||
+ (error_code > BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR &&
+ error_code != INT_MAX) )
+ {
+ throw runtime_error( string("The error code ") +
+ lexical_cast<string>(error_code) +
+ " is out of range" );
+ }
+ if (last_executed_ != INT_MIN)
+ throw runtime_error( "Operations in progress; call reset() "
+ "before creating more operations" );
+ map_type::const_iterator it = operations_.find(id);
+ if (it != operations_.end())
+ throw runtime_error( string("The operation ") +
+ lexical_cast<string>(id) +
+ " already exists" );
+ operation op(*this, id, error_code);
+ operations_.insert(make_pair(id, ptr_type(op.pimpl_)));
+ return op;
+}
+
+inline std::string operation_sequence::message() const
+{
+ using namespace std;
+ if (success_)
+ return "success";
+ std::string msg = failed_ ?
+ "operations occurred out of order: " :
+ "operation sequence is incomplete: ";
+ typedef vector<int>::size_type size_type;
+ for (size_type z = 0, n = log_.size(); z < n; ++z) {
+ msg += lexical_cast<string>(log_[z]);
+ if (z < n - 1)
+ msg += ',';
+ }
+ return msg;
+}
+
+inline void operation_sequence::reset()
+{
+ log_.clear();
+ total_executed_ = 0;
+ last_executed_ = INT_MIN;
+ success_ = false;
+ failed_ = false;
+}
+
+inline void operation_sequence::execute(int id)
+{
+ log_.push_back(id);
+ if (!failed_ && last_executed_ < id) {
+ if (++total_executed_ == operations_.size())
+ success_ = true;
+ last_executed_ = id;
+ } else {
+ success_ = false;
+ failed_ = true;
+ }
+}
+
+inline void operation_sequence::remove_operation(int id)
+{
+ using namespace std;
+ map_type::iterator it = operations_.find(id);
+ if (it == operations_.end())
+ throw runtime_error( string("No such operation: ") +
+ lexical_cast<string>(id) );
+ operations_.erase(it);
+}
+
+} } } // End namespace boost::iostreams::test.
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_OPERATION_SEQUENCE_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/sequence.hpp b/libs/iostreams/test/detail/sequence.hpp
new file mode 100644
index 0000000000..0b08f7b307
--- /dev/null
+++ b/libs/iostreams/test/detail/sequence.hpp
@@ -0,0 +1,274 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_SEQUENCE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_SEQUENCE_HPP_INCLUDED
+
+#include <algorithm>
+#include <iterator>
+#include <string.h> // strlen.
+#include <vector>
+#include <boost/iostreams/detail/default_arg.hpp>
+#include "./constants.hpp"
+
+namespace boost { namespace iostreams { namespace test {
+
+template<typename Ch = BOOST_IOSTREAMS_DEFAULT_ARG(char) >
+struct test_sequence : public std::vector<Ch> {
+ test_sequence()
+ {
+ const Ch* buf = test::detail::data((Ch*)0);
+ this->reserve(data_reps * data_length());
+ for (int z = 0; z < data_reps; ++z)
+ std::copy(buf, buf + data_length(), std::back_inserter(*this));
+ }
+};
+
+const char* text =
+ "The Lord spoke to Moses saying: Speak to the children of "
+ "Israel, and have them take for Me an offering; from every "
+ "person whose heart inspires him to generosity, you shall take "
+ "My offering. And this is the offering that you shall take "
+ "from them: gold, silver, and copper; blue, purple, and "
+ "crimson wool; linen and goat hair; ram skins dyed red, "
+ "tachash skins, and acacia wood; oil for lighting, spices for "
+ "the anointing oil and for the incense; shoham stones and "
+ "filling stones for the ephod and for the choshen. And they "
+ "shall make Me a sanctuary and I will dwell in their midst "
+ "according to all that I show you, the pattern of the Mishkan "
+ "and the pattern of all its vessels; and so shall you do. They "
+ "shall make an ark of acacia wood, two and a half cubits its "
+ "length, a cubit and a half its width, and a cubit and a half "
+ "its height. And you shall overlay it with pure gold; from "
+ "inside and from outside you shall overlay it, and you shall "
+ "make upon it a golden crown all around. And you shall cast "
+ "four golden rings for it, and you shall place them upon its "
+ "four corners, two rings on its one side, and two rings on its "
+ "other side. And you shall make poles of acacia wood and you "
+ "shall overlay them with gold. And you shall bring the poles "
+ "into the rings on the sides of the ark, to carry the ark with "
+ "them. The poles of the ark shall be in the rings; they shall "
+ "not be removed from it. And you shall place into the ark the "
+ "testimony, which I will give you. "
+ "And you shall make an ark cover of pure gold, two and a half "
+ "cubits its length and a cubit and a half its width. And you "
+ "shall make two golden cherubim; you shall make them of "
+ "hammered work, from the two ends of the ark cover. And make "
+ "one cherub from the one end and the other cherub from the "
+ "other end; from the ark cover you shall make the cherubim on "
+ "its two ends. The cherubim shall have their wings spread "
+ "upwards, shielding the ark cover with their wings, with their "
+ "faces toward one another; [turned] toward the ark cover shall "
+ "be the faces of the cherubim. And you shall place the ark "
+ "cover on the ark from above, and into the ark you shall place "
+ "the testimony, which I will give you. I will arrange My "
+ "meetings with you there, and I will speak with you from atop "
+ "the ark cover from between the two cherubim that are upon the "
+ "Ark of the Testimony, all that I will command you unto the "
+ "children of Israel. And you shall make a table of acacia "
+ "wood, two cubits its length, one cubit its width, and a cubit "
+ "and a half its height. And you shall overlay it with pure "
+ "gold, and you shall make for it a golden crown all around. "
+ "And you shall make for it a frame a handbreadth [wide] all "
+ "around, and you shall make a golden crown for its frame all "
+ "around. And you shall make for it four golden rings, and you "
+ "shall place the rings on the four corners that are on its "
+ "four legs. The rings shall be opposite the frame as holders "
+ "for the poles [with which] to carry the table. And you shall "
+ "make the poles of acacia wood, and you shall overlay them "
+ "with gold, and the table shall be carried with them. And you "
+ "shall make its forms, its spoons, its half pipes, and its "
+ "supports with which it will be covered; of pure gold you "
+ "shall make them. And you shall place on the table showbread "
+ "before Me at all times. "
+ "And you shall make a menorah of pure gold. The menorah shall "
+ "be made of hammered work; its base and its stem, its goblets, "
+ "its knobs, and its flowers shall [all] be [one piece] with "
+ "it. And six branches coming out of its sides: three menorah "
+ "branches from its one side and three menorah branches from "
+ "its second side. Three decorated goblets on one branch, a "
+ "knob and a flower, and three decorated goblets on one branch, "
+ "a knob and a flower; so for the six branches that come out of "
+ "the menorah. And on [the stem of] the menorah [shall be] four "
+ "decorated goblets, its knobs and its flowers. And a knob under "
+ "the two branches from it, and a knob under the two branches "
+ "from it, and a knob under the two branches from it; so for the "
+ "six branches that come out of the menorah. Their knobs and "
+ "their branches shall [all] be [one piece] with it; all of it "
+
+ "[shall be] one hammered mass of pure gold. And you shall make "
+ "its lamps seven, and he shall kindle its lamps [so that they] "
+ "shed light toward its face. And its tongs and its scoops "
+ "[shall be] of pure gold. He shall make it of a talent of pure "
+ "gold, with all these implements. Now see and make according "
+ "to their pattern, which you are shown on the mountain. "
+ "And the Mishkan you shall make out of ten curtains "
+ "[consisting] of twisted fine linen, and blue, purple, and "
+ "crimson wool. A cherubim design of the work of a master "
+ "weaver you shall make them. The length of one curtain [shall "
+ "be] twenty eight cubits, and the width of one curtain [shall "
+ "be] four cubits; the same measure for all the curtains. Five "
+ "of these curtains shall be joined to one another, and [the "
+ "other] five curtains shall [also] be joined to one another. "
+ "And you shall make loops of blue wool on the edge of one "
+ "curtain [that is] at the edge of the [first] set, and so "
+ "shall you do on the edge of the outermost curtain of the "
+ "second set. You shall make fifty loops on [the edge of] one "
+ "curtain, and you shall make fifty loops on the edge of the "
+ "curtain in the second set; the loops shall correspond to one "
+ "another. And you shall make fifty golden clasps, and you "
+ "shall fasten the curtains to one another with the clasps; so "
+ "shall the Mishkan become one. And [then] you shall make "
+ "curtains of goat hair for a tent over the Mishkan; you shall "
+ "make eleven curtains. The length of one curtain [shall be] "
+ "thirty cubits, and the width of one curtain four cubits; the "
+ "same measure for the eleven curtains. And you shall join the "
+ "five curtains by themselves, and the [other] six curtains by "
+ "themselves; and you shall fold the sixth curtain before the "
+ "front of the tent. And you shall make fifty loops on the edge "
+ "of one curtain, [which is] at the edge of the [first] set, and "
+ "fifty loops on the edge of the [outermost] curtain of the "
+ "second set. And you shall make fifty copper clasps; you shall "
+ "bring the clasps into the loops, and you shall fasten the "
+ "tent together so that it will become one. And the overhanging "
+ "excess in the curtains of the tent half of the extra curtain "
+ "shall hang over the rear of the Mishkan. And the cubit from "
+ "here and the cubit from there of the excess in the length of "
+ "the curtains of the tent shall hang over the sides of the "
+ "Mishkan from here and from there to cover it. And you shall "
+ "make a covering for the tent of ram skins dyed red and a "
+ "covering of tachash skins above.";
+
+struct text_sequence : public std::vector<char> {
+ text_sequence()
+ {
+ const char* c =
+ "The Lord spoke to Moses saying: Speak to the children of "
+ "Israel, and have them take for Me an offering; from every "
+ "person whose heart inspires him to generosity, you shall take "
+ "My offering. And this is the offering that you shall take "
+ "from them: gold, silver, and copper; blue, purple, and "
+ "crimson wool; linen and goat hair; ram skins dyed red, "
+ "tachash skins, and acacia wood; oil for lighting, spices for "
+ "the anointing oil and for the incense; shoham stones and "
+ "filling stones for the ephod and for the choshen. And they "
+ "shall make Me a sanctuary and I will dwell in their midst "
+ "according to all that I show you, the pattern of the Mishkan "
+ "and the pattern of all its vessels; and so shall you do. They "
+ "shall make an ark of acacia wood, two and a half cubits its "
+ "length, a cubit and a half its width, and a cubit and a half "
+ "its height. And you shall overlay it with pure gold; from "
+ "inside and from outside you shall overlay it, and you shall "
+ "make upon it a golden crown all around. And you shall cast "
+ "four golden rings for it, and you shall place them upon its "
+ "four corners, two rings on its one side, and two rings on its "
+ "other side. And you shall make poles of acacia wood and you "
+ "shall overlay them with gold. And you shall bring the poles "
+ "into the rings on the sides of the ark, to carry the ark with "
+ "them. The poles of the ark shall be in the rings; they shall "
+ "not be removed from it. And you shall place into the ark the "
+ "testimony, which I will give you. "
+ "And you shall make an ark cover of pure gold, two and a half "
+ "cubits its length and a cubit and a half its width. And you "
+ "shall make two golden cherubim; you shall make them of "
+ "hammered work, from the two ends of the ark cover. And make "
+ "one cherub from the one end and the other cherub from the "
+ "other end; from the ark cover you shall make the cherubim on "
+ "its two ends. The cherubim shall have their wings spread "
+ "upwards, shielding the ark cover with their wings, with their "
+ "faces toward one another; [turned] toward the ark cover shall "
+ "be the faces of the cherubim. And you shall place the ark "
+ "cover on the ark from above, and into the ark you shall place "
+ "the testimony, which I will give you. I will arrange My "
+ "meetings with you there, and I will speak with you from atop "
+ "the ark cover from between the two cherubim that are upon the "
+ "Ark of the Testimony, all that I will command you unto the "
+ "children of Israel. And you shall make a table of acacia "
+ "wood, two cubits its length, one cubit its width, and a cubit "
+ "and a half its height. And you shall overlay it with pure "
+ "gold, and you shall make for it a golden crown all around. "
+ "And you shall make for it a frame a handbreadth [wide] all "
+ "around, and you shall make a golden crown for its frame all "
+ "around. And you shall make for it four golden rings, and you "
+ "shall place the rings on the four corners that are on its "
+ "four legs. The rings shall be opposite the frame as holders "
+ "for the poles [with which] to carry the table. And you shall "
+ "make the poles of acacia wood, and you shall overlay them "
+ "with gold, and the table shall be carried with them. And you "
+ "shall make its forms, its spoons, its half pipes, and its "
+ "supports with which it will be covered; of pure gold you "
+ "shall make them. And you shall place on the table showbread "
+ "before Me at all times. "
+ "And you shall make a menorah of pure gold. The menorah shall "
+ "be made of hammered work; its base and its stem, its goblets, "
+ "its knobs, and its flowers shall [all] be [one piece] with "
+ "it. And six branches coming out of its sides: three menorah "
+ "branches from its one side and three menorah branches from "
+ "its second side. Three decorated goblets on one branch, a "
+ "knob and a flower, and three decorated goblets on one branch, "
+ "a knob and a flower; so for the six branches that come out of "
+ "the menorah. And on [the stem of] the menorah [shall be] four "
+ "decorated goblets, its knobs and its flowers. And a knob under "
+ "the two branches from it, and a knob under the two branches "
+ "from it, and a knob under the two branches from it; so for the "
+ "six branches that come out of the menorah. Their knobs and "
+ "their branches shall [all] be [one piece] with it; all of it "
+
+ "[shall be] one hammered mass of pure gold. And you shall make "
+ "its lamps seven, and he shall kindle its lamps [so that they] "
+ "shed light toward its face. And its tongs and its scoops "
+ "[shall be] of pure gold. He shall make it of a talent of pure "
+ "gold, with all these implements. Now see and make according "
+ "to their pattern, which you are shown on the mountain. "
+ "And the Mishkan you shall make out of ten curtains "
+ "[consisting] of twisted fine linen, and blue, purple, and "
+ "crimson wool. A cherubim design of the work of a master "
+ "weaver you shall make them. The length of one curtain [shall "
+ "be] twenty eight cubits, and the width of one curtain [shall "
+ "be] four cubits; the same measure for all the curtains. Five "
+ "of these curtains shall be joined to one another, and [the "
+ "other] five curtains shall [also] be joined to one another. "
+ "And you shall make loops of blue wool on the edge of one "
+ "curtain [that is] at the edge of the [first] set, and so "
+ "shall you do on the edge of the outermost curtain of the "
+ "second set. You shall make fifty loops on [the edge of] one "
+ "curtain, and you shall make fifty loops on the edge of the "
+ "curtain in the second set; the loops shall correspond to one "
+ "another. And you shall make fifty golden clasps, and you "
+ "shall fasten the curtains to one another with the clasps; so "
+ "shall the Mishkan become one. And [then] you shall make "
+ "curtains of goat hair for a tent over the Mishkan; you shall "
+ "make eleven curtains. The length of one curtain [shall be] "
+ "thirty cubits, and the width of one curtain four cubits; the "
+ "same measure for the eleven curtains. And you shall join the "
+ "five curtains by themselves, and the [other] six curtains by "
+ "themselves; and you shall fold the sixth curtain before the "
+ "front of the tent. And you shall make fifty loops on the edge "
+ "of one curtain, [which is] at the edge of the [first] set, and "
+ "fifty loops on the edge of the [outermost] curtain of the "
+ "second set. And you shall make fifty copper clasps; you shall "
+ "bring the clasps into the loops, and you shall fasten the "
+ "tent together so that it will become one. And the overhanging "
+ "excess in the curtains of the tent half of the extra curtain "
+ "shall hang over the rear of the Mishkan. And the cubit from "
+ "here and the cubit from there of the excess in the length of "
+ "the curtains of the tent shall hang over the sides of the "
+ "Mishkan from here and from there to cover it. And you shall "
+ "make a covering for the tent of ram skins dyed red and a "
+ "covering of tachash skins above.";
+ std::vector<char>::size_type len = strlen(c);
+ this->reserve(len);
+ this->insert(this->end(), c, c + len);
+ }
+};
+
+
+//----------------------------------------------------------------------------//
+
+} } } // End namespaces test, iostreams, boost.
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_SEQUENCE_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/temp_file.hpp b/libs/iostreams/test/detail/temp_file.hpp
new file mode 100644
index 0000000000..51908002f5
--- /dev/null
+++ b/libs/iostreams/test/detail/temp_file.hpp
@@ -0,0 +1,92 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_FILES_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_FILES_HPP_INCLUDED
+
+#include <cctype> // toupper, tolower
+#include <cstdio> // tmpname, TMP_MAX, remove
+#include <cstdlib> // rand, toupper, tolower (VC6)
+#include <fstream>
+#include <string>
+#include <boost/filesystem/v3/operations.hpp>
+#include "./constants.hpp"
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+# undef toupper
+# undef tolower
+# undef remove
+# undef rand
+namespace std {
+ using ::toupper; using ::tolower; using ::remove; using ::rand;
+}
+#endif
+
+namespace boost { namespace iostreams { namespace test {
+
+// Represents a temp file, deleted upon destruction.
+class temp_file {
+public:
+
+ // Constructs a temp file which does not initially exist.
+ temp_file() { set_name(); }
+ ~temp_file() { std::remove(name_.c_str()); }
+ const ::std::string name() const { return name_; }
+ operator const ::std::string() const { return name_; }
+private:
+ void set_name() {
+ name_ = boost::filesystem3::unique_path().string();
+ }
+
+ ::std::string name_;
+};
+
+struct test_file : public temp_file {
+ test_file()
+ {
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::out | BOOST_IOS::binary;
+ ::std::ofstream f(name().c_str(), mode);
+ const ::std::string n(name());
+ const char* buf = narrow_data();
+ for (int z = 0; z < data_reps; ++z)
+ f.write(buf, data_length());
+ }
+};
+
+
+struct uppercase_file : public temp_file {
+ uppercase_file()
+ {
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::out | BOOST_IOS::binary;
+ ::std::ofstream f(name().c_str(), mode);
+ const char* buf = narrow_data();
+ for (int z = 0; z < data_reps; ++z)
+ for (int w = 0; w < data_length(); ++w)
+ f.put((char) std::toupper(buf[w]));
+ }
+};
+
+struct lowercase_file : public temp_file {
+ lowercase_file()
+ {
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::out | BOOST_IOS::binary;
+ ::std::ofstream f(name().c_str(), mode);
+ const char* buf = narrow_data();
+ for (int z = 0; z < data_reps; ++z)
+ for (int w = 0; w < data_length(); ++w)
+ f.put((char) std::tolower(buf[w]));
+ }
+};
+
+//----------------------------------------------------------------------------//
+
+} } } // End namespaces test, iostreams, boost.
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_FILES_HPP_INCLUDED
diff --git a/libs/iostreams/test/detail/utf8_codecvt_facet.cpp b/libs/iostreams/test/detail/utf8_codecvt_facet.cpp
new file mode 100644
index 0000000000..26679f77bf
--- /dev/null
+++ b/libs/iostreams/test/detail/utf8_codecvt_facet.cpp
@@ -0,0 +1,371 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// utf8_codecvt_facet.cpp
+
+// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu)
+// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu).
+// Distributed under the Boost Software License, Version 1.0. (See accompany-
+// ing 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.
+
+//#include <cstdlib> // for multi-byte converson routines
+
+// Jonathan Turkanis:
+// - Replaced test for BOOST_NO_STD_WSTREAMBUF with test for
+// BOOST_IOSTREAMS_NO_WIDE_STREAMS;
+// - Derived from codecvt_helper instead of codecvt.
+
+#include <boost/config.hpp>
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#ifdef BOOST_IOSTREAMS_NO_LOCALES
+# error "C++ locales not supported on this platform"
+#else
+
+#include <cassert>
+#include <cstddef>
+
+#include <boost/detail/workaround.hpp>
+#include "./utf8_codecvt_facet.hpp"
+
+#if BOOST_WORKAROUND(__BORLANDC__, <= 0x600)
+# pragma warn -sig // Conversion may lose significant digits
+# pragma warn -rng // Constant is out of range in comparison
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation for wchar_t
+
+// Translate incoming UTF-8 into UCS-4
+std::codecvt_base::result utf8_codecvt_facet_wchar_t::do_in(
+ std::mbstate_t&,
+ const char * from,
+ const char * from_end,
+ const char * & from_next,
+ wchar_t * to,
+ wchar_t * to_end,
+ wchar_t * & to_next
+) const {
+ // Basic algorithm: The first octet determines how many
+ // octets total make up the UCS-4 character. The remaining
+ // "continuing octets" all begin with "10". To convert, subtract
+ // the amount that specifies the number of octets from the first
+ // octet. Subtract 0x80 (1000 0000) from each continuing octet,
+ // then mash the whole lot together. Note that each continuing
+ // octet only uses 6 bits as unique values, so only shift by
+ // multiples of 6 to combine.
+ while (from != from_end && to != to_end) {
+
+ // Error checking on the first octet
+ if (invalid_leading_octet(*from)){
+ from_next = from;
+ to_next = to;
+ return std::codecvt_base::error;
+ }
+
+ // The first octet is adjusted by a value dependent upon
+ // the number of "continuing octets" encoding the character
+ const int cont_octet_count = get_cont_octet_count(*from);
+ const wchar_t octet1_modifier_table[] = {
+ 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+ };
+
+ // The unsigned char conversion is necessary in case char is
+ // signed (I learned this the hard way)
+ wchar_t ucs_result =
+ (unsigned char)(*from++) - octet1_modifier_table[cont_octet_count];
+
+ // Invariants :
+ // 1) At the start of the loop, 'i' continuing characters have been
+ // processed
+ // 2) *from points to the next continuing character to be processed.
+ int i = 0;
+ while(i != cont_octet_count && from != from_end) {
+
+ // Error checking on continuing characters
+ if (invalid_continuing_octet(*from)) {
+ from_next = from;
+ to_next = to;
+ return std::codecvt_base::error;
+ }
+
+ ucs_result *= (1 << 6);
+
+ // each continuing character has an extra (10xxxxxx)b attached to
+ // it that must be removed.
+ ucs_result += (unsigned char)(*from++) - 0x80;
+ ++i;
+ }
+
+ // If the buffer ends with an incomplete unicode character...
+ if (from == from_end && i != cont_octet_count) {
+ // rewind "from" to before the current character translation
+ from_next = from - (i+1);
+ to_next = to;
+ return std::codecvt_base::partial;
+ }
+ *to++ = ucs_result;
+ }
+ from_next = from;
+ to_next = to;
+
+ // Were we done converting or did we run out of destination space?
+ if(from == from_end) return std::codecvt_base::ok;
+ else return std::codecvt_base::partial;
+}
+
+std::codecvt_base::result utf8_codecvt_facet_wchar_t::do_out(
+ std::mbstate_t &,
+ const wchar_t * from,
+ const wchar_t * from_end,
+ const wchar_t * & from_next,
+ char * to,
+ char * to_end,
+ char * & to_next
+) const
+{
+ // RG - consider merging this table with the other one
+ const wchar_t octet1_modifier_table[] = {
+ 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+ };
+
+ while (from != from_end && to != to_end) {
+
+#define BOOST_NULL // Prevent macro expansion
+ // Check for invalid UCS-4 character
+ if (*from > std::numeric_limits<wchar_t>::max BOOST_NULL ()) {
+ from_next = from;
+ to_next = to;
+ return std::codecvt_base::error;
+ }
+#undef BOOST_NULL
+
+ int cont_octet_count = get_cont_octet_out_count(*from);
+
+ // RG - comment this formula better
+ int shift_exponent = (cont_octet_count) * 6;
+
+ // Process the first character
+ *to++ = octet1_modifier_table[cont_octet_count] +
+ (unsigned char)(*from / (1 << shift_exponent));
+
+ // Process the continuation characters
+ // Invariants: At the start of the loop:
+ // 1) 'i' continuing octets have been generated
+ // 2) '*to' points to the next location to place an octet
+ // 3) shift_exponent is 6 more than needed for the next octet
+ int i = 0;
+ while (i != cont_octet_count && to != to_end) {
+ shift_exponent -= 6;
+ *to++ = 0x80 + ((*from / (1 << shift_exponent)) % (1 << 6));
+ ++i;
+ }
+ // If we filled up the out buffer before encoding the character
+ if(to == to_end && i != cont_octet_count) {
+ from_next = from;
+ to_next = to - (i+1);
+ return std::codecvt_base::partial;
+ }
+ *from++;
+ }
+ from_next = from;
+ to_next = to;
+ // Were we done or did we run out of destination space
+ if(from == from_end) return std::codecvt_base::ok;
+ else return std::codecvt_base::partial;
+}
+
+// How many char objects can I process to get <= max_limit
+// wchar_t objects?
+int utf8_codecvt_facet_wchar_t::do_length(
+ BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER std::mbstate_t &,
+ const char * from,
+ const char * from_end,
+ std::size_t max_limit
+) const throw()
+{
+ // RG - this code is confusing! I need a better way to express it.
+ // and test cases.
+
+ // Invariants:
+ // 1) last_octet_count has the size of the last measured character
+ // 2) char_count holds the number of characters shown to fit
+ // within the bounds so far (no greater than max_limit)
+ // 3) from_next points to the octet 'last_octet_count' before the
+ // last measured character.
+ int last_octet_count=0;
+ std::size_t char_count = 0;
+ const char* from_next = from;
+ // Use "<" because the buffer may represent incomplete characters
+ while (from_next+last_octet_count <= from_end && char_count <= max_limit) {
+ from_next += last_octet_count;
+ last_octet_count = (get_octet_count(*from_next));
+ ++char_count;
+ }
+ return from_next-from_end;
+}
+
+unsigned int utf8_codecvt_facet_wchar_t::get_octet_count(
+ unsigned char lead_octet
+){
+ // if the 0-bit (MSB) is 0, then 1 character
+ if (lead_octet <= 0x7f) return 1;
+
+ // Otherwise the count number of consecutive 1 bits starting at MSB
+ assert(0xc0 <= lead_octet && lead_octet <= 0xfd);
+
+ if (0xc0 <= lead_octet && lead_octet <= 0xdf) return 2;
+ else if (0xe0 <= lead_octet && lead_octet <= 0xef) return 3;
+ else if (0xf0 <= lead_octet && lead_octet <= 0xf7) return 4;
+ else if (0xf8 <= lead_octet && lead_octet <= 0xfb) return 5;
+ else return 6;
+}
+
+namespace {
+template<std::size_t s>
+int get_cont_octet_out_count_impl(wchar_t word){
+ if (word < 0x80) {
+ return 0;
+ }
+ if (word < 0x800) {
+ return 1;
+ }
+ return 2;
+}
+
+// note the following code will generate on some platforms where
+// wchar_t is defined as UCS2. The warnings are superfluous as
+// the specialization is never instantitiated with such compilers.
+template<>
+int get_cont_octet_out_count_impl<4>(wchar_t word)
+{
+ if (word < 0x80) {
+ return 0;
+ }
+ if (word < 0x800) {
+ return 1;
+ }
+ if (word < 0x10000) {
+ return 2;
+ }
+ if (word < 0x200000) {
+ return 3;
+ }
+ if (word < 0x4000000) {
+ return 4;
+ }
+ return 5;
+}
+
+} // namespace anonymous
+
+// How many "continuing octets" will be needed for this word
+// == total octets - 1.
+int utf8_codecvt_facet_wchar_t::get_cont_octet_out_count(
+ wchar_t word
+) const {
+ return get_cont_octet_out_count_impl<sizeof(wchar_t)>(word);
+}
+
+#if 0 // not used?
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation for char
+
+std::codecvt_base::result utf8_codecvt_facet_char::do_in(
+ std::mbstate_t & state,
+ const char * from,
+ const char * from_end,
+ const char * & from_next,
+ char * to,
+ char * to_end,
+ char * & to_next
+) const
+{
+ while(from_next < from_end){
+ wchar_t w;
+ wchar_t *wnext = & w;
+ utf8_codecvt_facet_wchar_t::result ucs4_result;
+ ucs4_result = base_class::do_in(
+ state,
+ from, from_end, from_next,
+ wnext, wnext + 1, wnext
+ );
+ if(codecvt_base::ok != ucs4_result)
+ return ucs4_result;
+ // if the conversion succeeds.
+ int length = std::wctomb(to_next, w);
+ assert(-1 != length);
+ to_next += length;
+ }
+ return codecvt_base::ok;
+}
+
+std::codecvt_base::result utf8_codecvt_facet_char::do_out(
+ mbstate_t & state,
+ const char * from,
+ const char * from_end,
+ const char * & from_next,
+ char * to,
+ char * to_end,
+ char * & to_next
+) const
+{
+ while(from_next < from_end){
+ wchar_t w;
+ int result = std::mbtowc(&w, from_next, MB_LENGTH_MAX);
+ assert(-1 != result);
+ from_next += result;
+ utf8_codecvt_facet_wchar_t::result ucs4_result;
+
+ const wchar_t *wptr = & w;
+ ucs4_result = base_class::do_out(
+ state,
+ wptr, wptr+1, wptr,
+ to_next, to_end, to_next
+ );
+ if(codecvt_base::ok != ucs4_result)
+ return ucs4_result;
+ }
+ return codecvt_base::ok;
+}
+
+// How many bytes objects can I process to get <= max_limit
+// char objects?
+int utf8_codecvt_facet_char::do_length(
+ // it seems that the standard doesn't use const so these librarires
+ // would be in error
+ BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER
+ utf8_codecvt_facet_wchar_t::mbstate_t & initial_state,
+ const char * from_next,
+ const char * from_end,
+ std::size_t max_limit
+) const
+{
+ int total_length = 0;
+ const char *from = from_next;
+ mbstate_t state = initial_state;
+ while(from_next < from_end){
+ wchar_t w;
+ wchar_t *wnext = & w;
+ utf8_codecvt_facet_wchar_t::result ucs4_result;
+ ucs4_result = base_class::do_in(
+ state,
+ from_next, from_end, from_next,
+ wnext, wnext + 1, wnext
+ );
+
+ if(codecvt_base::ok != ucs4_result)
+ break;
+
+ char carray[MB_LENGTH_MAX];
+ std::size_t count = wctomb(carray, w);
+ if(count > max_limit)
+ break;
+
+ max_limit -= count;
+ total_length = from_next - from;
+ }
+ return total_length;
+}
+#endif
+
+#endif //BOOST_IOSTREAMS_NO_WIDE_STREAMS
diff --git a/libs/iostreams/test/detail/utf8_codecvt_facet.hpp b/libs/iostreams/test/detail/utf8_codecvt_facet.hpp
new file mode 100644
index 0000000000..46932cf6eb
--- /dev/null
+++ b/libs/iostreams/test/detail/utf8_codecvt_facet.hpp
@@ -0,0 +1,200 @@
+#ifndef BOOST_UTF8_CODECVT_FACET_HPP
+#define BOOST_UTF8_CODECVT_FACET_HPP
+
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+# error wide streams not supported on this platform
+#endif
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// utf8_codecvt_facet.hpp
+
+// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu)
+// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu).
+// Distributed under the Boost Software License, Version 1.0. (See accompany-
+// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Note:(Robert Ramey). I have made the following alterations in the original
+// code.
+// a) Rendered utf8_codecvt<wchar_t, char> with using templates
+// b) Move longer functions outside class definition to prevent inlining
+// and make code smaller
+// c) added on a derived class to permit translation to/from current
+// locale to utf8
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as text - note these ar templated on the basic
+// stream templates to accommodate wide (and other?) kind of characters
+//
+// note the fact that on libraries without wide characters, ostream is
+// is not a specialization of basic_ostream which in fact is not defined
+// in such cases. So we can't use basic_ostream<OStream::char_type> but rather
+// use two template parameters
+//
+// utf8_codecvt_facet
+// This is an implementation of a std::codecvt facet for translating
+// from UTF-8 externally to UCS-4. Note that this is not tied to
+// any specific types in order to allow customization on platforms
+// where wchar_t is not big enough.
+//
+// NOTES: The current implementation jumps through some unpleasant hoops in
+// order to deal with signed character types. As a std::codecvt_base::result,
+// it is necessary for the ExternType to be convertible to unsigned char.
+// I chose not to tie the extern_type explicitly to char. But if any combination
+// of types other than <wchar_t,char_t> is used, then std::codecvt must be
+// specialized on those types for this to work.
+
+#include <locale>
+#include <cstddef> // size_t
+#include <cwchar> // mbstate_t
+#include <boost/integer_traits.hpp>
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#include <boost/iostreams/detail/codecvt_helper.hpp>
+
+// maximum lenght of a multibyte string
+#define MB_LENGTH_MAX 8
+
+struct utf8_codecvt_facet_wchar_t
+ : public boost::iostreams::detail::codecvt_helper<wchar_t, char, std::mbstate_t>
+{
+public:
+ explicit utf8_codecvt_facet_wchar_t(std::size_t no_locale_manage = 0)
+ : boost::iostreams::detail::codecvt_helper<wchar_t, char, std::mbstate_t>
+ (no_locale_manage)
+ { }
+protected:
+ virtual std::codecvt_base::result do_in(
+ std::mbstate_t& state,
+ const char * from,
+ const char * from_end,
+ const char * & from_next,
+ wchar_t * to,
+ wchar_t * to_end,
+ wchar_t*& to_next
+ ) const;
+
+ virtual std::codecvt_base::result do_out(
+ std::mbstate_t & state, const wchar_t * from,
+ const wchar_t * from_end, const wchar_t* & from_next,
+ char * to, char * to_end, char * & to_next
+ ) const;
+
+ bool invalid_continuing_octet(unsigned char octet_1) const {
+ return (octet_1 < 0x80|| 0xbf< octet_1);
+ }
+
+ bool invalid_leading_octet(unsigned char octet_1) const {
+ return (0x7f < octet_1 && octet_1 < 0xc0) ||
+ (octet_1 > 0xfd);
+ }
+
+ // continuing octets = octets except for the leading octet
+ static unsigned int get_cont_octet_count(unsigned char lead_octet) {
+ return get_octet_count(lead_octet) - 1;
+ }
+
+ static unsigned int get_octet_count(unsigned char lead_octet);
+
+ // How many "continuing octets" will be needed for this word
+ // == total octets - 1.
+ int get_cont_octet_out_count(wchar_t word) const ;
+
+ virtual bool do_always_noconv() const throw() { return false; }
+
+ // UTF-8 isn't really stateful since we rewind on partial conversions
+ virtual std::codecvt_base::result do_unshift(
+ std::mbstate_t&,
+ char * from,
+ char * /* to */,
+ char * & next
+ ) const{
+ next = from;
+ return ok;
+ }
+
+ virtual int do_encoding() const throw() {
+ const int variable_byte_external_encoding=0;
+ return variable_byte_external_encoding;
+ }
+
+ // How many char objects can I process to get <= max_limit
+ // wchar_t objects?
+ virtual int do_length(
+ BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER std::mbstate_t &,
+ const char * from,
+ const char * from_end,
+ std::size_t max_limit
+ ) const throw();
+
+ // Largest possible value do_length(state,from,from_end,1) could return.
+ virtual int do_max_length() const throw () {
+ return 6; // largest UTF-8 encoding of a UCS-4 character
+ }
+};
+
+#if 0 // not used - incorrect in any case
+// Robert Ramey - use the above to make a code converter from multi-byte
+// char strings to utf8 encoding
+struct utf8_codecvt_facet_char : public utf8_codecvt_facet_wchar_t
+{
+ typedef utf8_codecvt_facet_wchar_t base_class;
+public:
+ explicit utf8_codecvt_facet_char(std::size_t no_locale_manage=0)
+ : base_class(no_locale_manage)
+ {}
+protected:
+ virtual std::codecvt_base::result do_in(
+ std::mbstate_t & state,
+ const char * from,
+ const char * from_end,
+ const char * & from_next,
+ char * to,
+ char * to_end,
+ char * & to_next
+ ) const;
+
+ virtual std::codecvt_base::result do_out(
+ std::mbstate_t & state,
+ const char * from,
+ const char * from_end,
+ const char* & from_next,
+ char * to,
+ char * to_end,
+ char * & to_next
+ ) const;
+
+ // How many char objects can I process to get <= max_limit
+ // char objects?
+ virtual int do_length(
+ const std::mbstate_t&,
+ const char * from,
+ const char * from_end,
+ std::size_t max_limit
+ ) const;
+};
+#endif
+
+template<class Internal, class External>
+struct utf8_codecvt_facet
+{};
+
+template<>
+struct utf8_codecvt_facet<wchar_t, char>
+ : public utf8_codecvt_facet_wchar_t
+{};
+
+#if 0
+template<>
+struct utf8_codecvt_facet<char, char>
+ : public utf8_codecvt_facet_char
+{};
+#endif
+
+#endif // BOOST_UTF8_CODECVT_FACET_HPP
+
diff --git a/libs/iostreams/test/detail/verification.hpp b/libs/iostreams/test/detail/verification.hpp
new file mode 100644
index 0000000000..0ee3e31ea9
--- /dev/null
+++ b/libs/iostreams/test/detail/verification.hpp
@@ -0,0 +1,316 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+
+#ifndef BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED
+
+#include <iostream>
+#include <exception>
+#include <string>
+#include <string.h>
+#include <fstream>
+#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
+# include <istream>
+# include <ostream>
+#else
+# include <iostream.h>
+#endif
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/iostreams/detail/char_traits.hpp>
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#include "./constants.hpp"
+
+// Code generation bugs cause tests to fail with global optimization.
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# pragma optimize("g", off)
+#endif
+
+// Included only by tests; no need to #undef.
+#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
+# define BOOST_TEMPLATE_DECL template<typename Ch, typename Tr>
+# define BOOST_CHAR Ch
+# define BOOST_ISTREAM std::basic_istream<Ch, Tr>
+# define BOOST_OSTREAM std::basic_ostream<Ch, Tr>
+#else
+# define BOOST_TEMPLATE_DECL
+# define BOOST_CHAR char
+# define BOOST_ISTREAM std::istream
+# define BOOST_OSTREAM std::ostream
+#endif
+
+namespace boost { namespace iostreams { namespace test {
+
+BOOST_TEMPLATE_DECL
+bool compare_streams_in_chars(BOOST_ISTREAM& first, BOOST_ISTREAM& second)
+{
+ for (int z = 0; z < data_reps; ++z)
+ for (int w = 0; w < data_length(); ++w)
+ if (first.eof() != second.eof() || first.get() != second.get())
+ return false;
+ return true;
+}
+
+BOOST_TEMPLATE_DECL
+bool compare_streams_in_chunks(BOOST_ISTREAM& first, BOOST_ISTREAM& second)
+{
+ int i = 0;
+ do {
+ BOOST_CHAR buf_one[chunk_size];
+ BOOST_CHAR buf_two[chunk_size];
+ first.read(buf_one, chunk_size);
+ second.read(buf_two, chunk_size);
+ std::streamsize amt = first.gcount();
+ if ( amt != static_cast<std::streamsize>(second.gcount()) ||
+ BOOST_IOSTREAMS_CHAR_TRAITS(BOOST_CHAR)::
+ compare(buf_one, buf_two, amt) != 0 )
+ return false;
+ ++i;
+ } while (!first.eof());
+ return true;
+}
+
+bool compare_files(const std::string& first, const std::string& second)
+{
+ using namespace std;
+ ifstream one(first.c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ ifstream two(second.c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ return compare_streams_in_chunks(one, two);
+}
+
+#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
+ template<typename Container, typename Ch, typename Tr>
+#else
+ template<typename Container>
+#endif
+bool compare_container_and_stream(Container& cnt, BOOST_ISTREAM& is)
+{
+ typename Container::iterator first = cnt.begin();
+ typename Container::iterator last = cnt.end();
+ do {
+ if ((first == last) != is.eof()) return false;
+ if (first != last && *first++ != is.get()) return false;
+ } while (first != last);
+ return true;
+}
+
+template<typename Container>
+bool compare_container_and_file(Container& cnt, const std::string& file)
+{
+ std::ifstream fstrm(file.c_str(), BOOST_IOS::in | BOOST_IOS::binary);
+ return compare_container_and_stream(cnt, fstrm);
+}
+
+BOOST_TEMPLATE_DECL
+void write_data_in_chars(BOOST_OSTREAM& os)
+{
+ for (int z = 0; z < data_reps; ++z)
+ for (int w = 0; w < data_length(); ++w)
+ os.put(detail::data((BOOST_CHAR*)0)[w]);
+ os.flush();
+}
+
+BOOST_TEMPLATE_DECL
+void write_data_in_chunks(BOOST_OSTREAM& os)
+{
+ const BOOST_CHAR* buf = detail::data((BOOST_CHAR*)0);
+ for (int z = 0; z < data_reps; ++z)
+ os.write(buf, data_length());
+ os.flush();
+}
+
+bool test_seekable_in_chars(std::iostream& io)
+{
+ int i; // old 'for' scope workaround.
+
+ // Test seeking with ios::cur
+ for (i = 0; i < data_reps; ++i) {
+ int j;
+ for (j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ io.seekp(-chunk_size, BOOST_IOS::cur);
+ for (j = 0; j < chunk_size; ++j)
+ if (io.get() != narrow_data()[j])
+ return false;
+ io.seekp(-chunk_size, BOOST_IOS::cur);
+ for (j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ }
+
+ // Test seeking with ios::beg
+ std::streamoff off = 0;
+ io.seekp(0, BOOST_IOS::beg);
+ for (i = 0; i < data_reps; ++i, off += chunk_size) {
+ int j;
+ for (j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ io.seekp(off, BOOST_IOS::beg);
+ for (j = 0; j < chunk_size; ++j)
+ if (io.get() != narrow_data()[j])
+ return false;
+ io.seekp(off, BOOST_IOS::beg);
+ for (j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ }
+
+ // Test seeking with ios::end
+ io.seekp(0, BOOST_IOS::end);
+ off = io.tellp();
+ io.seekp(-off, BOOST_IOS::end);
+ for (i = 0; i < data_reps; ++i, off -= chunk_size) {
+ int j;
+ for (j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ io.seekp(-off, BOOST_IOS::end);
+ for (j = 0; j < chunk_size; ++j)
+ if (io.get() != narrow_data()[j])
+ return false;
+ io.seekp(-off, BOOST_IOS::end);
+ for (j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ }
+ return true;
+}
+
+bool test_seekable_in_chunks(std::iostream& io)
+{
+ int i; // old 'for' scope workaround.
+
+ // Test seeking with ios::cur
+ for (i = 0; i < data_reps; ++i) {
+ io.write(narrow_data(), chunk_size);
+ io.seekp(-chunk_size, BOOST_IOS::cur);
+ char buf[chunk_size];
+ io.read(buf, chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ io.seekp(-chunk_size, BOOST_IOS::cur);
+ io.write(narrow_data(), chunk_size);
+ }
+
+ // Test seeking with ios::beg
+ std::streamoff off = 0;
+ io.seekp(0, BOOST_IOS::beg);
+ for (i = 0; i < data_reps; ++i, off += chunk_size) {
+ io.write(narrow_data(), chunk_size);
+ io.seekp(off, BOOST_IOS::beg);
+ char buf[chunk_size];
+ io.read(buf, chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ io.seekp(off, BOOST_IOS::beg);
+ io.write(narrow_data(), chunk_size);
+ }
+
+ // Test seeking with ios::end
+ io.seekp(0, BOOST_IOS::end);
+ off = io.tellp();
+ io.seekp(-off, BOOST_IOS::end);
+ for (i = 0; i < data_reps; ++i, off -= chunk_size) {
+ io.write(narrow_data(), chunk_size);
+ io.seekp(-off, BOOST_IOS::end);
+ char buf[chunk_size];
+ io.read(buf, chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ io.seekp(-off, BOOST_IOS::end);
+ io.write(narrow_data(), chunk_size);
+ }
+ return true;
+}
+
+bool test_input_seekable(std::istream& io)
+{
+ int i; // old 'for' scope workaround.
+
+ // Test seeking with ios::cur
+ for (i = 0; i < data_reps; ++i) {
+ for (int j = 0; j < chunk_size; ++j)
+ if (io.get() != narrow_data()[j])
+ return false;
+ io.seekg(-chunk_size, BOOST_IOS::cur);
+ char buf[chunk_size];
+ io.read(buf, chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ }
+
+ // Test seeking with ios::beg
+ std::streamoff off = 0;
+ io.seekg(0, BOOST_IOS::beg);
+ for (i = 0; i < data_reps; ++i, off += chunk_size) {
+ for (int j = 0; j < chunk_size; ++j)
+ if (io.get() != narrow_data()[j])
+ return false;
+ io.seekg(off, BOOST_IOS::beg);
+ char buf[chunk_size];
+ io.read(buf, chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ }
+
+ // Test seeking with ios::end
+ io.seekg(0, BOOST_IOS::end);
+ off = io.tellg();
+ io.seekg(-off, BOOST_IOS::end);
+ for (i = 0; i < data_reps; ++i, off -= chunk_size) {
+ for (int j = 0; j < chunk_size; ++j)
+ if (io.get() != narrow_data()[j])
+ return false;
+ io.seekg(-off, BOOST_IOS::end);
+ char buf[chunk_size];
+ io.read(buf, chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ }
+ return true;
+}
+
+bool test_output_seekable(std::ostream& io)
+{
+ int i; // old 'for' scope workaround.
+
+ // Test seeking with ios::cur
+ for (i = 0; i < data_reps; ++i) {
+ for (int j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ io.seekp(-chunk_size, BOOST_IOS::cur);
+ io.write(narrow_data(), chunk_size);
+ }
+
+ // Test seeking with ios::beg
+ std::streamoff off = 0;
+ io.seekp(0, BOOST_IOS::beg);
+ for (i = 0; i < data_reps; ++i, off += chunk_size) {
+ for (int j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ io.seekp(off, BOOST_IOS::beg);
+ io.write(narrow_data(), chunk_size);
+ }
+
+ // Test seeking with ios::end
+ io.seekp(0, BOOST_IOS::end);
+ off = io.tellp();
+ io.seekp(-off, BOOST_IOS::end);
+ for (i = 0; i < data_reps; ++i, off -= chunk_size) {
+ for (int j = 0; j < chunk_size; ++j)
+ io.put(narrow_data()[j]);
+ io.seekp(-off, BOOST_IOS::end);
+ io.write(narrow_data(), chunk_size);
+ }
+ return true;
+}
+
+} } } // End namespaces test, iostreams, boost.
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# pragma optimize("", on)
+#endif
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED
diff --git a/libs/iostreams/test/direct_adapter_test.cpp b/libs/iostreams/test/direct_adapter_test.cpp
new file mode 100644
index 0000000000..0be50b0868
--- /dev/null
+++ b/libs/iostreams/test/direct_adapter_test.cpp
@@ -0,0 +1,111 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <algorithm> // equal.
+#include <fstream>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/detail/adapter/direct_adapter.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+using namespace std;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+void direct_adapter_test()
+{
+
+ typedef boost::iostreams::detail::direct_adapter<array_source>
+ indirect_array_source;
+ typedef boost::iostreams::detail::direct_adapter<array_sink>
+ indirect_array_sink;
+ typedef boost::iostreams::detail::direct_adapter<array>
+ indirect_array;
+ typedef stream<indirect_array_source>
+ indirect_array_istream;
+ typedef stream<indirect_array_sink>
+ indirect_array_ostream;
+ typedef stream<indirect_array>
+ indirect_array_stream;
+
+ test_file test;
+ test_sequence<> seq;
+
+ //--------------indirect_array_istream------------------------------------//
+
+ {
+ indirect_array_istream first(&seq[0], &seq[0] + seq.size());
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from indirect_array_istream in chars"
+ );
+ }
+
+ {
+ indirect_array_istream first(&seq[0], &seq[0] + seq.size());
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from indirect_array_istream in chunks"
+ );
+ }
+
+ //--------------indirect_array_ostream------------------------------------//
+
+ {
+ vector<char> dest(data_reps * data_length(), '?');
+ indirect_array_ostream out(&dest[0], &dest[0] + dest.size());
+ write_data_in_chars(out);
+ BOOST_CHECK_MESSAGE(
+ std::equal(seq.begin(), seq.end(), dest.begin()),
+ "failed writing to indirect_array_ostream in chunks"
+ );
+ }
+
+ {
+ vector<char> dest(data_reps * data_length(), '?');
+ indirect_array_ostream out(&dest[0], &dest[0] + dest.size());
+ write_data_in_chunks(out);
+ BOOST_CHECK_MESSAGE(
+ std::equal(seq.begin(), seq.end(), dest.begin()),
+ "failed writing to indirect_array_ostream in chunks"
+ );
+ }
+
+ //--------------indirect_array_stream-------------------------------------//
+
+ {
+ vector<char> test(data_reps * data_length(), '?');
+ indirect_array_stream io(&test[0], &test[0] + test.size());
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within indirect_array_stream, in chars"
+ );
+ }
+
+ {
+ vector<char> test(data_reps * data_length(), '?');
+ indirect_array_stream io(&test[0], &test[0] + test.size());
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within indirect_array_stream, in chunks"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("direct_adapter test");
+ test->add(BOOST_TEST_CASE(&direct_adapter_test));
+ return test;
+}
diff --git a/libs/iostreams/test/example_test.cpp b/libs/iostreams/test/example_test.cpp
new file mode 100644
index 0000000000..24384422a4
--- /dev/null
+++ b/libs/iostreams/test/example_test.cpp
@@ -0,0 +1,461 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2005-2007 Jonathan Turkanis
+// 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.
+
+#include <map>
+#include <boost/iostreams/detail/ios.hpp> // failure.
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "../example/container_device.hpp"
+#include "../example/dictionary_filter.hpp"
+#include "../example/line_wrapping_filter.hpp"
+#include "../example/shell_comments_filter.hpp"
+#include "../example/tab_expanding_filter.hpp"
+#include "../example/unix2dos_filter.hpp"
+#include "./detail/verification.hpp"
+#include "./detail/sequence.hpp"
+#include "./detail/temp_file.hpp"
+
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
+namespace ex = boost::iostreams::example;
+
+//------------------container_device test-------------------------------------//
+
+void container_device_test()
+{
+ using namespace std;
+ using namespace boost::iostreams::test;
+
+ typedef vector<char> vector_type;
+ typedef ex::container_source<vector_type> vector_source;
+ typedef ex::container_sink<vector_type> vector_sink;
+ typedef ex::container_device<vector_type> vector_device;
+
+ {
+ test_sequence<> seq;
+ test_file file;
+ io::stream<vector_source> first(seq);
+ io::stream<io::file_source> second(file.name(), in_mode);
+ BOOST_CHECK(compare_streams_in_chunks(first, second));
+ }
+
+ {
+ std::vector<char> first;
+ test_sequence<> second;
+ io::stream<vector_sink> out(first);
+ write_data_in_chunks(out);
+ BOOST_CHECK(first == second);
+ }
+
+ {
+ vector<char> v;
+ io::stream<vector_device> io(v);
+ BOOST_CHECK(test_seekable_in_chunks(io));
+ }
+}
+
+//------------------dictionary_filter test------------------------------------//
+
+void dictionary_filter_test()
+{
+ using namespace std;
+
+ io::example::dictionary d;
+
+ // See http://english2american.com.
+ d.add("answerphone", "answering machine");
+ d.add("bloke", "guy");
+ d.add("gearbox", "transmission");
+ d.add("ironmonger", "hardware shop");
+ d.add("loo", "restroom");
+ d.add("lorry", "truck");
+ d.add("rubber", "eraser");
+ d.add("spanner", "monkey wrench");
+ d.add("telly", "TV");
+ d.add("tyre", "tire");
+ d.add("waistcoat", "vest");
+ d.add("windscreen", "windshield");
+
+ const std::string input = // Note: last character is non-alphabetic.
+ "I had a message on my answerphone from the bloke at the car "
+ "dealership that the windscreen and tyre on my lorry were replaced. "
+ "However, the gearbox would not be ready until tomorrow since the "
+ "spanner that they needed was broken and they had to go to the "
+ "ironmonger to buy a replacement. Since my lorry was not ready, "
+ "I decided to take the bus downtown and buy a new waistcoat. I "
+ "also stopped at the liquor store to buy some wine. I came home "
+ "and watched the telly and drank my wine. I also worked on a "
+ "crossword puzzle. Fortunately I had a pencil with a new rubber. "
+ "During that evening I made frequent trips to the loo due to my "
+ "excessive drinking";
+
+ const std::string output = // Note: last character is non-alphabetic.
+ "I had a message on my answering machine from the guy at the car "
+ "dealership that the windshield and tire on my truck were replaced. "
+ "However, the transmission would not be ready until tomorrow since "
+ "the monkey wrench that they needed was broken and they had to go to "
+ "the hardware shop to buy a replacement. Since my truck was not ready, "
+ "I decided to take the bus downtown and buy a new vest. I also stopped "
+ "at the liquor store to buy some wine. I came home and watched the TV "
+ "and drank my wine. I also worked on a crossword puzzle. Fortunately I "
+ "had a pencil with a new eraser. During that evening I made frequent "
+ "trips to the restroom due to my excessive drinking";
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::dictionary_stdio_filter(d),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::dictionary_stdio_filter(d),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::dictionary_input_filter(d),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::dictionary_output_filter(d),
+ input, output )
+ );
+}
+
+//------------------line_wrapping_filter test---------------------------------//
+
+void line_wrapping_filter_test()
+{
+ using namespace std;
+
+ const std::string input =
+ "I had a message on my answerphone from the bloke at the car \n"
+ "dealership that the windscreen and tyre on my lorry were replaced. \n"
+ "However, the gearbox would not be ready until tomorrow since the \n"
+ "spanner that they needed was broken and they had to go to the \n"
+ "ironmonger to buy a replacement. Since my lorry was not ready, \n"
+ "I decided to take the bus downtown and buy a new waistcoat. I \n"
+ "also stopped at the liquor store to buy some wine. I came home \n"
+ "and watched the telly and drank my wine. I also worked on a \n"
+ "crossword puzzle. Fortunately I had a pencil with a new rubber. \n"
+ "During that evening I made frequent trips to the loo due to my \n"
+ "excessive drinking.";
+
+ const std::string output =
+ "I had a message on my answerphone from t\n"
+ "he bloke at the car \n"
+ "dealership that the windscreen and tyre \n"
+ "on my lorry were replaced. \n"
+ "However, the gearbox would not be ready \n"
+ "until tomorrow since the \n"
+ "spanner that they needed was broken and \n"
+ "they had to go to the \n"
+ "ironmonger to buy a replacement. Since m\n"
+ "y lorry was not ready, \n"
+ "I decided to take the bus downtown and b\n"
+ "uy a new waistcoat. I \n"
+ "also stopped at the liquor store to buy \n"
+ "some wine. I came home \n"
+ "and watched the telly and drank my wine.\n"
+ " I also worked on a \n"
+ "crossword puzzle. Fortunately I had a pe\n"
+ "ncil with a new rubber. \n"
+ "During that evening I made frequent trip\n"
+ "s to the loo due to my \n"
+ "excessive drinking.";
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::line_wrapping_stdio_filter(40),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::line_wrapping_stdio_filter(40),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::line_wrapping_input_filter(40),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::line_wrapping_output_filter(40),
+ input, output )
+ );
+}
+
+//------------------shell_comments_filter test--------------------------------//
+
+void shell_comments_filter_test()
+{
+ using namespace std;
+
+ const std::string input = // From <libs/filesystem/build/Jamfile>.
+ "lib boost_filesystem\n"
+ " : ../src/$(SOURCES).cpp\n"
+ " : # build requirements\n"
+ " [ common-names ] # magic for install and auto-link features\n"
+ " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n"
+ " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n"
+ " : debug release # build variants\n"
+ " ;\n"
+ "\n"
+ "dll boost_filesystem\n"
+ " : ../src/$(SOURCES).cpp\n"
+ " : # build requirements\n"
+ " [ common-names ] # magic for install and auto-link features\n"
+ " <define>BOOST_FILESYSTEM_DYN_LINK=1 # tell source we're building dll's\n"
+ " <runtime-link>dynamic # build only for dynamic runtimes\n"
+ " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n"
+ " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n"
+ " : debug release # build variants\n"
+ " ;";
+
+ const std::string output =
+ "lib boost_filesystem\n"
+ " : ../src/$(SOURCES).cpp\n"
+ " : \n"
+ " [ common-names ] \n"
+ " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n"
+ " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n"
+ " : debug release \n"
+ " ;\n"
+ "\n"
+ "dll boost_filesystem\n"
+ " : ../src/$(SOURCES).cpp\n"
+ " : \n"
+ " [ common-names ] \n"
+ " <define>BOOST_FILESYSTEM_DYN_LINK=1 \n"
+ " <runtime-link>dynamic \n"
+ " <include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)\n"
+ " <no-warn>exception.cpp <no-warn>operations_posix_windows.cpp\n"
+ " : debug release \n"
+ " ;";
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::shell_comments_stdio_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::shell_comments_stdio_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::shell_comments_input_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::shell_comments_output_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::shell_comments_dual_use_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::shell_comments_dual_use_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::shell_comments_multichar_input_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::shell_comments_multichar_output_filter(),
+ input, output )
+ );
+}
+
+//------------------tab_expanding_filter test---------------------------------//
+
+void tab_expanding_filter_test()
+{
+ using namespace std;
+
+ const std::string input =
+ "class tab_expanding_stdio_filter : public stdio_filter {\n"
+ "public:\n"
+ "\texplicit tab_expanding_stdio_filter(int\ttab_size = 8)\n"
+ "\t\t: tab_size_(tab_size), col_no_(0)\n"
+ "\t{\n"
+ "\t\tassert(tab_size\t> 0);\n"
+ "\t}\n"
+ "private:\n"
+ "\tvoid do_filter()\n"
+ "\t{\n"
+ "\t\tint\tc;\n"
+ "\t\twhile ((c = std::cin.get()) != EOF) {\n"
+ "\t\t\tif (c == '\\t') {\n"
+ "\t\t\t\tint\tspaces = tab_size_ - (col_no_ %\ttab_size_);\n"
+ "\t\t\t\tfor\t(; spaces >\t0; --spaces)\n"
+ "\t\t\t\t\tput_char(' ');\n"
+ "\t\t\t} else {\n"
+ "\t\t\t\tput_char(c);\n"
+ "\t\t\t}\n"
+ "\t\t}\n"
+ "\t}\n"
+ "\tvoid do_close()\t{ col_no_ =\t0; }\n"
+ "\tvoid put_char(int c)\n"
+ "\t{\n"
+ "\t\tstd::cout.put(c);\n"
+ "\t\tif (c == '\\n') {\n"
+ "\t\t\tcol_no_\t= 0;\n"
+ "\t\t} else {\n"
+ "\t\t\t++col_no_;\n"
+ "\t\t}\n"
+ "\t}\n"
+ "\tint\t tab_size_;\n"
+ "\tint\t col_no_;\n"
+ "};";
+
+ const std::string output =
+ "class tab_expanding_stdio_filter : public stdio_filter {\n"
+ "public:\n"
+ " explicit tab_expanding_stdio_filter(int tab_size = 8)\n"
+ " : tab_size_(tab_size), col_no_(0)\n"
+ " {\n"
+ " assert(tab_size > 0);\n"
+ " }\n"
+ "private:\n"
+ " void do_filter()\n"
+ " {\n"
+ " int c;\n"
+ " while ((c = std::cin.get()) != EOF) {\n"
+ " if (c == '\\t') {\n"
+ " int spaces = tab_size_ - (col_no_ % tab_size_);\n"
+ " for (; spaces > 0; --spaces)\n"
+ " put_char(' ');\n"
+ " } else {\n"
+ " put_char(c);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " void do_close() { col_no_ = 0; }\n"
+ " void put_char(int c)\n"
+ " {\n"
+ " std::cout.put(c);\n"
+ " if (c == '\\n') {\n"
+ " col_no_ = 0;\n"
+ " } else {\n"
+ " ++col_no_;\n"
+ " }\n"
+ " }\n"
+ " int tab_size_;\n"
+ " int col_no_;\n"
+ "};";
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::tab_expanding_stdio_filter(4),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::tab_expanding_stdio_filter(4),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::tab_expanding_input_filter(4),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::tab_expanding_output_filter(4),
+ input, output )
+ );
+}
+
+//------------------unix2dos_filter test--------------------------------------//
+
+void unix2dos_filter_test()
+{
+ using namespace std;
+
+ const std::string input =
+ "When I was one-and-twenty\n"
+ "I heard a wise man say,\n"
+ "'Give crowns and pounds and guineas\n"
+ "But not your heart away;\n"
+ "\n"
+ "Give pearls away and rubies\n"
+ "But keep your fancy free.'\n"
+ "But I was one-and-twenty,\n"
+ "No use to talk to me.\n"
+ "\n"
+ "When I was one-and-twenty\n"
+ "I heard him say again,\n"
+ "'The heart out of the bosom\n"
+ "Was never given in vain;\n"
+ "'Tis paid with sighs a plenty\n"
+ "And sold for endless rue.'\n"
+ "And I am two-and-twenty,\n"
+ "And oh, 'tis true, 'tis true.";
+
+ const std::string output =
+ "When I was one-and-twenty\r\n"
+ "I heard a wise man say,\r\n"
+ "'Give crowns and pounds and guineas\r\n"
+ "But not your heart away;\r\n"
+ "\r\n"
+ "Give pearls away and rubies\r\n"
+ "But keep your fancy free.'\r\n"
+ "But I was one-and-twenty,\r\n"
+ "No use to talk to me.\r\n"
+ "\r\n"
+ "When I was one-and-twenty\r\n"
+ "I heard him say again,\r\n"
+ "'The heart out of the bosom\r\n"
+ "Was never given in vain;\r\n"
+ "'Tis paid with sighs a plenty\r\n"
+ "And sold for endless rue.'\r\n"
+ "And I am two-and-twenty,\r\n"
+ "And oh, 'tis true, 'tis true.";
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::unix2dos_stdio_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::unix2dos_stdio_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_input_filter( io::example::unix2dos_input_filter(),
+ input, output )
+ );
+
+ BOOST_CHECK(
+ io::test_output_filter( io::example::unix2dos_output_filter(),
+ input, output )
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("example test");
+ test->add(BOOST_TEST_CASE(&container_device_test));
+ test->add(BOOST_TEST_CASE(&dictionary_filter_test));
+ test->add(BOOST_TEST_CASE(&tab_expanding_filter_test));
+ test->add(BOOST_TEST_CASE(&line_wrapping_filter_test));
+ test->add(BOOST_TEST_CASE(&shell_comments_filter_test));
+ test->add(BOOST_TEST_CASE(&unix2dos_filter_test));
+ return test;
+}
diff --git a/libs/iostreams/test/execute_test.cpp b/libs/iostreams/test/execute_test.cpp
new file mode 100644
index 0000000000..d477c6792d
--- /dev/null
+++ b/libs/iostreams/test/execute_test.cpp
@@ -0,0 +1,660 @@
+/*
+ * 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.
+ *
+ * Tests the function templates boost::iostreams::detail::execute_all and
+ * boost::iostreams::detail::execute_foreach
+ *
+ * File: libs/iostreams/test/execute_test.cpp
+ * Date: Thu Dec 06 13:21:54 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#include <boost/iostreams/detail/execute.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::detail;
+using boost::unit_test::test_suite;
+
+// Function object that sets a boolean flag and returns a value
+// specified at construction
+template<typename Result>
+class operation {
+public:
+ typedef Result result_type;
+ explicit operation(Result r, bool& executed)
+ : r_(r), executed_(executed)
+ { }
+ Result operator()() const
+ {
+ executed_ = true;
+ return r_;
+ }
+private:
+ operation& operator=(const operation&);
+ Result r_;
+ bool& executed_;
+};
+
+// Specialization for void return
+template<>
+class operation<void> {
+public:
+ typedef void result_type;
+ explicit operation(bool& executed) : executed_(executed) { }
+ void operator()() const { executed_ = true; }
+private:
+ operation& operator=(const operation&);
+ bool& executed_;
+};
+
+// Simple exception class with error code built in to type
+template<int Code>
+struct error { };
+
+// Function object that sets a boolean flag and throws an exception
+template<int Code>
+class thrower {
+public:
+ typedef void result_type;
+ explicit thrower(bool& executed) : executed_(executed) { }
+ void operator()() const
+ {
+ executed_ = true;
+ throw error<Code>();
+ }
+private:
+ thrower& operator=(const thrower&);
+ bool& executed_;
+};
+
+// Function object for use by foreach_test
+class foreach_func {
+public:
+ typedef void result_type;
+ explicit foreach_func(int& count) : count_(count) { }
+ void operator()(int x) const
+ {
+ ++count_;
+ switch (x) {
+ case 0: throw error<0>();
+ case 1: throw error<1>();
+ case 2: throw error<2>();
+ case 3: throw error<3>();
+ case 4: throw error<4>();
+ case 5: throw error<5>();
+ case 6: throw error<6>();
+ case 7: throw error<7>();
+ case 8: throw error<8>();
+ case 9: throw error<9>();
+ default:
+ break;
+ }
+ }
+private:
+ foreach_func& operator=(const foreach_func&);
+ int& count_; // Number of times operator() has been called
+};
+
+void success_test()
+{
+ // Test returning an int
+ {
+ bool executed = false;
+ BOOST_CHECK(execute_all(operation<int>(9, executed)) == 9);
+ BOOST_CHECK(executed);
+ }
+
+ // Test returning void
+ {
+ bool executed = false;
+ execute_all(operation<void>(executed));
+ BOOST_CHECK(executed);
+ }
+
+ // Test returning an int with one cleanup operation
+ {
+ bool executed = false, cleaned_up = false;
+ BOOST_CHECK(
+ execute_all(
+ operation<int>(9, executed),
+ operation<void>(cleaned_up)
+ ) == 9
+ );
+ BOOST_CHECK(executed && cleaned_up);
+ }
+
+ // Test returning void with one cleanup operation
+ {
+ bool executed = false, cleaned_up = false;
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up)
+ );
+ BOOST_CHECK(executed && cleaned_up);
+ }
+
+ // Test returning an int with two cleanup operations
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK(
+ execute_all(
+ operation<int>(9, executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2)
+ ) == 9
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test returning void with two cleanup operations
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2)
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test returning an int with three cleanup operations
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK(
+ execute_all(
+ operation<int>(9, executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ) == 9
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test returning void with three cleanup operations
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+}
+
+void operation_throws_test()
+{
+ // Test primary operation throwing with no cleanup operations
+ {
+ bool executed = false;
+ BOOST_CHECK_THROW(
+ execute_all(thrower<0>(executed)),
+ error<0>
+ );
+ BOOST_CHECK(executed);
+ }
+
+ // Test primary operation throwing with one cleanup operation
+ {
+ bool executed = false, cleaned_up = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ operation<void>(cleaned_up)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up);
+ }
+
+ // Test primary operation throwing with two cleanup operations
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test primary operation throwing with three cleanup operations
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+}
+
+void cleanup_throws_test()
+{
+ // Test single cleanup operation that throws
+ {
+ bool executed = false, cleaned_up = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up);
+ }
+
+ // Test fist of two cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up1),
+ operation<void>(cleaned_up2)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test second of two cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up1),
+ thrower<2>(cleaned_up2)
+ ),
+ error<2>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test first of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test second of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up1),
+ thrower<2>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ),
+ error<2>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test third of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ thrower<3>(cleaned_up3)
+ ),
+ error<3>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+}
+
+void multiple_exceptions_test()
+{
+ // Test primary operation and cleanup operation throwing
+ {
+ bool executed = false, cleaned_up = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ thrower<1>(cleaned_up)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up);
+ }
+
+ // Test primary operation and first of two cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ thrower<1>(cleaned_up1),
+ operation<void>(cleaned_up2)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test primary operation and second of two cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ operation<void>(cleaned_up1),
+ thrower<2>(cleaned_up2)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test two cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false, cleaned_up2 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up1),
+ thrower<2>(cleaned_up2)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2);
+ }
+
+ // Test primary operation and first of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ thrower<1>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test primary operation and second of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ operation<void>(cleaned_up1),
+ thrower<2>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test primary operation and third of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ thrower<0>(executed),
+ operation<void>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ thrower<3>(cleaned_up3)
+ ),
+ error<0>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test first and second of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up1),
+ thrower<2>(cleaned_up2),
+ operation<void>(cleaned_up3)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test first and third of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up1),
+ operation<void>(cleaned_up2),
+ thrower<3>(cleaned_up3)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test second and third of three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ operation<void>(cleaned_up1),
+ thrower<2>(cleaned_up2),
+ thrower<3>(cleaned_up3)
+ ),
+ error<2>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+
+ // Test three cleanup operations throwing
+ {
+ bool executed = false, cleaned_up1 = false,
+ cleaned_up2 = false, cleaned_up3 = false;
+ BOOST_CHECK_THROW(
+ execute_all(
+ operation<void>(executed),
+ thrower<1>(cleaned_up1),
+ thrower<2>(cleaned_up2),
+ thrower<3>(cleaned_up3)
+ ),
+ error<1>
+ );
+ BOOST_CHECK(executed && cleaned_up1 && cleaned_up2 && cleaned_up3);
+ }
+}
+
+#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0]))
+
+void foreach_test()
+{
+ // Test case where neither of two operations throws
+ {
+ int count = 0;
+ int seq[] = {-1, -1};
+ BOOST_CHECK_NO_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count))
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where first of two operations throws
+ {
+ int count = 0;
+ int seq[] = {0, -1};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<0>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where second of two operations throws
+ {
+ int count = 0;
+ int seq[] = {-1, 1};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<1>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where both of two operations throw
+ {
+ int count = 0;
+ int seq[] = {0, 1};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<0>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where none of three operations throws
+ {
+ int count = 0;
+ int seq[] = {-1, -1, -1};
+ BOOST_CHECK_NO_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count))
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where first of three operations throw
+ {
+ int count = 0;
+ int seq[] = {0, -1, -1};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<0>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where second of three operations throw
+ {
+ int count = 0;
+ int seq[] = {-1, 1, -1};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<1>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where third of three operations throw
+ {
+ int count = 0;
+ int seq[] = {-1, -1, 2};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<2>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where first and second of three operations throw
+ {
+ int count = 0;
+ int seq[] = {0, 1, -1};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<0>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where first and third of three operations throw
+ {
+ int count = 0;
+ int seq[] = {0, -1, 2};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<0>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where second and third of three operations throw
+ {
+ int count = 0;
+ int seq[] = {-1, 1, 2};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<1>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+
+ // Test case where three of three operations throw
+ {
+ int count = 0;
+ int seq[] = {0, 1, 2};
+ BOOST_CHECK_THROW(
+ execute_foreach(seq, seq + ARRAY_SIZE(seq), foreach_func(count)),
+ error<0>
+ );
+ BOOST_CHECK(count == ARRAY_SIZE(seq));
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("execute test");
+ test->add(BOOST_TEST_CASE(&success_test));
+ test->add(BOOST_TEST_CASE(&operation_throws_test));
+ test->add(BOOST_TEST_CASE(&cleanup_throws_test));
+ test->add(BOOST_TEST_CASE(&multiple_exceptions_test));
+ test->add(BOOST_TEST_CASE(&foreach_test));
+ return test;
+}
diff --git a/libs/iostreams/test/file_descriptor_test.cpp b/libs/iostreams/test/file_descriptor_test.cpp
new file mode 100644
index 0000000000..2260f4f9f0
--- /dev/null
+++ b/libs/iostreams/test/file_descriptor_test.cpp
@@ -0,0 +1,642 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <fstream>
+#include <fcntl.h>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+#include "detail/file_handle.hpp"
+
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+namespace boost_ios = boost::iostreams;
+using std::ifstream;
+using boost::unit_test::test_suite;
+
+void file_descriptor_test()
+{
+
+ typedef stream<file_descriptor_source> fdistream;
+ typedef stream<file_descriptor_sink> fdostream;
+ typedef stream<file_descriptor> fdstream;
+
+ test_file test1;
+ test_file test2;
+
+ //--------------Test file_descriptor_source-------------------------------//
+
+ {
+ fdistream first(file_descriptor_source(test1.name()), 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from file_descriptor_source in chars with no buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ {
+ fdistream first(file_descriptor_source(test1.name()), 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from file_descriptor_source in chunks with no buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ {
+ file_descriptor_source file(test1.name());
+ fdistream first(file);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from file_descriptor_source in chars with buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ {
+ file_descriptor_source file(test1.name());
+ fdistream first(file);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from file_descriptor_source in chunks with buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ // test illegal flag combinations
+ {
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::app | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::out),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::out | BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::out | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_source(test1.name(),
+ BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ }
+
+ //--------------Test file_descriptor_sink---------------------------------//
+
+ {
+ temp_file temp;
+ file_descriptor_sink file(temp.name(), BOOST_IOS::trunc);
+ fdostream out(file, 0);
+ BOOST_CHECK(out->is_open());
+ write_data_in_chars(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chars with no buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ file_descriptor_sink file(temp.name(), BOOST_IOS::trunc);
+ fdostream out(file, 0);
+ BOOST_CHECK(out->is_open());
+ write_data_in_chunks(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chunks with no buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ file_descriptor_sink file(temp.name(), BOOST_IOS::trunc);
+ fdostream out(file);
+ BOOST_CHECK(out->is_open());
+ write_data_in_chars(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chars with buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ file_descriptor_sink file(temp.name(), BOOST_IOS::trunc);
+ fdostream out(file);
+ BOOST_CHECK(out->is_open());
+ write_data_in_chunks(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chunks with buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ // set up the tests
+ {
+ file_descriptor_sink file(temp.name(), BOOST_IOS::trunc);
+ fdostream out(file);
+ write_data_in_chunks(out);
+ out.close();
+ file.close();
+ }
+ // test std::ios_base::app
+ {
+ file_descriptor_sink file(temp.name(), BOOST_IOS::app);
+ fdostream out(file);
+ BOOST_CHECK(out->is_open());
+ write_data_in_chars(out);
+ out.close();
+ std::string expected(narrow_data());
+ expected += narrow_data();
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_file(expected, temp.name()),
+ "failed writing to file_descriptor_sink in append mode"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+ // test std::ios_base::trunc
+ {
+ file_descriptor_sink file(temp.name(), BOOST_IOS::trunc);
+ fdostream out(file);
+ BOOST_CHECK(out->is_open());
+ write_data_in_chars(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in trunc mode"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ // test illegal flag combinations
+ {
+ BOOST_CHECK_THROW(
+ file_descriptor_sink(temp.name(),
+ BOOST_IOS::trunc | BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_sink(temp.name(),
+ BOOST_IOS::in),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_sink(temp.name(),
+ BOOST_IOS::in | BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_sink(temp.name(),
+ BOOST_IOS::in | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor_sink(temp.name(),
+ BOOST_IOS::in | BOOST_IOS::trunc | BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ }
+ }
+
+ //--Test seeking with file_descriptor_source and file_descriptor_sink-----//
+
+ test_file test3;
+ {
+ file_descriptor_sink sink(test3.name());
+ fdostream out(sink);
+ BOOST_CHECK(out->is_open());
+ BOOST_CHECK_MESSAGE(
+ test_output_seekable(out),
+ "failed seeking within a file_descriptor_sink"
+ );
+ out->close();
+ BOOST_CHECK(!out->is_open());
+
+ file_descriptor_source source(test3.name());
+ fdistream in(source);
+ BOOST_CHECK(in->is_open());
+ BOOST_CHECK_MESSAGE(
+ test_input_seekable(in),
+ "failed seeking within a file_descriptor_source"
+ );
+ in->close();
+ BOOST_CHECK(!in->is_open());
+ }
+
+ //--------------Test file_descriptor--------------------------------------//
+
+ {
+ temp_file temp;
+ file_descriptor file( temp.name(),
+ BOOST_IOS::in |
+ BOOST_IOS::out |
+ BOOST_IOS::trunc |
+ BOOST_IOS::binary );
+ fdstream io(file, BUFSIZ);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within a file_descriptor, in chars"
+ );
+ }
+
+ {
+ temp_file temp;
+ file_descriptor file( temp.name(),
+ BOOST_IOS::in |
+ BOOST_IOS::out |
+ BOOST_IOS::trunc |
+ BOOST_IOS::binary );
+ fdstream io(file, BUFSIZ);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within a file_descriptor, in chunks"
+ );
+ }
+
+ //--------------Test read-only file_descriptor----------------------------//
+
+ {
+ fdstream first(file_descriptor(test1.name(), BOOST_IOS::in), 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ write_data_in_chars(first);
+ BOOST_CHECK(first.fail());
+ first.clear();
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from file_descriptor in chars with no buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ {
+ fdstream first(file_descriptor(test1.name(), BOOST_IOS::in), 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ write_data_in_chunks(first);
+ BOOST_CHECK(first.fail());
+ first.clear();
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from file_descriptor in chunks with no buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ {
+ file_descriptor file(test1.name(), BOOST_IOS::in);
+ fdstream first(file);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ write_data_in_chars(first);
+ BOOST_CHECK(first.fail());
+ first.clear();
+ first.seekg(0, BOOST_IOS::beg);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from file_descriptor in chars with buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ {
+ file_descriptor file(test1.name(), BOOST_IOS::in);
+ fdstream first(file);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK(first->is_open());
+ write_data_in_chunks(first);
+ BOOST_CHECK(first.fail());
+ first.clear();
+ first.seekg(0, BOOST_IOS::beg);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from file_descriptor in chunks with buffer"
+ );
+ first->close();
+ BOOST_CHECK(!first->is_open());
+ }
+
+ //--------------Test write-only file_descriptor---------------------------//
+ {
+ temp_file temp;
+ file_descriptor file( temp.name(),
+ BOOST_IOS::out |
+ BOOST_IOS::trunc );
+ fdstream out(file, 0);
+ BOOST_CHECK(out->is_open());
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ write_data_in_chars(out);
+ out.seekg(0, BOOST_IOS::beg);
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor in chars with no buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ file_descriptor file( temp.name(),
+ BOOST_IOS::out |
+ BOOST_IOS::trunc );
+ fdstream out(file, 0);
+ BOOST_CHECK(out->is_open());
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ write_data_in_chunks(out);
+ out.seekg(0, BOOST_IOS::beg);
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chunks with no buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ file_descriptor file( temp.name(),
+ BOOST_IOS::out |
+ BOOST_IOS::trunc );
+ fdstream out(file);
+ BOOST_CHECK(out->is_open());
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ write_data_in_chars(out);
+ out.seekg(0, BOOST_IOS::beg);
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chars with buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ {
+ temp_file temp;
+ file_descriptor file( temp.name(),
+ BOOST_IOS::out |
+ BOOST_IOS::trunc );
+ fdstream out(file);
+ BOOST_CHECK(out->is_open());
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ write_data_in_chunks(out);
+ out.seekg(0, BOOST_IOS::beg);
+ out.get();
+ BOOST_CHECK(out.fail());
+ out.clear();
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test1.name(), temp.name()),
+ "failed writing to file_descriptor_sink in chunks with buffer"
+ );
+ file.close();
+ BOOST_CHECK(!file.is_open());
+ }
+
+ // test illegal flag combinations
+ {
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::openmode(0)),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::app | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::in | BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::in | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::in | BOOST_IOS::app | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::out | BOOST_IOS::app | BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app),
+ BOOST_IOSTREAMS_FAILURE);
+ BOOST_CHECK_THROW(
+ file_descriptor(test1.name(),
+ BOOST_IOS::in |
+ BOOST_IOS::out |
+ BOOST_IOS::app |
+ BOOST_IOS::trunc),
+ BOOST_IOSTREAMS_FAILURE);
+ }
+}
+
+template <class FileDescriptor>
+void file_handle_test_impl(FileDescriptor*)
+{
+ test_file test1;
+ test_file test2;
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ {
+ FileDescriptor device1(handle, boost_ios::never_close_handle);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ {
+ FileDescriptor device1(handle, boost_ios::close_handle);
+ BOOST_CHECK(device1.handle() == handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ FileDescriptor device1(handle, boost_ios::never_close_handle);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ FileDescriptor device1(handle, boost_ios::close_handle);
+ BOOST_CHECK(device1.handle() == handle);
+ device1.close();
+ BOOST_CHECK(!device1.is_open());
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = open_file_handle(test2.name());
+ {
+ FileDescriptor device1(handle1, boost_ios::never_close_handle);
+ BOOST_CHECK(device1.handle() == handle1);
+ device1.open(handle2, boost_ios::never_close_handle);
+ BOOST_CHECK(device1.handle() == handle2);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ close_file_handle(handle1);
+ close_file_handle(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = open_file_handle(test2.name());
+ {
+ FileDescriptor device1(handle1, boost_ios::close_handle);
+ BOOST_CHECK(device1.handle() == handle1);
+ device1.open(handle2, boost_ios::close_handle);
+ BOOST_CHECK(device1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_CLOSED(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle1 = open_file_handle(test1.name());
+ boost_ios::detail::file_handle handle2 = open_file_handle(test2.name());
+ {
+ FileDescriptor device1(handle1, boost_ios::close_handle);
+ BOOST_CHECK(device1.handle() == handle1);
+ device1.open(handle2, boost_ios::never_close_handle);
+ BOOST_CHECK(device1.handle() == handle2);
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle1);
+ BOOST_CHECK_HANDLE_OPEN(handle2);
+ close_file_handle(handle2);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ {
+ FileDescriptor device1;
+ BOOST_CHECK(!device1.is_open());
+ device1.open(handle, boost_ios::never_close_handle);
+ BOOST_CHECK(device1.handle() == handle);
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ }
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ close_file_handle(handle);
+ }
+
+ {
+ boost_ios::detail::file_handle handle = open_file_handle(test1.name());
+ {
+ FileDescriptor device1;
+ BOOST_CHECK(!device1.is_open());
+ device1.open(handle, boost_ios::close_handle);
+ BOOST_CHECK(device1.handle() == handle);
+ BOOST_CHECK_HANDLE_OPEN(handle);
+ }
+ BOOST_CHECK_HANDLE_CLOSED(handle);
+ }
+}
+
+void file_handle_test()
+{
+ file_handle_test_impl((boost_ios::file_descriptor*) 0);
+ file_handle_test_impl((boost_ios::file_descriptor_source*) 0);
+ file_handle_test_impl((boost_ios::file_descriptor_sink*) 0);
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("file_descriptor test");
+ test->add(BOOST_TEST_CASE(&file_descriptor_test));
+ test->add(BOOST_TEST_CASE(&file_handle_test));
+ return test;
+}
diff --git a/libs/iostreams/test/file_test.cpp b/libs/iostreams/test/file_test.cpp
new file mode 100644
index 0000000000..ac5035bfa5
--- /dev/null
+++ b/libs/iostreams/test/file_test.cpp
@@ -0,0 +1,63 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/iostreams/device/file.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using std::ifstream;
+using boost::unit_test::test_suite;
+
+void file_test()
+{
+ test_file test;
+
+ //--------------Test file_source------------------------------------------//
+
+ {
+ file_source f(test.name());
+ BOOST_CHECK(f.is_open());
+ f.close();
+ BOOST_CHECK(!f.is_open());
+ f.open(test.name());
+ BOOST_CHECK(f.is_open());
+ }
+
+ //--------------Test file_sink--------------------------------------------//
+
+ {
+ file_sink f(test.name());
+ BOOST_CHECK(f.is_open());
+ f.close();
+ BOOST_CHECK(!f.is_open());
+ f.open(test.name());
+ BOOST_CHECK(f.is_open());
+ }
+
+ //--------------Test file-------------------------------------------------//
+
+ {
+ file f(test.name());
+ BOOST_CHECK(f.is_open());
+ f.close();
+ BOOST_CHECK(!f.is_open());
+ f.open(test.name());
+ BOOST_CHECK(f.is_open());
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("file test");
+ test->add(BOOST_TEST_CASE(&file_test));
+ return test;
+}
diff --git a/libs/iostreams/test/filter_test.cpp b/libs/iostreams/test/filter_test.cpp
new file mode 100644
index 0000000000..0f1b708993
--- /dev/null
+++ b/libs/iostreams/test/filter_test.cpp
@@ -0,0 +1,98 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <string>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/filters.hpp"
+
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+const std::string lower =
+ "in addition to providing an abstract framework the "
+ "library provides a number of concrete filters, sources "
+ "and sinks which serve as example applications of the "
+ "library but are also useful in their own right. these "
+ "include components for accessing memory-mapped files, "
+ "for file access via operating system file descriptors, "
+ "for code conversion, for text filtering with regular "
+ "expressions, for line-ending conversion and for "
+ "compression and decompression in the zlib, gzip and "
+ "bzip2 formats.";
+
+const std::string upper =
+ "IN ADDITION TO PROVIDING AN ABSTRACT FRAMEWORK THE "
+ "LIBRARY PROVIDES A NUMBER OF CONCRETE FILTERS, SOURCES "
+ "AND SINKS WHICH SERVE AS EXAMPLE APPLICATIONS OF THE "
+ "LIBRARY BUT ARE ALSO USEFUL IN THEIR OWN RIGHT. THESE "
+ "INCLUDE COMPONENTS FOR ACCESSING MEMORY-MAPPED FILES, "
+ "FOR FILE ACCESS VIA OPERATING SYSTEM FILE DESCRIPTORS, "
+ "FOR CODE CONVERSION, FOR TEXT FILTERING WITH REGULAR "
+ "EXPRESSIONS, FOR LINE-ENDING CONVERSION AND FOR "
+ "COMPRESSION AND DECOMPRESSION IN THE ZLIB, GZIP AND "
+ "BZIP2 FORMATS.";
+
+struct toupper_dual_use_filter : public dual_use_filter {
+ template<typename Source>
+ int get(Source& s)
+ {
+ int c = boost::iostreams::get(s);
+ return c != EOF && c != WOULD_BLOCK ?
+ std::toupper((unsigned char) c) :
+ c;
+ }
+ template<typename Sink>
+ bool put(Sink& s, char c)
+ {
+ return boost::iostreams::put(
+ s, (char) std::toupper((unsigned char) c)
+ );
+ }
+};
+
+struct tolower_dual_use_filter : public dual_use_filter {
+ template<typename Source>
+ int get(Source& s)
+ {
+ int c = boost::iostreams::get(s);
+ return c != EOF && c != WOULD_BLOCK ?
+ std::tolower((unsigned char) c) :
+ c;
+ }
+ template<typename Sink>
+ bool put(Sink& s, char c)
+ {
+ return boost::iostreams::put(
+ s, (char) std::tolower((unsigned char) c)
+ );
+ }
+};
+
+void filter_test()
+{
+ BOOST_CHECK(test_input_filter(toupper_filter(), lower, upper));
+ BOOST_CHECK(test_input_filter(toupper_multichar_filter(), lower, upper));
+ BOOST_CHECK(test_input_filter(toupper_dual_use_filter(), lower, upper));
+ BOOST_CHECK(test_output_filter(tolower_filter(), upper, lower));
+ BOOST_CHECK(test_output_filter(tolower_multichar_filter(), upper, lower));
+ BOOST_CHECK(test_output_filter(tolower_dual_use_filter(), upper, lower));
+ BOOST_CHECK(test_filter_pair(tolower_filter(), toupper_filter(), upper));
+ BOOST_CHECK(
+ test_filter_pair( tolower_multichar_filter(),
+ toupper_multichar_filter(), upper )
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("filter test");
+ test->add(BOOST_TEST_CASE(&filter_test));
+ return test;
+}
diff --git a/libs/iostreams/test/filtering_stream_flush_test.hpp b/libs/iostreams/test/filtering_stream_flush_test.hpp
new file mode 100644
index 0000000000..28b29060e1
--- /dev/null
+++ b/libs/iostreams/test/filtering_stream_flush_test.hpp
@@ -0,0 +1,36 @@
+// (C) Copyright 2011 Steven Watanabe
+// 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.
+
+#include <fstream>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void test_filtering_ostream_flush()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ lowercase_file lower;
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_filter());
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chars(out);
+ out.flush();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chars with an "
+ "output filter"
+ );
+ }
+}
diff --git a/libs/iostreams/test/filtering_stream_test.cpp b/libs/iostreams/test/filtering_stream_test.cpp
new file mode 100644
index 0000000000..be3e5205d4
--- /dev/null
+++ b/libs/iostreams/test/filtering_stream_test.cpp
@@ -0,0 +1,52 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/test/unit_test.hpp>
+#include "read_input_test.hpp"
+#include "read_bidir_test.hpp"
+#include "read_seekable_test.hpp"
+#include "read_bidir_streambuf_test.hpp"
+#include "read_input_istream_test.hpp"
+#include "write_output_test.hpp"
+#include "write_bidir_test.hpp"
+#include "write_seekable_test.hpp"
+#include "write_output_iterator_test.hpp"
+#include "write_bidir_streambuf_test.hpp"
+#include "write_output_ostream_test.hpp"
+#include "read_input_filter_test.hpp"
+#include "read_bidir_filter_test.hpp"
+#include "write_output_filter_test.hpp"
+#include "write_bidir_filter_test.hpp"
+#include "seek_test.hpp"
+#include "putback_test.hpp"
+#include "filtering_stream_flush_test.hpp"
+
+using boost::unit_test::test_suite;
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("filtering_stream test");
+ test->add(BOOST_TEST_CASE(&read_input_test));
+ test->add(BOOST_TEST_CASE(&read_bidirectional_test));
+ test->add(BOOST_TEST_CASE(&read_seekable_test));
+ test->add(BOOST_TEST_CASE(&read_bidirectional_streambuf_test));
+ test->add(BOOST_TEST_CASE(&read_input_istream_test));
+ test->add(BOOST_TEST_CASE(&write_output_test));
+ test->add(BOOST_TEST_CASE(&write_bidirectional_test));
+ test->add(BOOST_TEST_CASE(&write_seekable_test));
+ test->add(BOOST_TEST_CASE(&write_output_iterator_test));
+ test->add(BOOST_TEST_CASE(&write_bidirectional_streambuf_test));
+ test->add(BOOST_TEST_CASE(&write_output_ostream_test));
+ test->add(BOOST_TEST_CASE(&read_input_filter_test));
+ test->add(BOOST_TEST_CASE(&read_bidirectional_filter_test));
+ test->add(BOOST_TEST_CASE(&write_output_filter_test));
+ test->add(BOOST_TEST_CASE(&write_bidirectional_filter_test));
+ test->add(BOOST_TEST_CASE(&seek_test));
+ test->add(BOOST_TEST_CASE(&putback_test));
+ test->add(BOOST_TEST_CASE(&test_filtering_ostream_flush));
+ return test;
+}
diff --git a/libs/iostreams/test/finite_state_filter_test.cpp b/libs/iostreams/test/finite_state_filter_test.cpp
new file mode 100644
index 0000000000..698fc8b792
--- /dev/null
+++ b/libs/iostreams/test/finite_state_filter_test.cpp
@@ -0,0 +1,182 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2005-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_LOCALE
+# error std::locale not supported on this platform
+#else
+
+# include <map>
+# include <boost/iostreams/detail/ios.hpp> // failure.
+# include <boost/iostreams/filter/test.hpp>
+# include <boost/mpl/vector.hpp>
+# include <boost/test/test_tools.hpp>
+# include <boost/test/unit_test.hpp>
+# include "../example/finite_state_filter.hpp"
+
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
+
+const std::string posix = // 'unix' is sometimes a macro.
+ "When I was one-and-twenty\n"
+ "I heard a wise man say,\n"
+ "'Give crowns and pounds and guineas\n"
+ "But not your heart away;\n"
+ "\n"
+ "Give pearls away and rubies\n"
+ "But keep your fancy free.'\n"
+ "But I was one-and-twenty,\n"
+ "No use to talk to me.\n"
+ "\n"
+ "When I was one-and-twenty\n"
+ "I heard him say again,\n"
+ "'The heart out of the bosom\n"
+ "Was never given in vain;\n"
+ "'Tis paid with sighs a plenty\n"
+ "And sold for endless rue.'\n"
+ "And I am two-and-twenty,\n"
+ "And oh, 'tis true, 'tis true.";
+
+const std::string dos =
+ "When I was one-and-twenty\r\n"
+ "I heard a wise man say,\r\n"
+ "'Give crowns and pounds and guineas\r\n"
+ "But not your heart away;\r\n"
+ "\r\n"
+ "Give pearls away and rubies\r\n"
+ "But keep your fancy free.'\r\n"
+ "But I was one-and-twenty,\r\n"
+ "No use to talk to me.\r\n"
+ "\r\n"
+ "When I was one-and-twenty\r\n"
+ "I heard him say again,\r\n"
+ "'The heart out of the bosom\r\n"
+ "Was never given in vain;\r\n"
+ "'Tis paid with sighs a plenty\r\n"
+ "And sold for endless rue.'\r\n"
+ "And I am two-and-twenty,\r\n"
+ "And oh, 'tis true, 'tis true.";
+
+const std::string comments =
+ "When I was /*one-and-twenty\n"
+ "I he*/ard a wise/ man say,\n"
+ "'Give cr//*owns *and po**/unds and guineas\n"
+ "But n*/ot yo*/ur he/*a*/rt /**/away;\n";
+
+const std::string no_comments =
+ "When I was "
+ "ard a wise/ man say,\n"
+ "'Give cr/unds and guineas\n"
+ "But n*/ot yo*/ur hert away;\n";
+
+struct identity_fsm
+ : io::finite_state_machine<identity_fsm, char>
+{
+ void on_any(char c) { push(c); }
+ typedef boost::mpl::vector0<> transition_table;
+};
+
+struct dos2unix_fsm : io::finite_state_machine<dos2unix_fsm> {
+ BOOST_IOSTREAMS_FSM(dos2unix_fsm) // Define skip and push.
+ typedef dos2unix_fsm self;
+ typedef boost::mpl::vector<
+ row<initial_state, is<'\r'>, initial_state, &self::skip>,
+ row<initial_state, is_any, initial_state, &self::push>
+ > transition_table;
+};
+
+struct unix2dos_fsm : io::finite_state_machine<unix2dos_fsm> {
+ BOOST_IOSTREAMS_FSM(unix2dos_fsm) // Define skip and push.
+ typedef unix2dos_fsm self;
+
+ void on_lf(char) { push('\r'); push('\n'); }
+
+ typedef boost::mpl::vector<
+ row<initial_state, is<'\n'>, initial_state, &self::on_lf>,
+ row<initial_state, is_any, initial_state, &self::push>
+ > transition_table;
+};
+
+struct uncommenting_fsm : io::finite_state_machine<uncommenting_fsm> {
+ BOOST_IOSTREAMS_FSM(uncommenting_fsm) // Define skip and push.
+ typedef uncommenting_fsm self;
+
+ static const int no_comment = initial_state;
+ static const int pre_comment = no_comment + 1;
+ static const int comment = pre_comment + 1;
+ static const int post_comment = comment + 1;
+
+ void push_slash(char c) { push('/'); push(c); }
+
+ typedef boost::mpl::vector<
+ row<no_comment, is<'/'>, pre_comment, &self::skip>,
+ row<no_comment, is_any, no_comment, &self::push>,
+ row<pre_comment, is<'*'>, comment, &self::skip>,
+ row<pre_comment, is<'/'>, pre_comment, &self::push>,
+ row<pre_comment, is_any, no_comment, &self::push_slash>,
+ row<comment, is<'*'>, post_comment, &self::skip>,
+ row<comment, is_any, comment, &self::skip>,
+ row<post_comment, is<'/'>, no_comment, &self::skip>,
+ row<post_comment, is<'*'>, post_comment, &self::skip>,
+ row<post_comment, is_any, comment, &self::skip>
+ > transition_table;
+};
+
+void finite_state_filter_test()
+{
+ using namespace std;
+
+ typedef io::finite_state_filter<identity_fsm> identity_filter;
+ typedef io::finite_state_filter<dos2unix_fsm> dos2unix_filter;
+ typedef io::finite_state_filter<unix2dos_fsm> unix2dos_filter;
+ typedef io::finite_state_filter<uncommenting_fsm> uncommenting_filter;
+
+ // Test identity_filter.
+
+ BOOST_CHECK(
+ io::test_input_filter(identity_filter(), dos, dos)
+ );
+ BOOST_CHECK(
+ io::test_output_filter(identity_filter(), dos, dos)
+ );
+
+ // Test dos2unix_filter.
+
+ BOOST_CHECK(
+ io::test_input_filter(dos2unix_filter(), dos, posix)
+ );
+ BOOST_CHECK(
+ io::test_output_filter(dos2unix_filter(), dos, posix)
+ );
+
+ // Test unix2dos_filter.
+
+ BOOST_CHECK(
+ io::test_input_filter(unix2dos_filter(), posix, dos)
+ );
+ BOOST_CHECK(
+ io::test_output_filter(unix2dos_filter(), posix, dos)
+ );
+
+ // Test uncommenting_filter.
+
+ BOOST_CHECK(
+ io::test_input_filter(uncommenting_filter(), comments, no_comments)
+ );
+ BOOST_CHECK(
+ io::test_output_filter(uncommenting_filter(), comments, no_comments)
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("example test");
+ test->add(BOOST_TEST_CASE(&finite_state_filter_test));
+ return test;
+}
+
+#endif // #ifdef BOOST_NO_STD_LOCALE //---------------------------------------//
diff --git a/libs/iostreams/test/flush_test.cpp b/libs/iostreams/test/flush_test.cpp
new file mode 100644
index 0000000000..edb72ca3d9
--- /dev/null
+++ b/libs/iostreams/test/flush_test.cpp
@@ -0,0 +1,145 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <algorithm> // equal.
+#include <fstream>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/device/null.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/operations.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/filters.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;
+
+void flush_test()
+{
+ {
+ stream_buffer<null_sink> null;
+ null.open(null_sink());
+ BOOST_CHECK_MESSAGE(
+ iostreams::flush(null),
+ "failed flushing stream_buffer"
+ );
+ BOOST_CHECK_MESSAGE(
+ null.strict_sync(),
+ "failed strict-syncing stream_buffer with "
+ "non-flushable resource"
+ );
+ }
+
+ {
+ stream<null_sink> null;
+ null.open(null_sink());
+ BOOST_CHECK_MESSAGE(
+ iostreams::flush(null),
+ "failed flushing stream"
+ );
+ BOOST_CHECK_MESSAGE(
+ null.strict_sync(),
+ "failed strict-syncing stream with "
+ "non-flushable resource"
+ );
+ }
+
+ {
+ filtering_ostream null;
+ null.push(null_sink());
+ BOOST_CHECK_MESSAGE(
+ iostreams::flush(null),
+ "failed flushing filtering_ostream"
+ );
+ BOOST_CHECK_MESSAGE(
+ null.strict_sync(),
+ "failed strict-syncing filtering_ostream with "
+ "non-flushable resource"
+ );
+ }
+
+ {
+ filtering_ostream null;
+ null.push(tolower_filter());
+ null.push(null_sink());
+ BOOST_CHECK_MESSAGE(
+ iostreams::flush(null),
+ "failed flushing filtering_ostream with non-flushable filter"
+ );
+ BOOST_CHECK_MESSAGE(
+ !null.strict_sync(),
+ "strict-syncing filtering_ostream with "
+ "non-flushable filter succeeded"
+ );
+ }
+
+ {
+ vector<char> dest1;
+ vector<char> dest2;
+ filtering_ostream out;
+ out.set_auto_close(false);
+ out.push(flushable_output_filter());
+
+ // Write to dest1.
+ out.push(iostreams::back_inserter(dest1));
+ write_data_in_chunks(out);
+ out.flush();
+
+ // Write to dest2.
+ out.pop();
+ out.push(iostreams::back_inserter(dest2));
+ write_data_in_chunks(out);
+ out.flush();
+
+ BOOST_CHECK_MESSAGE(
+ dest1.size() == dest2.size() &&
+ std::equal(dest1.begin(), dest1.end(), dest2.begin()),
+ "failed flush filtering_ostream with auto_close disabled"
+ );
+ }
+
+ {
+ vector<char> dest1;
+ vector<char> dest2;
+ filtering_ostream out;
+ out.set_auto_close(false);
+ out.push(flushable_output_filter());
+ out.push(flushable_output_filter());
+
+ // Write to dest1.
+ out.push(iostreams::back_inserter(dest1));
+ write_data_in_chunks(out);
+ out.flush();
+
+ // Write to dest2.
+ out.pop();
+ out.push(iostreams::back_inserter(dest2));
+ write_data_in_chunks(out);
+ out.flush();
+
+ BOOST_CHECK_MESSAGE(
+ dest1.size() == dest2.size() &&
+ std::equal(dest1.begin(), dest1.end(), dest2.begin()),
+ "failed flush filtering_ostream with two flushable filters "
+ "with auto_close disabled"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("flush test");
+ test->add(BOOST_TEST_CASE(&flush_test));
+ return test;
+}
diff --git a/libs/iostreams/test/grep_test.cpp b/libs/iostreams/test/grep_test.cpp
new file mode 100644
index 0000000000..f9af490dd0
--- /dev/null
+++ b/libs/iostreams/test/grep_test.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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.
+
+ * File: libs/iostreams/test/grep_test.cpp
+ * Date: Mon May 26 17:48:45 MDT 2008
+ * Copyright: 2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ *
+ * Tests the class template basic_grep_filter.
+ */
+
+#include <iostream>
+
+#include <boost/config.hpp> // Make sure ptrdiff_t is in std.
+#include <algorithm>
+#include <cstddef> // std::ptrdiff_t
+#include <string>
+#include <boost/iostreams/compose.hpp>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/filter/grep.hpp>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/ref.hpp>
+#include <boost/regex.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost;
+using namespace boost::iostreams;
+namespace io = boost::iostreams;
+using boost::unit_test::test_suite;
+
+// List of addresses of US Appeals Courts, from uscourts.gov
+std::string addresses =
+ "John Joseph Moakley United States Courthouse, Suite 2500\n"
+ "One Courthouse Way\n"
+ "Boston, MA 02210-3002\n"
+ "\n"
+ "Thurgood Marshall United States Courthouse, 18th Floor\n"
+ "40 Centre Street\n"
+ "New York, NY 10007-1501\n"
+ "\n"
+ "21400 James A. Byrne United States Courthouse\n"
+ "601 Market Street\n"
+ "Philadelphia, PA 19106-1729\n"
+ "\n"
+ "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n"
+ "1100 East Main Street\n"
+ "Richmond, VA 23219-3525\n"
+ "\n"
+ "F. Edward Hebert Federal Bldg\n"
+ "600 South Maestri Place\n"
+ "New Orleans, LA 70130\n"
+ "\n"
+ "Bob Casey United States Courthouse, 1st Floor\n"
+ "515 Rusk Street\n"
+ "Houston, TX 77002-2600\n"
+ "\n"
+ "Potter Stewart United States Courthouse, Suite 540\n"
+ "100 East Fifth Street\n"
+ "Cincinnati, OH 45202\n"
+ "\n"
+ "2722 Everett McKinley Dirksen United States Courthouse\n"
+ "219 South Dearborn Street\n"
+ "Chicago, IL 60604\n";
+
+// Lines containing "United States Courthouse"
+std::string us_courthouse =
+ "John Joseph Moakley United States Courthouse, Suite 2500\n"
+ "Thurgood Marshall United States Courthouse, 18th Floor\n"
+ "21400 James A. Byrne United States Courthouse\n"
+ "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n"
+ "Bob Casey United States Courthouse, 1st Floor\n"
+ "Potter Stewart United States Courthouse, Suite 540\n"
+ "2722 Everett McKinley Dirksen United States Courthouse\n";
+
+// Lines not containing "United States Courthouse"
+std::string us_courthouse_inv =
+ "One Courthouse Way\n"
+ "Boston, MA 02210-3002\n"
+ "\n"
+ "40 Centre Street\n"
+ "New York, NY 10007-1501\n"
+ "\n"
+ "601 Market Street\n"
+ "Philadelphia, PA 19106-1729\n"
+ "\n"
+ "1100 East Main Street\n"
+ "Richmond, VA 23219-3525\n"
+ "\n"
+ "F. Edward Hebert Federal Bldg\n"
+ "600 South Maestri Place\n"
+ "New Orleans, LA 70130\n"
+ "\n"
+ "515 Rusk Street\n"
+ "Houston, TX 77002-2600\n"
+ "\n"
+ "100 East Fifth Street\n"
+ "Cincinnati, OH 45202\n"
+ "\n"
+ "219 South Dearborn Street\n"
+ "Chicago, IL 60604\n";
+
+// Lines containing a state and zip
+std::string state_and_zip =
+ "Boston, MA 02210-3002\n"
+ "New York, NY 10007-1501\n"
+ "Philadelphia, PA 19106-1729\n"
+ "Richmond, VA 23219-3525\n"
+ "New Orleans, LA 70130\n"
+ "Houston, TX 77002-2600\n"
+ "Cincinnati, OH 45202\n"
+ "Chicago, IL 60604\n";
+
+// Lines not containing a state and zip
+std::string state_and_zip_inv =
+ "John Joseph Moakley United States Courthouse, Suite 2500\n"
+ "One Courthouse Way\n"
+ "\n"
+ "Thurgood Marshall United States Courthouse, 18th Floor\n"
+ "40 Centre Street\n"
+ "\n"
+ "21400 James A. Byrne United States Courthouse\n"
+ "601 Market Street\n"
+ "\n"
+ "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n"
+ "1100 East Main Street\n"
+ "\n"
+ "F. Edward Hebert Federal Bldg\n"
+ "600 South Maestri Place\n"
+ "\n"
+ "Bob Casey United States Courthouse, 1st Floor\n"
+ "515 Rusk Street\n"
+ "\n"
+ "Potter Stewart United States Courthouse, Suite 540\n"
+ "100 East Fifth Street\n"
+ "\n"
+ "2722 Everett McKinley Dirksen United States Courthouse\n"
+ "219 South Dearborn Street\n";
+
+// Lines containing at least three words
+std::string three_words =
+ "John Joseph Moakley United States Courthouse, Suite 2500\n"
+ "One Courthouse Way\n"
+ "Thurgood Marshall United States Courthouse, 18th Floor\n"
+ "40 Centre Street\n"
+ "21400 James A. Byrne United States Courthouse\n"
+ "601 Market Street\n"
+ "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n"
+ "1100 East Main Street\n"
+ "F. Edward Hebert Federal Bldg\n"
+ "600 South Maestri Place\n"
+ "Bob Casey United States Courthouse, 1st Floor\n"
+ "515 Rusk Street\n"
+ "Potter Stewart United States Courthouse, Suite 540\n"
+ "100 East Fifth Street\n"
+ "2722 Everett McKinley Dirksen United States Courthouse\n"
+ "219 South Dearborn Street\n";
+
+// Lines containing exactly three words
+std::string exactly_three_words =
+ "One Courthouse Way\n"
+ "40 Centre Street\n"
+ "601 Market Street\n"
+ "515 Rusk Street\n";
+
+// Lines that don't contain exactly three words
+std::string exactly_three_words_inv =
+ "John Joseph Moakley United States Courthouse, Suite 2500\n"
+ "Boston, MA 02210-3002\n"
+ "\n"
+ "Thurgood Marshall United States Courthouse, 18th Floor\n"
+ "New York, NY 10007-1501\n"
+ "\n"
+ "21400 James A. Byrne United States Courthouse\n"
+ "Philadelphia, PA 19106-1729\n"
+ "\n"
+ "Lewis F. Powell, Jr. United States Courthouse Annex, Suite 501\n"
+ "1100 East Main Street\n"
+ "Richmond, VA 23219-3525\n"
+ "\n"
+ "F. Edward Hebert Federal Bldg\n"
+ "600 South Maestri Place\n"
+ "New Orleans, LA 70130\n"
+ "\n"
+ "Bob Casey United States Courthouse, 1st Floor\n"
+ "Houston, TX 77002-2600\n"
+ "\n"
+ "Potter Stewart United States Courthouse, Suite 540\n"
+ "100 East Fifth Street\n"
+ "Cincinnati, OH 45202\n"
+ "\n"
+ "2722 Everett McKinley Dirksen United States Courthouse\n"
+ "219 South Dearborn Street\n"
+ "Chicago, IL 60604\n";
+
+void test_filter( grep_filter grep,
+ const std::string& input,
+ const std::string& output );
+
+void grep_filter_test()
+{
+ regex match_us_courthouse("\\bUnited States Courthouse\\b");
+ regex match_state_and_zip("\\b[A-Z]{2}\\s+[0-9]{5}(-[0-9]{4})?\\b");
+ regex match_three_words("\\b\\w+\\s+\\w+\\s+\\w+\\b");
+ regex_constants::match_flag_type match_default =
+ regex_constants::match_default;
+
+ {
+ grep_filter grep(match_us_courthouse);
+ test_filter(grep, addresses, us_courthouse);
+ }
+
+ {
+ grep_filter grep(match_us_courthouse, match_default, grep::invert);
+ test_filter(grep, addresses, us_courthouse_inv);
+ }
+
+ {
+ grep_filter grep(match_state_and_zip);
+ test_filter(grep, addresses, state_and_zip);
+ }
+
+ {
+ grep_filter grep(match_state_and_zip, match_default, grep::invert);
+ test_filter(grep, addresses, state_and_zip_inv);
+ }
+
+ {
+ grep_filter grep(match_three_words);
+ test_filter(grep, addresses, three_words);
+ }
+
+ {
+ grep_filter grep(match_three_words, match_default, grep::whole_line);
+ test_filter(grep, addresses, exactly_three_words);
+ }
+
+ {
+ int options = grep::whole_line | grep::invert;
+ grep_filter grep(match_three_words, match_default, options);
+ test_filter(grep, addresses, exactly_three_words_inv);
+ }
+}
+
+void test_filter( grep_filter grep,
+ const std::string& input,
+ const std::string& output )
+{
+ // Count lines in output
+ std::ptrdiff_t count = std::count(output.begin(), output.end(), '\n');
+
+ // Test as input filter
+ {
+ array_source src(input.data(), input.data() + input.size());
+ std::string dest;
+ io::copy(compose(boost::ref(grep), src), io::back_inserter(dest));
+ BOOST_CHECK(dest == output);
+ BOOST_CHECK(grep.count() == count);
+ }
+
+ // Test as output filter
+ {
+ array_source src(input.data(), input.data() + input.size());
+ std::string dest;
+ io::copy(src, compose(boost::ref(grep), io::back_inserter(dest)));
+ BOOST_CHECK(dest == output);
+ BOOST_CHECK(grep.count() == count);
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("grep_filter test");
+ test->add(BOOST_TEST_CASE(&grep_filter_test));
+ return test;
+}
diff --git a/libs/iostreams/test/gzip_test.cpp b/libs/iostreams/test/gzip_test.cpp
new file mode 100644
index 0000000000..fc0eba790e
--- /dev/null
+++ b/libs/iostreams/test/gzip_test.cpp
@@ -0,0 +1,121 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <string>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/ref.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/sequence.hpp"
+#include "detail/verification.hpp"
+
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+namespace io = boost::iostreams;
+using boost::unit_test::test_suite;
+
+struct gzip_alloc : std::allocator<char> { };
+
+void compression_test()
+{
+ text_sequence data;
+
+ // Test compression and decompression with metadata
+ for (int i = 0; i < 4; ++i) {
+ gzip_params params;
+ if (i & 1) {
+ params.file_name = "original file name";
+ }
+ if (i & 2) {
+ params.comment = "detailed file description";
+ }
+ gzip_compressor out(params);
+ gzip_decompressor in;
+ BOOST_CHECK(
+ test_filter_pair( boost::ref(out),
+ boost::ref(in),
+ std::string(data.begin(), data.end()) )
+ );
+ BOOST_CHECK(in.file_name() == params.file_name);
+ BOOST_CHECK(in.comment() == params.comment);
+ }
+
+ // Test compression and decompression with custom allocator
+ BOOST_CHECK(
+ test_filter_pair( basic_gzip_compressor<gzip_alloc>(),
+ basic_gzip_decompressor<gzip_alloc>(),
+ std::string(data.begin(), data.end()) )
+ );
+}
+
+void multiple_member_test()
+{
+ text_sequence data;
+ std::vector<char> temp, dest;
+
+ // Write compressed data to temp, twice in succession
+ filtering_ostream out;
+ out.push(gzip_compressor());
+ out.push(io::back_inserter(temp));
+ io::copy(make_iterator_range(data), out);
+ out.push(io::back_inserter(temp));
+ io::copy(make_iterator_range(data), out);
+
+ // Read compressed data from temp into dest
+ filtering_istream in;
+ in.push(gzip_decompressor());
+ in.push(array_source(&temp[0], temp.size()));
+ io::copy(in, io::back_inserter(dest));
+
+ // Check that dest consists of two copies of data
+ BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size());
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin()));
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
+
+ dest.clear();
+ io::copy(
+ array_source(&temp[0], temp.size()),
+ io::compose(gzip_decompressor(), io::back_inserter(dest)));
+
+ // Check that dest consists of two copies of data
+ BOOST_REQUIRE_EQUAL(data.size() * 2, dest.size());
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin()));
+ BOOST_CHECK(std::equal(data.begin(), data.end(), dest.begin() + dest.size() / 2));
+}
+
+void array_source_test()
+{
+ std::string data = "simple test string.";
+ std::string encoded;
+
+ filtering_ostream out;
+ out.push(gzip_compressor());
+ out.push(io::back_inserter(encoded));
+ io::copy(make_iterator_range(data), out);
+
+ std::string res;
+ io::array_source src(encoded.data(),encoded.length());
+ io::copy(io::compose(io::gzip_decompressor(), src), io::back_inserter(res));
+
+ BOOST_CHECK_EQUAL(data, res);
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("gzip test");
+ test->add(BOOST_TEST_CASE(&compression_test));
+ test->add(BOOST_TEST_CASE(&multiple_member_test));
+ test->add(BOOST_TEST_CASE(&array_source_test));
+ return test;
+}
diff --git a/libs/iostreams/test/invert_test.cpp b/libs/iostreams/test/invert_test.cpp
new file mode 100644
index 0000000000..0621653f47
--- /dev/null
+++ b/libs/iostreams/test/invert_test.cpp
@@ -0,0 +1,70 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filter/test.hpp>
+#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;
+namespace io = boost::iostreams;
+
+void read_write_test()
+{
+
+ test_file test;
+ lowercase_file lower;
+ uppercase_file upper;
+
+ BOOST_CHECK( test_input_filter(
+ invert(tolower_filter()),
+ file_source(test.name(), in_mode),
+ file_source(lower.name(), in_mode) ) );
+
+ BOOST_CHECK( test_output_filter(
+ invert(toupper_filter()),
+ file_source(test.name(), in_mode),
+ 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(&read_write_test));
+ test->add(BOOST_TEST_CASE(&close_test));
+ return test;
+}
diff --git a/libs/iostreams/test/large_file_test.cpp b/libs/iostreams/test/large_file_test.cpp
new file mode 100644
index 0000000000..c6cc8d8526
--- /dev/null
+++ b/libs/iostreams/test/large_file_test.cpp
@@ -0,0 +1,446 @@
+/*
+ * 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.
+ *
+ * Tests seeking with a file_descriptor using large file offsets.
+ *
+ * File: libs/iostreams/test/large_file_test.cpp
+ * Date: Tue Dec 25 21:34:47 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#include <cstdio> // SEEK_SET, etc.
+#include <ctime>
+#include <string>
+#include <boost/config.hpp> // BOOST_STRINGIZE
+#include <boost/detail/workaround.hpp>
+#include <boost/iostreams/detail/config/rtl.hpp>
+#include <boost/iostreams/detail/config/windows_posix.hpp>
+#include <boost/iostreams/detail/execute.hpp>
+#include <boost/iostreams/detail/ios.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/device/mapped_file.hpp>
+#include <boost/iostreams/positioning.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+
+ // OS-specific headers for low-level i/o.
+
+#include <fcntl.h> // file opening flags.
+#include <sys/stat.h> // file access permissions.
+#ifdef BOOST_IOSTREAMS_WINDOWS
+# include <io.h> // low-level file i/o.
+# define WINDOWS_LEAN_AND_MEAN
+# include <windows.h>
+# ifndef INVALID_SET_FILE_POINTER
+# define INVALID_SET_FILE_POINTER ((DWORD)-1)
+# endif
+#else
+# include <sys/types.h> // mode_t.
+# include <unistd.h> // low-level file i/o.
+#endif
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using boost::unit_test::test_suite;
+
+//------------------Definition of constants-----------------------------------//
+
+const stream_offset gigabyte = 1073741824;
+const stream_offset file_size = // Some compilers complain about "8589934593"
+ gigabyte * static_cast<stream_offset>(8) + static_cast<stream_offset>(1);
+const int offset_list[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, // Seek by 1GB
+ 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 7, 6, 8, // Seek by 2GB
+ 6, 7, 5, 6, 4, 5, 3, 4, 2, 3, 1, 2,
+ 0, 3, 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, // Seek by 3GB
+ 5, 7, 4, 6, 3, 5, 2, 4, 1,
+ 0, 4, 1, 5, 2, 6, 3, 7, 4, 8, // Seek by 4GB
+ 4, 7, 3, 6, 2, 5, 1, 4,
+ 0, 5, 1, 6, 2, 7, 3, 8, 3, 7, 2, 6, 1, 5, // Seek by 5GB
+ 0, 6, 1, 7, 2, 8, 2, 7, 1, 6, // Seek by 6GB
+ 0, 7, 1, 8, 1, 7, // Seek by 7GB
+ 0, 8, 0 }; // Seek by 8GB
+const int offset_list_length = sizeof(offset_list) / sizeof(int);
+#ifdef LARGE_FILE_TEMP
+# define BOOST_FILE_NAME BOOST_STRINGIZE(LARGE_FILE_TEMP)
+# define BOOST_KEEP_FILE false
+#else
+# define BOOST_FILE_NAME BOOST_STRINGIZE(LARGE_FILE_KEEP)
+# define BOOST_KEEP_FILE true
+#endif
+
+//------------------Definition of remove_large_file---------------------------//
+
+// Removes the large file
+void remove_large_file()
+{
+#ifdef BOOST_IOSTREAMS_WINDOWS
+ DeleteFile(TEXT(BOOST_FILE_NAME));
+#else
+ unlink(BOOST_FILE_NAME);
+#endif
+}
+
+//------------------Definition of large_file_exists---------------------------//
+
+// Returns true if the large file exists, has the correct size, and has been
+// modified since the last commit affecting this source file; if the file exists
+// but is invalid, deletes the file.
+bool large_file_exists()
+{
+ // Last mod date
+ time_t last_mod;
+
+#ifdef BOOST_IOSTREAMS_WINDOWS
+
+ // Check existence
+ WIN32_FIND_DATA info;
+ HANDLE hnd = FindFirstFile(TEXT(BOOST_FILE_NAME), &info);
+ if (hnd == INVALID_HANDLE_VALUE)
+ return false;
+
+ // Check size
+ FindClose(hnd);
+ stream_offset size =
+ (static_cast<stream_offset>(info.nFileSizeHigh) << 32) +
+ static_cast<stream_offset>(info.nFileSizeLow);
+ if (size != file_size) {
+ remove_large_file();
+ return false;
+ }
+
+ // Fetch last mod date
+ SYSTEMTIME stime;
+ if (!FileTimeToSystemTime(&info.ftLastWriteTime, &stime)) {
+ remove_large_file();
+ return false;
+ }
+ tm ctime;
+ ctime.tm_year = stime.wYear - 1900;
+ ctime.tm_mon = stime.wMonth - 1;
+ ctime.tm_mday = stime.wDay;
+ ctime.tm_hour = stime.wHour;
+ ctime.tm_min = stime.wMinute;
+ ctime.tm_sec = stime.wSecond;
+ ctime.tm_isdst = 0;
+ last_mod = mktime(&ctime);
+
+#else
+
+ // Check existence
+ struct BOOST_IOSTREAMS_FD_STAT info;
+ if (BOOST_IOSTREAMS_FD_STAT(BOOST_FILE_NAME, &info))
+ return false;
+
+ // Check size
+ if (info.st_size != file_size) {
+ remove_large_file();
+ return false;
+ }
+
+ // Fetch last mod date
+ last_mod = info.st_mtime;
+
+#endif
+
+ // Fetch last mod date of this file ("large_file_test.cpp")
+ string timestamp =
+ "$Date: 2009-05-20 15:41:20 -0400 (Wed, 20 May 2009) $";
+ if (timestamp.size() != 53) { // Length of auto-generated SVN timestamp
+ remove_large_file();
+ return false;
+ }
+ tm commit;
+ try {
+ commit.tm_year = lexical_cast<int>(timestamp.substr(7, 4)) - 1900;
+ commit.tm_mon = lexical_cast<int>(timestamp.substr(12, 2)) - 1;
+ commit.tm_mday = lexical_cast<int>(timestamp.substr(15, 2));
+ commit.tm_hour = lexical_cast<int>(timestamp.substr(18, 2));
+ commit.tm_min = lexical_cast<int>(timestamp.substr(21, 2));
+ commit.tm_sec = lexical_cast<int>(timestamp.substr(24, 2));
+ } catch (const bad_lexical_cast&) {
+ remove_large_file();
+ return false;
+ }
+
+ // If last commit was two days or more before file timestamp, existing
+ // file is okay; otherwise, it must be regenerated (the two-day window
+ // compensates for time zone differences)
+ return difftime(last_mod, mktime(&commit)) >= 60 * 60 * 48;
+}
+
+//------------------Definition of map_large_file------------------------------//
+
+// Initializes the large file by mapping it in small segments. This is an
+// optimization for Win32; the straightforward implementation using WriteFile
+// and SetFilePointer (see the Borland workaropund below) is painfully slow.
+bool map_large_file()
+{
+ for (stream_offset z = 0; z <= 8; ++z) {
+ try {
+ mapped_file_params params;
+ params.path = BOOST_FILE_NAME;
+ params.offset = z * gigabyte;
+ params.length = 1;
+ params.mode = BOOST_IOS::out;
+ mapped_file file(params);
+ file.begin()[0] = z + 1;
+ } catch (const std::exception&) {
+ remove_large_file();
+ return false;
+ }
+ }
+ return true;
+}
+
+//------------------Definition of create_large_file---------------------------//
+
+// Creates and initializes the large file if it does not already exist. The file
+// looks like this:
+//
+// 0 1GB 2GB 3GB 4GB 5GB 6GB 7GB 8GB
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 1.....2.....3.....4.....5.....6.....7.....8.....9
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// where the characters 1-9 appear at offsets that are multiples of 1GB and the
+// dots represent uninitialized data.
+bool create_large_file()
+{
+ // If file exists, has correct size, and is recent, we're done
+ if (BOOST_KEEP_FILE && large_file_exists())
+ return true;
+
+#ifdef BOOST_IOSTREAMS_WINDOWS
+
+ // Create file
+ HANDLE hnd =
+ CreateFile(
+ TEXT(BOOST_FILE_NAME),
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if (!hnd)
+ return false;
+
+ // Set file pointer
+ LONG off_low = static_cast<LONG>(file_size & 0xffffffff);
+ LONG off_high = static_cast<LONG>(file_size >> 32);
+ if ( SetFilePointer(hnd, off_low, &off_high, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER &&
+ GetLastError() != NO_ERROR )
+ {
+ CloseHandle(hnd);
+ remove_large_file();
+ return false;
+ }
+
+ // Set file size
+ if (!SetEndOfFile(hnd)) {
+ CloseHandle(hnd);
+ remove_large_file();
+ return false;
+ }
+
+# if !defined(__BORLANDC__) || __BORLANDC__ < 0x582 || __BORLANDC__ >= 0x592
+
+ // Close handle; all further access is via mapped_file
+ CloseHandle(hnd);
+
+ // Initialize file data
+ return map_large_file();
+
+# else // Borland >= 5.8.2 and Borland < 5.9.2
+
+ // Initialize file data (very slow, even though only 9 writes are required)
+ for (stream_offset z = 0; z <= 8; ++z) {
+
+ // Seek
+ LONG off_low = static_cast<LONG>((z * gigabyte) & 0xffffffff); // == 0
+ LONG off_high = static_cast<LONG>((z * gigabyte) >> 32);
+ if ( SetFilePointer(hnd, off_low, &off_high, FILE_BEGIN) ==
+ INVALID_SET_FILE_POINTER &&
+ GetLastError() != NO_ERROR )
+ {
+ CloseHandle(hnd);
+ remove_large_file();
+ return false;
+ }
+
+ // Write a character
+ char buf[1] = { z + 1 };
+ DWORD result;
+ BOOL success = WriteFile(hnd, buf, 1, &result, NULL);
+ if (!success || result != 1) {
+ CloseHandle(hnd);
+ remove_large_file();
+ return false;
+ }
+ }
+
+ // Close file
+ CloseHandle(hnd);
+ return true;
+
+# endif // Borland workaround
+#else // #ifdef BOOST_IOSTREAMS_WINDOWS
+
+ // Create file
+ int oflag = O_WRONLY | O_CREAT;
+ #ifdef _LARGEFILE64_SOURCE
+ oflag |= O_LARGEFILE;
+ #endif
+ mode_t pmode =
+ S_IRUSR | S_IWUSR |
+ S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH;
+ int fd = BOOST_IOSTREAMS_FD_OPEN(BOOST_FILE_NAME, oflag, pmode);
+ if (fd == -1)
+ return false;
+
+ // Set file size
+ if (BOOST_IOSTREAMS_FD_TRUNCATE(fd, file_size)) {
+ BOOST_IOSTREAMS_FD_CLOSE(fd);
+ return false;
+ }
+
+# ifndef __CYGWIN__
+
+ // Initialize file data
+ for (int z = 0; z <= 8; ++z) {
+
+ // Seek
+ BOOST_IOSTREAMS_FD_OFFSET off =
+ BOOST_IOSTREAMS_FD_SEEK(
+ fd,
+ static_cast<BOOST_IOSTREAMS_FD_OFFSET>(z * gigabyte),
+ SEEK_SET
+ );
+ if (off == -1) {
+ BOOST_IOSTREAMS_FD_CLOSE(fd);
+ return false;
+ }
+
+ // Write a character
+ char buf[1] = { z + 1 };
+ if (BOOST_IOSTREAMS_FD_WRITE(fd, buf, 1) == -1) {
+ BOOST_IOSTREAMS_FD_CLOSE(fd);
+ return false;
+ }
+ }
+
+ // Close file
+ BOOST_IOSTREAMS_FD_CLOSE(fd);
+ return true;
+
+# else // Cygwin
+
+ // Close descriptor; all further access is via mapped_file
+ BOOST_IOSTREAMS_FD_CLOSE(fd);
+
+ // Initialize file data
+ return map_large_file();
+
+# endif
+#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
+}
+
+//------------------Definition of large_file----------------------------------//
+
+// RAII utility
+class large_file {
+public:
+ large_file() { exists_ = create_large_file(); }
+ ~large_file() { if (!BOOST_KEEP_FILE) remove_large_file(); }
+ bool exists() const { return exists_; }
+ const char* path() const { return BOOST_FILE_NAME; }
+private:
+ bool exists_;
+};
+
+//------------------Definition of check_character-----------------------------//
+
+// Verify that the given file contains the given character at the current
+// position
+bool check_character(file_descriptor_source& file, char value)
+{
+ char buf[1];
+ int amt;
+ BOOST_CHECK_NO_THROW(amt = file.read(buf, 1));
+ BOOST_CHECK_MESSAGE(amt == 1, "failed reading character");
+ BOOST_CHECK_NO_THROW(file.seek(-1, BOOST_IOS::cur));
+ return buf[0] == value;
+}
+
+//------------------Definition of large_file_test-----------------------------//
+
+void large_file_test()
+{
+ BOOST_REQUIRE_MESSAGE(
+ sizeof(stream_offset) >= 8,
+ "large offsets not supported"
+ );
+
+ // Prepare file and file descriptor
+ large_file large;
+ file_descriptor_source file;
+ BOOST_REQUIRE_MESSAGE(
+ large.exists(), "failed creating file \"" << BOOST_FILE_NAME << '"'
+ );
+ BOOST_CHECK_NO_THROW(file.open(large.path(), BOOST_IOS::binary));
+
+ // Test seeking using ios_base::beg
+ for (int z = 0; z < offset_list_length; ++z) {
+ char value = offset_list[z] + 1;
+ stream_offset off =
+ static_cast<stream_offset>(offset_list[z]) * gigabyte;
+ BOOST_CHECK_NO_THROW(file.seek(off, BOOST_IOS::beg));
+ BOOST_CHECK_MESSAGE(
+ check_character(file, value),
+ "failed validating seek"
+ );
+ }
+
+ // Test seeking using ios_base::end
+ for (int z = 0; z < offset_list_length; ++z) {
+ char value = offset_list[z] + 1;
+ stream_offset off =
+ -static_cast<stream_offset>(8 - offset_list[z]) * gigabyte - 1;
+ BOOST_CHECK_NO_THROW(file.seek(off, BOOST_IOS::end));
+ BOOST_CHECK_MESSAGE(
+ check_character(file, value),
+ "failed validating seek"
+ );
+ }
+
+ // Test seeking using ios_base::cur
+ for (int next, cur = 0, z = 0; z < offset_list_length; ++z, cur = next) {
+ next = offset_list[z];
+ char value = offset_list[z] + 1;
+ stream_offset off = static_cast<stream_offset>(next - cur) * gigabyte;
+ BOOST_CHECK_NO_THROW(file.seek(off, BOOST_IOS::cur));
+ BOOST_CHECK_MESSAGE(
+ check_character(file, value),
+ "failed validating seek"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("execute test");
+ test->add(BOOST_TEST_CASE(&large_file_test));
+ return test;
+}
diff --git a/libs/iostreams/test/line_filter_test.cpp b/libs/iostreams/test/line_filter_test.cpp
new file mode 100644
index 0000000000..2629daa15e
--- /dev/null
+++ b/libs/iostreams/test/line_filter_test.cpp
@@ -0,0 +1,99 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <cctype>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filter/line.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/constants.hpp"
+#include "detail/filters.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+// Must come last.
+#include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x.
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+struct toupper_line_filter : line_filter {
+ std::string do_filter(const std::string& line)
+ {
+ std::string result(line);
+ for ( std::string::size_type z = 0, len = line.size();
+ z < len;
+ ++z )
+ {
+ result[z] = std::toupper((unsigned char) result[z]);
+ }
+ return result;
+ }
+};
+
+bool compare_streams_in_lines(std::istream& first, std::istream& second)
+{
+ do {
+ std::string line_one;
+ std::string line_two;
+ std::getline(first, line_one);
+ std::getline(second, line_two);
+ if (line_one != line_two || first.eof() != second.eof())
+ return false;
+ } while (!first.eof());
+ return true;
+}
+
+void read_line_filter()
+{
+ test_file src;
+ uppercase_file upper;
+ filtering_istream first;
+ first.push(toupper_line_filter());
+ first.push(file_source(src.name(), in_mode));
+ ifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_lines(first, second),
+ "failed reading from a line_filter"
+ );
+}
+
+void write_line_filter()
+{
+ test_file data;
+ temp_file dest;
+ uppercase_file upper;
+
+ filtering_ostream out;
+ out.push(toupper_line_filter());
+ out.push(file_sink(dest.name(), out_mode));
+ copy(file_source(data.name(), in_mode), out);
+ out.reset();
+
+ ifstream first(dest.name().c_str());
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_lines(first, second),
+ "failed writing to a line_filter"
+ );
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("line_filter test");
+ test->add(BOOST_TEST_CASE(&read_line_filter));
+ test->add(BOOST_TEST_CASE(&write_line_filter));
+ return test;
+}
+
+#include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x.
+
diff --git a/libs/iostreams/test/mapped_file_test.cpp b/libs/iostreams/test/mapped_file_test.cpp
new file mode 100644
index 0000000000..b7dd0c8154
--- /dev/null
+++ b/libs/iostreams/test/mapped_file_test.cpp
@@ -0,0 +1,329 @@
+// (C) Copyright Jorge Lodos 2008
+// (C) Copyright Jonathan Turkanis 2004
+// 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.
+
+// This is the original (boost 1.34) boost::iostream test for the mapped files with the
+// following modifications:
+// 1. The namespace for the mapped file was changed to seglib::filemap.
+// 2. Added test for privately mapped files.
+// 3. The test test_writeable was added for mapped files.
+// 4. The test test_resizeable was added for mapped files.
+//
+
+#include <fstream>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/mapped_file.hpp>
+#include <boost/filesystem/path.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+// Code generation bugs cause tests to fail with global optimization.
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# pragma optimize("g", off)
+#endif
+
+namespace boost { namespace iostreams { namespace test {
+
+bool test_writeable(mapped_file& mf)
+{
+ // Test writing
+ for (int i = 0; i < data_reps; ++i) {
+ memcpy(mf.data(), narrow_data(), chunk_size);
+ char buf[chunk_size];
+ memcpy(buf, mf.const_data(), chunk_size);
+ if (strncmp(buf, narrow_data(), chunk_size) != 0)
+ return false;
+ memset(mf.data(), 0, chunk_size);
+ }
+ return true;
+}
+
+bool test_resizeable(mapped_file& mf)
+{
+ // Test resizing
+ mapped_file::size_type size = mf.size();
+ if (size == 0)
+ return false;
+ mf.resize(size/2);
+ if (mf.size() != size/2)
+ return false;
+ mf.resize(size);
+ if (mf.size() != size)
+ return false;
+ return true;
+}
+
+} } } // End namespaces test, iostreams, boost.
+
+void mapped_file_test()
+{
+ using namespace boost::iostreams;
+ BOOST_MESSAGE("about to begin");
+
+ //--------------Reading from a mapped_file_source-------------------------//
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a stream based on a mapped_file_source,
+ // in chars.
+ boost::iostreams::test::test_file test1, test2;
+ boost::iostreams::stream<mapped_file_source> first(test1.name());
+ {
+ std::ifstream second( test2.name().c_str(),
+ BOOST_IOS::in | BOOST_IOS::binary );
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_streams_in_chars(first, second),
+ "failed reading from stream<mapped_file_source> in chars"
+ );
+
+ BOOST_MESSAGE(
+ "done reading from stream<mapped_file_source> in chars"
+ );
+ }
+ first.close();
+
+ // Test reading from a stream based on a mapped_file_source,
+ // in chunks. (Also tests reopening the stream.)
+ first.open(mapped_file_source(test1.name()));
+ {
+ std::ifstream second( test2.name().c_str(),
+ BOOST_IOS::in | BOOST_IOS::binary );
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_streams_in_chunks(first, second),
+ "failed reading from stream<mapped_file_source> in chunks"
+ );
+
+ BOOST_MESSAGE(
+ "done reading from stream<mapped_file_source> in chunks"
+ );
+ }
+ }
+
+ //--------------Writing to a mapped_file_sink-----------------------------//
+
+ {
+ // Test writing to a stream based on a mapped_file_sink, in
+ // chars.
+ boost::iostreams::test::uppercase_file first, second; // Will overwrite these.
+ boost::iostreams::test::test_file test;
+
+ boost::iostreams::stream<mapped_file_sink> out;
+ out.open(mapped_file_sink(first.name()));
+ boost::iostreams::test::write_data_in_chars(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(first.name(), test.name()),
+ "failed writing to stream<mapped_file_sink> in chars"
+ );
+
+ BOOST_MESSAGE(
+ "done writing to stream<mapped_file_source> in chars"
+ );
+
+ // Test writing to a stream based on a mapped_file_sink, in
+ // chunks. (Also tests reopening the stream.)
+ out.open(mapped_file_sink(second.name()));
+ boost::iostreams::test::write_data_in_chunks(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(second.name(), test.name()),
+ "failed writing to stream<mapped_file_sink> in chunks"
+ );
+
+ BOOST_MESSAGE(
+ "done writing to stream<mapped_file_source> in chunks"
+ );
+ }
+
+ //--------------Writing to a newly created file---------------------------//
+
+ {
+ // Test writing to a newly created mapped file.
+ boost::iostreams::test::temp_file first, second;
+ boost::iostreams::test::test_file test;
+
+ mapped_file_params p(first.name());
+ p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length();
+ boost::iostreams::stream<mapped_file_sink> out;
+ out.open(mapped_file_sink(p));
+ boost::iostreams::test::write_data_in_chars(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(first.name(), test.name()),
+ "failed writing to newly created mapped file in chars"
+ );
+
+
+ // Test writing to a newly created mapped file.
+ // (Also tests reopening the stream.)
+ p.path = second.name();
+ out.open(mapped_file_sink(p));
+ boost::iostreams::test::write_data_in_chunks(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(second.name(), test.name()),
+ "failed writing to newly created mapped file in chunks"
+ );
+ }
+
+ //--------------Writing to a pre-existing file---------------------------//
+ {
+ // Test for Bug #3953 - writing to a pre-existing mapped file.
+ boost::iostreams::test::test_file first, test;
+
+ mapped_file_params p(first.name());
+ p.new_file_size = boost::iostreams::test::data_reps * boost::iostreams::test::data_length();
+ boost::iostreams::stream<mapped_file_sink> out;
+ out.open(mapped_file_sink(p));
+ boost::iostreams::test::write_data_in_chars(out);
+ out.close();
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(first.name(), test.name()),
+ "failed writing to pre-existing mapped file in chars"
+ );
+ }
+
+ //--------------Random access with a mapped_file--------------------------//
+
+ {
+ // Test reading, writing and seeking within a stream based on a
+ // mapped_file, in chars.
+ boost::iostreams::test::test_file test;
+ boost::iostreams::stream<mapped_file> io;
+ io.open(mapped_file(test.name()));
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_seekable_in_chars(io),
+ "failed seeking within stream<mapped_file> in chars"
+ );
+
+ BOOST_MESSAGE(
+ "done seeking within stream<mapped_file> in chars"
+ );
+
+ io.close();
+
+ // Test reading, writing and seeking within a stream based on a
+ // mapped_file, in chunks. (Also tests reopening the
+ // stream.)
+ io.open(mapped_file(test.name()));
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_seekable_in_chunks(io),
+ "failed seeking within stream<mapped_file> in chunks"
+ );
+
+ BOOST_MESSAGE(
+ "done seeking within stream<mapped_file> in chunks"
+ );
+ }
+
+ //--------------Resizing a mapped_file------------------------------------//
+
+ {
+ // Test resizing a mapped_file.
+ boost::iostreams::test::test_file test;
+ mapped_file mf;
+ mf.open(test.name());
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_resizeable(mf),
+ "failed resizing a mapped_file"
+ );
+
+ BOOST_MESSAGE(
+ "done resizing a mapped_file"
+ );
+ }
+
+ //--------------Random access with a private mapped_file------------------//
+
+ {
+ // Use 2 copies of the file to compare later
+ boost::iostreams::test::test_file orig, copy;
+
+ // Test reading and writing within a mapped_file.
+ // Since the file is privately mapped, it should remain
+ // unchanged after writing when opened in readonly mode.
+ mapped_file mf;
+ mf.open(orig.name(), mapped_file::priv);
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_writeable(mf),
+ "failed seeking within private mapped_file"
+ );
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(orig.name(), copy.name()),
+ "failed writing to private mapped_file"
+ );
+
+ BOOST_MESSAGE(
+ "done seeking within private mapped_file"
+ );
+
+ mf.close();
+
+ // Test reopening the mapped file.
+ mf.open(orig.name(), mapped_file::priv);
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_writeable(mf),
+ "failed reopening private mapped_file"
+ );
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::compare_files(orig.name(), copy.name()),
+ "failed writing to reopened private mapped_file"
+ );
+
+ BOOST_MESSAGE(
+ "done reopening private mapped_file"
+ );
+ }
+
+ //-------------Check creating opening mapped_file with char*-------------//
+
+ {
+ boost::iostreams::test::test_file orig;
+ char name[50];
+ std::strcpy(name, orig.name().c_str());
+
+ mapped_file mf((char*) name);
+
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_writeable(mf),
+ "failed seeking within private mapped_file"
+ );
+
+ mf.close();
+ }
+
+ //---------Check creating opening mapped_file with filesystem3 path------//
+ {
+ boost::iostreams::test::test_file orig;
+
+ mapped_file mf(boost::filesystem::path(orig.name()));
+
+ BOOST_CHECK_MESSAGE(
+ boost::iostreams::test::test_writeable(mf),
+ "failed seeking within private mapped_file"
+ );
+
+ mf.close();
+ }
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# pragma optimize("", on)
+#endif
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
+{
+ boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test");
+ test->add(BOOST_TEST_CASE(&mapped_file_test));
+ return test;
+}
diff --git a/libs/iostreams/test/newline_test.cpp b/libs/iostreams/test/newline_test.cpp
new file mode 100644
index 0000000000..ab0c4dae0d
--- /dev/null
+++ b/libs/iostreams/test/newline_test.cpp
@@ -0,0 +1,486 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <string>
+#include <boost/iostreams/compose.hpp>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/device/null.hpp>
+#include <boost/iostreams/filter/newline.hpp>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/utility/base_from_member.hpp>
+
+namespace io = boost::iostreams;
+using boost::unit_test::test_suite;
+
+const std::string posix =
+ "When I was one-and-twenty\n"
+ "I heard a wise man say,\n"
+ "'Give crowns and pounds and guineas\n"
+ "But not your heart away;\n"
+ "\n"
+ "Give pearls away and rubies\n"
+ "But keep your fancy free.'\n"
+ "But I was one-and-twenty,\n"
+ "No use to talk to me.\n"
+ "\n"
+ "When I was one-and-twenty\n"
+ "I heard him say again,\n"
+ "'The heart out of the bosom\n"
+ "Was never given in vain;\n"
+ "\n"
+ "'Tis paid with sighs a plenty\n"
+ "And sold for endless rue.'\n"
+ "And I am two-and-twenty,\n"
+ "And oh, 'tis true, 'tis true.\n";
+
+const std::string dos =
+ "When I was one-and-twenty\r\n"
+ "I heard a wise man say,\r\n"
+ "'Give crowns and pounds and guineas\r\n"
+ "But not your heart away;\r\n"
+ "\r\n"
+ "Give pearls away and rubies\r\n"
+ "But keep your fancy free.'\r\n"
+ "But I was one-and-twenty,\r\n"
+ "No use to talk to me.\r\n"
+ "\r\n"
+ "When I was one-and-twenty\r\n"
+ "I heard him say again,\r\n"
+ "'The heart out of the bosom\r\n"
+ "Was never given in vain;\r\n"
+ "\r\n"
+ "'Tis paid with sighs a plenty\r\n"
+ "And sold for endless rue.'\r\n"
+ "And I am two-and-twenty,\r\n"
+ "And oh, 'tis true, 'tis true.\r\n";
+
+const std::string mac =
+ "When I was one-and-twenty\r"
+ "I heard a wise man say,\r"
+ "'Give crowns and pounds and guineas\r"
+ "But not your heart away;\r"
+ "\r"
+ "Give pearls away and rubies\r"
+ "But keep your fancy free.'\r"
+ "But I was one-and-twenty,\r"
+ "No use to talk to me.\r"
+ "\r"
+ "When I was one-and-twenty\r"
+ "I heard him say again,\r"
+ "'The heart out of the bosom\r"
+ "Was never given in vain;\r"
+ "\r"
+ "'Tis paid with sighs a plenty\r"
+ "And sold for endless rue.'\r"
+ "And I am two-and-twenty,\r"
+ "And oh, 'tis true, 'tis true.\r";
+
+const std::string no_final_newline =
+ "When I was one-and-twenty\n"
+ "I heard a wise man say,\n"
+ "'Give crowns and pounds and guineas\n"
+ "But not your heart away;\n"
+ "\n"
+ "Give pearls away and rubies\n"
+ "But keep your fancy free.'\n"
+ "But I was one-and-twenty,\n"
+ "No use to talk to me.\n"
+ "\n"
+ "When I was one-and-twenty\n"
+ "I heard him say again,\n"
+ "'The heart out of the bosom\n"
+ "Was never given in vain;\n"
+ "\n"
+ "'Tis paid with sighs a plenty\n"
+ "And sold for endless rue.'\n"
+ "And I am two-and-twenty,\n"
+ "And oh, 'tis true, 'tis true.";
+
+const std::string mixed =
+ "When I was one-and-twenty\n"
+ "I heard a wise man say,\r\n"
+ "'Give crowns and pounds and guineas\r"
+ "But not your heart away;\n"
+ "\r\n"
+ "Give pearls away and rubies\r"
+ "But keep your fancy free.'\n"
+ "But I was one-and-twenty,\r\n"
+ "No use to talk to me.\r"
+ "\r"
+ "When I was one-and-twenty\r\n"
+ "I heard him say again,\r"
+ "'The heart out of the bosom\n"
+ "Was never given in vain;\r\n"
+ "\r"
+ "'Tis paid with sighs a plenty\n"
+ "And sold for endless rue.'\r\n"
+ "And I am two-and-twenty,\r"
+ "And oh, 'tis true, 'tis true.\n";
+
+struct string_source : boost::base_from_member<std::string>, io::array_source {
+ typedef io::array_source base_type;
+ typedef boost::base_from_member<std::string> pbase_type;
+ string_source(const std::string& src)
+ : pbase_type(src), base_type(member.data(), member.size())
+ { }
+
+ string_source(const string_source& src)
+ : pbase_type(src.member), base_type(member.data(), member.size())
+ { }
+};
+
+void read_newline_filter()
+{
+ using namespace io;
+
+ // Test converting to posix format.
+
+ BOOST_CHECK(test_input_filter(newline_filter(newline::posix), posix, posix));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::posix), dos, posix));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::posix), mac, posix));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::posix), mixed, posix));
+
+ // Test converting to dos format.
+
+ BOOST_CHECK(test_input_filter(newline_filter(newline::dos), posix, dos));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::dos), dos, dos));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::dos), mac, dos));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::dos), mixed, dos));
+
+ // Test converting to mac format.
+
+ BOOST_CHECK(test_input_filter(newline_filter(newline::mac), posix, mac));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::mac), dos, mac));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::mac), mac, mac));
+ BOOST_CHECK(test_input_filter(newline_filter(newline::mac), mixed, mac));
+}
+
+// Verify that a filter works as expected with both a non-blocking sink
+// and a normal output stream.
+//
+// test_output_filter only tests for a non-blocking sink.
+// TODO: Other tests should probably test with an output stream.
+
+template<typename Filter>
+bool my_test_output_filter(Filter filter,
+ const std::string& input,
+ const std::string& output)
+{
+ const std::streamsize default_increment = 5;
+
+ for ( int inc = default_increment;
+ inc < default_increment * 40;
+ inc += default_increment )
+ {
+ io::array_source src(input.data(), input.data() + input.size());
+
+ std::ostringstream stream;
+ io::copy(src, compose(filter, stream));
+ if (stream.str() != output )
+ return false;
+
+ }
+ return test_output_filter(filter, input, output);
+}
+
+void write_newline_filter()
+{
+ using namespace io;
+
+ // Test converting to posix format.
+
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), posix, posix));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), dos, posix));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), mac, posix));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::posix), mixed, posix));
+
+ // Test converting to dos format.
+
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), posix, dos));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), dos, dos));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), mac, dos));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::dos), mixed, dos));
+
+ // Test converting to mac format.
+
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), posix, mac));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), dos, mac));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), mac, mac));
+ BOOST_CHECK(my_test_output_filter(newline_filter(newline::mac), mixed, mac));
+}
+
+void test_input_against_flags(int flags, const std::string& input, bool read)
+{
+ if (read) {
+ io::copy(
+ io::compose(
+ io::newline_checker(flags),
+ string_source(input)
+ ),
+ io::null_sink()
+ );
+ } else {
+ io::copy(
+ string_source(input),
+ io::compose(io::newline_checker(flags), io::null_sink())
+ );
+ }
+}
+
+void read_newline_checker()
+{
+ io::filtering_istream in;
+ io::newline_checker* checker = 0;
+
+ // Verify properties of ::posix.
+
+ in.push(io::newline_checker(io::newline::posix));
+ in.push(string_source(::posix));
+ BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink()));
+ checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker);
+ BOOST_CHECK(checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ in.pop(); // pop checker.
+
+ // Verify properties of ::dos.
+
+ in.push(io::newline_checker(io::newline::dos));
+ in.push(string_source(::dos));
+ try {
+ io::copy(in, io::null_sink());
+ } catch (io::newline_error&) {
+ BOOST_CHECK_MESSAGE(
+ false, "failed checking for dos line endings"
+ );
+ }
+ checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker);
+ BOOST_CHECK(!checker->is_posix());
+ BOOST_CHECK(checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ in.pop(); // pop checker.
+
+ // Verify properties of ::mac.
+
+ in.push(io::newline_checker(io::newline::mac));
+ in.push(string_source(::mac));
+ BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink()));
+ checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker);
+ BOOST_CHECK(!checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ in.pop(); // pop checker.
+
+ // Verify properties of no_final_newline.
+
+ in.push(io::newline_checker(io::newline::posix));
+ in.push(string_source(::no_final_newline));
+ BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink()));
+ checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker);
+ BOOST_CHECK(checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(!checker->has_final_newline());
+ in.pop(); // pop checker.
+
+ // Verify properties of mixed.
+
+ in.push(io::newline_checker());
+ in.push(string_source(::mixed));
+ BOOST_CHECK_NO_THROW(io::copy(in, io::null_sink()));
+ checker = BOOST_IOSTREAMS_COMPONENT(in, 0, io::newline_checker);
+ BOOST_CHECK(!checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(checker->is_mixed_posix());
+ BOOST_CHECK(checker->is_mixed_dos());
+ BOOST_CHECK(checker->is_mixed_mac());
+ BOOST_CHECK(checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ in.pop(); // pop checker.
+
+ // Verify exceptions when input does not satisfy target conditions.
+
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::dos, ::posix, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::mac, ::posix, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::posix, ::dos, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::mac, ::dos, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::posix, ::mac, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::dos, ::mac, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::final_newline, ::no_final_newline, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::posix, ::mixed, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::dos, ::mixed, true),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::mac, ::mixed, true),
+ io::newline_error
+ )
+}
+
+void write_newline_checker()
+{
+ io::filtering_ostream out;
+ io::newline_checker* checker = 0;
+
+ // Verify properties of ::posix.
+
+ out.push(io::newline_checker(io::newline::posix));
+ out.push(io::null_sink());
+ BOOST_CHECK_NO_THROW(io::copy(string_source(::posix), out))
+ checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker);
+ BOOST_CHECK(checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ out.pop(); // pop checker.
+
+ // Verify properties of ::dos.
+
+ out.push(io::newline_checker(io::newline::dos));
+ out.push(io::null_sink());
+ BOOST_CHECK_NO_THROW(io::copy(string_source(::dos), out))
+ checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker);
+ BOOST_CHECK(!checker->is_posix());
+ BOOST_CHECK(checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ out.pop(); // pop checker.
+
+ // Verify properties of ::mac.
+
+ out.push(io::newline_checker(io::newline::mac));
+ out.push(io::null_sink());
+ BOOST_CHECK_NO_THROW(io::copy(string_source(::mac), out))
+ checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker);
+ BOOST_CHECK(!checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ out.pop(); // pop checker.
+
+ // Verify properties of no_final_newline.
+
+ out.push(io::newline_checker(io::newline::posix));
+ out.push(io::null_sink());
+ BOOST_CHECK_NO_THROW(io::copy(string_source(::no_final_newline), out))
+ checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker);
+ BOOST_CHECK(checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(!checker->is_mixed());
+ BOOST_CHECK(!checker->has_final_newline());
+ out.pop(); // pop checker.
+
+ // Verify properties of mixed.
+
+ out.push(io::newline_checker());
+ out.push(io::null_sink());
+ BOOST_CHECK_NO_THROW(io::copy(string_source(::mixed), out))
+ checker = BOOST_IOSTREAMS_COMPONENT(out, 0, io::newline_checker);
+ BOOST_CHECK(!checker->is_posix());
+ BOOST_CHECK(!checker->is_dos());
+ BOOST_CHECK(!checker->is_mac());
+ BOOST_CHECK(checker->is_mixed_posix());
+ BOOST_CHECK(checker->is_mixed_dos());
+ BOOST_CHECK(checker->is_mixed_mac());
+ BOOST_CHECK(checker->is_mixed());
+ BOOST_CHECK(checker->has_final_newline());
+ out.pop(); // pop checker.
+
+ // Verify exceptions when input does not satisfy target conditions.
+
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::dos, ::posix, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::mac, ::posix, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::posix, ::dos, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::mac, ::dos, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::posix, ::mac, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::dos, ::mac, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::final_newline, ::no_final_newline, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::posix, ::mixed, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::dos, ::mixed, false),
+ io::newline_error
+ )
+ BOOST_CHECK_THROW(
+ test_input_against_flags(io::newline::mac, ::mixed, false),
+ io::newline_error
+ )
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("newline_filter test");
+ test->add(BOOST_TEST_CASE(&read_newline_filter));
+ test->add(BOOST_TEST_CASE(&write_newline_filter));
+ test->add(BOOST_TEST_CASE(&read_newline_checker));
+ test->add(BOOST_TEST_CASE(&write_newline_checker));
+ return test;
+}
diff --git a/libs/iostreams/test/null_test.cpp b/libs/iostreams/test/null_test.cpp
new file mode 100644
index 0000000000..e90d18f832
--- /dev/null
+++ b/libs/iostreams/test/null_test.cpp
@@ -0,0 +1,44 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <cctype>
+#include <boost/iostreams/device/null.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.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;
+
+void read_null_source()
+{
+ stream<null_source> in;
+ in.open(null_source());
+ in.get();
+ BOOST_CHECK(in.eof());
+}
+
+void write_null_sink()
+{
+ stream<null_sink> out;
+ out.open(null_sink());
+ write_data_in_chunks(out);
+ BOOST_CHECK(out.good());
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("null test");
+ test->add(BOOST_TEST_CASE(&read_null_source));
+ test->add(BOOST_TEST_CASE(&write_null_sink));
+ return test;
+}
diff --git a/libs/iostreams/test/operation_sequence_test.cpp b/libs/iostreams/test/operation_sequence_test.cpp
new file mode 100644
index 0000000000..b03b8e0707
--- /dev/null
+++ b/libs/iostreams/test/operation_sequence_test.cpp
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ *
+ * Tests the facilities defined in the header
+ * libs/iostreams/test/detail/operation_sequence.hpp
+ *
+ * File: libs/iostreams/test/operation_sequence_test.cpp
+ * Date: Mon Dec 10 18:58:19 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ */
+
+#include <stdexcept>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/operation_sequence.hpp"
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+ // Infrastructure for checking that operations are
+ // executed in the correct order
+
+void operation_sequence_test()
+{
+ // Test creating a duplicate operation
+ {
+ operation_sequence seq;
+ operation op = seq.new_operation(1);
+ BOOST_CHECK_THROW(seq.new_operation(1), runtime_error);
+ }
+
+ // Test reusing an operation id after first operation is destroyed
+ {
+ operation_sequence seq;
+ seq.new_operation(1);
+ BOOST_CHECK_NO_THROW(seq.new_operation(1));
+ }
+
+ // Test creating operations with illegal error codes
+ {
+ operation_sequence seq;
+ BOOST_CHECK_THROW(seq.new_operation(1, -100), runtime_error);
+ BOOST_CHECK_THROW(
+ seq.new_operation(1, BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR + 1),
+ runtime_error
+ );
+ }
+
+ // Test two successful operations executed out of order
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op2 = seq.new_operation(2);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op2.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op1.execute());
+ BOOST_CHECK(seq.is_failure());
+ }
+
+ // Test executing an operation twice without resetting the sequence
+ {
+ operation_sequence seq;
+ operation op = seq.new_operation(1);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op.execute());
+ BOOST_CHECK(seq.is_success());
+ BOOST_CHECK_NO_THROW(op.execute());
+ BOOST_CHECK(seq.is_failure());
+ }
+
+ // Test creating an operation after operation execution has commenced
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op2 = seq.new_operation(2);
+ operation op3;
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op1.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_THROW(op3 = seq.new_operation(3), runtime_error);
+ BOOST_CHECK_NO_THROW(op2.execute());
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test three successful operations with consecutive ids, executed in order
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op2 = seq.new_operation(2);
+ operation op3 = seq.new_operation(3);
+
+ // First pass
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ BOOST_CHECK(seq.is_success());
+
+ // Second pass
+ seq.reset();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test three successful operations with non-consecutive ids,
+ // executed in order
+ {
+ operation_sequence seq;
+ operation op2 = seq.new_operation(2);
+ operation op3 = seq.new_operation(101);
+ operation op1 = seq.new_operation(-43);
+
+ // First pass
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ BOOST_CHECK(seq.is_success());
+
+ // Second pass
+ seq.reset();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test checking for success after one of three operations
+ // has been destroyed
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op3 = seq.new_operation(3);
+
+ {
+ operation op2 = seq.new_operation(2);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ }
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test executing an operation sequence twice, with one of the
+ // operations replaced with a new operation with the same id
+ // in the second pass
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op3 = seq.new_operation(3);
+
+ // First pass
+ {
+ operation op2 = seq.new_operation(2);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Second pass
+ seq.reset();
+ {
+ operation op2 = seq.new_operation(2);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op1.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op2.execute();
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ op3.execute();
+ BOOST_CHECK(seq.is_success());
+ }
+ }
+
+ // Test three operations executed in order, the first of which throws
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1, 1);
+ operation op2 = seq.new_operation(2);
+ operation op3 = seq.new_operation(3);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_THROW(op1.execute(), operation_error<1>);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op2.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op3.execute());
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test three operations executed in order, the second of which throws
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op2 = seq.new_operation(2, 2);
+ operation op3 = seq.new_operation(3);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op1.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_THROW(op2.execute(), operation_error<2>);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op3.execute());
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test three operations executed in order, the third of which throws
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1);
+ operation op2 = seq.new_operation(2);
+ operation op3 = seq.new_operation(3, 3);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op1.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op2.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_THROW(op3.execute(), operation_error<3>);
+ BOOST_CHECK(seq.is_success());
+ }
+
+ // Test three operations executed in order, the first and
+ // third of which throw
+ {
+ operation_sequence seq;
+ operation op1 = seq.new_operation(1, 1);
+ operation op2 = seq.new_operation(2);
+ operation op3 = seq.new_operation(3, 3);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_THROW(op1.execute(), operation_error<1>);
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_NO_THROW(op2.execute());
+ BOOST_CHECK(!seq.is_failure() && !seq.is_success());
+ BOOST_CHECK_THROW(op3.execute(), operation_error<3>);
+ BOOST_CHECK(seq.is_success());
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("execute test");
+ test->add(BOOST_TEST_CASE(&operation_sequence_test));
+ return test;
+}
diff --git a/libs/iostreams/test/path_test.cpp b/libs/iostreams/test/path_test.cpp
new file mode 100644
index 0000000000..313c851bc3
--- /dev/null
+++ b/libs/iostreams/test/path_test.cpp
@@ -0,0 +1,25 @@
+// (C) Copyright Daniel James 2011.
+// 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.
+
+#include <boost/iostreams/detail/path.hpp>
+#include <boost/filesystem/path.hpp>
+
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+void path_test()
+{
+ boost::filesystem::path orig("a/b");
+ boost::iostreams::detail::path p(orig);
+ p = orig;
+}
+
+boost::unit_test::test_suite* init_unit_test_suite(int, char* [])
+{
+ boost::unit_test::test_suite* test = BOOST_TEST_SUITE("mapped_file test");
+ test->add(BOOST_TEST_CASE(&path_test));
+ return test;
+}
diff --git a/libs/iostreams/test/pipeline_test.cpp b/libs/iostreams/test/pipeline_test.cpp
new file mode 100644
index 0000000000..2f621c7cf4
--- /dev/null
+++ b/libs/iostreams/test/pipeline_test.cpp
@@ -0,0 +1,90 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/filters.hpp"
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+using boost::unit_test::test_suite;
+
+void pipeline_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ {
+ test_file src;
+ filtering_istream
+ in1( toupper_filter() |
+ file_source(src.name()) );
+ filtering_istream
+ in2( toupper_filter() |
+ toupper_filter() |
+ file_source(src.name()) );
+ filtering_istream
+ in3( toupper_filter() |
+ toupper_filter() |
+ toupper_filter() |
+ file_source(src.name()) );
+ filtering_istream
+ in4( toupper_filter() |
+ toupper_filter() |
+ toupper_filter() |
+ toupper_filter() |
+ file_source(src.name()) );
+ BOOST_CHECK(in1.size() == 2);
+ BOOST_CHECK(in2.size() == 3);
+ BOOST_CHECK(in3.size() == 4);
+ BOOST_CHECK(in4.size() == 5);
+ }
+
+ {
+ test_file src;
+ uppercase_file upper;
+ filtering_istream
+ first( toupper_filter() |
+ toupper_multichar_filter() |
+ file_source(src.name(), in_mode) );
+ ifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a filtering_istream in chunks with a "
+ "multichar input filter"
+ );
+ }
+
+ {
+ temp_file dest;
+ lowercase_file lower;
+ filtering_ostream
+ out( tolower_filter() |
+ tolower_multichar_filter() |
+ file_sink(dest.name(), out_mode) );
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chunks with a "
+ "multichar output filter with no buffer"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("pipeline test");
+ test->add(BOOST_TEST_CASE(&pipeline_test));
+ return test;
+}
diff --git a/libs/iostreams/test/putback_test.hpp b/libs/iostreams/test/putback_test.hpp
new file mode 100644
index 0000000000..05b4f5addb
--- /dev/null
+++ b/libs/iostreams/test/putback_test.hpp
@@ -0,0 +1,167 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_PUTBACK_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_PUTBACK_HPP_INCLUDED
+
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/putback.hpp>
+#include "detail/constants.hpp"
+#include "detail/temp_file.hpp"
+
+using boost::iostreams::test::chunk_size;
+
+bool putback_test_one(std::istream& is)
+{
+ try {
+ do {
+ char buf[chunk_size];
+ is.read(buf, chunk_size);
+ if (is.gcount() < static_cast<std::streamsize>(chunk_size))
+ break;
+ is.putback('a');
+ if (is.get() != 'a')
+ return false;
+ } while (!is.eof());
+ return true;
+ } catch (std::exception&) { return false; }
+}
+
+bool putback_test_two(std::istream& is)
+{
+ try {
+ do {
+ char buf[chunk_size];
+ is.read(buf, chunk_size);
+ if (is.gcount() < static_cast<std::streamsize>(chunk_size))
+ break;
+ is.putback('a');
+ is.putback('b');
+ is.putback('c');
+ is.putback('d');
+ if ( is.get() != 'd' || is.get() != 'c' ||
+ is.get() != 'b' || is.get() != 'a' )
+ {
+ return false;
+ }
+ } while (!is.eof());
+ return true;
+ } catch (std::exception&) { return false; }
+}
+
+template<typename Source>
+bool putback_test_three(Source& src)
+{
+ try {
+ while (true) {
+ char buf[chunk_size];
+ if (boost::iostreams::read(src, buf, chunk_size) < chunk_size)
+ break;
+ boost::iostreams::putback(src, 'a');
+ if (boost::iostreams::get(src) != 'a')
+ return false;
+ }
+ return true;
+ } catch (std::exception&) { return false; }
+}
+
+template<typename Source>
+bool putback_test_four(Source& src)
+{
+ try {
+ while (true) {
+ char buf[chunk_size];
+ if (boost::iostreams::read(src, buf, chunk_size) < chunk_size)
+ break;
+ boost::iostreams::putback(src, 'a');
+ boost::iostreams::putback(src, 'b');
+ boost::iostreams::putback(src, 'c');
+ boost::iostreams::putback(src, 'd');
+ if ( boost::iostreams::get(src) != 'd' ||
+ boost::iostreams::get(src) != 'c' ||
+ boost::iostreams::get(src) != 'b' ||
+ boost::iostreams::get(src) != 'a' )
+ {
+ return false;
+ }
+ }
+ return true;
+ } catch (std::exception&) { return false; }
+}
+
+void putback_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ filtering_istream is;
+ is.set_device_buffer_size(0);
+ is.push(file_source(test.name()));
+ BOOST_CHECK_MESSAGE(
+ putback_test_one(is),
+ "failed putting back to unbuffered filtering_istream"
+ );
+ }
+
+ {
+ filtering_istream is;
+ is.set_pback_size(4);
+ is.push(file_source(test.name()));
+ BOOST_CHECK_MESSAGE(
+ putback_test_two(is),
+ "failed putting back to buffered filtering_istream"
+ );
+ }
+
+ {
+ filtering_istream is;
+ is.set_device_buffer_size(0);
+ is.push(file_source(test.name()));
+ BOOST_CHECK_MESSAGE(
+ putback_test_three(is),
+ "failed putting back to unbuffered filtering_istream"
+ );
+ }
+
+ {
+ filtering_istream is;
+ is.set_pback_size(4);
+ is.push(file_source(test.name()));
+ BOOST_CHECK_MESSAGE(
+ putback_test_four(is),
+ "failed putting back to buffered filtering_istream"
+ );
+ }
+
+ {
+ filtering_istreambuf sb;
+ sb.set_device_buffer_size(0);
+ sb.push(file_source(test.name()));
+ BOOST_CHECK_MESSAGE(
+ putback_test_three(sb),
+ "failed putting back to unbuffered filtering_istream"
+ );
+ }
+
+ {
+ filtering_istreambuf sb;
+ sb.set_pback_size(4);
+ sb.push(file_source(test.name()));
+ BOOST_CHECK_MESSAGE(
+ putback_test_four(sb),
+ "failed putting back to buffered filtering_istream"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_PUTBACK_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_bidir_filter_test.hpp b/libs/iostreams/test/read_bidir_filter_test.hpp
new file mode 100644
index 0000000000..b30a0cf00b
--- /dev/null
+++ b/libs/iostreams/test/read_bidir_filter_test.hpp
@@ -0,0 +1,131 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_FILTER_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_FILTER_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/combine.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/filters.hpp"
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_bidirectional_filter_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ uppercase_file upper;
+
+ //{
+ // test_file src;
+ // temp_file dest; // Dummy.
+ // filtering_stream<bidirectional> first;
+ // first.push(combine(toupper_filter(), tolower_filter()));
+ // first.push(
+ // combine(file_source(src.name()), file_sink(dest.name()))
+ // );
+ // ifstream second(upper.name().c_str());
+ // BOOST_CHECK_MESSAGE(
+ // compare_streams_in_chars(first, second),
+ // "failed reading from filtering_stream<bidirectional> in chars with an "
+ // "input filter"
+ // );
+ //}
+
+ {
+ test_file src;
+ temp_file dest; // Dummy.
+ filtering_stream<bidirectional> first;
+ first.push(combine(toupper_filter(), tolower_filter()));
+ first.push(
+ combine(file_source(src.name()), file_sink(dest.name()))
+ );
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<bidirectional> in chunks with an "
+ "input filter"
+ );
+ }
+
+ //{
+ // test_file src;
+ // temp_file dest; // Dummy.
+ // filtering_stream<bidirectional> first(
+ // combine(toupper_multichar_filter(), tolower_filter()), 0
+ // );
+ // first.push(
+ // combine(file_source(src.name()), file_sink(dest.name()))
+ // );
+ // ifstream second(upper.name().c_str());
+ // BOOST_CHECK_MESSAGE(
+ // compare_streams_in_chars(first, second),
+ // "failed reading from filtering_stream<bidirectional> in chars with "
+ // "a multichar input filter with no buffer"
+ // );
+ //}
+
+ //{
+ // test_file src;
+ // temp_file dest; // Dummy.
+ // filtering_stream<bidirectional> first(
+ // combine(toupper_multichar_filter(), tolower_filter()), 0
+ // );
+ // first.push(
+ // combine(file_source(src.name()), file_sink(dest.name()))
+ // );
+ // ifstream second(upper.name().c_str());
+ // BOOST_CHECK_MESSAGE(
+ // compare_streams_in_chunks(first, second),
+ // "failed reading from filtering_stream<bidirectional> in chunks "
+ // "with a multichar input filter with no buffer"
+ // );
+ //}
+
+ //{
+ // test_file src;
+ // temp_file dest; // Dummy.
+ // filtering_stream<bidirectional> first(
+ // combine(toupper_multichar_filter(), tolower_filter())
+ // );
+ // first.push(
+ // combine(file_source(src.name()), file_sink(dest.name()))
+ // );
+ // ifstream second(upper.name().c_str());
+ // BOOST_CHECK_MESSAGE(
+ // compare_streams_in_chars(first, second),
+ // "failed reading from filtering_stream<bidirectional> in chars with a "
+ // "multichar input filter"
+ // );
+ //}
+
+ //{
+ // test_file src;
+ // temp_file dest; // Dummy.
+ // filtering_stream<bidirectional> first(
+ // combine(toupper_multichar_filter(), tolower_filter())
+ // );
+ // first.push(
+ // combine(file_source(src.name()), file_sink(dest.name()))
+ // );
+ // ifstream second(upper.name().c_str());
+ // BOOST_CHECK_MESSAGE(
+ // compare_streams_in_chunks(first, second),
+ // "failed reading from filtering_stream<bidirectional> in chunks "
+ // "with a multichar input filter"
+ // );
+ //}
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_FILTER_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_bidir_streambuf_test.hpp b/libs/iostreams/test/read_bidir_streambuf_test.hpp
new file mode 100644
index 0000000000..4a14cad248
--- /dev/null
+++ b/libs/iostreams/test/read_bidir_streambuf_test.hpp
@@ -0,0 +1,77 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_bidirectional_streambuf_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test1;
+ test_file test2;
+
+ {
+ filebuf fb;
+ fb.open(test1.name().c_str(), BOOST_IOS::in);
+ filtering_stream<bidirectional> first(fb, 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<bidirectional> based on a"
+ "streambuf in chars with no buffer"
+ );
+ }
+
+ {
+ filebuf fb;
+ fb.open(test1.name().c_str(), BOOST_IOS::in);
+ filtering_stream<bidirectional> first(fb, 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<bidirectional> based on a"
+ "streambuf in chunks with no buffer"
+ );
+ }
+
+ {
+ filebuf fb;
+ fb.open(test1.name().c_str(), BOOST_IOS::in);
+ filtering_stream<bidirectional> first(fb);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<bidirectional> based on a"
+ "streambuf in chars with large buffer"
+ );
+ }
+
+ {
+ filebuf fb;
+ fb.open(test1.name().c_str(), BOOST_IOS::in);
+ filtering_stream<bidirectional> first(fb);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<bidirectional> based on a"
+ "streambuf in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_bidir_test.hpp b/libs/iostreams/test/read_bidir_test.hpp
new file mode 100644
index 0000000000..8351bd16e0
--- /dev/null
+++ b/libs/iostreams/test/read_bidir_test.hpp
@@ -0,0 +1,85 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/combine.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_bidirectional_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ test_file src;
+ temp_file dest; // Dummy.
+ filtering_stream<bidirectional> first(
+ combine(file_source(src.name()), file_sink(dest.name())), 0
+ );
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<bidirectional>"
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ test_file src;
+ temp_file dest; // Dummy.
+ filtering_stream<bidirectional> first(
+ combine(file_source(src.name()), file_sink(dest.name())), 0
+ );
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<bidirectional>"
+ "in chunks with no buffer"
+ );
+ }
+
+ {
+ test_file src;
+ temp_file dest; // Dummy.
+ filtering_stream<bidirectional> first(
+ combine(file_source(src.name()), file_sink(dest.name()))
+ );
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<bidirectional>"
+ "in chars with large buffer"
+ );
+ }
+
+ {
+ test_file src;
+ temp_file dest; // Dummy.
+ filtering_stream<bidirectional> first(
+ combine(file_source(src.name()), file_sink(dest.name()))
+ );
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<bidirectional>"
+ "in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_BIDIRECTIONAL_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_input_filter_test.hpp b/libs/iostreams/test/read_input_filter_test.hpp
new file mode 100644
index 0000000000..7057546231
--- /dev/null
+++ b/libs/iostreams/test/read_input_filter_test.hpp
@@ -0,0 +1,105 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_FILTER_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_INPUT_FILTER_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/filters.hpp"
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_input_filter_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+ uppercase_file upper;
+
+ {
+ filtering_istream first;
+ first.push(toupper_filter());
+ first.push(file_source(test.name()));
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a filtering_istream in chars with an "
+ "input filter"
+ );
+ }
+
+ {
+ filtering_istream first;
+ first.push(toupper_filter());
+ first.push(file_source(test.name()));
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a filtering_istream in chunks with an "
+ "input filter"
+ );
+ }
+
+ {
+ filtering_istream first;
+ first.push(toupper_multichar_filter(), 0);
+ first.push(file_source(test.name()));
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a filtering_istream in chars with a "
+ "multichar input filter with no buffer"
+ );
+ }
+
+ {
+ filtering_istream first;
+ first.push(toupper_multichar_filter(), 0);
+ first.push(file_source(test.name()));
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a filtering_istream in chunks with a "
+ "multichar input filter with no buffer"
+ );
+ }
+
+ {
+ test_file src;
+ filtering_istream first;
+ first.push(toupper_multichar_filter());
+ first.push(file_source(src.name()));
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a filtering_istream in chars with a "
+ "multichar input filter"
+ );
+ }
+
+ {
+ test_file src;
+ filtering_istream first;
+ first.push(toupper_multichar_filter());
+ first.push(file_source(src.name()));
+ ifstream second(upper.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a filtering_istream in chunks with a "
+ "multichar input filter"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_FILTER_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_input_istream_test.hpp b/libs/iostreams/test/read_input_istream_test.hpp
new file mode 100644
index 0000000000..fa1552253f
--- /dev/null
+++ b/libs/iostreams/test/read_input_istream_test.hpp
@@ -0,0 +1,76 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_ISTREAM_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_INPUT_ISTREAM_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_input_istream_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+ test_file test2;
+
+ {
+ test_file test2;
+ ifstream src(test2.name().c_str());
+ filtering_istream first(src, 0);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_istream based on an istream"
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ test_file test2;
+ ifstream src(test2.name().c_str());
+ filtering_istream first(src, 0);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_istream based on an istream"
+ "in chunks with no buffer"
+ );
+ }
+
+ {
+ test_file test2;
+ ifstream src(test2.name().c_str());
+ filtering_istream first(src);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_istream based on an istream"
+ "in chars with large buffer"
+ );
+ }
+
+ {
+ test_file test2;
+ ifstream src(test2.name().c_str());
+ filtering_istream first(src);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_istream based on an istream"
+ "in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_ISTREAM_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_input_seq_test.hpp b/libs/iostreams/test/read_input_seq_test.hpp
new file mode 100644
index 0000000000..f26f833de5
--- /dev/null
+++ b/libs/iostreams/test/read_input_seq_test.hpp
@@ -0,0 +1,70 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_SEQUENCE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_INPUT_SEQUENCE_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_input_sequence_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file file;
+ test_sequence<> seq;
+
+ {
+ filtering_stream<input> first(make_iterator_range(seq), 0);
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from range_adapter "
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_stream<input> first(make_iterator_range(seq), 0);
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from range_adapter "
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_stream<input> first(make_iterator_range(seq));
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from range_adapter "
+ "in chars with large buffer"
+ );
+ }
+
+ {
+ filtering_stream<input> first(make_iterator_range(seq));
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from range_adapter "
+ "in chars with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_SEQUENCE_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_input_test.hpp b/libs/iostreams/test/read_input_test.hpp
new file mode 100644
index 0000000000..e8e0015beb
--- /dev/null
+++ b/libs/iostreams/test/read_input_test.hpp
@@ -0,0 +1,65 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_INPUT_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_input_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test1;
+ test_file test2;
+
+ {
+ filtering_istream first(file_source(test1.name()), 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_istream in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_istream first(file_source(test1.name()), 0);
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_istream in chunks with no buffer"
+ );
+ }
+
+ {
+ filtering_istream first(file_source(test1.name()));
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_istream in chars with buffer"
+ );
+ }
+
+ {
+ filtering_istream first(file_source(test1.name()));
+ ifstream second(test2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_istream in chunks with buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_INPUT_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_seekable_seq_test.hpp b/libs/iostreams/test/read_seekable_seq_test.hpp
new file mode 100644
index 0000000000..185d15d8dc
--- /dev/null
+++ b/libs/iostreams/test/read_seekable_seq_test.hpp
@@ -0,0 +1,71 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_SEQUENCE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_SEEKABLE_SEQUENCE_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_seekable_sequence_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file file;
+ test_sequence<> seq;
+
+ {
+ filtering_stream<seekable> first(make_iterator_range(seq), 0);
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<seekable> based on a"
+ "sequence in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_stream<seekable> first(make_iterator_range(seq), 0);
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<seekable> based on a"
+ "sequence in chunks with no buffer"
+ );
+ }
+
+ {
+ filtering_stream<seekable> first(make_iterator_range(seq));
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<seekable> based on a"
+ "sequence in chars with large buffer"
+ );
+ }
+
+ {
+ filtering_stream<seekable> first(make_iterator_range(seq));
+ ifstream second(file.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<seekable> based on a"
+ "sequence in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_SEQUENCE_HPP_INCLUDED
diff --git a/libs/iostreams/test/read_seekable_test.hpp b/libs/iostreams/test/read_seekable_test.hpp
new file mode 100644
index 0000000000..f059f61db8
--- /dev/null
+++ b/libs/iostreams/test/read_seekable_test.hpp
@@ -0,0 +1,69 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_READ_SEEKABLE_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void read_seekable_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test1;
+ test_file test2;
+
+ {
+ filtering_stream<seekable> first(file(test1.name(), in_mode), 0);
+ ifstream second(test2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<seekable>"
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_stream<seekable> first(file(test1.name(), in_mode), 0);
+ ifstream second(test2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<seekable>"
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_stream<seekable> first(file(test1.name(), in_mode));
+ ifstream second(test2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from filtering_stream<seekable>"
+ "in chars with large buffer"
+ );
+ }
+
+ {
+ filtering_stream<seekable> first(file(test1.name(), in_mode));
+ ifstream second(test2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from filtering_stream<seekable>"
+ "in chars with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_READ_SEEKABLE_HPP_INCLUDED
diff --git a/libs/iostreams/test/regex_filter_test.cpp b/libs/iostreams/test/regex_filter_test.cpp
new file mode 100644
index 0000000000..8fd02d67f8
--- /dev/null
+++ b/libs/iostreams/test/regex_filter_test.cpp
@@ -0,0 +1,329 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/filter/regex.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+using namespace std;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+struct replace_lower {
+ std::string operator() (const boost::match_results<const char*>&)
+ { return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
+#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+ std::wstring operator() (const boost::match_results<const wchar_t*>&)
+ { return L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
+#endif
+};
+
+void regex_filter_test()
+{
+ // Note: Given the basic stream and filter tests, two regex tests
+ // are probably sufficient: reading with a filter based on a function,
+ // and writing with a filter based on a format string.
+
+ test_file test;
+ uppercase_file upper;
+
+ boost::regex match_lower("[a-z]+");
+ std::string fmt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a regex filter based on a function in chars.
+ filtering_istream
+ first(boost::iostreams::regex_filter(match_lower, replace_lower()));
+ first.push(file_source(test.name(), in_mode));
+ {
+ ifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from function-based regex_filter in chars"
+ );
+ }
+ first.pop();
+
+ // Test reading from a regex filter based on a function in chunks.
+ // (Also tests reusing the regex filter.)
+ first.push(file_source(test.name(), in_mode));
+ {
+ ifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from function-based regex_filter in chunks"
+ );
+ }
+ }
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a regex filter based on a format string in chars.
+ filtering_istream
+ first(boost::iostreams::regex_filter(match_lower, fmt));
+ first.push(file_source(test.name(), in_mode));
+ {
+ ifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from format-string-based regex_filter in chars"
+ );
+ }
+ first.pop();
+
+ // Test reading from a regex filter based on a format string in chunks.
+ // (Also tests reusing the regex filter.)
+ first.push(file_source(test.name(), in_mode));
+ {
+ ifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from format-string-based regex_filter in chunks"
+ );
+ }
+ }
+
+ {
+ test_file dest1;
+ test_file dest2;
+
+ // Test writing to a regex filter based on a function in chars.
+ filtering_ostream
+ out(boost::iostreams::regex_filter(match_lower, replace_lower()));
+ out.push(file_sink(dest1.name(), out_mode));
+ write_data_in_chars(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), upper.name()),
+ "failed writing to function-based regex_filter in chars"
+ );
+
+ // Test writing to a regex filter based on a function in chunks.
+ // (Also tests reusing the regex filter.)
+ out.push(file_sink(dest2.name(), out_mode));
+ write_data_in_chunks(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest2.name(), upper.name()),
+ "failed writing to function-based regex_filter in chunks"
+ );
+ }
+
+ {
+ test_file dest1;
+ test_file dest2;
+
+ // Test writing to a regex filter based on a format string in chars.
+ filtering_ostream
+ out(boost::iostreams::regex_filter(match_lower, fmt));
+ out.push(file_sink(dest1.name(), out_mode));
+ write_data_in_chars(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), upper.name()),
+ "failed writing to format-string-based regex_filter in chars"
+ );
+
+ // Test writing to a regex filter based on a format string in chunks.
+ // (Also tests reusing the regex filter.)
+ out.push(file_sink(dest2.name(), out_mode));
+ write_data_in_chunks(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest2.name(), upper.name()),
+ "failed writing to format-string-based regex_filter in chunks"
+ );
+ }
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a regex filter with no matches; this checks that
+ // Ticket #1139 is fixed
+ boost::regex match_xxx("xxx");
+ test_file test2;
+ filtering_istream
+ first(boost::iostreams::regex_filter(match_xxx, replace_lower()));
+ first.push(file_source(test.name(), in_mode));
+ {
+ ifstream second(test2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a regex filter with no matches"
+ );
+ }
+ }
+}
+
+#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+
+void wregex_filter_test()
+{
+ // Note: Given the basic stream and filter tests, two regex tests
+ // are probably sufficient: reading with a filter based on a function,
+ // and writing with a filter based on a format string.
+
+ test_file test;
+ uppercase_file upper;
+
+ boost::wregex match_lower(L"[a-z]+");
+ std::wstring fmt = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a regex filter based on a function in chars.
+ filtering_wistream
+ first(boost::iostreams::wregex_filter(match_lower, replace_lower()));
+ first.push(wfile_source(test.name(), in_mode));
+ {
+ wifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from function-based regex_filter in chars"
+ );
+ }
+ first.pop();
+
+ // Test reading from a regex filter based on a function in chunks.
+ // (Also tests reusing the regex filter.)
+ first.push(wfile_source(test.name(), in_mode));
+ {
+ wifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from function-based regex_filter in chunks"
+ );
+ }
+ }
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a regex filter based on a format string in chars.
+ filtering_wistream
+ first(boost::iostreams::wregex_filter(match_lower, fmt));
+ first.push(wfile_source(test.name(), in_mode));
+ {
+ wifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from format-string-based regex_filter in chars"
+ );
+ }
+ first.pop();
+
+ // Test reading from a regex filter based on a format string in chunks.
+ // (Also tests reusing the regex filter.)
+ first.push(wfile_source(test.name(), in_mode));
+ {
+ wifstream second(upper.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from format-string-based regex_filter in chunks"
+ );
+ }
+ }
+
+ {
+ test_file dest1;
+ test_file dest2;
+
+ // Test writing to a regex filter based on a function in chars.
+ filtering_wostream
+ out(boost::iostreams::wregex_filter(match_lower, replace_lower()));
+ out.push(wfile_sink(dest1.name(), out_mode));
+ write_data_in_chars(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), upper.name()),
+ "failed writing to function-based regex_filter in chars"
+ );
+
+ // Test writing to a regex filter based on a function in chunks.
+ // (Also tests reusing the regex filter.)
+ out.push(wfile_sink(dest2.name(), out_mode));
+ write_data_in_chunks(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest2.name(), upper.name()),
+ "failed writing to function-based regex_filter in chunks"
+ );
+ }
+
+ {
+ test_file dest1;
+ test_file dest2;
+
+ // Test writing to a regex filter based on a format string in chars.
+ filtering_wostream
+ out(boost::iostreams::wregex_filter(match_lower, fmt));
+ out.push(wfile_sink(dest1.name(), out_mode));
+ write_data_in_chars(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), upper.name()),
+ "failed writing to format-string-based regex_filter in chars"
+ );
+
+ // Test writing to a regex filter based on a format string in chunks.
+ // (Also tests reusing the regex filter.)
+ out.push(wfile_sink(dest2.name(), out_mode));
+ write_data_in_chunks(out);
+ out.pop();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest2.name(), upper.name()),
+ "failed writing to format-string-based regex_filter in chunks"
+ );
+ }
+
+ {
+ // Note: the ifstream second is placed in a nested scope because
+ // closing and reopening a single ifstream failed for CW 9.4 on Windows.
+
+ // Test reading from a regex filter with no matches; this checks that
+ // Ticket #1139 is fixed
+ boost::wregex match_xxx(L"xxx");
+ test_file test2;
+ filtering_wistream
+ first(boost::iostreams::wregex_filter(match_xxx, replace_lower()));
+ first.push(wfile_source(test.name(), in_mode));
+ {
+ wifstream second(test2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a regex filter with no matches"
+ );
+ }
+ }
+}
+
+#endif
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("regex_filter test");
+ test->add(BOOST_TEST_CASE(&regex_filter_test));
+#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+ test->add(BOOST_TEST_CASE(&wregex_filter_test));
+#endif
+ return test;
+}
diff --git a/libs/iostreams/test/restrict_test.cpp b/libs/iostreams/test/restrict_test.cpp
new file mode 100644
index 0000000000..3abf21555a
--- /dev/null
+++ b/libs/iostreams/test/restrict_test.cpp
@@ -0,0 +1,690 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2005-2007 Jonathan Turkanis
+// 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.
+
+// Allow this file to be used by slice_test.hpp. It is important not to
+// replace BOOST_RESTRICT with BOOST_IOSTREAMS_RESTRICT here, since that
+// would interfere with the oepration of the header
+// <boost/iostreams/restrict.hpp>
+#include <iostream>
+
+#if defined(BOOST_RESTRICT_USE_SLICE)
+# include <boost/iostreams/slice.hpp>
+# define BOOST_RESTRICT slice
+#else
+# include <boost/iostreams/restrict.hpp>
+# define BOOST_RESTRICT restrict
+#endif
+
+#include <algorithm> // equal.
+#include <cctype>
+#include <iterator> // back_inserter.
+#include <vector>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/device/null.hpp>
+#include <boost/iostreams/filtering_stream.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::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+namespace io = boost::iostreams;
+
+const char pad_char = '\n';
+const int small_padding = 50;
+const int large_padding = default_device_buffer_size + 50;
+
+void write_padding(std::ofstream& out, int len)
+{
+ for (int z = 0; z < len; ++z)
+ out.put(pad_char);
+}
+
+struct restricted_test_file : public temp_file {
+ restricted_test_file(int padding, bool half_open = false)
+ {
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::out | BOOST_IOS::binary;
+ ::std::ofstream f(name().c_str(), mode);
+ write_padding(f, padding);
+ const char* buf = narrow_data();
+ for (int z = 0; z < data_reps; ++z)
+ f.write(buf, data_length());
+ if (!half_open)
+ write_padding(f, padding);
+ }
+};
+
+struct restricted_test_sequence : public std::vector<char> {
+ restricted_test_sequence(int padding, bool half_open = false)
+ {
+ for (int z = 0; z < padding; ++z)
+ push_back(pad_char);
+ const char* buf = narrow_data();
+ for (int w = 0; w < data_reps; ++w)
+ insert(end(), buf, buf + data_length());
+ if (!half_open)
+ for (int x = 0; x < padding; ++x)
+ push_back(pad_char);
+ }
+};
+
+struct restricted_uppercase_file : public temp_file {
+ restricted_uppercase_file(int padding, bool half_open = false)
+ {
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::out | BOOST_IOS::binary;
+ ::std::ofstream f(name().c_str(), mode);
+ write_padding(f, padding);
+ const char* buf = narrow_data();
+ for (int z = 0; z < data_reps; ++z)
+ for (int w = 0; w < data_length(); ++w)
+ f.put((char) std::toupper(buf[w]));
+ if (!half_open)
+ write_padding(f, padding);
+ }
+};
+
+struct restricted_lowercase_file : public temp_file {
+ restricted_lowercase_file(int padding, bool half_open = false)
+ {
+ BOOST_IOS::openmode mode =
+ BOOST_IOS::out | BOOST_IOS::binary;
+ ::std::ofstream f(name().c_str(), mode);
+ write_padding(f, padding);
+ const char* buf = narrow_data();
+ for (int z = 0; z < data_reps; ++z)
+ for (int w = 0; w < data_length(); ++w)
+ f.put((char) std::tolower(buf[w]));
+ if (!half_open)
+ write_padding(f, padding);
+ }
+};
+
+// Can't have a restricted view of a non-seekble output filter.
+struct tolower_seekable_filter : public seekable_filter {
+ typedef char char_type;
+ struct category
+ : output_seekable,
+ filter_tag
+ { };
+ template<typename Sink>
+ bool put(Sink& s, char c)
+ { return boost::iostreams::put(s, (char) std::tolower(c)); }
+
+ template<typename Sink>
+ std::streampos seek(Sink& s, stream_offset off, BOOST_IOS::seekdir way)
+ { return boost::iostreams::seek(s, off, way); }
+};
+
+void read_device()
+{
+ {
+ restricted_test_file src1(small_padding);
+ test_file src2;
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ filtering_istream first(
+ BOOST_RESTRICT(file_source(src1.name(), in_mode), off, len));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from restriction<Device> with small padding"
+ );
+ }
+
+ {
+ restricted_test_file src1(large_padding);
+ test_file src2;
+ stream_offset off = large_padding,
+ len = data_reps * data_length();
+ filtering_istream first(
+ BOOST_RESTRICT(file_source(src1.name(), in_mode), off, len));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from restriction<Device> with large padding"
+ );
+ }
+
+ {
+ restricted_test_file src1(small_padding, true);
+ test_file src2;
+ stream_offset off = small_padding;
+ filtering_istream first(
+ BOOST_RESTRICT(file_source(src1.name(), in_mode), off));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from half-open restriction<Device> "
+ "with small padding"
+ );
+ }
+
+ {
+ restricted_test_file src1(large_padding, true);
+ test_file src2;
+ stream_offset off = large_padding;
+ filtering_istream first(
+ BOOST_RESTRICT(file_source(src1.name(), in_mode), off));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from half-open restriction<Device> "
+ "with large padding"
+ );
+ }
+}
+
+void read_direct_device()
+{
+ {
+ test_sequence<char> first;
+ restricted_test_sequence src(small_padding);
+ array_source array_src(&src[0], &src[0] + src.size());
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ filtering_istream second(BOOST_RESTRICT(array_src, off, len));
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed reading from restriction<Direct>"
+ );
+ }
+
+ {
+ test_sequence<char> first;
+ restricted_test_sequence src(small_padding, true);
+ array_source array_src(&src[0], &src[0] + src.size());
+ stream_offset off = small_padding;
+ filtering_istream second(BOOST_RESTRICT(array_src, off));
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed reading from half-open restriction<Direct>"
+ );
+ }
+}
+
+void read_filter()
+{
+ {
+ restricted_test_file src1(small_padding);
+ uppercase_file src2;
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ filtering_istream first;
+ first.push(BOOST_RESTRICT(toupper_filter(), off, len));
+ first.push(file_source(src1.name(), in_mode));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from restriction<Filter> with small padding"
+ );
+ }
+
+ {
+ restricted_test_file src1(large_padding);
+ uppercase_file src2;
+ stream_offset off = large_padding,
+ len = data_reps * data_length();
+ filtering_istream first;
+ first.push(BOOST_RESTRICT(toupper_filter(), off, len));
+ first.push(file_source(src1.name(), in_mode));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from restriction<Filter> with large padding"
+ );
+ }
+
+ {
+ restricted_test_file src1(small_padding, true);
+ uppercase_file src2;
+ stream_offset off = small_padding;
+ filtering_istream first;
+ first.push(BOOST_RESTRICT(toupper_filter(), off));
+ first.push(file_source(src1.name(), in_mode));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from half-open restriction<Filter> "
+ "with small padding"
+ );
+ }
+
+ {
+ restricted_test_file src1(large_padding, true);
+ uppercase_file src2;
+ stream_offset off = large_padding;
+ filtering_istream first;
+ first.push(BOOST_RESTRICT(toupper_filter(), off));
+ first.push(file_source(src1.name(), in_mode));
+ ifstream second(src2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from half-open restriction<Filter> "
+ "with large padding"
+ );
+ }
+}
+
+void write_device()
+{
+ {
+ restricted_uppercase_file dest1(small_padding);
+ restricted_test_file dest2(small_padding);
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ filtering_ostream out(
+ BOOST_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off, len));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to restriction<Device> with small padding"
+ );
+ }
+
+ {
+ restricted_uppercase_file dest1(large_padding);
+ restricted_test_file dest2(large_padding);
+ stream_offset off = large_padding,
+ len = data_reps * data_length();
+ filtering_ostream out
+ (BOOST_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off, len));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to restriction<Device> with large padding"
+ );
+ }
+
+ {
+ restricted_uppercase_file dest1(small_padding, true);
+ restricted_test_file dest2(small_padding, true);
+ stream_offset off = small_padding;
+ filtering_ostream out
+ (BOOST_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to half-open restriction<Device> "
+ "with small padding"
+ );
+ }
+
+ {
+ restricted_uppercase_file dest1(large_padding, true);
+ restricted_test_file dest2(large_padding, true);
+ stream_offset off = large_padding;
+ filtering_ostream out
+ (BOOST_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to half-open restriction<Device> "
+ "with large padding"
+ );
+ }
+}
+
+void write_direct_device()
+{
+ {
+ vector<char> dest1( data_reps * data_length() +
+ 2 * small_padding,
+ '\n' );
+ restricted_test_sequence dest2(small_padding);
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ array_sink array(&dest1[0], &dest1[0] + dest1.size());
+ filtering_ostream out(BOOST_RESTRICT(array, off, len));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ std::equal(dest1.begin(), dest1.end(), dest2.begin()),
+ "failed writing to restriction<Direct>"
+ );
+ }
+
+ {
+ vector<char> dest1(
+ data_reps * data_length() + small_padding, '\n');
+ restricted_test_sequence dest2(small_padding, true);
+ stream_offset off = small_padding;
+ array_sink array(&dest1[0], &dest1[0] + dest1.size());
+ filtering_ostream out(BOOST_RESTRICT(array, off));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ std::equal(dest1.begin(), dest1.end(), dest2.begin()),
+ "failed writing to half-open restriction<Direct>"
+ );
+ }
+}
+
+void write_filter()
+{
+ {
+ restricted_test_file dest1(small_padding);
+ restricted_lowercase_file dest2(small_padding);
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ filtering_ostream out;
+ out.push(BOOST_RESTRICT(tolower_seekable_filter(), off, len));
+ out.push(file(dest1.name(), BOOST_IOS::binary));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to restriction<Filter> with small padding"
+ );
+ }
+
+ {
+ restricted_test_file dest1(large_padding);
+ restricted_lowercase_file dest2(large_padding);
+ stream_offset off = large_padding,
+ len = data_reps * data_length();
+ filtering_ostream out;
+ out.push(BOOST_RESTRICT(tolower_seekable_filter(), off, len));
+ out.push(file(dest1.name(), BOOST_IOS::binary));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to restriction<Filter> with large padding"
+ );
+ }
+
+ {
+ restricted_test_file dest1(small_padding, true);
+ restricted_lowercase_file dest2(small_padding, true);
+ stream_offset off = small_padding;
+ filtering_ostream out;
+ out.push(BOOST_RESTRICT(tolower_seekable_filter(), off));
+ out.push(file(dest1.name(), BOOST_IOS::binary));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to restriction<Filter> with small padding"
+ );
+ }
+
+ {
+ restricted_test_file dest1(large_padding, true);
+ restricted_lowercase_file dest2(large_padding, true);
+ stream_offset off = large_padding;
+ filtering_ostream out;
+ out.push(BOOST_RESTRICT(tolower_seekable_filter(), off));
+ out.push(file(dest1.name(), BOOST_IOS::binary));
+ write_data_in_chunks(out);
+ out.reset();
+ ifstream first(dest1.name().c_str(), in_mode);
+ ifstream second(dest2.name().c_str(), in_mode);
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to restriction<Filter> with large padding"
+ );
+ }
+}
+
+void seek_device()
+{
+ {
+ restricted_test_file src(large_padding);
+ stream_offset off = large_padding,
+ len = data_reps * data_length();
+ filtering_stream<seekable> io(
+ BOOST_RESTRICT(file(src.name(), BOOST_IOS::binary), off, len));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within restriction<Device>"
+ );
+ }
+
+ {
+ restricted_test_file src(large_padding, true);
+ stream_offset off = large_padding;
+ filtering_stream<seekable> io(
+ BOOST_RESTRICT(file(src.name(), BOOST_IOS::binary), off));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within half-open restriction<Device>"
+ );
+ }
+}
+
+void seek_direct_device()
+{
+ {
+ vector<char> src(
+ data_reps * data_length() + 2 * small_padding, '\n');
+ stream_offset off = small_padding,
+ len = data_reps * data_length();
+ array ar(&src[0], &src[0] + src.size());
+ filtering_stream<seekable> io(BOOST_RESTRICT(ar, off, len));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within restriction<Direct> with small padding"
+ );
+ }
+
+ {
+ vector<char> src(
+ data_reps * data_length() + small_padding, '\n');
+ stream_offset off = small_padding;
+ array ar(&src[0], &src[0] + src.size());
+ filtering_stream<seekable> io(BOOST_RESTRICT(ar, off));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within half-open restriction<Direct> "
+ "with small padding"
+ );
+ }
+}
+
+void seek_filter()
+{
+ {
+ restricted_test_file src(small_padding);
+ stream_offset off = large_padding,
+ len = data_reps * data_length();
+ filtering_stream<seekable> io;
+ io.push(BOOST_RESTRICT(identity_seekable_filter(), off, len));
+ io.push(file(src.name(), BOOST_IOS::binary));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within restriction<Device>"
+ );
+ }
+
+ {
+ restricted_test_file src(small_padding, true);
+ stream_offset off = large_padding;
+ filtering_stream<seekable> io;
+ io.push(BOOST_RESTRICT(identity_seekable_filter(), off));
+ io.push(file(src.name(), BOOST_IOS::binary));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within half-open restriction<Device>"
+ );
+ }
+}
+
+void close_device()
+{
+ // Restrict a source
+ {
+ operation_sequence seq;
+ chain<input> ch;
+ ch.push(
+ io::BOOST_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::BOOST_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::BOOST_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::BOOST_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::BOOST_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::BOOST_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;
+ operation dummy;
+ ch.push(
+ io::BOOST_RESTRICT(
+ closable_filter<dual_use>(
+ seq.new_operation(2),
+ dummy
+ ),
+ 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;
+ operation dummy;
+ ch.push(
+ io::BOOST_RESTRICT(
+ closable_filter<dual_use>(
+ dummy,
+ seq.new_operation(1)
+ ),
+ 0
+ )
+ );
+ 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(BOOST_STRINGIZE(BOOST_RESTRICT) " test");
+ test->add(BOOST_TEST_CASE(&read_device));
+ test->add(BOOST_TEST_CASE(&read_direct_device));
+ test->add(BOOST_TEST_CASE(&read_filter));
+ test->add(BOOST_TEST_CASE(&write_device));
+ test->add(BOOST_TEST_CASE(&write_direct_device));
+ 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;
+}
diff --git a/libs/iostreams/test/seek_test.hpp b/libs/iostreams/test/seek_test.hpp
new file mode 100644
index 0000000000..68c0aeaf09
--- /dev/null
+++ b/libs/iostreams/test/seek_test.hpp
@@ -0,0 +1,51 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_SEEK_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_SEEK_HPP_INCLUDED
+
+
+#include <boost/config.hpp> // BOOST_MSVC, make sure size_t is in std.
+#include <cstddef> // std::size_t.
+#include <string>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "../example/container_device.hpp" // We use container_device instead
+#include "detail/verification.hpp" // of make_iterator_range to
+ // reduce dependence on Boost.Range
+
+void seek_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::example;
+ using namespace boost::iostreams::test;
+
+ {
+ string test(data_reps * data_length(), '\0');
+ filtering_stream<seekable> io;
+ io.push(container_device<string>(test));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within a filtering_stream<seekable>, in chars"
+ );
+ }
+
+ {
+ string test(data_reps * data_length(), '\0');
+ filtering_stream<seekable> io;
+ io.push(container_device<string>(test));
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within a filtering_stream<seekable>, in chunks"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_SEEK_HPP_INCLUDED
diff --git a/libs/iostreams/test/seekable_file_test.cpp b/libs/iostreams/test/seekable_file_test.cpp
new file mode 100644
index 0000000000..738bc1bac2
--- /dev/null
+++ b/libs/iostreams/test/seekable_file_test.cpp
@@ -0,0 +1,56 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.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;
+
+void seekable_file_test()
+{
+ {
+ temp_file temp;
+ file f( temp.name(),
+ BOOST_IOS::in | BOOST_IOS::out |
+ BOOST_IOS::trunc | BOOST_IOS::binary);
+ filtering_stream<seekable> io(f);
+ io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within a file, in chars"
+ );
+ }
+
+ {
+ temp_file temp;
+ file f( temp.name(),
+ BOOST_IOS::in | BOOST_IOS::out |
+ BOOST_IOS::trunc | BOOST_IOS::binary);
+ filtering_stream<seekable> io(f);
+ io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within a file, in chunks"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("seekable file test");
+ test->add(BOOST_TEST_CASE(&seekable_file_test));
+ return test;
+}
diff --git a/libs/iostreams/test/seekable_filter_test.cpp b/libs/iostreams/test/seekable_filter_test.cpp
new file mode 100644
index 0000000000..afd0af8fce
--- /dev/null
+++ b/libs/iostreams/test/seekable_filter_test.cpp
@@ -0,0 +1,95 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <vector>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/device/array.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "../example/container_device.hpp" // We use container_device instead
+#include "detail/filters.hpp" // of make_iterator_range to
+#include "detail/temp_file.hpp" // reduce dependence on Boost.Range
+#include "detail/verification.hpp"
+
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::example;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+
+// Code generation bugs cause tests to fail with global optimization.
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# pragma optimize("g", off)
+#endif
+
+void seekable_filter_test()
+{
+ {
+ vector<char> test(data_reps * data_length(), '0');
+ filtering_stream<seekable> io;
+ io.push(identity_seekable_filter());
+ io.push(container_device< vector<char> >(test));
+ io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within a file, in chars"
+ );
+ }
+
+ {
+ vector<char> test(data_reps * data_length(), '0');
+ filtering_stream<seekable> io;
+ io.push(identity_seekable_filter());
+ io.push(container_device< vector<char> >(test));
+ io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within a file, in chunks"
+ );
+ }
+
+ {
+ vector<char> test(data_reps * data_length(), '0');
+ filtering_stream<seekable> io;
+ io.push(identity_seekable_multichar_filter());
+ io.push(container_device< vector<char> >(test));
+ io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chars(io),
+ "failed seeking within a file, in chars"
+ );
+ }
+
+ {
+ vector<char> test(data_reps * data_length(), '0');
+ filtering_stream<seekable> io;
+ io.push(identity_seekable_multichar_filter());
+ io.push(container_device< vector<char> >(test));
+ io.exceptions(BOOST_IOS::failbit | BOOST_IOS::badbit);
+ BOOST_CHECK_MESSAGE(
+ test_seekable_in_chunks(io),
+ "failed seeking within a file, in chunks"
+ );
+ }
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# pragma optimize("", on)
+#endif
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("seekable filter test");
+ test->add(BOOST_TEST_CASE(&seekable_filter_test));
+ return test;
+}
diff --git a/libs/iostreams/test/sequence_test.cpp b/libs/iostreams/test/sequence_test.cpp
new file mode 100644
index 0000000000..9dd182ccb8
--- /dev/null
+++ b/libs/iostreams/test/sequence_test.cpp
@@ -0,0 +1,24 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2007 Jonathan Turkanis
+// 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.
+
+#include <boost/test/unit_test.hpp>
+#include "read_input_seq_test.hpp"
+#include "read_seekable_seq_test.hpp"
+#include "write_output_seq_test.hpp"
+#include "write_seekable_seq_test.hpp"
+
+using boost::unit_test::test_suite;
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("sequence test");
+ test->add(BOOST_TEST_CASE(&read_input_sequence_test));
+ test->add(BOOST_TEST_CASE(&read_seekable_sequence_test));
+ test->add(BOOST_TEST_CASE(&write_output_sequence_test));
+ test->add(BOOST_TEST_CASE(&write_seekable_sequence_test));
+ return test;
+}
diff --git a/libs/iostreams/test/slice_test.cpp b/libs/iostreams/test/slice_test.cpp
new file mode 100644
index 0000000000..2ec42d542e
--- /dev/null
+++ b/libs/iostreams/test/slice_test.cpp
@@ -0,0 +1,17 @@
+/*
+ * 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.
+
+ * File: test/slice_test.hpp
+ * Date: Sun Jan 06 12:57:30 MST 2008
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ *
+ * Tests the overloaded function template boost::iostreams::slice.
+ */
+
+#define BOOST_RESTRICT_USE_SLICE
+#include "restrict_test.cpp"
diff --git a/libs/iostreams/test/stdio_filter_test.cpp b/libs/iostreams/test/stdio_filter_test.cpp
new file mode 100644
index 0000000000..6bcbe31567
--- /dev/null
+++ b/libs/iostreams/test/stdio_filter_test.cpp
@@ -0,0 +1,144 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <cctype>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filter/stdio.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/filters.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+// Must come last.
+#include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x.
+
+using namespace boost::iostreams;
+using boost::unit_test::test_suite;
+
+struct toupper_stdio_filter : stdio_filter {
+ void do_filter()
+ {
+ int c;
+ while ((c = std::cin.get()) != EOF)
+ std::cout.put(std::toupper((unsigned char)c));
+ }
+};
+
+struct tolower_stdio_filter : stdio_filter {
+ void do_filter()
+ {
+ int c;
+ while ((c = std::cin.get()) != EOF)
+ std::cout.put(std::tolower((unsigned char)c));
+ }
+};
+
+struct padding_stdio_filter : stdio_filter {
+ padding_stdio_filter(char pad_char) : pad_char_(pad_char) { }
+ void do_filter()
+ {
+ int c;
+ while ((c = std::cin.get()) != EOF) {
+ std::cout.put(c);
+ std::cout.put(pad_char_);
+ }
+ }
+ char pad_char_;
+};
+
+void read_stdio_filter()
+{
+ using namespace boost::iostreams::test;
+
+ test_file src1, src2;
+ filtering_istream first, second;
+
+ first.push(toupper_filter());
+ first.push(padding_filter('a'));
+ first.push(file_source(src1.name(), in_mode));
+ second.push(toupper_stdio_filter());
+ second.push(padding_stdio_filter('a'));
+ second.push(file_source(src2.name(), in_mode));
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a stdio_filter"
+ );
+
+ first.reset();
+ first.push(padding_filter('a'));
+ first.push(toupper_filter());
+ first.push(file_source(src1.name(), in_mode));
+ second.reset();
+ second.push(padding_stdio_filter('a'));
+ second.push(toupper_stdio_filter());
+ second.push(file_source(src2.name(), in_mode));
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a stdio_filter"
+ );
+}
+
+void write_stdio_filter()
+{
+ using namespace std;
+ using namespace boost::iostreams::test;
+
+ temp_file dest1, dest2;
+ filtering_ostream out1, out2;
+
+ out1.push(tolower_filter());
+ out1.push(padding_filter('a'));
+ out1.push(file_sink(dest1.name(), in_mode));
+ out2.push(tolower_stdio_filter());
+ out2.push(padding_stdio_filter('a'));
+ out2.push(file_sink(dest2.name(), in_mode));
+ write_data_in_chunks(out1);
+ write_data_in_chunks(out2);
+ out1.reset();
+ out2.reset();
+
+ {
+ ifstream first(dest1.name().c_str());
+ ifstream second(dest2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to a stdio_filter"
+ );
+ }
+
+ out1.push(padding_filter('a'));
+ out1.push(tolower_filter());
+ out1.push(file_sink(dest1.name(), in_mode));
+ out2.push(padding_stdio_filter('a'));
+ out2.push(tolower_stdio_filter());
+ out2.push(file_sink(dest2.name(), in_mode));
+ write_data_in_chunks(out1);
+ write_data_in_chunks(out2);
+ out1.reset();
+ out2.reset();
+
+ {
+ ifstream first(dest1.name().c_str());
+ ifstream second(dest2.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed writing to a stdio_filter"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("line_filter test");
+ test->add(BOOST_TEST_CASE(&read_stdio_filter));
+ test->add(BOOST_TEST_CASE(&write_stdio_filter));
+ return test;
+}
+
+#include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x.
diff --git a/libs/iostreams/test/stream_offset_32bit_test.cpp b/libs/iostreams/test/stream_offset_32bit_test.cpp
new file mode 100644
index 0000000000..542e31cbb3
--- /dev/null
+++ b/libs/iostreams/test/stream_offset_32bit_test.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+
+ * File: libs/iostreams/test/stream_offset_32bit_test.cpp
+ * Date: Sun Dec 23 21:11:23 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ *
+ * Tests the functions defined in the header "boost/iostreams/positioning.hpp"
+ * with small (32-bit) file offsets.
+ */
+
+#include <boost/iostreams/positioning.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/type_traits/is_integral.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using boost::unit_test::test_suite;
+
+void stream_offset_32bit_test()
+{
+ stream_offset small_file = 1000000;
+ stream_offset off = -small_file;
+ streampos pos = offset_to_position(off);
+
+ while (off < small_file)
+ {
+ BOOST_CHECK(off == position_to_offset(offset_to_position(off)));
+ BOOST_CHECK(pos == offset_to_position(position_to_offset(pos)));
+ off += 20000;
+ pos += 20000;
+ BOOST_CHECK(off == position_to_offset(offset_to_position(off)));
+ BOOST_CHECK(pos == offset_to_position(position_to_offset(pos)));
+ off -= 10000;
+ pos -= 10000;
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("stream_offset 32-bit test");
+ test->add(BOOST_TEST_CASE(&stream_offset_32bit_test));
+ return test;
+}
diff --git a/libs/iostreams/test/stream_offset_64bit_test.cpp b/libs/iostreams/test/stream_offset_64bit_test.cpp
new file mode 100644
index 0000000000..6ebda4f18d
--- /dev/null
+++ b/libs/iostreams/test/stream_offset_64bit_test.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.
+
+ * File: libs/iostreams/test/stream_offset_64bit_test.cpp
+ * Date: Sun Dec 23 21:11:23 MST 2007
+ * Copyright: 2007-2008 CodeRage, LLC
+ * Author: Jonathan Turkanis
+ * Contact: turkanis at coderage dot com
+ *
+ * Tests the functions defined in the header "boost/iostreams/positioning.hpp"
+ * with large (64-bit) file offsets.
+ */
+
+#include <cstdio> // fpos_t
+#include <iostream>
+#include <sstream>
+#include <boost/config.hpp> // BOOST_MSVC
+#include <boost/iostreams/detail/ios.hpp>
+#include <boost/iostreams/positioning.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using boost::unit_test::test_suite;
+
+#ifdef BOOST_MSVC
+# pragma warning(disable:4127)
+#endif
+
+void stream_offset_64bit_test()
+{
+ stream_offset large_file = (stream_offset) 100 *
+ (stream_offset) 1024 *
+ (stream_offset) 1024 *
+ (stream_offset) 1024;
+ stream_offset first = -large_file - (-large_file) % 10000000;
+ stream_offset last = large_file - large_file % 10000000;
+
+ for (stream_offset off = first; off < last; off += 10000000)
+ {
+ if (off != position_to_offset(offset_to_position(off))) {
+ cout << "****************************************\n"
+ << "* sizeof(fpos_t) = " << sizeof(fpos_t) << "\n"
+ << "* sizeof(streamoff) = " << sizeof(streamoff) << "\n"
+ << "* sizeof(stream_offset) = "
+ << sizeof(stream_offset) << "\n"
+ << "****************************************\n";
+ stringstream s;
+ s << "off != position_to_offset(offset_to_position(off)) "
+ "failed for (off >> 32) == 0x"
+ << hex
+ << static_cast<unsigned int>(off >> 32)
+ << " and (off & 0xFFFFFFFF) == 0x"
+ << static_cast<unsigned int>(off & 0xFFFFFFFF)
+ << std::endl;
+ BOOST_REQUIRE_MESSAGE(0, s.str().c_str());
+ }
+ }
+}
+
+void stream_offset_64bit_test2()
+{
+ boost::int64_t val = boost::int64_t(1) << 31;
+ std::streampos pos = boost::iostreams::offset_to_position(val);
+ pos -= 2;
+ BOOST_CHECK_EQUAL(val - 2, boost::iostreams::position_to_offset(pos));
+
+ val = -val;
+ pos = boost::iostreams::offset_to_position(val);
+ pos += 2;
+ BOOST_CHECK_EQUAL(val + 2, boost::iostreams::position_to_offset(pos));
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("stream_offset 64-bit test");
+ test->add(BOOST_TEST_CASE(&stream_offset_64bit_test));
+ test->add(BOOST_TEST_CASE(&stream_offset_64bit_test2));
+ return test;
+}
diff --git a/libs/iostreams/test/stream_state_test.cpp b/libs/iostreams/test/stream_state_test.cpp
new file mode 100644
index 0000000000..8d2a560c4a
--- /dev/null
+++ b/libs/iostreams/test/stream_state_test.cpp
@@ -0,0 +1,161 @@
+// (C) Copyright Frank Birbacher 2007
+// 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.
+
+#include <boost/iostreams/categories.hpp> // tags.
+#include <boost/iostreams/detail/ios.hpp> // openmode, seekdir, int types.
+#include <boost/iostreams/detail/error.hpp>
+#include <boost/iostreams/positioning.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace 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.
+ */
+
+//------------------Definition of error_device--------------------------------//
+
+// Device whose member functions throw
+struct error_device {
+ typedef char char_type;
+ typedef seekable_device_tag category;
+ error_device(char const*) {}
+ std::streamsize read(char_type*, std::streamsize)
+ {
+ throw detail::bad_read();
+ }
+ std::streamsize write(const char_type*, std::streamsize)
+ {
+ throw detail::bad_write();
+ }
+ std::streampos seek(stream_offset, BOOST_IOS::seekdir)
+ {
+ throw detail::bad_seek();
+ }
+};
+
+typedef stream<error_device> test_stream;
+
+//------------------Stream state tester---------------------------------------//
+
+void check_stream_for_badbit(std::iostream& str)
+{
+ BOOST_CHECK_MESSAGE(!str.good(), "stream still good");
+ BOOST_CHECK_MESSAGE(!str.eof(), "eofbit set but not expected");
+ BOOST_CHECK_MESSAGE(str.bad(), "stream did not set badbit");
+ BOOST_CHECK_MESSAGE(str.fail(), "stream did not fail");
+ BOOST_CHECK_MESSAGE(str.operator ! (),
+ "stream does not report failure by operator !");
+ BOOST_CHECK_MESSAGE(0 == str.operator void* (),
+ "stream does not report failure by operator void*");
+}
+
+//------------------Test case generators--------------------------------------//
+
+template<void (*const function)(std::iostream&)>
+struct wrap_nothrow {
+ static void execute()
+ {
+ test_stream stream("foo");
+ BOOST_CHECK_NO_THROW( function(stream) );
+ check_stream_for_badbit(stream);
+ }
+};
+
+template<void (*const function)(std::iostream&)>
+struct wrap_throw {
+ static void execute()
+ {
+ typedef std::ios_base ios;
+ test_stream stream("foo");
+
+ stream.exceptions(ios::failbit | ios::badbit);
+ BOOST_CHECK_THROW( function(stream), std::exception );
+
+ check_stream_for_badbit(stream);
+ }
+};
+
+template<void (*const function)(std::iostream&)>
+struct wrap_throw_delayed {
+ static void execute()
+ {
+ typedef std::ios_base ios;
+ test_stream stream("foo");
+
+ function(stream);
+ BOOST_CHECK_THROW(
+ stream.exceptions(ios::failbit | ios::badbit),
+ ios::failure
+ );
+
+ check_stream_for_badbit(stream);
+ }
+};
+
+//------------------Stream operations that throw------------------------------//
+
+void test_read(std::iostream& str)
+{
+ char data[10];
+ str.read(data, 10);
+}
+
+void test_write(std::iostream& str)
+{
+ char data[10] = {0};
+ str.write(data, 10);
+ //force use of streambuf
+ str.flush();
+}
+
+void test_seekg(std::iostream& str)
+{
+ str.seekg(10);
+}
+
+void test_seekp(std::iostream& str)
+{
+ str.seekp(10);
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("stream state test");
+
+ test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_read>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw <&test_read>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_read>::execute));
+
+ test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_write>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw <&test_write>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_write>::execute));
+
+ test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_seekg>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw <&test_seekg>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_seekg>::execute));
+
+ test->add(BOOST_TEST_CASE(&wrap_nothrow <&test_seekp>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw <&test_seekp>::execute));
+ test->add(BOOST_TEST_CASE(&wrap_throw_delayed<&test_seekp>::execute));
+
+ return test;
+}
diff --git a/libs/iostreams/test/symmetric_filter_test.cpp b/libs/iostreams/test/symmetric_filter_test.cpp
new file mode 100644
index 0000000000..6f84f10c8b
--- /dev/null
+++ b/libs/iostreams/test/symmetric_filter_test.cpp
@@ -0,0 +1,182 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/iostreams/detail/buffer.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filter/symmetric.hpp>
+#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"
+
+// Must come last.
+#include <boost/iostreams/detail/config/disable_warnings.hpp>
+
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+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.
+struct toupper_symmetric_filter_impl {
+ typedef char char_type;
+ explicit toupper_symmetric_filter_impl(
+ std::streamsize buffer_size =
+ default_filter_buffer_size
+ )
+ : buf_(buffer_size)
+ {
+ buf_.set(0, 0);
+ }
+ bool filter( const char*& src_begin, const char* src_end,
+ char*& dest_begin, char* dest_end, bool /* flush */ )
+ {
+ while ( can_read(src_begin, src_end) ||
+ can_write(dest_begin, dest_end) )
+ {
+ if (can_read(src_begin, src_end))
+ read(src_begin, src_end);
+ if (can_write(dest_begin, dest_end))
+ write(dest_begin, dest_end);
+ }
+ bool result = buf_.ptr() != buf_.eptr();
+ return result;
+ }
+ void close() { buf_.set(0, 0); }
+ void read(const char*& src_begin, const char* src_end)
+ {
+ std::ptrdiff_t count =
+ (std::min) ( src_end - src_begin,
+ static_cast<std::ptrdiff_t>(buf_.size()) -
+ (buf_.eptr() - buf_.data()) );
+ while (count-- > 0)
+ *buf_.eptr()++ = std::toupper(*src_begin++);
+ }
+ void write(char*& dest_begin, char* dest_end)
+ {
+ std::ptrdiff_t count =
+ (std::min) ( dest_end - dest_begin,
+ buf_.eptr() - buf_.ptr() );
+ while (count-- > 0)
+ *dest_begin++ = *buf_.ptr()++;
+ if (buf_.ptr() == buf_.eptr())
+ buf_.set(0, 0);
+ }
+ bool can_read(const char*& src_begin, const char* src_end)
+ { return src_begin != src_end && buf_.eptr() != buf_.end(); }
+ bool can_write(char*& dest_begin, char* dest_end)
+ { return dest_begin != dest_end && buf_.ptr() != buf_.eptr(); }
+ boost::iostreams::detail::buffer<char> buf_;
+};
+
+typedef symmetric_filter<toupper_symmetric_filter_impl>
+ toupper_symmetric_filter;
+
+void read_symmetric_filter()
+{
+ test_file test;
+ uppercase_file upper;
+ BOOST_CHECK(
+ test_input_filter( toupper_symmetric_filter(default_filter_buffer_size),
+ file_source(test.name(), in_mode),
+ file_source(upper.name(), in_mode) )
+ );
+}
+
+void write_symmetric_filter()
+{
+ test_file test;
+ uppercase_file upper;
+ BOOST_CHECK(
+ test_output_filter( toupper_symmetric_filter(default_filter_buffer_size),
+ file_source(test.name(), in_mode),
+ file_source(upper.name(), in_mode) )
+ );
+}
+
+void close_symmetric_filter()
+{
+ // Test input
+ {
+ operation_sequence seq;
+ chain<input> ch;
+ ch.push(
+ io::symmetric_filter<closable_symmetric_filter>
+ (1, 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>
+ (1, seq.new_operation(1))
+ );
+ ch.push(closable_device<output>(seq.new_operation(2)));
+ BOOST_CHECK_NO_THROW(ch.reset());
+ BOOST_CHECK_OPERATION_SEQUENCE(seq);
+ }
+}
+
+#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+
+struct wcopy_filter_impl {
+ typedef wchar_t char_type;
+ bool filter( const wchar_t*& src_begin, const wchar_t* src_end,
+ wchar_t*& dest_begin, wchar_t* dest_end, bool /* flush */ )
+ {
+ if(src_begin != src_end && dest_begin != dest_end) {
+ *dest_begin++ = *src_begin++;
+ }
+ return false;
+ }
+ void close() {}
+};
+
+typedef symmetric_filter<wcopy_filter_impl> wcopy_filter;
+
+void wide_symmetric_filter()
+{
+ {
+ warray_source src(wide_data(), wide_data() + data_length());
+ std::wstring dest;
+ io::copy(src, io::compose(wcopy_filter(16), io::back_inserter(dest)));
+ BOOST_CHECK(dest == wide_data());
+ }
+ {
+ warray_source src(wide_data(), wide_data() + data_length());
+ std::wstring dest;
+ io::copy(io::compose(wcopy_filter(16), src), io::back_inserter(dest));
+ BOOST_CHECK(dest == wide_data());
+ }
+}
+
+#endif
+
+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->add(BOOST_TEST_CASE(&write_symmetric_filter));
+ test->add(BOOST_TEST_CASE(&close_symmetric_filter));
+#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+ test->add(BOOST_TEST_CASE(&wide_symmetric_filter));
+#endif
+ return test;
+}
+
+#include <boost/iostreams/detail/config/enable_warnings.hpp>
diff --git a/libs/iostreams/test/tee_test.cpp b/libs/iostreams/test/tee_test.cpp
new file mode 100644
index 0000000000..fbc724fce3
--- /dev/null
+++ b/libs/iostreams/test/tee_test.cpp
@@ -0,0 +1,370 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#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"
+
+using namespace std;
+using namespace boost;
+using namespace boost::iostreams;
+using namespace boost::iostreams::test;
+using boost::unit_test::test_suite;
+
+void read_write_test()
+{
+ {
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push(tee(file_sink(dest.name(), out_mode)));
+ first.push(file_source(src1.name(), in_mode));
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chars(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_filter in chars"
+ );
+ }
+
+ {
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push(tee(file_sink(dest.name(), out_mode)));
+ first.push(file_source(src1.name(), in_mode));
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chunks(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_filter in chunks"
+ );
+ }
+
+ {
+ temp_file dest1;
+ temp_file dest2;
+ filtering_ostream out;
+ out.push(tee(file_sink(dest1.name(), out_mode)));
+ out.push(file_sink(dest2.name(), out_mode));
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), dest2.name()),
+ "failed writing to a tee_filter in chars"
+ );
+ }
+
+ {
+ temp_file dest1;
+ temp_file dest2;
+ filtering_ostream out;
+ out.push(tee(file_sink(dest1.name(), out_mode)));
+ out.push(file_sink(dest2.name(), out_mode));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), dest2.name()),
+ "failed writing to a tee_filter in chunks"
+ );
+ }
+
+ {
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push( tee( file_source(src1.name(), in_mode),
+ file_sink(dest.name(), out_mode) ) );
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chars(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_device in chars"
+ );
+ }
+
+ {
+ test_file src1, src2;
+ temp_file dest;
+ filtering_istream first, second;
+ first.push( tee( file_source(src1.name(), in_mode),
+ file_sink(dest.name(), out_mode) ) );
+ second.push(file_source(src2.name(), in_mode));
+ compare_streams_in_chunks(first, second); // ignore return value
+ first.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), src1.name()),
+ "failed reading from a tee_device in chunks"
+ );
+ }
+
+ {
+ temp_file dest1;
+ temp_file dest2;
+ filtering_ostream out;
+ out.push( tee( file_sink(dest1.name(), out_mode),
+ file_sink(dest2.name(), out_mode) ) );
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), dest2.name()),
+ "failed writing to a tee_device in chars"
+ );
+ }
+
+ {
+ temp_file dest1;
+ temp_file dest2;
+ filtering_ostream out;
+ out.push( tee( file_sink(dest1.name(), out_mode),
+ file_sink(dest2.name(), out_mode) ) );
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest1.name(), dest2.name()),
+ "failed writing to a tee_device in chunks"
+ );
+ }
+}
+
+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(
+ boost::iostreams::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(
+ boost::iostreams::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(
+ boost::iostreams::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(boost::iostreams::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(
+ boost::iostreams::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(boost::iostreams::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(
+ boost::iostreams::tee(
+ boost::iostreams::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(
+ boost::iostreams::tee(
+ boost::iostreams::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(
+ boost::iostreams::tee(
+ boost::iostreams::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(
+ boost::iostreams::tee(
+ boost::iostreams::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(
+ boost::iostreams::tee(
+ boost::iostreams::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(
+ boost::iostreams::tee(
+ boost::iostreams::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(&read_write_test));
+ test->add(BOOST_TEST_CASE(&close_test));
+ return test;
+}
diff --git a/libs/iostreams/test/wide_stream_test.cpp b/libs/iostreams/test/wide_stream_test.cpp
new file mode 100644
index 0000000000..425485ad1a
--- /dev/null
+++ b/libs/iostreams/test/wide_stream_test.cpp
@@ -0,0 +1,145 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <boost/iostreams/detail/config/wide_streams.hpp>
+#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS
+# error wide streams not supported on this platform
+#endif
+
+#include <sstream>
+#include <vector>
+#include <boost/iostreams/device/back_inserter.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "../example/container_device.hpp" // We use container_device instead
+#include "detail/filters.hpp" // of make_iterator_range to
+#include "detail/sequence.hpp" // reduce dependence on Boost.Range
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+using boost::unit_test::test_suite;
+
+void read_wide_input_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::example;
+ using namespace boost::iostreams::test;
+
+ test_sequence<wchar_t> seq;
+ container_device< test_sequence<wchar_t> > source(seq);
+
+ {
+ filtering_wistream first(source, 0);
+ basic_istringstream<wchar_t> second(
+ basic_string<wchar_t>(seq.begin(), seq.end())
+ );
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a filter_wistream in chars with no buffer"
+ );
+ }
+
+ {
+ filtering_wistream first(source, 0);
+ basic_istringstream<wchar_t> second(
+ basic_string<wchar_t>(seq.begin(), seq.end())
+ );
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a filter_wistream in chunks with no buffer"
+ );
+ }
+
+ {
+ filtering_wistream first(source);
+ basic_istringstream<wchar_t> second(
+ basic_string<wchar_t>(seq.begin(), seq.end())
+ );
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chars(first, second),
+ "failed reading from a filter_wistream in chars with large buffer"
+ );
+ }
+
+ {
+ filtering_wistream first(source);
+ basic_istringstream<wchar_t> second(
+ basic_string<wchar_t>(seq.begin(), seq.end())
+ );
+ BOOST_CHECK_MESSAGE(
+ compare_streams_in_chunks(first, second),
+ "failed reading from a filter_wistream in chunks with large buffer"
+ );
+ }
+}
+
+void write_wide_output_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ {
+ vector<wchar_t> first;
+ test_sequence<wchar_t> second;
+ filtering_wostream out(iostreams::back_inserter(first), 0);
+ write_data_in_chars(out);
+ BOOST_CHECK_MESSAGE(
+ first.size() == second.size() &&
+ std::equal(first.begin(), first.end(), second.begin()),
+ "failed writing to filtering_wostream in chars with no buffer"
+ );
+ }
+
+ {
+ vector<wchar_t> first;
+ test_sequence<wchar_t> second;
+ filtering_wostream out(iostreams::back_inserter(first), 0);
+ write_data_in_chunks(out);
+ BOOST_CHECK_MESSAGE(
+ first.size() == second.size() &&
+ std::equal(first.begin(), first.end(), second.begin()),
+ "failed writing to filtering_wostream in chunks with no buffer"
+ );
+ }
+
+ {
+ vector<wchar_t> first;
+ test_sequence<wchar_t> second;
+ filtering_wostream out(iostreams::back_inserter(first), 0);
+ write_data_in_chars(out);
+ BOOST_CHECK_MESSAGE(
+ first.size() == second.size() &&
+ std::equal(first.begin(), first.end(), second.begin()),
+ "failed writing to filtering_wostream in chars with large buffer"
+ );
+ }
+
+ {
+ vector<wchar_t> first;
+ test_sequence<wchar_t> second;
+ filtering_wostream out(iostreams::back_inserter(first));
+ write_data_in_chunks(out);
+ BOOST_CHECK_MESSAGE(
+ first.size() == second.size() &&
+ std::equal(first.begin(), first.end(), second.begin()),
+ "failed writing to filtering_wostream in chunks with large buffer"
+ );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("wide stream test");
+ test->add(BOOST_TEST_CASE(&read_wide_input_test));
+ test->add(BOOST_TEST_CASE(&write_wide_output_test));
+ return test;
+}
diff --git a/libs/iostreams/test/write_bidir_filter_test.hpp b/libs/iostreams/test/write_bidir_filter_test.hpp
new file mode 100644
index 0000000000..8865ec1805
--- /dev/null
+++ b/libs/iostreams/test/write_bidir_filter_test.hpp
@@ -0,0 +1,134 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_INOUT_FILTER_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_INOUT_FILTER_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/combine.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/filters.hpp"
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_bidirectional_filter_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ lowercase_file lower;
+ BOOST_IOS::openmode mode = out_mode | BOOST_IOS::trunc;
+
+ {
+ temp_file lower2;
+ filebuf dest;
+ filtering_stream<bidirectional> out;
+ dest.open(lower2.name().c_str(), mode);
+ out.push(combine(toupper_filter(), tolower_filter()));
+ out.push(dest);
+ write_data_in_chars(out);
+ out.reset();
+ dest.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(lower2.name(), lower.name()),
+ "failed writing to a filtering_stream<bidirectional> in chars with an "
+ "output filter"
+ );
+ }
+
+ {
+ // OutputFilter.
+ temp_file lower2;
+ filebuf dest;
+ filtering_stream<bidirectional> out;
+ out.push(combine(toupper_filter(), tolower_filter()));
+ dest.open(lower2.name().c_str(), mode);
+ out.push(dest);
+ write_data_in_chunks(out);
+ out.reset();
+ dest.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(lower2.name(), lower.name()),
+ "failed writing to a filtering_stream<bidirectional> in chunks with an "
+ "output filter"
+ );
+ }
+
+ {
+ temp_file lower2;
+ filebuf dest;
+ filtering_stream<bidirectional> out;
+ out.push(combine(toupper_filter(), tolower_multichar_filter()), 0);
+ dest.open(lower2.name().c_str(), mode);
+ out.push(dest);
+ write_data_in_chars(out);
+ out.reset();
+ dest.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(lower2.name(), lower.name()),
+ "failed writing to a filtering_stream<bidirectional> in chars "
+ "with a multichar output filter with no buffer"
+ );
+ }
+
+ {
+ temp_file lower2;
+ filebuf dest;
+ filtering_stream<bidirectional> out;
+ out.push(combine(toupper_filter(), tolower_multichar_filter()), 0);
+ dest.open(lower2.name().c_str(), mode);
+ out.push(dest);
+ write_data_in_chunks(out);
+ out.reset();
+ dest.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(lower2.name(), lower.name()),
+ "failed writing to a filtering_stream<bidirectional> in chunks "
+ "with a multichar output filter with no buffer"
+ );
+ }
+
+ {
+ temp_file lower2;
+ filebuf dest;
+ filtering_stream<bidirectional> out;
+ out.push(combine(toupper_filter(), tolower_multichar_filter()));
+ dest.open(lower2.name().c_str(), mode);
+ out.push(dest);
+ write_data_in_chars(out);
+ out.reset();
+ dest.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(lower2.name(), lower.name()),
+ "failed writing to a filtering_stream<bidirectional> in chars "
+ "with a multichar output filter"
+ );
+ }
+
+ {
+ temp_file lower2;
+ filebuf dest;
+ filtering_stream<bidirectional> out;
+ out.push(combine(toupper_filter(), tolower_multichar_filter()));
+ dest.open(lower2.name().c_str(), mode);
+ out.push(dest);
+ write_data_in_chunks(out);
+ out.reset();
+ dest.close();
+ BOOST_CHECK_MESSAGE(
+ compare_files(lower2.name(), lower.name()),
+ "failed writing to a filtering_stream<bidirectional> in chunks "
+ "with a buffered output filter"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_FILTER_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_bidir_streambuf_test.hpp b/libs/iostreams/test/write_bidir_streambuf_test.hpp
new file mode 100644
index 0000000000..7dadaca08f
--- /dev/null
+++ b/libs/iostreams/test/write_bidir_streambuf_test.hpp
@@ -0,0 +1,87 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_bidirectional_streambuf_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ temp_file test2;
+ {
+ filebuf dest;
+ dest.open(test2.name().c_str(), out_mode);
+ filtering_stream<bidirectional> out(dest, 0);
+ write_data_in_chars(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> based "
+ "on a streambuf in chars with no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ {
+ filebuf dest;
+ dest.open(test2.name().c_str(), out_mode);
+ filtering_stream<bidirectional> out(dest, 0);
+ write_data_in_chunks(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> based "
+ "on a streambuf in chunks with no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ {
+ filebuf dest;
+ dest.open(test2.name().c_str(), out_mode);
+ filtering_stream<bidirectional> out(dest);
+ write_data_in_chars(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> based "
+ "on a streambuf in chars with large buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ {
+ filebuf dest;
+ dest.open(test2.name().c_str(), out_mode);
+ filtering_stream<bidirectional> out(dest);
+ write_data_in_chunks(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> based "
+ "on a streambuf in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_STREAMBUF_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_bidir_test.hpp b/libs/iostreams/test/write_bidir_test.hpp
new file mode 100644
index 0000000000..12cc3ef5d9
--- /dev/null
+++ b/libs/iostreams/test/write_bidir_test.hpp
@@ -0,0 +1,89 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/combine.hpp>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_bidirectional_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ temp_file dest;
+ temp_file src; // Dummy;
+ filtering_stream<bidirectional> out(
+ combine(file_source(src.name()), file_sink(dest.name(), out_mode)), 0
+ );
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> in chars "
+ "with no buffer"
+ );
+ }
+
+ {
+ temp_file dest;
+ temp_file src; // Dummy;
+ filtering_stream<bidirectional> out(
+ combine(file_source(src.name()), file_sink(dest.name(), out_mode)), 0
+ );
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> in chunks "
+ "with no buffer"
+ );
+ }
+
+ {
+ temp_file dest;
+ temp_file src; // Dummy;
+ filtering_stream<bidirectional> out(
+ combine(file_source(src.name()), file_sink(dest.name(), out_mode))
+ );
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> in chars "
+ "with large buffer"
+ );
+ }
+
+ {
+ temp_file dest;
+ temp_file src; // Dummy;
+ filtering_stream<bidirectional> out(
+ combine(file_source(src.name()), file_sink(dest.name(), out_mode))
+ );
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), test.name()),
+ "failed writing to filtering_stream<bidirectional> in chunks "
+ "with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_BIDIRECTIONAL_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_output_filter_test.hpp b/libs/iostreams/test/write_output_filter_test.hpp
new file mode 100644
index 0000000000..34a367319c
--- /dev/null
+++ b/libs/iostreams/test/write_output_filter_test.hpp
@@ -0,0 +1,114 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_FILTER_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_FILTER_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/filters.hpp"
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_output_filter_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ lowercase_file lower;
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_filter());
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chars with an "
+ "output filter"
+ );
+ }
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_filter());
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chunks with an "
+ "output filter"
+ );
+ }
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_multichar_filter(), 0);
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chars with a "
+ "multichar output filter with no buffer"
+ );
+ }
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_multichar_filter(), 0);
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chunks with a "
+ "multichar output filter with no buffer"
+ );
+ }
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_multichar_filter());
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chars with a "
+ "multichar output filter"
+ );
+ }
+
+ {
+ temp_file dest;
+ filtering_ostream out;
+ out.push(tolower_multichar_filter());
+ out.push(file_sink(dest.name(), out_mode));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(dest.name(), lower.name()),
+ "failed writing to a filtering_ostream in chunks with a "
+ "multichar output filter"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_FILTER_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_output_iterator_test.hpp b/libs/iostreams/test/write_output_iterator_test.hpp
new file mode 100644
index 0000000000..6cedc16185
--- /dev/null
+++ b/libs/iostreams/test/write_output_iterator_test.hpp
@@ -0,0 +1,85 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_ITERATOR_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_ITERATOR_HPP_INCLUDED
+
+#include <fstream>
+#include <iterator> // Back inserter.
+#include <vector>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+// Note: adding raw inserter iterators to chains is not supported
+// on VC6.
+
+void write_output_iterator_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ vector<char> first;
+ filtering_ostream out;
+ out.push(std::back_inserter(first), 0);
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on an "
+ "output iterator in chars with no buffer"
+ );
+ }
+
+ {
+ vector<char> first;
+ filtering_ostream out;
+ out.push(std::back_inserter(first), 0);
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on an "
+ "output iterator in chunks with no buffer"
+ );
+ }
+
+ {
+ vector<char> first;
+ filtering_ostream out;
+ out.push(std::back_inserter(first));
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on an "
+ "output iterator in chars with large buffer"
+ );
+ }
+
+ {
+ vector<char> first;
+ filtering_ostream out;
+ out.push(std::back_inserter(first));
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on an "
+ "output iterator in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_ITERATOR_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_output_ostream_test.hpp b/libs/iostreams/test/write_output_ostream_test.hpp
new file mode 100644
index 0000000000..c6dd713f1a
--- /dev/null
+++ b/libs/iostreams/test/write_output_ostream_test.hpp
@@ -0,0 +1,84 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_OSTREAM_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_OSTREAM_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_output_ostream_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ temp_file test2;
+ {
+ ofstream dest(test2.name().c_str(), out_mode);
+ filtering_ostream out(dest, 0);
+ write_data_in_chars(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream based on an ostream "
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ {
+ ofstream dest(test2.name().c_str(), out_mode);
+ filtering_ostream out(dest, 0);
+ write_data_in_chunks(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream based on an ostream "
+ "in chunks with no buffer"
+ );
+ }
+
+ {
+ test_file test2;
+ {
+ ofstream dest(test2.name().c_str(), out_mode);
+ filtering_ostream out(dest);
+ write_data_in_chars(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream based on an ostream "
+ "in chars with large buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ {
+ ofstream dest(test2.name().c_str(), out_mode);
+ filtering_ostream out(dest);
+ write_data_in_chunks(out);
+ }
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream based on an ostream "
+ "in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_OSTREAM_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_output_seq_test.hpp b/libs/iostreams/test/write_output_seq_test.hpp
new file mode 100644
index 0000000000..2ff5fb4492
--- /dev/null
+++ b/libs/iostreams/test/write_output_seq_test.hpp
@@ -0,0 +1,78 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_SEQUENCE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_SEQUENCE_HPP_INCLUDED
+
+#include <fstream>
+#include <vector>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_output_sequence_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_ostream out(make_iterator_range(first), 0);
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on a sequence "
+ "in chars with no buffer"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_ostream out(make_iterator_range(first), 0);
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on a sequence "
+ "in chunks with no buffer"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_ostream out(make_iterator_range(first));
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on a sequence "
+ "in chars with large buffer"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_ostream out(make_iterator_range(first));
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_ostream based on a sequence "
+ "in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_SEQUENCE_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_output_test.hpp b/libs/iostreams/test/write_output_test.hpp
new file mode 100644
index 0000000000..d8e56abff8
--- /dev/null
+++ b/libs/iostreams/test/write_output_test.hpp
@@ -0,0 +1,73 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_output_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ temp_file test2;
+ filtering_ostream out(file_sink(test2.name(), out_mode), 0);
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream in chars with no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ filtering_ostream out(file_sink(test2.name(), out_mode), 0);
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream in chunks with no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ filtering_ostream out(file_sink(test2.name(), out_mode));
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream in chars with buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ filtering_ostream out(file_sink(test2.name(), out_mode));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_ostream in chunks with buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_OUTPUT_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_seekable_seq_test.hpp b/libs/iostreams/test/write_seekable_seq_test.hpp
new file mode 100644
index 0000000000..5fce08fb8c
--- /dev/null
+++ b/libs/iostreams/test/write_seekable_seq_test.hpp
@@ -0,0 +1,79 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_SEQUENCE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_SEQUENCE_HPP_INCLUDED
+
+#include <fstream>
+#include <vector>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/sequence.hpp"
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_seekable_sequence_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_stream<seekable> out(make_iterator_range(first), 0);
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_stream<seekable> based on a "
+ "sequence in chars with no buffer"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_stream<seekable> out(make_iterator_range(first), 0);
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_stream<seekable> based on a "
+ "sequence in chunks with no buffer"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_stream<seekable> out(make_iterator_range(first));
+ write_data_in_chars(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_stream<seekable> based on a "
+ "sequence in chars with large buffer"
+ );
+ }
+
+ {
+ vector<char> first(data_reps * data_length(), '?');
+ filtering_stream<seekable> out(make_iterator_range(first));
+ write_data_in_chunks(out);
+ ifstream second(test.name().c_str());
+ BOOST_CHECK_MESSAGE(
+ compare_container_and_stream(first, second),
+ "failed writing to filtering_stream<seekable> based on a "
+ "sequence in chunks with large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_SEQUENCE_HPP_INCLUDED
diff --git a/libs/iostreams/test/write_seekable_test.hpp b/libs/iostreams/test/write_seekable_test.hpp
new file mode 100644
index 0000000000..cf83d0e86e
--- /dev/null
+++ b/libs/iostreams/test/write_seekable_test.hpp
@@ -0,0 +1,77 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_HPP_INCLUDED
+#define BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_HPP_INCLUDED
+
+#include <fstream>
+#include <boost/iostreams/device/file.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include "detail/temp_file.hpp"
+#include "detail/verification.hpp"
+
+void write_seekable_test()
+{
+ using namespace std;
+ using namespace boost;
+ using namespace boost::iostreams;
+ using namespace boost::iostreams::test;
+
+ test_file test;
+ BOOST_IOS::openmode mode = out_mode | BOOST_IOS::trunc;
+
+ {
+ temp_file test2;
+ filtering_stream<seekable> out(file(test2.name(), mode), 0);
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<seekable> in chars with"
+ "no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ filtering_stream<seekable> out(file(test2.name(), mode), 0);
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<seekable> in chunks with"
+ "no buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ filtering_stream<seekable> out(file(test2.name(), mode));
+ write_data_in_chars(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<seekable> in chars with"
+ "large buffer"
+ );
+ }
+
+ {
+ temp_file test2;
+ filtering_stream<seekable> out(file(test2.name(), mode));
+ write_data_in_chunks(out);
+ out.reset();
+ BOOST_CHECK_MESSAGE(
+ compare_files(test2.name(), test.name()),
+ "failed writing to filtering_stream<seekable> in chunks with"
+ "large buffer"
+ );
+ }
+}
+
+#endif // #ifndef BOOST_IOSTREAMS_TEST_WRITE_SEEKABLE_HPP_INCLUDED
diff --git a/libs/iostreams/test/zlib_test.cpp b/libs/iostreams/test/zlib_test.cpp
new file mode 100644
index 0000000000..17ab340993
--- /dev/null
+++ b/libs/iostreams/test/zlib_test.cpp
@@ -0,0 +1,60 @@
+// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
+// (C) Copyright 2004-2007 Jonathan Turkanis
+// 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.
+
+#include <string>
+#include <boost/iostreams/filter/test.hpp>
+#include <boost/iostreams/filter/zlib.hpp>
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/test/test_tools.hpp>
+#include <boost/test/unit_test.hpp>
+#include "detail/sequence.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;
+
+struct zlib_alloc : std::allocator<char> { };
+
+void zlib_test()
+{
+ text_sequence data;
+ BOOST_CHECK(
+ test_filter_pair( zlib_compressor(),
+ zlib_decompressor(),
+ std::string(data.begin(), data.end()) )
+ );
+ BOOST_CHECK(
+ test_filter_pair( basic_zlib_compressor<zlib_alloc>(),
+ basic_zlib_decompressor<zlib_alloc>(),
+ std::string(data.begin(), data.end()) )
+ );
+ BOOST_CHECK(
+ test_filter_pair( zlib_compressor(),
+ zlib_decompressor(),
+ std::string() )
+ );
+ {
+ filtering_istream strm;
+ strm.push( zlib_compressor() );
+ strm.push( null_source() );
+ }
+ {
+ filtering_istream strm;
+ strm.push( zlib_decompressor() );
+ strm.push( null_source() );
+ }
+}
+
+test_suite* init_unit_test_suite(int, char* [])
+{
+ test_suite* test = BOOST_TEST_SUITE("zlib test");
+ test->add(BOOST_TEST_CASE(&zlib_test));
+ return test;
+}