• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Distributed under the Boost Software License, Version 1.0.(See accompanying
3  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4  *
5  * See http://www.boost.org/libs/iostreams for documentation.
6  *
7  * Verifies that the close() member functions of filters and devices
8  * are called with the correct arguments in the correct order when
9  * used with chains and streams.
10  *
11  * File:        libs/iostreams/test/close_test.cpp
12  * Date:        Sun Dec 09 16:12:23 MST 2007
13  * Copyright:   2007 CodeRage
14  * Author:      Jonathan Turkanis
15  */
16 
17 #include <boost/iostreams/chain.hpp>
18 #include <boost/iostreams/filtering_streambuf.hpp>
19 #include <boost/iostreams/stream.hpp>
20 #include <boost/test/test_tools.hpp>
21 #include <boost/test/unit_test.hpp>
22 #include "detail/closable.hpp"
23 #include "detail/operation_sequence.hpp"
24 
25 using namespace std;
26 using namespace boost;
27 using namespace boost::iostreams;
28 using namespace boost::iostreams::test;
29 using boost::unit_test::test_suite;
30 namespace io = boost::iostreams;
31 
input_chain_test()32 void input_chain_test()
33 {
34     // Test input filter and device
35     {
36         operation_sequence          seq;
37         filtering_streambuf<input>  ch;
38 
39         // Test chain::pop()
40         ch.push(closable_filter<input>(seq.new_operation(2)));
41         ch.push(closable_device<input>(seq.new_operation(1)));
42         BOOST_CHECK_NO_THROW(ch.pop());
43         BOOST_CHECK_OPERATION_SEQUENCE(seq);
44 
45         // Test filter reuse and io::close()
46         seq.reset();
47         ch.push(closable_device<input>(seq.new_operation(1)));
48         BOOST_CHECK_NO_THROW(io::close(ch));
49         BOOST_CHECK_OPERATION_SEQUENCE(seq);
50 
51         // Test filter reuse and chain::reset()
52         seq.reset();
53         ch.push(closable_device<input>(seq.new_operation(1)));
54         BOOST_CHECK_NO_THROW(ch.reset());
55         BOOST_CHECK_OPERATION_SEQUENCE(seq);
56     }
57 
58     // Test bidirectional filter and device
59     {
60         operation_sequence          seq;
61         filtering_streambuf<input>  ch;
62 
63         // Test chain::pop()
64         ch.push(
65             closable_filter<bidirectional>(
66                 seq.new_operation(2),
67                 seq.new_operation(3)
68             )
69         );
70         ch.push(
71             closable_device<bidirectional>(
72                 seq.new_operation(1),
73                 seq.new_operation(4)
74             )
75         );
76         BOOST_CHECK_NO_THROW(ch.pop());
77         BOOST_CHECK_OPERATION_SEQUENCE(seq);
78 
79         // Test filter reuse and io::close()
80         seq.reset();
81         ch.push(
82             closable_device<bidirectional>(
83                 seq.new_operation(1),
84                 seq.new_operation(4)
85             )
86         );
87         BOOST_CHECK_NO_THROW(io::close(ch));
88         BOOST_CHECK_OPERATION_SEQUENCE(seq);
89 
90         // Test filter reuse and chain::reset()
91         seq.reset();
92         ch.push(
93             closable_device<bidirectional>(
94                 seq.new_operation(1),
95                 seq.new_operation(4)
96             )
97         );
98         BOOST_CHECK_NO_THROW(ch.reset());
99         BOOST_CHECK_OPERATION_SEQUENCE(seq);
100     }
101 
102     // Test seekable filter and device
103     {
104         operation_sequence          seq;
105         filtering_streambuf<input>  ch;
106 
107         // Test chain::pop()
108         ch.push(closable_filter<seekable>(seq.new_operation(1)));
109         ch.push(closable_device<seekable>(seq.new_operation(2)));
110         BOOST_CHECK_NO_THROW(ch.pop());
111         BOOST_CHECK_OPERATION_SEQUENCE(seq);
112 
113         // Test filter reuse and io::close()
114         seq.reset();
115         ch.push(closable_device<seekable>(seq.new_operation(2)));
116         BOOST_CHECK_NO_THROW(io::close(ch));
117         BOOST_CHECK_OPERATION_SEQUENCE(seq);
118 
119         // Test filter reuse and chain::reset()
120         seq.reset();
121         ch.push(closable_device<seekable>(seq.new_operation(2)));
122         BOOST_CHECK_NO_THROW(ch.reset());
123         BOOST_CHECK_OPERATION_SEQUENCE(seq);
124     }
125 
126     // Test dual-user filter
127     {
128         operation_sequence          seq;
129         filtering_streambuf<input>  ch;
130         operation                   dummy;
131 
132         // Test chain::pop()
133         ch.push(
134             closable_filter<dual_use>(
135                 seq.new_operation(2),
136                 dummy
137             )
138         );
139         ch.push(closable_device<input>(seq.new_operation(1)));
140         BOOST_CHECK_NO_THROW(ch.pop());
141         BOOST_CHECK_OPERATION_SEQUENCE(seq);
142 
143         // Test filter reuse and io::close()
144         seq.reset();
145         ch.push(closable_device<input>(seq.new_operation(1)));
146         BOOST_CHECK_NO_THROW(io::close(ch));
147         BOOST_CHECK_OPERATION_SEQUENCE(seq);
148 
149         // Test filter reuse and chain::reset()
150         seq.reset();
151         ch.push(closable_device<input>(seq.new_operation(1)));
152         BOOST_CHECK_NO_THROW(ch.reset());
153         BOOST_CHECK_OPERATION_SEQUENCE(seq);
154     }
155 
156     // Test direct source
157     {
158         operation_sequence          seq;
159         filtering_streambuf<input>  ch;
160 
161         // Test chain::pop()
162         ch.push(closable_filter<input>(seq.new_operation(2)));
163         ch.push(closable_device<direct_input>(seq.new_operation(1)));
164         BOOST_CHECK_NO_THROW(ch.pop());
165         BOOST_CHECK_OPERATION_SEQUENCE(seq);
166 
167         // Test filter reuse and io::close()
168         seq.reset();
169         ch.push(closable_device<direct_input>(seq.new_operation(1)));
170         BOOST_CHECK_NO_THROW(io::close(ch));
171         BOOST_CHECK_OPERATION_SEQUENCE(seq);
172 
173         // Test filter reuse and chain::reset()
174         seq.reset();
175         ch.push(closable_device<direct_input>(seq.new_operation(1)));
176         BOOST_CHECK_NO_THROW(ch.reset());
177         BOOST_CHECK_OPERATION_SEQUENCE(seq);
178     }
179 
180     // Test direct bidirectional device
181     {
182         operation_sequence          seq;
183         filtering_streambuf<input>  ch;
184 
185         // Test chain::pop()
186         ch.push(closable_filter<input>(seq.new_operation(2)));
187         ch.push(
188             closable_device<direct_bidirectional>(
189                 seq.new_operation(1),
190                 seq.new_operation(3)
191             )
192         );
193         BOOST_CHECK_NO_THROW(ch.pop());
194         BOOST_CHECK_OPERATION_SEQUENCE(seq);
195 
196         // Test filter reuse and io::close()
197         seq.reset();
198         ch.push(
199             closable_device<direct_bidirectional>(
200                 seq.new_operation(1),
201                 seq.new_operation(3)
202             )
203         );
204         BOOST_CHECK_NO_THROW(io::close(ch));
205         BOOST_CHECK_OPERATION_SEQUENCE(seq);
206 
207         // Test filter reuse and chain::reset()
208         seq.reset();
209         ch.push(
210             closable_device<direct_bidirectional>(
211                 seq.new_operation(1),
212                 seq.new_operation(3)
213             )
214         );
215         BOOST_CHECK_NO_THROW(ch.reset());
216         BOOST_CHECK_OPERATION_SEQUENCE(seq);
217     }
218 
219     // Test direct seekable device
220     {
221         operation_sequence          seq;
222         filtering_streambuf<input>  ch;
223 
224         // Test chain::pop()
225         ch.push(closable_filter<input>(seq.new_operation(1)));
226         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
227         BOOST_CHECK_NO_THROW(ch.pop());
228         BOOST_CHECK_OPERATION_SEQUENCE(seq);
229 
230         // Test filter reuse and io::close()
231         seq.reset();
232         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
233         BOOST_CHECK_NO_THROW(io::close(ch));
234         BOOST_CHECK_OPERATION_SEQUENCE(seq);
235 
236         // Test filter reuse and chain::reset()
237         seq.reset();
238         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
239         BOOST_CHECK_NO_THROW(ch.reset());
240         BOOST_CHECK_OPERATION_SEQUENCE(seq);
241     }
242 }
243 
output_chain_test()244 void output_chain_test()
245 {
246     // Test output filter and device
247     {
248         operation_sequence           seq;
249         filtering_streambuf<output>  ch;
250 
251         // Test chain::pop()
252         ch.push(closable_filter<output>(seq.new_operation(1)));
253         ch.push(closable_device<output>(seq.new_operation(2)));
254         BOOST_CHECK_NO_THROW(ch.pop());
255         BOOST_CHECK_OPERATION_SEQUENCE(seq);
256 
257         // Test filter reuse and io::close()
258         seq.reset();
259         ch.push(closable_device<output>(seq.new_operation(2)));
260         BOOST_CHECK_NO_THROW(io::close(ch));
261         BOOST_CHECK_OPERATION_SEQUENCE(seq);
262 
263         // Test filter reuse and chain::reset()
264         seq.reset();
265         ch.push(closable_device<output>(seq.new_operation(2)));
266         BOOST_CHECK_NO_THROW(ch.reset());
267         BOOST_CHECK_OPERATION_SEQUENCE(seq);
268     }
269 
270     // Test bidirectional filter and device
271     {
272         operation_sequence           seq;
273         filtering_streambuf<output>  ch;
274 
275         // Test chain::pop()
276         ch.push(
277             closable_filter<bidirectional>(
278                 seq.new_operation(2),
279                 seq.new_operation(3)
280             )
281         );
282         ch.push(
283             closable_device<bidirectional>(
284                 seq.new_operation(1),
285                 seq.new_operation(4)
286             )
287         );
288         BOOST_CHECK_NO_THROW(ch.pop());
289         BOOST_CHECK_OPERATION_SEQUENCE(seq);
290 
291         // Test filter reuse and io::close()
292         seq.reset();
293         ch.push(
294             closable_device<bidirectional>(
295                 seq.new_operation(1),
296                 seq.new_operation(4)
297             )
298         );
299         BOOST_CHECK_NO_THROW(io::close(ch));
300         BOOST_CHECK_OPERATION_SEQUENCE(seq);
301 
302         // Test filter reuse and chain::reset()
303         seq.reset();
304         ch.push(
305             closable_device<bidirectional>(
306                 seq.new_operation(1),
307                 seq.new_operation(4)
308             )
309         );
310         BOOST_CHECK_NO_THROW(ch.reset());
311         BOOST_CHECK_OPERATION_SEQUENCE(seq);
312     }
313 
314     // Test seekable filter and device
315     {
316         operation_sequence           seq;
317         filtering_streambuf<output>  ch;
318 
319         // Test chain::pop()
320         ch.push(closable_filter<seekable>(seq.new_operation(1)));
321         ch.push(closable_device<seekable>(seq.new_operation(2)));
322         BOOST_CHECK_NO_THROW(ch.pop());
323         BOOST_CHECK_OPERATION_SEQUENCE(seq);
324 
325         // Test filter reuse and io::close()
326         seq.reset();
327         ch.push(closable_device<seekable>(seq.new_operation(2)));
328         BOOST_CHECK_NO_THROW(io::close(ch));
329         BOOST_CHECK_OPERATION_SEQUENCE(seq);
330 
331         // Test filter reuse and chain::reset()
332         seq.reset();
333         ch.push(closable_device<seekable>(seq.new_operation(2)));
334         BOOST_CHECK_NO_THROW(ch.reset());
335         BOOST_CHECK_OPERATION_SEQUENCE(seq);
336     }
337 
338     // Test dual-user filter
339     {
340         operation_sequence           seq;
341         filtering_streambuf<output>  ch;
342         operation                    dummy;
343 
344         // Test chain::pop()
345         ch.push(
346             closable_filter<dual_use>(
347                 dummy,
348                 seq.new_operation(1)
349             )
350         );
351         ch.push(closable_device<output>(seq.new_operation(3)));
352         BOOST_CHECK_NO_THROW(ch.pop());
353         BOOST_CHECK_OPERATION_SEQUENCE(seq);
354 
355         // Test filter reuse and io::close()
356         seq.reset();
357         ch.push(closable_device<output>(seq.new_operation(3)));
358         BOOST_CHECK_NO_THROW(io::close(ch));
359         BOOST_CHECK_OPERATION_SEQUENCE(seq);
360 
361         // Test filter reuse and chain::reset()
362         seq.reset();
363         ch.push(closable_device<output>(seq.new_operation(3)));
364         BOOST_CHECK_NO_THROW(ch.reset());
365         BOOST_CHECK_OPERATION_SEQUENCE(seq);
366     }
367 
368     // Test direct sink
369     {
370         operation_sequence           seq;
371         filtering_streambuf<output>  ch;
372 
373         // Test chain::pop()
374         ch.push(closable_filter<output>(seq.new_operation(1)));
375         ch.push(closable_device<direct_output>(seq.new_operation(2)));
376         BOOST_CHECK_NO_THROW(ch.pop());
377         BOOST_CHECK_OPERATION_SEQUENCE(seq);
378 
379         // Test filter reuse and io::close()
380         seq.reset();
381         ch.push(closable_device<direct_output>(seq.new_operation(2)));
382         BOOST_CHECK_NO_THROW(io::close(ch));
383         BOOST_CHECK_OPERATION_SEQUENCE(seq);
384 
385         // Test filter reuse and chain::reset()
386         seq.reset();
387         ch.push(closable_device<direct_output>(seq.new_operation(2)));
388         BOOST_CHECK_NO_THROW(ch.reset());
389         BOOST_CHECK_OPERATION_SEQUENCE(seq);
390     }
391 
392     // Test direct bidirectional device
393     {
394         operation_sequence           seq;
395         filtering_streambuf<output>  ch;
396 
397         // Test chain::pop()
398         ch.push(closable_filter<output>(seq.new_operation(2)));
399         ch.push(
400             closable_device<direct_bidirectional>(
401                 seq.new_operation(1),
402                 seq.new_operation(3)
403             )
404         );
405         BOOST_CHECK_NO_THROW(ch.pop());
406         BOOST_CHECK_OPERATION_SEQUENCE(seq);
407 
408         // Test filter reuse and io::close()
409         seq.reset();
410         ch.push(
411             closable_device<direct_bidirectional>(
412                 seq.new_operation(1),
413                 seq.new_operation(3)
414             )
415         );
416         BOOST_CHECK_NO_THROW(io::close(ch));
417         BOOST_CHECK_OPERATION_SEQUENCE(seq);
418 
419         // Test filter reuse and chain::reset()
420         seq.reset();
421         ch.push(
422             closable_device<direct_bidirectional>(
423                 seq.new_operation(1),
424                 seq.new_operation(3)
425             )
426         );
427         BOOST_CHECK_NO_THROW(ch.reset());
428         BOOST_CHECK_OPERATION_SEQUENCE(seq);
429     }
430 
431     // Test direct seekable device
432     {
433         operation_sequence           seq;
434         filtering_streambuf<output>  ch;
435 
436         // Test chain::pop()
437         ch.push(closable_filter<output>(seq.new_operation(1)));
438         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
439         BOOST_CHECK_NO_THROW(ch.pop());
440         BOOST_CHECK_OPERATION_SEQUENCE(seq);
441 
442         // Test filter reuse and io::close()
443         seq.reset();
444         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
445         BOOST_CHECK_NO_THROW(io::close(ch));
446         BOOST_CHECK_OPERATION_SEQUENCE(seq);
447 
448         // Test filter reuse and chain::reset()
449         seq.reset();
450         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
451         BOOST_CHECK_NO_THROW(ch.reset());
452         BOOST_CHECK_OPERATION_SEQUENCE(seq);
453     }
454 }
455 
bidirectional_chain_test()456 void bidirectional_chain_test()
457 {
458     // Test bidirectional filter and device
459     {
460         operation_sequence                  seq;
461         filtering_streambuf<bidirectional>  ch;
462 
463         // Test chain::pop()
464         ch.push(
465             closable_filter<bidirectional>(
466                 seq.new_operation(2),
467                 seq.new_operation(3)
468             )
469         );
470         ch.push(
471             closable_device<bidirectional>(
472                 seq.new_operation(1),
473                 seq.new_operation(4)
474             )
475         );
476         BOOST_CHECK_NO_THROW(ch.pop());
477         BOOST_CHECK_OPERATION_SEQUENCE(seq);
478 
479         // Test filter reuse and io::close()
480         seq.reset();
481         ch.push(
482             closable_device<bidirectional>(
483                 seq.new_operation(1),
484                 seq.new_operation(4)
485             )
486         );
487         BOOST_CHECK_NO_THROW(io::close(ch));
488         BOOST_CHECK_OPERATION_SEQUENCE(seq);
489 
490         // Test filter reuse and chain::reset()
491         seq.reset();
492         ch.push(
493             closable_device<bidirectional>(
494                 seq.new_operation(1),
495                 seq.new_operation(4)
496             )
497         );
498         BOOST_CHECK_NO_THROW(ch.reset());
499         BOOST_CHECK_OPERATION_SEQUENCE(seq);
500     }
501 
502     // Test direct bidirectional device
503     {
504         operation_sequence                  seq;
505         filtering_streambuf<bidirectional>  ch;
506 
507         // Test chain::pop()
508         ch.push(
509             closable_filter<bidirectional>(
510                 seq.new_operation(2),
511                 seq.new_operation(3)
512             )
513         );
514         ch.push(
515             closable_device<direct_bidirectional>(
516                 seq.new_operation(1),
517                 seq.new_operation(4)
518             )
519         );
520         BOOST_CHECK_NO_THROW(ch.pop());
521         BOOST_CHECK_OPERATION_SEQUENCE(seq);
522 
523         // Test filter reuse and io::close()
524         seq.reset();
525         ch.push(
526             closable_device<direct_bidirectional>(
527                 seq.new_operation(1),
528                 seq.new_operation(4)
529             )
530         );
531         BOOST_CHECK_NO_THROW(io::close(ch));
532         BOOST_CHECK_OPERATION_SEQUENCE(seq);
533 
534         // Test filter reuse and chain::reset()
535         seq.reset();
536         ch.push(
537             closable_device<direct_bidirectional>(
538                 seq.new_operation(1),
539                 seq.new_operation(4)
540             )
541         );
542         BOOST_CHECK_NO_THROW(ch.reset());
543         BOOST_CHECK_OPERATION_SEQUENCE(seq);
544     }
545 }
546 
seekable_chain_test()547 void seekable_chain_test()
548 {
549     // Test seekable filter and device
550     {
551         operation_sequence             seq;
552         filtering_streambuf<seekable>  ch;
553 
554         // Test chain::pop()
555         ch.push(closable_filter<seekable>(seq.new_operation(1)));
556         ch.push(closable_device<seekable>(seq.new_operation(2)));
557         BOOST_CHECK_NO_THROW(ch.pop());
558         BOOST_CHECK_OPERATION_SEQUENCE(seq);
559 
560         // Test filter reuse and io::close()
561         seq.reset();
562         ch.push(closable_device<seekable>(seq.new_operation(2)));
563         BOOST_CHECK_NO_THROW(io::close(ch));
564         BOOST_CHECK_OPERATION_SEQUENCE(seq);
565 
566         // Test filter reuse and chain::reset()
567         seq.reset();
568         ch.push(closable_device<seekable>(seq.new_operation(2)));
569         BOOST_CHECK_NO_THROW(ch.reset());
570         BOOST_CHECK_OPERATION_SEQUENCE(seq);
571     }
572 
573     // Test direct seekable device
574     {
575         operation_sequence             seq;
576         filtering_streambuf<seekable>  ch;
577 
578         // Test chain::pop()
579         ch.push(closable_filter<seekable>(seq.new_operation(1)));
580         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
581         BOOST_CHECK_NO_THROW(ch.pop());
582         BOOST_CHECK_OPERATION_SEQUENCE(seq);
583 
584         // Test filter reuse and io::close()
585         seq.reset();
586         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
587         BOOST_CHECK_NO_THROW(io::close(ch));
588         BOOST_CHECK_OPERATION_SEQUENCE(seq);
589 
590         // Test filter reuse and chain::reset()
591         seq.reset();
592         ch.push(closable_device<direct_seekable>(seq.new_operation(2)));
593         BOOST_CHECK_NO_THROW(ch.reset());
594         BOOST_CHECK_OPERATION_SEQUENCE(seq);
595     }
596 }
597 
stream_test()598 void stream_test()
599 {
600     // Test source
601     {
602         operation_sequence                seq;
603         stream< closable_device<input> >  str;
604         str.open(closable_device<input>(seq.new_operation(1)));
605         BOOST_CHECK_NO_THROW(str.close());
606         BOOST_CHECK_OPERATION_SEQUENCE(seq);
607     }
608 
609     // Test sink
610     {
611         operation_sequence                 seq;
612         stream< closable_device<output> >  str;
613         str.open(closable_device<output>(seq.new_operation(1)));
614         BOOST_CHECK_NO_THROW(str.close());
615         BOOST_CHECK_OPERATION_SEQUENCE(seq);
616     }
617 
618     // Test bidirectional device
619     {
620         operation_sequence                        seq;
621         stream< closable_device<bidirectional> >  str;
622         str.open(
623             closable_device<bidirectional>(
624                 seq.new_operation(1),
625                 seq.new_operation(2)
626             )
627         );
628         BOOST_CHECK_NO_THROW(str.close());
629         BOOST_CHECK_OPERATION_SEQUENCE(seq);
630     }
631 
632     // Test seekable device
633     {
634         operation_sequence                   seq;
635         stream< closable_device<seekable> >  str;
636         str.open(closable_device<seekable>(seq.new_operation(1)));
637         BOOST_CHECK_NO_THROW(str.close());
638         BOOST_CHECK_OPERATION_SEQUENCE(seq);
639     }
640 }
641 
init_unit_test_suite(int,char * [])642 test_suite* init_unit_test_suite(int, char* [])
643 {
644     test_suite* test = BOOST_TEST_SUITE("execute test");
645     test->add(BOOST_TEST_CASE(&input_chain_test));
646     test->add(BOOST_TEST_CASE(&output_chain_test));
647     test->add(BOOST_TEST_CASE(&bidirectional_chain_test));
648     test->add(BOOST_TEST_CASE(&seekable_chain_test));
649     test->add(BOOST_TEST_CASE(&stream_test));
650     return test;
651 }
652