Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / iostreams / test / compose_test.cpp
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 <cctype>
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"
19
20 // Must come last.
21 #include <boost/iostreams/detail/config/disable_warnings.hpp> // BCC 5.x.
22
23 using namespace std;
24 using namespace boost::iostreams;
25 using namespace boost::iostreams::test;
26 using boost::unit_test::test_suite;
27 namespace io = boost::iostreams;
28
29 void read_composite()
30 {
31     test_file          src1, src2;
32     filtering_istream  first, second;
33
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) ) ) );
41     BOOST_CHECK_MESSAGE(
42         compare_streams_in_chunks(first, second),
43         "failed reading from a stdio_filter"
44     );
45
46     // Test composite filter
47     first.reset();
48     second.reset();
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) ) );
55     BOOST_CHECK_MESSAGE(
56         compare_streams_in_chunks(first, second),
57         "failed reading from a stdio_filter"
58     );
59 }
60
61 void write_composite()
62 {
63     temp_file          dest1, dest2;
64     filtering_ostream  out1, out2;
65
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);
75     out1.reset();
76     out2.reset();
77
78     {
79         ifstream first(dest1.name().c_str());
80         ifstream second(dest2.name().c_str());
81         BOOST_CHECK_MESSAGE(
82             compare_streams_in_chunks(first, second),
83             "failed writing to a stdio_filter"
84         );
85     }
86
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);
96     out1.reset();
97     out2.reset();
98
99     {
100         ifstream first(dest1.name().c_str());
101         ifstream second(dest2.name().c_str());
102         BOOST_CHECK_MESSAGE(
103             compare_streams_in_chunks(first, second),
104             "failed writing to a stdio_filter"
105         );
106     }
107 }
108
109 void close_composite_device()
110 {
111     // Compose an input filter with a source
112     {
113         operation_sequence  seq;
114         chain<input>        ch;
115         ch.push(
116             io::compose(
117                 closable_filter<input>(seq.new_operation(2)),
118                 closable_device<input>(seq.new_operation(1))
119             )
120         );
121         BOOST_CHECK_NO_THROW(ch.reset());
122         BOOST_CHECK_OPERATION_SEQUENCE(seq);
123     }
124
125     // Compose a bidirectional filter with a source
126     {
127         operation_sequence  seq;
128         chain<input>        ch;
129         ch.push(
130             io::compose(
131                 closable_filter<bidirectional>(
132                     seq.new_operation(2),
133                     seq.new_operation(3)
134                 ),
135                 closable_device<input>(seq.new_operation(1))
136             )
137         );
138         BOOST_CHECK_NO_THROW(ch.reset());
139         BOOST_CHECK_OPERATION_SEQUENCE(seq);
140     }
141
142     // Compose a seekable filter with a source
143     {
144         operation_sequence  seq;
145         chain<input>        ch;
146         ch.push(
147             io::compose(
148                 closable_filter<seekable>(seq.new_operation(2)),
149                 closable_device<input>(seq.new_operation(1))
150             )
151         );
152         BOOST_CHECK_NO_THROW(ch.reset());
153         BOOST_CHECK_OPERATION_SEQUENCE(seq);
154     }
155
156     // Compose a dual-use filter with a source
157     {
158         operation_sequence  seq;
159         chain<input>        ch;
160         operation           dummy;
161         ch.push(
162             io::compose(
163                 closable_filter<dual_use>(
164                     seq.new_operation(2),
165                     dummy
166                 ),
167                 closable_device<input>(seq.new_operation(1))
168             )
169         );
170         BOOST_CHECK_NO_THROW(ch.reset());
171         BOOST_CHECK_OPERATION_SEQUENCE(seq);
172     }
173
174     // Compose an output filter with a sink
175     {
176         operation_sequence  seq;
177         chain<output>       ch;
178         ch.push(
179             io::compose(
180                 closable_filter<output>(seq.new_operation(1)),
181                 closable_device<output>(seq.new_operation(2))
182             )
183         );
184         BOOST_CHECK_NO_THROW(ch.reset());
185         BOOST_CHECK_OPERATION_SEQUENCE(seq);
186     }
187
188     // Compose a bidirectional filter with a sink
189     {
190         operation_sequence  seq;
191         chain<output>       ch;
192         ch.push(
193             io::compose(
194                 closable_filter<bidirectional>(
195                     seq.new_operation(1),
196                     seq.new_operation(2)
197                 ),
198                 closable_device<output>(seq.new_operation(3))
199             )
200         );
201         BOOST_CHECK_NO_THROW(ch.reset());
202         BOOST_CHECK_OPERATION_SEQUENCE(seq);
203     }
204
205     // Compose a seekable filter with a sink
206     {
207         operation_sequence  seq;
208         chain<output>       ch;
209         ch.push(
210             io::compose(
211                 closable_filter<seekable>(seq.new_operation(1)),
212                 closable_device<output>(seq.new_operation(2))
213             )
214         );
215         BOOST_CHECK_NO_THROW(ch.reset());
216         BOOST_CHECK_OPERATION_SEQUENCE(seq);
217     }
218
219     // Compose a dual-use filter with a sink
220     {
221         operation_sequence  seq;
222         chain<output>       ch;
223         operation           dummy;
224         ch.push(
225             io::compose(
226                 closable_filter<dual_use>(
227                     dummy,
228                     seq.new_operation(1)
229                 ),
230                 closable_device<output>(seq.new_operation(2))
231             )
232         );
233         BOOST_CHECK_NO_THROW(ch.reset());
234         BOOST_CHECK_OPERATION_SEQUENCE(seq);
235     }
236
237     // Compose a bidirectional filter with a bidirectional device
238     {
239         operation_sequence    seq;
240         chain<bidirectional>  ch;
241         ch.push(
242             io::compose(
243                 closable_filter<bidirectional>(
244                     seq.new_operation(2),
245                     seq.new_operation(3)
246                 ),
247                 closable_device<bidirectional>(
248                     seq.new_operation(1),
249                     seq.new_operation(4)
250                 )
251             )
252         );
253         BOOST_CHECK_NO_THROW(ch.reset());
254         BOOST_CHECK_OPERATION_SEQUENCE(seq);
255     }
256
257     // Compose a seekable filter with a seekable device
258     {
259         operation_sequence  seq;
260         chain<seekable>     ch;
261         ch.push(
262             io::compose(
263                 closable_filter<seekable>(seq.new_operation(1)),
264                 closable_device<seekable>(seq.new_operation(2))
265             )
266         );
267         BOOST_CHECK_NO_THROW(ch.reset());
268         BOOST_CHECK_OPERATION_SEQUENCE(seq);
269     }
270 }
271
272 void close_composite_filter()
273 {
274     // Compose two input filters
275     {
276         operation_sequence  seq;
277         chain<input>        ch;
278         ch.push(
279             io::compose(
280                 closable_filter<input>(seq.new_operation(3)),
281                 closable_filter<input>(seq.new_operation(2))
282             )
283         );
284         ch.push(closable_device<input>(seq.new_operation(1)));
285         BOOST_CHECK_NO_THROW(ch.reset());
286         BOOST_CHECK_OPERATION_SEQUENCE(seq);
287     }
288
289     // Compose a bidirectional filter with an input filter
290     {
291         operation_sequence  seq;
292         chain<input>        ch;
293         ch.push(
294             io::compose(
295                 closable_filter<bidirectional>(
296                     seq.new_operation(3),
297                     seq.new_operation(4)
298                 ),
299                 closable_filter<input>(seq.new_operation(2))
300             )
301         );
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());
305     }
306
307     // Compose a seekable filter with an input filter
308     {
309         operation_sequence  seq;
310         chain<input>        ch;
311         ch.push(
312             io::compose(
313                 closable_filter<seekable>(seq.new_operation(3)),
314                 closable_filter<input>(seq.new_operation(2))
315             )
316         );
317         ch.push(closable_device<input>(seq.new_operation(1)));
318         BOOST_CHECK_NO_THROW(ch.reset());
319         BOOST_CHECK_OPERATION_SEQUENCE(seq);
320     }
321
322     // Compose a dual-use filter with an input filter
323     {
324         operation_sequence  seq;
325         chain<input>        ch;
326         operation           dummy;
327         ch.push(
328             io::compose(
329                 closable_filter<dual_use>(
330                     seq.new_operation(3),
331                     dummy
332                 ),
333                 closable_filter<input>(seq.new_operation(2))
334             )
335         );
336         ch.push(closable_device<input>(seq.new_operation(1)));
337         BOOST_CHECK_NO_THROW(ch.reset());
338         BOOST_CHECK_OPERATION_SEQUENCE(seq);
339     }
340
341     // Compose two output filters
342     {
343         operation_sequence  seq;
344         chain<output>       ch;
345         ch.push(
346             io::compose(
347                 closable_filter<output>(seq.new_operation(1)),
348                 closable_filter<output>(seq.new_operation(2))
349             )
350         );
351         ch.push(closable_device<output>(seq.new_operation(3)));
352         BOOST_CHECK_NO_THROW(ch.reset());
353         BOOST_CHECK_OPERATION_SEQUENCE(seq);
354     }
355
356     // Compose a bidirectional filter with an output filter
357     {
358         operation_sequence  seq;
359         chain<output>       ch;
360         ch.push(
361             io::compose(
362                 closable_filter<bidirectional>(
363                     seq.new_operation(1),
364                     seq.new_operation(2)
365                 ),
366                 closable_filter<output>(seq.new_operation(3))
367             )
368         );
369         ch.push(closable_device<output>(seq.new_operation(4)));
370         BOOST_CHECK_NO_THROW(ch.reset());
371         BOOST_CHECK_OPERATION_SEQUENCE(seq);
372     }
373
374     // Compose a seekable filter with an output filter
375     {
376         operation_sequence  seq;
377         chain<output>       ch;
378         ch.push(
379             io::compose(
380                 closable_filter<seekable>(seq.new_operation(1)),
381                 closable_filter<output>(seq.new_operation(2))
382             )
383         );
384         ch.push(closable_device<output>(seq.new_operation(3)));
385         BOOST_CHECK_NO_THROW(ch.reset());
386         BOOST_CHECK_OPERATION_SEQUENCE(seq);
387     }
388
389     // Compose a dual-use filter with an output filter
390     {
391         operation_sequence  seq;
392         chain<output>       ch;
393         operation           dummy;
394         ch.push(
395             io::compose(
396                 closable_filter<dual_use>(
397                     dummy,
398                     seq.new_operation(1)
399                 ),
400                 closable_filter<output>(seq.new_operation(2))
401             )
402         );
403         ch.push(closable_device<output>(seq.new_operation(3)));
404         BOOST_CHECK_NO_THROW(ch.reset());
405         BOOST_CHECK_OPERATION_SEQUENCE(seq);
406     }
407
408     // Compose two bidirectional filters
409     {
410         operation_sequence    seq;
411         chain<bidirectional>  ch;
412         ch.push(
413             io::compose(
414                 closable_filter<bidirectional>(
415                     seq.new_operation(3),
416                     seq.new_operation(4)
417                 ),
418                 closable_filter<bidirectional>(
419                     seq.new_operation(2),
420                     seq.new_operation(5)
421                 )
422             )
423         );
424         ch.push(
425             closable_device<bidirectional>(
426                 seq.new_operation(1),
427                 seq.new_operation(6)
428             )
429         );
430         BOOST_CHECK_NO_THROW(ch.reset());
431         BOOST_CHECK_OPERATION_SEQUENCE(seq);
432     }
433
434     // Compose two seekable filters
435     {
436         operation_sequence  seq;
437         chain<seekable>     ch;
438         ch.push(
439             io::compose(
440                 closable_filter<seekable>(seq.new_operation(1)),
441                 closable_filter<seekable>(seq.new_operation(2))
442             )
443         );
444         ch.push(closable_device<seekable>(seq.new_operation(3)));
445         BOOST_CHECK_NO_THROW(ch.reset());
446         BOOST_CHECK_OPERATION_SEQUENCE(seq);
447     }
448
449     // Compose two dual-use filters for input
450     {
451         operation_sequence  seq;
452         chain<input>        ch;
453         operation           dummy;
454         ch.push(
455             io::compose(
456                 closable_filter<dual_use>(
457                     seq.new_operation(3),
458                     dummy
459                 ),
460                 closable_filter<dual_use>(
461                     seq.new_operation(2),
462                     dummy
463                 )
464             )
465         );
466         ch.push(closable_device<input>(seq.new_operation(1)));
467         BOOST_CHECK_NO_THROW(ch.reset());
468         BOOST_CHECK_OPERATION_SEQUENCE(seq);
469     }
470
471     // Compose two dual-use filters for output
472     {
473         operation_sequence  seq;
474         chain<output>       ch;
475         operation           dummy;
476         ch.push(
477             io::compose(
478                 closable_filter<dual_use>(
479                     dummy,
480                     seq.new_operation(1)
481                 ),
482                 closable_filter<dual_use>(
483                     dummy,
484                     seq.new_operation(2)
485                 )
486             )
487         );
488         ch.push(closable_device<output>(seq.new_operation(3)));
489         BOOST_CHECK_NO_THROW(ch.reset());
490         BOOST_CHECK_OPERATION_SEQUENCE(seq);
491     }
492 }
493
494 test_suite* init_unit_test_suite(int, char* [])
495 {
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));
501     return test;
502 }
503
504 #include <boost/iostreams/detail/config/enable_warnings.hpp> // BCC 5.x.