]> git.proxmox.com Git - ceph.git/blob - ceph/src/Beast/test/core/streambuf.cpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / test / core / streambuf.cpp
1 //
2 // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7
8 // Test that header file is self-contained.
9 #include <beast/core/streambuf.hpp>
10
11 #include "buffer_test.hpp"
12 #include <beast/core/buffer_concepts.hpp>
13 #include <beast/core/to_string.hpp>
14 #include <beast/unit_test/suite.hpp>
15 #include <boost/asio/buffer.hpp>
16 #include <algorithm>
17 #include <atomic>
18 #include <memory>
19 #include <string>
20
21 namespace beast {
22
23 static_assert(is_DynamicBuffer<streambuf>::value, "");
24
25 struct test_allocator_info
26 {
27 std::size_t ncopy = 0;
28 std::size_t nmove = 0;
29 std::size_t nselect = 0;
30 };
31
32 template<class T,
33 bool Assign, bool Move, bool Swap, bool Select>
34 class test_allocator;
35
36 template<class T,
37 bool Assign, bool Move, bool Swap, bool Select>
38 struct test_allocator_base
39 {
40 };
41
42 template<class T,
43 bool Assign, bool Move, bool Swap>
44 struct test_allocator_base<T, Assign, Move, Swap, true>
45 {
46 static
47 test_allocator<T, Assign, Move, Swap, true>
48 select_on_container_copy_construction(
49 test_allocator<T, Assign, Move, Swap, true> const& a)
50 {
51 return test_allocator<T, Assign, Move, Swap, true>{};
52 }
53 };
54
55 template<class T,
56 bool Assign, bool Move, bool Swap, bool Select>
57 class test_allocator : public test_allocator_base<
58 T, Assign, Move, Swap, Select>
59 {
60 std::size_t id_;
61 std::shared_ptr<test_allocator_info> info_;
62
63 template<class, bool, bool, bool, bool>
64 friend class test_allocator;
65
66 public:
67 using value_type = T;
68 using propagate_on_container_copy_assignment =
69 std::integral_constant<bool, Assign>;
70 using propagate_on_container_move_assignment =
71 std::integral_constant<bool, Move>;
72 using propagate_on_container_swap =
73 std::integral_constant<bool, Swap>;
74
75 template<class U>
76 struct rebind
77 {
78 using other = test_allocator<
79 U, Assign, Move, Swap, Select>;
80 };
81
82 test_allocator()
83 : id_([]
84 {
85 static std::atomic<
86 std::size_t> sid(0);
87 return ++sid;
88 }())
89 , info_(std::make_shared<test_allocator_info>())
90 {
91 }
92
93 test_allocator(test_allocator const& u) noexcept
94 : id_(u.id_)
95 , info_(u.info_)
96 {
97 ++info_->ncopy;
98 }
99
100 template<class U>
101 test_allocator(test_allocator<
102 U, Assign, Move, Swap, Select> const& u) noexcept
103 : id_(u.id_)
104 , info_(u.info_)
105 {
106 ++info_->ncopy;
107 }
108
109 test_allocator(test_allocator&& t)
110 : id_(t.id_)
111 , info_(t.info_)
112 {
113 ++info_->nmove;
114 }
115
116 value_type*
117 allocate(std::size_t n)
118 {
119 return static_cast<value_type*>(
120 ::operator new (n*sizeof(value_type)));
121 }
122
123 void
124 deallocate(value_type* p, std::size_t) noexcept
125 {
126 ::operator delete(p);
127 }
128
129 std::size_t
130 id() const
131 {
132 return id_;
133 }
134
135 test_allocator_info const*
136 operator->() const
137 {
138 return info_.get();
139 }
140 };
141
142 class basic_streambuf_test : public beast::unit_test::suite
143 {
144 public:
145 template<class Alloc1, class Alloc2>
146 static
147 bool
148 eq(basic_streambuf<Alloc1> const& sb1,
149 basic_streambuf<Alloc2> const& sb2)
150 {
151 return to_string(sb1.data()) == to_string(sb2.data());
152 }
153
154 template<class ConstBufferSequence>
155 void
156 expect_size(std::size_t n, ConstBufferSequence const& buffers)
157 {
158 BEAST_EXPECT(test::size_pre(buffers) == n);
159 BEAST_EXPECT(test::size_post(buffers) == n);
160 BEAST_EXPECT(test::size_rev_pre(buffers) == n);
161 BEAST_EXPECT(test::size_rev_post(buffers) == n);
162 }
163
164 template<class U, class V>
165 static
166 void
167 self_assign(U& u, V&& v)
168 {
169 u = std::forward<V>(v);
170 }
171
172 void testSpecialMembers()
173 {
174 using boost::asio::buffer;
175 std::string const s = "Hello, world";
176 BEAST_EXPECT(s.size() == 12);
177 for(std::size_t i = 1; i < 12; ++i) {
178 for(std::size_t x = 1; x < 4; ++x) {
179 for(std::size_t y = 1; y < 4; ++y) {
180 std::size_t z = s.size() - (x + y);
181 {
182 streambuf sb(i);
183 sb.commit(buffer_copy(sb.prepare(x), buffer(s.data(), x)));
184 sb.commit(buffer_copy(sb.prepare(y), buffer(s.data()+x, y)));
185 sb.commit(buffer_copy(sb.prepare(z), buffer(s.data()+x+y, z)));
186 BEAST_EXPECT(to_string(sb.data()) == s);
187 {
188 streambuf sb2(sb);
189 BEAST_EXPECT(eq(sb, sb2));
190 }
191 {
192 streambuf sb2;
193 sb2 = sb;
194 BEAST_EXPECT(eq(sb, sb2));
195 }
196 {
197 streambuf sb2(std::move(sb));
198 BEAST_EXPECT(to_string(sb2.data()) == s);
199 expect_size(0, sb.data());
200 sb = std::move(sb2);
201 BEAST_EXPECT(to_string(sb.data()) == s);
202 expect_size(0, sb2.data());
203 }
204 self_assign(sb, sb);
205 BEAST_EXPECT(to_string(sb.data()) == s);
206 self_assign(sb, std::move(sb));
207 BEAST_EXPECT(to_string(sb.data()) == s);
208 }
209 }}}
210 try
211 {
212 streambuf sb0(0);
213 fail();
214 }
215 catch(std::exception const&)
216 {
217 pass();
218 }
219 }
220
221 void testAllocator()
222 {
223 // VFALCO This needs work
224 {
225 using alloc_type =
226 test_allocator<char, false, false, false, false>;
227 using sb_type = basic_streambuf<alloc_type>;
228 sb_type sb;
229 BEAST_EXPECT(sb.get_allocator().id() == 1);
230 }
231 {
232 using alloc_type =
233 test_allocator<char, false, false, false, false>;
234 using sb_type = basic_streambuf<alloc_type>;
235 sb_type sb;
236 BEAST_EXPECT(sb.get_allocator().id() == 2);
237 sb_type sb2(sb);
238 BEAST_EXPECT(sb2.get_allocator().id() == 2);
239 sb_type sb3(sb, alloc_type{});
240 }
241 }
242
243 void
244 testPrepare()
245 {
246 using boost::asio::buffer_size;
247 {
248 streambuf sb(2);
249 BEAST_EXPECT(buffer_size(sb.prepare(5)) == 5);
250 BEAST_EXPECT(buffer_size(sb.prepare(8)) == 8);
251 BEAST_EXPECT(buffer_size(sb.prepare(7)) == 7);
252 }
253 {
254 streambuf sb(2);
255 sb.prepare(2);
256 BEAST_EXPECT(test::buffer_count(sb.prepare(5)) == 2);
257 BEAST_EXPECT(test::buffer_count(sb.prepare(8)) == 3);
258 BEAST_EXPECT(test::buffer_count(sb.prepare(4)) == 2);
259 }
260 }
261
262 void testCommit()
263 {
264 streambuf sb(2);
265 sb.prepare(2);
266 sb.prepare(5);
267 sb.commit(1);
268 expect_size(1, sb.data());
269 }
270
271 void testConsume()
272 {
273 streambuf sb(1);
274 expect_size(5, sb.prepare(5));
275 sb.commit(3);
276 expect_size(3, sb.data());
277 sb.consume(1);
278 expect_size(2, sb.data());
279 }
280
281 void testMatrix()
282 {
283 using boost::asio::buffer;
284 using boost::asio::buffer_size;
285 std::string const s = "Hello, world";
286 BEAST_EXPECT(s.size() == 12);
287 for(std::size_t i = 1; i < 12; ++i) {
288 for(std::size_t x = 1; x < 4; ++x) {
289 for(std::size_t y = 1; y < 4; ++y) {
290 for(std::size_t t = 1; t < 4; ++ t) {
291 for(std::size_t u = 1; u < 4; ++ u) {
292 std::size_t z = s.size() - (x + y);
293 std::size_t v = s.size() - (t + u);
294 {
295 streambuf sb(i);
296 {
297 auto d = sb.prepare(z);
298 BEAST_EXPECT(buffer_size(d) == z);
299 }
300 {
301 auto d = sb.prepare(0);
302 BEAST_EXPECT(buffer_size(d) == 0);
303 }
304 {
305 auto d = sb.prepare(y);
306 BEAST_EXPECT(buffer_size(d) == y);
307 }
308 {
309 auto d = sb.prepare(x);
310 BEAST_EXPECT(buffer_size(d) == x);
311 sb.commit(buffer_copy(d, buffer(s.data(), x)));
312 }
313 BEAST_EXPECT(sb.size() == x);
314 BEAST_EXPECT(buffer_size(sb.data()) == sb.size());
315 {
316 auto d = sb.prepare(x);
317 BEAST_EXPECT(buffer_size(d) == x);
318 }
319 {
320 auto d = sb.prepare(0);
321 BEAST_EXPECT(buffer_size(d) == 0);
322 }
323 {
324 auto d = sb.prepare(z);
325 BEAST_EXPECT(buffer_size(d) == z);
326 }
327 {
328 auto d = sb.prepare(y);
329 BEAST_EXPECT(buffer_size(d) == y);
330 sb.commit(buffer_copy(d, buffer(s.data()+x, y)));
331 }
332 sb.commit(1);
333 BEAST_EXPECT(sb.size() == x + y);
334 BEAST_EXPECT(buffer_size(sb.data()) == sb.size());
335 {
336 auto d = sb.prepare(x);
337 BEAST_EXPECT(buffer_size(d) == x);
338 }
339 {
340 auto d = sb.prepare(y);
341 BEAST_EXPECT(buffer_size(d) == y);
342 }
343 {
344 auto d = sb.prepare(0);
345 BEAST_EXPECT(buffer_size(d) == 0);
346 }
347 {
348 auto d = sb.prepare(z);
349 BEAST_EXPECT(buffer_size(d) == z);
350 sb.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
351 }
352 sb.commit(2);
353 BEAST_EXPECT(sb.size() == x + y + z);
354 BEAST_EXPECT(buffer_size(sb.data()) == sb.size());
355 BEAST_EXPECT(to_string(sb.data()) == s);
356 sb.consume(t);
357 {
358 auto d = sb.prepare(0);
359 BEAST_EXPECT(buffer_size(d) == 0);
360 }
361 BEAST_EXPECT(to_string(sb.data()) == s.substr(t, std::string::npos));
362 sb.consume(u);
363 BEAST_EXPECT(to_string(sb.data()) == s.substr(t + u, std::string::npos));
364 sb.consume(v);
365 BEAST_EXPECT(to_string(sb.data()) == "");
366 sb.consume(1);
367 {
368 auto d = sb.prepare(0);
369 BEAST_EXPECT(buffer_size(d) == 0);
370 }
371 }
372 }}}}}
373 }
374
375 void testIterators()
376 {
377 using boost::asio::buffer_size;
378 streambuf sb(1);
379 sb.prepare(1);
380 sb.commit(1);
381 sb.prepare(2);
382 sb.commit(2);
383 expect_size(3, sb.data());
384 sb.prepare(1);
385 expect_size(3, sb.prepare(3));
386 sb.commit(2);
387 BEAST_EXPECT(test::buffer_count(sb.data()) == 4);
388 }
389
390 void testOutputStream()
391 {
392 streambuf sb;
393 sb << "x";
394 BEAST_EXPECT(to_string(sb.data()) == "x");
395 }
396
397 void testCapacity()
398 {
399 using boost::asio::buffer_size;
400 {
401 streambuf sb{10};
402 BEAST_EXPECT(sb.alloc_size() == 10);
403 BEAST_EXPECT(read_size_helper(sb, 1) == 1);
404 BEAST_EXPECT(read_size_helper(sb, 10) == 10);
405 BEAST_EXPECT(read_size_helper(sb, 20) == 20);
406 BEAST_EXPECT(read_size_helper(sb, 1000) == 512);
407 sb.prepare(3);
408 sb.commit(3);
409 BEAST_EXPECT(read_size_helper(sb, 10) == 7);
410 BEAST_EXPECT(read_size_helper(sb, 1000) == 7);
411 }
412 {
413 streambuf sb(1000);
414 BEAST_EXPECT(sb.alloc_size() == 1000);
415 BEAST_EXPECT(read_size_helper(sb, 1) == 1);
416 BEAST_EXPECT(read_size_helper(sb, 1000) == 1000);
417 BEAST_EXPECT(read_size_helper(sb, 2000) == 1000);
418 sb.prepare(3);
419 BEAST_EXPECT(read_size_helper(sb, 1) == 1);
420 BEAST_EXPECT(read_size_helper(sb, 1000) == 1000);
421 BEAST_EXPECT(read_size_helper(sb, 2000) == 1000);
422 sb.commit(3);
423 BEAST_EXPECT(read_size_helper(sb, 1) == 1);
424 BEAST_EXPECT(read_size_helper(sb, 1000) == 997);
425 BEAST_EXPECT(read_size_helper(sb, 2000) == 997);
426 sb.consume(2);
427 BEAST_EXPECT(read_size_helper(sb, 1) == 1);
428 BEAST_EXPECT(read_size_helper(sb, 1000) == 997);
429 BEAST_EXPECT(read_size_helper(sb, 2000) == 997);
430 }
431 {
432 streambuf sb{2};
433 BEAST_EXPECT(sb.alloc_size() == 2);
434 BEAST_EXPECT(test::buffer_count(sb.prepare(2)) == 1);
435 BEAST_EXPECT(test::buffer_count(sb.prepare(3)) == 2);
436 BEAST_EXPECT(buffer_size(sb.prepare(5)) == 5);
437 BEAST_EXPECT(read_size_helper(sb, 10) == 6);
438 }
439 {
440 auto avail =
441 [](streambuf const& sb)
442 {
443 return sb.capacity() - sb.size();
444 };
445 streambuf sb{100};
446 BEAST_EXPECT(sb.alloc_size() == 100);
447 BEAST_EXPECT(avail(sb) == 0);
448 sb.prepare(100);
449 BEAST_EXPECT(avail(sb) == 100);
450 sb.commit(100);
451 BEAST_EXPECT(avail(sb) == 0);
452 sb.consume(100);
453 BEAST_EXPECT(avail(sb) == 0);
454 sb.alloc_size(200);
455 BEAST_EXPECT(sb.alloc_size() == 200);
456 sb.prepare(1);
457 BEAST_EXPECT(avail(sb) == 200);
458 }
459 }
460
461 void run() override
462 {
463 testSpecialMembers();
464 testAllocator();
465 testPrepare();
466 testCommit();
467 testConsume();
468 testMatrix();
469 testIterators();
470 testOutputStream();
471 testCapacity();
472 }
473 };
474
475 BEAST_DEFINE_TESTSUITE(basic_streambuf,core,beast);
476
477 } // beast