psemek/libs/util/tests/hash_table.cpp

403 lines
7.3 KiB
C++

#include <psemek/test/test.hpp>
#include <psemek/util/hash_table.hpp>
#include <psemek/random/generator.hpp>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
using namespace psemek;
using namespace psemek::util;
test_case(util_hash__set_empty)
{
hash_set<int> set;
expect(set.size() == 0);
expect(set.empty());
int call_count = 0;
for ([[maybe_unused]] auto value : set)
++call_count;
expect_equal(call_count, 0);
}
test_case(util_hash__set_insert)
{
hash_set<int> set;
int const count = 1024 * 16;
for (int i = 0; i < count; ++i)
expect(set.insert(i * i).second);
expect_equal(set.size(), count);
for (int i = 0; i < count; ++i)
{
expect(set.contains(i * i));
auto it = set.find(i * i);
expect(it != set.end());
expect_equal(*it, i * i);
}
for (int i = count; i < 2 * count; ++i)
{
expect(!set.contains(i * i));
expect(set.find(i * i) == set.end());
}
}
test_case(util_hash__set_clear)
{
hash_set<int> set;
int const count = 1024 * 1024;
for (int i = 0; i < count; ++i)
expect(set.insert(i).second);
expect_equal(set.size(), count);
set.clear();
expect(set.empty());
expect_equal(set.size(), 0);
int call_count = 0;
for ([[maybe_unused]] auto value : set)
++call_count;
expect_equal(call_count, 0);
}
test_case(util_hash__set_move)
{
hash_set<int> set1;
int const count = 1024 * 1024;
for (int i = 0; i < count; ++i)
expect(set1.insert(i).second);
expect_equal(set1.size(), count);
hash_set<int> set2 = std::move(set1);
expect(set1.empty());
expect_equal(set1.size(), 0);
expect(!set2.empty());
expect_equal(set2.size(), count);
for (int i = 0; i < count; ++i)
{
expect(!set1.contains(i));
expect(set2.contains(i));
}
for (int i = count; i < 2 * count; ++i)
{
expect(!set1.contains(i));
expect(!set2.contains(i));
}
hash_set<int> set3;
set3 = std::move(set2);
expect(set2.empty());
expect_equal(set2.size(), 0);
expect(!set3.empty());
expect_equal(set3.size(), count);
for (int i = 0; i < count; ++i)
{
expect(!set2.contains(i));
expect(set3.contains(i));
}
for (int i = count; i < 2 * count; ++i)
{
expect(!set2.contains(i));
expect(!set3.contains(i));
}
}
test_case(util_hash__set_benchmark)
{
random::generator rng;
std::vector<int> values;
int const count = 1024 * 1024;
for (int i = 0; i < count; ++i)
values.push_back(i);
std::shuffle(values.begin(), values.end(), rng);
test_profile(hash_set_total)
{
hash_set<int> set;
test_profile(hash_set_insert)
{
for (auto value : values)
set.insert(value);
expect_equal(set.size(), count);
}
test_profile(hash_set_iterate)
{
int size = 0;
for (auto value : set)
{
expect(0 <= value && value < count);
++size;
}
expect_equal(size, count);
}
test_profile(hash_set_find)
{
for (auto value : values)
{
auto it = set.find(value);
expect(it != set.end());
expect_equal(*it, value);
}
}
test_profile(hash_set_clear)
{
set.clear();
}
}
test_profile(unordered_set_total)
{
std::unordered_set<int> set;
test_profile(unordered_set_insert)
{
for (auto value : values)
set.insert(value);
expect_equal(set.size(), count);
}
test_profile(unordered_set_iterate)
{
int size = 0;
for (auto value : set)
{
expect(0 <= value && value < count);
++size;
}
expect_equal(size, count);
}
test_profile(unordered_set_find)
{
for (auto value : values)
{
auto it = set.find(value);
expect(it != set.end());
expect_equal(*it, value);
}
}
test_profile(unordered_set_clear)
{
set.clear();
}
}
}
test_case(util_hash__map_empty)
{
hash_map<int, int> map;
expect(map.size() == 0);
expect(map.empty());
int call_count = 0;
for ([[maybe_unused]] auto const & pair : map)
++call_count;
expect_equal(call_count, 0);
}
test_case(util_hash__map_insert)
{
hash_map<int, int> map;
int const count = 1024 * 16;
for (int i = 0; i < count; ++i)
expect(map.insert({i * i, i}).second);
expect_equal(map.size(), count);
for (int i = 0; i < count; ++i)
{
expect(map.contains(i * i));
auto it = map.find(i * i);
expect(it != map.end());
expect_equal(it->first, i * i);
expect_equal(it->second, i);
}
for (int i = count; i < 2 * count; ++i)
{
expect(!map.contains(i * i));
expect(map.find(i * i) == map.end());
}
}
test_case(util_hash__map_clear)
{
hash_map<int, int> map;
int const count = 1024 * 1024;
for (int i = 0; i < count; ++i)
expect(map.insert({i, (i * 19) % count}).second);
expect_equal(map.size(), count);
map.clear();
expect(map.empty());
expect_equal(map.size(), 0);
int call_count = 0;
for ([[maybe_unused]] auto value : map)
++call_count;
expect_equal(call_count, 0);
}
test_case(util_hash__map_move)
{
hash_map<int, int> map1;
int const count = 1024 * 1024;
for (int i = 0; i < count; ++i)
expect(map1.insert({i, (i * 19) % count}).second);
expect_equal(map1.size(), count);
hash_map<int, int> map2 = std::move(map1);
expect(map1.empty());
expect_equal(map1.size(), 0);
expect(!map2.empty());
expect_equal(map2.size(), count);
for (int i = 0; i < count; ++i)
{
expect(!map1.contains(i));
auto it = map2.find(i);
expect(it != map2.end());
expect_equal(it->first, i);
expect_equal(it->second, (i * 19) % count);
}
for (int i = count; i < 2 * count; ++i)
{
expect(!map1.contains(i));
expect(!map2.contains(i));
}
hash_map<int, int> map3;
map3 = std::move(map2);
expect(map2.empty());
expect_equal(map2.size(), 0);
expect(!map3.empty());
expect_equal(map3.size(), count);
for (int i = 0; i < count; ++i)
{
expect(!map2.contains(i));
auto it = map3.find(i);
expect(it != map3.end());
expect_equal(it->first, i);
expect_equal(it->second, (i * 19) % count);
}
for (int i = count; i < 2 * count; ++i)
{
expect(!map2.contains(i));
expect(!map3.contains(i));
}
}
test_case(util_hash__map_benchmark)
{
random::generator rng;
std::vector<int> keys;
int const count = 1024 * 1024;
for (int i = 0; i < count; ++i)
keys.push_back(i);
std::shuffle(keys.begin(), keys.end(), rng);
test_profile(hash_map_total)
{
hash_map<int, int> map;
test_profile(hash_map_insert)
{
for (auto key : keys)
map.insert({key, -key});
expect_equal(map.size(), count);
}
test_profile(hash_map_iterate)
{
int size = 0;
for (auto const & pair : map)
{
expect(0 <= pair.first && pair.first < count);
expect_equal(pair.second, -pair.first);
++size;
}
expect_equal(size, count);
}
test_profile(hash_map_find)
{
for (auto key : keys)
{
auto it = map.find(key);
expect(map.find(key) != map.end());
expect_equal(it->second, -key);
}
}
test_profile(hash_map_clear)
{
map.clear();
}
}
test_profile(unordered_map_total)
{
std::unordered_map<int, int> map;
test_profile(unordered_map_insert)
{
for (auto key : keys)
map.insert({key, -key});
}
test_profile(unordered_map_iterate)
{
int size = 0;
for (auto const & pair : map)
{
expect(0 <= pair.first && pair.first < count);
expect_equal(pair.second, -pair.first);
++size;
}
expect_equal(size, count);
}
test_profile(unordered_map_find)
{
for (auto key : keys)
{
auto it = map.find(key);
expect(map.find(key) != map.end());
expect_equal(it->second, -key);
}
}
test_profile(unordered_map_clear)
{
map.clear();
}
}
}