1 //
2 // Copyright (c) 2016-2019 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 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 // Test that header file is self-contained.
11 #include <boost/beast/core/flat_buffer.hpp>
12 
13 #include "test_buffer.hpp"
14 
15 #include <boost/beast/core/ostream.hpp>
16 #include <boost/beast/core/read_size.hpp>
17 #include <boost/beast/core/string.hpp>
18 #include <boost/beast/test/test_allocator.hpp>
19 #include <boost/beast/_experimental/unit_test/suite.hpp>
20 #include <algorithm>
21 #include <cctype>
22 
23 namespace boost {
24 namespace beast {
25 
26 class flat_buffer_test : public beast::unit_test::suite
27 {
28 public:
29     BOOST_STATIC_ASSERT(
30         is_mutable_dynamic_buffer<flat_buffer>::value);
31 
32     void
testDynamicBuffer()33     testDynamicBuffer()
34     {
35         flat_buffer b(30);
36         BEAST_EXPECT(b.max_size() == 30);
37         test_dynamic_buffer(b);
38     }
39 
40     void
testSpecialMembers()41     testSpecialMembers()
42     {
43         using namespace test;
44 
45         using a_t = test::test_allocator<char,
46             true, true, true, true, true>;
47 
48         // Equal == false
49         using a_neq_t = test::test_allocator<char,
50             false, true, true, true, true>;
51 
52         // construction
53         {
54             {
55                 flat_buffer b;
56                 BEAST_EXPECT(b.capacity() == 0);
57             }
58             {
59                 flat_buffer b{500};
60                 BEAST_EXPECT(b.capacity() == 0);
61                 BEAST_EXPECT(b.max_size() == 500);
62             }
63             {
64                 a_neq_t a1;
65                 basic_flat_buffer<a_neq_t> b{a1};
66                 BEAST_EXPECT(b.get_allocator() == a1);
67                 a_neq_t a2;
68                 BEAST_EXPECT(b.get_allocator() != a2);
69             }
70             {
71                 a_neq_t a;
72                 basic_flat_buffer<a_neq_t> b{500, a};
73                 BEAST_EXPECT(b.capacity() == 0);
74                 BEAST_EXPECT(b.max_size() == 500);
75             }
76         }
77 
78         // move construction
79         {
80             {
81                 basic_flat_buffer<a_t> b1{30};
82                 BEAST_EXPECT(b1.get_allocator()->nmove == 0);
83                 ostream(b1) << "Hello";
84                 basic_flat_buffer<a_t> b2{std::move(b1)};
85                 BEAST_EXPECT(b2.get_allocator()->nmove == 1);
86                 BEAST_EXPECT(b1.size() == 0);
87                 BEAST_EXPECT(b1.capacity() == 0);
88                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
89                 BEAST_EXPECT(b1.max_size() == b2.max_size());
90             }
91             {
92                 basic_flat_buffer<a_t> b1{30};
93                 ostream(b1) << "Hello";
94                 a_t a;
95                 basic_flat_buffer<a_t> b2{std::move(b1), a};
96                 BEAST_EXPECT(b1.size() == 0);
97                 BEAST_EXPECT(b1.capacity() == 0);
98                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
99                 BEAST_EXPECT(b1.max_size() == b2.max_size());
100             }
101             {
102                 basic_flat_buffer<a_neq_t> b1{30};
103                 ostream(b1) << "Hello";
104                 a_neq_t a;
105                 basic_flat_buffer<a_neq_t> b2{std::move(b1), a};
106                 BEAST_EXPECT(b1.size() != 0);
107                 BEAST_EXPECT(b1.capacity() != 0);
108                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
109                 BEAST_EXPECT(b1.max_size() == b2.max_size());
110             }
111         }
112 
113         // copy construction
114         {
115             basic_flat_buffer<a_t> b1;
116             ostream(b1) << "Hello";
117             basic_flat_buffer<a_t> b2(b1);
118             BEAST_EXPECT(b1.get_allocator() == b2.get_allocator());
119             BEAST_EXPECT(buffers_to_string(b1.data()) == "Hello");
120             BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
121         }
122         {
123             basic_flat_buffer<a_neq_t> b1;
124             ostream(b1) << "Hello";
125             a_neq_t a;
126             basic_flat_buffer<a_neq_t> b2(b1, a);
127             BEAST_EXPECT(b1.get_allocator() != b2.get_allocator());
128             BEAST_EXPECT(buffers_to_string(b1.data()) == "Hello");
129             BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
130         }
131         {
132             basic_flat_buffer<a_t> b1;
133             ostream(b1) << "Hello";
134             basic_flat_buffer<a_neq_t> b2(b1);
135             BEAST_EXPECT(buffers_to_string(b1.data()) == "Hello");
136             BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
137         }
138         {
139             basic_flat_buffer<a_neq_t> b1;
140             ostream(b1) << "Hello";
141             a_t a;
142             basic_flat_buffer<a_t> b2(b1, a);
143             BEAST_EXPECT(b2.get_allocator() == a);
144             BEAST_EXPECT(buffers_to_string(b1.data()) == "Hello");
145             BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
146         }
147         {
148             flat_buffer b1;
149             ostream(b1) << "Hello";
150             basic_flat_buffer<a_t> b2;
151             b2.reserve(1);
152             BEAST_EXPECT(b2.capacity() == 1);
153             b2 = b1;
154             BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
155             BEAST_EXPECT(b2.capacity() == b2.size());
156         }
157 
158         // move assignment
159         {
160             {
161                 flat_buffer b1;
162                 ostream(b1) << "Hello";
163                 flat_buffer b2;
164                 b2 = std::move(b1);
165                 BEAST_EXPECT(b1.size() == 0);
166                 BEAST_EXPECT(b1.capacity() == 0);
167                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
168             }
169             {
170                 using na_t = test::test_allocator<char,
171                     true, true, false, true, true>;
172                 basic_flat_buffer<na_t> b1;
173                 ostream(b1) << "Hello";
174                 basic_flat_buffer<na_t> b2;
175                 b2 = std::move(b1);
176                 BEAST_EXPECT(b1.get_allocator() == b2.get_allocator());
177                 BEAST_EXPECT(b1.size() == 0);
178                 BEAST_EXPECT(b1.capacity() == 0);
179                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
180             }
181             {
182                 using na_t = test::test_allocator<char,
183                     false, true, false, true, true>;
184                 basic_flat_buffer<na_t> b1;
185                 ostream(b1) << "Hello";
186                 basic_flat_buffer<na_t> b2;
187                 b2 = std::move(b1);
188                 BEAST_EXPECT(b1.get_allocator() != b2.get_allocator());
189                 BEAST_EXPECT(b1.size() != 0);
190                 BEAST_EXPECT(b1.capacity() != 0);
191                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
192             }
193             {
194                 // propagate_on_container_move_assignment : true
195                 using pocma_t = test::test_allocator<char,
196                     true, true, true, true, true>;
197                 basic_flat_buffer<pocma_t> b1;
198                 ostream(b1) << "Hello";
199                 basic_flat_buffer<pocma_t> b2;
200                 b2 = std::move(b1);
201                 BEAST_EXPECT(b1.size() == 0);
202                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
203             }
204             {
205                 // propagate_on_container_move_assignment : false
206                 using pocma_t = test::test_allocator<char,
207                     true, true, false, true, true>;
208                 basic_flat_buffer<pocma_t> b1;
209                 ostream(b1) << "Hello";
210                 basic_flat_buffer<pocma_t> b2;
211                 b2 = std::move(b1);
212                 BEAST_EXPECT(b1.size() == 0);
213                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
214             }
215         }
216 
217         // copy assignment
218         {
219             {
220                 flat_buffer b1;
221                 ostream(b1) << "Hello";
222                 flat_buffer b2;
223                 b2 = b1;
224                 BEAST_EXPECT(buffers_to_string(b1.data()) == "Hello");
225                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
226                 basic_flat_buffer<a_t> b3;
227                 b3 = b2;
228                 BEAST_EXPECT(buffers_to_string(b3.data()) == "Hello");
229             }
230             {
231                 // propagate_on_container_copy_assignment : true
232                 using pocca_t = test::test_allocator<char,
233                     true, true, true, true, true>;
234                 basic_flat_buffer<pocca_t> b1;
235                 ostream(b1) << "Hello";
236                 basic_flat_buffer<pocca_t> b2;
237                 b2 = b1;
238                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
239             }
240             {
241                 // propagate_on_container_copy_assignment : false
242                 using pocca_t = test::test_allocator<char,
243                     true, false, true, true, true>;
244                 basic_flat_buffer<pocca_t> b1;
245                 ostream(b1) << "Hello";
246                 basic_flat_buffer<pocca_t> b2;
247                 b2 = b1;
248                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
249             }
250         }
251 
252         // operations
253         {
254             string_view const s = "Hello, world!";
255             flat_buffer b1{64};
256             BEAST_EXPECT(b1.size() == 0);
257             BEAST_EXPECT(b1.max_size() == 64);
258             BEAST_EXPECT(b1.capacity() == 0);
259             ostream(b1) << s;
260             BEAST_EXPECT(buffers_to_string(b1.data()) == s);
261             {
262                 flat_buffer b2{b1};
263                 BEAST_EXPECT(buffers_to_string(b2.data()) == s);
264                 b2.consume(7);
265                 BEAST_EXPECT(buffers_to_string(b2.data()) == s.substr(7));
266             }
267             {
268                 flat_buffer b2{32};
269                 BEAST_EXPECT(b2.max_size() == 32);
270                 b2 = b1;
271                 BEAST_EXPECT(b2.max_size() == b1.max_size());
272                 BEAST_EXPECT(buffers_to_string(b2.data()) == s);
273                 b2.consume(7);
274                 BEAST_EXPECT(buffers_to_string(b2.data()) == s.substr(7));
275             }
276         }
277 
278         // cause memmove
279         {
280             flat_buffer b{20};
281             ostream(b) << "12345";
282             b.consume(3);
283             ostream(b) << "67890123";
284             BEAST_EXPECT(buffers_to_string(b.data()) == "4567890123");
285         }
286 
287         // max_size
288         {
289             flat_buffer b{10};
290             BEAST_EXPECT(b.max_size() == 10);
291             b.max_size(32);
292             BEAST_EXPECT(b.max_size() == 32);
293         }
294 
295         // allocator max_size
296         {
297             basic_flat_buffer<a_t> b;
298             auto a = b.get_allocator();
299             BOOST_STATIC_ASSERT(
300                 ! std::is_const<decltype(a)>::value);
301             a->max_size = 30;
302             try
303             {
304                 b.prepare(1000);
305                 fail("", __FILE__, __LINE__);
306             }
307             catch(std::length_error const&)
308             {
309                 pass();
310             }
311         }
312 
313         // read_size
314         {
315             flat_buffer b{10};
316             BEAST_EXPECT(read_size(b, 512) == 10);
317             b.prepare(4);
318             b.commit(4);
319             BEAST_EXPECT(read_size(b, 512) == 6);
320             b.consume(2);
321             BEAST_EXPECT(read_size(b, 512) == 8);
322             b.prepare(8);
323             b.commit(8);
324             BEAST_EXPECT(read_size(b, 512) == 0);
325         }
326 
327         // swap
328         {
329             {
330                 basic_flat_buffer<a_neq_t> b1;
331                 ostream(b1) << "Hello";
332                 basic_flat_buffer<a_neq_t> b2;
333                 BEAST_EXPECT(b1.get_allocator() != b2.get_allocator());
334                 swap(b1, b2);
335                 BEAST_EXPECT(b1.get_allocator() != b2.get_allocator());
336                 BEAST_EXPECT(b1.size() == 0);
337                 BEAST_EXPECT(b1.capacity() == 0);
338                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
339             }
340             {
341                 using na_t = test::test_allocator<char,
342                     true, true, true, false, true>;
343                 na_t a1;
344                 basic_flat_buffer<na_t> b1{a1};
345                 na_t a2;
346                 ostream(b1) << "Hello";
347                 basic_flat_buffer<na_t> b2{a2};
348                 BEAST_EXPECT(b1.get_allocator() == a1);
349                 BEAST_EXPECT(b2.get_allocator() == a2);
350                 swap(b1, b2);
351                 BEAST_EXPECT(b1.get_allocator() == b2.get_allocator());
352                 BEAST_EXPECT(b1.size() == 0);
353                 BEAST_EXPECT(b1.capacity() == 0);
354                 BEAST_EXPECT(buffers_to_string(b2.data()) == "Hello");
355             }
356         }
357 
358         // prepare
359         {
360             flat_buffer b{100};
361             b.prepare(10);
362             b.commit(10);
363             b.prepare(5);
364             BEAST_EXPECT(b.capacity() >= 5);
365             try
366             {
367                 b.prepare(1000);
368                 fail("", __FILE__, __LINE__);
369             }
370             catch(std::length_error const&)
371             {
372                 pass();
373             }
374         }
375 
376         // reserve
377         {
378             flat_buffer b;
379             BEAST_EXPECT(b.capacity() == 0);
380             b.reserve(50);
381             BEAST_EXPECT(b.capacity() == 50);
382             b.prepare(20);
383             b.commit(20);
384             b.reserve(50);
385             BEAST_EXPECT(b.capacity() == 50);
386 
387             b.max_size(b.capacity());
388             b.reserve(b.max_size() + 20);
389             BEAST_EXPECT(b.capacity() == 70);
390             BEAST_EXPECT(b.max_size() == 70);
391         }
392 
393         // shrink to fit
394         {
395             flat_buffer b;
396             BEAST_EXPECT(b.capacity() == 0);
397             b.prepare(50);
398             BEAST_EXPECT(b.capacity() == 50);
399             b.commit(50);
400             BEAST_EXPECT(b.capacity() == 50);
401             b.prepare(75);
402             BEAST_EXPECT(b.capacity() >= 125);
403             b.shrink_to_fit();
404             BEAST_EXPECT(b.capacity() == b.size());
405             b.shrink_to_fit();
406             BEAST_EXPECT(b.capacity() == b.size());
407             b.consume(b.size());
408             BEAST_EXPECT(b.size() == 0);
409             b.shrink_to_fit();
410             BEAST_EXPECT(b.capacity() == 0);
411         }
412 
413         // clear
414         {
415             flat_buffer b;
416             BEAST_EXPECT(b.capacity() == 0);
417             b.prepare(50);
418             b.commit(50);
419             BEAST_EXPECT(b.size() == 50);
420             BEAST_EXPECT(b.capacity() == 50);
421             b.clear();
422             BEAST_EXPECT(b.size() == 0);
423             BEAST_EXPECT(b.capacity() == 50);
424         }
425     }
426 
427     void
run()428     run() override
429     {
430         testDynamicBuffer();
431         testSpecialMembers();
432     }
433 };
434 
435 BEAST_DEFINE_TESTSUITE(beast,core,flat_buffer);
436 
437 } // beast
438 } // boost
439