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.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
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>
32 using namespace seastar
;
35 static sstring
to_sstring(const packet
& p
) {
36 sstring
res(sstring::initialized_later(), p
.len());
38 for (auto& frag
: p
.fragments()) {
39 i
= std::copy(frag
.base
, frag
.base
+ frag
.size
, i
);
48 stream_maker
size(size_t size
) && {
50 return std::move(*this);
53 stream_maker
trim(bool do_trim
) && {
55 return std::move(*this);
58 lw_shared_ptr
<output_stream
<char>> operator()(data_sink sink
) {
59 return make_lw_shared
<output_stream
<char>>(std::move(sink
), _size
, _trim
);
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
) {
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
)));
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());
79 for (auto&& chunk
: *sh_expected_splits
) {
80 BOOST_REQUIRE(to_sstring((*v
)[i
]) == chunk
);
87 SEASTAR_TEST_CASE(test_splitting
) {
88 auto ctor
= stream_maker().trim(false).size(4);
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"}); })
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"}); })
108 SEASTAR_TEST_CASE(test_splitting_with_trimming
) {
109 auto ctor
= stream_maker().trim(true).size(4);
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"}); })
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);
127 return out
->flush().then([v
, out
] {
128 BOOST_REQUIRE(v
->empty());