map_test.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "common/map.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. #include <initializer_list>
  8. #include <type_traits>
  9. #include <utility>
  10. #include <vector>
  11. #include "common/raw_hashtable_test_helpers.h"
  12. namespace Carbon::Testing {
  13. namespace {
  14. using RawHashtable::FixedHashKeyContext;
  15. using RawHashtable::IndexKeyContext;
  16. using RawHashtable::TestData;
  17. using RawHashtable::TestKeyContext;
  18. using ::testing::Pair;
  19. using ::testing::UnorderedElementsAreArray;
  20. template <typename MapT, typename MatcherRangeT>
  21. void ExpectMapElementsAre(MapT&& m, MatcherRangeT element_matchers) {
  22. // Now collect the elements into a container.
  23. using KeyT = typename std::remove_reference<MapT>::type::KeyT;
  24. using ValueT = typename std::remove_reference<MapT>::type::ValueT;
  25. std::vector<std::pair<KeyT, ValueT>> map_entries;
  26. m.ForEach([&map_entries](KeyT& k, ValueT& v) {
  27. map_entries.push_back({k, v});
  28. });
  29. // Use the GoogleMock unordered container matcher to validate and show errors
  30. // on wrong elements.
  31. EXPECT_THAT(map_entries, UnorderedElementsAreArray(element_matchers));
  32. }
  33. // Allow directly using an initializer list.
  34. template <typename MapT, typename MatcherT>
  35. void ExpectMapElementsAre(MapT&& m,
  36. std::initializer_list<MatcherT> element_matchers) {
  37. std::vector<MatcherT> element_matchers_storage = element_matchers;
  38. ExpectMapElementsAre(m, element_matchers_storage);
  39. }
  40. template <typename ValueCB, typename RangeT, typename... RangeTs>
  41. auto MakeKeyValues(ValueCB value_cb, RangeT&& range, RangeTs&&... ranges) {
  42. using KeyT = typename RangeT::value_type;
  43. using ValueT = decltype(value_cb(std::declval<KeyT>()));
  44. std::vector<std::pair<KeyT, ValueT>> elements;
  45. auto add_range = [&](RangeT&& r) {
  46. for (const auto&& e : r) {
  47. elements.push_back({e, value_cb(e)});
  48. }
  49. };
  50. add_range(std::forward<RangeT>(range));
  51. (add_range(std::forward<RangeT>(ranges)), ...);
  52. return elements;
  53. }
  54. template <typename MapT>
  55. class MapTest : public ::testing::Test {};
  56. using Types = ::testing::Types<
  57. Map<int, int>, Map<int, int, 16>, Map<int, int, 64>,
  58. Map<int, int, 0, TestKeyContext>, Map<int, int, 16, TestKeyContext>,
  59. Map<int, int, 64, TestKeyContext>, Map<TestData, TestData>,
  60. Map<TestData, TestData, 16>, Map<TestData, TestData, 0, TestKeyContext>,
  61. Map<TestData, TestData, 16, TestKeyContext>>;
  62. TYPED_TEST_SUITE(MapTest, Types);
  63. TYPED_TEST(MapTest, Basic) {
  64. TypeParam m;
  65. EXPECT_FALSE(m.Contains(42));
  66. EXPECT_EQ(nullptr, m[42]);
  67. EXPECT_TRUE(m.Insert(1, 100).is_inserted());
  68. ASSERT_TRUE(m.Contains(1));
  69. auto result = m.Lookup(1);
  70. EXPECT_TRUE(result);
  71. EXPECT_EQ(1, result.key());
  72. EXPECT_EQ(100, result.value());
  73. EXPECT_EQ(100, *m[1]);
  74. // Reinsertion doesn't change the value.
  75. auto i_result = m.Insert(1, 101);
  76. EXPECT_FALSE(i_result.is_inserted());
  77. EXPECT_EQ(100, i_result.value());
  78. EXPECT_EQ(100, *m[1]);
  79. // Update does change the value.
  80. i_result = m.Update(1, 101);
  81. EXPECT_FALSE(i_result.is_inserted());
  82. EXPECT_EQ(101, i_result.value());
  83. EXPECT_EQ(101, *m[1]);
  84. // Verify all the elements.
  85. ExpectMapElementsAre(m, {Pair(1, 101)});
  86. // Fill up a bunch to ensure we trigger growth a few times.
  87. for (int i : llvm::seq(2, 512)) {
  88. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  89. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  90. }
  91. ExpectMapElementsAre(
  92. m, MakeKeyValues([](int k) { return k * 100 + static_cast<int>(k == 1); },
  93. llvm::seq(1, 512)));
  94. for (int i : llvm::seq(1, 512)) {
  95. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  96. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  97. EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);
  98. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  99. EXPECT_EQ(i * 100 + 1, *m[i]);
  100. }
  101. EXPECT_FALSE(m.Contains(513));
  102. // Verify all the elements.
  103. ExpectMapElementsAre(
  104. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 512)));
  105. }
  106. TYPED_TEST(MapTest, FactoryAPI) {
  107. TypeParam m;
  108. EXPECT_TRUE(m.Insert(1, [] { return 100; }).is_inserted());
  109. ASSERT_TRUE(m.Contains(1));
  110. EXPECT_EQ(100, *m[1]);
  111. // Reinsertion doesn't invoke the callback.
  112. EXPECT_FALSE(m.Insert(1, []() -> int {
  113. llvm_unreachable("Should never be called!");
  114. }).is_inserted());
  115. // Update does invoke the callback.
  116. auto i_result = m.Update(1, [] { return 101; });
  117. EXPECT_FALSE(i_result.is_inserted());
  118. EXPECT_EQ(101, i_result.value());
  119. EXPECT_EQ(101, *m[1]);
  120. }
  121. TYPED_TEST(MapTest, Copy) {
  122. using MapT = TypeParam;
  123. MapT m;
  124. // Make sure we exceed the small size for some of the map types, but not all
  125. // of them, so we cover all the combinations of copying between small and
  126. // large.
  127. for (int i : llvm::seq(1, 24)) {
  128. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  129. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  130. }
  131. MapT other_m1 = m;
  132. ExpectMapElementsAre(
  133. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));
  134. // Add some more elements to the original.
  135. for (int i : llvm::seq(24, 32)) {
  136. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  137. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  138. }
  139. // The first copy doesn't change.
  140. ExpectMapElementsAre(
  141. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));
  142. // A new copy does.
  143. MapT other_m2 = m;
  144. ExpectMapElementsAre(
  145. other_m2, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  146. // Copy-assign updates.
  147. other_m1 = m;
  148. ExpectMapElementsAre(
  149. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  150. // Self-assign is a no-op.
  151. other_m1 = const_cast<const MapT&>(other_m1);
  152. ExpectMapElementsAre(
  153. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  154. // But mutating original still doesn't change copies.
  155. for (int i : llvm::seq(32, 48)) {
  156. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  157. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  158. }
  159. ExpectMapElementsAre(
  160. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  161. ExpectMapElementsAre(
  162. other_m2, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  163. }
  164. TYPED_TEST(MapTest, Move) {
  165. using MapT = TypeParam;
  166. MapT m;
  167. // Make sure we exceed the small size for some of the map types, but not all
  168. // of them, so we cover all the combinations of moving between small and
  169. // large.
  170. for (int i : llvm::seq(1, 24)) {
  171. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  172. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  173. }
  174. MapT other_m1 = std::move(m);
  175. ExpectMapElementsAre(
  176. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));
  177. // Add some more elements.
  178. for (int i : llvm::seq(24, 32)) {
  179. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  180. ASSERT_TRUE(other_m1.Insert(i, i * 100).is_inserted());
  181. }
  182. ExpectMapElementsAre(
  183. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  184. // Move back over a moved-from.
  185. m = std::move(other_m1);
  186. ExpectMapElementsAre(
  187. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  188. // Copy over moved-from state also works.
  189. other_m1 = m;
  190. ExpectMapElementsAre(
  191. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  192. // Now add still more elements.
  193. for (int i : llvm::seq(32, 48)) {
  194. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  195. ASSERT_TRUE(other_m1.Insert(i, i * 100).is_inserted());
  196. }
  197. ExpectMapElementsAre(
  198. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 48)));
  199. // And move-assign over the copy looks like the moved-from table not the copy.
  200. other_m1 = std::move(m);
  201. ExpectMapElementsAre(
  202. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  203. // Self-swap (which does a self-move) works and is a no-op.
  204. std::swap(other_m1, other_m1);
  205. ExpectMapElementsAre(
  206. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  207. // Test copying of a moved-from table over a valid table and self-move-assign.
  208. // The former is required to be valid, and the latter is in at least the case
  209. // of self-move-assign-when-moved-from, but the result can be in any state so
  210. // just do them and ensure we don't crash.
  211. MapT other_m2 = other_m1;
  212. // NOLINTNEXTLINE(bugprone-use-after-move): Testing required use-after-move.
  213. other_m2 = m;
  214. other_m1 = std::move(other_m1);
  215. m = std::move(m);
  216. }
  217. TYPED_TEST(MapTest, Conversions) {
  218. using MapT = TypeParam;
  219. using KeyT = MapT::KeyT;
  220. using ValueT = MapT::ValueT;
  221. using KeyContextT = MapT::KeyContextT;
  222. MapT m;
  223. ASSERT_TRUE(m.Insert(1, 101).is_inserted());
  224. ASSERT_TRUE(m.Insert(2, 102).is_inserted());
  225. ASSERT_TRUE(m.Insert(3, 103).is_inserted());
  226. ASSERT_TRUE(m.Insert(4, 104).is_inserted());
  227. MapView<KeyT, ValueT, KeyContextT> mv = m;
  228. MapView<const KeyT, ValueT, KeyContextT> cmv = m;
  229. MapView<KeyT, const ValueT, KeyContextT> cmv2 = m;
  230. MapView<const KeyT, const ValueT, KeyContextT> cmv3 = m;
  231. EXPECT_TRUE(mv.Contains(1));
  232. EXPECT_EQ(101, *mv[1]);
  233. EXPECT_TRUE(cmv.Contains(2));
  234. EXPECT_EQ(102, *cmv[2]);
  235. EXPECT_TRUE(cmv2.Contains(3));
  236. EXPECT_EQ(103, *cmv2[3]);
  237. EXPECT_TRUE(cmv3.Contains(4));
  238. EXPECT_EQ(104, *cmv3[4]);
  239. }
  240. TYPED_TEST(MapTest, GrowToAllocSize) {
  241. using MapT = TypeParam;
  242. MapT m;
  243. // Grow when empty. May be a no-op for some small sizes.
  244. m.GrowToAllocSize(32);
  245. // Add some elements that will need to be propagated through subsequent
  246. // growths. Also delete some.
  247. ssize_t storage_bytes = m.ComputeMetrics().storage_bytes;
  248. for (int i : llvm::seq(1, 24)) {
  249. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  250. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  251. }
  252. for (int i : llvm::seq(1, 8)) {
  253. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  254. ASSERT_TRUE(m.Erase(i));
  255. }
  256. // No further growth triggered.
  257. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  258. // No-op.
  259. m.GrowToAllocSize(16);
  260. ExpectMapElementsAre(
  261. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));
  262. // No further growth triggered.
  263. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  264. // Get a few doubling based growths, and at least one beyond the largest small
  265. // size.
  266. m.GrowToAllocSize(64);
  267. ExpectMapElementsAre(
  268. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));
  269. m.GrowToAllocSize(128);
  270. ExpectMapElementsAre(
  271. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));
  272. // Update the storage bytes after growth.
  273. EXPECT_LT(storage_bytes, m.ComputeMetrics().storage_bytes);
  274. storage_bytes = m.ComputeMetrics().storage_bytes;
  275. // Add some more, but not enough to trigger further growth, and then grow by
  276. // several more multiples of two to test handling large growth.
  277. for (int i : llvm::seq(24, 48)) {
  278. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  279. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  280. }
  281. for (int i : llvm::seq(8, 16)) {
  282. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  283. ASSERT_TRUE(m.Erase(i));
  284. }
  285. // No growth from insertions.
  286. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  287. m.GrowToAllocSize(1024);
  288. ExpectMapElementsAre(
  289. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(16, 48)));
  290. // Storage should have grown.
  291. EXPECT_LT(storage_bytes, m.ComputeMetrics().storage_bytes);
  292. }
  293. TYPED_TEST(MapTest, GrowForInsert) {
  294. using MapT = TypeParam;
  295. MapT m;
  296. m.GrowForInsertCount(42);
  297. ssize_t storage_bytes = m.ComputeMetrics().storage_bytes;
  298. for (int i : llvm::seq(1, 42)) {
  299. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  300. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  301. }
  302. ExpectMapElementsAre(
  303. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 42)));
  304. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  305. // Erase many elements and grow again for another insert.
  306. for (int i : llvm::seq(1, 32)) {
  307. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  308. ASSERT_TRUE(m.Erase(i));
  309. }
  310. m.GrowForInsertCount(42);
  311. storage_bytes = m.ComputeMetrics().storage_bytes;
  312. for (int i : llvm::seq(42, 84)) {
  313. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  314. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  315. }
  316. ExpectMapElementsAre(
  317. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(32, 84)));
  318. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  319. // Erase all the elements, then grow for a much larger insertion and insert
  320. // again.
  321. for (int i : llvm::seq(32, 84)) {
  322. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  323. ASSERT_TRUE(m.Erase(i));
  324. }
  325. m.GrowForInsertCount(321);
  326. storage_bytes = m.ComputeMetrics().storage_bytes;
  327. for (int i : llvm::seq(128, 321 + 128)) {
  328. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  329. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  330. }
  331. ExpectMapElementsAre(m, MakeKeyValues([](int k) { return k * 100; },
  332. llvm::seq(128, 321 + 128)));
  333. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  334. }
  335. // This test is largely exercising the underlying `RawHashtable` implementation
  336. // with complex growth, erasure, and re-growth.
  337. TYPED_TEST(MapTest, ComplexOpSequence) {
  338. // Use a small size as well to cover more growth scenarios.
  339. TypeParam m;
  340. EXPECT_FALSE(m.Contains(42));
  341. EXPECT_EQ(nullptr, m[42]);
  342. EXPECT_TRUE(m.Insert(1, 100).is_inserted());
  343. ASSERT_TRUE(m.Contains(1));
  344. auto result = m.Lookup(1);
  345. EXPECT_TRUE(result);
  346. EXPECT_EQ(1, result.key());
  347. EXPECT_EQ(100, result.value());
  348. EXPECT_EQ(100, *m[1]);
  349. // Reinsertion doesn't change the value.
  350. auto i_result = m.Insert(1, 101);
  351. EXPECT_FALSE(i_result.is_inserted());
  352. EXPECT_EQ(100, i_result.value());
  353. EXPECT_EQ(100, *m[1]);
  354. // Update does change the value.
  355. i_result = m.Update(1, 101);
  356. EXPECT_FALSE(i_result.is_inserted());
  357. EXPECT_EQ(101, i_result.value());
  358. EXPECT_EQ(101, *m[1]);
  359. // Verify all the elements.
  360. ExpectMapElementsAre(m, {Pair(1, 101)});
  361. // Fill up the small buffer but don't overflow it.
  362. for (int i : llvm::seq(2, 5)) {
  363. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  364. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  365. }
  366. for (int i : llvm::seq(1, 5)) {
  367. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  368. ASSERT_TRUE(m.Contains(i));
  369. EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);
  370. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  371. EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);
  372. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  373. EXPECT_EQ(i * 100 + 1, *m[i]);
  374. }
  375. EXPECT_FALSE(m.Contains(5));
  376. // Verify all the elements.
  377. ExpectMapElementsAre(
  378. m, {Pair(1, 101), Pair(2, 201), Pair(3, 301), Pair(4, 401)});
  379. // Erase some entries from the small buffer.
  380. EXPECT_FALSE(m.Erase(42));
  381. EXPECT_TRUE(m.Erase(2));
  382. EXPECT_EQ(101, *m[1]);
  383. EXPECT_EQ(nullptr, m[2]);
  384. EXPECT_EQ(301, *m[3]);
  385. EXPECT_EQ(401, *m[4]);
  386. EXPECT_TRUE(m.Erase(1));
  387. EXPECT_EQ(nullptr, m[1]);
  388. EXPECT_EQ(nullptr, m[2]);
  389. EXPECT_EQ(301, *m[3]);
  390. EXPECT_EQ(401, *m[4]);
  391. EXPECT_TRUE(m.Erase(4));
  392. EXPECT_EQ(nullptr, m[1]);
  393. EXPECT_EQ(nullptr, m[2]);
  394. EXPECT_EQ(301, *m[3]);
  395. EXPECT_EQ(nullptr, m[4]);
  396. // Fill them back in, but with a different order and going back to the
  397. // original value.
  398. EXPECT_TRUE(m.Insert(1, 100).is_inserted());
  399. EXPECT_TRUE(m.Insert(2, 200).is_inserted());
  400. EXPECT_TRUE(m.Insert(4, 400).is_inserted());
  401. EXPECT_EQ(100, *m[1]);
  402. EXPECT_EQ(200, *m[2]);
  403. EXPECT_EQ(301, *m[3]);
  404. EXPECT_EQ(400, *m[4]);
  405. // Then update their values to match.
  406. EXPECT_FALSE(m.Update(1, 101).is_inserted());
  407. EXPECT_FALSE(m.Update(2, 201).is_inserted());
  408. EXPECT_FALSE(m.Update(4, 401).is_inserted());
  409. // Now fill up the first metadata group.
  410. for (int i : llvm::seq(5, 14)) {
  411. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  412. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  413. }
  414. for (int i : llvm::seq(1, 14)) {
  415. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  416. ASSERT_TRUE(m.Contains(i));
  417. EXPECT_EQ(i * 100 + static_cast<int>(i < 5), *m[i]);
  418. EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());
  419. EXPECT_EQ(i * 100 + static_cast<int>(i < 5), *m[i]);
  420. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  421. EXPECT_EQ(i * 100 + 2, *m[i]);
  422. }
  423. EXPECT_FALSE(m.Contains(42));
  424. // Verify all the elements by walking the entire map.
  425. ExpectMapElementsAre(
  426. m, {Pair(1, 102), Pair(2, 202), Pair(3, 302), Pair(4, 402), Pair(5, 502),
  427. Pair(6, 602), Pair(7, 702), Pair(8, 802), Pair(9, 902),
  428. Pair(10, 1002), Pair(11, 1102), Pair(12, 1202), Pair(13, 1302)});
  429. // Now fill up several more groups.
  430. for (int i : llvm::seq(14, 100)) {
  431. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  432. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  433. }
  434. for (int i : llvm::seq(1, 100)) {
  435. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  436. ASSERT_TRUE(m.Contains(i));
  437. EXPECT_EQ(i * 100 + 2 * static_cast<int>(i < 14), *m[i]);
  438. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  439. EXPECT_EQ(i * 100 + 2 * static_cast<int>(i < 14), *m[i]);
  440. EXPECT_FALSE(m.Update(i, i * 100 + 3).is_inserted());
  441. EXPECT_EQ(i * 100 + 3, *m[i]);
  442. }
  443. EXPECT_FALSE(m.Contains(420));
  444. // Check walking the entire container.
  445. ExpectMapElementsAre(
  446. m, MakeKeyValues([](int k) { return k * 100 + 3; }, llvm::seq(1, 100)));
  447. // Clear back to empty.
  448. m.Clear();
  449. EXPECT_FALSE(m.Contains(42));
  450. EXPECT_EQ(nullptr, m[42]);
  451. // Refill but with both overlapping and different values.
  452. for (int i : llvm::seq(50, 150)) {
  453. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  454. }
  455. for (int i : llvm::seq(50, 150)) {
  456. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  457. ASSERT_TRUE(m.Contains(i));
  458. EXPECT_EQ(i * 100, *m[i]);
  459. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  460. EXPECT_EQ(i * 100, *m[i]);
  461. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  462. EXPECT_EQ(i * 100 + 1, *m[i]);
  463. }
  464. EXPECT_FALSE(m.Contains(42));
  465. EXPECT_FALSE(m.Contains(420));
  466. ExpectMapElementsAre(
  467. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(50, 150)));
  468. EXPECT_FALSE(m.Erase(42));
  469. EXPECT_TRUE(m.Contains(73));
  470. EXPECT_TRUE(m.Erase(73));
  471. EXPECT_FALSE(m.Contains(73));
  472. for (int i : llvm::seq(102, 136)) {
  473. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  474. EXPECT_TRUE(m.Contains(i));
  475. EXPECT_TRUE(m.Erase(i));
  476. EXPECT_FALSE(m.Contains(i));
  477. }
  478. for (int i : llvm::seq(50, 150)) {
  479. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  480. if (i == 73 || (i >= 102 && i < 136)) {
  481. continue;
  482. }
  483. ASSERT_TRUE(m.Contains(i));
  484. EXPECT_EQ(i * 100 + 1, *m[i]);
  485. EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());
  486. EXPECT_EQ(i * 100 + 1, *m[i]);
  487. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  488. EXPECT_EQ(i * 100 + 2, *m[i]);
  489. }
  490. EXPECT_TRUE(m.Insert(73, 73 * 100 + 3).is_inserted());
  491. EXPECT_EQ(73 * 100 + 3, *m[73]);
  492. ExpectMapElementsAre(
  493. m, MakeKeyValues([](int k) { return k * 100 + 2 + (k == 73); },
  494. llvm::seq(50, 102), llvm::seq(136, 150)));
  495. // Reset back to empty and small.
  496. m.Reset();
  497. EXPECT_FALSE(m.Contains(42));
  498. EXPECT_EQ(nullptr, m[42]);
  499. // Refill but with both overlapping and different values, now triggering
  500. // growth too. Also, use update instead of insert.
  501. for (int i : llvm::seq(75, 175)) {
  502. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  503. EXPECT_TRUE(m.Update(i, i * 100).is_inserted());
  504. }
  505. for (int i : llvm::seq(75, 175)) {
  506. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  507. ASSERT_TRUE(m.Contains(i));
  508. EXPECT_EQ(i * 100, *m[i]);
  509. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  510. EXPECT_EQ(i * 100, *m[i]);
  511. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  512. EXPECT_EQ(i * 100 + 1, *m[i]);
  513. }
  514. EXPECT_FALSE(m.Contains(42));
  515. EXPECT_FALSE(m.Contains(420));
  516. ExpectMapElementsAre(
  517. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(75, 175)));
  518. EXPECT_FALSE(m.Erase(42));
  519. EXPECT_TRUE(m.Contains(93));
  520. EXPECT_TRUE(m.Erase(93));
  521. EXPECT_FALSE(m.Contains(93));
  522. for (int i : llvm::seq(102, 136)) {
  523. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  524. EXPECT_TRUE(m.Contains(i));
  525. EXPECT_TRUE(m.Erase(i));
  526. EXPECT_FALSE(m.Contains(i));
  527. }
  528. for (int i : llvm::seq(75, 175)) {
  529. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  530. if (i == 93 || (i >= 102 && i < 136)) {
  531. continue;
  532. }
  533. ASSERT_TRUE(m.Contains(i));
  534. EXPECT_EQ(i * 100 + 1, *m[i]);
  535. EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());
  536. EXPECT_EQ(i * 100 + 1, *m[i]);
  537. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  538. EXPECT_EQ(i * 100 + 2, *m[i]);
  539. }
  540. EXPECT_TRUE(m.Insert(93, 93 * 100 + 3).is_inserted());
  541. EXPECT_EQ(93 * 100 + 3, *m[93]);
  542. ExpectMapElementsAre(
  543. m, MakeKeyValues([](int k) { return k * 100 + 2 + (k == 93); },
  544. llvm::seq(75, 102), llvm::seq(136, 175)));
  545. }
  546. template <typename MapT>
  547. class MapCollisionTest : public ::testing::Test {};
  548. using CollisionTypes = ::testing::Types<
  549. Map<int, int, 16,
  550. FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ false, 0>>,
  551. Map<int, int, 16,
  552. FixedHashKeyContext<7, /*FixIndexBits*/ false, /*FixTagBits*/ true, 0>>,
  553. Map<int, int, 16,
  554. FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ true, 0>>,
  555. Map<int, int, 16,
  556. FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ true,
  557. ~static_cast<uint64_t>(0)>>>;
  558. TYPED_TEST_SUITE(MapCollisionTest, CollisionTypes);
  559. TYPED_TEST(MapCollisionTest, Basic) {
  560. TypeParam m;
  561. // Fill the map through a couple of growth steps, verifying at each step. Note
  562. // that because this is a collision test, we synthesize actively harmful
  563. // hashes in terms of collisions and so this test is essentially quadratic. We
  564. // need to keep it relatively small.
  565. for (int i : llvm::seq(1, 256)) {
  566. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  567. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  568. }
  569. ExpectMapElementsAre(
  570. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 256)));
  571. // Erase and re-fill from the back.
  572. for (int i : llvm::seq(192, 256)) {
  573. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  574. EXPECT_TRUE(m.Erase(i));
  575. }
  576. ExpectMapElementsAre(
  577. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 192)));
  578. for (int i : llvm::seq(192, 256)) {
  579. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  580. EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());
  581. }
  582. ExpectMapElementsAre(m,
  583. MakeKeyValues([](int k) { return k * 100 + (k >= 192); },
  584. llvm::seq(1, 256)));
  585. // Erase and re-fill from the front.
  586. for (int i : llvm::seq(1, 64)) {
  587. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  588. EXPECT_TRUE(m.Erase(i));
  589. }
  590. ExpectMapElementsAre(m,
  591. MakeKeyValues([](int k) { return k * 100 + (k >= 192); },
  592. llvm::seq(64, 256)));
  593. for (int i : llvm::seq(1, 64)) {
  594. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  595. EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());
  596. }
  597. ExpectMapElementsAre(
  598. m, MakeKeyValues([](int k) { return k * 100 + (k < 64) + (k >= 192); },
  599. llvm::seq(1, 256)));
  600. // Erase and re-fill from the middle.
  601. for (int i : llvm::seq(64, 192)) {
  602. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  603. EXPECT_TRUE(m.Erase(i));
  604. }
  605. ExpectMapElementsAre(m, MakeKeyValues([](int k) { return k * 100 + 1; },
  606. llvm::seq(1, 64), llvm::seq(192, 256)));
  607. for (int i : llvm::seq(64, 192)) {
  608. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  609. EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());
  610. }
  611. ExpectMapElementsAre(
  612. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 256)));
  613. // Erase and re-fill from both the back and front.
  614. for (auto s : {llvm::seq(192, 256), llvm::seq(1, 64)}) {
  615. for (int i : s) {
  616. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  617. EXPECT_TRUE(m.Erase(i));
  618. }
  619. }
  620. ExpectMapElementsAre(
  621. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(64, 192)));
  622. for (auto s : {llvm::seq(192, 256), llvm::seq(1, 64)}) {
  623. for (int i : s) {
  624. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  625. EXPECT_TRUE(m.Insert(i, i * 100 + 2).is_inserted());
  626. }
  627. }
  628. ExpectMapElementsAre(
  629. m,
  630. MakeKeyValues([](int k) { return k * 100 + 1 + (k < 64) + (k >= 192); },
  631. llvm::seq(1, 256)));
  632. // And update the middle elements in place.
  633. for (int i : llvm::seq(64, 192)) {
  634. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  635. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  636. }
  637. ExpectMapElementsAre(
  638. m, MakeKeyValues([](int k) { return k * 100 + 2; }, llvm::seq(1, 256)));
  639. }
  640. TEST(MapContextTest, Basic) {
  641. llvm::SmallVector<TestData> keys;
  642. for (int i : llvm::seq(0, 513)) {
  643. keys.push_back(i * 100000);
  644. }
  645. IndexKeyContext<TestData> key_context(keys);
  646. Map<ssize_t, int, 0, IndexKeyContext<TestData>> m;
  647. EXPECT_FALSE(m.Contains(42, key_context));
  648. EXPECT_TRUE(m.Insert(1, 100, key_context).is_inserted());
  649. ASSERT_TRUE(m.Contains(1, key_context));
  650. auto result = m.Lookup(TestData(100000), key_context);
  651. EXPECT_TRUE(result);
  652. EXPECT_EQ(1, result.key());
  653. EXPECT_EQ(100, result.value());
  654. // Reinsertion doesn't change the value. Also, double check a temporary
  655. // context.
  656. auto i_result = m.Insert(1, 101, IndexKeyContext<TestData>(keys));
  657. EXPECT_FALSE(i_result.is_inserted());
  658. EXPECT_EQ(100, i_result.value());
  659. // Update does change the value.
  660. i_result = m.Update(1, 101, key_context);
  661. EXPECT_FALSE(i_result.is_inserted());
  662. EXPECT_EQ(101, i_result.value());
  663. // Verify all the elements.
  664. ExpectMapElementsAre(m, {Pair(1, 101)});
  665. // Fill up a bunch to ensure we trigger growth a few times.
  666. for (int i : llvm::seq(2, 512)) {
  667. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  668. EXPECT_TRUE(m.Insert(i, i * 100, key_context).is_inserted());
  669. }
  670. // Check all the elements, including using the context.
  671. for (int j : llvm::seq(1, 512)) {
  672. SCOPED_TRACE(llvm::formatv("Assert key: {0}", j).str());
  673. ASSERT_EQ(j * 100 + static_cast<int>(j == 1),
  674. m.Lookup(j, key_context).value());
  675. ASSERT_EQ(j * 100 + static_cast<int>(j == 1),
  676. m.Lookup(TestData(j * 100000), key_context).value());
  677. }
  678. for (int i : llvm::seq(1, 512)) {
  679. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  680. EXPECT_FALSE(m.Insert(i, i * 100 + 1, key_context).is_inserted());
  681. EXPECT_EQ(i * 100 + static_cast<int>(i == 1),
  682. m.Lookup(i, key_context).value());
  683. EXPECT_FALSE(m.Update(i, i * 100 + 1, key_context).is_inserted());
  684. EXPECT_EQ(i * 100 + 1, m.Lookup(i, key_context).value());
  685. }
  686. EXPECT_FALSE(m.Contains(0, key_context));
  687. EXPECT_FALSE(m.Contains(512, key_context));
  688. // Verify all the elements.
  689. ExpectMapElementsAre(
  690. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 512)));
  691. }
  692. } // namespace
  693. } // namespace Carbon::Testing