]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/iostreams/test/tee_test.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / iostreams / test / tee_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 <fstream>
9 #include <boost/iostreams/compose.hpp>
10 #include <boost/iostreams/device/file.hpp>
11 #include <boost/iostreams/filtering_stream.hpp>
12 #include <boost/iostreams/tee.hpp>
13 #include <boost/test/test_tools.hpp>
14 #include <boost/test/unit_test.hpp>
15 #include "detail/closable.hpp"
16 #include "detail/operation_sequence.hpp"
17 #include "detail/temp_file.hpp"
18 #include "detail/verification.hpp"
19
20 using namespace std;
21 using namespace boost;
22 using namespace boost::iostreams;
23 using namespace boost::iostreams::test;
24 using boost::unit_test::test_suite;
25
26 void read_write_test()
27 {
28 {
29 test_file src1, src2;
30 temp_file dest;
31 filtering_istream first, second;
32 first.push(tee(file_sink(dest.name(), out_mode)));
33 first.push(file_source(src1.name(), in_mode));
34 second.push(file_source(src2.name(), in_mode));
35 compare_streams_in_chars(first, second); // ignore return value
36 first.reset();
37 BOOST_CHECK_MESSAGE(
38 compare_files(dest.name(), src1.name()),
39 "failed reading from a tee_filter in chars"
40 );
41 }
42
43 {
44 test_file src1, src2;
45 temp_file dest;
46 filtering_istream first, second;
47 first.push(tee(file_sink(dest.name(), out_mode)));
48 first.push(file_source(src1.name(), in_mode));
49 second.push(file_source(src2.name(), in_mode));
50 compare_streams_in_chunks(first, second); // ignore return value
51 first.reset();
52 BOOST_CHECK_MESSAGE(
53 compare_files(dest.name(), src1.name()),
54 "failed reading from a tee_filter in chunks"
55 );
56 }
57
58 {
59 temp_file dest1;
60 temp_file dest2;
61 filtering_ostream out;
62 out.push(tee(file_sink(dest1.name(), out_mode)));
63 out.push(file_sink(dest2.name(), out_mode));
64 write_data_in_chars(out);
65 out.reset();
66 BOOST_CHECK_MESSAGE(
67 compare_files(dest1.name(), dest2.name()),
68 "failed writing to a tee_filter in chars"
69 );
70 }
71
72 {
73 temp_file dest1;
74 temp_file dest2;
75 filtering_ostream out;
76 out.push(tee(file_sink(dest1.name(), out_mode)));
77 out.push(file_sink(dest2.name(), out_mode));
78 write_data_in_chunks(out);
79 out.reset();
80 BOOST_CHECK_MESSAGE(
81 compare_files(dest1.name(), dest2.name()),
82 "failed writing to a tee_filter in chunks"
83 );
84 }
85
86 {
87 test_file src1, src2;
88 temp_file dest;
89 filtering_istream first, second;
90 first.push( tee( file_source(src1.name(), in_mode),
91 file_sink(dest.name(), out_mode) ) );
92 second.push(file_source(src2.name(), in_mode));
93 compare_streams_in_chars(first, second); // ignore return value
94 first.reset();
95 BOOST_CHECK_MESSAGE(
96 compare_files(dest.name(), src1.name()),
97 "failed reading from a tee_device in chars"
98 );
99 }
100
101 {
102 test_file src1, src2;
103 temp_file dest;
104 filtering_istream first, second;
105 first.push( tee( file_source(src1.name(), in_mode),
106 file_sink(dest.name(), out_mode) ) );
107 second.push(file_source(src2.name(), in_mode));
108 compare_streams_in_chunks(first, second); // ignore return value
109 first.reset();
110 BOOST_CHECK_MESSAGE(
111 compare_files(dest.name(), src1.name()),
112 "failed reading from a tee_device in chunks"
113 );
114 }
115
116 {
117 temp_file dest1;
118 temp_file dest2;
119 filtering_ostream out;
120 out.push( tee( file_sink(dest1.name(), out_mode),
121 file_sink(dest2.name(), out_mode) ) );
122 write_data_in_chars(out);
123 out.reset();
124 BOOST_CHECK_MESSAGE(
125 compare_files(dest1.name(), dest2.name()),
126 "failed writing to a tee_device in chars"
127 );
128 }
129
130 {
131 temp_file dest1;
132 temp_file dest2;
133 filtering_ostream out;
134 out.push( tee( file_sink(dest1.name(), out_mode),
135 file_sink(dest2.name(), out_mode) ) );
136 write_data_in_chunks(out);
137 out.reset();
138 BOOST_CHECK_MESSAGE(
139 compare_files(dest1.name(), dest2.name()),
140 "failed writing to a tee_device in chunks"
141 );
142 }
143 }
144
145 void close_test()
146 {
147 // Note: The implementation of tee_device closes the first
148 // sink before the second
149
150 // Tee two sinks (Borland <= 5.8.2 needs a little help compiling this case,
151 // but it executes the closing algorithm correctly)
152 {
153 operation_sequence seq;
154 chain<output> ch;
155 ch.push(
156 boost::iostreams::tee(
157 closable_device<output>(seq.new_operation(1)),
158 closable_device<
159 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x582))
160 borland_output
161 #else
162 output
163 #endif
164 >(seq.new_operation(2))
165 )
166 );
167 BOOST_CHECK_NO_THROW(ch.reset());
168 BOOST_CHECK_OPERATION_SEQUENCE(seq);
169 }
170
171 // Tee two bidirectional devices
172 {
173 operation_sequence seq;
174 chain<output> ch;
175 ch.push(
176 boost::iostreams::tee(
177 closable_device<bidirectional>(
178 seq.new_operation(1),
179 seq.new_operation(2)
180 ),
181 closable_device<bidirectional>(
182 seq.new_operation(3),
183 seq.new_operation(4)
184 )
185 )
186 );
187 BOOST_CHECK_NO_THROW(ch.reset());
188 BOOST_CHECK_OPERATION_SEQUENCE(seq);
189 }
190
191 // Tee two seekable devices
192 {
193 operation_sequence seq;
194 chain<output> ch;
195 ch.push(
196 boost::iostreams::tee(
197 closable_device<seekable>(seq.new_operation(1)),
198 closable_device<seekable>(seq.new_operation(2))
199 )
200 );
201 BOOST_CHECK_NO_THROW(ch.reset());
202 BOOST_CHECK_OPERATION_SEQUENCE(seq);
203 }
204
205 // Tee a sink
206 {
207 operation_sequence seq;
208 chain<output> ch;
209 ch.push(boost::iostreams::tee(closable_device<output>(seq.new_operation(1))));
210 ch.push(closable_device<output>(seq.new_operation(2)));
211 BOOST_CHECK_NO_THROW(ch.reset());
212 BOOST_CHECK_OPERATION_SEQUENCE(seq);
213 }
214
215 // Tee a bidirectional device
216 {
217 operation_sequence seq;
218 chain<output> ch;
219 ch.push(
220 boost::iostreams::tee(
221 closable_device<bidirectional>(
222 seq.new_operation(1),
223 seq.new_operation(2)
224 )
225 )
226 );
227 ch.push(closable_device<output>(seq.new_operation(3)));
228 BOOST_CHECK_NO_THROW(ch.reset());
229 BOOST_CHECK_OPERATION_SEQUENCE(seq);
230 }
231
232 // Tee a seekable device
233 {
234 operation_sequence seq;
235 chain<output> ch;
236 ch.push(boost::iostreams::tee(closable_device<seekable>(seq.new_operation(1))));
237 ch.push(closable_device<seekable>(seq.new_operation(2)));
238 BOOST_CHECK_NO_THROW(ch.reset());
239 BOOST_CHECK_OPERATION_SEQUENCE(seq);
240 }
241 }
242
243 void test_std_io()
244 {
245 {
246 temp_file dest1;
247 temp_file dest2;
248 filtering_ostream out;
249 std::ofstream stream1(dest1.name().c_str(), out_mode);
250 out.push(tee(stream1));
251 out.push(file_sink(dest2.name(), out_mode));
252 write_data_in_chunks(out);
253 BOOST_CHECK_MESSAGE(
254 compare_files(dest1.name(), dest2.name()),
255 "failed writing to a tee_device in chunks"
256 );
257 }
258 {
259 temp_file dest1;
260 temp_file dest2;
261 filtering_ostream out;
262 std::ofstream stream1(dest1.name().c_str(), out_mode);
263 out.push( tee ( stream1,
264 file_sink(dest2.name(), out_mode) ) );
265 write_data_in_chunks(out);
266 BOOST_CHECK_MESSAGE(
267 compare_files(dest1.name(), dest2.name()),
268 "failed writing to a tee_device in chunks"
269 );
270 }
271 {
272 temp_file dest1;
273 temp_file dest2;
274 filtering_ostream out;
275 std::ofstream stream2(dest2.name().c_str(), out_mode);
276 out.push( tee ( file_sink(dest1.name(), out_mode),
277 stream2 ) );
278 write_data_in_chunks(out);
279 BOOST_CHECK_MESSAGE(
280 compare_files(dest1.name(), dest2.name()),
281 "failed writing to a tee_device in chunks"
282 );
283 }
284 {
285 temp_file dest1;
286 temp_file dest2;
287 filtering_ostream out;
288 std::ofstream stream1(dest1.name().c_str(), out_mode);
289 std::ofstream stream2(dest2.name().c_str(), out_mode);
290 out.push(tee(stream1, stream2));
291 write_data_in_chunks(out);
292 BOOST_CHECK_MESSAGE(
293 compare_files(dest1.name(), dest2.name()),
294 "failed writing to a tee_device in chunks"
295 );
296 }
297 }
298
299 void tee_composite_test()
300 {
301 // This test is probably redundant, given the above test and the tests in
302 // compose_test.cpp, but it verifies that ticket #1002 is fixed
303
304 // Tee a composite sink with a sink
305 {
306 operation_sequence seq;
307 chain<output> ch;
308 ch.push(
309 boost::iostreams::tee(
310 boost::iostreams::compose(
311 closable_filter<output>(seq.new_operation(1)),
312 closable_device<output>(seq.new_operation(2))
313 ),
314 closable_device<output>(seq.new_operation(3))
315 )
316 );
317 BOOST_CHECK_NO_THROW(ch.reset());
318 BOOST_CHECK_OPERATION_SEQUENCE(seq);
319 }
320
321 // Tee a composite bidirectional device with a sink
322 {
323 operation_sequence seq;
324 chain<output> ch;
325 ch.push(
326 boost::iostreams::tee(
327 boost::iostreams::compose(
328 closable_filter<bidirectional>(
329 seq.new_operation(2),
330 seq.new_operation(3)
331 ),
332 closable_device<bidirectional>(
333 seq.new_operation(1),
334 seq.new_operation(4)
335 )
336 ),
337 closable_device<output>(seq.new_operation(5))
338 )
339 );
340 BOOST_CHECK_NO_THROW(ch.reset());
341 BOOST_CHECK_OPERATION_SEQUENCE(seq);
342 }
343
344 // Tee a composite composite seekable device with a sink
345 {
346 operation_sequence seq;
347 chain<output> ch;
348 ch.push(
349 boost::iostreams::tee(
350 boost::iostreams::compose(
351 closable_filter<seekable>(seq.new_operation(1)),
352 closable_device<seekable>(seq.new_operation(2))
353 ),
354 closable_device<output>(seq.new_operation(3))
355 )
356 );
357 BOOST_CHECK_NO_THROW(ch.reset());
358 BOOST_CHECK_OPERATION_SEQUENCE(seq);
359 }
360
361
362 // Tee a composite sink
363 {
364 operation_sequence seq;
365 chain<output> ch;
366 ch.push(
367 boost::iostreams::tee(
368 boost::iostreams::compose(
369 closable_filter<output>(seq.new_operation(1)),
370 closable_device<output>(seq.new_operation(2))
371 )
372 )
373 );
374 ch.push(closable_device<output>(seq.new_operation(3)));
375 BOOST_CHECK_NO_THROW(ch.reset());
376 BOOST_CHECK_OPERATION_SEQUENCE(seq);
377 }
378
379 // Tee a composite bidirectional device with a sink
380 {
381 operation_sequence seq;
382 chain<output> ch;
383 ch.push(
384 boost::iostreams::tee(
385 boost::iostreams::compose(
386 closable_filter<bidirectional>(
387 seq.new_operation(2),
388 seq.new_operation(3)
389 ),
390 closable_device<bidirectional>(
391 seq.new_operation(1),
392 seq.new_operation(4)
393 )
394 )
395 )
396 );
397 ch.push(closable_device<output>(seq.new_operation(5)));
398 BOOST_CHECK_NO_THROW(ch.reset());
399 BOOST_CHECK_OPERATION_SEQUENCE(seq);
400 }
401
402 // Tee a composite composite seekable device with a sink
403 {
404 operation_sequence seq;
405 chain<output> ch;
406 ch.push(
407 boost::iostreams::tee(
408 boost::iostreams::compose(
409 closable_filter<seekable>(seq.new_operation(1)),
410 closable_device<seekable>(seq.new_operation(2))
411 )
412 )
413 );
414 ch.push(closable_device<output>(seq.new_operation(3)));
415 BOOST_CHECK_NO_THROW(ch.reset());
416 BOOST_CHECK_OPERATION_SEQUENCE(seq);
417 }
418 }
419
420 test_suite* init_unit_test_suite(int, char* [])
421 {
422 test_suite* test = BOOST_TEST_SUITE("tee test");
423 test->add(BOOST_TEST_CASE(&read_write_test));
424 test->add(BOOST_TEST_CASE(&close_test));
425 return test;
426 }