1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_containers/inline_deque.h"
16
17 #include <algorithm>
18 #include <array>
19 #include <cstddef>
20
21 #include "pw_compilation_testing/negative_compilation.h"
22 #include "pw_containers/algorithm.h"
23 #include "pw_containers_private/test_helpers.h"
24 #include "pw_unit_test/framework.h"
25
26 namespace pw::containers {
27 namespace {
28
29 using namespace std::literals::string_view_literals;
30 using test::CopyOnly;
31 using test::Counter;
32 using test::MoveOnly;
33
TEST(InlineDeque,Construct_Sized)34 TEST(InlineDeque, Construct_Sized) {
35 InlineDeque<int, 3> deque;
36 EXPECT_TRUE(deque.empty());
37 EXPECT_EQ(deque.size(), 0u);
38 EXPECT_EQ(deque.max_size(), 3u);
39 }
40
TEST(InlineDeque,Construct_GenericSized)41 TEST(InlineDeque, Construct_GenericSized) {
42 InlineDeque<int, 3> sized_deque;
43 InlineDeque<int>& deque(sized_deque);
44 EXPECT_TRUE(deque.empty());
45 EXPECT_EQ(deque.size(), 0u);
46 EXPECT_EQ(deque.max_size(), 3u);
47 }
48
TEST(InlineDeque,Construct_ConstexprSized)49 TEST(InlineDeque, Construct_ConstexprSized) {
50 constexpr InlineDeque<int, 3> deque(pw::kConstexpr);
51 EXPECT_TRUE(deque.empty());
52 EXPECT_EQ(deque.size(), 0u);
53 EXPECT_EQ(deque.max_size(), 3u);
54 }
55
TEST(InlineDeque,Construct_CopySameCapacity)56 TEST(InlineDeque, Construct_CopySameCapacity) {
57 InlineDeque<CopyOnly, 4> deque(4, CopyOnly(123));
58 const auto& deque_ref = deque;
59 InlineDeque<CopyOnly, 4> copied(deque_ref);
60
61 ASSERT_EQ(4u, deque.size());
62 EXPECT_EQ(123, deque[3].value);
63
64 ASSERT_EQ(4u, copied.size());
65 EXPECT_EQ(123, copied[3].value);
66 }
67
TEST(InlineDeque,Construct_MoveSameCapacity)68 TEST(InlineDeque, Construct_MoveSameCapacity) {
69 InlineDeque<MoveOnly, 4> deque;
70 deque.emplace_back(MoveOnly(1));
71 deque.emplace_back(MoveOnly(2));
72 deque.emplace_back(MoveOnly(3));
73 deque.emplace_back(MoveOnly(4));
74 InlineDeque<MoveOnly, 4> moved(std::move(deque));
75
76 // NOLINTNEXTLINE(bugprone-use-after-move)
77 EXPECT_EQ(0u, deque.size());
78
79 ASSERT_EQ(4u, moved.size());
80 EXPECT_EQ(4, moved[3].value);
81 }
82
TEST(InlineDeque,Construct_CopyLargerCapacity)83 TEST(InlineDeque, Construct_CopyLargerCapacity) {
84 InlineDeque<CopyOnly, 4> deque(4, CopyOnly(123));
85 InlineDeque<CopyOnly, 5> copied(deque);
86
87 ASSERT_EQ(4u, deque.size());
88 EXPECT_EQ(123, deque[3].value);
89
90 ASSERT_EQ(4u, copied.size());
91 EXPECT_EQ(123, copied[3].value);
92 }
93
TEST(InlineDeque,Construct_MoveLargerCapacity)94 TEST(InlineDeque, Construct_MoveLargerCapacity) {
95 InlineDeque<MoveOnly, 4> deque;
96 deque.emplace_back(MoveOnly(1));
97 deque.emplace_back(MoveOnly(2));
98 deque.emplace_back(MoveOnly(3));
99 deque.emplace_back(MoveOnly(4));
100 InlineDeque<MoveOnly, 5> moved(std::move(deque));
101
102 // NOLINTNEXTLINE(bugprone-use-after-move)
103 EXPECT_EQ(0u, deque.size());
104
105 ASSERT_EQ(4u, moved.size());
106 EXPECT_EQ(4, moved[3].value);
107 }
108
TEST(InlineDeque,Construct_CopySmallerCapacity)109 TEST(InlineDeque, Construct_CopySmallerCapacity) {
110 InlineDeque<CopyOnly, 4> deque(3, CopyOnly(123));
111 InlineDeque<CopyOnly, 3> copied(deque);
112
113 ASSERT_EQ(3u, deque.size());
114 EXPECT_EQ(123, deque[2].value);
115
116 ASSERT_EQ(3u, copied.size());
117 EXPECT_EQ(123, copied[2].value);
118 }
119
TEST(InlineDeque,Destruct_ZeroLength)120 TEST(InlineDeque, Destruct_ZeroLength) {
121 Counter::Reset();
122 {
123 InlineDeque<Counter, 0> deque;
124 EXPECT_EQ(deque.size(), 0u);
125 }
126 EXPECT_EQ(Counter::created, 0);
127 EXPECT_EQ(Counter::destroyed, 0);
128 }
129
TEST(InlineDeque,Destruct_Empty)130 TEST(InlineDeque, Destruct_Empty) {
131 Counter::Reset();
132
133 {
134 InlineDeque<Counter, 3> deque;
135 EXPECT_EQ(deque.size(), 0u);
136 }
137 EXPECT_EQ(Counter::created, 0);
138 EXPECT_EQ(Counter::destroyed, 0);
139 }
140
TEST(InlineDeque,Destruct_MultipleEntries)141 TEST(InlineDeque, Destruct_MultipleEntries) {
142 Counter value;
143 Counter::Reset();
144
145 {
146 InlineDeque<Counter, 128> deque(100, value);
147 }
148
149 EXPECT_EQ(Counter::created, 100);
150 EXPECT_EQ(Counter::destroyed, 100);
151 }
152
TEST(InlineDeque,Assign_InitializerList)153 TEST(InlineDeque, Assign_InitializerList) {
154 InlineDeque<int, 4> deque = {1, 3, 5, 7};
155
156 ASSERT_EQ(4u, deque.size());
157
158 EXPECT_EQ(1, deque[0]);
159 EXPECT_EQ(3, deque[1]);
160 EXPECT_EQ(5, deque[2]);
161 EXPECT_EQ(7, deque[3]);
162 }
163
TEST(InlineDeque,Assign_CopySameCapacity)164 TEST(InlineDeque, Assign_CopySameCapacity) {
165 InlineDeque<CopyOnly, 4> deque(4, CopyOnly(123));
166 InlineDeque<CopyOnly, 4> copied = deque;
167
168 ASSERT_EQ(4u, deque.size());
169 EXPECT_EQ(123, deque[3].value);
170
171 ASSERT_EQ(4u, copied.size());
172 EXPECT_EQ(123, copied[3].value);
173 }
174
TEST(InlineDeque,Assign_CopyLargerCapacity)175 TEST(InlineDeque, Assign_CopyLargerCapacity) {
176 InlineDeque<CopyOnly, 4> deque(4, CopyOnly(123));
177 InlineDeque<CopyOnly, 5> copied = deque;
178
179 ASSERT_EQ(4u, deque.size());
180 EXPECT_EQ(123, deque[3].value);
181
182 ASSERT_EQ(4u, copied.size());
183 EXPECT_EQ(123, copied[3].value);
184 }
185
TEST(InlineDeque,Assign_CopySmallerCapacity)186 TEST(InlineDeque, Assign_CopySmallerCapacity) {
187 InlineDeque<CopyOnly, 4> deque(3, CopyOnly(123));
188 InlineDeque<CopyOnly, 3> copied = deque;
189
190 ASSERT_EQ(3u, deque.size());
191 EXPECT_EQ(123, deque[2].value);
192
193 ASSERT_EQ(3u, copied.size());
194 EXPECT_EQ(123, copied[2].value);
195 }
196
TEST(InlineDeque,Assign_MoveSameCapacity)197 TEST(InlineDeque, Assign_MoveSameCapacity) {
198 InlineDeque<MoveOnly, 4> deque;
199 deque.emplace_back(MoveOnly(1));
200 deque.emplace_back(MoveOnly(2));
201 deque.emplace_back(MoveOnly(3));
202 deque.emplace_back(MoveOnly(4));
203 InlineDeque<MoveOnly, 4> moved = std::move(deque);
204
205 // NOLINTNEXTLINE(bugprone-use-after-move)
206 EXPECT_EQ(0u, deque.size());
207
208 ASSERT_EQ(4u, moved.size());
209 EXPECT_EQ(4, moved[3].value);
210 }
211
TEST(InlineDeque,Assign_MoveLargerCapacity)212 TEST(InlineDeque, Assign_MoveLargerCapacity) {
213 InlineDeque<MoveOnly, 4> deque;
214 deque.emplace_back(MoveOnly(1));
215 deque.emplace_back(MoveOnly(2));
216 deque.emplace_back(MoveOnly(3));
217 deque.emplace_back(MoveOnly(4));
218 InlineDeque<MoveOnly, 5> moved = std::move(deque);
219
220 // NOLINTNEXTLINE(bugprone-use-after-move)
221 EXPECT_EQ(0u, deque.size());
222
223 ASSERT_EQ(4u, moved.size());
224 EXPECT_EQ(4, moved[3].value);
225 }
226
TEST(InlineDeque,Assign_MoveSmallerCapacity)227 TEST(InlineDeque, Assign_MoveSmallerCapacity) {
228 InlineDeque<MoveOnly, 4> deque;
229 deque.emplace_back(MoveOnly(1));
230 deque.emplace_back(MoveOnly(2));
231 deque.emplace_back(MoveOnly(3));
232 InlineDeque<MoveOnly, 3> moved = std::move(deque);
233
234 // NOLINTNEXTLINE(bugprone-use-after-move)
235 EXPECT_EQ(0u, deque.size());
236
237 ASSERT_EQ(3u, moved.size());
238 EXPECT_EQ(3, moved[2].value);
239 }
240
TEST(InlineDeque,Access_Iterator)241 TEST(InlineDeque, Access_Iterator) {
242 InlineDeque<Counter, 2> deque(2);
243 for (Counter& item : deque) {
244 EXPECT_EQ(item.value, 0);
245 }
246 for (const Counter& item : deque) {
247 EXPECT_EQ(item.value, 0);
248 }
249 }
250
TEST(InlineDeque,Access_ConstIterator)251 TEST(InlineDeque, Access_ConstIterator) {
252 const InlineDeque<Counter, 2> deque(2);
253 for (const Counter& item : deque) {
254 EXPECT_EQ(item.value, 0);
255 }
256 }
257
TEST(InlineDeque,Access_ZeroLength)258 TEST(InlineDeque, Access_ZeroLength) {
259 InlineDeque<Counter, 0> deque;
260
261 EXPECT_EQ(0u, deque.size());
262 EXPECT_EQ(0u, deque.max_size());
263 EXPECT_TRUE(deque.empty());
264 EXPECT_TRUE(deque.full());
265
266 for (Counter& item : deque) {
267 (void)item;
268 FAIL();
269 }
270 }
271
TEST(InlineDeque,Access_ContiguousData)272 TEST(InlineDeque, Access_ContiguousData) {
273 // Content = {}, Storage = [x, x]
274 InlineDeque<int, 2> deque;
275
276 {
277 auto [first, second] = deque.contiguous_data();
278 EXPECT_EQ(first.size(), 0u);
279 EXPECT_EQ(second.size(), 0u);
280 }
281
282 // Content = {1}, Storage = [1, x]
283 deque.push_back(1);
284 {
285 auto [first, second] = deque.contiguous_data();
286 EXPECT_TRUE(Equal(first, std::array<int, 1>{1}));
287 EXPECT_TRUE(Equal(second, std::array<int, 0>{}));
288 }
289
290 // Content = {1, 2}, Storage = [1, 2]
291 deque.push_back(2);
292 EXPECT_TRUE(deque.full());
293 {
294 auto [first, second] = deque.contiguous_data();
295 EXPECT_TRUE(Equal(first, std::array<int, 2>{1, 2}));
296 EXPECT_TRUE(Equal(second, std::array<int, 0>{}));
297 }
298
299 // Content = {2}, Storage = [x, 2]
300 deque.pop_front();
301 {
302 auto [first, second] = deque.contiguous_data();
303 EXPECT_TRUE(Equal(first, std::array<int, 1>{2}));
304 EXPECT_TRUE(Equal(second, std::array<int, 0>{}));
305 }
306
307 // Content = {2, 1}, Storage = [1, 2]
308 deque.push_back(1);
309 {
310 auto [first, second] = deque.contiguous_data();
311 EXPECT_TRUE(Equal(first, std::array<int, 1>{2}));
312 EXPECT_TRUE(Equal(second, std::array<int, 1>{1}));
313 }
314
315 // Content = {1}, Storage = [1, x]
316 deque.pop_front();
317 {
318 auto [first, second] = deque.contiguous_data();
319 EXPECT_TRUE(Equal(first, std::array<int, 1>{1}));
320 EXPECT_TRUE(Equal(second, std::array<int, 0>{}));
321 }
322
323 // Content = {1, 2}, Storage = [1, 2]
324 deque.push_back(2);
325 {
326 auto [first, second] = deque.contiguous_data();
327 EXPECT_TRUE(Equal(first, std::array<int, 2>{1, 2}));
328 EXPECT_TRUE(Equal(second, std::array<int, 0>{}));
329 }
330 }
331
TEST(InlineDeque,Access_ConstContiguousData)332 TEST(InlineDeque, Access_ConstContiguousData) {
333 // Content = {1, 2}, Storage = [1, 2]
334 const InlineDeque<int, 2> deque = {1, 2};
335
336 {
337 auto [first, second] = deque.contiguous_data();
338 EXPECT_EQ(first.size(), 2u);
339 EXPECT_EQ(second.size(), 0u);
340 }
341 }
342
TEST(InlineDeque,Modify_Clear)343 TEST(InlineDeque, Modify_Clear) {
344 Counter::Reset();
345
346 InlineDeque<Counter, 100> deque;
347 deque.emplace_back();
348 deque.emplace_back();
349 deque.emplace_back();
350
351 deque.clear();
352
353 EXPECT_EQ(3, Counter::created);
354 EXPECT_EQ(3, Counter::destroyed);
355 }
356
TEST(InlineDeque,Modify_PushBack_Copy)357 TEST(InlineDeque, Modify_PushBack_Copy) {
358 Counter value(99);
359 Counter::Reset();
360
361 {
362 InlineDeque<Counter, 10> deque;
363 deque.push_back(value);
364
365 ASSERT_EQ(deque.size(), 1u);
366 EXPECT_EQ(deque.front().value, 99);
367 }
368
369 EXPECT_EQ(Counter::created, 1);
370 EXPECT_EQ(Counter::destroyed, 1);
371 }
372
TEST(InlineDeque,Modify_PushBack_Move)373 TEST(InlineDeque, Modify_PushBack_Move) {
374 Counter::Reset();
375
376 {
377 Counter value(99);
378 InlineDeque<Counter, 10> deque;
379 deque.push_back(std::move(value));
380
381 EXPECT_EQ(deque.size(), 1u);
382 EXPECT_EQ(deque.front().value, 99);
383 // NOLINTNEXTLINE(bugprone-use-after-move)
384 EXPECT_EQ(value.value, 0);
385 }
386
387 EXPECT_EQ(Counter::created, 1);
388 EXPECT_EQ(Counter::destroyed, 2);
389 EXPECT_EQ(Counter::moved, 1);
390 }
391
TEST(InlineDeque,Modify_EmplaceBack)392 TEST(InlineDeque, Modify_EmplaceBack) {
393 Counter::Reset();
394
395 {
396 InlineDeque<Counter, 10> deque;
397 deque.emplace_back(314);
398
399 ASSERT_EQ(deque.size(), 1u);
400 EXPECT_EQ(deque.front().value, 314);
401 }
402
403 EXPECT_EQ(Counter::created, 1);
404 EXPECT_EQ(Counter::destroyed, 1);
405 }
406
TEST(InlineDeque,Modify_WrapForwards)407 TEST(InlineDeque, Modify_WrapForwards) {
408 Counter::Reset();
409
410 {
411 InlineDeque<Counter, 3> deque;
412 deque.emplace_back(1);
413 deque.emplace_back(2);
414 deque.emplace_back(3);
415
416 ASSERT_EQ(deque.size(), 3u);
417 EXPECT_EQ(deque[0].value, 1);
418 EXPECT_EQ(deque.front().value, 1);
419 EXPECT_EQ(deque[1].value, 2);
420 EXPECT_EQ(deque[2].value, 3);
421 EXPECT_EQ(deque.back().value, 3);
422
423 deque.pop_front();
424 deque.emplace_back(4);
425
426 ASSERT_EQ(deque.size(), 3u);
427 EXPECT_EQ(deque[0].value, 2);
428 EXPECT_EQ(deque.front().value, 2);
429 EXPECT_EQ(deque[1].value, 3);
430 EXPECT_EQ(deque[2].value, 4);
431 EXPECT_EQ(deque.back().value, 4);
432 }
433
434 EXPECT_EQ(Counter::created, 4);
435 EXPECT_EQ(Counter::destroyed, 4);
436 }
437
TEST(InlineDeque,Modify_WrapBackwards)438 TEST(InlineDeque, Modify_WrapBackwards) {
439 Counter::Reset();
440
441 {
442 InlineDeque<Counter, 3> deque;
443 deque.emplace_front(1);
444 deque.emplace_front(2);
445 deque.emplace_front(3);
446
447 ASSERT_EQ(deque.size(), 3u);
448 EXPECT_EQ(deque[0].value, 3);
449 EXPECT_EQ(deque.front().value, 3);
450 EXPECT_EQ(deque[1].value, 2);
451 EXPECT_EQ(deque[2].value, 1);
452 EXPECT_EQ(deque.back().value, 1);
453
454 deque.pop_back();
455 deque.emplace_front(4);
456
457 ASSERT_EQ(deque.size(), 3u);
458 EXPECT_EQ(deque[0].value, 4);
459 EXPECT_EQ(deque.front().value, 4);
460 EXPECT_EQ(deque[1].value, 3);
461 EXPECT_EQ(deque[2].value, 2);
462 EXPECT_EQ(deque.back().value, 2);
463 }
464
465 EXPECT_EQ(Counter::created, 4);
466 EXPECT_EQ(Counter::destroyed, 4);
467 }
468
TEST(InlineDeque,Modify_PushFront_Copy)469 TEST(InlineDeque, Modify_PushFront_Copy) {
470 Counter value(99);
471 Counter::Reset();
472
473 {
474 InlineDeque<Counter, 10> deque;
475 deque.push_front(value);
476
477 EXPECT_EQ(deque.size(), 1u);
478 EXPECT_EQ(deque.front().value, 99);
479 }
480
481 EXPECT_EQ(Counter::created, 1);
482 EXPECT_EQ(Counter::destroyed, 1);
483 }
484
TEST(InlineDeque,Modify_PushFront_Move)485 TEST(InlineDeque, Modify_PushFront_Move) {
486 Counter::Reset();
487
488 {
489 Counter value(99);
490 InlineDeque<Counter, 10> deque;
491 deque.push_front(std::move(value));
492
493 EXPECT_EQ(deque.size(), 1u);
494 EXPECT_EQ(deque.front().value, 99);
495 // NOLINTNEXTLINE(bugprone-use-after-move)
496 EXPECT_EQ(value.value, 0);
497 }
498
499 EXPECT_EQ(Counter::created, 1);
500 EXPECT_EQ(Counter::destroyed, 2);
501 EXPECT_EQ(Counter::moved, 1);
502 }
503
TEST(InlineDeque,Modify_EmplaceFront)504 TEST(InlineDeque, Modify_EmplaceFront) {
505 Counter::Reset();
506
507 {
508 InlineDeque<Counter, 10> deque;
509 deque.emplace_front(314);
510
511 EXPECT_EQ(deque.size(), 1u);
512 EXPECT_EQ(deque.front().value, 314);
513 }
514
515 EXPECT_EQ(Counter::created, 1);
516 EXPECT_EQ(Counter::destroyed, 1);
517 }
518
TEST(InlineDeque,Modify_PopBack)519 TEST(InlineDeque, Modify_PopBack) {
520 Counter::Reset();
521
522 InlineDeque<Counter, 3> deque;
523 deque.emplace_front(1); // This wraps to the other end.
524 deque.emplace_back(2); // This is the first entry in storage.
525 deque.emplace_back(3);
526 // Content = {1, 2, 3}, Storage = [2, 3, 1]
527
528 ASSERT_EQ(deque.size(), 3u);
529 EXPECT_EQ(deque[0].value, 1);
530 EXPECT_EQ(deque[1].value, 2);
531 EXPECT_EQ(deque[2].value, 3);
532
533 deque.pop_back();
534 // Content = {1, 2}, Storage = [2, x, 1]
535 ASSERT_EQ(deque.size(), 2u);
536 EXPECT_EQ(deque[0].value, 1);
537 EXPECT_EQ(deque[1].value, 2);
538
539 // This wraps around.
540 deque.pop_back();
541 // Content = {1}, Storage = [x, x, 1]
542
543 ASSERT_EQ(deque.size(), 1u);
544 EXPECT_EQ(deque[0].value, 1);
545
546 EXPECT_EQ(Counter::created, 3);
547 EXPECT_EQ(Counter::destroyed, 2);
548 }
549
TEST(InlineDeque,Modify_PopFront)550 TEST(InlineDeque, Modify_PopFront) {
551 Counter::Reset();
552
553 InlineDeque<Counter, 3> deque;
554 deque.emplace_front(1); // This wraps to the other end.
555 deque.emplace_back(2); // This is the first entry in storage.
556 deque.emplace_back(3);
557 // Content = {1, 2, 3}, Storage = [2, 3, 1]
558
559 ASSERT_EQ(deque.size(), 3u);
560 EXPECT_EQ(deque[0].value, 1);
561 EXPECT_EQ(deque[1].value, 2);
562 EXPECT_EQ(deque[2].value, 3);
563
564 // This wraps around
565 deque.pop_front();
566 // Content = {2, 3}, Storage = [2, 3, x]
567
568 EXPECT_EQ(deque.size(), 2u);
569 EXPECT_EQ(deque[0].value, 2);
570 EXPECT_EQ(deque[1].value, 3);
571
572 deque.pop_front();
573 // Content = {3}, Storage = [x, 3, x]
574 ASSERT_EQ(deque.size(), 1u);
575 EXPECT_EQ(deque[0].value, 3);
576
577 EXPECT_EQ(Counter::created, 3);
578 EXPECT_EQ(Counter::destroyed, 2);
579 }
580
TEST(InlineDeque,Modify_Resize_Larger)581 TEST(InlineDeque, Modify_Resize_Larger) {
582 InlineDeque<CopyOnly, 10> deque(1, CopyOnly(123));
583 deque.resize(3, CopyOnly(123));
584
585 EXPECT_EQ(deque.size(), 3u);
586 for (auto& i : deque) {
587 EXPECT_EQ(i.value, 123);
588 }
589 }
590
TEST(InlineDeque,Modify_Resize_LargerThanMax)591 TEST(InlineDeque, Modify_Resize_LargerThanMax) {
592 InlineDeque<CopyOnly, 10> deque;
593 deque.resize(1000, CopyOnly(123));
594
595 EXPECT_EQ(deque.size(), 10u);
596 for (auto& i : deque) {
597 EXPECT_EQ(i.value, 123);
598 }
599 }
600
TEST(InlineDeque,Modify_Resize_Smaller)601 TEST(InlineDeque, Modify_Resize_Smaller) {
602 InlineDeque<CopyOnly, 10> deque(9, CopyOnly(123));
603 deque.resize(3, CopyOnly(123));
604
605 EXPECT_EQ(deque.size(), 3u);
606 for (auto& i : deque) {
607 EXPECT_EQ(i.value, 123);
608 }
609 }
610
TEST(InlineDeque,Modify_Resize_Zero)611 TEST(InlineDeque, Modify_Resize_Zero) {
612 InlineDeque<CopyOnly, 10> deque(10, CopyOnly(123));
613 deque.resize(0, CopyOnly(123));
614
615 EXPECT_EQ(deque.size(), 0u);
616 }
617
TEST(InlineDeque,Generic)618 TEST(InlineDeque, Generic) {
619 InlineDeque<int, 10> deque;
620 InlineDeque<int>& generic_deque(deque);
621 generic_deque = {1, 2, 3, 4, 5};
622
623 EXPECT_EQ(generic_deque.size(), deque.size());
624 EXPECT_EQ(generic_deque.max_size(), deque.max_size());
625
626 unsigned short i = 0;
627 for (int value : deque) {
628 EXPECT_EQ(value, generic_deque[i]);
629 i += 1;
630 }
631
632 i = 0;
633 for (int value : generic_deque) {
634 EXPECT_EQ(deque[i], value);
635 i += 1;
636 }
637 }
638
TEST(InlineDeque,ConstexprMaxSize)639 TEST(InlineDeque, ConstexprMaxSize) {
640 InlineDeque<int, 10> deque;
641 constexpr size_t kMaxSize = deque.max_size();
642 EXPECT_EQ(deque.max_size(), kMaxSize);
643
644 // Ensure the generic sized container does not have a constexpr max_size().
645 [[maybe_unused]] InlineDeque<int>& generic_deque(deque);
646 #if PW_NC_TEST(InlineDeque_GenericMaxSize_NotConstexpr)
647 PW_NC_EXPECT_CLANG(
648 "kGenericMaxSize.* must be initialized by a constant expression");
649 PW_NC_EXPECT_GCC("call to non-'constexpr' function .*InlineDeque.*max_size");
650 [[maybe_unused]] constexpr size_t kGenericMaxSize = generic_deque.max_size();
651 #endif // PW_NC_TEST
652 }
653
TEST(InlineDeque,StdMaxElement)654 TEST(InlineDeque, StdMaxElement) {
655 // Content = {1, 2, 3, 4}, Storage = [1, 2, 3, 4]
656 InlineDeque<int, 4> deque = {1, 2, 3, 4};
657
658 auto max_element_it = std::max_element(deque.begin(), deque.end());
659 ASSERT_NE(max_element_it, deque.end());
660 EXPECT_EQ(*max_element_it, 4);
661
662 // Content = {2, 3, 4}, Storage = [x, 2, 3, 4]
663 deque.pop_front();
664
665 max_element_it = std::max_element(deque.begin(), deque.end());
666 ASSERT_NE(max_element_it, deque.end());
667 EXPECT_EQ(*max_element_it, 4);
668
669 // Content = {2, 3, 4, 5}, Storage = [5, 2, 3, 4]
670 deque.push_back(5);
671 max_element_it = std::max_element(deque.begin(), deque.end());
672 ASSERT_NE(max_element_it, deque.end());
673 EXPECT_EQ(*max_element_it, 5);
674
675 // Content = {}, Storage = [x, x, x, x]
676 deque.clear();
677
678 max_element_it = std::max_element(deque.begin(), deque.end());
679 ASSERT_EQ(max_element_it, deque.end());
680 }
681
TEST(InlineDeque,StdMaxElementConst)682 TEST(InlineDeque, StdMaxElementConst) {
683 // Content = {1, 2, 3, 4}, Storage = [1, 2, 3, 4]
684 InlineDeque<int, 4> deque = {1, 2, 3, 4};
685
686 auto max_element_it = std::max_element(deque.cbegin(), deque.cend());
687 ASSERT_NE(max_element_it, deque.cend());
688 EXPECT_EQ(*max_element_it, 4);
689
690 // Content = {2, 3, 4}, Storage = [x, 2, 3, 4]
691 deque.pop_front();
692
693 max_element_it = std::max_element(deque.cbegin(), deque.cend());
694 ASSERT_NE(max_element_it, deque.cend());
695 EXPECT_EQ(*max_element_it, 4);
696
697 // Content = {2, 3, 4, 5}, Storage = [5, 2, 3, 4]
698 deque.push_back(5);
699 max_element_it = std::max_element(deque.cbegin(), deque.cend());
700 ASSERT_NE(max_element_it, deque.cend());
701 EXPECT_EQ(*max_element_it, 5);
702
703 // Content = {}, Storage = [x, x, x, x]
704 deque.clear();
705
706 max_element_it = std::max_element(deque.cbegin(), deque.cend());
707 ASSERT_EQ(max_element_it, deque.cend());
708 }
709
TEST(InlineDeque,OperatorPlus)710 TEST(InlineDeque, OperatorPlus) {
711 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
712 InlineDeque<int, 4> deque = {0, 0, 1, 2};
713 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
714 deque.pop_front();
715 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
716 deque.push_back(3);
717 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
718 deque.pop_front();
719 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
720 deque.push_back(4);
721
722 for (int i = 0; i < 4; i++) {
723 ASSERT_EQ(*(deque.begin() + i), static_cast<int>(i + 1));
724 ASSERT_EQ(*(i + deque.begin()), static_cast<int>(i + 1));
725 }
726
727 ASSERT_EQ(deque.begin() + deque.size(), deque.end());
728 }
729
TEST(InlineDeque,OperatorPlusPlus)730 TEST(InlineDeque, OperatorPlusPlus) {
731 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
732 InlineDeque<int, 4> deque = {0, 0, 1, 2};
733 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
734 deque.pop_front();
735 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
736 deque.push_back(3);
737 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
738 deque.pop_front();
739 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
740 deque.push_back(4);
741
742 auto it = deque.begin();
743
744 ASSERT_EQ(*it, 1);
745 it++;
746 ASSERT_EQ(*it, 2);
747 it++;
748 ASSERT_EQ(*it, 3);
749 it++;
750 ASSERT_EQ(*it, 4);
751 it++;
752
753 ASSERT_EQ(it, deque.end());
754 }
755
TEST(InlineDeque,OperatorPlusEquals)756 TEST(InlineDeque, OperatorPlusEquals) {
757 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
758 InlineDeque<int, 4> deque = {0, 0, 1, 2};
759 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
760 deque.pop_front();
761 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
762 deque.push_back(3);
763 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
764 deque.pop_front();
765 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
766 deque.push_back(4);
767
768 auto it = deque.begin();
769
770 ASSERT_EQ(*it, 1);
771 it += 1;
772 ASSERT_EQ(*it, 2);
773 it += 1;
774 ASSERT_EQ(*it, 3);
775 it += 1;
776 ASSERT_EQ(*it, 4);
777 it += 1;
778 ASSERT_EQ(it, deque.end());
779
780 it = deque.begin();
781 ASSERT_EQ(*it, 1);
782 it += 2;
783 ASSERT_EQ(*it, 3);
784 it += 2;
785 ASSERT_EQ(it, deque.end());
786
787 it = deque.begin();
788 it += deque.size();
789
790 ASSERT_EQ(it, deque.end());
791 }
792
TEST(InlineDeque,OpeartorMinus)793 TEST(InlineDeque, OpeartorMinus) {
794 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
795 InlineDeque<int, 4> deque = {0, 0, 1, 2};
796 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
797 deque.pop_front();
798 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
799 deque.push_back(3);
800 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
801 deque.pop_front();
802 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
803 deque.push_back(4);
804
805 for (int i = 1; i <= 4; i++) {
806 ASSERT_EQ(*(deque.end() - i), static_cast<int>(5 - i));
807 }
808
809 ASSERT_EQ(deque.end() - deque.size(), deque.begin());
810 }
TEST(InlineDeque,OperatorMinusMinus)811 TEST(InlineDeque, OperatorMinusMinus) {
812 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
813 InlineDeque<int, 4> deque = {0, 0, 1, 2};
814 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
815 deque.pop_front();
816 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
817 deque.push_back(3);
818 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
819 deque.pop_front();
820 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
821 deque.push_back(4);
822
823 auto it = deque.end();
824
825 it--;
826 ASSERT_EQ(*it, 4);
827 it--;
828 ASSERT_EQ(*it, 3);
829 it--;
830 ASSERT_EQ(*it, 2);
831 it--;
832 ASSERT_EQ(*it, 1);
833
834 ASSERT_EQ(it, deque.begin());
835 }
836
TEST(InlineDeque,OperatorMinusEquals)837 TEST(InlineDeque, OperatorMinusEquals) {
838 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
839 InlineDeque<int, 4> deque = {0, 0, 1, 2};
840 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
841 deque.pop_front();
842 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
843 deque.push_back(3);
844 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
845 deque.pop_front();
846 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
847 deque.push_back(4);
848
849 auto it = deque.end();
850
851 it -= 1;
852 ASSERT_EQ(*it, 4);
853 it -= 1;
854 ASSERT_EQ(*it, 3);
855 it -= 1;
856 ASSERT_EQ(*it, 2);
857 it -= 1;
858 ASSERT_EQ(*it, 1);
859
860 ASSERT_EQ(it, deque.begin());
861
862 it = deque.end();
863
864 it -= 2;
865 ASSERT_EQ(*it, 3);
866 it -= 2;
867 ASSERT_EQ(*it, 1);
868
869 ASSERT_EQ(it, deque.begin());
870
871 it = deque.end();
872 it -= deque.size();
873
874 ASSERT_EQ(it, deque.begin());
875 }
876
TEST(InlineDeque,OperatorSquareBracket)877 TEST(InlineDeque, OperatorSquareBracket) {
878 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
879 InlineDeque<int, 4> deque = {0, 0, 1, 2};
880 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
881 deque.pop_front();
882 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
883 deque.push_back(3);
884 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
885 deque.pop_front();
886 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
887 deque.push_back(4);
888
889 for (unsigned short i = 0; i < deque.size(); i++) {
890 ASSERT_EQ(deque.begin()[i], static_cast<int>(i + 1));
891 }
892 }
893
TEST(InlineDeque,OperatorLessThan)894 TEST(InlineDeque, OperatorLessThan) {
895 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
896 InlineDeque<int, 4> deque = {0, 0, 1, 2};
897 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
898 deque.pop_front();
899 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
900 deque.push_back(3);
901 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
902 deque.pop_front();
903 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
904 deque.push_back(4);
905
906 for (int i = 0; i < deque.size(); i++) {
907 for (int j = 0; j < i; j++) {
908 ASSERT_TRUE((deque.begin() + j) < (deque.begin() + i));
909 }
910
911 ASSERT_TRUE((deque.begin() + i) < deque.end());
912 }
913 }
914
TEST(InlineDeque,OperatorLessThanEqual)915 TEST(InlineDeque, OperatorLessThanEqual) {
916 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
917 InlineDeque<int, 4> deque = {0, 0, 1, 2};
918 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
919 deque.pop_front();
920 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
921 deque.push_back(3);
922 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
923 deque.pop_front();
924 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
925 deque.push_back(4);
926
927 for (int i = 0; i < deque.size(); i++) {
928 for (int j = 0; j <= i; j++) {
929 ASSERT_TRUE((deque.begin() + j) <= (deque.begin() + i));
930 }
931
932 ASSERT_TRUE((deque.begin() + i) <= deque.end());
933 }
934 }
935
TEST(InlineDeque,OperatorGreater)936 TEST(InlineDeque, OperatorGreater) {
937 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
938 InlineDeque<int, 4> deque = {0, 0, 1, 2};
939 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
940 deque.pop_front();
941 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
942 deque.push_back(3);
943 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
944 deque.pop_front();
945 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
946 deque.push_back(4);
947
948 for (int i = 0; i < deque.size(); i++) {
949 for (int j = i + 1; j < deque.size(); j++) {
950 ASSERT_TRUE((deque.begin() + j) > (deque.begin() + i));
951 }
952
953 ASSERT_TRUE(deque.end() > (deque.begin() + i));
954 }
955 }
956
TEST(InlineDeque,OperatorGreaterThanEqual)957 TEST(InlineDeque, OperatorGreaterThanEqual) {
958 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
959 InlineDeque<int, 4> deque = {0, 0, 1, 2};
960 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
961 deque.pop_front();
962 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
963 deque.push_back(3);
964 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
965 deque.pop_front();
966 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
967 deque.push_back(4);
968
969 for (int i = 0; i < deque.size(); i++) {
970 for (int j = i; j < deque.size(); j++) {
971 ASSERT_TRUE((deque.begin() + j) >= (deque.begin() + i));
972 }
973
974 ASSERT_TRUE(deque.end() >= (deque.begin() + i));
975 }
976 }
977
TEST(InlineDeque,DereferenceOperator)978 TEST(InlineDeque, DereferenceOperator) {
979 // Content = {0, 0, 1, 2}, Storage = [0, 0, 1, 2]
980 InlineDeque<int, 4> deque = {0, 0, 1, 2};
981 // Content = {0, 1, 2}, Storage = [x, 0, 1, 2]
982 deque.pop_front();
983 // Content = {0, 1, 2, 3}, Storage = [3, 0, 1, 2]
984 deque.push_back(3);
985 // Content = {1, 2, 3}, Storage = [3, x, 1, 2]
986 deque.pop_front();
987 // Content = {1, 2, 3, 4}, Storage = [3, 4, 1, 2]
988 deque.push_back(4);
989
990 for (int i = 0; i < deque.size(); i++) {
991 const auto it = deque.begin() + i;
992 ASSERT_EQ(*(it.operator->()), static_cast<int>(i + 1));
993 }
994 }
995
996 // Test that InlineDeque<T> is trivially destructible when its type is.
997 static_assert(std::is_trivially_destructible_v<InlineDeque<int, 4>>);
998
999 static_assert(std::is_trivially_destructible_v<MoveOnly>);
1000 static_assert(std::is_trivially_destructible_v<InlineDeque<MoveOnly, 1>>);
1001
1002 static_assert(std::is_trivially_destructible_v<CopyOnly>);
1003 static_assert(std::is_trivially_destructible_v<InlineDeque<CopyOnly, 99>>);
1004
1005 static_assert(!std::is_trivially_destructible_v<Counter>);
1006 static_assert(!std::is_trivially_destructible_v<InlineDeque<Counter, 99>>);
1007
1008 // Generic-capacity deques cannot be constructed or destructed.
1009 static_assert(!std::is_constructible_v<InlineDeque<int>>);
1010 static_assert(!std::is_destructible_v<InlineDeque<int>>);
1011
1012 // Tests that InlineDeque<T> does not have any extra padding.
1013 static_assert(sizeof(InlineDeque<uint8_t, 1>) ==
1014 sizeof(InlineDeque<uint8_t>::size_type) * 4 +
1015 std::max(sizeof(InlineDeque<uint8_t>::size_type),
1016 sizeof(uint8_t)));
1017 static_assert(sizeof(InlineDeque<uint8_t, 2>) ==
1018 sizeof(InlineDeque<uint8_t>::size_type) * 4 +
1019 2 * sizeof(uint8_t));
1020 static_assert(sizeof(InlineDeque<uint16_t, 1>) ==
1021 sizeof(InlineDeque<uint16_t>::size_type) * 4 + sizeof(uint16_t));
1022 static_assert(sizeof(InlineDeque<uint32_t, 1>) ==
1023 sizeof(InlineDeque<uint32_t>::size_type) * 4 + sizeof(uint32_t));
1024 static_assert(sizeof(InlineDeque<uint64_t, 1>) ==
1025 sizeof(InlineDeque<uint64_t>::size_type) * 4 + sizeof(uint64_t));
1026
1027 // Test that InlineDeque<T> is copy constructible
1028 static_assert(std::is_copy_constructible_v<InlineDeque<int, 4>::iterator>);
1029
1030 // Test that InlineDeque<T> is move constructible
1031 static_assert(std::is_move_constructible_v<InlineDeque<MoveOnly, 4>::iterator>);
1032
1033 // Test that InlineDeque<T> is copy assignable
1034 static_assert(std::is_copy_assignable_v<InlineDeque<int>::iterator>);
1035 static_assert(std::is_copy_assignable_v<InlineDeque<int, 4>::iterator>);
1036
1037 // Test that InlineDeque<T> is move assignable
1038 static_assert(std::is_move_assignable_v<InlineDeque<MoveOnly>>);
1039 static_assert(std::is_move_assignable_v<InlineDeque<MoveOnly, 4>>);
1040
1041 // Test that InlineDeque<T>::iterator can be converted to a const_iterator
1042 static_assert(std::is_convertible<InlineDeque<int>::iterator,
1043 InlineDeque<int>::const_iterator>::value);
1044 static_assert(std::is_convertible<InlineDeque<int, 4>::iterator,
1045 InlineDeque<int, 4>::const_iterator>::value);
1046
1047 // Test that InlineDeque<T>::const_iterator can NOT be converted to a iterator
1048 static_assert(!std::is_convertible<InlineDeque<int>::const_iterator,
1049 InlineDeque<int>::iterator>::value);
1050 static_assert(!std::is_convertible<InlineDeque<int, 4>::const_iterator,
1051 InlineDeque<int, 4>::iterator>::value);
1052
1053 } // namespace
1054 } // namespace pw::containers
1055