Files
asl/asl/containers/hash_set_tests.cpp

191 lines
3.7 KiB
C++

// Copyright 2025 Steven Le Rouzic
//
// SPDX-License-Identifier: BSD-3-Clause
#include "asl/containers/hash_set.hpp"
#include "asl/testing/testing.hpp"
#include "asl/tests/types.hpp"
#include "asl/strings/string.hpp"
#include "asl/strings/string_view.hpp"
ASL_TEST(empty)
{
const asl::hash_set<int> set;
ASL_TEST_EXPECT(set.size() == 0);
for (int i = 0; i < 100; ++i)
{
ASL_TEST_EXPECT(!set.contains(i));
}
}
ASL_TEST(a_bunch_of_strings)
{
asl::hash_set<asl::string<>> set;
set.insert("Hello, world!");
ASL_TEST_EXPECT(set.size() == 1);
set.insert("Hello, puppy!");
ASL_TEST_EXPECT(set.size() == 2);
set.insert("Hello, puppy!");
ASL_TEST_EXPECT(set.size() == 2);
ASL_TEST_EXPECT(set.contains("Hello, world!"_sv));
ASL_TEST_EXPECT(set.contains("Hello, puppy!"_sv));
ASL_TEST_EXPECT(!set.contains("Hello, Steven!"_sv));
}
ASL_TEST(a_bunch_of_ints)
{
asl::hash_set<int> set;
const int count = 3000;
for (int i = 0; i < count; ++i)
{
set.insert(i);
}
ASL_TEST_EXPECT(set.size() == count);
for (int i = 0; i < count * 2; ++i)
{
ASL_TEST_EXPECT(set.contains(i) == (i < count));
}
}
struct HashWithDestructor: public DestructorObserver
{
int x;
HashWithDestructor(int x_, bool* ptr)
: DestructorObserver{ptr}
, x{x_}
{}
constexpr bool operator==(const HashWithDestructor& other) const
{
return x == other.x;
}
};
struct CustomComparator
{
static bool eq(const HashWithDestructor& a, const HashWithDestructor& b)
{
return a.x == b.x;
}
static bool eq(const HashWithDestructor& a, int b)
{
return a.x == b;
}
};
struct CustomHasher
{
static uint64_t hash(const HashWithDestructor& b)
{
return asl::hash_value(b.x);
}
static uint64_t hash(int x)
{
return asl::hash_value(x);
}
};
// NOLINTNEXTLINE(*-complexity)
ASL_TEST(destructor_and_remove)
{
static constexpr int kCount = 200;
bool destroyed[kCount]{};
{
asl::hash_set<HashWithDestructor, asl::DefaultAllocator, CustomHasher, CustomComparator> set;
for (int i = 0; i < kCount; ++i)
{
set.insert(i, &destroyed[i]); // NOLINT
}
ASL_TEST_EXPECT(set.size() == kCount);
for (const bool i : destroyed)
{
ASL_TEST_EXPECT(!i); // NOLINT
}
for (int i = 0; i < kCount; i += 2)
{
ASL_TEST_EXPECT(set.remove(i));
}
for (int i = 0; i < kCount; i += 2)
{
ASL_TEST_EXPECT(!set.contains(i));
ASL_TEST_EXPECT(set.contains(i+1));
ASL_TEST_EXPECT(destroyed[i]); // NOLINT
ASL_TEST_EXPECT(!destroyed[i + 1]); // NOLINT
}
}
for (const bool i : destroyed)
{
ASL_TEST_EXPECT(i); // NOLINT
}
}
ASL_TEST(copy)
{
asl::hash_set<int> set1;
for (int i = 0; i < 100; ++i)
{
set1.insert(i);
}
const asl::hash_set<int> set2 = set1;
asl::hash_set<int> set3;
set3 = set1;
ASL_TEST_EXPECT(set2.size() == 100);
ASL_TEST_EXPECT(set3.size() == 100);
for (int i = 0; i < 100; ++i)
{
ASL_TEST_EXPECT(set2.contains(i));
ASL_TEST_EXPECT(set3.contains(i));
}
}
ASL_TEST(move)
{
asl::hash_set<int> set1;
for (int i = 0; i < 100; ++i)
{
set1.insert(i);
}
asl::hash_set<int> set2 = std::move(set1);
ASL_TEST_EXPECT(set2.size() == 100);
for (int i = 0; i < 100; ++i)
{
ASL_TEST_EXPECT(set2.contains(i));
}
set1 = std::move(set2);
ASL_TEST_EXPECT(set1.size() == 100);
for (int i = 0; i < 100; ++i)
{
ASL_TEST_EXPECT(set1.contains(i));
}
}