map_test.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  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. }
  147. TYPED_TEST(MapTest, Move) {
  148. using MapT = TypeParam;
  149. MapT m;
  150. // Make sure we exceed the small size for some of the map types, but not all
  151. // of them, so we cover all the combinations of moving between small and
  152. // large.
  153. for (int i : llvm::seq(1, 24)) {
  154. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  155. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  156. }
  157. MapT other_m1 = std::move(m);
  158. ExpectMapElementsAre(
  159. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));
  160. // Add some more elements.
  161. for (int i : llvm::seq(24, 32)) {
  162. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  163. ASSERT_TRUE(other_m1.Insert(i, i * 100).is_inserted());
  164. }
  165. ExpectMapElementsAre(
  166. other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));
  167. }
  168. TYPED_TEST(MapTest, Conversions) {
  169. using MapT = TypeParam;
  170. using KeyT = MapT::KeyT;
  171. using ValueT = MapT::ValueT;
  172. using KeyContextT = MapT::KeyContextT;
  173. MapT m;
  174. ASSERT_TRUE(m.Insert(1, 101).is_inserted());
  175. ASSERT_TRUE(m.Insert(2, 102).is_inserted());
  176. ASSERT_TRUE(m.Insert(3, 103).is_inserted());
  177. ASSERT_TRUE(m.Insert(4, 104).is_inserted());
  178. MapView<KeyT, ValueT, KeyContextT> mv = m;
  179. MapView<const KeyT, ValueT, KeyContextT> cmv = m;
  180. MapView<KeyT, const ValueT, KeyContextT> cmv2 = m;
  181. MapView<const KeyT, const ValueT, KeyContextT> cmv3 = m;
  182. EXPECT_TRUE(mv.Contains(1));
  183. EXPECT_EQ(101, *mv[1]);
  184. EXPECT_TRUE(cmv.Contains(2));
  185. EXPECT_EQ(102, *cmv[2]);
  186. EXPECT_TRUE(cmv2.Contains(3));
  187. EXPECT_EQ(103, *cmv2[3]);
  188. EXPECT_TRUE(cmv3.Contains(4));
  189. EXPECT_EQ(104, *cmv3[4]);
  190. }
  191. TYPED_TEST(MapTest, GrowToAllocSize) {
  192. using MapT = TypeParam;
  193. MapT m;
  194. // Grow when empty. May be a no-op for some small sizes.
  195. m.GrowToAllocSize(32);
  196. // Add some elements that will need to be propagated through subsequent
  197. // growths. Also delete some.
  198. ssize_t storage_bytes = m.ComputeMetrics().storage_bytes;
  199. for (int i : llvm::seq(1, 24)) {
  200. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  201. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  202. }
  203. for (int i : llvm::seq(1, 8)) {
  204. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  205. ASSERT_TRUE(m.Erase(i));
  206. }
  207. // No further growth triggered.
  208. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  209. // No-op.
  210. m.GrowToAllocSize(16);
  211. ExpectMapElementsAre(
  212. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));
  213. // No further growth triggered.
  214. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  215. // Get a few doubling based growths, and at least one beyond the largest small
  216. // size.
  217. m.GrowToAllocSize(64);
  218. ExpectMapElementsAre(
  219. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));
  220. m.GrowToAllocSize(128);
  221. ExpectMapElementsAre(
  222. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));
  223. // Update the storage bytes after growth.
  224. EXPECT_LT(storage_bytes, m.ComputeMetrics().storage_bytes);
  225. storage_bytes = m.ComputeMetrics().storage_bytes;
  226. // Add some more, but not enough to trigger further growth, and then grow by
  227. // several more multiples of two to test handling large growth.
  228. for (int i : llvm::seq(24, 48)) {
  229. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  230. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  231. }
  232. for (int i : llvm::seq(8, 16)) {
  233. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  234. ASSERT_TRUE(m.Erase(i));
  235. }
  236. // No growth from insertions.
  237. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  238. m.GrowToAllocSize(1024);
  239. ExpectMapElementsAre(
  240. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(16, 48)));
  241. // Storage should have grown.
  242. EXPECT_LT(storage_bytes, m.ComputeMetrics().storage_bytes);
  243. }
  244. TYPED_TEST(MapTest, GrowForInsert) {
  245. using MapT = TypeParam;
  246. MapT m;
  247. m.GrowForInsertCount(42);
  248. ssize_t storage_bytes = m.ComputeMetrics().storage_bytes;
  249. for (int i : llvm::seq(1, 42)) {
  250. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  251. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  252. }
  253. ExpectMapElementsAre(
  254. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 42)));
  255. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  256. // Erase many elements and grow again for another insert.
  257. for (int i : llvm::seq(1, 32)) {
  258. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  259. ASSERT_TRUE(m.Erase(i));
  260. }
  261. m.GrowForInsertCount(42);
  262. storage_bytes = m.ComputeMetrics().storage_bytes;
  263. for (int i : llvm::seq(42, 84)) {
  264. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  265. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  266. }
  267. ExpectMapElementsAre(
  268. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(32, 84)));
  269. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  270. // Erase all the elements, then grow for a much larger insertion and insert
  271. // again.
  272. for (int i : llvm::seq(32, 84)) {
  273. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  274. ASSERT_TRUE(m.Erase(i));
  275. }
  276. m.GrowForInsertCount(321);
  277. storage_bytes = m.ComputeMetrics().storage_bytes;
  278. for (int i : llvm::seq(128, 321 + 128)) {
  279. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  280. ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());
  281. }
  282. ExpectMapElementsAre(m, MakeKeyValues([](int k) { return k * 100; },
  283. llvm::seq(128, 321 + 128)));
  284. EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);
  285. }
  286. // This test is largely exercising the underlying `RawHashtable` implementation
  287. // with complex growth, erasure, and re-growth.
  288. TYPED_TEST(MapTest, ComplexOpSequence) {
  289. // Use a small size as well to cover more growth scenarios.
  290. TypeParam m;
  291. EXPECT_FALSE(m.Contains(42));
  292. EXPECT_EQ(nullptr, m[42]);
  293. EXPECT_TRUE(m.Insert(1, 100).is_inserted());
  294. ASSERT_TRUE(m.Contains(1));
  295. auto result = m.Lookup(1);
  296. EXPECT_TRUE(result);
  297. EXPECT_EQ(1, result.key());
  298. EXPECT_EQ(100, result.value());
  299. EXPECT_EQ(100, *m[1]);
  300. // Reinsertion doesn't change the value.
  301. auto i_result = m.Insert(1, 101);
  302. EXPECT_FALSE(i_result.is_inserted());
  303. EXPECT_EQ(100, i_result.value());
  304. EXPECT_EQ(100, *m[1]);
  305. // Update does change the value.
  306. i_result = m.Update(1, 101);
  307. EXPECT_FALSE(i_result.is_inserted());
  308. EXPECT_EQ(101, i_result.value());
  309. EXPECT_EQ(101, *m[1]);
  310. // Verify all the elements.
  311. ExpectMapElementsAre(m, {Pair(1, 101)});
  312. // Fill up the small buffer but don't overflow it.
  313. for (int i : llvm::seq(2, 5)) {
  314. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  315. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  316. }
  317. for (int i : llvm::seq(1, 5)) {
  318. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  319. ASSERT_TRUE(m.Contains(i));
  320. EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);
  321. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  322. EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);
  323. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  324. EXPECT_EQ(i * 100 + 1, *m[i]);
  325. }
  326. EXPECT_FALSE(m.Contains(5));
  327. // Verify all the elements.
  328. ExpectMapElementsAre(
  329. m, {Pair(1, 101), Pair(2, 201), Pair(3, 301), Pair(4, 401)});
  330. // Erase some entries from the small buffer.
  331. EXPECT_FALSE(m.Erase(42));
  332. EXPECT_TRUE(m.Erase(2));
  333. EXPECT_EQ(101, *m[1]);
  334. EXPECT_EQ(nullptr, m[2]);
  335. EXPECT_EQ(301, *m[3]);
  336. EXPECT_EQ(401, *m[4]);
  337. EXPECT_TRUE(m.Erase(1));
  338. EXPECT_EQ(nullptr, m[1]);
  339. EXPECT_EQ(nullptr, m[2]);
  340. EXPECT_EQ(301, *m[3]);
  341. EXPECT_EQ(401, *m[4]);
  342. EXPECT_TRUE(m.Erase(4));
  343. EXPECT_EQ(nullptr, m[1]);
  344. EXPECT_EQ(nullptr, m[2]);
  345. EXPECT_EQ(301, *m[3]);
  346. EXPECT_EQ(nullptr, m[4]);
  347. // Fill them back in, but with a different order and going back to the
  348. // original value.
  349. EXPECT_TRUE(m.Insert(1, 100).is_inserted());
  350. EXPECT_TRUE(m.Insert(2, 200).is_inserted());
  351. EXPECT_TRUE(m.Insert(4, 400).is_inserted());
  352. EXPECT_EQ(100, *m[1]);
  353. EXPECT_EQ(200, *m[2]);
  354. EXPECT_EQ(301, *m[3]);
  355. EXPECT_EQ(400, *m[4]);
  356. // Then update their values to match.
  357. EXPECT_FALSE(m.Update(1, 101).is_inserted());
  358. EXPECT_FALSE(m.Update(2, 201).is_inserted());
  359. EXPECT_FALSE(m.Update(4, 401).is_inserted());
  360. // Now fill up the first metadata group.
  361. for (int i : llvm::seq(5, 14)) {
  362. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  363. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  364. }
  365. for (int i : llvm::seq(1, 14)) {
  366. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  367. ASSERT_TRUE(m.Contains(i));
  368. EXPECT_EQ(i * 100 + static_cast<int>(i < 5), *m[i]);
  369. EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());
  370. EXPECT_EQ(i * 100 + static_cast<int>(i < 5), *m[i]);
  371. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  372. EXPECT_EQ(i * 100 + 2, *m[i]);
  373. }
  374. EXPECT_FALSE(m.Contains(42));
  375. // Verify all the elements by walking the entire map.
  376. ExpectMapElementsAre(
  377. m, {Pair(1, 102), Pair(2, 202), Pair(3, 302), Pair(4, 402), Pair(5, 502),
  378. Pair(6, 602), Pair(7, 702), Pair(8, 802), Pair(9, 902),
  379. Pair(10, 1002), Pair(11, 1102), Pair(12, 1202), Pair(13, 1302)});
  380. // Now fill up several more groups.
  381. for (int i : llvm::seq(14, 100)) {
  382. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  383. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  384. }
  385. for (int i : llvm::seq(1, 100)) {
  386. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  387. ASSERT_TRUE(m.Contains(i));
  388. EXPECT_EQ(i * 100 + 2 * static_cast<int>(i < 14), *m[i]);
  389. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  390. EXPECT_EQ(i * 100 + 2 * static_cast<int>(i < 14), *m[i]);
  391. EXPECT_FALSE(m.Update(i, i * 100 + 3).is_inserted());
  392. EXPECT_EQ(i * 100 + 3, *m[i]);
  393. }
  394. EXPECT_FALSE(m.Contains(420));
  395. // Check walking the entire container.
  396. ExpectMapElementsAre(
  397. m, MakeKeyValues([](int k) { return k * 100 + 3; }, llvm::seq(1, 100)));
  398. // Clear back to empty.
  399. m.Clear();
  400. EXPECT_FALSE(m.Contains(42));
  401. EXPECT_EQ(nullptr, m[42]);
  402. // Refill but with both overlapping and different values.
  403. for (int i : llvm::seq(50, 150)) {
  404. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  405. }
  406. for (int i : llvm::seq(50, 150)) {
  407. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  408. ASSERT_TRUE(m.Contains(i));
  409. EXPECT_EQ(i * 100, *m[i]);
  410. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  411. EXPECT_EQ(i * 100, *m[i]);
  412. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  413. EXPECT_EQ(i * 100 + 1, *m[i]);
  414. }
  415. EXPECT_FALSE(m.Contains(42));
  416. EXPECT_FALSE(m.Contains(420));
  417. ExpectMapElementsAre(
  418. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(50, 150)));
  419. EXPECT_FALSE(m.Erase(42));
  420. EXPECT_TRUE(m.Contains(73));
  421. EXPECT_TRUE(m.Erase(73));
  422. EXPECT_FALSE(m.Contains(73));
  423. for (int i : llvm::seq(102, 136)) {
  424. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  425. EXPECT_TRUE(m.Contains(i));
  426. EXPECT_TRUE(m.Erase(i));
  427. EXPECT_FALSE(m.Contains(i));
  428. }
  429. for (int i : llvm::seq(50, 150)) {
  430. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  431. if (i == 73 || (i >= 102 && i < 136)) {
  432. continue;
  433. }
  434. ASSERT_TRUE(m.Contains(i));
  435. EXPECT_EQ(i * 100 + 1, *m[i]);
  436. EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());
  437. EXPECT_EQ(i * 100 + 1, *m[i]);
  438. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  439. EXPECT_EQ(i * 100 + 2, *m[i]);
  440. }
  441. EXPECT_TRUE(m.Insert(73, 73 * 100 + 3).is_inserted());
  442. EXPECT_EQ(73 * 100 + 3, *m[73]);
  443. ExpectMapElementsAre(
  444. m, MakeKeyValues([](int k) { return k * 100 + 2 + (k == 73); },
  445. llvm::seq(50, 102), llvm::seq(136, 150)));
  446. // Reset back to empty and small.
  447. m.Reset();
  448. EXPECT_FALSE(m.Contains(42));
  449. EXPECT_EQ(nullptr, m[42]);
  450. // Refill but with both overlapping and different values, now triggering
  451. // growth too. Also, use update instead of insert.
  452. for (int i : llvm::seq(75, 175)) {
  453. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  454. EXPECT_TRUE(m.Update(i, i * 100).is_inserted());
  455. }
  456. for (int i : llvm::seq(75, 175)) {
  457. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  458. ASSERT_TRUE(m.Contains(i));
  459. EXPECT_EQ(i * 100, *m[i]);
  460. EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());
  461. EXPECT_EQ(i * 100, *m[i]);
  462. EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());
  463. EXPECT_EQ(i * 100 + 1, *m[i]);
  464. }
  465. EXPECT_FALSE(m.Contains(42));
  466. EXPECT_FALSE(m.Contains(420));
  467. ExpectMapElementsAre(
  468. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(75, 175)));
  469. EXPECT_FALSE(m.Erase(42));
  470. EXPECT_TRUE(m.Contains(93));
  471. EXPECT_TRUE(m.Erase(93));
  472. EXPECT_FALSE(m.Contains(93));
  473. for (int i : llvm::seq(102, 136)) {
  474. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  475. EXPECT_TRUE(m.Contains(i));
  476. EXPECT_TRUE(m.Erase(i));
  477. EXPECT_FALSE(m.Contains(i));
  478. }
  479. for (int i : llvm::seq(75, 175)) {
  480. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  481. if (i == 93 || (i >= 102 && i < 136)) {
  482. continue;
  483. }
  484. ASSERT_TRUE(m.Contains(i));
  485. EXPECT_EQ(i * 100 + 1, *m[i]);
  486. EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());
  487. EXPECT_EQ(i * 100 + 1, *m[i]);
  488. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  489. EXPECT_EQ(i * 100 + 2, *m[i]);
  490. }
  491. EXPECT_TRUE(m.Insert(93, 93 * 100 + 3).is_inserted());
  492. EXPECT_EQ(93 * 100 + 3, *m[93]);
  493. ExpectMapElementsAre(
  494. m, MakeKeyValues([](int k) { return k * 100 + 2 + (k == 93); },
  495. llvm::seq(75, 102), llvm::seq(136, 175)));
  496. }
  497. template <typename MapT>
  498. class MapCollisionTest : public ::testing::Test {};
  499. using CollisionTypes = ::testing::Types<
  500. Map<int, int, 16,
  501. FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ false, 0>>,
  502. Map<int, int, 16,
  503. FixedHashKeyContext<7, /*FixIndexBits*/ false, /*FixTagBits*/ true, 0>>,
  504. Map<int, int, 16,
  505. FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ true, 0>>,
  506. Map<int, int, 16,
  507. FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ true,
  508. ~static_cast<uint64_t>(0)>>>;
  509. TYPED_TEST_SUITE(MapCollisionTest, CollisionTypes);
  510. TYPED_TEST(MapCollisionTest, Basic) {
  511. TypeParam m;
  512. // Fill the map through a couple of growth steps, verifying at each step. Note
  513. // that because this is a collision test, we synthesize actively harmful
  514. // hashes in terms of collisions and so this test is essentially quadratic. We
  515. // need to keep it relatively small.
  516. for (int i : llvm::seq(1, 256)) {
  517. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  518. EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());
  519. }
  520. ExpectMapElementsAre(
  521. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 256)));
  522. // Erase and re-fill from the back.
  523. for (int i : llvm::seq(192, 256)) {
  524. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  525. EXPECT_TRUE(m.Erase(i));
  526. }
  527. ExpectMapElementsAre(
  528. m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 192)));
  529. for (int i : llvm::seq(192, 256)) {
  530. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  531. EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());
  532. }
  533. ExpectMapElementsAre(m,
  534. MakeKeyValues([](int k) { return k * 100 + (k >= 192); },
  535. llvm::seq(1, 256)));
  536. // Erase and re-fill from the front.
  537. for (int i : llvm::seq(1, 64)) {
  538. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  539. EXPECT_TRUE(m.Erase(i));
  540. }
  541. ExpectMapElementsAre(m,
  542. MakeKeyValues([](int k) { return k * 100 + (k >= 192); },
  543. llvm::seq(64, 256)));
  544. for (int i : llvm::seq(1, 64)) {
  545. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  546. EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());
  547. }
  548. ExpectMapElementsAre(
  549. m, MakeKeyValues([](int k) { return k * 100 + (k < 64) + (k >= 192); },
  550. llvm::seq(1, 256)));
  551. // Erase and re-fill from the middle.
  552. for (int i : llvm::seq(64, 192)) {
  553. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  554. EXPECT_TRUE(m.Erase(i));
  555. }
  556. ExpectMapElementsAre(m, MakeKeyValues([](int k) { return k * 100 + 1; },
  557. llvm::seq(1, 64), llvm::seq(192, 256)));
  558. for (int i : llvm::seq(64, 192)) {
  559. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  560. EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());
  561. }
  562. ExpectMapElementsAre(
  563. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 256)));
  564. // Erase and re-fill from both the back and front.
  565. for (auto s : {llvm::seq(192, 256), llvm::seq(1, 64)}) {
  566. for (int i : s) {
  567. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  568. EXPECT_TRUE(m.Erase(i));
  569. }
  570. }
  571. ExpectMapElementsAre(
  572. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(64, 192)));
  573. for (auto s : {llvm::seq(192, 256), llvm::seq(1, 64)}) {
  574. for (int i : s) {
  575. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  576. EXPECT_TRUE(m.Insert(i, i * 100 + 2).is_inserted());
  577. }
  578. }
  579. ExpectMapElementsAre(
  580. m,
  581. MakeKeyValues([](int k) { return k * 100 + 1 + (k < 64) + (k >= 192); },
  582. llvm::seq(1, 256)));
  583. // And update the middle elements in place.
  584. for (int i : llvm::seq(64, 192)) {
  585. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  586. EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());
  587. }
  588. ExpectMapElementsAre(
  589. m, MakeKeyValues([](int k) { return k * 100 + 2; }, llvm::seq(1, 256)));
  590. }
  591. TEST(MapContextTest, Basic) {
  592. llvm::SmallVector<TestData> keys;
  593. for (int i : llvm::seq(0, 513)) {
  594. keys.push_back(i * 100000);
  595. }
  596. IndexKeyContext<TestData> key_context(keys);
  597. Map<ssize_t, int, 0, IndexKeyContext<TestData>> m;
  598. EXPECT_FALSE(m.Contains(42, key_context));
  599. EXPECT_TRUE(m.Insert(1, 100, key_context).is_inserted());
  600. ASSERT_TRUE(m.Contains(1, key_context));
  601. auto result = m.Lookup(TestData(100000), key_context);
  602. EXPECT_TRUE(result);
  603. EXPECT_EQ(1, result.key());
  604. EXPECT_EQ(100, result.value());
  605. // Reinsertion doesn't change the value. Also, double check a temporary
  606. // context.
  607. auto i_result = m.Insert(1, 101, IndexKeyContext<TestData>(keys));
  608. EXPECT_FALSE(i_result.is_inserted());
  609. EXPECT_EQ(100, i_result.value());
  610. // Update does change the value.
  611. i_result = m.Update(1, 101, key_context);
  612. EXPECT_FALSE(i_result.is_inserted());
  613. EXPECT_EQ(101, i_result.value());
  614. // Verify all the elements.
  615. ExpectMapElementsAre(m, {Pair(1, 101)});
  616. // Fill up a bunch to ensure we trigger growth a few times.
  617. for (int i : llvm::seq(2, 512)) {
  618. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  619. EXPECT_TRUE(m.Insert(i, i * 100, key_context).is_inserted());
  620. }
  621. // Check all the elements, including using the context.
  622. for (int j : llvm::seq(1, 512)) {
  623. SCOPED_TRACE(llvm::formatv("Assert key: {0}", j).str());
  624. ASSERT_EQ(j * 100 + static_cast<int>(j == 1),
  625. m.Lookup(j, key_context).value());
  626. ASSERT_EQ(j * 100 + static_cast<int>(j == 1),
  627. m.Lookup(TestData(j * 100000), key_context).value());
  628. }
  629. for (int i : llvm::seq(1, 512)) {
  630. SCOPED_TRACE(llvm::formatv("Key: {0}", i).str());
  631. EXPECT_FALSE(m.Insert(i, i * 100 + 1, key_context).is_inserted());
  632. EXPECT_EQ(i * 100 + static_cast<int>(i == 1),
  633. m.Lookup(i, key_context).value());
  634. EXPECT_FALSE(m.Update(i, i * 100 + 1, key_context).is_inserted());
  635. EXPECT_EQ(i * 100 + 1, m.Lookup(i, key_context).value());
  636. }
  637. EXPECT_FALSE(m.Contains(0, key_context));
  638. EXPECT_FALSE(m.Contains(512, key_context));
  639. // Verify all the elements.
  640. ExpectMapElementsAre(
  641. m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 512)));
  642. }
  643. } // namespace
  644. } // namespace Carbon::Testing