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