xref: /aosp_15_r20/external/cronet/base/containers/enum_set_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/containers/enum_set.h"
6 
7 #include <stddef.h>
8 
9 #include "base/containers/to_vector.h"
10 #include "base/test/gtest_util.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest-death-test.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace base {
16 namespace {
17 
18 enum class TestEnum {
19   TEST_BELOW_MIN_NEGATIVE = -1,
20   TEST_BELOW_MIN = 0,
21   TEST_1 = 1,
22   TEST_MIN = TEST_1,
23   TEST_2,
24   TEST_3,
25   TEST_4,
26   TEST_5,
27   TEST_MAX = TEST_5,
28   TEST_6_OUT_OF_BOUNDS,
29   TEST_7_OUT_OF_BOUNDS
30 };
31 using TestEnumSet = EnumSet<TestEnum, TestEnum::TEST_MIN, TestEnum::TEST_MAX>;
32 
33 enum class TestEnumExtreme {
34   TEST_0 = 0,
35   TEST_MIN = TEST_0,
36   TEST_63 = 63,
37   TEST_MAX = TEST_63,
38   TEST_64_OUT_OF_BOUNDS,
39 };
40 using TestEnumExtremeSet = EnumSet<TestEnumExtreme,
41                                    TestEnumExtreme::TEST_MIN,
42                                    TestEnumExtreme::TEST_MAX>;
43 
44 class EnumSetTest : public ::testing::Test {};
45 class EnumSetDeathTest : public ::testing::Test {};
46 
TEST_F(EnumSetTest,ClassConstants)47 TEST_F(EnumSetTest, ClassConstants) {
48   EXPECT_EQ(TestEnum::TEST_MIN, TestEnumSet::kMinValue);
49   EXPECT_EQ(TestEnum::TEST_MAX, TestEnumSet::kMaxValue);
50   EXPECT_EQ(5u, TestEnumSet::kValueCount);
51 }
52 
53 // Use static_assert to check that functions we expect to be compile time
54 // evaluatable are really that way.
TEST_F(EnumSetTest,ConstexprsAreValid)55 TEST_F(EnumSetTest, ConstexprsAreValid) {
56   static_assert(TestEnumSet::All().Has(TestEnum::TEST_2),
57                 "Expected All() to be integral constant expression");
58   static_assert(TestEnumSet::FromRange(TestEnum::TEST_2, TestEnum::TEST_4)
59                     .Has(TestEnum::TEST_2),
60                 "Expected FromRange() to be integral constant expression");
61   static_assert(TestEnumSet{TestEnum::TEST_2}.Has(TestEnum::TEST_2),
62                 "Expected TestEnumSet() to be integral constant expression");
63   static_assert(
64       TestEnumSet::FromEnumBitmask(1 << static_cast<uint64_t>(TestEnum::TEST_2))
65           .Has(TestEnum::TEST_2),
66       "Expected TestEnumSet() to be integral constant expression");
67 }
68 
TEST_F(EnumSetTest,DefaultConstructor)69 TEST_F(EnumSetTest, DefaultConstructor) {
70   const TestEnumSet enums;
71   EXPECT_TRUE(enums.empty());
72   EXPECT_EQ(0u, enums.size());
73   EXPECT_FALSE(enums.Has(TestEnum::TEST_1));
74   EXPECT_FALSE(enums.Has(TestEnum::TEST_2));
75   EXPECT_FALSE(enums.Has(TestEnum::TEST_3));
76   EXPECT_FALSE(enums.Has(TestEnum::TEST_4));
77   EXPECT_FALSE(enums.Has(TestEnum::TEST_5));
78 }
79 
TEST_F(EnumSetTest,OneArgConstructor)80 TEST_F(EnumSetTest, OneArgConstructor) {
81   const TestEnumSet enums = {TestEnum::TEST_4};
82   EXPECT_FALSE(enums.empty());
83   EXPECT_EQ(1u, enums.size());
84   EXPECT_FALSE(enums.Has(TestEnum::TEST_1));
85   EXPECT_FALSE(enums.Has(TestEnum::TEST_2));
86   EXPECT_FALSE(enums.Has(TestEnum::TEST_3));
87   EXPECT_TRUE(enums.Has(TestEnum::TEST_4));
88   EXPECT_FALSE(enums.Has(TestEnum::TEST_5));
89 }
90 
TEST_F(EnumSetTest,OneArgConstructorSize)91 TEST_F(EnumSetTest, OneArgConstructorSize) {
92   TestEnumExtremeSet enums = {TestEnumExtreme::TEST_0};
93   EXPECT_TRUE(enums.Has(TestEnumExtreme::TEST_0));
94 }
95 
TEST_F(EnumSetTest,TwoArgConstructor)96 TEST_F(EnumSetTest, TwoArgConstructor) {
97   const TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_2};
98   EXPECT_FALSE(enums.empty());
99   EXPECT_EQ(2u, enums.size());
100   EXPECT_FALSE(enums.Has(TestEnum::TEST_1));
101   EXPECT_TRUE(enums.Has(TestEnum::TEST_2));
102   EXPECT_FALSE(enums.Has(TestEnum::TEST_3));
103   EXPECT_TRUE(enums.Has(TestEnum::TEST_4));
104   EXPECT_FALSE(enums.Has(TestEnum::TEST_5));
105 }
106 
TEST_F(EnumSetTest,ThreeArgConstructor)107 TEST_F(EnumSetTest, ThreeArgConstructor) {
108   const TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_2,
109                              TestEnum::TEST_1};
110   EXPECT_FALSE(enums.empty());
111   EXPECT_EQ(3u, enums.size());
112   EXPECT_TRUE(enums.Has(TestEnum::TEST_1));
113   EXPECT_TRUE(enums.Has(TestEnum::TEST_2));
114   EXPECT_FALSE(enums.Has(TestEnum::TEST_3));
115   EXPECT_TRUE(enums.Has(TestEnum::TEST_4));
116   EXPECT_FALSE(enums.Has(TestEnum::TEST_5));
117 }
118 
TEST_F(EnumSetTest,DuplicatesInConstructor)119 TEST_F(EnumSetTest, DuplicatesInConstructor) {
120   EXPECT_EQ(
121       TestEnumSet({TestEnum::TEST_4, TestEnum::TEST_2, TestEnum::TEST_1,
122                    TestEnum::TEST_4, TestEnum::TEST_2, TestEnum::TEST_4}),
123       TestEnumSet({TestEnum::TEST_1, TestEnum::TEST_2, TestEnum::TEST_4}));
124 }
125 
TEST_F(EnumSetTest,All)126 TEST_F(EnumSetTest, All) {
127   const TestEnumSet enums(TestEnumSet::All());
128   EXPECT_FALSE(enums.empty());
129   EXPECT_EQ(5u, enums.size());
130   EXPECT_TRUE(enums.Has(TestEnum::TEST_1));
131   EXPECT_TRUE(enums.Has(TestEnum::TEST_2));
132   EXPECT_TRUE(enums.Has(TestEnum::TEST_3));
133   EXPECT_TRUE(enums.Has(TestEnum::TEST_4));
134   EXPECT_TRUE(enums.Has(TestEnum::TEST_5));
135 }
136 
TEST_F(EnumSetTest,AllExtreme)137 TEST_F(EnumSetTest, AllExtreme) {
138   const TestEnumExtremeSet enums(TestEnumExtremeSet::All());
139   EXPECT_FALSE(enums.empty());
140   EXPECT_EQ(64u, enums.size());
141   EXPECT_TRUE(enums.Has(TestEnumExtreme::TEST_0));
142   EXPECT_TRUE(enums.Has(TestEnumExtreme::TEST_63));
143   EXPECT_FALSE(enums.Has(TestEnumExtreme::TEST_64_OUT_OF_BOUNDS));
144 }
145 
TEST_F(EnumSetTest,FromRange)146 TEST_F(EnumSetTest, FromRange) {
147   EXPECT_EQ(TestEnumSet({TestEnum::TEST_2, TestEnum::TEST_3, TestEnum::TEST_4}),
148             TestEnumSet::FromRange(TestEnum::TEST_2, TestEnum::TEST_4));
149   EXPECT_EQ(TestEnumSet::All(),
150             TestEnumSet::FromRange(TestEnum::TEST_1, TestEnum::TEST_5));
151   EXPECT_EQ(TestEnumSet({TestEnum::TEST_2}),
152             TestEnumSet::FromRange(TestEnum::TEST_2, TestEnum::TEST_2));
153 
154   using RestrictedRangeSet =
155       EnumSet<TestEnum, TestEnum::TEST_2, TestEnum::TEST_MAX>;
156   EXPECT_EQ(RestrictedRangeSet(
157                 {TestEnum::TEST_2, TestEnum::TEST_3, TestEnum::TEST_4}),
158             RestrictedRangeSet::FromRange(TestEnum::TEST_2, TestEnum::TEST_4));
159   EXPECT_EQ(RestrictedRangeSet::All(),
160             RestrictedRangeSet::FromRange(TestEnum::TEST_2, TestEnum::TEST_5));
161 }
162 
TEST_F(EnumSetTest,Put)163 TEST_F(EnumSetTest, Put) {
164   TestEnumSet enums = {TestEnum::TEST_4};
165   enums.Put(TestEnum::TEST_3);
166   EXPECT_EQ(TestEnumSet({TestEnum::TEST_3, TestEnum::TEST_4}), enums);
167   enums.Put(TestEnum::TEST_5);
168   EXPECT_EQ(TestEnumSet({TestEnum::TEST_3, TestEnum::TEST_4, TestEnum::TEST_5}),
169             enums);
170 }
171 
TEST_F(EnumSetTest,PutAll)172 TEST_F(EnumSetTest, PutAll) {
173   TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_5};
174   enums.PutAll({TestEnum::TEST_3, TestEnum::TEST_4});
175   EXPECT_EQ(TestEnumSet({TestEnum::TEST_3, TestEnum::TEST_4, TestEnum::TEST_5}),
176             enums);
177 }
178 
TEST_F(EnumSetTest,PutRange)179 TEST_F(EnumSetTest, PutRange) {
180   TestEnumSet enums;
181   enums.PutRange(TestEnum::TEST_2, TestEnum::TEST_4);
182   EXPECT_EQ(TestEnumSet({TestEnum::TEST_2, TestEnum::TEST_3, TestEnum::TEST_4}),
183             enums);
184 }
185 
TEST_F(EnumSetTest,RetainAll)186 TEST_F(EnumSetTest, RetainAll) {
187   TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_5};
188   enums.RetainAll(TestEnumSet({TestEnum::TEST_3, TestEnum::TEST_4}));
189   EXPECT_EQ(TestEnumSet({TestEnum::TEST_4}), enums);
190 }
191 
TEST_F(EnumSetTest,Remove)192 TEST_F(EnumSetTest, Remove) {
193   TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_5};
194   enums.Remove(TestEnum::TEST_1);
195   enums.Remove(TestEnum::TEST_3);
196   EXPECT_EQ(TestEnumSet({TestEnum::TEST_4, TestEnum::TEST_5}), enums);
197   enums.Remove(TestEnum::TEST_4);
198   EXPECT_EQ(TestEnumSet({TestEnum::TEST_5}), enums);
199   enums.Remove(TestEnum::TEST_5);
200   enums.Remove(TestEnum::TEST_6_OUT_OF_BOUNDS);
201   EXPECT_TRUE(enums.empty());
202 }
203 
TEST_F(EnumSetTest,RemoveAll)204 TEST_F(EnumSetTest, RemoveAll) {
205   TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_5};
206   enums.RemoveAll(TestEnumSet({TestEnum::TEST_3, TestEnum::TEST_4}));
207   EXPECT_EQ(TestEnumSet({TestEnum::TEST_5}), enums);
208 }
209 
TEST_F(EnumSetTest,Clear)210 TEST_F(EnumSetTest, Clear) {
211   TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_5};
212   enums.Clear();
213   EXPECT_TRUE(enums.empty());
214 }
215 
TEST_F(EnumSetTest,Set)216 TEST_F(EnumSetTest, Set) {
217   TestEnumSet enums;
218   EXPECT_TRUE(enums.empty());
219 
220   enums.PutOrRemove(TestEnum::TEST_3, false);
221   EXPECT_TRUE(enums.empty());
222 
223   enums.PutOrRemove(TestEnum::TEST_4, true);
224   EXPECT_EQ(enums, TestEnumSet({TestEnum::TEST_4}));
225 
226   enums.PutOrRemove(TestEnum::TEST_5, true);
227   EXPECT_EQ(enums, TestEnumSet({TestEnum::TEST_4, TestEnum::TEST_5}));
228   enums.PutOrRemove(TestEnum::TEST_5, true);
229   EXPECT_EQ(enums, TestEnumSet({TestEnum::TEST_4, TestEnum::TEST_5}));
230 
231   enums.PutOrRemove(TestEnum::TEST_4, false);
232   EXPECT_EQ(enums, TestEnumSet({TestEnum::TEST_5}));
233 }
234 
TEST_F(EnumSetTest,Has)235 TEST_F(EnumSetTest, Has) {
236   const TestEnumSet enums = {TestEnum::TEST_4, TestEnum::TEST_5};
237   EXPECT_FALSE(enums.Has(TestEnum::TEST_1));
238   EXPECT_FALSE(enums.Has(TestEnum::TEST_2));
239   EXPECT_FALSE(enums.Has(TestEnum::TEST_3));
240   EXPECT_TRUE(enums.Has(TestEnum::TEST_4));
241   EXPECT_TRUE(enums.Has(TestEnum::TEST_5));
242   EXPECT_FALSE(enums.Has(TestEnum::TEST_6_OUT_OF_BOUNDS));
243 }
244 
TEST_F(EnumSetTest,HasAll)245 TEST_F(EnumSetTest, HasAll) {
246   const TestEnumSet enums1 = {TestEnum::TEST_4, TestEnum::TEST_5};
247   const TestEnumSet enums2 = {TestEnum::TEST_3, TestEnum::TEST_4};
248   const TestEnumSet enums3 = Union(enums1, enums2);
249   EXPECT_TRUE(enums1.HasAll(enums1));
250   EXPECT_FALSE(enums1.HasAll(enums2));
251   EXPECT_FALSE(enums1.HasAll(enums3));
252 
253   EXPECT_FALSE(enums2.HasAll(enums1));
254   EXPECT_TRUE(enums2.HasAll(enums2));
255   EXPECT_FALSE(enums2.HasAll(enums3));
256 
257   EXPECT_TRUE(enums3.HasAll(enums1));
258   EXPECT_TRUE(enums3.HasAll(enums2));
259   EXPECT_TRUE(enums3.HasAll(enums3));
260 }
261 
TEST_F(EnumSetTest,HasAny)262 TEST_F(EnumSetTest, HasAny) {
263   const TestEnumSet enums1 = {TestEnum::TEST_4, TestEnum::TEST_5};
264   const TestEnumSet enums2 = {TestEnum::TEST_3, TestEnum::TEST_4};
265   const TestEnumSet enums3 = {TestEnum::TEST_1, TestEnum::TEST_2};
266   EXPECT_TRUE(enums1.HasAny(enums1));
267   EXPECT_TRUE(enums1.HasAny(enums2));
268   EXPECT_FALSE(enums1.HasAny(enums3));
269 
270   EXPECT_TRUE(enums2.HasAny(enums1));
271   EXPECT_TRUE(enums2.HasAny(enums2));
272   EXPECT_FALSE(enums2.HasAny(enums3));
273 
274   EXPECT_FALSE(enums3.HasAny(enums1));
275   EXPECT_FALSE(enums3.HasAny(enums2));
276   EXPECT_TRUE(enums3.HasAny(enums3));
277 }
278 
TEST_F(EnumSetTest,Iterators)279 TEST_F(EnumSetTest, Iterators) {
280   const TestEnumSet enums1 = {TestEnum::TEST_4, TestEnum::TEST_5};
281   TestEnumSet enums2;
282   for (TestEnum e : enums1) {
283     enums2.Put(e);
284   }
285   EXPECT_EQ(enums2, enums1);
286 }
287 
TEST_F(EnumSetTest,RangeBasedForLoop)288 TEST_F(EnumSetTest, RangeBasedForLoop) {
289   const TestEnumSet enums1 = {TestEnum::TEST_2, TestEnum::TEST_5};
290   TestEnumSet enums2;
291   for (TestEnum e : enums1) {
292     enums2.Put(e);
293   }
294   EXPECT_EQ(enums2, enums1);
295 }
296 
TEST_F(EnumSetTest,IteratorComparisonOperators)297 TEST_F(EnumSetTest, IteratorComparisonOperators) {
298   const TestEnumSet enums = {TestEnum::TEST_2, TestEnum::TEST_4};
299   const auto first_it = enums.begin();
300   const auto second_it = ++enums.begin();
301 
302   // Copy for equality testing.
303   const auto first_it_copy = first_it;
304 
305   // Sanity check, as the rest of the test relies on |first_it| and
306   // |first_it_copy| pointing to the same element and |first_it| and |second_it|
307   // pointing to different elements.
308   ASSERT_EQ(*first_it, *first_it_copy);
309   ASSERT_NE(*first_it, *second_it);
310 
311   EXPECT_TRUE(first_it == first_it_copy);
312   EXPECT_FALSE(first_it != first_it_copy);
313 
314   EXPECT_TRUE(first_it != second_it);
315   EXPECT_FALSE(first_it == second_it);
316 }
317 
TEST_F(EnumSetTest,IteratorIncrementOperators)318 TEST_F(EnumSetTest, IteratorIncrementOperators) {
319   const TestEnumSet enums = {TestEnum::TEST_2, TestEnum::TEST_4};
320   const auto begin = enums.begin();
321 
322   auto post_inc_it = begin;
323   auto pre_inc_it = begin;
324 
325   auto post_inc_return_it = post_inc_it++;
326   auto pre_inc_return_it = ++pre_inc_it;
327 
328   // |pre_inc_it| and |post_inc_it| should point to the same element.
329   EXPECT_EQ(pre_inc_it, post_inc_it);
330   EXPECT_EQ(*pre_inc_it, *post_inc_it);
331 
332   // |pre_inc_it| should NOT point to the first element.
333   EXPECT_NE(begin, pre_inc_it);
334   EXPECT_NE(*begin, *pre_inc_it);
335 
336   // |post_inc_it| should NOT point to the first element.
337   EXPECT_NE(begin, post_inc_it);
338   EXPECT_NE(*begin, *post_inc_it);
339 
340   // Prefix increment should return new iterator.
341   EXPECT_EQ(pre_inc_return_it, post_inc_it);
342   EXPECT_EQ(*pre_inc_return_it, *post_inc_it);
343 
344   // Postfix increment should return original iterator.
345   EXPECT_EQ(post_inc_return_it, begin);
346   EXPECT_EQ(*post_inc_return_it, *begin);
347 }
348 
TEST_F(EnumSetTest,Union)349 TEST_F(EnumSetTest, Union) {
350   const TestEnumSet enums1 = {TestEnum::TEST_4, TestEnum::TEST_5};
351   const TestEnumSet enums2 = {TestEnum::TEST_3, TestEnum::TEST_4};
352   const TestEnumSet enums3 = Union(enums1, enums2);
353 
354   EXPECT_EQ(TestEnumSet({TestEnum::TEST_3, TestEnum::TEST_4, TestEnum::TEST_5}),
355             enums3);
356 }
357 
TEST_F(EnumSetTest,Intersection)358 TEST_F(EnumSetTest, Intersection) {
359   const TestEnumSet enums1 = {TestEnum::TEST_4, TestEnum::TEST_5};
360   const TestEnumSet enums2 = {TestEnum::TEST_3, TestEnum::TEST_4};
361   const TestEnumSet enums3 = Intersection(enums1, enums2);
362 
363   EXPECT_EQ(TestEnumSet({TestEnum::TEST_4}), enums3);
364 }
365 
TEST_F(EnumSetTest,Difference)366 TEST_F(EnumSetTest, Difference) {
367   const TestEnumSet enums1 = {TestEnum::TEST_4, TestEnum::TEST_5};
368   const TestEnumSet enums2 = {TestEnum::TEST_3, TestEnum::TEST_4};
369   const TestEnumSet enums3 = Difference(enums1, enums2);
370 
371   EXPECT_EQ(TestEnumSet({TestEnum::TEST_5}), enums3);
372 }
373 
TEST_F(EnumSetTest,ToFromEnumBitmask)374 TEST_F(EnumSetTest, ToFromEnumBitmask) {
375   const TestEnumSet empty;
376   EXPECT_EQ(empty.ToEnumBitmask(), 0ULL);
377   EXPECT_EQ(TestEnumSet::FromEnumBitmask(0), empty);
378 
379   const TestEnumSet enums1 = {TestEnum::TEST_2};
380   const uint64_t val1 = 1ULL << static_cast<uint64_t>(TestEnum::TEST_2);
381   EXPECT_EQ(enums1.ToEnumBitmask(), val1);
382   EXPECT_EQ(TestEnumSet::FromEnumBitmask(val1), enums1);
383 
384   const TestEnumSet enums2 = {TestEnum::TEST_3, TestEnum::TEST_4};
385   const uint64_t val2 = 1ULL << static_cast<uint64_t>(TestEnum::TEST_3) |
386                         1ULL << static_cast<uint64_t>(TestEnum::TEST_4);
387   EXPECT_EQ(enums2.ToEnumBitmask(), val2);
388   EXPECT_EQ(TestEnumSet::FromEnumBitmask(val2), enums2);
389 }
390 
TEST_F(EnumSetTest,ToFromEnumBitmaskExtreme)391 TEST_F(EnumSetTest, ToFromEnumBitmaskExtreme) {
392   const TestEnumExtremeSet empty;
393   EXPECT_EQ(empty.ToEnumBitmask(), 0ULL);
394   EXPECT_EQ(TestEnumExtremeSet::FromEnumBitmask(0ULL), empty);
395 
396   const TestEnumExtremeSet enums1 = {TestEnumExtreme::TEST_63};
397   const uint64_t val1 = 1ULL << static_cast<uint64_t>(TestEnumExtreme::TEST_63);
398   EXPECT_EQ(enums1.ToEnumBitmask(), val1);
399   EXPECT_EQ(TestEnumExtremeSet::FromEnumBitmask(val1), enums1);
400 }
401 
TEST_F(EnumSetTest,FromEnumBitmaskIgnoresExtraBits)402 TEST_F(EnumSetTest, FromEnumBitmaskIgnoresExtraBits) {
403   const TestEnumSet kSets[] = {
404       {},
405       {TestEnum::TEST_MIN},
406       {TestEnum::TEST_MAX},
407       {TestEnum::TEST_MIN, TestEnum::TEST_MAX},
408       {TestEnum::TEST_MIN, TestEnum::TEST_MAX},
409       {TestEnum::TEST_2, TestEnum::TEST_4},
410   };
411   size_t i = 0;
412   for (const TestEnumSet& set : kSets) {
413     SCOPED_TRACE(i++);
414     const uint64_t val = set.ToEnumBitmask();
415 
416     // Produce a bitstring for a single enum value. When `e` is in range
417     // relative to TestEnumSet, this function behaves identically to
418     // `single_val_bitstring`. When `e` is not in range, this function attempts
419     // to compute a value, while `single_val_bitstring` intentionally crashes.
420     auto single_val_bitstring = [](TestEnum e) -> uint64_t {
421       uint64_t shift_amount = static_cast<uint64_t>(e);
422       // Shifting left more than the number of bits in the lhs would be UB.
423       CHECK_LT(shift_amount, sizeof(uint64_t) * 8);
424       return 1ULL << shift_amount;
425     };
426 
427     const uint64_t kJunkVals[] = {
428         // Add junk bits above TEST_MAX.
429         val | single_val_bitstring(TestEnum::TEST_6_OUT_OF_BOUNDS),
430         val | single_val_bitstring(TestEnum::TEST_7_OUT_OF_BOUNDS),
431         val | single_val_bitstring(TestEnum::TEST_6_OUT_OF_BOUNDS) |
432             single_val_bitstring(TestEnum::TEST_7_OUT_OF_BOUNDS),
433         // Add junk bits below TEST_MIN.
434         val | single_val_bitstring(TestEnum::TEST_BELOW_MIN),
435     };
436     for (uint64_t junk_val : kJunkVals) {
437       SCOPED_TRACE(junk_val);
438       ASSERT_NE(val, junk_val);
439 
440       const TestEnumSet set_from_junk = TestEnumSet::FromEnumBitmask(junk_val);
441       EXPECT_EQ(set_from_junk, set);
442       EXPECT_EQ(set_from_junk.ToEnumBitmask(), set.ToEnumBitmask());
443 
444       // Iterating both sets should produce the same sequence.
445       auto it1 = set.begin();
446       auto it2 = set_from_junk.begin();
447       while (it1 != set.end() && it2 != set_from_junk.end()) {
448         EXPECT_EQ(*it1, *it2);
449         ++it1;
450         ++it2;
451       }
452       EXPECT_TRUE(it1 == set.end());
453       EXPECT_TRUE(it2 == set_from_junk.end());
454     }
455   }
456 }
457 
TEST_F(EnumSetTest,OneEnumValue)458 TEST_F(EnumSetTest, OneEnumValue) {
459   enum class TestEnumOne {
460     kTest1 = 1,
461     kTestMin = kTest1,
462     kTestMax = kTest1,
463   };
464   using TestEnumOneSet =
465       EnumSet<TestEnumOne, TestEnumOne::kTestMin, TestEnumOne::kTestMax>;
466   EXPECT_EQ(TestEnumOne::kTestMin, TestEnumOneSet::kMinValue);
467   EXPECT_EQ(TestEnumOne::kTestMax, TestEnumOneSet::kMaxValue);
468   EXPECT_EQ(1u, TestEnumOneSet::kValueCount);
469 }
470 
TEST_F(EnumSetTest,SparseEnum)471 TEST_F(EnumSetTest, SparseEnum) {
472   enum class TestEnumSparse {
473     TEST_1 = 1,
474     TEST_MIN = 1,
475     TEST_50 = 50,
476     TEST_100 = 100,
477     TEST_MAX = TEST_100,
478   };
479   using TestEnumSparseSet = EnumSet<TestEnumSparse, TestEnumSparse::TEST_MIN,
480                                     TestEnumSparse::TEST_MAX>;
481   TestEnumSparseSet sparse;
482   sparse.Put(TestEnumSparse::TEST_MIN);
483   sparse.Put(TestEnumSparse::TEST_MAX);
484   EXPECT_EQ(sparse.size(), 2u);
485 
486   EXPECT_EQ(TestEnumSparseSet::All().size(), 100u);
487 }
488 
TEST_F(EnumSetTest,SparseEnumSmall)489 TEST_F(EnumSetTest, SparseEnumSmall) {
490   enum class TestEnumSparse {
491     TEST_1 = 1,
492     TEST_MIN = 1,
493     TEST_50 = 50,
494     TEST_60 = 60,
495     TEST_MAX = TEST_60,
496   };
497   using TestEnumSparseSet = EnumSet<TestEnumSparse, TestEnumSparse::TEST_MIN,
498                                     TestEnumSparse::TEST_MAX>;
499   TestEnumSparseSet sparse;
500   sparse.Put(TestEnumSparse::TEST_MIN);
501   sparse.Put(TestEnumSparse::TEST_MAX);
502   EXPECT_EQ(sparse.size(), 2u);
503 
504   // This may seem a little surprising! There are only 3 distinct values in
505   // TestEnumSparse, so why does TestEnumSparseSet think it has 60 of them? This
506   // is an artifact of EnumSet's design, as it has no way of knowing which
507   // values between the min and max are actually named in the enum's definition.
508   EXPECT_EQ(TestEnumSparseSet::All().size(), 60u);
509 }
510 
TEST_F(EnumSetDeathTest,CrashesOnOutOfRange)511 TEST_F(EnumSetDeathTest, CrashesOnOutOfRange) {
512   EXPECT_CHECK_DEATH(TestEnumSet({TestEnum::TEST_BELOW_MIN}));
513   EXPECT_CHECK_DEATH(TestEnumSet({TestEnum::TEST_6_OUT_OF_BOUNDS}));
514   EXPECT_CHECK_DEATH(TestEnumSet({TestEnum::TEST_7_OUT_OF_BOUNDS}));
515 }
516 
TEST_F(EnumSetDeathTest,EnumWithNegatives)517 TEST_F(EnumSetDeathTest, EnumWithNegatives) {
518   enum class TestEnumNeg {
519     TEST_BELOW_MIN = -3,
520     TEST_A = -2,
521     TEST_MIN = TEST_A,
522     TEST_B = -1,
523     TEST_C = 0,
524     TEST_D = 1,
525     TEST_E = 2,
526     TEST_MAX = TEST_E,
527     TEST_F = 3,
528   };
529   // This EnumSet starts negative and ends positive.
530   using TestEnumWithNegSet =
531       EnumSet<TestEnumNeg, TestEnumNeg::TEST_MIN, TestEnumNeg::TEST_MAX>;
532 
533   // Should crash because TEST_BELOW_MIN is not in range.
534   EXPECT_CHECK_DEATH(TestEnumWithNegSet({TestEnumNeg::TEST_BELOW_MIN}));
535   // TEST_D is in range, but note that TEST_MIN is negative. This should work.
536   EXPECT_TRUE(
537       TestEnumWithNegSet({TestEnumNeg::TEST_D}).Has(TestEnumNeg::TEST_D));
538   // Even though TEST_A is negative, it is in range, so this should work.
539   EXPECT_TRUE(
540       TestEnumWithNegSet({TestEnumNeg::TEST_A}).Has(TestEnumNeg::TEST_A));
541 }
542 
TEST_F(EnumSetDeathTest,EnumWithOnlyNegatives)543 TEST_F(EnumSetDeathTest, EnumWithOnlyNegatives) {
544   enum class TestEnumNeg {
545     TEST_BELOW_MIN = -10,
546     TEST_A = -9,
547     TEST_MIN = TEST_A,
548     TEST_B = -8,
549     TEST_C = -7,
550     TEST_D = -6,
551     TEST_MAX = TEST_D,
552     TEST_F = -5,
553   };
554   // This EnumSet starts negative and ends negative.
555   using TestEnumWithNegSet =
556       EnumSet<TestEnumNeg, TestEnumNeg::TEST_MIN, TestEnumNeg::TEST_MAX>;
557 
558   // Should crash because TEST_BELOW_MIN is not in range.
559   EXPECT_CHECK_DEATH(TestEnumWithNegSet({TestEnumNeg::TEST_BELOW_MIN}));
560   // TEST_A, TEST_D are in range, but note that TEST_MIN and values are
561   // negative. This should work.
562   EXPECT_TRUE(
563       TestEnumWithNegSet({TestEnumNeg::TEST_A}).Has(TestEnumNeg::TEST_A));
564   EXPECT_TRUE(
565       TestEnumWithNegSet({TestEnumNeg::TEST_D}).Has(TestEnumNeg::TEST_D));
566 }
567 
TEST_F(EnumSetDeathTest,VariadicConstructorCrashesOnOutOfRange)568 TEST_F(EnumSetDeathTest, VariadicConstructorCrashesOnOutOfRange) {
569   // Constructor should crash given out-of-range values.
570   EXPECT_CHECK_DEATH(TestEnumSet({TestEnum::TEST_BELOW_MIN}).empty());
571   EXPECT_CHECK_DEATH(TestEnumSet({TestEnum::TEST_BELOW_MIN_NEGATIVE}).empty());
572   EXPECT_CHECK_DEATH(TestEnumSet({TestEnum::TEST_6_OUT_OF_BOUNDS}).empty());
573 }
574 
TEST_F(EnumSetDeathTest,FromRangeCrashesOnBadInputs)575 TEST_F(EnumSetDeathTest, FromRangeCrashesOnBadInputs) {
576   // FromRange crashes when the bounds are in range, but out of order.
577   EXPECT_CHECK_DEATH(
578       TestEnumSet().FromRange(TestEnum::TEST_3, TestEnum::TEST_1));
579 
580   // FromRange crashes when the start value is out of range.
581   EXPECT_CHECK_DEATH(
582       TestEnumSet().FromRange(TestEnum::TEST_BELOW_MIN, TestEnum::TEST_1));
583   EXPECT_CHECK_DEATH(TestEnumSet().FromRange(TestEnum::TEST_BELOW_MIN_NEGATIVE,
584                                              TestEnum::TEST_1));
585   EXPECT_CHECK_DEATH(TestEnumSet().FromRange(TestEnum::TEST_6_OUT_OF_BOUNDS,
586                                              TestEnum::TEST_1));
587 
588   // FromRange crashes when the end value is out of range.
589   EXPECT_CHECK_DEATH(
590       TestEnumSet().FromRange(TestEnum::TEST_3, TestEnum::TEST_BELOW_MIN));
591   EXPECT_CHECK_DEATH(TestEnumSet().FromRange(
592       TestEnum::TEST_3, TestEnum::TEST_BELOW_MIN_NEGATIVE));
593   EXPECT_CHECK_DEATH(TestEnumSet().FromRange(TestEnum::TEST_3,
594                                              TestEnum::TEST_6_OUT_OF_BOUNDS));
595 
596   // Crashes when start and end are both out of range.
597   EXPECT_CHECK_DEATH(TestEnumSet().FromRange(TestEnum::TEST_7_OUT_OF_BOUNDS,
598                                              TestEnum::TEST_6_OUT_OF_BOUNDS));
599   EXPECT_CHECK_DEATH(TestEnumSet().FromRange(TestEnum::TEST_6_OUT_OF_BOUNDS,
600                                              TestEnum::TEST_7_OUT_OF_BOUNDS));
601 }
602 
TEST_F(EnumSetDeathTest,PutCrashesOnOutOfRange)603 TEST_F(EnumSetDeathTest, PutCrashesOnOutOfRange) {
604   EXPECT_CHECK_DEATH(TestEnumSet().Put(TestEnum::TEST_BELOW_MIN));
605   EXPECT_CHECK_DEATH(TestEnumSet().Put(TestEnum::TEST_BELOW_MIN_NEGATIVE));
606   EXPECT_CHECK_DEATH(TestEnumSet().Put(TestEnum::TEST_6_OUT_OF_BOUNDS));
607   EXPECT_CHECK_DEATH(TestEnumSet().Put(TestEnum::TEST_7_OUT_OF_BOUNDS));
608 }
609 
TEST_F(EnumSetDeathTest,PutRangeCrashesOnBadInputs)610 TEST_F(EnumSetDeathTest, PutRangeCrashesOnBadInputs) {
611   // Crashes when one input is out of range.
612   EXPECT_CHECK_DEATH(TestEnumSet().PutRange(TestEnum::TEST_BELOW_MIN_NEGATIVE,
613                                             TestEnum::TEST_BELOW_MIN));
614   EXPECT_CHECK_DEATH(
615       TestEnumSet().PutRange(TestEnum::TEST_3, TestEnum::TEST_7_OUT_OF_BOUNDS));
616 
617   // Crashes when both inputs are out of range.
618   EXPECT_CHECK_DEATH(TestEnumSet().PutRange(TestEnum::TEST_6_OUT_OF_BOUNDS,
619                                             TestEnum::TEST_7_OUT_OF_BOUNDS));
620 
621   // Crashes when inputs are out of order.
622   EXPECT_CHECK_DEATH(
623       TestEnumSet().PutRange(TestEnum::TEST_2, TestEnum::TEST_1));
624 }
625 
TEST_F(EnumSetTest,ToStringEmpty)626 TEST_F(EnumSetTest, ToStringEmpty) {
627   const TestEnumSet enums;
628   EXPECT_THAT(enums.ToString(), testing::Eq("00000"));
629 }
630 
TEST_F(EnumSetTest,ToString)631 TEST_F(EnumSetTest, ToString) {
632   const TestEnumSet enums = {TestEnum::TEST_4};
633   EXPECT_THAT(enums.ToString(), testing::Eq("01000"));
634 }
635 
TEST_F(EnumSetTest,ToVectorEmpty)636 TEST_F(EnumSetTest, ToVectorEmpty) {
637   const TestEnumSet enums;
638   EXPECT_TRUE(ToVector(enums).empty());
639 }
640 
TEST_F(EnumSetTest,ToVector)641 TEST_F(EnumSetTest, ToVector) {
642   const TestEnumSet enums = {TestEnum::TEST_2, TestEnum::TEST_4};
643   EXPECT_THAT(ToVector(enums),
644               testing::ElementsAre(TestEnum::TEST_2, TestEnum::TEST_4));
645 }
646 
647 }  // namespace
648 }  // namespace base
649