xref: /aosp_15_r20/external/pigweed/pw_containers/intrusive_item_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 <cstdint>
16 
17 #include "pw_compilation_testing/negative_compilation.h"
18 #include "pw_containers/intrusive_forward_list.h"
19 #include "pw_containers/intrusive_list.h"
20 #include "pw_containers/intrusive_map.h"
21 #include "pw_containers/intrusive_multimap.h"
22 #include "pw_containers/intrusive_multiset.h"
23 #include "pw_containers/intrusive_set.h"
24 #include "pw_unit_test/framework.h"
25 
26 namespace {
27 
28 using pw::IntrusiveForwardList;
29 using pw::IntrusiveMap;
30 using pw::IntrusiveMultiMap;
31 using pw::IntrusiveMultiSet;
32 using pw::IntrusiveSet;
33 using pw::containers::future::IntrusiveList;
34 
35 struct ForwardListItem1 : public IntrusiveForwardList<ForwardListItem1>::Item {
36 };
37 struct ForwardListItem2 : public IntrusiveForwardList<ForwardListItem2>::Item {
38 };
39 struct ListItem1 : public IntrusiveList<ListItem1>::Item {};
40 struct ListItem2 : public IntrusiveList<ListItem2>::Item {};
41 
42 struct MapPair1 : public IntrusiveMap<uint32_t, MapPair1>::Pair {
MapPair1__anon2a4d2c500111::MapPair143   explicit MapPair1(uint32_t id) : IntrusiveMap<uint32_t, MapPair1>::Pair(id) {}
44 };
45 struct MapPair2 : public IntrusiveMap<uint32_t, MapPair2>::Pair {
MapPair2__anon2a4d2c500111::MapPair246   explicit MapPair2(uint32_t id) : IntrusiveMap<uint32_t, MapPair2>::Pair(id) {}
47 };
48 struct MultiMapPair1 : public IntrusiveMultiMap<uint32_t, MultiMapPair1>::Pair {
MultiMapPair1__anon2a4d2c500111::MultiMapPair149   explicit MultiMapPair1(uint32_t id)
50       : IntrusiveMultiMap<uint32_t, MultiMapPair1>::Pair(id) {}
51 };
52 struct MultiMapPair2 : public IntrusiveMultiMap<uint32_t, MultiMapPair2>::Pair {
MultiMapPair2__anon2a4d2c500111::MultiMapPair253   explicit MultiMapPair2(uint32_t id)
54       : IntrusiveMultiMap<uint32_t, MultiMapPair2>::Pair(id) {}
55 };
56 
57 struct SetItem1 : public IntrusiveSet<SetItem1>::Item {
operator <__anon2a4d2c500111::SetItem158   bool operator<(const SetItem1& rhs) const { return this < &rhs; }
59 };
60 struct SetItem2 : public IntrusiveSet<SetItem2>::Item {
operator <__anon2a4d2c500111::SetItem261   bool operator<(const SetItem2& rhs) const { return this < &rhs; }
62 };
63 struct MultiSetItem1 : public IntrusiveMultiSet<MultiSetItem1>::Item {
operator <__anon2a4d2c500111::MultiSetItem164   bool operator<(const MultiSetItem1& rhs) const { return this < &rhs; }
65 };
66 struct MultiSetItem2 : public IntrusiveMultiSet<MultiSetItem2>::Item {
operator <__anon2a4d2c500111::MultiSetItem267   bool operator<(const MultiSetItem2& rhs) const { return this < &rhs; }
68 };
69 
70 class Base {
71  public:
Base(const char * name)72   explicit constexpr Base(const char* name) : name_(name) {}
name() const73   constexpr const char* name() const { return name_; }
74 
75  private:
76   const char* name_;
77 };
78 
79 class Derived : public Base,
80                 public ForwardListItem1,
81                 public ForwardListItem2,
82                 public ListItem1,
83                 public ListItem2,
84                 public MapPair1,
85                 public MapPair2,
86                 public MultiMapPair1,
87                 public MultiMapPair2,
88                 public SetItem1,
89                 public SetItem2,
90                 public MultiSetItem1,
91                 public MultiSetItem2 {
92  public:
Derived(const char * name,uint32_t id)93   Derived(const char* name, uint32_t id)
94       : Base(name),
95         MapPair1(id),
96         MapPair2(id),
97         MultiMapPair1(id),
98         MultiMapPair2(id) {}
99 };
100 
TEST(IntrusiveItemTest,AddToEachContainerSequentially)101 TEST(IntrusiveItemTest, AddToEachContainerSequentially) {
102   Derived item("a", 1);
103 
104   IntrusiveForwardList<ForwardListItem1> forward_list1;
105   IntrusiveForwardList<ForwardListItem2> forward_list2;
106   IntrusiveList<ListItem1> list1;
107   IntrusiveList<ListItem2> list2;
108   IntrusiveMap<uint32_t, MapPair1> map1;
109   IntrusiveMap<uint32_t, MapPair2> map2;
110   IntrusiveMultiMap<uint32_t, MultiMapPair1> multimap1;
111   IntrusiveMultiMap<uint32_t, MultiMapPair2> multimap2;
112   IntrusiveSet<SetItem1> set1;
113   IntrusiveSet<SetItem2> set2;
114   IntrusiveMultiSet<MultiSetItem1> multiset1;
115   IntrusiveMultiSet<MultiSetItem2> multiset2;
116 
117   forward_list1.push_front(item);
118   forward_list1.clear();
119 
120   forward_list2.push_front(item);
121   forward_list2.clear();
122 
123   list1.push_back(item);
124   list1.clear();
125 
126   list2.push_back(item);
127   list2.clear();
128 
129   map1.insert(item);
130   map1.clear();
131 
132   map2.insert(item);
133   map2.clear();
134 
135   multimap1.insert(item);
136   multimap1.clear();
137 
138   multimap2.insert(item);
139   multimap2.clear();
140 
141   set1.insert(item);
142   set1.clear();
143 
144   set2.insert(item);
145   set2.clear();
146 
147   multiset1.insert(item);
148   multiset1.clear();
149 
150   multiset2.insert(item);
151   multiset2.clear();
152 }
153 
TEST(IntrusiveItemTest,AddToEachContainerSimultaneousy)154 TEST(IntrusiveItemTest, AddToEachContainerSimultaneousy) {
155   Derived item("a", 1);
156 
157   IntrusiveForwardList<ForwardListItem1> forward_list1;
158   IntrusiveForwardList<ForwardListItem2> forward_list2;
159   IntrusiveList<ListItem1> list1;
160   IntrusiveList<ListItem2> list2;
161   IntrusiveMap<uint32_t, MapPair1> map1;
162   IntrusiveMap<uint32_t, MapPair2> map2;
163   IntrusiveMultiMap<uint32_t, MultiMapPair1> multimap1;
164   IntrusiveMultiMap<uint32_t, MultiMapPair2> multimap2;
165   IntrusiveSet<SetItem1> set1;
166   IntrusiveSet<SetItem2> set2;
167   IntrusiveMultiSet<MultiSetItem1> multiset1;
168   IntrusiveMultiSet<MultiSetItem2> multiset2;
169 
170   forward_list1.push_front(item);
171   list1.push_back(item);
172   map1.insert(item);
173   multimap1.insert(item);
174   set1.insert(item);
175   multiset1.insert(item);
176 
177   forward_list1.clear();
178   list1.clear();
179   map1.clear();
180   multimap1.clear();
181   set1.clear();
182   multiset1.clear();
183 
184   forward_list2.push_front(item);
185   list2.push_back(item);
186   map2.insert(item);
187   multimap2.insert(item);
188   set2.insert(item);
189   multiset2.insert(item);
190 
191   forward_list2.clear();
192   list2.clear();
193   map2.clear();
194   multimap2.clear();
195   set2.clear();
196   multiset2.clear();
197 }
198 
199 #if PW_NC_TEST(ForwardListValueTypeHasMultipleBases)
200 PW_NC_EXPECT_CLANG(
201     "member 'ItemType' found in multiple base classes of different types");
202 PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
203 [[maybe_unused]] IntrusiveForwardList<Derived> bad_fwd_list;
204 
205 #elif PW_NC_TEST(ListValueTypeHasMultipleBases)
206 PW_NC_EXPECT_CLANG(
207     "member 'ItemType' found in multiple base classes of different types");
208 PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
209 [[maybe_unused]] IntrusiveList<Derived> bad_list;
210 
211 #elif PW_NC_TEST(MapValueTypeHasMultipleBases)
212 PW_NC_EXPECT_CLANG(
213     "member 'key' found in multiple base classes of different types");
214 PW_NC_EXPECT_GCC("request for member 'key' is ambiguous");
215 [[maybe_unused]] IntrusiveMap<uint32_t, Derived> bad_map;
216 
217 #elif PW_NC_TEST(MultiMapValueTypeHasMultipleBases)
218 PW_NC_EXPECT_CLANG(
219     "member 'key' found in multiple base classes of different types");
220 PW_NC_EXPECT_GCC("request for member 'key' is ambiguous");
221 [[maybe_unused]] IntrusiveMultiMap<uint32_t, Derived> bad_multimap;
222 
223 #elif PW_NC_TEST(SetValueTypeHasMultipleBases)
224 PW_NC_EXPECT_CLANG(
225     "member 'ItemType' found in multiple base classes of different types");
226 PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
227 [[maybe_unused]] IntrusiveSet<Derived> bad_set([](const Derived& lhs,
__anon2a4d2c500202(const Derived& lhs, const Derived& rhs) 228                                                   const Derived& rhs) {
229   return &lhs < &rhs;
230 });
231 
232 #elif PW_NC_TEST(MultiSetValueTypeHasMultipleBases)
233 PW_NC_EXPECT_CLANG(
234     "member 'ItemType' found in multiple base classes of different types");
235 PW_NC_EXPECT_GCC("lookup of 'ItemType' in '{anonymous}::Derived' is ambiguous");
236 [[maybe_unused]] IntrusiveMultiSet<Derived> bad_multiset(
__anon2a4d2c500302(const Derived& lhs, const Derived& rhs) 237     [](const Derived& lhs, const Derived& rhs) { return &lhs < &rhs; });
238 
239 #endif  // PW_NC_TEST
240 
241 }  // namespace
242