37# include <gtest/gtest.h>
47using namespace testing;
57 const size_t cap =
tbl.capacity();
58 for (
size_t i = 0; i < cap; ++i)
66 for (
size_t i = 0; i <
tbl.size(); ++i)
69 auto ptr =
tbl.search(i);
74 for (
size_t i = 0, n =
tbl.size(); i < n; ++i)
76 auto ptr =
tbl.search(i);
99 return r1.key == r2.key;
123 for (
size_t i = 0; i < 100; ++i)
134 for (
size_t i = 0, n =
tbl.size(); i < n; ++i)
136 auto ptr =
tbl.search(i);
151 auto *bucket =
decltype(
tbl)::key_to_bucket(ptr);
168 const int num_elements = 50;
169 for (
int i = 0; i < num_elements; ++i)
176 for (
int i = 0; i < 10; ++i)
184 <<
"Table size should not change after failed remove attempts";
187 for (
int i = 0; i < num_elements; ++i)
189 auto ptr =
tbl.search(i * 2);
191 <<
"Element " << i * 2 <<
" should still be in the table";
197 for (
int i = 0; i < num_elements; ++i)
199 auto ptr =
tbl.search(i * 2);
214 for (
int i = 0; i < 20; ++i)
226 for (
int i = 0; i < 20; ++i)
228 if (i == 10)
continue;
229 EXPECT_NE(
tbl.search(i),
nullptr) <<
"Element " << i <<
" should still exist";
239 for (
int i = 0; i < 20; ++i)
245 auto ptr =
tbl.search(10);
260 for (
int i = 0; i < 50; ++i)
276 <<
"Capacity changed - possible unnecessary rehash on failed remove";
282 for (
int i = 0; i < 50; ++i)
283 EXPECT_NE(
tbl.search(i * 2),
nullptr) <<
"Element " << i * 2 <<
" not found";
313 auto ptr =
tbl.insert(key);
317 <<
" but oracle already had it";
323 <<
" but oracle didn't have it";
337 catch (
const domain_error &)
339 FAIL() <<
"Remove threw for key " << key <<
" that was in oracle";
350 auto ptr =
tbl.search(key);
353 <<
"Search mismatch for key " << key;
361 <<
"Size mismatch at operation " << i <<
", key=" << key;
367 auto ptr =
tbl.search(key);
368 ASSERT_NE(ptr,
nullptr) <<
"Final check: key " << key <<
" missing";
376 const size_t target =
tbl.capacity() - 1;
379 for (
size_t i = 0; i < target; ++i)
381 auto ptr =
tbl.insert(
static_cast<int>(i));
382 ASSERT_NE(ptr,
nullptr) <<
"Insert failed at i=" << i;
388 for (
size_t i = 0; i < target; ++i)
391 <<
"Element " << i <<
" not found after fill";
395 vector<int>
keys(target);
401 for (
size_t i = 0; i < target; ++i)
414 auto bad_hash = [](
const int &) ->
size_t {
return 42; };
419 const int num_elements = 50;
420 for (
int i = 0; i < num_elements; ++i)
422 auto ptr =
tbl.insert(i);
423 ASSERT_NE(ptr,
nullptr) <<
"Insert failed at i=" << i <<
" with bad hash";
429 for (
int i = 0; i < num_elements; ++i)
431 auto ptr =
tbl.search(i);
432 ASSERT_NE(ptr,
nullptr) <<
"Element " << i <<
" not found with collision";
437 for (
int i = num_elements - 1; i >= 0; --i)
451 const int cycles = 100;
460 auto ptr =
tbl.insert(key);
461 ASSERT_NE(ptr,
nullptr) <<
"Insert failed at cycle " <<
cycle <<
", i=" << i;
492 auto ptr =
tbl.insert(key);
493 if (
oracle.count(key) == 0 && ptr !=
nullptr)
502 auto ptr =
tbl.search(key);
503 ASSERT_NE(ptr,
nullptr) <<
"Key " << key <<
" lost after resize";
509 for (
size_t i = 0; i <
to_remove; ++i, ++it)
520 ASSERT_NE(
tbl.search(key),
nullptr) <<
"Key " << key <<
" missing after partial remove";
537 for (
int i = 0; i <
num_ops; ++i)
544 auto ptr =
tbl.insert(key);
557 catch (
const domain_error &)
559 FAIL() <<
"Remove threw for key " << key <<
" that was in oracle";
565 auto ptr =
tbl.search(key);
568 <<
"Search mismatch for key " << key;
595 auto ptr =
tbl.insert(key);
606 auto ptr =
tbl.search(key);
607 ASSERT_NE(ptr,
nullptr) <<
"Key " << key <<
" lost during resize";
643 for (
int i = 0; i < len; ++i)
650 for (
int i = 0; i <
num_ops; ++i)
654 if (
oracle.count(key) == 0)
656 auto ptr =
tbl.insert(key);
671 for (
const auto & key :
oracle)
673 auto ptr =
tbl.search(key);
674 ASSERT_NE(ptr,
nullptr) <<
"String key missing: " << key;
684 for (
int i = 0; i < 30; ++i)
688 for (
int i = 0; i < 30; i += 2)
694 for (
int i = 1; i < 30; i += 2)
696 auto ptr =
tbl.search_or_insert(i);
703 for (
int i = 0; i < 30; i += 2)
706 auto ptr =
tbl.search_or_insert(i);
713 for (
int i = 0; i < 30; ++i)
715 auto ptr =
tbl.search(i);
716 ASSERT_NE(ptr,
nullptr) <<
"Key " << i <<
" not found";
724 auto bad_hash = [](
const int &) ->
size_t {
return 7; };
729 for (
int i = 0; i < 20; ++i)
732 for (
int i = 0; i < 20; i += 3)
736 for (
int i = 20; i < 30; ++i)
738 auto [ptr,
existed] =
tbl.contains_or_insert(i);
745 for (
int i = 20; i < 30; ++i)
747 auto [ptr,
existed] =
tbl.contains_or_insert(i);
759 std::mt19937
gen(54321);
760 std::uniform_int_distribution<>
key_dist(0, 500);
761 std::uniform_int_distribution<>
op_dist(0, 2);
770 auto ptr =
tbl.search_or_insert(key);
771 ASSERT_NE(ptr,
nullptr) <<
"search_or_insert returned nullptr for key " << key;
777 <<
"Key " << key <<
" not found immediately after search_or_insert at iter " <<
iter;
779 else if (op == 1 &&
oracle.count(key))
784 <<
"Key " << key <<
" should exist before removal at iter " <<
iter
785 <<
", oracle.count=" <<
oracle.count(key) <<
", tbl.size=" <<
tbl.size();
791 auto ptr =
tbl.search(key);
793 ASSERT_NE(ptr,
nullptr) <<
"Key " << key <<
" should exist at iter " <<
iter;
799 <<
"Size mismatch at iter " <<
iter <<
": tbl=" <<
tbl.size() <<
", oracle=" <<
oracle.size();
805 auto ptr =
tbl.search(key);
806 ASSERT_NE(ptr,
nullptr) <<
"Key " << key <<
" missing";
815 std::mt19937
gen(54321);
816 std::uniform_int_distribution<>
key_dist(0, 500);
817 std::uniform_int_distribution<>
op_dist(0, 2);
828 auto p =
tbl.search(
k);
830 <<
"Pre-op check: Key " <<
k <<
" missing at iter " <<
iter
831 <<
" (about to do op " << op <<
" on key " << key <<
")";
838 auto ptr =
tbl.search_or_insert(key);
839 ASSERT_NE(ptr,
nullptr) <<
"search_or_insert returned nullptr at iter " <<
iter;
845 <<
"Size should increase for new key at iter " <<
iter;
847 else if (op == 1 &&
oracle.count(key))
854 <<
"Size mismatch at iter " <<
iter;
865 for (
int i = 0; i < 50; ++i)
873 for (
int i = 0; i < 50; ++i)
887 for (
int i = 0; i < 50; ++i)
898 for (
int i = 0; i < 50; ++i)
905 for (
int i = 0; i < 50; ++i)
915 for (
int i = 0; i < 50; ++i)
924 for (
int i = 0; i < 50; ++i)
936 for (
int i = 0; i < 50; ++i)
943 for (
int i = 0; i < 50; ++i)
949 for (
int i = 0; i < 50; ++i)
987 auto first =
tbl.insert(42);
990 auto second =
tbl.insert(42);
1017 int& ref =
tbl.find(42);
1033 for (
int i = 0; i < 50; ++i)
1039 for (
int i = 0; i < 50; i += 2)
1057 for (
int i = 0; i < 30; ++i)
1066 for (
int i = 0; i < 30; ++i)
1074 for (
int i = 0; i < 30; ++i)
1081 for (
int i = 0; i < 30; ++i)
1094 for (
int i = 0; i < 50; ++i)
1101 for (
auto it =
tbl.get_it(); it.has_curr(); it.next())
1102 visited.insert(it.get_curr());
1111 auto it =
tbl.get_it();
1120 auto it =
tbl.get_it();
1132 for (
int i = 0; i < 10; ++i)
1135 auto it =
tbl.get_it();
1136 while (it.has_curr())
1154template <
typename HashTable>
1158 for (
size_t i = 0; i <
tbl.capacity(); ++i)
1160 switch (
tbl.table[i].status)
1162 case HashTable::EMPTY: ++stats.
empty;
break;
1163 case HashTable::BUSY: ++stats.
busy;
break;
1164 case HashTable::DELETED: ++stats.
deleted;
break;
1173 auto bad_hash = [](
const int &) ->
size_t {
return 0; };
1177 for (
int i = 0; i < 5; ++i)
1190 EXPECT_EQ(
after.deleted, 0) <<
"Last element should become EMPTY via probe_counter";
1192 for (
int i = 0; i < 4; ++i)
1199 auto bad_hash = [](
const int &) ->
size_t {
return 0; };
1202 for (
int i = 0; i < 5; ++i)
1210 EXPECT_EQ(stats.deleted, 1) <<
"Middle should stay DELETED";
1212 for (
int i = 0; i < 5; ++i)
1223 auto bad_hash = [](
const int &) ->
size_t {
return 0; };
1226 for (
int i = 0; i < 5; ++i)
1230 for (
int i = 4; i >= 0; --i)
1235 EXPECT_EQ(stats.deleted, 0) <<
"All should become EMPTY when removed in reverse";
1246 for (
int i = 0; i < 10; ++i)
1250 tbl.for_each([&
sum](
int x) {
sum += x; });
1258 for (
int i = 0; i < 10; ++i)
1268 for (
int i = 0; i < 10; ++i)
1278 for (
int i = 0; i < 10; ++i)
1281 auto evens =
tbl.filter([](
int x) {
return x % 2 == 0; });
static string random_string(std::mt19937 &rng, size_t len)
Open addressing hash table with double hashing collision resolution.
Key * search(const Key &key) const noexcept
searches the table for the key.
constexpr size_t size() const noexcept
Returns the number of entries in the table.
Key * insert(const Key &key)
Inserts a key into the hash table (copy version).
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
MapOLhash< int, Foo > tbl
Main namespace for Aleph-w library functions.
size_t snd_hash_fct(const Key &key) noexcept
Secondary default hash: different distribution from dft_hash_fct.
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
void iota(C &container, typename C::Item_Type start)
Fill all elements of a container with unit-step sequential values.
size_t dft_hash_fct(const Key &key) noexcept
Primary default hash: best speed/quality trade-off.
auto shuffle(const C< T > &c)
Randomly shuffle a sequence.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
size_t snd_hash(const MyRecord &r) noexcept
size_t fst_hast(const MyRecord &r) noexcept
ODhashBucketStats count_odhash_bucket_states(const HashTable &tbl)
bool operator()(const MyRecord &r1, const MyRecord &r2) const noexcept
bool operator==(const MyRecord &r) const noexcept
MyRecord(size_t k, const string &v)
Open addressing hash table with double hashing.