1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2005-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 // Allow this file to be used by slice_test.hpp. It is important not to
9 // replace BOOST_IOSTREAMS_RESTRICT with BOOST_IOSTREAMS_RESTRICT here, since that
10 // would interfere with the oepration of the header
11 // <boost/iostreams/restrict.hpp>
12 #include <iostream>
13
14 #if defined(BOOST_IOSTREAMS_RESTRICT_USE_SLICE)
15 # include <boost/iostreams/slice.hpp>
16 # define BOOST_IOSTREAMS_RESTRICT slice
17 #else
18 # include <boost/iostreams/restrict.hpp>
19 # define BOOST_IOSTREAMS_RESTRICT restrict
20 #endif
21
22 #include <algorithm> // equal.
23 #include <cctype>
24 #include <iterator> // back_inserter.
25 #include <vector>
26 #include <boost/iostreams/copy.hpp>
27 #include <boost/iostreams/device/file.hpp>
28 #include <boost/iostreams/device/null.hpp>
29 #include <boost/iostreams/filtering_stream.hpp>
30 #include <boost/test/test_tools.hpp>
31 #include <boost/test/unit_test.hpp>
32 #include "detail/closable.hpp"
33 #include "detail/constants.hpp"
34 #include "detail/filters.hpp"
35 #include "detail/operation_sequence.hpp"
36 #include "detail/sequence.hpp"
37 #include "detail/temp_file.hpp"
38 #include "detail/verification.hpp"
39
40 using namespace std;
41 using namespace boost::iostreams;
42 using namespace boost::iostreams::test;
43 using boost::unit_test::test_suite;
44 namespace io = boost::iostreams;
45
46 const char pad_char = '\n';
47 const int small_padding = 50;
48 const int large_padding = default_device_buffer_size + 50;
49
write_padding(std::ofstream & out,int len)50 void write_padding(std::ofstream& out, int len)
51 {
52 for (int z = 0; z < len; ++z)
53 out.put(pad_char);
54 }
55
56 struct restricted_test_file : public temp_file {
restricted_test_filerestricted_test_file57 restricted_test_file(int padding, bool half_open = false)
58 {
59 BOOST_IOS::openmode mode =
60 BOOST_IOS::out | BOOST_IOS::binary;
61 ::std::ofstream f(name().c_str(), mode);
62 write_padding(f, padding);
63 const char* buf = narrow_data();
64 for (int z = 0; z < data_reps; ++z)
65 f.write(buf, data_length());
66 if (!half_open)
67 write_padding(f, padding);
68 }
69 };
70
71 struct restricted_test_sequence : public std::vector<char> {
restricted_test_sequencerestricted_test_sequence72 restricted_test_sequence(int padding, bool half_open = false)
73 {
74 for (int z = 0; z < padding; ++z)
75 push_back(pad_char);
76 const char* buf = narrow_data();
77 for (int w = 0; w < data_reps; ++w)
78 insert(end(), buf, buf + data_length());
79 if (!half_open)
80 for (int x = 0; x < padding; ++x)
81 push_back(pad_char);
82 }
83 };
84
85 struct restricted_uppercase_file : public temp_file {
restricted_uppercase_filerestricted_uppercase_file86 restricted_uppercase_file(int padding, bool half_open = false)
87 {
88 BOOST_IOS::openmode mode =
89 BOOST_IOS::out | BOOST_IOS::binary;
90 ::std::ofstream f(name().c_str(), mode);
91 write_padding(f, padding);
92 const char* buf = narrow_data();
93 for (int z = 0; z < data_reps; ++z)
94 for (int w = 0; w < data_length(); ++w)
95 f.put((char) std::toupper(buf[w]));
96 if (!half_open)
97 write_padding(f, padding);
98 }
99 };
100
101 struct restricted_lowercase_file : public temp_file {
restricted_lowercase_filerestricted_lowercase_file102 restricted_lowercase_file(int padding, bool half_open = false)
103 {
104 BOOST_IOS::openmode mode =
105 BOOST_IOS::out | BOOST_IOS::binary;
106 ::std::ofstream f(name().c_str(), mode);
107 write_padding(f, padding);
108 const char* buf = narrow_data();
109 for (int z = 0; z < data_reps; ++z)
110 for (int w = 0; w < data_length(); ++w)
111 f.put((char) std::tolower(buf[w]));
112 if (!half_open)
113 write_padding(f, padding);
114 }
115 };
116
117 // Can't have a restricted view of a non-seekble output filter.
118 struct tolower_seekable_filter : public seekable_filter {
119 typedef char char_type;
120 struct category
121 : output_seekable,
122 filter_tag
123 { };
124 template<typename Sink>
puttolower_seekable_filter125 bool put(Sink& s, char c)
126 { return boost::iostreams::put(s, (char) std::tolower(c)); }
127
128 template<typename Sink>
seektolower_seekable_filter129 std::streampos seek(Sink& s, stream_offset off, BOOST_IOS::seekdir way)
130 { return boost::iostreams::seek(s, off, way); }
131 };
132
read_device()133 void read_device()
134 {
135 {
136 restricted_test_file src1(small_padding);
137 test_file src2;
138 stream_offset off = small_padding,
139 len = data_reps * data_length();
140 filtering_istream first(
141 BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off, len));
142 ifstream second(src2.name().c_str(), in_mode);
143 BOOST_CHECK_MESSAGE(
144 compare_streams_in_chunks(first, second),
145 "failed reading from restriction<Device> with small padding"
146 );
147 }
148
149 {
150 restricted_test_file src1(large_padding);
151 test_file src2;
152 stream_offset off = large_padding,
153 len = data_reps * data_length();
154 filtering_istream first(
155 BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off, len));
156 ifstream second(src2.name().c_str(), in_mode);
157 BOOST_CHECK_MESSAGE(
158 compare_streams_in_chunks(first, second),
159 "failed reading from restriction<Device> with large padding"
160 );
161 }
162
163 {
164 restricted_test_file src1(small_padding, true);
165 test_file src2;
166 stream_offset off = small_padding;
167 filtering_istream first(
168 BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off));
169 ifstream second(src2.name().c_str(), in_mode);
170 BOOST_CHECK_MESSAGE(
171 compare_streams_in_chunks(first, second),
172 "failed reading from half-open restriction<Device> "
173 "with small padding"
174 );
175 }
176
177 {
178 restricted_test_file src1(large_padding, true);
179 test_file src2;
180 stream_offset off = large_padding;
181 filtering_istream first(
182 BOOST_IOSTREAMS_RESTRICT(file_source(src1.name(), in_mode), off));
183 ifstream second(src2.name().c_str(), in_mode);
184 BOOST_CHECK_MESSAGE(
185 compare_streams_in_chunks(first, second),
186 "failed reading from half-open restriction<Device> "
187 "with large padding"
188 );
189 }
190 }
191
read_direct_device()192 void read_direct_device()
193 {
194 {
195 test_sequence<char> first;
196 restricted_test_sequence src(small_padding);
197 array_source array_src(&src[0], &src[0] + src.size());
198 stream_offset off = small_padding,
199 len = data_reps * data_length();
200 filtering_istream second(BOOST_IOSTREAMS_RESTRICT(array_src, off, len));
201 BOOST_CHECK_MESSAGE(
202 compare_container_and_stream(first, second),
203 "failed reading from restriction<Direct>"
204 );
205 }
206
207 {
208 test_sequence<char> first;
209 restricted_test_sequence src(small_padding, true);
210 array_source array_src(&src[0], &src[0] + src.size());
211 stream_offset off = small_padding;
212 filtering_istream second(BOOST_IOSTREAMS_RESTRICT(array_src, off));
213 BOOST_CHECK_MESSAGE(
214 compare_container_and_stream(first, second),
215 "failed reading from half-open restriction<Direct>"
216 );
217 }
218 }
219
read_filter()220 void read_filter()
221 {
222 {
223 restricted_test_file src1(small_padding);
224 uppercase_file src2;
225 stream_offset off = small_padding,
226 len = data_reps * data_length();
227 filtering_istream first;
228 first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off, len));
229 first.push(file_source(src1.name(), in_mode));
230 ifstream second(src2.name().c_str(), in_mode);
231 BOOST_CHECK_MESSAGE(
232 compare_streams_in_chunks(first, second),
233 "failed reading from restriction<Filter> with small padding"
234 );
235 }
236
237 {
238 restricted_test_file src1(large_padding);
239 uppercase_file src2;
240 stream_offset off = large_padding,
241 len = data_reps * data_length();
242 filtering_istream first;
243 first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off, len));
244 first.push(file_source(src1.name(), in_mode));
245 ifstream second(src2.name().c_str(), in_mode);
246 BOOST_CHECK_MESSAGE(
247 compare_streams_in_chunks(first, second),
248 "failed reading from restriction<Filter> with large padding"
249 );
250 }
251
252 {
253 restricted_test_file src1(small_padding, true);
254 uppercase_file src2;
255 stream_offset off = small_padding;
256 filtering_istream first;
257 first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off));
258 first.push(file_source(src1.name(), in_mode));
259 ifstream second(src2.name().c_str(), in_mode);
260 BOOST_CHECK_MESSAGE(
261 compare_streams_in_chunks(first, second),
262 "failed reading from half-open restriction<Filter> "
263 "with small padding"
264 );
265 }
266
267 {
268 restricted_test_file src1(large_padding, true);
269 uppercase_file src2;
270 stream_offset off = large_padding;
271 filtering_istream first;
272 first.push(BOOST_IOSTREAMS_RESTRICT(toupper_filter(), off));
273 first.push(file_source(src1.name(), in_mode));
274 ifstream second(src2.name().c_str(), in_mode);
275 BOOST_CHECK_MESSAGE(
276 compare_streams_in_chunks(first, second),
277 "failed reading from half-open restriction<Filter> "
278 "with large padding"
279 );
280 }
281 }
282
write_device()283 void write_device()
284 {
285 {
286 restricted_uppercase_file dest1(small_padding);
287 restricted_test_file dest2(small_padding);
288 stream_offset off = small_padding,
289 len = data_reps * data_length();
290 filtering_ostream out(
291 BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off, len));
292 write_data_in_chunks(out);
293 out.reset();
294 ifstream first(dest1.name().c_str(), in_mode);
295 ifstream second(dest2.name().c_str(), in_mode);
296 BOOST_CHECK_MESSAGE(
297 compare_streams_in_chunks(first, second),
298 "failed writing to restriction<Device> with small padding"
299 );
300 }
301
302 {
303 restricted_uppercase_file dest1(large_padding);
304 restricted_test_file dest2(large_padding);
305 stream_offset off = large_padding,
306 len = data_reps * data_length();
307 filtering_ostream out
308 (BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off, len));
309 write_data_in_chunks(out);
310 out.reset();
311 ifstream first(dest1.name().c_str(), in_mode);
312 ifstream second(dest2.name().c_str(), in_mode);
313 BOOST_CHECK_MESSAGE(
314 compare_streams_in_chunks(first, second),
315 "failed writing to restriction<Device> with large padding"
316 );
317 }
318
319 {
320 restricted_uppercase_file dest1(small_padding, true);
321 restricted_test_file dest2(small_padding, true);
322 stream_offset off = small_padding;
323 filtering_ostream out
324 (BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off));
325 write_data_in_chunks(out);
326 out.reset();
327 ifstream first(dest1.name().c_str(), in_mode);
328 ifstream second(dest2.name().c_str(), in_mode);
329 BOOST_CHECK_MESSAGE(
330 compare_streams_in_chunks(first, second),
331 "failed writing to half-open restriction<Device> "
332 "with small padding"
333 );
334 }
335
336 {
337 restricted_uppercase_file dest1(large_padding, true);
338 restricted_test_file dest2(large_padding, true);
339 stream_offset off = large_padding;
340 filtering_ostream out
341 (BOOST_IOSTREAMS_RESTRICT(file(dest1.name(), BOOST_IOS::binary), off));
342 write_data_in_chunks(out);
343 out.reset();
344 ifstream first(dest1.name().c_str(), in_mode);
345 ifstream second(dest2.name().c_str(), in_mode);
346 BOOST_CHECK_MESSAGE(
347 compare_streams_in_chunks(first, second),
348 "failed writing to half-open restriction<Device> "
349 "with large padding"
350 );
351 }
352 }
353
write_direct_device()354 void write_direct_device()
355 {
356 {
357 vector<char> dest1( data_reps * data_length() +
358 2 * small_padding,
359 '\n' );
360 restricted_test_sequence dest2(small_padding);
361 stream_offset off = small_padding,
362 len = data_reps * data_length();
363 array_sink array(&dest1[0], &dest1[0] + dest1.size());
364 filtering_ostream out(BOOST_IOSTREAMS_RESTRICT(array, off, len));
365 write_data_in_chunks(out);
366 out.reset();
367 BOOST_CHECK_MESSAGE(
368 std::equal(dest1.begin(), dest1.end(), dest2.begin()),
369 "failed writing to restriction<Direct>"
370 );
371 }
372
373 {
374 vector<char> dest1(
375 data_reps * data_length() + small_padding, '\n');
376 restricted_test_sequence dest2(small_padding, true);
377 stream_offset off = small_padding;
378 array_sink array(&dest1[0], &dest1[0] + dest1.size());
379 filtering_ostream out(BOOST_IOSTREAMS_RESTRICT(array, off));
380 write_data_in_chunks(out);
381 out.reset();
382 BOOST_CHECK_MESSAGE(
383 std::equal(dest1.begin(), dest1.end(), dest2.begin()),
384 "failed writing to half-open restriction<Direct>"
385 );
386 }
387 }
388
write_filter()389 void write_filter()
390 {
391 {
392 restricted_test_file dest1(small_padding);
393 restricted_lowercase_file dest2(small_padding);
394 stream_offset off = small_padding,
395 len = data_reps * data_length();
396 filtering_ostream out;
397 out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off, len));
398 out.push(file(dest1.name(), BOOST_IOS::binary));
399 write_data_in_chunks(out);
400 out.reset();
401 ifstream first(dest1.name().c_str(), in_mode);
402 ifstream second(dest2.name().c_str(), in_mode);
403 BOOST_CHECK_MESSAGE(
404 compare_streams_in_chunks(first, second),
405 "failed writing to restriction<Filter> with small padding"
406 );
407 }
408
409 {
410 restricted_test_file dest1(large_padding);
411 restricted_lowercase_file dest2(large_padding);
412 stream_offset off = large_padding,
413 len = data_reps * data_length();
414 filtering_ostream out;
415 out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off, len));
416 out.push(file(dest1.name(), BOOST_IOS::binary));
417 write_data_in_chunks(out);
418 out.reset();
419 ifstream first(dest1.name().c_str(), in_mode);
420 ifstream second(dest2.name().c_str(), in_mode);
421 BOOST_CHECK_MESSAGE(
422 compare_streams_in_chunks(first, second),
423 "failed writing to restriction<Filter> with large padding"
424 );
425 }
426
427 {
428 restricted_test_file dest1(small_padding, true);
429 restricted_lowercase_file dest2(small_padding, true);
430 stream_offset off = small_padding;
431 filtering_ostream out;
432 out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off));
433 out.push(file(dest1.name(), BOOST_IOS::binary));
434 write_data_in_chunks(out);
435 out.reset();
436 ifstream first(dest1.name().c_str(), in_mode);
437 ifstream second(dest2.name().c_str(), in_mode);
438 BOOST_CHECK_MESSAGE(
439 compare_streams_in_chunks(first, second),
440 "failed writing to restriction<Filter> with small padding"
441 );
442 }
443
444 {
445 restricted_test_file dest1(large_padding, true);
446 restricted_lowercase_file dest2(large_padding, true);
447 stream_offset off = large_padding;
448 filtering_ostream out;
449 out.push(BOOST_IOSTREAMS_RESTRICT(tolower_seekable_filter(), off));
450 out.push(file(dest1.name(), BOOST_IOS::binary));
451 write_data_in_chunks(out);
452 out.reset();
453 ifstream first(dest1.name().c_str(), in_mode);
454 ifstream second(dest2.name().c_str(), in_mode);
455 BOOST_CHECK_MESSAGE(
456 compare_streams_in_chunks(first, second),
457 "failed writing to restriction<Filter> with large padding"
458 );
459 }
460 }
461
seek_device()462 void seek_device()
463 {
464 {
465 restricted_test_file src(large_padding);
466 stream_offset off = large_padding,
467 len = data_reps * data_length();
468 filtering_stream<seekable> io(
469 BOOST_IOSTREAMS_RESTRICT(file(src.name(), BOOST_IOS::binary), off, len));
470 BOOST_CHECK_MESSAGE(
471 test_seekable_in_chunks(io),
472 "failed seeking within restriction<Device>"
473 );
474 }
475
476 {
477 restricted_test_file src(large_padding, true);
478 stream_offset off = large_padding;
479 filtering_stream<seekable> io(
480 BOOST_IOSTREAMS_RESTRICT(file(src.name(), BOOST_IOS::binary), off));
481 BOOST_CHECK_MESSAGE(
482 test_seekable_in_chunks(io),
483 "failed seeking within half-open restriction<Device>"
484 );
485 }
486 }
487
seek_direct_device()488 void seek_direct_device()
489 {
490 {
491 vector<char> src(
492 data_reps * data_length() + 2 * small_padding, '\n');
493 stream_offset off = small_padding,
494 len = data_reps * data_length();
495 io::array ar(&src[0], &src[0] + src.size());
496 filtering_stream<seekable> io(BOOST_IOSTREAMS_RESTRICT(ar, off, len));
497 BOOST_CHECK_MESSAGE(
498 test_seekable_in_chars(io),
499 "failed seeking within restriction<Direct> with small padding"
500 );
501 }
502
503 {
504 vector<char> src(
505 data_reps * data_length() + small_padding, '\n');
506 stream_offset off = small_padding;
507 io::array ar(&src[0], &src[0] + src.size());
508 filtering_stream<seekable> io(BOOST_IOSTREAMS_RESTRICT(ar, off));
509 BOOST_CHECK_MESSAGE(
510 test_seekable_in_chars(io),
511 "failed seeking within half-open restriction<Direct> "
512 "with small padding"
513 );
514 }
515 }
516
seek_filter()517 void seek_filter()
518 {
519 {
520 restricted_test_file src(small_padding);
521 stream_offset off = large_padding,
522 len = data_reps * data_length();
523 filtering_stream<seekable> io;
524 io.push(BOOST_IOSTREAMS_RESTRICT(identity_seekable_filter(), off, len));
525 io.push(file(src.name(), BOOST_IOS::binary));
526 BOOST_CHECK_MESSAGE(
527 test_seekable_in_chars(io),
528 "failed seeking within restriction<Device>"
529 );
530 }
531
532 {
533 restricted_test_file src(small_padding, true);
534 stream_offset off = large_padding;
535 filtering_stream<seekable> io;
536 io.push(BOOST_IOSTREAMS_RESTRICT(identity_seekable_filter(), off));
537 io.push(file(src.name(), BOOST_IOS::binary));
538 BOOST_CHECK_MESSAGE(
539 test_seekable_in_chars(io),
540 "failed seeking within half-open restriction<Device>"
541 );
542 }
543 }
544
close_device()545 void close_device()
546 {
547 // Restrict a source
548 {
549 operation_sequence seq;
550 chain<input> ch;
551 ch.push(
552 io::BOOST_IOSTREAMS_RESTRICT(
553 closable_device<input>(seq.new_operation(1)),
554 0
555 )
556 );
557 BOOST_CHECK_NO_THROW(ch.reset());
558 BOOST_CHECK_OPERATION_SEQUENCE(seq);
559 }
560
561 // Restrict a seekable device
562 {
563 operation_sequence seq;
564 chain<seekable> ch;
565 ch.push(
566 io::BOOST_IOSTREAMS_RESTRICT(
567 closable_device<seekable>(seq.new_operation(1)),
568 0
569 )
570 );
571 BOOST_CHECK_NO_THROW(ch.reset());
572 BOOST_CHECK_OPERATION_SEQUENCE(seq);
573 }
574
575 // Restrict a direct source
576 {
577 operation_sequence seq;
578 chain<input> ch;
579 ch.push(
580 io::BOOST_IOSTREAMS_RESTRICT(
581 closable_device<direct_input>(seq.new_operation(1)),
582 0
583 )
584 );
585 BOOST_CHECK_NO_THROW(ch.reset());
586 BOOST_CHECK_OPERATION_SEQUENCE(seq);
587 }
588
589 // Restrict a direct seekable device
590 {
591 operation_sequence seq;
592 chain<seekable> ch;
593 ch.push(
594 io::BOOST_IOSTREAMS_RESTRICT(
595 closable_device<direct_seekable>(seq.new_operation(1)),
596 0
597 )
598 );
599 BOOST_CHECK_NO_THROW(ch.reset());
600 BOOST_CHECK_OPERATION_SEQUENCE(seq);
601 }
602 }
603
close_filter()604 void close_filter()
605 {
606 // Restrict an input filter
607 {
608 operation_sequence seq;
609 chain<input> ch;
610 ch.push(
611 io::BOOST_IOSTREAMS_RESTRICT(
612 closable_filter<input>(seq.new_operation(2)),
613 0
614 )
615 );
616 ch.push(closable_device<input>(seq.new_operation(1)));
617 BOOST_CHECK_NO_THROW(ch.reset());
618 BOOST_CHECK_OPERATION_SEQUENCE(seq);
619 }
620
621 // Restrict a seekable filter
622 {
623 operation_sequence seq;
624 chain<seekable> ch;
625 ch.push(
626 io::BOOST_IOSTREAMS_RESTRICT(
627 closable_filter<seekable>(seq.new_operation(1)),
628 0
629 )
630 );
631 ch.push(closable_device<seekable>(seq.new_operation(2)));
632 BOOST_CHECK_NO_THROW(ch.reset());
633 BOOST_CHECK_OPERATION_SEQUENCE(seq);
634 }
635
636 // Restrict a dual_use filter for input
637 {
638 operation_sequence seq;
639 chain<input> ch;
640 operation dummy;
641 ch.push(
642 io::BOOST_IOSTREAMS_RESTRICT(
643 closable_filter<dual_use>(
644 seq.new_operation(2),
645 dummy
646 ),
647 0
648 )
649 );
650 ch.push(closable_device<input>(seq.new_operation(1)));
651 BOOST_CHECK_NO_THROW(ch.reset());
652 BOOST_CHECK_OPERATION_SEQUENCE(seq);
653 }
654
655 // Restrict a dual_use filter for output
656 {
657 operation_sequence seq;
658 chain<output> ch;
659 operation dummy;
660 ch.push(
661 io::BOOST_IOSTREAMS_RESTRICT(
662 closable_filter<dual_use>(
663 dummy,
664 seq.new_operation(1)
665 ),
666 0
667 )
668 );
669 ch.push(closable_device<output>(seq.new_operation(2)));
670 BOOST_CHECK_NO_THROW(ch.reset());
671 BOOST_CHECK_OPERATION_SEQUENCE(seq);
672 }
673 }
674
init_unit_test_suite(int,char * [])675 test_suite* init_unit_test_suite(int, char* [])
676 {
677 test_suite* test =
678 BOOST_TEST_SUITE(BOOST_STRINGIZE(BOOST_IOSTREAMS_RESTRICT) " test");
679 test->add(BOOST_TEST_CASE(&read_device));
680 test->add(BOOST_TEST_CASE(&read_direct_device));
681 test->add(BOOST_TEST_CASE(&read_filter));
682 test->add(BOOST_TEST_CASE(&write_device));
683 test->add(BOOST_TEST_CASE(&write_direct_device));
684 test->add(BOOST_TEST_CASE(&write_filter));
685 test->add(BOOST_TEST_CASE(&seek_device));
686 test->add(BOOST_TEST_CASE(&seek_direct_device));
687 test->add(BOOST_TEST_CASE(&close_device));
688 test->add(BOOST_TEST_CASE(&close_filter));
689 return test;
690 }
691