enum_set_unittest.cc 21 KB

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