]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/tests/unit/output_stream_test.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / seastar / tests / unit / output_stream_test.cc
1 /*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18 /*
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
20 */
21
22 #include <seastar/core/app-template.hh>
23 #include <seastar/core/shared_ptr.hh>
24 #include <seastar/core/reactor.hh>
25 #include <seastar/core/vector-data-sink.hh>
26 #include <seastar/core/future-util.hh>
27 #include <seastar/core/sstring.hh>
28 #include <seastar/net/packet.hh>
29 #include <seastar/testing/test_case.hh>
30 #include <vector>
31
32 using namespace seastar;
33 using namespace net;
34
35 static sstring to_sstring(const packet& p) {
36 sstring res(sstring::initialized_later(), p.len());
37 auto i = res.begin();
38 for (auto& frag : p.fragments()) {
39 i = std::copy(frag.base, frag.base + frag.size, i);
40 }
41 return res;
42 }
43
44 struct stream_maker {
45 bool _trim = false;
46 size_t _size;
47
48 stream_maker size(size_t size) && {
49 _size = size;
50 return std::move(*this);
51 }
52
53 stream_maker trim(bool do_trim) && {
54 _trim = do_trim;
55 return std::move(*this);
56 }
57
58 lw_shared_ptr<output_stream<char>> operator()(data_sink sink) {
59 return make_lw_shared<output_stream<char>>(std::move(sink), _size, _trim);
60 }
61 };
62
63 template <typename T, typename StreamConstructor>
64 future<> assert_split(StreamConstructor stream_maker, std::initializer_list<T> write_calls,
65 std::vector<std::string> expected_split) {
66 static int i = 0;
67 BOOST_TEST_MESSAGE("checking split: " << i++);
68 auto sh_write_calls = make_lw_shared<std::initializer_list<T>>(std::move(write_calls));
69 auto sh_expected_splits = make_lw_shared<std::vector<std::string>>(std::move(expected_split));
70 auto v = make_shared<std::vector<packet>>();
71 auto out = stream_maker(data_sink(std::make_unique<vector_data_sink>(*v)));
72
73 return do_for_each(sh_write_calls->begin(), sh_write_calls->end(), [out, sh_write_calls] (auto&& chunk) {
74 return out->write(chunk);
75 }).then([out, v, sh_expected_splits] {
76 return out->close().then([out, v, sh_expected_splits] {
77 BOOST_REQUIRE_EQUAL(v->size(), sh_expected_splits->size());
78 int i = 0;
79 for (auto&& chunk : *sh_expected_splits) {
80 BOOST_REQUIRE(to_sstring((*v)[i]) == chunk);
81 i++;
82 }
83 });
84 });
85 }
86
87 SEASTAR_TEST_CASE(test_splitting) {
88 auto ctor = stream_maker().trim(false).size(4);
89 return now()
90 .then([=] { return assert_split(ctor, {"1"}, {"1"}); })
91 .then([=] { return assert_split(ctor, {"12", "3"}, {"123"}); })
92 .then([=] { return assert_split(ctor, {"12", "34"}, {"1234"}); })
93 .then([=] { return assert_split(ctor, {"12", "345"}, {"1234", "5"}); })
94 .then([=] { return assert_split(ctor, {"1234"}, {"1234"}); })
95 .then([=] { return assert_split(ctor, {"12345"}, {"12345"}); })
96 .then([=] { return assert_split(ctor, {"1234567890"}, {"1234567890"}); })
97 .then([=] { return assert_split(ctor, {"1", "23456"}, {"1234", "56"}); })
98 .then([=] { return assert_split(ctor, {"123", "4567"}, {"1234", "567"}); })
99 .then([=] { return assert_split(ctor, {"123", "45678"}, {"1234", "5678"}); })
100 .then([=] { return assert_split(ctor, {"123", "4567890"}, {"1234", "567890"}); })
101 .then([=] { return assert_split(ctor, {"1234", "567"}, {"1234", "567"}); })
102
103 .then([] { return assert_split(stream_maker().trim(false).size(3), {"1", "234567", "89"}, {"123", "4567", "89"}); })
104 .then([] { return assert_split(stream_maker().trim(false).size(3), {"1", "2345", "67"}, {"123", "456", "7"}); })
105 ;
106 }
107
108 SEASTAR_TEST_CASE(test_splitting_with_trimming) {
109 auto ctor = stream_maker().trim(true).size(4);
110 return now()
111 .then([=] { return assert_split(ctor, {"1"}, {"1"}); })
112 .then([=] { return assert_split(ctor, {"12", "3"}, {"123"}); })
113 .then([=] { return assert_split(ctor, {"12", "3456789"}, {"1234", "5678", "9"}); })
114 .then([=] { return assert_split(ctor, {"12", "3456789", "12"}, {"1234", "5678", "912"}); })
115 .then([=] { return assert_split(ctor, {"123456789"}, {"1234", "5678", "9"}); })
116 .then([=] { return assert_split(ctor, {"12345678"}, {"1234", "5678"}); })
117 .then([=] { return assert_split(ctor, {"12345678", "9"}, {"1234", "5678", "9"}); })
118 .then([=] { return assert_split(ctor, {"1234", "567890"}, {"1234", "5678", "90"}); })
119 ;
120 }
121
122 SEASTAR_TEST_CASE(test_flush_on_empty_buffer_does_not_push_empty_packet_down_stream) {
123 auto v = make_shared<std::vector<packet>>();
124 auto out = make_shared<output_stream<char>>(
125 data_sink(std::make_unique<vector_data_sink>(*v)), 8);
126
127 return out->flush().then([v, out] {
128 BOOST_REQUIRE(v->empty());
129 return out->close();
130 }).finally([out]{});
131 }