xref: /aosp_15_r20/external/pigweed/pw_containers/intrusive_set_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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