1 | // (C) COPYRIGHT 2017 ARM Limited |
2 | |
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 | #include <boost/iostreams/categories.hpp> // tags. |
7 | #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp> |
8 | #include <boost/iostreams/filter/gzip.hpp> |
9 | #include <boost/iostreams/filtering_stream.hpp> |
10 | #include <boost/iostreams/write.hpp> |
11 | #include <boost/test/unit_test.hpp> |
12 | |
13 | using namespace boost; |
14 | using namespace boost::iostreams; |
15 | using boost::unit_test::test_suite; |
16 | |
17 | struct limit_device { |
18 | typedef char char_type; |
19 | typedef sink_tag category; |
20 | int written, overflow_count, limit; |
21 | explicit limit_device(int limit = 20) : written(0), overflow_count(0), limit(limit) {} |
22 | std::streamsize write(const char_type *, std::streamsize n) |
23 | { |
24 | if (written > limit) { |
25 | // first return partial writes, then an error |
26 | ++overflow_count; |
27 | if (overflow_count > 2 || n < 2) |
28 | { |
29 | return -1; |
30 | } |
31 | n /= 2; |
32 | } |
33 | written += n; |
34 | return n; |
35 | } |
36 | }; |
37 | |
38 | static void disk_full_test() |
39 | { |
40 | // non_blocking_adapter used to handle write returning |
41 | // -1 correctly, usually hanging (see ticket 2557). |
42 | // As non_blocking_adapter is used for ofstream, this |
43 | // would happen for ordinary files when reaching quota, |
44 | // disk full or rlimits. |
45 | // Could be tested without gzip_compressor, |
46 | // but this tests a bit better that the whole path can handle it. |
47 | // TODO: should there be some check on error bit being set |
48 | // or should an exception be triggered? |
49 | limit_device outdev; |
50 | non_blocking_adapter<limit_device> nonblock_outdev(outdev); |
51 | filtering_ostream out; |
52 | out.push(t: gzip_compressor()); |
53 | out.push(t: nonblock_outdev); |
54 | write(t&: out, s: "teststring0123456789" , n: 20); |
55 | out.flush(); |
56 | write(t&: out, s: "secondwrite123456789" , n: 20); |
57 | close(t&: out); |
58 | } |
59 | |
60 | test_suite* init_unit_test_suite(int, char* []) |
61 | { |
62 | test_suite* test = BOOST_TEST_SUITE("disk full test" ); |
63 | test->add(BOOST_TEST_CASE(&disk_full_test)); |
64 | return test; |
65 | } |
66 | |