1 // Copyright 2024 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/intrusive_set.h"
16
17 #include "pw_compilation_testing/negative_compilation.h"
18 #include "pw_containers/intrusive_multiset.h"
19 #include "pw_span/span.h"
20 #include "pw_unit_test/framework.h"
21
22 namespace {
23
24 // Base item.
25 class BaseItem {
26 public:
BaseItem(size_t key,const char * name)27 BaseItem(size_t key, const char* name) : key_(key), name_(name) {}
28
key() const29 constexpr const size_t& key() const { return key_; }
name() const30 constexpr const char* name() const { return name_; }
set_name(const char * name)31 void set_name(const char* name) { name_ = name; }
32
operator <(const BaseItem & rhs) const33 bool operator<(const BaseItem& rhs) const { return key() < rhs.key(); }
34
35 private:
36 size_t key_;
37 const char* name_;
38 };
39
40 // A basic item that can be used in a set.
41 struct TestItem : public ::pw::IntrusiveSet<TestItem>::Item, public BaseItem {
TestItem__anonb368cb8d0111::TestItem42 TestItem(size_t key, const char* name) : BaseItem(key, name) {}
43 };
44
45 // Test fixture.
46 class IntrusiveSetTest : public ::testing::Test {
47 protected:
48 using IntrusiveSet = ::pw::IntrusiveSet<TestItem>;
49 static constexpr size_t kNumItems = 10;
50
SetUp()51 void SetUp() override { set_.insert(items_.begin(), items_.end()); }
52
TearDown()53 void TearDown() override { set_.clear(); }
54
55 std::array<TestItem, kNumItems> items_ = {{
56 {30, "a"},
57 {50, "b"},
58 {20, "c"},
59 {40, "d"},
60 {10, "e"},
61 {35, "A"},
62 {55, "B"},
63 {25, "C"},
64 {45, "D"},
65 {15, "E"},
66 }};
67
68 IntrusiveSet set_;
69 };
70
71 // Unit tests.
72
TEST_F(IntrusiveSetTest,Construct_Default)73 TEST_F(IntrusiveSetTest, Construct_Default) {
74 IntrusiveSet set;
75 EXPECT_TRUE(set.empty());
76 EXPECT_EQ(set.begin(), set.end());
77 EXPECT_EQ(set.rbegin(), set.rend());
78 EXPECT_EQ(set.size(), 0U);
79 EXPECT_EQ(set.lower_bound(items_[0]), set.end());
80 EXPECT_EQ(set.upper_bound(items_[0]), set.end());
81 }
82
TEST_F(IntrusiveSetTest,Construct_ObjectIterators)83 TEST_F(IntrusiveSetTest, Construct_ObjectIterators) {
84 set_.clear();
85 IntrusiveSet set(items_.begin(), items_.end());
86 EXPECT_FALSE(set.empty());
87 EXPECT_EQ(set.size(), items_.size());
88 set.clear();
89 }
90
TEST_F(IntrusiveSetTest,Construct_ObjectIterators_Empty)91 TEST_F(IntrusiveSetTest, Construct_ObjectIterators_Empty) {
92 IntrusiveSet set(items_.end(), items_.end());
93 EXPECT_TRUE(set.empty());
94 EXPECT_EQ(set.size(), 0U);
95 }
96
TEST_F(IntrusiveSetTest,Construct_PointerIterators)97 TEST_F(IntrusiveSetTest, Construct_PointerIterators) {
98 std::array<TestItem*, 3> ptrs = {&items_[0], &items_[1], &items_[2]};
99 set_.clear();
100 IntrusiveSet set(ptrs.begin(), ptrs.end());
101 EXPECT_FALSE(set.empty());
102 EXPECT_EQ(set.size(), 3U);
103 set.clear();
104 }
105
TEST_F(IntrusiveSetTest,Construct_PointerIterators_Empty)106 TEST_F(IntrusiveSetTest, Construct_PointerIterators_Empty) {
107 std::array<TestItem*, 0> ptrs;
108 IntrusiveSet set(ptrs.begin(), ptrs.end());
109 EXPECT_TRUE(set.empty());
110 EXPECT_EQ(set.size(), 0U);
111 set.clear();
112 }
113
TEST_F(IntrusiveSetTest,Construct_InitializerList)114 TEST_F(IntrusiveSetTest, Construct_InitializerList) {
115 set_.clear();
116 IntrusiveSet set({&items_[0], &items_[2], &items_[4]});
117 auto iter = set.begin();
118 EXPECT_EQ((iter++)->key(), 10U);
119 EXPECT_EQ((iter++)->key(), 20U);
120 EXPECT_EQ((iter++)->key(), 30U);
121 set.clear();
122 }
123
TEST_F(IntrusiveSetTest,Construct_InitializerList_Empty)124 TEST_F(IntrusiveSetTest, Construct_InitializerList_Empty) {
125 IntrusiveSet set(std::initializer_list<TestItem*>{});
126 EXPECT_TRUE(set.empty());
127 EXPECT_EQ(set.size(), 0U);
128 }
129
TEST_F(IntrusiveSetTest,Construct_CustomCompare)130 TEST_F(IntrusiveSetTest, Construct_CustomCompare) {
131 auto greater_than = [](const BaseItem& lhs, const BaseItem& rhs) {
132 return lhs.key() > rhs.key();
133 };
134 set_.clear();
135 IntrusiveSet set({&items_[0], &items_[2], &items_[4]},
136 std::move(greater_than));
137 auto iter = set.begin();
138 EXPECT_EQ((iter++)->key(), 30U);
139 EXPECT_EQ((iter++)->key(), 20U);
140 EXPECT_EQ((iter++)->key(), 10U);
141 set.clear();
142 }
143
144 // A struct that is not a set item.
145 struct NotAnItem : public BaseItem {
NotAnItem__anonb368cb8d0111::NotAnItem146 NotAnItem(size_t key, const char* name) : BaseItem(key, name) {}
147 };
148
149 #if PW_NC_TEST(IncompatibleItem)
150 PW_NC_EXPECT("IntrusiveSet items must be derived from IntrusiveSet<T>::Item");
151
152 struct BadItem : public ::pw::IntrusiveSet<NotAnItem>::Item {
153 public:
operator <__anonb368cb8d0111::BadItem154 constexpr bool operator<(const BadItem& rhs) const { return this < &rhs; }
155 };
156
157 [[maybe_unused]] ::pw::IntrusiveSet<BadItem> bad_set1;
158
159 #elif PW_NC_TEST(DoesNotInheritFromItem)
160 PW_NC_EXPECT("IntrusiveSet items must be derived from IntrusiveSet<T>::Item");
161
162 [[maybe_unused]] ::pw::IntrusiveSet<NotAnItem> bad_set2;
163
164 #endif // PW_NC_TEST
165
166 // Iterators
167
TEST_F(IntrusiveSetTest,Iterator)168 TEST_F(IntrusiveSetTest, Iterator) {
169 const IntrusiveSet& set = set_;
170 auto iter = set.begin();
171 size_t key = 10;
172 for (size_t i = 0; i < kNumItems; ++i) {
173 auto& item = *iter++;
174 EXPECT_EQ(item.key(), key);
175 key += 5;
176 }
177 EXPECT_EQ(key, 60U);
178 EXPECT_EQ(iter, set.end());
179 EXPECT_EQ(iter, set.cend());
180 for (size_t i = 0; i < kNumItems; ++i) {
181 key -= 5;
182 EXPECT_EQ((--iter)->key(), key);
183 }
184 EXPECT_EQ(key, 10U);
185 EXPECT_EQ(iter, set.begin());
186 EXPECT_EQ(iter, set.cbegin());
187 }
188
TEST_F(IntrusiveSetTest,ReverseIterator)189 TEST_F(IntrusiveSetTest, ReverseIterator) {
190 const IntrusiveSet& set = set_;
191 auto iter = set.rbegin();
192 size_t key = 55;
193 for (size_t i = 0; i < kNumItems; ++i) {
194 auto& item = *iter++;
195 EXPECT_EQ(item.key(), key);
196 key -= 5;
197 }
198 EXPECT_EQ(key, 5U);
199 EXPECT_EQ(iter, set.rend());
200 EXPECT_EQ(iter, set.crend());
201 for (size_t i = 0; i < kNumItems; ++i) {
202 key += 5;
203 EXPECT_EQ((--iter)->key(), key);
204 }
205 EXPECT_EQ(key, 55U);
206 EXPECT_EQ(iter, set.rbegin());
207 EXPECT_EQ(iter, set.crbegin());
208 }
209
TEST_F(IntrusiveSetTest,ConstIterator_CompareNonConst)210 TEST_F(IntrusiveSetTest, ConstIterator_CompareNonConst) {
211 EXPECT_EQ(set_.end(), set_.cend());
212 }
213
214 // A set item that is distinct from TestItem
215 struct OtherItem : public ::pw::IntrusiveSet<OtherItem>::Item, public BaseItem {
OtherItem__anonb368cb8d0111::OtherItem216 OtherItem(size_t key, const char* name) : BaseItem(key, name) {}
217 };
218
TEST_F(IntrusiveSetTest,ConstIterator_CompareNonConst_CompilationFails)219 TEST_F(IntrusiveSetTest, ConstIterator_CompareNonConst_CompilationFails) {
220 ::pw::IntrusiveSet<OtherItem> set;
221 #if PW_NC_TEST(CannotCompareIncompatibleIteratorsEqual)
222 PW_NC_EXPECT("set_\.end\(\) == set\.end\(\)");
223 static_cast<void>(set_.end() == set.end());
224 #elif PW_NC_TEST(CannotCompareIncompatibleIteratorsInequal)
225 PW_NC_EXPECT("set_\.end\(\) != set\.end\(\)");
226 static_cast<void>(set_.end() != set.end());
227 #endif // PW_NC_TEST
228 }
229
230 #if PW_NC_TEST(CannotModifyThroughConstIterator)
231 PW_NC_EXPECT("function is not marked const|discards qualifiers");
232
TEST_F(IntrusiveSetTest,ConstIterator_Modify)233 TEST_F(IntrusiveSetTest, ConstIterator_Modify) {
234 const IntrusiveSet& set = set_;
235 auto iter = set.begin();
236 iter->set_name("nope");
237 }
238
239 #endif // PW_NC_TEST
240
241 // Capacity
242
TEST_F(IntrusiveSetTest,IsEmpty)243 TEST_F(IntrusiveSetTest, IsEmpty) {
244 const IntrusiveSet& set = set_;
245 EXPECT_FALSE(set.empty());
246 set_.clear();
247 EXPECT_TRUE(set.empty());
248 }
249
TEST_F(IntrusiveSetTest,GetSize)250 TEST_F(IntrusiveSetTest, GetSize) {
251 const IntrusiveSet& set = set_;
252 EXPECT_EQ(set.size(), kNumItems);
253 set_.clear();
254 EXPECT_EQ(set.size(), 0U);
255 }
256
TEST_F(IntrusiveSetTest,GetMaxSize)257 TEST_F(IntrusiveSetTest, GetMaxSize) {
258 const IntrusiveSet& set = set_;
259 EXPECT_EQ(set.max_size(), size_t(std::numeric_limits<ptrdiff_t>::max()));
260 }
261
262 // Modifiers
263
TEST_F(IntrusiveSetTest,Insert)264 TEST_F(IntrusiveSetTest, Insert) {
265 set_.clear();
266 bool sorted = true;
267 size_t prev_key = 0;
268 for (auto& item : items_) {
269 sorted &= prev_key < item.key();
270
271 // Use the "hinted" version of insert.
272 set_.insert(set_.end(), item);
273 prev_key = item.key();
274 }
275 EXPECT_FALSE(sorted);
276
277 EXPECT_EQ(set_.size(), kNumItems);
278 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
279 }
280
TEST_F(IntrusiveSetTest,Insert_Duplicate)281 TEST_F(IntrusiveSetTest, Insert_Duplicate) {
282 TestItem item1(60, "1");
283 TestItem item2(60, "2");
284
285 auto result = set_.insert(item1);
286 EXPECT_STREQ(result.first->name(), "1");
287 EXPECT_TRUE(result.second);
288
289 result = set_.insert(item2);
290 EXPECT_STREQ(result.first->name(), "1");
291 EXPECT_FALSE(result.second);
292
293 EXPECT_EQ(set_.size(), kNumItems + 1);
294 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
295
296 // Explicitly clear the set before item 1 goes out of scope.
297 set_.clear();
298 }
299
TEST_F(IntrusiveSetTest,Insert_ObjectIterators)300 TEST_F(IntrusiveSetTest, Insert_ObjectIterators) {
301 set_.clear();
302 set_.insert(items_.begin(), items_.end());
303 EXPECT_EQ(set_.size(), kNumItems);
304 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
305 }
306
TEST_F(IntrusiveSetTest,Insert_ObjectIterators_Empty)307 TEST_F(IntrusiveSetTest, Insert_ObjectIterators_Empty) {
308 set_.insert(items_.end(), items_.end());
309 EXPECT_EQ(set_.size(), kNumItems);
310 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
311 }
312
TEST_F(IntrusiveSetTest,Insert_ObjectIterators_WithDuplicates)313 TEST_F(IntrusiveSetTest, Insert_ObjectIterators_WithDuplicates) {
314 std::array<TestItem, 3> items = {{
315 {50, "B"},
316 {40, "D"},
317 {60, "F"},
318 }};
319
320 set_.insert(items.begin(), items.end());
321 EXPECT_EQ(set_.size(), kNumItems + 1);
322 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
323
324 auto iter = set_.find(items[0]);
325 ASSERT_NE(iter, set_.end());
326 EXPECT_STRNE(iter->name(), "B");
327
328 iter = set_.find(items[1]);
329 ASSERT_NE(iter, set_.end());
330 EXPECT_STRNE(iter->name(), "D");
331
332 iter = set_.find(items[2]);
333 ASSERT_NE(iter, set_.end());
334 EXPECT_STREQ(iter->name(), "F");
335
336 // Explicitly clear the set before items goes out of scope.
337 set_.clear();
338 }
339
TEST_F(IntrusiveSetTest,Insert_PointerIterators)340 TEST_F(IntrusiveSetTest, Insert_PointerIterators) {
341 set_.clear();
342 std::array<TestItem*, 3> ptrs = {&items_[0], &items_[1], &items_[2]};
343
344 set_.insert(ptrs.begin(), ptrs.end());
345 EXPECT_EQ(set_.size(), 3U);
346 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
347 }
348
TEST_F(IntrusiveSetTest,Insert_PointerIterators_Empty)349 TEST_F(IntrusiveSetTest, Insert_PointerIterators_Empty) {
350 std::array<TestItem*, 0> ptrs;
351
352 set_.insert(ptrs.begin(), ptrs.end());
353 EXPECT_EQ(set_.size(), kNumItems);
354 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
355 }
356
TEST_F(IntrusiveSetTest,Insert_PointerIterators_WithDuplicates)357 TEST_F(IntrusiveSetTest, Insert_PointerIterators_WithDuplicates) {
358 TestItem item1(50, "B");
359 TestItem item2(40, "D");
360 TestItem item3(60, "F");
361 std::array<TestItem*, 3> ptrs = {&item1, &item2, &item3};
362
363 set_.insert(ptrs.begin(), ptrs.end());
364 EXPECT_EQ(set_.size(), kNumItems + 1);
365 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
366
367 auto iter = set_.find(item1);
368 ASSERT_NE(iter, set_.end());
369 EXPECT_STRNE(iter->name(), "B");
370
371 iter = set_.find(item2);
372 ASSERT_NE(iter, set_.end());
373 EXPECT_STRNE(iter->name(), "D");
374
375 iter = set_.find(item3);
376 ASSERT_NE(iter, set_.end());
377 EXPECT_STREQ(iter->name(), "F");
378
379 // Explicitly clear the set before items goes out of scope.
380 set_.clear();
381 }
382
TEST_F(IntrusiveSetTest,Insert_InitializerList)383 TEST_F(IntrusiveSetTest, Insert_InitializerList) {
384 set_.clear();
385 set_.insert({&items_[0], &items_[2], &items_[4]});
386 EXPECT_EQ(set_.size(), 3U);
387 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
388 }
389
TEST_F(IntrusiveSetTest,Insert_InitializerList_Empty)390 TEST_F(IntrusiveSetTest, Insert_InitializerList_Empty) {
391 set_.insert({});
392 EXPECT_EQ(set_.size(), kNumItems);
393 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
394 }
395
TEST_F(IntrusiveSetTest,Insert_InitializerList_WithDuplicates)396 TEST_F(IntrusiveSetTest, Insert_InitializerList_WithDuplicates) {
397 TestItem item1(50, "B");
398 TestItem item2(40, "D");
399 TestItem item3(60, "F");
400
401 set_.insert({&item1, &item2, &item3});
402 EXPECT_EQ(set_.size(), kNumItems + 1);
403 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
404
405 auto iter = set_.find(item1);
406 ASSERT_NE(iter, set_.end());
407 EXPECT_STRNE(iter->name(), "B");
408
409 iter = set_.find(item2);
410 ASSERT_NE(iter, set_.end());
411 EXPECT_STRNE(iter->name(), "D");
412
413 iter = set_.find(item3);
414 ASSERT_NE(iter, set_.end());
415 EXPECT_STREQ(iter->name(), "F");
416
417 // Explicitly clear the set before items goes out of scope.
418 set_.clear();
419 }
420
421 // An item derived from TestItem.
422 struct DerivedItem : public TestItem {
DerivedItem__anonb368cb8d0111::DerivedItem423 DerivedItem(size_t n, const char* name) : TestItem(n * 10, name) {}
424 };
425
TEST_F(IntrusiveSetTest,Insert_DerivedItems)426 TEST_F(IntrusiveSetTest, Insert_DerivedItems) {
427 DerivedItem item1(6, "f");
428 set_.insert(item1);
429
430 DerivedItem item2(7, "g");
431 set_.insert(item2);
432
433 EXPECT_EQ(set_.size(), kNumItems + 2);
434 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
435
436 // Explicitly clear the set before items goes out of scope.
437 set_.clear();
438 }
439
TEST_F(IntrusiveSetTest,Insert_DerivedItems_CompilationFails)440 TEST_F(IntrusiveSetTest, Insert_DerivedItems_CompilationFails) {
441 ::pw::IntrusiveSet<DerivedItem> derived_from_compatible_item_type;
442
443 DerivedItem item1(6, "f");
444 derived_from_compatible_item_type.insert(item1);
445
446 EXPECT_EQ(derived_from_compatible_item_type.size(), 1U);
447
448 #if PW_NC_TEST(CannotAddBaseClassToDerivedClassSet)
449 PW_NC_EXPECT("derived_from_compatible_item_type\.insert\(item2\)");
450
451 TestItem item2(70, "g");
452 derived_from_compatible_item_type.insert(item2);
453 #endif
454 derived_from_compatible_item_type.clear();
455 }
456
TEST_F(IntrusiveSetTest,Erase_OneItem)457 TEST_F(IntrusiveSetTest, Erase_OneItem) {
458 for (size_t i = 0; i < kNumItems; ++i) {
459 EXPECT_EQ(set_.size(), kNumItems);
460 EXPECT_EQ(set_.erase(items_[i]), 1U);
461 EXPECT_EQ(set_.size(), kNumItems - 1);
462 auto iter = set_.find(items_[i]);
463 EXPECT_EQ(iter, set_.end());
464 set_.insert(items_[i]);
465 }
466 }
467
TEST_F(IntrusiveSetTest,Erase_OnlyItem)468 TEST_F(IntrusiveSetTest, Erase_OnlyItem) {
469 set_.clear();
470 set_.insert(items_[0]);
471 EXPECT_EQ(set_.size(), 1U);
472
473 EXPECT_EQ(set_.erase(items_[0]), 1U);
474 EXPECT_EQ(set_.size(), 0U);
475 }
476
TEST_F(IntrusiveSetTest,Erase_AllOnebyOne)477 TEST_F(IntrusiveSetTest, Erase_AllOnebyOne) {
478 auto iter = set_.begin();
479 for (size_t n = kNumItems; n != 0; --n) {
480 ASSERT_NE(iter, set_.end());
481 iter = set_.erase(iter);
482 }
483 EXPECT_EQ(iter, set_.end());
484 EXPECT_EQ(set_.size(), 0U);
485 }
486
TEST_F(IntrusiveSetTest,Erase_Range)487 TEST_F(IntrusiveSetTest, Erase_Range) {
488 auto first = set_.begin();
489 auto last = set_.end();
490 ++first;
491 --last;
492 auto iter = set_.erase(first, last);
493 EXPECT_EQ(set_.size(), 2U);
494 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
495 EXPECT_EQ(iter->key(), 55U);
496 }
497
TEST_F(IntrusiveSetTest,Erase_MissingItem)498 TEST_F(IntrusiveSetTest, Erase_MissingItem) {
499 TestItem item(60, "F");
500 EXPECT_EQ(set_.erase(item), 0U);
501 }
502
TEST_F(IntrusiveSetTest,Erase_Reinsert)503 TEST_F(IntrusiveSetTest, Erase_Reinsert) {
504 EXPECT_EQ(set_.size(), items_.size());
505
506 EXPECT_EQ(set_.erase(items_[0]), 1U);
507 EXPECT_EQ(set_.find(items_[0]), set_.end());
508
509 EXPECT_EQ(set_.erase(items_[2]), 1U);
510 EXPECT_EQ(set_.find(items_[2]), set_.end());
511
512 EXPECT_EQ(set_.erase(items_[4]), 1U);
513 EXPECT_EQ(set_.find(items_[4]), set_.end());
514
515 EXPECT_EQ(set_.size(), items_.size() - 3);
516
517 set_.insert(items_[4]);
518 auto iter = set_.find(items_[4]);
519 EXPECT_NE(iter, set_.end());
520
521 set_.insert(items_[0]);
522 iter = set_.find(items_[0]);
523 EXPECT_NE(iter, set_.end());
524
525 set_.insert(items_[2]);
526 iter = set_.find(items_[2]);
527 EXPECT_NE(iter, set_.end());
528
529 EXPECT_EQ(set_.size(), items_.size());
530 }
531
TEST_F(IntrusiveSetTest,Swap)532 TEST_F(IntrusiveSetTest, Swap) {
533 std::array<TestItem, 3> items = {{
534 {50, "B"},
535 {40, "D"},
536 {60, "F"},
537 }};
538 IntrusiveSet set(items.begin(), items.end());
539
540 set_.swap(set);
541 EXPECT_EQ(set.size(), kNumItems);
542 EXPECT_TRUE(std::is_sorted(set.begin(), set.end()));
543
544 auto iter = set.begin();
545 EXPECT_STREQ((iter++)->name(), "e");
546 EXPECT_STREQ((iter++)->name(), "E");
547 EXPECT_STREQ((iter++)->name(), "c");
548 EXPECT_STREQ((iter++)->name(), "C");
549 EXPECT_STREQ((iter++)->name(), "a");
550 EXPECT_STREQ((iter++)->name(), "A");
551 EXPECT_STREQ((iter++)->name(), "d");
552 EXPECT_STREQ((iter++)->name(), "D");
553 EXPECT_STREQ((iter++)->name(), "b");
554 EXPECT_STREQ((iter++)->name(), "B");
555 EXPECT_EQ(iter, set.end());
556 set.clear();
557
558 EXPECT_EQ(set_.size(), 3U);
559 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
560 iter = set_.begin();
561 EXPECT_STREQ((iter++)->name(), "D");
562 EXPECT_STREQ((iter++)->name(), "B");
563 EXPECT_STREQ((iter++)->name(), "F");
564 EXPECT_EQ(iter, set_.end());
565
566 // Explicitly clear the set before items goes out of scope.
567 set_.clear();
568 }
569
TEST_F(IntrusiveSetTest,Swap_Empty)570 TEST_F(IntrusiveSetTest, Swap_Empty) {
571 IntrusiveSet set;
572
573 set_.swap(set);
574 EXPECT_EQ(set.size(), kNumItems);
575 EXPECT_TRUE(std::is_sorted(set.begin(), set.end()));
576
577 auto iter = set.begin();
578 EXPECT_STREQ((iter++)->name(), "e");
579 EXPECT_STREQ((iter++)->name(), "E");
580 EXPECT_STREQ((iter++)->name(), "c");
581 EXPECT_STREQ((iter++)->name(), "C");
582 EXPECT_STREQ((iter++)->name(), "a");
583 EXPECT_STREQ((iter++)->name(), "A");
584 EXPECT_STREQ((iter++)->name(), "d");
585 EXPECT_STREQ((iter++)->name(), "D");
586 EXPECT_STREQ((iter++)->name(), "b");
587 EXPECT_STREQ((iter++)->name(), "B");
588 EXPECT_EQ(iter, set.end());
589 set.clear();
590
591 EXPECT_EQ(set_.size(), 0U);
592 }
593
TEST_F(IntrusiveSetTest,Merge)594 TEST_F(IntrusiveSetTest, Merge) {
595 std::array<TestItem, 3> items = {{
596 {5, "f"},
597 {75, "g"},
598 {85, "h"},
599 }};
600 IntrusiveSet set(items.begin(), items.end());
601
602 set_.merge(set);
603 EXPECT_TRUE(set.empty());
604 EXPECT_EQ(set_.size(), kNumItems + 3);
605 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
606
607 auto iter = set_.begin();
608 EXPECT_STREQ((iter++)->name(), "f");
609 EXPECT_STREQ((iter++)->name(), "e");
610 EXPECT_STREQ((iter++)->name(), "E");
611 EXPECT_STREQ((iter++)->name(), "c");
612 EXPECT_STREQ((iter++)->name(), "C");
613 EXPECT_STREQ((iter++)->name(), "a");
614 EXPECT_STREQ((iter++)->name(), "A");
615 EXPECT_STREQ((iter++)->name(), "d");
616 EXPECT_STREQ((iter++)->name(), "D");
617 EXPECT_STREQ((iter++)->name(), "b");
618 EXPECT_STREQ((iter++)->name(), "B");
619 EXPECT_STREQ((iter++)->name(), "g");
620 EXPECT_STREQ((iter++)->name(), "h");
621 EXPECT_EQ(iter, set_.end());
622
623 // Explicitly clear the set before items goes out of scope.
624 set_.clear();
625 }
626
TEST_F(IntrusiveSetTest,Merge_Empty)627 TEST_F(IntrusiveSetTest, Merge_Empty) {
628 IntrusiveSet set;
629
630 set_.merge(set);
631 EXPECT_EQ(set_.size(), kNumItems);
632 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
633
634 set.merge(set_);
635 EXPECT_TRUE(set_.empty());
636 EXPECT_EQ(set.size(), kNumItems);
637 EXPECT_TRUE(std::is_sorted(set.begin(), set.end()));
638
639 set.clear();
640 }
641
TEST_F(IntrusiveSetTest,Merge_WithDuplicates)642 TEST_F(IntrusiveSetTest, Merge_WithDuplicates) {
643 std::array<TestItem, 3> items = {{
644 {50, "B"},
645 {40, "D"},
646 {60, "F"},
647 }};
648 IntrusiveSet set(items.begin(), items.end());
649
650 set_.merge(set);
651 EXPECT_TRUE(set.empty());
652 EXPECT_EQ(set_.size(), kNumItems + 1);
653 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
654
655 auto iter = set_.begin();
656 EXPECT_STREQ((iter++)->name(), "e");
657 EXPECT_STREQ((iter++)->name(), "E");
658 EXPECT_STREQ((iter++)->name(), "c");
659 EXPECT_STREQ((iter++)->name(), "C");
660 EXPECT_STREQ((iter++)->name(), "a");
661 EXPECT_STREQ((iter++)->name(), "A");
662 EXPECT_STREQ((iter++)->name(), "d");
663 EXPECT_STREQ((iter++)->name(), "D");
664 EXPECT_STREQ((iter++)->name(), "b");
665 EXPECT_STREQ((iter++)->name(), "B");
666 EXPECT_STREQ((iter++)->name(), "F");
667 EXPECT_EQ(iter, set_.end());
668
669 // Explicitly clear the set before items goes out of scope.
670 set_.clear();
671 }
672
TEST_F(IntrusiveSetTest,Merge_MultiSet)673 TEST_F(IntrusiveSetTest, Merge_MultiSet) {
674 std::array<TestItem, 3> items = {{
675 {50, "B"},
676 {40, "D"},
677 {60, "F"},
678 }};
679 ::pw::IntrusiveMultiSet<TestItem> multiset(items.begin(), items.end());
680
681 set_.merge(multiset);
682 EXPECT_TRUE(multiset.empty());
683 EXPECT_EQ(set_.size(), kNumItems + 1);
684 EXPECT_TRUE(std::is_sorted(set_.begin(), set_.end()));
685
686 auto iter = set_.begin();
687 EXPECT_STREQ((iter++)->name(), "e");
688 EXPECT_STREQ((iter++)->name(), "E");
689 EXPECT_STREQ((iter++)->name(), "c");
690 EXPECT_STREQ((iter++)->name(), "C");
691 EXPECT_STREQ((iter++)->name(), "a");
692 EXPECT_STREQ((iter++)->name(), "A");
693 EXPECT_STREQ((iter++)->name(), "d");
694 EXPECT_STREQ((iter++)->name(), "D");
695 EXPECT_STREQ((iter++)->name(), "b");
696 EXPECT_STREQ((iter++)->name(), "B");
697 EXPECT_STREQ((iter++)->name(), "F");
698 EXPECT_EQ(iter, set_.end());
699
700 // Explicitly clear the set before items goes out of scope.
701 set_.clear();
702 }
703
TEST_F(IntrusiveSetTest,Count)704 TEST_F(IntrusiveSetTest, Count) {
705 const IntrusiveSet& set = set_;
706 for (const auto& item : items_) {
707 EXPECT_EQ(set.count(item), 1U);
708 }
709 }
710
TEST_F(IntrusiveSetTest,Count_NoSuchKey)711 TEST_F(IntrusiveSetTest, Count_NoSuchKey) {
712 const IntrusiveSet& set = set_;
713 TestItem item(60, "F");
714 EXPECT_EQ(set.count(item), 0U);
715 }
716
TEST_F(IntrusiveSetTest,Find)717 TEST_F(IntrusiveSetTest, Find) {
718 const IntrusiveSet& set = set_;
719 for (const auto& item : items_) {
720 auto iter = set.find(item);
721 ASSERT_NE(iter, set.end());
722 EXPECT_EQ(iter->key(), item.key());
723 }
724 }
725
TEST_F(IntrusiveSetTest,Find_NoSuchKey)726 TEST_F(IntrusiveSetTest, Find_NoSuchKey) {
727 const IntrusiveSet& set = set_;
728 TestItem item(60, "F");
729 auto iter = set.find(item);
730 EXPECT_EQ(iter, set.end());
731 }
732
TEST_F(IntrusiveSetTest,LowerBound)733 TEST_F(IntrusiveSetTest, LowerBound) {
734 const IntrusiveSet& set = set_;
735 auto iter = set.lower_bound({10, "?"});
736 ASSERT_NE(iter, set.end());
737 EXPECT_STREQ(iter->name(), "e");
738
739 iter = set.lower_bound({20, "?"});
740 ASSERT_NE(iter, set.end());
741 EXPECT_STREQ(iter->name(), "c");
742
743 iter = set.lower_bound({30, "?"});
744 ASSERT_NE(iter, set.end());
745 EXPECT_STREQ(iter->name(), "a");
746
747 iter = set.lower_bound({40, "?"});
748 ASSERT_NE(iter, set.end());
749 EXPECT_STREQ(iter->name(), "d");
750
751 iter = set.lower_bound({50, "?"});
752 ASSERT_NE(iter, set.end());
753 EXPECT_STREQ(iter->name(), "b");
754 }
755
TEST_F(IntrusiveSetTest,LowerBound_NoExactKey)756 TEST_F(IntrusiveSetTest, LowerBound_NoExactKey) {
757 const IntrusiveSet& set = set_;
758 auto iter = set.lower_bound({6, "?"});
759 ASSERT_NE(iter, set.end());
760 EXPECT_STREQ(iter->name(), "e");
761
762 iter = set.lower_bound({16, "?"});
763 ASSERT_NE(iter, set.end());
764 EXPECT_STREQ(iter->name(), "c");
765
766 iter = set.lower_bound({26, "?"});
767 ASSERT_NE(iter, set.end());
768 EXPECT_STREQ(iter->name(), "a");
769
770 iter = set.lower_bound({36, "?"});
771 ASSERT_NE(iter, set.end());
772 EXPECT_STREQ(iter->name(), "d");
773
774 iter = set.lower_bound({46, "?"});
775 ASSERT_NE(iter, set.end());
776 EXPECT_STREQ(iter->name(), "b");
777 }
778
TEST_F(IntrusiveSetTest,LowerBound_OutOfRange)779 TEST_F(IntrusiveSetTest, LowerBound_OutOfRange) {
780 const IntrusiveSet& set = set_;
781 EXPECT_EQ(set.lower_bound({56, "?"}), set.end());
782 }
783
TEST_F(IntrusiveSetTest,UpperBound)784 TEST_F(IntrusiveSetTest, UpperBound) {
785 const IntrusiveSet& set = set_;
786 auto iter = set.upper_bound({15, "?"});
787 ASSERT_NE(iter, set.end());
788 EXPECT_STREQ(iter->name(), "c");
789
790 iter = set.upper_bound({25, "?"});
791 ASSERT_NE(iter, set.end());
792 EXPECT_STREQ(iter->name(), "a");
793
794 iter = set.upper_bound({35, "?"});
795 ASSERT_NE(iter, set.end());
796 EXPECT_STREQ(iter->name(), "d");
797
798 iter = set.upper_bound({45, "?"});
799 ASSERT_NE(iter, set.end());
800 EXPECT_STREQ(iter->name(), "b");
801
802 EXPECT_EQ(set.upper_bound({55, "?"}), set.end());
803 }
804
TEST_F(IntrusiveSetTest,UpperBound_NoExactKey)805 TEST_F(IntrusiveSetTest, UpperBound_NoExactKey) {
806 const IntrusiveSet& set = set_;
807 auto iter = set.upper_bound({6, "?"});
808 ASSERT_NE(iter, set.end());
809 EXPECT_STREQ(iter->name(), "e");
810
811 iter = set.upper_bound({16, "?"});
812 ASSERT_NE(iter, set.end());
813 EXPECT_STREQ(iter->name(), "c");
814
815 iter = set.upper_bound({26, "?"});
816 ASSERT_NE(iter, set.end());
817 EXPECT_STREQ(iter->name(), "a");
818
819 iter = set.upper_bound({36, "?"});
820 ASSERT_NE(iter, set.end());
821 EXPECT_STREQ(iter->name(), "d");
822
823 iter = set.upper_bound({46, "?"});
824 ASSERT_NE(iter, set.end());
825 EXPECT_STREQ(iter->name(), "b");
826 }
827
TEST_F(IntrusiveSetTest,UpperBound_OutOfRange)828 TEST_F(IntrusiveSetTest, UpperBound_OutOfRange) {
829 const IntrusiveSet& set = set_;
830 EXPECT_EQ(set.upper_bound({56, "?"}), set.end());
831 }
832
TEST_F(IntrusiveSetTest,EqualRange)833 TEST_F(IntrusiveSetTest, EqualRange) {
834 const IntrusiveSet& set = set_;
835
836 auto pair = set.equal_range({10, "?"});
837 IntrusiveSet::const_iterator lower = pair.first;
838 IntrusiveSet::const_iterator upper = pair.second;
839 ASSERT_NE(lower, set.end());
840 EXPECT_STREQ(lower->name(), "e");
841 ASSERT_NE(upper, set.end());
842 EXPECT_STREQ(upper->name(), "E");
843
844 std::tie(lower, upper) = set.equal_range({20, "?"});
845 ASSERT_NE(lower, set.end());
846 EXPECT_STREQ(lower->name(), "c");
847 ASSERT_NE(upper, set.end());
848 EXPECT_STREQ(upper->name(), "C");
849
850 std::tie(lower, upper) = set.equal_range({30, "?"});
851 ASSERT_NE(lower, set.end());
852 EXPECT_STREQ(lower->name(), "a");
853 ASSERT_NE(upper, set.end());
854 EXPECT_STREQ(upper->name(), "A");
855
856 std::tie(lower, upper) = set.equal_range({40, "?"});
857 ASSERT_NE(lower, set.end());
858 EXPECT_STREQ(lower->name(), "d");
859 ASSERT_NE(upper, set.end());
860 EXPECT_STREQ(upper->name(), "D");
861
862 std::tie(lower, upper) = set.equal_range({50, "?"});
863 ASSERT_NE(lower, set.end());
864 EXPECT_STREQ(lower->name(), "b");
865 ASSERT_NE(upper, set.end());
866 EXPECT_STREQ(upper->name(), "B");
867 }
868
TEST_F(IntrusiveSetTest,EqualRange_NoExactKey)869 TEST_F(IntrusiveSetTest, EqualRange_NoExactKey) {
870 const IntrusiveSet& set = set_;
871
872 auto pair = set.equal_range({6, "?"});
873 IntrusiveSet::const_iterator lower = pair.first;
874 IntrusiveSet::const_iterator upper = pair.second;
875 ASSERT_NE(lower, set.end());
876 EXPECT_STREQ(lower->name(), "e");
877 ASSERT_NE(upper, set.end());
878 EXPECT_STREQ(upper->name(), "e");
879
880 std::tie(lower, upper) = set.equal_range({16, "?"});
881 ASSERT_NE(lower, set.end());
882 EXPECT_STREQ(lower->name(), "c");
883 ASSERT_NE(upper, set.end());
884 EXPECT_STREQ(upper->name(), "c");
885
886 std::tie(lower, upper) = set.equal_range({26, "?"});
887 ASSERT_NE(lower, set.end());
888 EXPECT_STREQ(lower->name(), "a");
889 ASSERT_NE(upper, set.end());
890 EXPECT_STREQ(upper->name(), "a");
891
892 std::tie(lower, upper) = set.equal_range({36, "?"});
893 ASSERT_NE(lower, set.end());
894 EXPECT_STREQ(lower->name(), "d");
895 ASSERT_NE(upper, set.end());
896 EXPECT_STREQ(upper->name(), "d");
897
898 std::tie(lower, upper) = set.equal_range({46, "?"});
899 ASSERT_NE(lower, set.end());
900 EXPECT_STREQ(lower->name(), "b");
901 ASSERT_NE(upper, set.end());
902 EXPECT_STREQ(upper->name(), "b");
903 }
904
TEST_F(IntrusiveSetTest,EqualRange_OutOfRange)905 TEST_F(IntrusiveSetTest, EqualRange_OutOfRange) {
906 const IntrusiveSet& set = set_;
907
908 auto pair = set.equal_range({56, "?"});
909 IntrusiveSet::const_iterator lower = pair.first;
910 IntrusiveSet::const_iterator upper = pair.second;
911 EXPECT_EQ(lower, set.end());
912 EXPECT_EQ(upper, set.end());
913 }
914
915 } // namespace
916