| 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 | |