Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
hash_backends_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
41# include <string>
42# include <type_traits>
43# include <unordered_set>
44
45# include <gtest/gtest.h>
46
47# include <tpl_hash.H>
48
49using namespace Aleph;
50
51namespace
52{
53
54// ============================================================================
55// Compile-time default checks
56// ============================================================================
57
58// HashSet<Key> must default to OLhashTable (linear probing).
59// This was changed from ODhashTable in commit 323aeb7b for consistency with
60// DynHashSet and better cache locality. If you intentionally change this
61// default again, update this assert and document it as a breaking change.
62static_assert(std::is_same_v<HashSet<int>, HashSet<int, OLhashTable>>,
63 "HashSet<Key> default backend must be OLhashTable. "
64 "If this changed intentionally, document it as a breaking change.");
65
66// HashMap<Key,Data> must default to MapOLhash.
67static_assert(std::is_same_v<HashMap<int, int>, HashMap<int, int, MapOLhash>>,
68 "HashMap<Key,Data> default backend must be MapOLhash. "
69 "If this changed intentionally, document it as a breaking change.");
70
71// DynHashSet<Key> must default to OLhashTable (unchanged historical default).
72static_assert(std::is_same_v<DynHashSet<int>, DynHashSet<int, OLhashTable>>,
73 "DynHashSet<Key> default backend must be OLhashTable.");
74
75// DynHashMap<Key,Data> must default to MapOLhash (unchanged historical default).
76static_assert(std::is_same_v<DynHashMap<int, int>,
78 "DynHashMap<Key,Data> default backend must be MapOLhash.");
79
80// ============================================================================
81// Helpers
82// ============================================================================
83
84constexpr int N = 200;
85
86// Collect all keys in a HashSet into a std::unordered_set for comparison.
87template <typename Set>
88std::unordered_set<int> collect(Set &s)
89{
90 std::unordered_set<int> result;
91 s.for_each([&](const int k) { result.insert(k); });
92 return result;
93}
94
95template <typename Map>
96std::unordered_set<int> collect_keys(Map &m)
97{
98 std::unordered_set<int> result;
99 m.for_each([&](const std::pair<int, std::string> &p) { result.insert(p.first); });
100 return result;
101}
102
103// ============================================================================
104// HashSet — OL backend (default)
105// ============================================================================
106
107struct HashSetOLTest : ::testing::Test
108{
110};
111
112TEST_F(HashSetOLTest, InsertAndContains)
113{
114 for (int i = 0; i < N; ++i)
115 s.insert(i);
116
117 for (int i = 0; i < N; ++i)
118 EXPECT_TRUE(s.contains(i)) << "key " << i << " missing after insert";
119}
120
122{
123 for (int i = 0; i < N; ++i)
124 s.insert(i);
125
126 EXPECT_FALSE(s.contains(N));
127 EXPECT_FALSE(s.contains(-1));
128}
129
130TEST_F(HashSetOLTest, IterationCoversAllKeys)
131{
132 for (int i = 0; i < N; ++i)
133 s.insert(i);
134
135 auto found = collect(s);
136 EXPECT_EQ(found.size(), (size_t) N);
137 for (int i = 0; i < N; ++i)
138 EXPECT_TRUE(found.count(i)) << "key " << i << " missing from iteration";
139}
140
141TEST_F(HashSetOLTest, RemoveKey)
142{
143 for (int i = 0; i < N; ++i)
144 s.insert(i);
145
146 s.remove(42);
147 EXPECT_FALSE(s.contains(42));
148
149 // All other keys still present.
150 for (int i = 0; i < N; ++i)
151 {
152 if (i != 42)
153 EXPECT_TRUE(s.contains(i)) << "key " << i << " missing after remove(42)";
154 }
155}
156
157TEST_F(HashSetOLTest, DuplicateInsertIsNoOp)
158{
159 s.insert(7);
160 s.insert(7);
161 size_t count = 0;
162 s.for_each([&](const int k) { if (k == 7) ++count; });
163 EXPECT_EQ(count, 1u);
164}
165
166// ============================================================================
167// HashSet — OD backend (explicit)
168// ============================================================================
169
170struct HashSetODTest : ::testing::Test
171{
173};
174
175TEST_F(HashSetODTest, InsertAndContains)
176{
177 for (int i = 0; i < N; ++i)
178 s.insert(i);
179
180 for (int i = 0; i < N; ++i)
181 EXPECT_TRUE(s.contains(i)) << "key " << i << " missing after insert";
182}
183
185{
186 for (int i = 0; i < N; ++i)
187 s.insert(i);
188
189 EXPECT_FALSE(s.contains(N));
190 EXPECT_FALSE(s.contains(-1));
191}
192
193TEST_F(HashSetODTest, IterationCoversAllKeys)
194{
195 for (int i = 0; i < N; ++i)
196 s.insert(i);
197
198 auto found = collect(s);
199 EXPECT_EQ(found.size(), (size_t) N);
200 for (int i = 0; i < N; ++i)
201 EXPECT_TRUE(found.count(i)) << "key " << i << " missing from iteration";
202}
203
204TEST_F(HashSetODTest, RemoveKey)
205{
206 for (int i = 0; i < N; ++i)
207 s.insert(i);
208
209 s.remove(42);
210 EXPECT_FALSE(s.contains(42));
211
212 for (int i = 0; i < N; ++i)
213 {
214 if (i != 42)
215 EXPECT_TRUE(s.contains(i)) << "key " << i << " missing after remove(42)";
216 }
217}
218
219// ============================================================================
220// HashSet — both backends produce the same key set
221// ============================================================================
222
224{
227
228 for (int i = 0; i < N; ++i)
229 {
230 ol.insert(i);
231 od.insert(i);
232 }
233
235}
236
237// ============================================================================
238// HashMap — OL backend (default)
239// ============================================================================
240
241struct HashMapOLTest : ::testing::Test
242{
244};
245
246TEST_F(HashMapOLTest, InsertAndSearch)
247{
248 for (int i = 0; i < N; ++i)
249 m.insert(i, std::to_string(i));
250
251 for (int i = 0; i < N; ++i)
252 {
253 auto *p = m.search(i);
254 ASSERT_NE(p, nullptr) << "key " << i << " not found";
255 EXPECT_EQ(p->second, std::to_string(i));
256 }
257}
258
260{
261 for (int i = 0; i < N; ++i)
262 m.insert(i, std::to_string(i));
263
264 EXPECT_EQ(m.search(N), nullptr);
265 EXPECT_EQ(m.search(-1), nullptr);
266}
267
268TEST_F(HashMapOLTest, IterationCoversAllKeys)
269{
270 for (int i = 0; i < N; ++i)
271 m.insert(i, std::to_string(i));
272
273 auto keys = collect_keys(m);
274 EXPECT_EQ(keys.size(), (size_t) N);
275 for (int i = 0; i < N; ++i)
276 EXPECT_TRUE(keys.count(i)) << "key " << i << " missing from iteration";
277}
278
279// ============================================================================
280// HashMap — OD backend (explicit)
281// ============================================================================
282
283struct HashMapODTest : ::testing::Test
284{
286};
287
288TEST_F(HashMapODTest, InsertAndSearch)
289{
290 for (int i = 0; i < N; ++i)
291 m.insert(i, std::to_string(i));
292
293 for (int i = 0; i < N; ++i)
294 {
295 auto *p = m.search(i);
296 ASSERT_NE(p, nullptr) << "key " << i << " not found";
297 EXPECT_EQ(p->second, std::to_string(i));
298 }
299}
300
302{
303 for (int i = 0; i < N; ++i)
304 m.insert(i, std::to_string(i));
305
306 EXPECT_EQ(m.search(N), nullptr);
307 EXPECT_EQ(m.search(-1), nullptr);
308}
309
310TEST_F(HashMapODTest, IterationCoversAllKeys)
311{
312 for (int i = 0; i < N; ++i)
313 m.insert(i, std::to_string(i));
314
315 auto keys = collect_keys(m);
316 EXPECT_EQ(keys.size(), (size_t) N);
317 for (int i = 0; i < N; ++i)
318 EXPECT_TRUE(keys.count(i)) << "key " << i << " missing from iteration";
319}
320
321// ============================================================================
322// HashMap — both backends produce the same key/value set
323// ============================================================================
324
326{
329
330 for (int i = 0; i < N; ++i)
331 {
332 ol.insert(i, std::to_string(i));
333 od.insert(i, std::to_string(i));
334 }
335
336 EXPECT_EQ(collect_keys(ol), collect_keys(od));
337
338 for (int i = 0; i < N; ++i)
339 {
340 auto *pol = ol.search(i);
341 auto *pod = od.search(i);
342 ASSERT_NE(pol, nullptr);
343 ASSERT_NE(pod, nullptr);
344 EXPECT_EQ(pol->second, pod->second);
345 }
346}
347
348// ============================================================================
349// DynHashSet / DynHashMap (aliases) — smoke test with default backends
350// ============================================================================
351
353{
355 for (int i = 0; i < N; ++i)
356 s.insert(i);
357
358 auto found = collect(s);
359 EXPECT_EQ(found.size(), (size_t) N);
360}
361
363{
365 for (int i = 0; i < N; ++i)
366 m.insert(i, std::to_string(i));
367
368 auto keys = collect_keys(m);
369 EXPECT_EQ(keys.size(), (size_t) N);
370}
371
372} // namespace
TEST_F(StaticArenaFixture, simple_fail)
Definition ah-arena.cc:59
Key * search(const Key &key) const noexcept
searches the table for the key.
Definition tpl_odhash.H:543
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:779
Key * insert(const Key &key)
Inserts a key into the hash table (copy version).
Definition hashDry.H:203
#define TEST(name)
#define N
Definition fib.C:294
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
int keys[]
static int * k
Unified hash table interface.