xref: /aosp_15_r20/external/pigweed/pw_containers/intrusive_multimap_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_multimap.h"
16 
17 #include "pw_compilation_testing/negative_compilation.h"
18 #include "pw_containers/intrusive_map.h"
19 #include "pw_span/span.h"
20 #include "pw_unit_test/framework.h"
21 
22 namespace {
23 
24 // Base pair.
25 class BaseItem {
26  public:
BaseItem(const char * name)27   explicit BaseItem(const char* name) : name_(name) {}
28 
name() const29   constexpr const char* name() const { return name_; }
set_name(const char * name)30   void set_name(const char* name) { name_ = name; }
31 
32  private:
33   const char* name_;
34 };
35 
36 // A basic pair that can be used in a map.
37 class TestPair : public ::pw::IntrusiveMultiMap<size_t, TestPair>::Pair,
38                  public BaseItem {
39  private:
40   using Pair = ::pw::IntrusiveMultiMap<size_t, TestPair>::Pair;
41 
42  public:
TestPair(size_t key,const char * name)43   TestPair(size_t key, const char* name) : Pair(key), BaseItem(name) {}
44 };
45 
46 // Test fixture.
47 class IntrusiveMultiMapTest : public ::testing::Test {
48  protected:
49   using IntrusiveMultiMap = ::pw::IntrusiveMultiMap<size_t, TestPair>;
50   static constexpr size_t kNumPairs = 10;
51 
SetUp()52   void SetUp() override { multimap_.insert(pairs_.begin(), pairs_.end()); }
53 
TearDown()54   void TearDown() override { multimap_.clear(); }
55 
56   std::array<TestPair, kNumPairs> pairs_ = {{
57       {30, "a"},
58       {50, "b"},
59       {20, "c"},
60       {40, "d"},
61       {10, "e"},
62       {30, "A"},
63       {50, "B"},
64       {20, "C"},
65       {40, "D"},
66       {10, "E"},
67   }};
68 
69   IntrusiveMultiMap multimap_;
70 };
71 
72 // Unit tests.
73 
TEST_F(IntrusiveMultiMapTest,Construct_Default)74 TEST_F(IntrusiveMultiMapTest, Construct_Default) {
75   IntrusiveMultiMap multimap;
76   EXPECT_TRUE(multimap.empty());
77   EXPECT_EQ(multimap.begin(), multimap.end());
78   EXPECT_EQ(multimap.rbegin(), multimap.rend());
79   EXPECT_EQ(multimap.size(), 0U);
80   EXPECT_EQ(multimap.lower_bound(0), multimap.end());
81   EXPECT_EQ(multimap.upper_bound(0), multimap.end());
82 }
83 
TEST_F(IntrusiveMultiMapTest,Construct_ObjectIterators)84 TEST_F(IntrusiveMultiMapTest, Construct_ObjectIterators) {
85   multimap_.clear();
86   IntrusiveMultiMap multimap(pairs_.begin(), pairs_.end());
87   EXPECT_FALSE(multimap.empty());
88   EXPECT_EQ(multimap.size(), pairs_.size());
89   multimap.clear();
90 }
91 
TEST_F(IntrusiveMultiMapTest,Construct_ObjectIterators_Empty)92 TEST_F(IntrusiveMultiMapTest, Construct_ObjectIterators_Empty) {
93   IntrusiveMultiMap multimap(pairs_.end(), pairs_.end());
94   EXPECT_TRUE(multimap.empty());
95   EXPECT_EQ(multimap.size(), 0U);
96 }
97 
TEST_F(IntrusiveMultiMapTest,Construct_PointerIterators)98 TEST_F(IntrusiveMultiMapTest, Construct_PointerIterators) {
99   std::array<TestPair*, 3> ptrs = {&pairs_[0], &pairs_[1], &pairs_[2]};
100   multimap_.clear();
101   IntrusiveMultiMap multimap(ptrs.begin(), ptrs.end());
102   EXPECT_FALSE(multimap.empty());
103   EXPECT_EQ(multimap.size(), 3U);
104   multimap.clear();
105 }
106 
TEST_F(IntrusiveMultiMapTest,Construct_PointerIterators_Empty)107 TEST_F(IntrusiveMultiMapTest, Construct_PointerIterators_Empty) {
108   std::array<TestPair*, 0> ptrs;
109   IntrusiveMultiMap multimap(ptrs.begin(), ptrs.end());
110   EXPECT_TRUE(multimap.empty());
111   EXPECT_EQ(multimap.size(), 0U);
112   multimap.clear();
113 }
114 
TEST_F(IntrusiveMultiMapTest,Construct_InitializerList)115 TEST_F(IntrusiveMultiMapTest, Construct_InitializerList) {
116   multimap_.clear();
117   IntrusiveMultiMap multimap({&pairs_[0], &pairs_[2], &pairs_[4]});
118   auto iter = multimap.begin();
119   EXPECT_EQ((iter++)->key(), 10U);
120   EXPECT_EQ((iter++)->key(), 20U);
121   EXPECT_EQ((iter++)->key(), 30U);
122   EXPECT_EQ(iter, multimap.end());
123   multimap.clear();
124 }
125 
TEST_F(IntrusiveMultiMapTest,Construct_InitializerList_Empty)126 TEST_F(IntrusiveMultiMapTest, Construct_InitializerList_Empty) {
127   IntrusiveMultiMap multimap({});
128   EXPECT_TRUE(multimap.empty());
129   EXPECT_EQ(multimap.size(), 0U);
130 }
131 
TEST_F(IntrusiveMultiMapTest,Construct_CustomCompare)132 TEST_F(IntrusiveMultiMapTest, Construct_CustomCompare) {
133   multimap_.clear();
134   IntrusiveMultiMap multimap({&pairs_[0], &pairs_[2], &pairs_[4]},
135                              std::greater<>());
136   auto iter = multimap.begin();
137   EXPECT_EQ((iter++)->key(), 30U);
138   EXPECT_EQ((iter++)->key(), 20U);
139   EXPECT_EQ((iter++)->key(), 10U);
140   EXPECT_EQ(iter, multimap.end());
141   multimap.clear();
142 }
143 
144 // A map pair that includes a key accessor method.
145 struct HalvedKey : public ::pw::IntrusiveMultiMap<size_t, HalvedKey>::Item,
146                    public BaseItem {
147  private:
148   using MapItem = ::pw::IntrusiveMultiMap<size_t, HalvedKey>::Item;
149 
150  public:
HalvedKey__anond08d356a0111::HalvedKey151   HalvedKey(size_t half_key, const char* name)
152       : BaseItem(name), half_key_(half_key) {}
key__anond08d356a0111::HalvedKey153   size_t key() const { return half_key_ * 2; }
154 
155  private:
156   const size_t half_key_;
157 };
158 
TEST_F(IntrusiveMultiMapTest,Construct_CustomItem)159 TEST_F(IntrusiveMultiMapTest, Construct_CustomItem) {
160   std::array<HalvedKey, 3> items = {{
161       {50, "B"},
162       {40, "D"},
163       {60, "F"},
164   }};
165   pw::IntrusiveMultiMap<size_t, HalvedKey> multimap(items.begin(), items.end());
166 
167   auto iter = multimap.find(80);
168   ASSERT_NE(iter, multimap.end());
169   EXPECT_STREQ(iter->name(), "D");
170 
171   iter = multimap.find(100);
172   ASSERT_NE(iter, multimap.end());
173   EXPECT_STREQ(iter->name(), "B");
174 
175   iter = multimap.find(120);
176   ASSERT_NE(iter, multimap.end());
177   EXPECT_STREQ(iter->name(), "F");
178 
179   multimap.clear();
180 }
181 
182 // A map item that has no explicit key.
183 struct NoKey : public ::pw::IntrusiveMultiMap<size_t, NoKey>::Item,
184                public BaseItem {
185  public:
NoKey__anond08d356a0111::NoKey186   explicit NoKey(const char* name) : BaseItem(name) {}
187 };
188 
189 // A functor to get an implied key from a `NoKey` item.
190 struct GetImpliedKey {
operator ()__anond08d356a0111::GetImpliedKey191   size_t operator()(const NoKey& item) const {
192     return std::strlen(item.name());
193   }
194 };
195 
TEST_F(IntrusiveMultiMapTest,Construct_CustomGetKey)196 TEST_F(IntrusiveMultiMapTest, Construct_CustomGetKey) {
197   std::array<NoKey, 5> items = {
198       NoKey("CC"),
199       NoKey("AAA"),
200       NoKey("AAA"),
201       NoKey("B"),
202       NoKey("DDDD"),
203   };
204   pw::IntrusiveMultiMap<size_t, NoKey> multimap(
205       items.begin(), items.end(), std::less<>(), GetImpliedKey());
206 
207   auto iter = multimap.begin();
208   EXPECT_STREQ((iter++)->name(), "B");
209   EXPECT_STREQ((iter++)->name(), "CC");
210   EXPECT_STREQ((iter++)->name(), "AAA");
211   EXPECT_STREQ((iter++)->name(), "AAA");
212   EXPECT_STREQ((iter++)->name(), "DDDD");
213   multimap.clear();
214 }
215 
216 //  A struct that is not a multimap pair.
217 class NotAnItem : public BaseItem {
218  public:
NotAnItem(const char * name,size_t key)219   NotAnItem(const char* name, size_t key) : BaseItem(name), key_(key) {}
key() const220   size_t key() const { return key_; }
221 
222  private:
223   const size_t key_;
224 };
225 
226 #if PW_NC_TEST(IncompatibleItem)
227 PW_NC_EXPECT(
228     "IntrusiveMultiMap items must be derived from IntrusiveMultiMap<Key, "
229     "T>::Item");
230 
231 struct BadItem : public ::pw::IntrusiveMultiMap<size_t, NotAnItem>::Item {
BadItem__anond08d356a0111::BadItem232   constexpr explicit BadItem(size_t key) : key_(key) {}
key__anond08d356a0111::BadItem233   constexpr size_t key() const { return key_; }
operator <__anond08d356a0111::BadItem234   constexpr bool operator<(const Pair& rhs) { return key_ < rhs.key(); }
235 
236  private:
237   const size_t key_;
238 };
239 
240 [[maybe_unused]] ::pw::IntrusiveMultiMap<size_t, BadItem> bad_multimap1;
241 
242 #elif PW_NC_TEST(DoesNotInheritFromItem)
243 PW_NC_EXPECT(
244     "IntrusiveMultiMap items must be derived from IntrusiveMultiMap<Key, "
245     "T>::Item");
246 
247 [[maybe_unused]] ::pw::IntrusiveMultiMap<size_t, NotAnItem> bad_multimap2;
248 
249 #endif  // PW_NC_TEST
250 
251 // Iterators
252 
TEST_F(IntrusiveMultiMapTest,Iterator)253 TEST_F(IntrusiveMultiMapTest, Iterator) {
254   const IntrusiveMultiMap& multimap = multimap_;
255   auto iter = multimap.begin();
256   size_t key = 10;
257   for (size_t i = 0; i < kNumPairs; i += 2) {
258     EXPECT_EQ((*iter++).key(), key);
259     EXPECT_EQ((*iter++).key(), key);
260     key += 10;
261   }
262   EXPECT_EQ(key, 60U);
263   EXPECT_EQ(iter, multimap.end());
264   EXPECT_EQ(iter, multimap.cend());
265   for (size_t i = 0; i < kNumPairs; i += 2) {
266     key -= 10;
267     EXPECT_EQ((--iter)->key(), key);
268     EXPECT_EQ((--iter)->key(), key);
269   }
270   EXPECT_EQ(key, 10U);
271   EXPECT_EQ(iter, multimap.begin());
272   EXPECT_EQ(iter, multimap.cbegin());
273 }
274 
TEST_F(IntrusiveMultiMapTest,ReverseIterator)275 TEST_F(IntrusiveMultiMapTest, ReverseIterator) {
276   const IntrusiveMultiMap& multimap = multimap_;
277   auto iter = multimap.rbegin();
278   size_t key = 50;
279   for (size_t i = 0; i < kNumPairs; i += 2) {
280     EXPECT_EQ((*iter++).key(), key);
281     EXPECT_EQ((*iter++).key(), key);
282     key -= 10;
283   }
284   EXPECT_EQ(key, 0U);
285   EXPECT_EQ(iter, multimap.rend());
286   EXPECT_EQ(iter, multimap.crend());
287   for (size_t i = 0; i < kNumPairs; i += 2) {
288     key += 10;
289     EXPECT_EQ((--iter)->key(), key);
290     EXPECT_EQ((--iter)->key(), key);
291   }
292   EXPECT_EQ(key, 50U);
293   EXPECT_EQ(iter, multimap.rbegin());
294   EXPECT_EQ(iter, multimap.crbegin());
295 }
296 
TEST_F(IntrusiveMultiMapTest,ConstIterator_CompareNonConst)297 TEST_F(IntrusiveMultiMapTest, ConstIterator_CompareNonConst) {
298   EXPECT_EQ(multimap_.end(), multimap_.cend());
299 }
300 
301 // A multimap pair that is distinct from TestPair
302 class OtherPair : public ::pw::IntrusiveMultiMap<size_t, OtherPair>::Pair,
303                   public BaseItem {
304  private:
305   using Pair = ::pw::IntrusiveMultiMap<size_t, OtherPair>::Pair;
306 
307  public:
OtherPair(size_t key,const char * name)308   OtherPair(size_t key, const char* name) : Pair(key), BaseItem(name) {}
309 };
310 
TEST_F(IntrusiveMultiMapTest,ConstIterator_CompareNonConst_CompilationFails)311 TEST_F(IntrusiveMultiMapTest, ConstIterator_CompareNonConst_CompilationFails) {
312   ::pw::IntrusiveMultiMap<size_t, OtherPair> multimap;
313 #if PW_NC_TEST(CannotCompareIncompatibleIteratorsEqual)
314   PW_NC_EXPECT("multimap_\.end\(\) == multimap\.end\(\)");
315   static_cast<void>(multimap_.end() == multimap.end());
316 #elif PW_NC_TEST(CannotCompareIncompatibleIteratorsInequal)
317   PW_NC_EXPECT("multimap_\.end\(\) != multimap\.end\(\)");
318   static_cast<void>(multimap_.end() != multimap.end());
319 #endif  // PW_NC_TEST
320 }
321 
322 #if PW_NC_TEST(CannotModifyThroughConstIterator)
323 PW_NC_EXPECT("function is not marked const|discards qualifiers");
324 
TEST_F(IntrusiveMultiMapTest,ConstIterator_Modify)325 TEST_F(IntrusiveMultiMapTest, ConstIterator_Modify) {
326   const IntrusiveMultiMap& multimap = multimap_;
327   auto iter = multimap.begin();
328   iter->set_name("nope");
329 }
330 
331 #endif  // PW_NC_TEST
332 
333 // Capacity
334 
TEST_F(IntrusiveMultiMapTest,IsEmpty)335 TEST_F(IntrusiveMultiMapTest, IsEmpty) {
336   const IntrusiveMultiMap& multimap = multimap_;
337   EXPECT_FALSE(multimap.empty());
338   multimap_.clear();
339   EXPECT_TRUE(multimap.empty());
340 }
341 
TEST_F(IntrusiveMultiMapTest,GetSize)342 TEST_F(IntrusiveMultiMapTest, GetSize) {
343   const IntrusiveMultiMap& multimap = multimap_;
344   EXPECT_EQ(multimap.size(), kNumPairs);
345   multimap_.clear();
346   EXPECT_EQ(multimap.size(), 0U);
347 }
348 
TEST_F(IntrusiveMultiMapTest,GetMaxSize)349 TEST_F(IntrusiveMultiMapTest, GetMaxSize) {
350   const IntrusiveMultiMap& multimap = multimap_;
351   EXPECT_EQ(multimap.max_size(), size_t(std::numeric_limits<ptrdiff_t>::max()));
352 }
353 
354 // Modifiers
355 
356 // This functions allows tests to use `std::is_sorted` without specializing
357 // `std::less<TestPair>`. Since `std::less` is the default value for the
358 // `Compare` template parameter, leaving it untouched avoids accidentally
359 // masking type-handling errors.
LessThan(const TestPair & lhs,const TestPair & rhs)360 constexpr bool LessThan(const TestPair& lhs, const TestPair& rhs) {
361   return lhs.key() < rhs.key();
362 }
363 
TEST_F(IntrusiveMultiMapTest,Insert)364 TEST_F(IntrusiveMultiMapTest, Insert) {
365   multimap_.clear();
366   bool sorted = true;
367   size_t prev_key = 0;
368   for (auto& pair : pairs_) {
369     sorted &= prev_key < pair.key();
370 
371     // Use the "hinted" version of insert.
372     multimap_.insert(multimap_.end(), pair);
373     prev_key = pair.key();
374   }
375   EXPECT_FALSE(sorted);
376 
377   EXPECT_EQ(multimap_.size(), kNumPairs);
378   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
379 }
380 
TEST_F(IntrusiveMultiMapTest,Insert_Duplicate)381 TEST_F(IntrusiveMultiMapTest, Insert_Duplicate) {
382   TestPair pair1(60, "1");
383   TestPair pair2(60, "2");
384 
385   auto iter = multimap_.insert(pair1);
386   EXPECT_STREQ(iter->name(), "1");
387 
388   iter = multimap_.insert(pair2);
389   EXPECT_STREQ(iter->name(), "2");
390 
391   EXPECT_EQ(multimap_.size(), kNumPairs + 2);
392   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
393 
394   // Explicitly clear the multimap before pair 1 goes out of scope.
395   multimap_.clear();
396 }
397 
TEST_F(IntrusiveMultiMapTest,Insert_ObjectIterators)398 TEST_F(IntrusiveMultiMapTest, Insert_ObjectIterators) {
399   multimap_.clear();
400   multimap_.insert(pairs_.begin(), pairs_.end());
401   EXPECT_EQ(multimap_.size(), kNumPairs);
402   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
403 }
404 
TEST_F(IntrusiveMultiMapTest,Insert_ObjectIterators_Empty)405 TEST_F(IntrusiveMultiMapTest, Insert_ObjectIterators_Empty) {
406   multimap_.insert(pairs_.end(), pairs_.end());
407   EXPECT_EQ(multimap_.size(), kNumPairs);
408   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
409 }
410 
TEST_F(IntrusiveMultiMapTest,Insert_ObjectIterators_WithDuplicates)411 TEST_F(IntrusiveMultiMapTest, Insert_ObjectIterators_WithDuplicates) {
412   std::array<TestPair, 3> pairs = {{
413       {50, "B"},
414       {40, "D"},
415       {60, "F"},
416   }};
417 
418   multimap_.insert(pairs.begin(), pairs.end());
419   EXPECT_EQ(multimap_.size(), kNumPairs + 3);
420   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
421 
422   auto iter = multimap_.find(40);
423   ASSERT_NE(iter, multimap_.end());
424   EXPECT_STREQ((iter++)->name(), "d");
425   EXPECT_STREQ(iter->name(), "D");
426 
427   iter = multimap_.find(50);
428   ASSERT_NE(iter, multimap_.end());
429   EXPECT_STREQ((iter++)->name(), "b");
430   EXPECT_STREQ(iter->name(), "B");
431 
432   iter = multimap_.find(60);
433   ASSERT_NE(iter, multimap_.end());
434   EXPECT_STREQ(iter->name(), "F");
435 
436   // Explicitly clear the multimap before pairs goes out of scope.
437   multimap_.clear();
438 }
439 
TEST_F(IntrusiveMultiMapTest,Insert_PointerIterators)440 TEST_F(IntrusiveMultiMapTest, Insert_PointerIterators) {
441   multimap_.clear();
442   std::array<TestPair*, 3> ptrs = {&pairs_[0], &pairs_[1], &pairs_[2]};
443 
444   multimap_.insert(ptrs.begin(), ptrs.end());
445   EXPECT_EQ(multimap_.size(), 3U);
446   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
447 }
448 
TEST_F(IntrusiveMultiMapTest,Insert_PointerIterators_Empty)449 TEST_F(IntrusiveMultiMapTest, Insert_PointerIterators_Empty) {
450   std::array<TestPair*, 0> ptrs;
451 
452   multimap_.insert(ptrs.begin(), ptrs.end());
453   EXPECT_EQ(multimap_.size(), kNumPairs);
454   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
455 }
456 
TEST_F(IntrusiveMultiMapTest,Insert_PointerIterators_WithDuplicates)457 TEST_F(IntrusiveMultiMapTest, Insert_PointerIterators_WithDuplicates) {
458   TestPair pair1(50, "B");
459   TestPair pair2(40, "D");
460   TestPair pair3(60, "F");
461   std::array<TestPair*, 3> ptrs = {&pair1, &pair2, &pair3};
462 
463   multimap_.insert(ptrs.begin(), ptrs.end());
464   EXPECT_EQ(multimap_.size(), kNumPairs + 3);
465   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
466 
467   auto iter = multimap_.find(40);
468   ASSERT_NE(iter, multimap_.end());
469   EXPECT_STREQ((iter++)->name(), "d");
470   EXPECT_STREQ(iter->name(), "D");
471 
472   iter = multimap_.find(50);
473   ASSERT_NE(iter, multimap_.end());
474   EXPECT_STREQ((iter++)->name(), "b");
475   EXPECT_STREQ(iter->name(), "B");
476 
477   iter = multimap_.find(60);
478   ASSERT_NE(iter, multimap_.end());
479   EXPECT_STREQ(iter->name(), "F");
480 
481   // Explicitly clear the multimap before pairs goes out of scope.
482   multimap_.clear();
483 }
484 
TEST_F(IntrusiveMultiMapTest,Insert_InitializerList)485 TEST_F(IntrusiveMultiMapTest, Insert_InitializerList) {
486   multimap_.clear();
487   multimap_.insert({&pairs_[0], &pairs_[2], &pairs_[4]});
488   EXPECT_EQ(multimap_.size(), 3U);
489   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
490 }
491 
TEST_F(IntrusiveMultiMapTest,Insert_InitializerList_Empty)492 TEST_F(IntrusiveMultiMapTest, Insert_InitializerList_Empty) {
493   multimap_.insert({});
494   EXPECT_EQ(multimap_.size(), kNumPairs);
495   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
496 }
497 
TEST_F(IntrusiveMultiMapTest,Insert_InitializerList_WithDuplicates)498 TEST_F(IntrusiveMultiMapTest, Insert_InitializerList_WithDuplicates) {
499   TestPair pair1(50, "B");
500   TestPair pair2(40, "D");
501   TestPair pair3(60, "F");
502 
503   multimap_.insert({&pair1, &pair2, &pair3});
504   EXPECT_EQ(multimap_.size(), kNumPairs + 3);
505   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
506 
507   auto iter = multimap_.find(40);
508   ASSERT_NE(iter, multimap_.end());
509   EXPECT_STREQ((iter++)->name(), "d");
510   EXPECT_STREQ(iter->name(), "D");
511 
512   iter = multimap_.find(50);
513   ASSERT_NE(iter, multimap_.end());
514   EXPECT_STREQ((iter++)->name(), "b");
515   EXPECT_STREQ(iter->name(), "B");
516 
517   iter = multimap_.find(60);
518   ASSERT_NE(iter, multimap_.end());
519   EXPECT_STREQ(iter->name(), "F");
520 
521   // Explicitly clear the multimap before pairs goes out of scope.
522   multimap_.clear();
523 }
524 
525 // A pair derived from TestPair.
526 struct DerivedPair : public TestPair {
DerivedPair__anond08d356a0111::DerivedPair527   DerivedPair(size_t n, const char* name) : TestPair(n * 10, name) {}
528 };
529 
TEST_F(IntrusiveMultiMapTest,Insert_DerivedPairs)530 TEST_F(IntrusiveMultiMapTest, Insert_DerivedPairs) {
531   DerivedPair pair1(6, "f");
532   multimap_.insert(pair1);
533 
534   DerivedPair pair2(7, "g");
535   multimap_.insert(pair2);
536 
537   EXPECT_EQ(multimap_.size(), kNumPairs + 2);
538   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
539 
540   // Explicitly clear the multimap before pairs goes out of scope.
541   multimap_.clear();
542 }
543 
TEST_F(IntrusiveMultiMapTest,Insert_DerivedPairs_CompilationFails)544 TEST_F(IntrusiveMultiMapTest, Insert_DerivedPairs_CompilationFails) {
545   ::pw::IntrusiveMultiMap<size_t, DerivedPair>
546       derived_from_compatible_pair_type;
547 
548   DerivedPair pair1(6, "f");
549   derived_from_compatible_pair_type.insert(pair1);
550 
551   EXPECT_EQ(derived_from_compatible_pair_type.size(), 1U);
552 
553 #if PW_NC_TEST(CannotAddBaseClassToDerivedClassMap)
554   PW_NC_EXPECT("derived_from_compatible_pair_type\.insert\(pair2\)");
555 
556   TestPair pair2(70, "g");
557   derived_from_compatible_pair_type.insert(pair2);
558 #endif
559   derived_from_compatible_pair_type.clear();
560 }
561 
TEST_F(IntrusiveMultiMapTest,Erase_One_ByItem)562 TEST_F(IntrusiveMultiMapTest, Erase_One_ByItem) {
563   for (size_t i = 0; i < kNumPairs; ++i) {
564     EXPECT_EQ(multimap_.size(), kNumPairs);
565     auto iter = multimap_.erase(pairs_[i]);
566     if (iter != multimap_.end()) {
567       EXPECT_GE(iter->key(), pairs_[i].key());
568     }
569     EXPECT_EQ(multimap_.size(), kNumPairs - 1);
570     multimap_.insert(pairs_[i]);
571   }
572 }
573 
TEST_F(IntrusiveMultiMapTest,Erase_Two_ByKey)574 TEST_F(IntrusiveMultiMapTest, Erase_Two_ByKey) {
575   constexpr size_t kHalf = kNumPairs / 2;
576   for (size_t i = 0; i < kHalf; ++i) {
577     ASSERT_EQ(pairs_[i].key(), pairs_[i + kHalf].key());
578     EXPECT_EQ(multimap_.size(), kNumPairs);
579     EXPECT_EQ(multimap_.erase(pairs_[i].key()), 2U);
580     EXPECT_EQ(multimap_.size(), kNumPairs - 2);
581     auto iter = multimap_.find(pairs_[i].key());
582     EXPECT_EQ(iter, multimap_.end());
583     multimap_.insert(pairs_[i]);
584     multimap_.insert(pairs_[i + kHalf]);
585   }
586 }
587 
TEST_F(IntrusiveMultiMapTest,Erase_OnlyItem)588 TEST_F(IntrusiveMultiMapTest, Erase_OnlyItem) {
589   multimap_.clear();
590   multimap_.insert(pairs_[0]);
591   EXPECT_EQ(multimap_.size(), 1U);
592 
593   EXPECT_EQ(multimap_.erase(pairs_[0].key()), 1U);
594   EXPECT_EQ(multimap_.size(), 0U);
595 }
596 
TEST_F(IntrusiveMultiMapTest,Erase_AllOnebyOne)597 TEST_F(IntrusiveMultiMapTest, Erase_AllOnebyOne) {
598   auto iter = multimap_.begin();
599   for (size_t n = kNumPairs; n != 0; --n) {
600     ASSERT_NE(iter, multimap_.end());
601     iter = multimap_.erase(iter);
602   }
603   EXPECT_EQ(iter, multimap_.end());
604   EXPECT_EQ(multimap_.size(), 0U);
605 }
606 
TEST_F(IntrusiveMultiMapTest,Erase_Range)607 TEST_F(IntrusiveMultiMapTest, Erase_Range) {
608   auto first = multimap_.begin();
609   auto last = multimap_.end();
610   ++first;
611   --last;
612   auto iter = multimap_.erase(first, last);
613   EXPECT_EQ(multimap_.size(), 2U);
614   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
615   EXPECT_EQ(iter->key(), 50U);
616 }
617 
TEST_F(IntrusiveMultiMapTest,Erase_MissingItem)618 TEST_F(IntrusiveMultiMapTest, Erase_MissingItem) {
619   EXPECT_EQ(multimap_.erase(100), 0U);
620 }
621 
TEST_F(IntrusiveMultiMapTest,Erase_Reinsert)622 TEST_F(IntrusiveMultiMapTest, Erase_Reinsert) {
623   constexpr size_t kHalf = kNumPairs / 2;
624   EXPECT_EQ(multimap_.size(), pairs_.size());
625 
626   ASSERT_EQ(pairs_[0].key(), pairs_[0 + kHalf].key());
627   EXPECT_EQ(multimap_.erase(pairs_[0].key()), 2U);
628   EXPECT_EQ(multimap_.find(pairs_[0].key()), multimap_.end());
629 
630   ASSERT_EQ(pairs_[2].key(), pairs_[2 + kHalf].key());
631   EXPECT_EQ(multimap_.erase(pairs_[2].key()), 2U);
632   EXPECT_EQ(multimap_.find(pairs_[2].key()), multimap_.end());
633 
634   ASSERT_EQ(pairs_[4].key(), pairs_[4 + kHalf].key());
635   EXPECT_EQ(multimap_.erase(pairs_[4].key()), 2U);
636   EXPECT_EQ(multimap_.find(pairs_[4].key()), multimap_.end());
637 
638   EXPECT_EQ(multimap_.size(), pairs_.size() - 6);
639 
640   multimap_.insert(pairs_[4]);
641   auto iter = multimap_.find(pairs_[4].key());
642   EXPECT_NE(iter, multimap_.end());
643 
644   multimap_.insert(pairs_[0]);
645   iter = multimap_.find(pairs_[0].key());
646   EXPECT_NE(iter, multimap_.end());
647 
648   multimap_.insert(pairs_[2]);
649   iter = multimap_.find(pairs_[2].key());
650   EXPECT_NE(iter, multimap_.end());
651 
652   EXPECT_EQ(multimap_.size(), pairs_.size() - 3);
653 }
654 
TEST_F(IntrusiveMultiMapTest,Erase_Duplicate)655 TEST_F(IntrusiveMultiMapTest, Erase_Duplicate) {
656   TestPair pair1(32, "1");
657   TestPair pair2(32, "2");
658   TestPair pair3(32, "3");
659   multimap_.insert(pair1);
660   multimap_.insert(pair2);
661   multimap_.insert(pair3);
662 
663   auto iter = multimap_.find(32);
664   ASSERT_NE(iter, multimap_.end());
665   EXPECT_STREQ(iter->name(), "1");
666 
667   iter = multimap_.erase(iter);
668   ASSERT_NE(iter, multimap_.end());
669   EXPECT_STREQ(iter->name(), "2");
670 
671   iter = multimap_.erase(iter);
672   ASSERT_NE(iter, multimap_.end());
673   EXPECT_STREQ(iter->name(), "3");
674 
675   multimap_.erase(iter);
676   EXPECT_EQ(multimap_.find(32), multimap_.end());
677 }
678 
TEST_F(IntrusiveMultiMapTest,Swap)679 TEST_F(IntrusiveMultiMapTest, Swap) {
680   std::array<TestPair, 3> pairs = {{
681       {50, "B"},
682       {40, "D"},
683       {60, "F"},
684   }};
685   IntrusiveMultiMap multimap(pairs.begin(), pairs.end());
686 
687   multimap_.swap(multimap);
688   EXPECT_EQ(multimap.size(), kNumPairs);
689   EXPECT_TRUE(std::is_sorted(multimap.begin(), multimap.end(), LessThan));
690   auto iter = multimap.begin();
691   EXPECT_STREQ((iter++)->name(), "e");
692   EXPECT_STREQ((iter++)->name(), "E");
693   EXPECT_STREQ((iter++)->name(), "c");
694   EXPECT_STREQ((iter++)->name(), "C");
695   EXPECT_STREQ((iter++)->name(), "a");
696   EXPECT_STREQ((iter++)->name(), "A");
697   EXPECT_STREQ((iter++)->name(), "d");
698   EXPECT_STREQ((iter++)->name(), "D");
699   EXPECT_STREQ((iter++)->name(), "b");
700   EXPECT_STREQ((iter++)->name(), "B");
701   EXPECT_EQ(iter, multimap.end());
702   multimap.clear();
703 
704   EXPECT_EQ(multimap_.size(), 3U);
705   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
706   iter = multimap_.begin();
707   EXPECT_STREQ((iter++)->name(), "D");
708   EXPECT_STREQ((iter++)->name(), "B");
709   EXPECT_STREQ((iter++)->name(), "F");
710   EXPECT_EQ(iter, multimap_.end());
711 
712   // Explicitly clear the multimap before pairs goes out of scope.
713   multimap_.clear();
714 }
715 
TEST_F(IntrusiveMultiMapTest,Swap_Empty)716 TEST_F(IntrusiveMultiMapTest, Swap_Empty) {
717   IntrusiveMultiMap multimap;
718 
719   multimap_.swap(multimap);
720   EXPECT_EQ(multimap.size(), kNumPairs);
721   EXPECT_TRUE(std::is_sorted(multimap.begin(), multimap.end(), LessThan));
722   auto iter = multimap.begin();
723   EXPECT_STREQ((iter++)->name(), "e");
724   EXPECT_STREQ((iter++)->name(), "E");
725   EXPECT_STREQ((iter++)->name(), "c");
726   EXPECT_STREQ((iter++)->name(), "C");
727   EXPECT_STREQ((iter++)->name(), "a");
728   EXPECT_STREQ((iter++)->name(), "A");
729   EXPECT_STREQ((iter++)->name(), "d");
730   EXPECT_STREQ((iter++)->name(), "D");
731   EXPECT_STREQ((iter++)->name(), "b");
732   EXPECT_STREQ((iter++)->name(), "B");
733   EXPECT_EQ(iter, multimap.end());
734   multimap.clear();
735 
736   EXPECT_EQ(multimap_.size(), 0U);
737 }
738 
TEST_F(IntrusiveMultiMapTest,Merge)739 TEST_F(IntrusiveMultiMapTest, Merge) {
740   std::array<TestPair, 3> pairs = {{
741       {5, "f"},
742       {75, "g"},
743       {85, "h"},
744   }};
745   IntrusiveMultiMap multimap(pairs.begin(), pairs.end());
746 
747   multimap_.merge(multimap);
748   EXPECT_TRUE(multimap.empty());
749   EXPECT_EQ(multimap_.size(), kNumPairs + 3);
750   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
751   auto iter = multimap_.begin();
752   EXPECT_STREQ((iter++)->name(), "f");
753   EXPECT_STREQ((iter++)->name(), "e");
754   EXPECT_STREQ((iter++)->name(), "E");
755   EXPECT_STREQ((iter++)->name(), "c");
756   EXPECT_STREQ((iter++)->name(), "C");
757   EXPECT_STREQ((iter++)->name(), "a");
758   EXPECT_STREQ((iter++)->name(), "A");
759   EXPECT_STREQ((iter++)->name(), "d");
760   EXPECT_STREQ((iter++)->name(), "D");
761   EXPECT_STREQ((iter++)->name(), "b");
762   EXPECT_STREQ((iter++)->name(), "B");
763   EXPECT_STREQ((iter++)->name(), "g");
764   EXPECT_STREQ((iter++)->name(), "h");
765   EXPECT_EQ(iter, multimap_.end());
766 
767   // Explicitly clear the multimap before pairs goes out of scope.
768   multimap_.clear();
769 }
770 
TEST_F(IntrusiveMultiMapTest,Merge_Empty)771 TEST_F(IntrusiveMultiMapTest, Merge_Empty) {
772   IntrusiveMultiMap multimap;
773 
774   multimap_.merge(multimap);
775   EXPECT_EQ(multimap_.size(), kNumPairs);
776   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
777 
778   multimap.merge(multimap_);
779   EXPECT_TRUE(multimap_.empty());
780   EXPECT_EQ(multimap.size(), kNumPairs);
781   EXPECT_TRUE(std::is_sorted(multimap.begin(), multimap.end(), LessThan));
782 
783   multimap.clear();
784 }
785 
TEST_F(IntrusiveMultiMapTest,Merge_WithDuplicates)786 TEST_F(IntrusiveMultiMapTest, Merge_WithDuplicates) {
787   std::array<TestPair, 3> pairs = {{
788       {15, "f"},
789       {45, "g"},
790       {55, "h"},
791   }};
792   IntrusiveMultiMap multimap(pairs.begin(), pairs.end());
793 
794   multimap_.merge(multimap);
795   EXPECT_TRUE(multimap.empty());
796   EXPECT_EQ(multimap_.size(), kNumPairs + 3);
797   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
798   auto iter = multimap_.begin();
799   EXPECT_STREQ((iter++)->name(), "e");
800   EXPECT_STREQ((iter++)->name(), "E");
801   EXPECT_STREQ((iter++)->name(), "f");
802   EXPECT_STREQ((iter++)->name(), "c");
803   EXPECT_STREQ((iter++)->name(), "C");
804   EXPECT_STREQ((iter++)->name(), "a");
805   EXPECT_STREQ((iter++)->name(), "A");
806   EXPECT_STREQ((iter++)->name(), "d");
807   EXPECT_STREQ((iter++)->name(), "D");
808   EXPECT_STREQ((iter++)->name(), "g");
809   EXPECT_STREQ((iter++)->name(), "b");
810   EXPECT_STREQ((iter++)->name(), "B");
811   EXPECT_STREQ((iter++)->name(), "h");
812   EXPECT_EQ(iter, multimap_.end());
813 
814   // Explicitly clear the multimap before pairs goes out of scope.
815   multimap_.clear();
816 }
817 
TEST_F(IntrusiveMultiMapTest,Merge_Map)818 TEST_F(IntrusiveMultiMapTest, Merge_Map) {
819   std::array<TestPair, 3> pairs = {{
820       {15, "f"},
821       {45, "g"},
822       {55, "h"},
823   }};
824   ::pw::IntrusiveMap<size_t, TestPair> map(pairs.begin(), pairs.end());
825 
826   multimap_.merge(map);
827   EXPECT_TRUE(map.empty());
828   EXPECT_EQ(multimap_.size(), kNumPairs + 3);
829   EXPECT_TRUE(std::is_sorted(multimap_.begin(), multimap_.end(), LessThan));
830   auto iter = multimap_.begin();
831   EXPECT_STREQ((iter++)->name(), "e");
832   EXPECT_STREQ((iter++)->name(), "E");
833   EXPECT_STREQ((iter++)->name(), "f");
834   EXPECT_STREQ((iter++)->name(), "c");
835   EXPECT_STREQ((iter++)->name(), "C");
836   EXPECT_STREQ((iter++)->name(), "a");
837   EXPECT_STREQ((iter++)->name(), "A");
838   EXPECT_STREQ((iter++)->name(), "d");
839   EXPECT_STREQ((iter++)->name(), "D");
840   EXPECT_STREQ((iter++)->name(), "g");
841   EXPECT_STREQ((iter++)->name(), "b");
842   EXPECT_STREQ((iter++)->name(), "B");
843   EXPECT_STREQ((iter++)->name(), "h");
844   EXPECT_EQ(iter, multimap_.end());
845 
846   // Explicitly clear the multimap before pairs goes out of scope.
847   multimap_.clear();
848 }
849 
TEST_F(IntrusiveMultiMapTest,Count)850 TEST_F(IntrusiveMultiMapTest, Count) {
851   std::array<TestPair, 3> pairs = {{
852       {50, "B"},
853       {40, "D"},
854       {60, "F"},
855   }};
856   multimap_.insert(pairs.begin(), pairs.end());
857 
858   const IntrusiveMultiMap& multimap = multimap_;
859   EXPECT_EQ(multimap.count(10), 2U);
860   EXPECT_EQ(multimap.count(20), 2U);
861   EXPECT_EQ(multimap.count(30), 2U);
862   EXPECT_EQ(multimap.count(40), 3U);
863   EXPECT_EQ(multimap.count(50), 3U);
864   EXPECT_EQ(multimap.count(60), 1U);
865 
866   // Explicitly clear the multimap before pairs goes out of scope.
867   multimap_.clear();
868 }
869 
TEST_F(IntrusiveMultiMapTest,Count_NoSuchKey)870 TEST_F(IntrusiveMultiMapTest, Count_NoSuchKey) {
871   const IntrusiveMultiMap& multimap = multimap_;
872   EXPECT_EQ(multimap.count(60), 0U);
873 }
874 
TEST_F(IntrusiveMultiMapTest,Find)875 TEST_F(IntrusiveMultiMapTest, Find) {
876   const IntrusiveMultiMap& multimap = multimap_;
877   size_t key = 10;
878   for (size_t i = 0; i < kNumPairs; i += 2) {
879     auto iter = multimap.find(key);
880     ASSERT_NE(iter, multimap.end());
881     EXPECT_EQ(iter->key(), key);
882     key += 10;
883   }
884 }
885 
TEST_F(IntrusiveMultiMapTest,Find_NoSuchKey)886 TEST_F(IntrusiveMultiMapTest, Find_NoSuchKey) {
887   const IntrusiveMultiMap& multimap = multimap_;
888   auto iter = multimap.find(60);
889   EXPECT_EQ(iter, multimap.end());
890 }
891 
TEST_F(IntrusiveMultiMapTest,Find_WithDuplicates)892 TEST_F(IntrusiveMultiMapTest, Find_WithDuplicates) {
893   std::array<TestPair, 3> pairs = {{
894       {50, "B"},
895       {40, "D"},
896       {60, "F"},
897   }};
898   multimap_.insert(pairs.begin(), pairs.end());
899 
900   auto iter = multimap_.find(40);
901   ASSERT_NE(iter, multimap_.end());
902   EXPECT_EQ(iter->key(), 40U);
903   EXPECT_EQ((iter++)->name(), "d");
904   EXPECT_EQ(iter->key(), 40U);
905   EXPECT_EQ(iter->name(), "D");
906 
907   iter = multimap_.find(50);
908   ASSERT_NE(iter, multimap_.end());
909   EXPECT_EQ(iter->key(), 50U);
910   EXPECT_EQ((iter++)->name(), "b");
911   EXPECT_EQ(iter->key(), 50U);
912   EXPECT_EQ(iter->name(), "B");
913 
914   // Explicitly clear the multimap before pairs goes out of scope.
915   multimap_.clear();
916 }
917 
TEST_F(IntrusiveMultiMapTest,LowerBound)918 TEST_F(IntrusiveMultiMapTest, LowerBound) {
919   const IntrusiveMultiMap& multimap = multimap_;
920   auto iter = multimap.lower_bound(10);
921   ASSERT_NE(iter, multimap.end());
922   EXPECT_STREQ(iter->name(), "e");
923 
924   iter = multimap.lower_bound(20);
925   ASSERT_NE(iter, multimap.end());
926   EXPECT_STREQ(iter->name(), "c");
927 
928   iter = multimap.lower_bound(30);
929   ASSERT_NE(iter, multimap.end());
930   EXPECT_STREQ(iter->name(), "a");
931 
932   iter = multimap.lower_bound(40);
933   ASSERT_NE(iter, multimap.end());
934   EXPECT_STREQ(iter->name(), "d");
935 
936   iter = multimap.lower_bound(50);
937   ASSERT_NE(iter, multimap.end());
938   EXPECT_STREQ(iter->name(), "b");
939 }
940 
TEST_F(IntrusiveMultiMapTest,LowerBound_NoExactKey)941 TEST_F(IntrusiveMultiMapTest, LowerBound_NoExactKey) {
942   const IntrusiveMultiMap& multimap = multimap_;
943   auto iter = multimap.lower_bound(5);
944   ASSERT_NE(iter, multimap.end());
945   EXPECT_STREQ(iter->name(), "e");
946 
947   iter = multimap.lower_bound(15);
948   ASSERT_NE(iter, multimap.end());
949   EXPECT_STREQ(iter->name(), "c");
950 
951   iter = multimap.lower_bound(25);
952   ASSERT_NE(iter, multimap.end());
953   EXPECT_STREQ(iter->name(), "a");
954 
955   iter = multimap.lower_bound(35);
956   ASSERT_NE(iter, multimap.end());
957   EXPECT_STREQ(iter->name(), "d");
958 
959   iter = multimap.lower_bound(45);
960   ASSERT_NE(iter, multimap.end());
961   EXPECT_STREQ(iter->name(), "b");
962 }
963 
TEST_F(IntrusiveMultiMapTest,LowerBound_OutOfRange)964 TEST_F(IntrusiveMultiMapTest, LowerBound_OutOfRange) {
965   const IntrusiveMultiMap& multimap = multimap_;
966   EXPECT_EQ(multimap.lower_bound(55), multimap.end());
967 }
968 
TEST_F(IntrusiveMultiMapTest,UpperBound)969 TEST_F(IntrusiveMultiMapTest, UpperBound) {
970   const IntrusiveMultiMap& multimap = multimap_;
971   auto iter = multimap.upper_bound(15);
972   ASSERT_NE(iter, multimap.end());
973   EXPECT_STREQ(iter->name(), "c");
974 
975   iter = multimap.upper_bound(25);
976   ASSERT_NE(iter, multimap.end());
977   EXPECT_STREQ(iter->name(), "a");
978 
979   iter = multimap.upper_bound(35);
980   ASSERT_NE(iter, multimap.end());
981   EXPECT_STREQ(iter->name(), "d");
982 
983   iter = multimap.upper_bound(45);
984   ASSERT_NE(iter, multimap.end());
985   EXPECT_STREQ(iter->name(), "b");
986 
987   EXPECT_EQ(multimap.upper_bound(55), multimap.end());
988 }
989 
TEST_F(IntrusiveMultiMapTest,UpperBound_NoExactKey)990 TEST_F(IntrusiveMultiMapTest, UpperBound_NoExactKey) {
991   const IntrusiveMultiMap& multimap = multimap_;
992   auto iter = multimap.upper_bound(5);
993   ASSERT_NE(iter, multimap.end());
994   EXPECT_STREQ(iter->name(), "e");
995 
996   iter = multimap.upper_bound(15);
997   ASSERT_NE(iter, multimap.end());
998   EXPECT_STREQ(iter->name(), "c");
999 
1000   iter = multimap.upper_bound(25);
1001   ASSERT_NE(iter, multimap.end());
1002   EXPECT_STREQ(iter->name(), "a");
1003 
1004   iter = multimap.upper_bound(35);
1005   ASSERT_NE(iter, multimap.end());
1006   EXPECT_STREQ(iter->name(), "d");
1007 
1008   iter = multimap.upper_bound(45);
1009   ASSERT_NE(iter, multimap.end());
1010   EXPECT_STREQ(iter->name(), "b");
1011 }
1012 
TEST_F(IntrusiveMultiMapTest,UpperBound_OutOfRange)1013 TEST_F(IntrusiveMultiMapTest, UpperBound_OutOfRange) {
1014   const IntrusiveMultiMap& multimap = multimap_;
1015   EXPECT_EQ(multimap.upper_bound(55), multimap.end());
1016 }
1017 
TEST_F(IntrusiveMultiMapTest,EqualRange)1018 TEST_F(IntrusiveMultiMapTest, EqualRange) {
1019   const IntrusiveMultiMap& multimap = multimap_;
1020 
1021   auto pair = multimap.equal_range(10);
1022   IntrusiveMultiMap::const_iterator lower = pair.first;
1023   IntrusiveMultiMap::const_iterator upper = pair.second;
1024   ASSERT_NE(lower, multimap.end());
1025   EXPECT_STREQ(lower->name(), "e");
1026   ASSERT_NE(upper, multimap.end());
1027   EXPECT_STREQ(upper->name(), "c");
1028   EXPECT_EQ(std::distance(lower, upper), 2);
1029 
1030   std::tie(lower, upper) = multimap.equal_range(20);
1031   ASSERT_NE(lower, multimap.end());
1032   EXPECT_STREQ(lower->name(), "c");
1033   ASSERT_NE(upper, multimap.end());
1034   EXPECT_STREQ(upper->name(), "a");
1035   EXPECT_EQ(std::distance(lower, upper), 2);
1036 
1037   std::tie(lower, upper) = multimap.equal_range(30);
1038   ASSERT_NE(lower, multimap.end());
1039   EXPECT_STREQ(lower->name(), "a");
1040   ASSERT_NE(upper, multimap.end());
1041   EXPECT_STREQ(upper->name(), "d");
1042   EXPECT_EQ(std::distance(lower, upper), 2);
1043 
1044   std::tie(lower, upper) = multimap.equal_range(40);
1045   ASSERT_NE(lower, multimap.end());
1046   EXPECT_STREQ(lower->name(), "d");
1047   ASSERT_NE(upper, multimap.end());
1048   EXPECT_STREQ(upper->name(), "b");
1049   EXPECT_EQ(std::distance(lower, upper), 2);
1050 
1051   std::tie(lower, upper) = multimap.equal_range(50);
1052   ASSERT_NE(lower, multimap.end());
1053   EXPECT_STREQ(lower->name(), "b");
1054   EXPECT_EQ(upper, multimap.end());
1055   EXPECT_EQ(std::distance(lower, upper), 2);
1056 }
1057 
TEST_F(IntrusiveMultiMapTest,EqualRange_NoExactKey)1058 TEST_F(IntrusiveMultiMapTest, EqualRange_NoExactKey) {
1059   const IntrusiveMultiMap& multimap = multimap_;
1060 
1061   auto pair = multimap.equal_range(5);
1062   IntrusiveMultiMap::const_iterator lower = pair.first;
1063   IntrusiveMultiMap::const_iterator upper = pair.second;
1064   ASSERT_NE(lower, multimap.end());
1065   EXPECT_STREQ(lower->name(), "e");
1066   EXPECT_EQ(lower, upper);
1067 
1068   std::tie(lower, upper) = multimap.equal_range(15);
1069   ASSERT_NE(lower, multimap.end());
1070   EXPECT_STREQ(lower->name(), "c");
1071   EXPECT_EQ(lower, upper);
1072 
1073   std::tie(lower, upper) = multimap.equal_range(25);
1074   ASSERT_NE(lower, multimap.end());
1075   EXPECT_STREQ(lower->name(), "a");
1076   EXPECT_EQ(lower, upper);
1077 
1078   std::tie(lower, upper) = multimap.equal_range(35);
1079   ASSERT_NE(lower, multimap.end());
1080   EXPECT_STREQ(lower->name(), "d");
1081   EXPECT_EQ(lower, upper);
1082 
1083   std::tie(lower, upper) = multimap.equal_range(45);
1084   ASSERT_NE(lower, multimap.end());
1085   EXPECT_STREQ(lower->name(), "b");
1086   EXPECT_EQ(lower, upper);
1087 }
1088 
TEST_F(IntrusiveMultiMapTest,EqualRange_OutOfRange)1089 TEST_F(IntrusiveMultiMapTest, EqualRange_OutOfRange) {
1090   const IntrusiveMultiMap& multimap = multimap_;
1091 
1092   auto pair = multimap.equal_range(60);
1093   IntrusiveMultiMap::const_iterator lower = pair.first;
1094   IntrusiveMultiMap::const_iterator upper = pair.second;
1095   EXPECT_EQ(lower, multimap.end());
1096   EXPECT_EQ(upper, multimap.end());
1097 }
1098 
1099 }  // namespace
1100