OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/containers/circular_deque.h" |
| 6 |
| 7 #include "base/test/copy_only_int.h" |
| 8 #include "base/test/move_only_int.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 |
| 11 using base::internal::VectorBuffer; |
| 12 |
| 13 namespace base { |
| 14 |
| 15 namespace { |
| 16 |
| 17 circular_deque<int> MakeSequence(size_t max) { |
| 18 circular_deque<int> ret; |
| 19 for (size_t i = 0; i < max; i++) |
| 20 ret.push_back(i); |
| 21 return ret; |
| 22 } |
| 23 |
| 24 // Cycles through the queue, popping items from the back and pushing items |
| 25 // at the front to validate behavior across different configurations of the |
| 26 // queue in relation to the underlying buffer. The tester closure is run for |
| 27 // each cycle. |
| 28 template <class QueueT, class Tester> |
| 29 void CycleTest(circular_deque<QueueT>& queue, const Tester& tester) { |
| 30 size_t steps = queue.size() * 2; |
| 31 for (size_t i = 0; i < steps; i++) { |
| 32 tester(queue, i); |
| 33 queue.pop_back(); |
| 34 queue.push_front(QueueT()); |
| 35 } |
| 36 } |
| 37 |
| 38 } // namespace |
| 39 |
| 40 TEST(CircularDeque, FillConstructor) { |
| 41 constexpr size_t num_elts = 9; |
| 42 |
| 43 std::vector<int> foo(15); |
| 44 EXPECT_EQ(15u, foo.size()); |
| 45 |
| 46 // Fill with default constructor. |
| 47 { |
| 48 circular_deque<int> buf(num_elts); |
| 49 |
| 50 EXPECT_EQ(num_elts, buf.size()); |
| 51 EXPECT_EQ(num_elts, static_cast<size_t>(buf.end() - buf.begin())); |
| 52 |
| 53 for (size_t i = 0; i < num_elts; i++) |
| 54 EXPECT_EQ(0, buf[i]); |
| 55 } |
| 56 |
| 57 // Fill with explicit value. |
| 58 { |
| 59 int value = 199; |
| 60 circular_deque<int> buf(num_elts, value); |
| 61 |
| 62 EXPECT_EQ(num_elts, buf.size()); |
| 63 EXPECT_EQ(num_elts, static_cast<size_t>(buf.end() - buf.begin())); |
| 64 |
| 65 for (size_t i = 0; i < num_elts; i++) |
| 66 EXPECT_EQ(value, buf[i]); |
| 67 } |
| 68 } |
| 69 |
| 70 TEST(CircularDeque, CopyAndRangeConstructor) { |
| 71 int values[] = {1, 2, 3, 4, 5, 6}; |
| 72 circular_deque<CopyOnlyInt> first(std::begin(values), std::end(values)); |
| 73 |
| 74 circular_deque<CopyOnlyInt> second(first); |
| 75 EXPECT_EQ(6u, second.size()); |
| 76 for (int i = 0; i < 6; i++) |
| 77 EXPECT_EQ(i + 1, second[i].data()); |
| 78 } |
| 79 |
| 80 TEST(CircularDeque, MoveConstructor) { |
| 81 int values[] = {1, 2, 3, 4, 5, 6}; |
| 82 circular_deque<MoveOnlyInt> first(std::begin(values), std::end(values)); |
| 83 |
| 84 circular_deque<MoveOnlyInt> second(std::move(first)); |
| 85 EXPECT_TRUE(first.empty()); |
| 86 EXPECT_EQ(6u, second.size()); |
| 87 for (int i = 0; i < 6; i++) |
| 88 EXPECT_EQ(i + 1, second[i].data()); |
| 89 } |
| 90 |
| 91 TEST(CircularDeque, InitializerListConstructor) { |
| 92 circular_deque<int> empty({}); |
| 93 ASSERT_TRUE(empty.empty()); |
| 94 |
| 95 circular_deque<int> first({1, 2, 3, 4, 5, 6}); |
| 96 EXPECT_EQ(6u, first.size()); |
| 97 for (int i = 0; i < 6; i++) |
| 98 EXPECT_EQ(i + 1, first[i]); |
| 99 } |
| 100 |
| 101 TEST(CircularDeque, EqualsCopy) { |
| 102 circular_deque<int> first = {1, 2, 3, 4, 5, 6}; |
| 103 circular_deque<int> copy; |
| 104 EXPECT_TRUE(copy.empty()); |
| 105 copy = first; |
| 106 EXPECT_EQ(6u, copy.size()); |
| 107 for (int i = 0; i < 6; i++) { |
| 108 EXPECT_EQ(i + 1, first[i]); |
| 109 EXPECT_EQ(i + 1, copy[i]); |
| 110 EXPECT_NE(&first[i], ©[i]); |
| 111 } |
| 112 } |
| 113 |
| 114 TEST(CircularDeque, EqualsMove) { |
| 115 circular_deque<int> first = {1, 2, 3, 4, 5, 6}; |
| 116 circular_deque<int> move; |
| 117 EXPECT_TRUE(move.empty()); |
| 118 move = std::move(first); |
| 119 EXPECT_TRUE(first.empty()); |
| 120 EXPECT_EQ(6u, move.size()); |
| 121 for (int i = 0; i < 6; i++) |
| 122 EXPECT_EQ(i + 1, move[i]); |
| 123 } |
| 124 |
| 125 TEST(CircularDeque, EqualsInitializerList) { |
| 126 circular_deque<int> q; |
| 127 EXPECT_TRUE(q.empty()); |
| 128 q = {1, 2, 3, 4, 5, 6}; |
| 129 EXPECT_EQ(6u, q.size()); |
| 130 for (int i = 0; i < 6; i++) |
| 131 EXPECT_EQ(i + 1, q[i]); |
| 132 } |
| 133 |
| 134 TEST(CircularDeque, AssignCountValue) { |
| 135 circular_deque<int> empty; |
| 136 empty.assign(0, 52); |
| 137 EXPECT_EQ(0u, empty.size()); |
| 138 |
| 139 circular_deque<int> full; |
| 140 size_t count = 13; |
| 141 int value = 12345; |
| 142 full.assign(count, value); |
| 143 EXPECT_EQ(count, full.size()); |
| 144 |
| 145 for (size_t i = 0; i < count; i++) |
| 146 EXPECT_EQ(value, full[i]); |
| 147 } |
| 148 |
| 149 TEST(CircularDeque, AssignIterator) { |
| 150 int range[8] = {11, 12, 13, 14, 15, 16, 17, 18}; |
| 151 |
| 152 circular_deque<int> empty; |
| 153 empty.assign(std::begin(range), std::begin(range)); |
| 154 EXPECT_TRUE(empty.empty()); |
| 155 |
| 156 circular_deque<int> full; |
| 157 full.assign(std::begin(range), std::end(range)); |
| 158 EXPECT_EQ(8u, full.size()); |
| 159 for (size_t i = 0; i < 8; i++) |
| 160 EXPECT_EQ(range[i], full[i]); |
| 161 } |
| 162 |
| 163 TEST(CircularDeque, AssignInitializerList) { |
| 164 circular_deque<int> empty; |
| 165 empty.assign({}); |
| 166 EXPECT_TRUE(empty.empty()); |
| 167 |
| 168 circular_deque<int> full; |
| 169 full.assign({11, 12, 13, 14, 15, 16, 17, 18}); |
| 170 EXPECT_EQ(8u, full.size()); |
| 171 for (int i = 0; i < 8; i++) |
| 172 EXPECT_EQ(11 + i, full[i]); |
| 173 } |
| 174 |
| 175 // Tests [] and .at(). |
| 176 TEST(CircularDeque, At) { |
| 177 circular_deque<int> q = MakeSequence(10); |
| 178 CycleTest(q, [](const circular_deque<int>& q, size_t cycle) { |
| 179 size_t expected_size = 10; |
| 180 EXPECT_EQ(expected_size, q.size()); |
| 181 |
| 182 // A sequence of 0's. |
| 183 size_t index = 0; |
| 184 size_t num_zeros = std::min(expected_size, cycle); |
| 185 for (size_t i = 0; i < num_zeros; i++, index++) { |
| 186 EXPECT_EQ(0, q[index]); |
| 187 EXPECT_EQ(0, q.at(index)); |
| 188 } |
| 189 |
| 190 // Followed by a sequence of increasing ints. |
| 191 size_t num_ints = expected_size - num_zeros; |
| 192 for (int i = 0; i < static_cast<int>(num_ints); i++, index++) { |
| 193 EXPECT_EQ(i, q[index]); |
| 194 EXPECT_EQ(i, q.at(index)); |
| 195 } |
| 196 }); |
| 197 } |
| 198 |
| 199 // This also tests the copy constructor with lots of different types of |
| 200 // input configurations. |
| 201 TEST(CircularDeque, FrontBackPushPop) { |
| 202 circular_deque<int> q = MakeSequence(10); |
| 203 |
| 204 int expected_front = 0; |
| 205 int expected_back = 9; |
| 206 |
| 207 // Go in one direction. |
| 208 for (int i = 0; i < 100; i++) { |
| 209 const circular_deque<int> const_q(q); |
| 210 |
| 211 EXPECT_EQ(expected_front, q.front()); |
| 212 EXPECT_EQ(expected_back, q.back()); |
| 213 EXPECT_EQ(expected_front, const_q.front()); |
| 214 EXPECT_EQ(expected_back, const_q.back()); |
| 215 |
| 216 expected_front++; |
| 217 expected_back++; |
| 218 |
| 219 q.pop_front(); |
| 220 q.push_back(expected_back); |
| 221 } |
| 222 |
| 223 // Go back in reverse. |
| 224 for (int i = 0; i < 100; i++) { |
| 225 const circular_deque<int> const_q(q); |
| 226 |
| 227 EXPECT_EQ(expected_front, q.front()); |
| 228 EXPECT_EQ(expected_back, q.back()); |
| 229 EXPECT_EQ(expected_front, const_q.front()); |
| 230 EXPECT_EQ(expected_back, const_q.back()); |
| 231 |
| 232 expected_front--; |
| 233 expected_back--; |
| 234 |
| 235 q.pop_back(); |
| 236 q.push_front(expected_front); |
| 237 } |
| 238 } |
| 239 |
| 240 TEST(CircularDeque, ReallocateWithSplitBuffer) { |
| 241 // Tests reallocating a deque with an internal buffer that looks like this: |
| 242 // 4 5 x x 0 1 2 3 |
| 243 // end-^ ^-begin |
| 244 circular_deque<int> q; |
| 245 q.reserve(7); // Internal buffer is always 1 larger than requested. |
| 246 q.push_back(-1); |
| 247 q.push_back(-1); |
| 248 q.push_back(-1); |
| 249 q.push_back(-1); |
| 250 q.push_back(0); |
| 251 q.pop_front(); |
| 252 q.pop_front(); |
| 253 q.pop_front(); |
| 254 q.pop_front(); |
| 255 q.push_back(1); |
| 256 q.push_back(2); |
| 257 q.push_back(3); |
| 258 q.push_back(4); |
| 259 q.push_back(5); |
| 260 |
| 261 q.shrink_to_fit(); |
| 262 EXPECT_EQ(6u, q.size()); |
| 263 |
| 264 EXPECT_EQ(0, q[0]); |
| 265 EXPECT_EQ(1, q[1]); |
| 266 EXPECT_EQ(2, q[2]); |
| 267 EXPECT_EQ(3, q[3]); |
| 268 EXPECT_EQ(4, q[4]); |
| 269 EXPECT_EQ(5, q[5]); |
| 270 } |
| 271 |
| 272 TEST(CircularDeque, Swap) { |
| 273 circular_deque<int> a = MakeSequence(10); |
| 274 circular_deque<int> b = MakeSequence(100); |
| 275 |
| 276 a.swap(b); |
| 277 EXPECT_EQ(100u, a.size()); |
| 278 for (int i = 0; i < 100; i++) |
| 279 EXPECT_EQ(i, a[i]); |
| 280 |
| 281 EXPECT_EQ(10u, b.size()); |
| 282 for (int i = 0; i < 10; i++) |
| 283 EXPECT_EQ(i, b[i]); |
| 284 } |
| 285 |
| 286 TEST(CircularDeque, Iteration) { |
| 287 circular_deque<int> q = MakeSequence(10); |
| 288 |
| 289 int expected_front = 0; |
| 290 int expected_back = 9; |
| 291 |
| 292 // This loop causes various combinations of begin and end to be tested. |
| 293 for (int i = 0; i < 30; i++) { |
| 294 // Range-based for loop going forward. |
| 295 int current_expected = expected_front; |
| 296 for (int cur : q) { |
| 297 EXPECT_EQ(current_expected, cur); |
| 298 current_expected++; |
| 299 } |
| 300 |
| 301 // Manually test reverse iterators. |
| 302 current_expected = expected_back; |
| 303 for (auto cur = q.crbegin(); cur < q.crend(); cur++) { |
| 304 EXPECT_EQ(current_expected, *cur); |
| 305 current_expected--; |
| 306 } |
| 307 |
| 308 expected_front++; |
| 309 expected_back++; |
| 310 |
| 311 q.pop_front(); |
| 312 q.push_back(expected_back); |
| 313 } |
| 314 |
| 315 // Go back in reverse. |
| 316 for (int i = 0; i < 100; i++) { |
| 317 const circular_deque<int> const_q(q); |
| 318 |
| 319 EXPECT_EQ(expected_front, q.front()); |
| 320 EXPECT_EQ(expected_back, q.back()); |
| 321 EXPECT_EQ(expected_front, const_q.front()); |
| 322 EXPECT_EQ(expected_back, const_q.back()); |
| 323 |
| 324 expected_front--; |
| 325 expected_back--; |
| 326 |
| 327 q.pop_back(); |
| 328 q.push_front(expected_front); |
| 329 } |
| 330 } |
| 331 |
| 332 TEST(CircularDeque, IteratorComparisons) { |
| 333 circular_deque<int> q = MakeSequence(10); |
| 334 |
| 335 // This loop causes various combinations of begin and end to be tested. |
| 336 for (int i = 0; i < 30; i++) { |
| 337 EXPECT_LT(q.begin(), q.end()); |
| 338 EXPECT_LE(q.begin(), q.end()); |
| 339 EXPECT_LE(q.begin(), q.begin()); |
| 340 |
| 341 EXPECT_GT(q.end(), q.begin()); |
| 342 EXPECT_GE(q.end(), q.begin()); |
| 343 EXPECT_GE(q.end(), q.end()); |
| 344 |
| 345 EXPECT_EQ(q.begin(), q.begin()); |
| 346 EXPECT_NE(q.begin(), q.end()); |
| 347 |
| 348 q.push_front(10); |
| 349 q.pop_back(); |
| 350 } |
| 351 } |
| 352 |
| 353 TEST(CircularDeque, IteratorIntegerOps) { |
| 354 circular_deque<int> q = MakeSequence(10); |
| 355 |
| 356 int expected_front = 0; |
| 357 int expected_back = 9; |
| 358 |
| 359 for (int i = 0; i < 30; i++) { |
| 360 EXPECT_EQ(0, q.begin() - q.begin()); |
| 361 EXPECT_EQ(0, q.end() - q.end()); |
| 362 EXPECT_EQ(q.size(), static_cast<size_t>(q.end() - q.begin())); |
| 363 |
| 364 // += |
| 365 circular_deque<int>::iterator eight = q.begin(); |
| 366 eight += 8; |
| 367 EXPECT_EQ(8, eight - q.begin()); |
| 368 EXPECT_EQ(expected_front + 8, *eight); |
| 369 |
| 370 // -= |
| 371 eight -= 8; |
| 372 EXPECT_EQ(q.begin(), eight); |
| 373 |
| 374 // + |
| 375 eight = eight + 8; |
| 376 EXPECT_EQ(8, eight - q.begin()); |
| 377 |
| 378 // - |
| 379 eight = eight - 8; |
| 380 EXPECT_EQ(q.begin(), eight); |
| 381 |
| 382 expected_front++; |
| 383 expected_back++; |
| 384 |
| 385 q.pop_front(); |
| 386 q.push_back(expected_back); |
| 387 } |
| 388 } |
| 389 |
| 390 TEST(CircularDeque, CapacityReserveShrink) { |
| 391 circular_deque<int> q; |
| 392 |
| 393 // A default constructed queue should have no capacity since it should waste |
| 394 // no space. |
| 395 EXPECT_TRUE(q.empty()); |
| 396 EXPECT_EQ(0u, q.size()); |
| 397 EXPECT_EQ(0u, q.capacity()); |
| 398 |
| 399 size_t new_capacity = 100; |
| 400 q.reserve(new_capacity); |
| 401 EXPECT_EQ(new_capacity, q.capacity()); |
| 402 |
| 403 // Adding that many items should not cause a resize. |
| 404 for (size_t i = 0; i < new_capacity; i++) |
| 405 q.push_back(i); |
| 406 EXPECT_EQ(new_capacity, q.size()); |
| 407 EXPECT_EQ(new_capacity, q.capacity()); |
| 408 |
| 409 // Shrinking doesn't resize capacity. |
| 410 size_t capacity_2 = new_capacity / 2; |
| 411 q.resize(capacity_2); |
| 412 EXPECT_EQ(capacity_2, q.size()); |
| 413 EXPECT_EQ(new_capacity, q.capacity()); |
| 414 |
| 415 // Shrink to fit to that size. |
| 416 q.shrink_to_fit(); |
| 417 EXPECT_EQ(capacity_2, q.size()); |
| 418 EXPECT_EQ(capacity_2, q.capacity()); |
| 419 |
| 420 // Shrink to 0, should have the same capacity. |
| 421 q.resize(0); |
| 422 EXPECT_EQ(0u, q.size()); |
| 423 EXPECT_EQ(capacity_2, q.capacity()); |
| 424 |
| 425 // Shrinking to fit should give 0 capacity. |
| 426 q.shrink_to_fit(); |
| 427 EXPECT_EQ(0u, q.size()); |
| 428 EXPECT_EQ(0u, q.capacity()); |
| 429 } |
| 430 |
| 431 TEST(CircularDeque, ClearAndEmpty) { |
| 432 circular_deque<int> q; |
| 433 EXPECT_TRUE(q.empty()); |
| 434 |
| 435 q.resize(10); |
| 436 EXPECT_EQ(10u, q.size()); |
| 437 EXPECT_FALSE(q.empty()); |
| 438 |
| 439 q.clear(); |
| 440 EXPECT_EQ(0u, q.size()); |
| 441 EXPECT_TRUE(q.empty()); |
| 442 } |
| 443 |
| 444 TEST(CircularDeque, Resize) { |
| 445 circular_deque<int> q; |
| 446 |
| 447 // Resize with default constructor. |
| 448 size_t first_size = 10; |
| 449 q.resize(first_size); |
| 450 EXPECT_EQ(first_size, q.size()); |
| 451 for (size_t i = 0; i < first_size; i++) |
| 452 EXPECT_EQ(0, q[i]); |
| 453 |
| 454 // Resize with different value. |
| 455 size_t second_expand = 10; |
| 456 q.resize(first_size + second_expand, 3); |
| 457 EXPECT_EQ(first_size + second_expand, q.size()); |
| 458 for (size_t i = 0; i < first_size; i++) |
| 459 EXPECT_EQ(0, q[i]); |
| 460 for (size_t i = 0; i < second_expand; i++) |
| 461 EXPECT_EQ(3, q[i + first_size]); |
| 462 |
| 463 // Erase from the end and add to the beginning so resize is forced to cross |
| 464 // a circular buffer wrap boundary. |
| 465 q.shrink_to_fit(); |
| 466 for (int i = 0; i < 5; i++) { |
| 467 q.pop_back(); |
| 468 q.push_front(6); |
| 469 } |
| 470 q.resize(10); |
| 471 |
| 472 EXPECT_EQ(6, q[0]); |
| 473 EXPECT_EQ(6, q[1]); |
| 474 EXPECT_EQ(6, q[2]); |
| 475 EXPECT_EQ(6, q[3]); |
| 476 EXPECT_EQ(6, q[4]); |
| 477 EXPECT_EQ(0, q[5]); |
| 478 EXPECT_EQ(0, q[6]); |
| 479 EXPECT_EQ(0, q[7]); |
| 480 EXPECT_EQ(0, q[8]); |
| 481 EXPECT_EQ(0, q[9]); |
| 482 } |
| 483 |
| 484 /* |
| 485 This test should assert in a debug build. It tries to dereference an iterator |
| 486 after mutating the container. Uncomment to double-check that this works. |
| 487 TEST(CircularDeque, UseIteratorAfterMutate) { |
| 488 circular_deque<int> q; |
| 489 q.push_back(0); |
| 490 |
| 491 auto old_begin = q.begin(); |
| 492 EXPECT_EQ(0, *old_begin); |
| 493 |
| 494 q.push_back(1); |
| 495 EXPECT_EQ(0, *old_begin); // Should DCHECK. |
| 496 } |
| 497 */ |
| 498 |
| 499 } // namespace base |
OLD | NEW |