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.)
6 // See http://www.boost.org/libs/iostreams for documentation.
9 #include <boost/iostreams/compose.hpp>
10 #include <boost/iostreams/device/file.hpp>
11 #include <boost/iostreams/filtering_stream.hpp>
12 #include <boost/test/test_tools.hpp>
13 #include <boost/test/unit_test.hpp>
14 #include "detail/closable.hpp"
15 #include "detail/operation_sequence.hpp"
16 #include "detail/filters.hpp"
17 #include "detail/temp_file.hpp"
18 #include "detail/verification.hpp"
21 #include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x.
24 using namespace boost::iostreams;
25 using namespace boost::iostreams::test;
26 using boost::unit_test::test_suite;
27 namespace io = boost::iostreams;
32 filtering_istream first, second;
34 // Test composite device
35 first.push(toupper_filter());
36 first.push(padding_filter('a'));
37 first.push(file_source(src1.name(), in_mode));
38 second.push( compose( toupper_filter(),
39 compose( padding_filter('a'),
40 file_source(src1.name(), in_mode) ) ) );
42 compare_streams_in_chunks(first, second),
43 "failed reading from a stdio_filter"
46 // Test composite filter
49 first.push(toupper_filter());
50 first.push(padding_filter('a'));
51 first.push(file_source(src1.name(), in_mode));
52 second.push( compose( compose( toupper_filter(),
53 padding_filter('a') ),
54 file_source(src1.name(), in_mode) ) );
56 compare_streams_in_chunks(first, second),
57 "failed reading from a stdio_filter"
61 void write_composite()
63 temp_file dest1, dest2;
64 filtering_ostream out1, out2;
66 // Test composite device
67 out1.push(tolower_filter());
68 out1.push(padding_filter('a'));
69 out1.push(file_sink(dest1.name(), in_mode));
70 out2.push( compose( tolower_filter(),
71 compose( padding_filter('a'),
72 file_sink(dest2.name(), in_mode) ) ) );
73 write_data_in_chunks(out1);
74 write_data_in_chunks(out2);
79 ifstream first(dest1.name().c_str());
80 ifstream second(dest2.name().c_str());
82 compare_streams_in_chunks(first, second),
83 "failed writing to a stdio_filter"
87 // Test composite filter
88 out1.push(tolower_filter());
89 out1.push(padding_filter('a'));
90 out1.push(file_sink(dest1.name(), in_mode));
91 out2.push( compose( compose( tolower_filter(),
92 padding_filter('a') ),
93 file_sink(dest2.name(), in_mode) ) );
94 write_data_in_chunks(out1);
95 write_data_in_chunks(out2);
100 ifstream first(dest1.name().c_str());
101 ifstream second(dest2.name().c_str());
103 compare_streams_in_chunks(first, second),
104 "failed writing to a stdio_filter"
109 void close_composite_device()
111 // Compose an input filter with a source
113 operation_sequence seq;
117 closable_filter<input>(seq.new_operation(2)),
118 closable_device<input>(seq.new_operation(1))
121 BOOST_CHECK_NO_THROW(ch.reset());
122 BOOST_CHECK_OPERATION_SEQUENCE(seq);
125 // Compose a bidirectional filter with a source
127 operation_sequence seq;
131 closable_filter<bidirectional>(
132 seq.new_operation(2),
135 closable_device<input>(seq.new_operation(1))
138 BOOST_CHECK_NO_THROW(ch.reset());
139 BOOST_CHECK_OPERATION_SEQUENCE(seq);
142 // Compose a seekable filter with a source
144 operation_sequence seq;
148 closable_filter<seekable>(seq.new_operation(2)),
149 closable_device<input>(seq.new_operation(1))
152 BOOST_CHECK_NO_THROW(ch.reset());
153 BOOST_CHECK_OPERATION_SEQUENCE(seq);
156 // Compose a dual-use filter with a source
158 operation_sequence seq;
163 closable_filter<dual_use>(
164 seq.new_operation(2),
167 closable_device<input>(seq.new_operation(1))
170 BOOST_CHECK_NO_THROW(ch.reset());
171 BOOST_CHECK_OPERATION_SEQUENCE(seq);
174 // Compose an output filter with a sink
176 operation_sequence seq;
180 closable_filter<output>(seq.new_operation(1)),
181 closable_device<output>(seq.new_operation(2))
184 BOOST_CHECK_NO_THROW(ch.reset());
185 BOOST_CHECK_OPERATION_SEQUENCE(seq);
188 // Compose a bidirectional filter with a sink
190 operation_sequence seq;
194 closable_filter<bidirectional>(
195 seq.new_operation(1),
198 closable_device<output>(seq.new_operation(3))
201 BOOST_CHECK_NO_THROW(ch.reset());
202 BOOST_CHECK_OPERATION_SEQUENCE(seq);
205 // Compose a seekable filter with a sink
207 operation_sequence seq;
211 closable_filter<seekable>(seq.new_operation(1)),
212 closable_device<output>(seq.new_operation(2))
215 BOOST_CHECK_NO_THROW(ch.reset());
216 BOOST_CHECK_OPERATION_SEQUENCE(seq);
219 // Compose a dual-use filter with a sink
221 operation_sequence seq;
226 closable_filter<dual_use>(
230 closable_device<output>(seq.new_operation(2))
233 BOOST_CHECK_NO_THROW(ch.reset());
234 BOOST_CHECK_OPERATION_SEQUENCE(seq);
237 // Compose a bidirectional filter with a bidirectional device
239 operation_sequence seq;
240 chain<bidirectional> ch;
243 closable_filter<bidirectional>(
244 seq.new_operation(2),
247 closable_device<bidirectional>(
248 seq.new_operation(1),
253 BOOST_CHECK_NO_THROW(ch.reset());
254 BOOST_CHECK_OPERATION_SEQUENCE(seq);
257 // Compose a seekable filter with a seekable device
259 operation_sequence seq;
263 closable_filter<seekable>(seq.new_operation(1)),
264 closable_device<seekable>(seq.new_operation(2))
267 BOOST_CHECK_NO_THROW(ch.reset());
268 BOOST_CHECK_OPERATION_SEQUENCE(seq);
272 void close_composite_filter()
274 // Compose two input filters
276 operation_sequence seq;
280 closable_filter<input>(seq.new_operation(3)),
281 closable_filter<input>(seq.new_operation(2))
284 ch.push(closable_device<input>(seq.new_operation(1)));
285 BOOST_CHECK_NO_THROW(ch.reset());
286 BOOST_CHECK_OPERATION_SEQUENCE(seq);
289 // Compose a bidirectional filter with an input filter
291 operation_sequence seq;
295 closable_filter<bidirectional>(
296 seq.new_operation(3),
299 closable_filter<input>(seq.new_operation(2))
302 ch.push(closable_device<input>(seq.new_operation(1)));
303 BOOST_CHECK_NO_THROW(ch.reset());
304 BOOST_CHECK_MESSAGE(seq.is_success(), seq.message());
307 // Compose a seekable filter with an input filter
309 operation_sequence seq;
313 closable_filter<seekable>(seq.new_operation(3)),
314 closable_filter<input>(seq.new_operation(2))
317 ch.push(closable_device<input>(seq.new_operation(1)));
318 BOOST_CHECK_NO_THROW(ch.reset());
319 BOOST_CHECK_OPERATION_SEQUENCE(seq);
322 // Compose a dual-use filter with an input filter
324 operation_sequence seq;
329 closable_filter<dual_use>(
330 seq.new_operation(3),
333 closable_filter<input>(seq.new_operation(2))
336 ch.push(closable_device<input>(seq.new_operation(1)));
337 BOOST_CHECK_NO_THROW(ch.reset());
338 BOOST_CHECK_OPERATION_SEQUENCE(seq);
341 // Compose two output filters
343 operation_sequence seq;
347 closable_filter<output>(seq.new_operation(1)),
348 closable_filter<output>(seq.new_operation(2))
351 ch.push(closable_device<output>(seq.new_operation(3)));
352 BOOST_CHECK_NO_THROW(ch.reset());
353 BOOST_CHECK_OPERATION_SEQUENCE(seq);
356 // Compose a bidirectional filter with an output filter
358 operation_sequence seq;
362 closable_filter<bidirectional>(
363 seq.new_operation(1),
366 closable_filter<output>(seq.new_operation(3))
369 ch.push(closable_device<output>(seq.new_operation(4)));
370 BOOST_CHECK_NO_THROW(ch.reset());
371 BOOST_CHECK_OPERATION_SEQUENCE(seq);
374 // Compose a seekable filter with an output filter
376 operation_sequence seq;
380 closable_filter<seekable>(seq.new_operation(1)),
381 closable_filter<output>(seq.new_operation(2))
384 ch.push(closable_device<output>(seq.new_operation(3)));
385 BOOST_CHECK_NO_THROW(ch.reset());
386 BOOST_CHECK_OPERATION_SEQUENCE(seq);
389 // Compose a dual-use filter with an output filter
391 operation_sequence seq;
396 closable_filter<dual_use>(
400 closable_filter<output>(seq.new_operation(2))
403 ch.push(closable_device<output>(seq.new_operation(3)));
404 BOOST_CHECK_NO_THROW(ch.reset());
405 BOOST_CHECK_OPERATION_SEQUENCE(seq);
408 // Compose two bidirectional filters
410 operation_sequence seq;
411 chain<bidirectional> ch;
414 closable_filter<bidirectional>(
415 seq.new_operation(3),
418 closable_filter<bidirectional>(
419 seq.new_operation(2),
425 closable_device<bidirectional>(
426 seq.new_operation(1),
430 BOOST_CHECK_NO_THROW(ch.reset());
431 BOOST_CHECK_OPERATION_SEQUENCE(seq);
434 // Compose two seekable filters
436 operation_sequence seq;
440 closable_filter<seekable>(seq.new_operation(1)),
441 closable_filter<seekable>(seq.new_operation(2))
444 ch.push(closable_device<seekable>(seq.new_operation(3)));
445 BOOST_CHECK_NO_THROW(ch.reset());
446 BOOST_CHECK_OPERATION_SEQUENCE(seq);
449 // Compose two dual-use filters for input
451 operation_sequence seq;
456 closable_filter<dual_use>(
457 seq.new_operation(3),
460 closable_filter<dual_use>(
461 seq.new_operation(2),
466 ch.push(closable_device<input>(seq.new_operation(1)));
467 BOOST_CHECK_NO_THROW(ch.reset());
468 BOOST_CHECK_OPERATION_SEQUENCE(seq);
471 // Compose two dual-use filters for output
473 operation_sequence seq;
478 closable_filter<dual_use>(
482 closable_filter<dual_use>(
488 ch.push(closable_device<output>(seq.new_operation(3)));
489 BOOST_CHECK_NO_THROW(ch.reset());
490 BOOST_CHECK_OPERATION_SEQUENCE(seq);
494 test_suite* init_unit_test_suite(int, char* [])
496 test_suite* test = BOOST_TEST_SUITE("line_filter test");
497 test->add(BOOST_TEST_CASE(&read_composite));
498 test->add(BOOST_TEST_CASE(&write_composite));
499 test->add(BOOST_TEST_CASE(&close_composite_device));
500 test->add(BOOST_TEST_CASE(&close_composite_filter));
504 #include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x.