1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2004-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 #include <cstdio>  // EOF.
9 #include <boost/iostreams/filtering_stream.hpp>
10 #include <boost/iostreams/stream.hpp>
11 #include <boost/shared_ptr.hpp>
12 #include <boost/test/test_tools.hpp>
13 #include <boost/test/unit_test.hpp>
14 #include "detail/temp_file.hpp"
15 #include "detail/verification.hpp"
16 
17 using namespace std;
18 using namespace boost;
19 using namespace boost::iostreams;
20 using namespace boost::iostreams::test;
21 using boost::unit_test::test_suite;
22 
23 class closable_source : public source {
24 public:
closable_source()25     closable_source() : open_(new bool(true)) { }
read(char *,std::streamsize)26     std::streamsize read(char*, std::streamsize) { return 0; }
open()27     void open() { *open_ = true; }
close()28     void close() { *open_ = false; }
is_open() const29     bool is_open() const { return *open_; }
30 private:
31     boost::shared_ptr<bool> open_;
32 };
33 
34 class closable_input_filter : public input_filter {
35 public:
closable_input_filter()36     closable_input_filter() : open_(new bool(true)) { }
37 
38     template<typename Source>
get(Source &)39     int get(Source&) { return EOF; }
40 
open()41     void open() { *open_ = true; }
42 
43     template<typename Source>
close(Source &)44     void close(Source&) { *open_ = false; }
45 
is_open() const46     bool is_open() const { return *open_; }
47 private:
48     boost::shared_ptr<bool> open_;
49 };
50 
auto_close_source()51 void auto_close_source()
52 {
53     // Rely on auto_close to close source.
54     closable_source src;
55     {
56         stream<closable_source> in(src);
57         BOOST_CHECK(src.is_open());
58         BOOST_CHECK(in.auto_close());
59     }
60     BOOST_CHECK(!src.is_open());
61 
62     // Use close() to close components.
63     src.open();
64     {
65         stream<closable_source> in(src);
66         BOOST_CHECK(src.is_open());
67         BOOST_CHECK(in.auto_close());
68         in.close();
69         BOOST_CHECK(!src.is_open());
70     }
71 
72     // Use close() to close components, with auto_close disabled.
73     src.open();
74     {
75         stream<closable_source> in(src);
76         BOOST_CHECK(src.is_open());
77         in.set_auto_close(false);
78         in.close();
79         BOOST_CHECK(!src.is_open());
80     }
81 
82     // Disable auto_close.
83     src.open();
84     {
85         stream<closable_source> in(src);
86         BOOST_CHECK(src.is_open());
87         in.set_auto_close(false);
88         BOOST_CHECK(!in.auto_close());
89     }
90     BOOST_CHECK(src.is_open());
91 }
92 
auto_close_filter()93 void auto_close_filter()
94 {
95     closable_source        src;
96     closable_input_filter  flt;
97 
98     // Rely on auto_close to close components.
99     {
100         filtering_istream in;
101         in.push(flt);
102         in.push(src);
103         BOOST_CHECK(flt.is_open());
104         BOOST_CHECK(src.is_open());
105         BOOST_CHECK(in.auto_close());
106     }
107     BOOST_CHECK(!flt.is_open());
108     BOOST_CHECK(!src.is_open());
109 
110     // Use reset() to close components.
111     flt.open();
112     src.open();
113     {
114         filtering_istream in;
115         in.push(flt);
116         in.push(src);
117         BOOST_CHECK(flt.is_open());
118         BOOST_CHECK(src.is_open());
119         BOOST_CHECK(in.auto_close());
120         in.reset();
121         BOOST_CHECK(!flt.is_open());
122         BOOST_CHECK(!src.is_open());
123     }
124 
125     // Use reset() to close components, with auto_close disabled.
126     flt.open();
127     src.open();
128     {
129         filtering_istream in;
130         in.push(flt);
131         in.push(src);
132         BOOST_CHECK(flt.is_open());
133         BOOST_CHECK(src.is_open());
134         in.set_auto_close(false);
135         in.reset();
136         BOOST_CHECK(!flt.is_open());
137         BOOST_CHECK(!src.is_open());
138     }
139 
140     // Disable auto_close.
141     flt.open();
142     src.open();
143     {
144         filtering_istream in;
145         in.push(flt);
146         in.push(src);
147         BOOST_CHECK(flt.is_open());
148         BOOST_CHECK(src.is_open());
149         in.set_auto_close(false);
150         BOOST_CHECK(!in.auto_close());
151         in.pop();
152         BOOST_CHECK(flt.is_open());
153         BOOST_CHECK(src.is_open());
154     }
155     BOOST_CHECK(!flt.is_open());
156     BOOST_CHECK(src.is_open());
157 
158     // Disable auto_close; disconnect and reconnect resource.
159     flt.open();
160     src.open();
161     {
162         filtering_istream in;
163         in.push(flt);
164         in.push(src);
165         BOOST_CHECK(flt.is_open());
166         BOOST_CHECK(src.is_open());
167         in.set_auto_close(false);
168         BOOST_CHECK(!in.auto_close());
169         in.pop();
170         BOOST_CHECK(flt.is_open());
171         BOOST_CHECK(src.is_open());
172         in.push(src);
173     }
174     BOOST_CHECK(!flt.is_open());
175     BOOST_CHECK(!src.is_open());
176 }
177 
init_unit_test_suite(int,char * [])178 test_suite* init_unit_test_suite(int, char* [])
179 {
180     test_suite* test = BOOST_TEST_SUITE("auto_close test");
181     test->add(BOOST_TEST_CASE(&auto_close_source));
182     test->add(BOOST_TEST_CASE(&auto_close_filter));
183     return test;
184 }
185