diff options
author | tender-bum <tender-bum@yandex-team.ru> | 2022-02-10 16:50:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:50:01 +0300 |
commit | 4aef354b224559d2b031487a10d4f5cc6e82e95a (patch) | |
tree | 5d5cb817648f650d76cf1076100726fd9b8448e8 /library/cpp/containers/flat_hash/lib/ut | |
parent | c78b06a63de7beec995c1007bc5332bdf3d75b69 (diff) | |
download | ydb-4aef354b224559d2b031487a10d4f5cc6e82e95a.tar.gz |
Restoring authorship annotation for <tender-bum@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/containers/flat_hash/lib/ut')
6 files changed, 991 insertions, 991 deletions
diff --git a/library/cpp/containers/flat_hash/lib/ut/containers_ut.cpp b/library/cpp/containers/flat_hash/lib/ut/containers_ut.cpp index 9d39a43f90..b17b30fa80 100644 --- a/library/cpp/containers/flat_hash/lib/ut/containers_ut.cpp +++ b/library/cpp/containers/flat_hash/lib/ut/containers_ut.cpp @@ -1,410 +1,410 @@ #include <library/cpp/containers/flat_hash/lib/containers.h> - + #include <library/cpp/testing/unittest/registar.h> - -#include <util/generic/algorithm.h> -#include <util/random/random.h> -#include <util/random/shuffle.h> - -using namespace NFlatHash; - -namespace { - constexpr size_t INIT_SIZE = 128; - - struct TDummy { - static size_t Count; - - TDummy() { ++Count; } - TDummy(const TDummy&) { ++Count; } - ~TDummy() { --Count; } - }; - size_t TDummy::Count = 0; - - struct TAlmostDummy { - static size_t Count; - - TAlmostDummy(int j = 0) : Junk(j) { ++Count; } - TAlmostDummy(const TAlmostDummy& d) : Junk(d.Junk) { ++Count; } - ~TAlmostDummy() { --Count; } - - bool operator==(const TAlmostDummy& r) const { return Junk == r.Junk; }; - bool operator!=(const TAlmostDummy& r) const { return !operator==(r); }; - - int Junk; - }; - size_t TAlmostDummy::Count = 0; - - struct TNotSimple { - enum class EType { - Value, - Empty, - Deleted - } Type_ = EType::Value; - - TString Junk = "something"; // to prevent triviality propagation - int Value = 0; - - static int CtorCalls; - static int DtorCalls; - static int CopyCtorCalls; - static int MoveCtorCalls; - - TNotSimple() { - ++CtorCalls; - } - explicit TNotSimple(int value) - : Value(value) - { - ++CtorCalls; - } - - TNotSimple(const TNotSimple& rhs) { - ++CopyCtorCalls; - Value = rhs.Value; - Type_ = rhs.Type_; - } - TNotSimple(TNotSimple&& rhs) { - ++MoveCtorCalls; - Value = rhs.Value; - Type_ = rhs.Type_; - } - - ~TNotSimple() { - ++DtorCalls; - } - - TNotSimple& operator=(const TNotSimple& rhs) { - ++CopyCtorCalls; - Value = rhs.Value; - Type_ = rhs.Type_; - return *this; - } - TNotSimple& operator=(TNotSimple&& rhs) { - ++MoveCtorCalls; - Value = rhs.Value; - Type_ = rhs.Type_; - return *this; - } - - static TNotSimple Empty() { - TNotSimple ret; - ret.Type_ = EType::Empty; - return ret; - } - - static TNotSimple Deleted() { - TNotSimple ret; - ret.Type_ = EType::Deleted; - return ret; - } - - bool operator==(const TNotSimple& rhs) const noexcept { - return Value == rhs.Value; - } - - static void ResetStats() { - CtorCalls = 0; - DtorCalls = 0; - CopyCtorCalls = 0; - MoveCtorCalls = 0; - } - }; - - int TNotSimple::CtorCalls = 0; - int TNotSimple::DtorCalls = 0; - int TNotSimple::CopyCtorCalls = 0; - int TNotSimple::MoveCtorCalls = 0; - - struct TNotSimpleEmptyMarker { - using value_type = TNotSimple; - - value_type Create() const { - return TNotSimple::Empty(); - } - - bool Equals(const value_type& rhs) const { - return rhs.Type_ == TNotSimple::EType::Empty; - } - }; - - struct TNotSimpleDeletedMarker { - using value_type = TNotSimple; - - value_type Create() const { - return TNotSimple::Deleted(); - } - - bool Equals(const value_type& rhs) const { - return rhs.Type_ == TNotSimple::EType::Deleted; - } - }; - - template <class Container> - void CheckContainersEqual(const Container& a, const Container& b) { - UNIT_ASSERT_EQUAL(a.Size(), b.Size()); - UNIT_ASSERT_EQUAL(a.Taken(), b.Empty()); - for (typename Container::size_type i = 0; i < a.Size(); ++i) { - if (a.IsTaken(i)) { - UNIT_ASSERT(b.IsTaken(i)); - UNIT_ASSERT_EQUAL(a.Node(i), b.Node(i)); - } - } - } - - template <class Container, class... Args> - void SmokingTest(typename Container::size_type size, Args&&... args) { - using size_type = typename Container::size_type; - using value_type = typename Container::value_type; - - Container cont(size, std::forward<Args>(args)...); - UNIT_ASSERT_EQUAL(cont.Size(), size); - UNIT_ASSERT_EQUAL(cont.Taken(), 0); - - for (size_type i = 0; i < cont.Size(); ++i) { - UNIT_ASSERT(cont.IsEmpty(i)); - UNIT_ASSERT(!cont.IsTaken(i)); - } - - // Filling the container till half - TVector<size_type> toInsert(cont.Size()); - Iota(toInsert.begin(), toInsert.end(), 0); - Shuffle(toInsert.begin(), toInsert.end()); - toInsert.resize(toInsert.size() / 2); - for (auto i : toInsert) { - UNIT_ASSERT(cont.IsEmpty(i)); - UNIT_ASSERT(!cont.IsTaken(i)); - value_type value(RandomNumber<size_type>(cont.Size())); - cont.InitNode(i, value); - UNIT_ASSERT(!cont.IsEmpty(i)); - UNIT_ASSERT(cont.IsTaken(i)); - UNIT_ASSERT_EQUAL(cont.Node(i), value); - } - UNIT_ASSERT_EQUAL(cont.Taken(), toInsert.size()); - - // Copy construction test - auto cont2 = cont; - CheckContainersEqual(cont, cont2); - - // Copy assignment test - cont2 = cont2.Clone(0); - UNIT_ASSERT_EQUAL(cont2.Size(), 0); - UNIT_ASSERT_EQUAL(cont2.Taken(), 0); - - // Copy assignment test - cont2 = cont; - CheckContainersEqual(cont, cont2); - - // Move construction test - auto cont3 = std::move(cont2); - UNIT_ASSERT_EQUAL(cont2.Size(), 0); - CheckContainersEqual(cont, cont3); - - // Move assignment test - cont2 = std::move(cont3); - UNIT_ASSERT_EQUAL(cont3.Size(), 0); - CheckContainersEqual(cont, cont2); - } -} - -Y_UNIT_TEST_SUITE(TFlatContainerTest) { - Y_UNIT_TEST(SmokingTest) { - SmokingTest<TFlatContainer<int>>(INIT_SIZE); - } - - Y_UNIT_TEST(SmokingTestNotSimpleType) { - TNotSimple::ResetStats(); - SmokingTest<TFlatContainer<TNotSimple>>(INIT_SIZE); - - UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls + TNotSimple::CopyCtorCalls + TNotSimple::MoveCtorCalls, - TNotSimple::DtorCalls); - UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls, INIT_SIZE / 2 /* created while filling */); - UNIT_ASSERT_EQUAL(TNotSimple::DtorCalls, INIT_SIZE / 2 /* removed filling temporary */ - + INIT_SIZE / 2 /* removed while cloning */ - + INIT_SIZE /* 3 containers dtors */); - UNIT_ASSERT_EQUAL(TNotSimple::CopyCtorCalls, INIT_SIZE / 2 /* 3 created while filling */ - + INIT_SIZE / 2 /* created while copy constructing */ - + INIT_SIZE / 2/* created while copy assigning */); - UNIT_ASSERT_EQUAL(TNotSimple::MoveCtorCalls, 0); - } - - Y_UNIT_TEST(DummyHalfSizeTest) { - using TContainer = TFlatContainer<TDummy>; - using size_type = typename TContainer::size_type; - - { - TContainer cont(INIT_SIZE); - UNIT_ASSERT_EQUAL(TDummy::Count, 0); - - TVector<size_type> toInsert(cont.Size()); - Iota(toInsert.begin(), toInsert.end(), 0); - Shuffle(toInsert.begin(), toInsert.end()); - toInsert.resize(toInsert.size() / 2); - for (auto i : toInsert) { - UNIT_ASSERT(cont.IsEmpty(i)); - UNIT_ASSERT(!cont.IsTaken(i)); - cont.InitNode(i); - UNIT_ASSERT_EQUAL(TDummy::Count, cont.Taken()); - UNIT_ASSERT(!cont.IsEmpty(i)); - UNIT_ASSERT(cont.IsTaken(i)); - } - UNIT_ASSERT_EQUAL(cont.Taken(), cont.Size() / 2); - UNIT_ASSERT_EQUAL(TDummy::Count, cont.Taken()); - } - UNIT_ASSERT_EQUAL(TDummy::Count, 0); - } - - Y_UNIT_TEST(DeleteTest) { - using TContainer = TFlatContainer<TDummy>; - using size_type = typename TContainer::size_type; - - TContainer cont(INIT_SIZE); - auto idx = RandomNumber<size_type>(INIT_SIZE); - UNIT_ASSERT(!cont.IsTaken(idx)); - UNIT_ASSERT(!cont.IsDeleted(idx)); - UNIT_ASSERT_EQUAL(TDummy::Count, 0); - - cont.InitNode(idx); - UNIT_ASSERT_EQUAL(cont.Taken(), 1); - UNIT_ASSERT(cont.IsTaken(idx)); - UNIT_ASSERT(!cont.IsDeleted(idx)); - UNIT_ASSERT_EQUAL(TDummy::Count, 1); - - cont.DeleteNode(idx); - UNIT_ASSERT(!cont.IsTaken(idx)); - UNIT_ASSERT(cont.IsDeleted(idx)); - UNIT_ASSERT_EQUAL(TDummy::Count, 0); - } -} - -Y_UNIT_TEST_SUITE(TDenseContainerTest) { - Y_UNIT_TEST(SmokingTest) { - SmokingTest<TDenseContainer<int, NSet::TStaticValueMarker<-1>>>(INIT_SIZE); - } - - Y_UNIT_TEST(NotSimpleTypeSmokingTest) { - TNotSimple::ResetStats(); - SmokingTest<TDenseContainer<TNotSimple, TNotSimpleEmptyMarker>>(INIT_SIZE); - - UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls + TNotSimple::CopyCtorCalls + TNotSimple::MoveCtorCalls, - TNotSimple::DtorCalls); - UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls, INIT_SIZE / 2 /* created while filling */ - + 2 /* created by empty marker */); - UNIT_ASSERT_EQUAL(TNotSimple::DtorCalls, 1 /* removed empty marker temporary */ - + INIT_SIZE /* half removed while resetting in container, - half removed inserted temporary */ - + INIT_SIZE /* removed while cloning */ - + 1 /* removed empty marker temporary */ - + INIT_SIZE * 2 /* 3 containers dtors */); - UNIT_ASSERT_EQUAL(TNotSimple::CopyCtorCalls, INIT_SIZE /* created while constructing */ - + INIT_SIZE / 2 /* 3 created while filling */ - + INIT_SIZE /* created while copy constructing */ - + INIT_SIZE /* created while copy assigning */); - UNIT_ASSERT_EQUAL(TNotSimple::MoveCtorCalls, 0); - } - - Y_UNIT_TEST(RemovalContainerSmokingTest) { - SmokingTest<TRemovalDenseContainer<int, NSet::TStaticValueMarker<-1>, - NSet::TStaticValueMarker<-2>>>(INIT_SIZE); - } - - Y_UNIT_TEST(NotSimpleTypeRemovalContainerSmokingTest) { - TNotSimple::ResetStats(); - SmokingTest<TRemovalDenseContainer<TNotSimple, TNotSimpleEmptyMarker, - TNotSimpleDeletedMarker>>(INIT_SIZE); - - UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls + TNotSimple::CopyCtorCalls + TNotSimple::MoveCtorCalls, - TNotSimple::DtorCalls); - UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls, INIT_SIZE / 2 /* created while filling */ - + 2 /* created by empty marker */); - UNIT_ASSERT_EQUAL(TNotSimple::DtorCalls, 1 /* removed empty marker temporary */ - + INIT_SIZE /* half removed while resetting in container, - half removed inserted temporary */ - + INIT_SIZE /* removed while cloning */ - + 1 /* removed empty marker temporary */ - + INIT_SIZE * 2 /* 3 containers dtors */); - UNIT_ASSERT_EQUAL(TNotSimple::CopyCtorCalls, INIT_SIZE /* created while constructing */ - + INIT_SIZE / 2 /* 3 created while filling */ - + INIT_SIZE /* created while copy constructing */ - + INIT_SIZE /* created while copy assigning */); - UNIT_ASSERT_EQUAL(TNotSimple::MoveCtorCalls, 0); - } - - Y_UNIT_TEST(DummyHalfSizeTest) { - using TContainer = TDenseContainer<TAlmostDummy, NSet::TEqValueMarker<TAlmostDummy>>; - using size_type = typename TContainer::size_type; - - { - TContainer cont(INIT_SIZE, TAlmostDummy{-1}); - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 1); // 1 for empty marker - - TVector<size_type> toInsert(cont.Size()); - Iota(toInsert.begin(), toInsert.end(), 0); - Shuffle(toInsert.begin(), toInsert.end()); - toInsert.resize(toInsert.size() / 2); - for (auto i : toInsert) { - UNIT_ASSERT(cont.IsEmpty(i)); - UNIT_ASSERT(!cont.IsTaken(i)); - cont.InitNode(i, (int)RandomNumber<size_type>(cont.Size())); - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 1); - UNIT_ASSERT(!cont.IsEmpty(i)); - UNIT_ASSERT(cont.IsTaken(i)); - } - UNIT_ASSERT_EQUAL(cont.Taken(), toInsert.size()); - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 1); - } - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, 0); - } - - Y_UNIT_TEST(DeleteTest) { - using TContainer = TRemovalDenseContainer<TAlmostDummy, NSet::TEqValueMarker<TAlmostDummy>, - NSet::TEqValueMarker<TAlmostDummy>>; - using size_type = typename TContainer::size_type; - - TContainer cont(INIT_SIZE, TAlmostDummy{ -2 }, TAlmostDummy{ -1 }); - auto idx = RandomNumber<size_type>(cont.Size()); - UNIT_ASSERT(!cont.IsTaken(idx)); - UNIT_ASSERT(!cont.IsDeleted(idx)); - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 2); // 2 for markers - - cont.InitNode(idx, (int)RandomNumber<size_type>(cont.Size())); - UNIT_ASSERT_EQUAL(cont.Taken(), 1); - UNIT_ASSERT(cont.IsTaken(idx)); - UNIT_ASSERT(!cont.IsDeleted(idx)); - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 2); - - cont.DeleteNode(idx); - UNIT_ASSERT(!cont.IsTaken(idx)); - UNIT_ASSERT(cont.IsDeleted(idx)); - UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 2); - } - - Y_UNIT_TEST(FancyInitsTest) { - { - using TContainer = TDenseContainer<int>; - TContainer cont{ INIT_SIZE, -1 }; - } - { - using TContainer = TDenseContainer<int, NSet::TStaticValueMarker<-1>>; - TContainer cont{ INIT_SIZE }; - static_assert(!std::is_constructible_v<TContainer, size_t, int>); - } - { - using TContainer = TDenseContainer<int, NSet::TEqValueMarker<int>>; - TContainer cont{ INIT_SIZE, -1 }; - TContainer cont2{ INIT_SIZE, NSet::TEqValueMarker<int>{ -1 } }; - } - { - using TContainer = TRemovalDenseContainer<int>; - TContainer cont{ INIT_SIZE, -1, -2 }; - TContainer cont2{ INIT_SIZE, NSet::TEqValueMarker<int>{ -1 }, - NSet::TEqValueMarker<int>{ -2 } }; - } - { - using TContainer = TRemovalDenseContainer<int, NSet::TStaticValueMarker<-1>, - NSet::TStaticValueMarker<-1>>; - TContainer cont{ INIT_SIZE }; - static_assert(!std::is_constructible_v<TContainer, size_t, int>); - static_assert(!std::is_constructible_v<TContainer, size_t, int, int>); - } - } -} + +#include <util/generic/algorithm.h> +#include <util/random/random.h> +#include <util/random/shuffle.h> + +using namespace NFlatHash; + +namespace { + constexpr size_t INIT_SIZE = 128; + + struct TDummy { + static size_t Count; + + TDummy() { ++Count; } + TDummy(const TDummy&) { ++Count; } + ~TDummy() { --Count; } + }; + size_t TDummy::Count = 0; + + struct TAlmostDummy { + static size_t Count; + + TAlmostDummy(int j = 0) : Junk(j) { ++Count; } + TAlmostDummy(const TAlmostDummy& d) : Junk(d.Junk) { ++Count; } + ~TAlmostDummy() { --Count; } + + bool operator==(const TAlmostDummy& r) const { return Junk == r.Junk; }; + bool operator!=(const TAlmostDummy& r) const { return !operator==(r); }; + + int Junk; + }; + size_t TAlmostDummy::Count = 0; + + struct TNotSimple { + enum class EType { + Value, + Empty, + Deleted + } Type_ = EType::Value; + + TString Junk = "something"; // to prevent triviality propagation + int Value = 0; + + static int CtorCalls; + static int DtorCalls; + static int CopyCtorCalls; + static int MoveCtorCalls; + + TNotSimple() { + ++CtorCalls; + } + explicit TNotSimple(int value) + : Value(value) + { + ++CtorCalls; + } + + TNotSimple(const TNotSimple& rhs) { + ++CopyCtorCalls; + Value = rhs.Value; + Type_ = rhs.Type_; + } + TNotSimple(TNotSimple&& rhs) { + ++MoveCtorCalls; + Value = rhs.Value; + Type_ = rhs.Type_; + } + + ~TNotSimple() { + ++DtorCalls; + } + + TNotSimple& operator=(const TNotSimple& rhs) { + ++CopyCtorCalls; + Value = rhs.Value; + Type_ = rhs.Type_; + return *this; + } + TNotSimple& operator=(TNotSimple&& rhs) { + ++MoveCtorCalls; + Value = rhs.Value; + Type_ = rhs.Type_; + return *this; + } + + static TNotSimple Empty() { + TNotSimple ret; + ret.Type_ = EType::Empty; + return ret; + } + + static TNotSimple Deleted() { + TNotSimple ret; + ret.Type_ = EType::Deleted; + return ret; + } + + bool operator==(const TNotSimple& rhs) const noexcept { + return Value == rhs.Value; + } + + static void ResetStats() { + CtorCalls = 0; + DtorCalls = 0; + CopyCtorCalls = 0; + MoveCtorCalls = 0; + } + }; + + int TNotSimple::CtorCalls = 0; + int TNotSimple::DtorCalls = 0; + int TNotSimple::CopyCtorCalls = 0; + int TNotSimple::MoveCtorCalls = 0; + + struct TNotSimpleEmptyMarker { + using value_type = TNotSimple; + + value_type Create() const { + return TNotSimple::Empty(); + } + + bool Equals(const value_type& rhs) const { + return rhs.Type_ == TNotSimple::EType::Empty; + } + }; + + struct TNotSimpleDeletedMarker { + using value_type = TNotSimple; + + value_type Create() const { + return TNotSimple::Deleted(); + } + + bool Equals(const value_type& rhs) const { + return rhs.Type_ == TNotSimple::EType::Deleted; + } + }; + + template <class Container> + void CheckContainersEqual(const Container& a, const Container& b) { + UNIT_ASSERT_EQUAL(a.Size(), b.Size()); + UNIT_ASSERT_EQUAL(a.Taken(), b.Empty()); + for (typename Container::size_type i = 0; i < a.Size(); ++i) { + if (a.IsTaken(i)) { + UNIT_ASSERT(b.IsTaken(i)); + UNIT_ASSERT_EQUAL(a.Node(i), b.Node(i)); + } + } + } + + template <class Container, class... Args> + void SmokingTest(typename Container::size_type size, Args&&... args) { + using size_type = typename Container::size_type; + using value_type = typename Container::value_type; + + Container cont(size, std::forward<Args>(args)...); + UNIT_ASSERT_EQUAL(cont.Size(), size); + UNIT_ASSERT_EQUAL(cont.Taken(), 0); + + for (size_type i = 0; i < cont.Size(); ++i) { + UNIT_ASSERT(cont.IsEmpty(i)); + UNIT_ASSERT(!cont.IsTaken(i)); + } + + // Filling the container till half + TVector<size_type> toInsert(cont.Size()); + Iota(toInsert.begin(), toInsert.end(), 0); + Shuffle(toInsert.begin(), toInsert.end()); + toInsert.resize(toInsert.size() / 2); + for (auto i : toInsert) { + UNIT_ASSERT(cont.IsEmpty(i)); + UNIT_ASSERT(!cont.IsTaken(i)); + value_type value(RandomNumber<size_type>(cont.Size())); + cont.InitNode(i, value); + UNIT_ASSERT(!cont.IsEmpty(i)); + UNIT_ASSERT(cont.IsTaken(i)); + UNIT_ASSERT_EQUAL(cont.Node(i), value); + } + UNIT_ASSERT_EQUAL(cont.Taken(), toInsert.size()); + + // Copy construction test + auto cont2 = cont; + CheckContainersEqual(cont, cont2); + + // Copy assignment test + cont2 = cont2.Clone(0); + UNIT_ASSERT_EQUAL(cont2.Size(), 0); + UNIT_ASSERT_EQUAL(cont2.Taken(), 0); + + // Copy assignment test + cont2 = cont; + CheckContainersEqual(cont, cont2); + + // Move construction test + auto cont3 = std::move(cont2); + UNIT_ASSERT_EQUAL(cont2.Size(), 0); + CheckContainersEqual(cont, cont3); + + // Move assignment test + cont2 = std::move(cont3); + UNIT_ASSERT_EQUAL(cont3.Size(), 0); + CheckContainersEqual(cont, cont2); + } +} + +Y_UNIT_TEST_SUITE(TFlatContainerTest) { + Y_UNIT_TEST(SmokingTest) { + SmokingTest<TFlatContainer<int>>(INIT_SIZE); + } + + Y_UNIT_TEST(SmokingTestNotSimpleType) { + TNotSimple::ResetStats(); + SmokingTest<TFlatContainer<TNotSimple>>(INIT_SIZE); + + UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls + TNotSimple::CopyCtorCalls + TNotSimple::MoveCtorCalls, + TNotSimple::DtorCalls); + UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls, INIT_SIZE / 2 /* created while filling */); + UNIT_ASSERT_EQUAL(TNotSimple::DtorCalls, INIT_SIZE / 2 /* removed filling temporary */ + + INIT_SIZE / 2 /* removed while cloning */ + + INIT_SIZE /* 3 containers dtors */); + UNIT_ASSERT_EQUAL(TNotSimple::CopyCtorCalls, INIT_SIZE / 2 /* 3 created while filling */ + + INIT_SIZE / 2 /* created while copy constructing */ + + INIT_SIZE / 2/* created while copy assigning */); + UNIT_ASSERT_EQUAL(TNotSimple::MoveCtorCalls, 0); + } + + Y_UNIT_TEST(DummyHalfSizeTest) { + using TContainer = TFlatContainer<TDummy>; + using size_type = typename TContainer::size_type; + + { + TContainer cont(INIT_SIZE); + UNIT_ASSERT_EQUAL(TDummy::Count, 0); + + TVector<size_type> toInsert(cont.Size()); + Iota(toInsert.begin(), toInsert.end(), 0); + Shuffle(toInsert.begin(), toInsert.end()); + toInsert.resize(toInsert.size() / 2); + for (auto i : toInsert) { + UNIT_ASSERT(cont.IsEmpty(i)); + UNIT_ASSERT(!cont.IsTaken(i)); + cont.InitNode(i); + UNIT_ASSERT_EQUAL(TDummy::Count, cont.Taken()); + UNIT_ASSERT(!cont.IsEmpty(i)); + UNIT_ASSERT(cont.IsTaken(i)); + } + UNIT_ASSERT_EQUAL(cont.Taken(), cont.Size() / 2); + UNIT_ASSERT_EQUAL(TDummy::Count, cont.Taken()); + } + UNIT_ASSERT_EQUAL(TDummy::Count, 0); + } + + Y_UNIT_TEST(DeleteTest) { + using TContainer = TFlatContainer<TDummy>; + using size_type = typename TContainer::size_type; + + TContainer cont(INIT_SIZE); + auto idx = RandomNumber<size_type>(INIT_SIZE); + UNIT_ASSERT(!cont.IsTaken(idx)); + UNIT_ASSERT(!cont.IsDeleted(idx)); + UNIT_ASSERT_EQUAL(TDummy::Count, 0); + + cont.InitNode(idx); + UNIT_ASSERT_EQUAL(cont.Taken(), 1); + UNIT_ASSERT(cont.IsTaken(idx)); + UNIT_ASSERT(!cont.IsDeleted(idx)); + UNIT_ASSERT_EQUAL(TDummy::Count, 1); + + cont.DeleteNode(idx); + UNIT_ASSERT(!cont.IsTaken(idx)); + UNIT_ASSERT(cont.IsDeleted(idx)); + UNIT_ASSERT_EQUAL(TDummy::Count, 0); + } +} + +Y_UNIT_TEST_SUITE(TDenseContainerTest) { + Y_UNIT_TEST(SmokingTest) { + SmokingTest<TDenseContainer<int, NSet::TStaticValueMarker<-1>>>(INIT_SIZE); + } + + Y_UNIT_TEST(NotSimpleTypeSmokingTest) { + TNotSimple::ResetStats(); + SmokingTest<TDenseContainer<TNotSimple, TNotSimpleEmptyMarker>>(INIT_SIZE); + + UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls + TNotSimple::CopyCtorCalls + TNotSimple::MoveCtorCalls, + TNotSimple::DtorCalls); + UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls, INIT_SIZE / 2 /* created while filling */ + + 2 /* created by empty marker */); + UNIT_ASSERT_EQUAL(TNotSimple::DtorCalls, 1 /* removed empty marker temporary */ + + INIT_SIZE /* half removed while resetting in container, + half removed inserted temporary */ + + INIT_SIZE /* removed while cloning */ + + 1 /* removed empty marker temporary */ + + INIT_SIZE * 2 /* 3 containers dtors */); + UNIT_ASSERT_EQUAL(TNotSimple::CopyCtorCalls, INIT_SIZE /* created while constructing */ + + INIT_SIZE / 2 /* 3 created while filling */ + + INIT_SIZE /* created while copy constructing */ + + INIT_SIZE /* created while copy assigning */); + UNIT_ASSERT_EQUAL(TNotSimple::MoveCtorCalls, 0); + } + + Y_UNIT_TEST(RemovalContainerSmokingTest) { + SmokingTest<TRemovalDenseContainer<int, NSet::TStaticValueMarker<-1>, + NSet::TStaticValueMarker<-2>>>(INIT_SIZE); + } + + Y_UNIT_TEST(NotSimpleTypeRemovalContainerSmokingTest) { + TNotSimple::ResetStats(); + SmokingTest<TRemovalDenseContainer<TNotSimple, TNotSimpleEmptyMarker, + TNotSimpleDeletedMarker>>(INIT_SIZE); + + UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls + TNotSimple::CopyCtorCalls + TNotSimple::MoveCtorCalls, + TNotSimple::DtorCalls); + UNIT_ASSERT_EQUAL(TNotSimple::CtorCalls, INIT_SIZE / 2 /* created while filling */ + + 2 /* created by empty marker */); + UNIT_ASSERT_EQUAL(TNotSimple::DtorCalls, 1 /* removed empty marker temporary */ + + INIT_SIZE /* half removed while resetting in container, + half removed inserted temporary */ + + INIT_SIZE /* removed while cloning */ + + 1 /* removed empty marker temporary */ + + INIT_SIZE * 2 /* 3 containers dtors */); + UNIT_ASSERT_EQUAL(TNotSimple::CopyCtorCalls, INIT_SIZE /* created while constructing */ + + INIT_SIZE / 2 /* 3 created while filling */ + + INIT_SIZE /* created while copy constructing */ + + INIT_SIZE /* created while copy assigning */); + UNIT_ASSERT_EQUAL(TNotSimple::MoveCtorCalls, 0); + } + + Y_UNIT_TEST(DummyHalfSizeTest) { + using TContainer = TDenseContainer<TAlmostDummy, NSet::TEqValueMarker<TAlmostDummy>>; + using size_type = typename TContainer::size_type; + + { + TContainer cont(INIT_SIZE, TAlmostDummy{-1}); + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 1); // 1 for empty marker + + TVector<size_type> toInsert(cont.Size()); + Iota(toInsert.begin(), toInsert.end(), 0); + Shuffle(toInsert.begin(), toInsert.end()); + toInsert.resize(toInsert.size() / 2); + for (auto i : toInsert) { + UNIT_ASSERT(cont.IsEmpty(i)); + UNIT_ASSERT(!cont.IsTaken(i)); + cont.InitNode(i, (int)RandomNumber<size_type>(cont.Size())); + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 1); + UNIT_ASSERT(!cont.IsEmpty(i)); + UNIT_ASSERT(cont.IsTaken(i)); + } + UNIT_ASSERT_EQUAL(cont.Taken(), toInsert.size()); + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 1); + } + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, 0); + } + + Y_UNIT_TEST(DeleteTest) { + using TContainer = TRemovalDenseContainer<TAlmostDummy, NSet::TEqValueMarker<TAlmostDummy>, + NSet::TEqValueMarker<TAlmostDummy>>; + using size_type = typename TContainer::size_type; + + TContainer cont(INIT_SIZE, TAlmostDummy{ -2 }, TAlmostDummy{ -1 }); + auto idx = RandomNumber<size_type>(cont.Size()); + UNIT_ASSERT(!cont.IsTaken(idx)); + UNIT_ASSERT(!cont.IsDeleted(idx)); + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 2); // 2 for markers + + cont.InitNode(idx, (int)RandomNumber<size_type>(cont.Size())); + UNIT_ASSERT_EQUAL(cont.Taken(), 1); + UNIT_ASSERT(cont.IsTaken(idx)); + UNIT_ASSERT(!cont.IsDeleted(idx)); + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 2); + + cont.DeleteNode(idx); + UNIT_ASSERT(!cont.IsTaken(idx)); + UNIT_ASSERT(cont.IsDeleted(idx)); + UNIT_ASSERT_EQUAL(TAlmostDummy::Count, cont.Size() + 2); + } + + Y_UNIT_TEST(FancyInitsTest) { + { + using TContainer = TDenseContainer<int>; + TContainer cont{ INIT_SIZE, -1 }; + } + { + using TContainer = TDenseContainer<int, NSet::TStaticValueMarker<-1>>; + TContainer cont{ INIT_SIZE }; + static_assert(!std::is_constructible_v<TContainer, size_t, int>); + } + { + using TContainer = TDenseContainer<int, NSet::TEqValueMarker<int>>; + TContainer cont{ INIT_SIZE, -1 }; + TContainer cont2{ INIT_SIZE, NSet::TEqValueMarker<int>{ -1 } }; + } + { + using TContainer = TRemovalDenseContainer<int>; + TContainer cont{ INIT_SIZE, -1, -2 }; + TContainer cont2{ INIT_SIZE, NSet::TEqValueMarker<int>{ -1 }, + NSet::TEqValueMarker<int>{ -2 } }; + } + { + using TContainer = TRemovalDenseContainer<int, NSet::TStaticValueMarker<-1>, + NSet::TStaticValueMarker<-1>>; + TContainer cont{ INIT_SIZE }; + static_assert(!std::is_constructible_v<TContainer, size_t, int>); + static_assert(!std::is_constructible_v<TContainer, size_t, int, int>); + } + } +} diff --git a/library/cpp/containers/flat_hash/lib/ut/iterator_ut.cpp b/library/cpp/containers/flat_hash/lib/ut/iterator_ut.cpp index 10111b74da..0b77bf043f 100644 --- a/library/cpp/containers/flat_hash/lib/ut/iterator_ut.cpp +++ b/library/cpp/containers/flat_hash/lib/ut/iterator_ut.cpp @@ -1,85 +1,85 @@ #include <library/cpp/containers/flat_hash/lib/iterator.h> #include <library/cpp/containers/flat_hash/lib/containers.h> - + #include <library/cpp/testing/unittest/registar.h> - -#include <util/random/random.h> -#include <util/generic/algorithm.h> - -using namespace NFlatHash; - -namespace { - constexpr size_t INIT_SIZE = 128; - - template <class Container> - void SmokingTest(Container& cont) { - using value_type = typename Container::value_type; - using iterator = TIterator<Container, value_type>; - using size_type = typename Container::size_type; - - iterator f(&cont), l(&cont, cont.Size()); - UNIT_ASSERT_EQUAL(f, l); - UNIT_ASSERT_EQUAL((size_type)std::distance(f, l), cont.Taken()); - - TVector<std::pair<size_type, value_type>> toAdd{ - { 0, (int)RandomNumber<size_type>(INIT_SIZE) }, - { 1 + RandomNumber<size_type>(INIT_SIZE - 2), (int)RandomNumber<size_type>(INIT_SIZE) }, - { INIT_SIZE - 1, (int)RandomNumber<size_type>(INIT_SIZE) } - }; - - for (const auto& p : toAdd) { - UNIT_ASSERT(cont.IsEmpty(p.first)); - cont.InitNode(p.first, p.second); - } - UNIT_ASSERT_EQUAL(cont.Size(), INIT_SIZE); - f = iterator{ &cont }; - l = iterator{ &cont, INIT_SIZE }; - UNIT_ASSERT_UNEQUAL(f, l); - UNIT_ASSERT_EQUAL((size_type)std::distance(f, l), cont.Taken()); - - TVector<value_type> added(f, l); - UNIT_ASSERT(::Equal(toAdd.begin(), toAdd.end(), added.begin(), [](const auto& p, auto v) { - return p.second == v; - })); - } - - template <class Container> - void ConstTest(Container& cont) { - using value_type = typename Container::value_type; - using iterator = TIterator<Container, value_type>; - using const_iterator = TIterator<const Container, const value_type>; - - iterator it{ &cont, INIT_SIZE / 2 }; - const_iterator cit1{ it }; - const_iterator cit2{ &cont, INIT_SIZE / 2 }; - - UNIT_ASSERT_EQUAL(cit1, cit2); - - static_assert(std::is_same<decltype(*it), value_type&>::value); - static_assert(std::is_same<decltype(*cit1), const value_type&>::value); - } -} - -Y_UNIT_TEST_SUITE(TIteratorTest) { - Y_UNIT_TEST(SmokingTest) { - { - TFlatContainer<int> cont(INIT_SIZE); - SmokingTest(cont); - } - { - TDenseContainer<int, NSet::TStaticValueMarker<-1>> cont(INIT_SIZE); - SmokingTest(cont); - } - } - - Y_UNIT_TEST(ConstTest) { - { - TFlatContainer<int> cont(INIT_SIZE); - ConstTest(cont); - } - { - TDenseContainer<int, NSet::TStaticValueMarker<-1>> cont(INIT_SIZE); - ConstTest(cont); - } - } -} + +#include <util/random/random.h> +#include <util/generic/algorithm.h> + +using namespace NFlatHash; + +namespace { + constexpr size_t INIT_SIZE = 128; + + template <class Container> + void SmokingTest(Container& cont) { + using value_type = typename Container::value_type; + using iterator = TIterator<Container, value_type>; + using size_type = typename Container::size_type; + + iterator f(&cont), l(&cont, cont.Size()); + UNIT_ASSERT_EQUAL(f, l); + UNIT_ASSERT_EQUAL((size_type)std::distance(f, l), cont.Taken()); + + TVector<std::pair<size_type, value_type>> toAdd{ + { 0, (int)RandomNumber<size_type>(INIT_SIZE) }, + { 1 + RandomNumber<size_type>(INIT_SIZE - 2), (int)RandomNumber<size_type>(INIT_SIZE) }, + { INIT_SIZE - 1, (int)RandomNumber<size_type>(INIT_SIZE) } + }; + + for (const auto& p : toAdd) { + UNIT_ASSERT(cont.IsEmpty(p.first)); + cont.InitNode(p.first, p.second); + } + UNIT_ASSERT_EQUAL(cont.Size(), INIT_SIZE); + f = iterator{ &cont }; + l = iterator{ &cont, INIT_SIZE }; + UNIT_ASSERT_UNEQUAL(f, l); + UNIT_ASSERT_EQUAL((size_type)std::distance(f, l), cont.Taken()); + + TVector<value_type> added(f, l); + UNIT_ASSERT(::Equal(toAdd.begin(), toAdd.end(), added.begin(), [](const auto& p, auto v) { + return p.second == v; + })); + } + + template <class Container> + void ConstTest(Container& cont) { + using value_type = typename Container::value_type; + using iterator = TIterator<Container, value_type>; + using const_iterator = TIterator<const Container, const value_type>; + + iterator it{ &cont, INIT_SIZE / 2 }; + const_iterator cit1{ it }; + const_iterator cit2{ &cont, INIT_SIZE / 2 }; + + UNIT_ASSERT_EQUAL(cit1, cit2); + + static_assert(std::is_same<decltype(*it), value_type&>::value); + static_assert(std::is_same<decltype(*cit1), const value_type&>::value); + } +} + +Y_UNIT_TEST_SUITE(TIteratorTest) { + Y_UNIT_TEST(SmokingTest) { + { + TFlatContainer<int> cont(INIT_SIZE); + SmokingTest(cont); + } + { + TDenseContainer<int, NSet::TStaticValueMarker<-1>> cont(INIT_SIZE); + SmokingTest(cont); + } + } + + Y_UNIT_TEST(ConstTest) { + { + TFlatContainer<int> cont(INIT_SIZE); + ConstTest(cont); + } + { + TDenseContainer<int, NSet::TStaticValueMarker<-1>> cont(INIT_SIZE); + ConstTest(cont); + } + } +} diff --git a/library/cpp/containers/flat_hash/lib/ut/probings_ut.cpp b/library/cpp/containers/flat_hash/lib/ut/probings_ut.cpp index 7d709fdaa5..593f8cbb1b 100644 --- a/library/cpp/containers/flat_hash/lib/ut/probings_ut.cpp +++ b/library/cpp/containers/flat_hash/lib/ut/probings_ut.cpp @@ -1,34 +1,34 @@ #include <library/cpp/containers/flat_hash/lib/probings.h> - + #include <library/cpp/testing/unittest/registar.h> - -using namespace NFlatHash; - -namespace { - struct TDummySizeFitter { - constexpr auto EvalIndex(size_t idx, size_t) const { - return idx; - } - }; - + +using namespace NFlatHash; + +namespace { + struct TDummySizeFitter { + constexpr auto EvalIndex(size_t idx, size_t) const { + return idx; + } + }; + constexpr TDummySizeFitter SIZE_FITTER; - - auto atLeast13 = [](size_t idx) { return idx >= 13; }; -} - -Y_UNIT_TEST_SUITE(TProbingsTest) { - Y_UNIT_TEST(LinearProbingTest) { - using TProbing = TLinearProbing; - UNIT_ASSERT_EQUAL(TProbing::FindBucket(SIZE_FITTER, 1, 0, atLeast13), 13); - } - - Y_UNIT_TEST(QuadraticProbingTest) { - using TProbing = TQuadraticProbing; - UNIT_ASSERT_EQUAL(TProbing::FindBucket(SIZE_FITTER, 1, 0, atLeast13), 17); - } - - Y_UNIT_TEST(DenseProbingTest) { - using TProbing = TDenseProbing; - UNIT_ASSERT_EQUAL(TProbing::FindBucket(SIZE_FITTER, 1, 0, atLeast13), 16); - } -} + + auto atLeast13 = [](size_t idx) { return idx >= 13; }; +} + +Y_UNIT_TEST_SUITE(TProbingsTest) { + Y_UNIT_TEST(LinearProbingTest) { + using TProbing = TLinearProbing; + UNIT_ASSERT_EQUAL(TProbing::FindBucket(SIZE_FITTER, 1, 0, atLeast13), 13); + } + + Y_UNIT_TEST(QuadraticProbingTest) { + using TProbing = TQuadraticProbing; + UNIT_ASSERT_EQUAL(TProbing::FindBucket(SIZE_FITTER, 1, 0, atLeast13), 17); + } + + Y_UNIT_TEST(DenseProbingTest) { + using TProbing = TDenseProbing; + UNIT_ASSERT_EQUAL(TProbing::FindBucket(SIZE_FITTER, 1, 0, atLeast13), 16); + } +} diff --git a/library/cpp/containers/flat_hash/lib/ut/size_fitters_ut.cpp b/library/cpp/containers/flat_hash/lib/ut/size_fitters_ut.cpp index 52084e734b..4167947ece 100644 --- a/library/cpp/containers/flat_hash/lib/ut/size_fitters_ut.cpp +++ b/library/cpp/containers/flat_hash/lib/ut/size_fitters_ut.cpp @@ -1,51 +1,51 @@ #include <library/cpp/containers/flat_hash/lib/size_fitters.h> - + #include <library/cpp/testing/unittest/registar.h> - -using namespace NFlatHash; - -Y_UNIT_TEST_SUITE(TAndSizeFitterTest) { - Y_UNIT_TEST(EvalSizeTest) { - TAndSizeFitter sf; - UNIT_ASSERT_EQUAL(sf.EvalSize(5), 8); - UNIT_ASSERT_EQUAL(sf.EvalSize(8), 8); - UNIT_ASSERT_EQUAL(sf.EvalSize(13), 16); - UNIT_ASSERT_EQUAL(sf.EvalSize(25), 32); - for (size_t i = 1; i < 100; ++i) { - UNIT_ASSERT_EQUAL(sf.EvalSize(i), FastClp2(i)); - } - } - - Y_UNIT_TEST(EvalIndexTest) { - TAndSizeFitter sf; - for (size_t j = 1; j < 10; ++j) { - sf.Update(1 << j); - for (size_t i = 0; i < 100; ++i) { - UNIT_ASSERT_EQUAL(sf.EvalIndex(i, 1 << j), i & ((1 << j) - 1)); - } - } - } -} - -Y_UNIT_TEST_SUITE(TModSizeFitterTest) { - Y_UNIT_TEST(EvalSizeTest) { - TModSizeFitter sf; - UNIT_ASSERT_EQUAL(sf.EvalSize(5), 5); - UNIT_ASSERT_EQUAL(sf.EvalSize(8), 8); - UNIT_ASSERT_EQUAL(sf.EvalSize(13), 13); - UNIT_ASSERT_EQUAL(sf.EvalSize(25), 25); - for (size_t i = 1; i < 100; ++i) { - UNIT_ASSERT_EQUAL(sf.EvalSize(i), i); - } - } - - Y_UNIT_TEST(EvalIndexTest) { - TModSizeFitter sf; - for (size_t j = 1; j < 10; ++j) { - sf.Update(1 << j); // just for integrity - for (size_t i = 0; i < 100; ++i) { - UNIT_ASSERT_EQUAL(sf.EvalIndex(i, 1 << j), i % (1 << j)); - } - } - } -} + +using namespace NFlatHash; + +Y_UNIT_TEST_SUITE(TAndSizeFitterTest) { + Y_UNIT_TEST(EvalSizeTest) { + TAndSizeFitter sf; + UNIT_ASSERT_EQUAL(sf.EvalSize(5), 8); + UNIT_ASSERT_EQUAL(sf.EvalSize(8), 8); + UNIT_ASSERT_EQUAL(sf.EvalSize(13), 16); + UNIT_ASSERT_EQUAL(sf.EvalSize(25), 32); + for (size_t i = 1; i < 100; ++i) { + UNIT_ASSERT_EQUAL(sf.EvalSize(i), FastClp2(i)); + } + } + + Y_UNIT_TEST(EvalIndexTest) { + TAndSizeFitter sf; + for (size_t j = 1; j < 10; ++j) { + sf.Update(1 << j); + for (size_t i = 0; i < 100; ++i) { + UNIT_ASSERT_EQUAL(sf.EvalIndex(i, 1 << j), i & ((1 << j) - 1)); + } + } + } +} + +Y_UNIT_TEST_SUITE(TModSizeFitterTest) { + Y_UNIT_TEST(EvalSizeTest) { + TModSizeFitter sf; + UNIT_ASSERT_EQUAL(sf.EvalSize(5), 5); + UNIT_ASSERT_EQUAL(sf.EvalSize(8), 8); + UNIT_ASSERT_EQUAL(sf.EvalSize(13), 13); + UNIT_ASSERT_EQUAL(sf.EvalSize(25), 25); + for (size_t i = 1; i < 100; ++i) { + UNIT_ASSERT_EQUAL(sf.EvalSize(i), i); + } + } + + Y_UNIT_TEST(EvalIndexTest) { + TModSizeFitter sf; + for (size_t j = 1; j < 10; ++j) { + sf.Update(1 << j); // just for integrity + for (size_t i = 0; i < 100; ++i) { + UNIT_ASSERT_EQUAL(sf.EvalIndex(i, 1 << j), i % (1 << j)); + } + } + } +} diff --git a/library/cpp/containers/flat_hash/lib/ut/table_ut.cpp b/library/cpp/containers/flat_hash/lib/ut/table_ut.cpp index dda4ba3fd0..ea511e2c6a 100644 --- a/library/cpp/containers/flat_hash/lib/ut/table_ut.cpp +++ b/library/cpp/containers/flat_hash/lib/ut/table_ut.cpp @@ -3,409 +3,409 @@ #include <library/cpp/containers/flat_hash/lib/probings.h> #include <library/cpp/containers/flat_hash/lib/size_fitters.h> #include <library/cpp/containers/flat_hash/lib/table.h> - + #include <library/cpp/testing/unittest/registar.h> - -#include <util/generic/algorithm.h> -#include <util/random/random.h> -#include <util/random/shuffle.h> - -using namespace NFlatHash; - -namespace { - template <class T> - struct TJustType { - using type = T; - }; - - template <class... Ts> - struct TTypePack {}; - - template <class F, class... Ts> - constexpr void ForEachType(F&& f, TTypePack<Ts...>) { - ApplyToMany(std::forward<F>(f), TJustType<Ts>{}...); - } - -/* Usage example: - * - * TForEachType<int, float, TString>::Apply([](auto t) { - * using T = GET_TYPE(t); - * }); - * So T would be: - * int on #0 iteration - * float on #1 iteration - * TString on #2 iteration - */ -#define GET_TYPE(ti) typename decltype(ti)::type - - constexpr size_t INIT_SIZE = 32; - constexpr size_t BIG_INIT_SIZE = 128; - - template <class T> - struct TSimpleKeyGetter { - static constexpr T& Apply(T& t) { return t; } - static constexpr const T& Apply(const T& t) { return t; } - }; - - template <class T, - class KeyEqual = std::equal_to<T>, - class ValueEqual = std::equal_to<T>, - class KeyGetter = TSimpleKeyGetter<T>, - class F, - class... Containers> - void ForEachTable(F f, TTypePack<Containers...> cs) { - ForEachType([&](auto p) { - using TProbing = GET_TYPE(p); - - ForEachType([&](auto sf) { - using TSizeFitter = GET_TYPE(sf); - - ForEachType([&](auto t) { - using TContainer = GET_TYPE(t); - static_assert(std::is_same_v<typename TContainer::value_type, T>); - - using TTable = TTable<THash<T>, - KeyEqual, - TContainer, - KeyGetter, - TProbing, - TSizeFitter, - TSimpleExpander>; - - f(TJustType<TTable>{}); - }, cs); - }, TTypePack<TAndSizeFitter, TModSizeFitter>{}); - }, TTypePack<TLinearProbing, TQuadraticProbing, TDenseProbing>{}); - } - - using TAtomContainers = TTypePack<TFlatContainer<int>, - TDenseContainer<int, NSet::TStaticValueMarker<-1>>>; - using TContainers = TTypePack<TFlatContainer<int>, - TDenseContainer<int, NSet::TStaticValueMarker<-1>>>; - using TRemovalContainers = TTypePack<TFlatContainer<int>, - TRemovalDenseContainer<int, NSet::TStaticValueMarker<-2>, - NSet::TStaticValueMarker<-1>>>; -} - -Y_UNIT_TEST_SUITE(TCommonTableAtomsTest) { - Y_UNIT_TEST(InitTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - UNIT_ASSERT(table.empty()); - UNIT_ASSERT_EQUAL(table.size(), 0); - UNIT_ASSERT_EQUAL(table.bucket_count(), INIT_SIZE); - UNIT_ASSERT_EQUAL(table.bucket_size(RandomNumber<size_t>(INIT_SIZE)), 0); - }, TAtomContainers{}); - } - - Y_UNIT_TEST(IteratorTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - auto first = table.begin(); - auto last = table.end(); - UNIT_ASSERT_EQUAL(first, last); - UNIT_ASSERT_EQUAL(std::distance(first, last), 0); - - auto cFirst = table.cbegin(); - auto cLast = table.cend(); - UNIT_ASSERT_EQUAL(cFirst, cLast); - UNIT_ASSERT_EQUAL(std::distance(cFirst, cLast), 0); - }, TAtomContainers{}); - } - - Y_UNIT_TEST(ContainsAndCountTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - for (int i = 0; i < 100; ++i) { - UNIT_ASSERT_EQUAL(table.count(i), 0); - UNIT_ASSERT(!table.contains(i)); - } - }, TAtomContainers{}); - } - - Y_UNIT_TEST(FindTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - for (int i = 0; i < 100; ++i) { - auto it = table.find(i); - UNIT_ASSERT_EQUAL(it, table.end()); - } - }, TAtomContainers{}); - } -} - -Y_UNIT_TEST_SUITE(TCommonTableTest) { - Y_UNIT_TEST(InsertTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - UNIT_ASSERT(table.empty()); - UNIT_ASSERT_EQUAL(table.size(), 0); - - int toInsert = RandomNumber<size_t>(100); - UNIT_ASSERT_EQUAL(table.count(toInsert), 0); - UNIT_ASSERT(!table.contains(toInsert)); - - auto p = table.insert(toInsert); - UNIT_ASSERT_EQUAL(p.first, table.begin()); - UNIT_ASSERT(p.second); - - UNIT_ASSERT(!table.empty()); - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(toInsert), 1); - UNIT_ASSERT(table.contains(toInsert)); - - auto it = table.find(toInsert); - UNIT_ASSERT_UNEQUAL(it, table.end()); - UNIT_ASSERT_EQUAL(it, table.begin()); - UNIT_ASSERT_EQUAL(*it, toInsert); - - auto p2 = table.insert(toInsert); - UNIT_ASSERT_EQUAL(p.first, p2.first); - UNIT_ASSERT(!p2.second); - - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(toInsert), 1); - UNIT_ASSERT(table.contains(toInsert)); - }, TContainers{}); - } - - Y_UNIT_TEST(ClearTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - TVector<int> toInsert(INIT_SIZE); - Iota(toInsert.begin(), toInsert.end(), 0); - ShuffleRange(toInsert); - toInsert.resize(INIT_SIZE / 3); - - for (auto i : toInsert) { - auto p = table.insert(i); - UNIT_ASSERT_EQUAL(*p.first, i); - UNIT_ASSERT(p.second); - } - UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table.begin(), table.end()), toInsert.size()); - - for (auto i : toInsert) { - UNIT_ASSERT(table.contains(i)); - UNIT_ASSERT_EQUAL(table.count(i), 1); - } - - auto bc = table.bucket_count(); - table.clear(); - UNIT_ASSERT(table.empty()); - UNIT_ASSERT_EQUAL(table.bucket_count(), bc); - - for (auto i : toInsert) { - UNIT_ASSERT(!table.contains(i)); - UNIT_ASSERT_EQUAL(table.count(i), 0); - } - - table.insert(toInsert.front()); - UNIT_ASSERT(!table.empty()); - }, TContainers{}); - } - - Y_UNIT_TEST(CopyMoveTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - TVector<int> toInsert(INIT_SIZE); - Iota(toInsert.begin(), toInsert.end(), 0); - ShuffleRange(toInsert); - toInsert.resize(INIT_SIZE / 3); - - for (auto i : toInsert) { - auto p = table.insert(i); - UNIT_ASSERT_EQUAL(*p.first, i); - UNIT_ASSERT(p.second); - } - UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table.begin(), table.end()), toInsert.size()); - - for (auto i : toInsert) { - UNIT_ASSERT(table.contains(i)); - UNIT_ASSERT_EQUAL(table.count(i), 1); - } - - // Copy construction test - auto table2 = table; - UNIT_ASSERT_EQUAL(table2.size(), table.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table2.begin(), table2.end()), table.size()); - for (auto i : table) { - UNIT_ASSERT(table2.contains(i)); - UNIT_ASSERT_EQUAL(table2.count(i), 1); - } - - table2.clear(); - UNIT_ASSERT(table2.empty()); - - // Copy assignment test - table2 = table; - UNIT_ASSERT_EQUAL(table2.size(), table.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table2.begin(), table2.end()), table.size()); - for (auto i : table) { - UNIT_ASSERT(table2.contains(i)); - UNIT_ASSERT_EQUAL(table2.count(i), 1); - } - - // Move construction test - auto table3 = std::move(table2); - UNIT_ASSERT(table2.empty()); - UNIT_ASSERT(table2.bucket_count() > 0); - - UNIT_ASSERT_EQUAL(table3.size(), table.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table3.begin(), table3.end()), table.size()); - for (auto i : table) { - UNIT_ASSERT(table3.contains(i)); - UNIT_ASSERT_EQUAL(table3.count(i), 1); - } - - table2.insert(toInsert.front()); - UNIT_ASSERT(!table2.empty()); - UNIT_ASSERT_EQUAL(table2.size(), 1); - UNIT_ASSERT_UNEQUAL(table2.bucket_count(), 0); - - // Move assignment test - table2 = std::move(table3); - UNIT_ASSERT(table3.empty()); - UNIT_ASSERT(table3.bucket_count() > 0); - - UNIT_ASSERT_EQUAL(table2.size(), table.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table2.begin(), table2.end()), table.size()); - for (auto i : table) { - UNIT_ASSERT(table2.contains(i)); - UNIT_ASSERT_EQUAL(table2.count(i), 1); - } - - table3.insert(toInsert.front()); - UNIT_ASSERT(!table3.empty()); - UNIT_ASSERT_EQUAL(table3.size(), 1); - UNIT_ASSERT_UNEQUAL(table3.bucket_count(), 0); - }, TContainers{}); - } - - Y_UNIT_TEST(RehashTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - TVector<int> toInsert(INIT_SIZE); - Iota(toInsert.begin(), toInsert.end(), 0); - ShuffleRange(toInsert); - toInsert.resize(INIT_SIZE / 3); - - for (auto i : toInsert) { - table.insert(i); - } - - auto bc = table.bucket_count(); - table.rehash(bc * 2); - UNIT_ASSERT(bc * 2 <= table.bucket_count()); - - UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); - UNIT_ASSERT_EQUAL((size_t)std::distance(table.begin(), table.end()), toInsert.size()); - for (auto i : toInsert) { - UNIT_ASSERT(table.contains(i)); - UNIT_ASSERT_EQUAL(table.count(i), 1); - } - - TVector<int> tmp(table.begin(), table.end()); - Sort(toInsert.begin(), toInsert.end()); - Sort(tmp.begin(), tmp.end()); - - UNIT_ASSERT_VALUES_EQUAL(tmp, toInsert); - - table.rehash(0); - UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); - UNIT_ASSERT(table.bucket_count() > table.size()); - - table.clear(); - UNIT_ASSERT(table.empty()); - table.rehash(INIT_SIZE); - UNIT_ASSERT(table.bucket_count() >= INIT_SIZE); - - table.rehash(0); - UNIT_ASSERT(table.bucket_count() > 0); - }, TContainers{}); - } - - Y_UNIT_TEST(EraseTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ INIT_SIZE }; - - int value = RandomNumber<ui32>(); - table.insert(value); - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(value), 1); - - auto it = table.find(value); - table.erase(it); - - UNIT_ASSERT_EQUAL(table.size(), 0); - UNIT_ASSERT_EQUAL(table.count(value), 0); - - table.insert(value); - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(value), 1); - - table.erase(value); - - UNIT_ASSERT_EQUAL(table.size(), 0); - UNIT_ASSERT_EQUAL(table.count(value), 0); - - table.insert(value); - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(value), 1); - - table.erase(table.find(value), table.end()); - - UNIT_ASSERT_EQUAL(table.size(), 0); - UNIT_ASSERT_EQUAL(table.count(value), 0); - - table.erase(value); - - UNIT_ASSERT_EQUAL(table.size(), 0); - UNIT_ASSERT_EQUAL(table.count(value), 0); - }, TRemovalContainers{}); - } - - Y_UNIT_TEST(EraseBigTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ BIG_INIT_SIZE }; - - for (int i = 0; i < 1000; ++i) { - for (int j = 0; j < static_cast<int>(BIG_INIT_SIZE); ++j) { - table.emplace(j); - } - for (int j = 0; j < static_cast<int>(BIG_INIT_SIZE); ++j) { - table.erase(j); - } - } - UNIT_ASSERT(table.bucket_count() <= BIG_INIT_SIZE * 8); - }, TRemovalContainers{}); - } - - Y_UNIT_TEST(ConstructWithSizeTest) { - ForEachTable<int>([](auto t) { - GET_TYPE(t) table{ 1000 }; - UNIT_ASSERT(table.bucket_count() >= 1000); - - int value = RandomNumber<ui32>(); - table.insert(value); - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(value), 1); - UNIT_ASSERT(table.bucket_count() >= 1000); - - table.rehash(10); - UNIT_ASSERT_EQUAL(table.size(), 1); - UNIT_ASSERT_EQUAL(table.count(value), 1); - UNIT_ASSERT(table.bucket_count() < 1000); - UNIT_ASSERT(table.bucket_count() >= 10); - }, TContainers{}); - } -} + +#include <util/generic/algorithm.h> +#include <util/random/random.h> +#include <util/random/shuffle.h> + +using namespace NFlatHash; + +namespace { + template <class T> + struct TJustType { + using type = T; + }; + + template <class... Ts> + struct TTypePack {}; + + template <class F, class... Ts> + constexpr void ForEachType(F&& f, TTypePack<Ts...>) { + ApplyToMany(std::forward<F>(f), TJustType<Ts>{}...); + } + +/* Usage example: + * + * TForEachType<int, float, TString>::Apply([](auto t) { + * using T = GET_TYPE(t); + * }); + * So T would be: + * int on #0 iteration + * float on #1 iteration + * TString on #2 iteration + */ +#define GET_TYPE(ti) typename decltype(ti)::type + + constexpr size_t INIT_SIZE = 32; + constexpr size_t BIG_INIT_SIZE = 128; + + template <class T> + struct TSimpleKeyGetter { + static constexpr T& Apply(T& t) { return t; } + static constexpr const T& Apply(const T& t) { return t; } + }; + + template <class T, + class KeyEqual = std::equal_to<T>, + class ValueEqual = std::equal_to<T>, + class KeyGetter = TSimpleKeyGetter<T>, + class F, + class... Containers> + void ForEachTable(F f, TTypePack<Containers...> cs) { + ForEachType([&](auto p) { + using TProbing = GET_TYPE(p); + + ForEachType([&](auto sf) { + using TSizeFitter = GET_TYPE(sf); + + ForEachType([&](auto t) { + using TContainer = GET_TYPE(t); + static_assert(std::is_same_v<typename TContainer::value_type, T>); + + using TTable = TTable<THash<T>, + KeyEqual, + TContainer, + KeyGetter, + TProbing, + TSizeFitter, + TSimpleExpander>; + + f(TJustType<TTable>{}); + }, cs); + }, TTypePack<TAndSizeFitter, TModSizeFitter>{}); + }, TTypePack<TLinearProbing, TQuadraticProbing, TDenseProbing>{}); + } + + using TAtomContainers = TTypePack<TFlatContainer<int>, + TDenseContainer<int, NSet::TStaticValueMarker<-1>>>; + using TContainers = TTypePack<TFlatContainer<int>, + TDenseContainer<int, NSet::TStaticValueMarker<-1>>>; + using TRemovalContainers = TTypePack<TFlatContainer<int>, + TRemovalDenseContainer<int, NSet::TStaticValueMarker<-2>, + NSet::TStaticValueMarker<-1>>>; +} + +Y_UNIT_TEST_SUITE(TCommonTableAtomsTest) { + Y_UNIT_TEST(InitTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + UNIT_ASSERT(table.empty()); + UNIT_ASSERT_EQUAL(table.size(), 0); + UNIT_ASSERT_EQUAL(table.bucket_count(), INIT_SIZE); + UNIT_ASSERT_EQUAL(table.bucket_size(RandomNumber<size_t>(INIT_SIZE)), 0); + }, TAtomContainers{}); + } + + Y_UNIT_TEST(IteratorTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + auto first = table.begin(); + auto last = table.end(); + UNIT_ASSERT_EQUAL(first, last); + UNIT_ASSERT_EQUAL(std::distance(first, last), 0); + + auto cFirst = table.cbegin(); + auto cLast = table.cend(); + UNIT_ASSERT_EQUAL(cFirst, cLast); + UNIT_ASSERT_EQUAL(std::distance(cFirst, cLast), 0); + }, TAtomContainers{}); + } + + Y_UNIT_TEST(ContainsAndCountTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + for (int i = 0; i < 100; ++i) { + UNIT_ASSERT_EQUAL(table.count(i), 0); + UNIT_ASSERT(!table.contains(i)); + } + }, TAtomContainers{}); + } + + Y_UNIT_TEST(FindTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + for (int i = 0; i < 100; ++i) { + auto it = table.find(i); + UNIT_ASSERT_EQUAL(it, table.end()); + } + }, TAtomContainers{}); + } +} + +Y_UNIT_TEST_SUITE(TCommonTableTest) { + Y_UNIT_TEST(InsertTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + UNIT_ASSERT(table.empty()); + UNIT_ASSERT_EQUAL(table.size(), 0); + + int toInsert = RandomNumber<size_t>(100); + UNIT_ASSERT_EQUAL(table.count(toInsert), 0); + UNIT_ASSERT(!table.contains(toInsert)); + + auto p = table.insert(toInsert); + UNIT_ASSERT_EQUAL(p.first, table.begin()); + UNIT_ASSERT(p.second); + + UNIT_ASSERT(!table.empty()); + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(toInsert), 1); + UNIT_ASSERT(table.contains(toInsert)); + + auto it = table.find(toInsert); + UNIT_ASSERT_UNEQUAL(it, table.end()); + UNIT_ASSERT_EQUAL(it, table.begin()); + UNIT_ASSERT_EQUAL(*it, toInsert); + + auto p2 = table.insert(toInsert); + UNIT_ASSERT_EQUAL(p.first, p2.first); + UNIT_ASSERT(!p2.second); + + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(toInsert), 1); + UNIT_ASSERT(table.contains(toInsert)); + }, TContainers{}); + } + + Y_UNIT_TEST(ClearTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + TVector<int> toInsert(INIT_SIZE); + Iota(toInsert.begin(), toInsert.end(), 0); + ShuffleRange(toInsert); + toInsert.resize(INIT_SIZE / 3); + + for (auto i : toInsert) { + auto p = table.insert(i); + UNIT_ASSERT_EQUAL(*p.first, i); + UNIT_ASSERT(p.second); + } + UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table.begin(), table.end()), toInsert.size()); + + for (auto i : toInsert) { + UNIT_ASSERT(table.contains(i)); + UNIT_ASSERT_EQUAL(table.count(i), 1); + } + + auto bc = table.bucket_count(); + table.clear(); + UNIT_ASSERT(table.empty()); + UNIT_ASSERT_EQUAL(table.bucket_count(), bc); + + for (auto i : toInsert) { + UNIT_ASSERT(!table.contains(i)); + UNIT_ASSERT_EQUAL(table.count(i), 0); + } + + table.insert(toInsert.front()); + UNIT_ASSERT(!table.empty()); + }, TContainers{}); + } + + Y_UNIT_TEST(CopyMoveTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + TVector<int> toInsert(INIT_SIZE); + Iota(toInsert.begin(), toInsert.end(), 0); + ShuffleRange(toInsert); + toInsert.resize(INIT_SIZE / 3); + + for (auto i : toInsert) { + auto p = table.insert(i); + UNIT_ASSERT_EQUAL(*p.first, i); + UNIT_ASSERT(p.second); + } + UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table.begin(), table.end()), toInsert.size()); + + for (auto i : toInsert) { + UNIT_ASSERT(table.contains(i)); + UNIT_ASSERT_EQUAL(table.count(i), 1); + } + + // Copy construction test + auto table2 = table; + UNIT_ASSERT_EQUAL(table2.size(), table.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table2.begin(), table2.end()), table.size()); + for (auto i : table) { + UNIT_ASSERT(table2.contains(i)); + UNIT_ASSERT_EQUAL(table2.count(i), 1); + } + + table2.clear(); + UNIT_ASSERT(table2.empty()); + + // Copy assignment test + table2 = table; + UNIT_ASSERT_EQUAL(table2.size(), table.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table2.begin(), table2.end()), table.size()); + for (auto i : table) { + UNIT_ASSERT(table2.contains(i)); + UNIT_ASSERT_EQUAL(table2.count(i), 1); + } + + // Move construction test + auto table3 = std::move(table2); + UNIT_ASSERT(table2.empty()); + UNIT_ASSERT(table2.bucket_count() > 0); + + UNIT_ASSERT_EQUAL(table3.size(), table.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table3.begin(), table3.end()), table.size()); + for (auto i : table) { + UNIT_ASSERT(table3.contains(i)); + UNIT_ASSERT_EQUAL(table3.count(i), 1); + } + + table2.insert(toInsert.front()); + UNIT_ASSERT(!table2.empty()); + UNIT_ASSERT_EQUAL(table2.size(), 1); + UNIT_ASSERT_UNEQUAL(table2.bucket_count(), 0); + + // Move assignment test + table2 = std::move(table3); + UNIT_ASSERT(table3.empty()); + UNIT_ASSERT(table3.bucket_count() > 0); + + UNIT_ASSERT_EQUAL(table2.size(), table.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table2.begin(), table2.end()), table.size()); + for (auto i : table) { + UNIT_ASSERT(table2.contains(i)); + UNIT_ASSERT_EQUAL(table2.count(i), 1); + } + + table3.insert(toInsert.front()); + UNIT_ASSERT(!table3.empty()); + UNIT_ASSERT_EQUAL(table3.size(), 1); + UNIT_ASSERT_UNEQUAL(table3.bucket_count(), 0); + }, TContainers{}); + } + + Y_UNIT_TEST(RehashTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + TVector<int> toInsert(INIT_SIZE); + Iota(toInsert.begin(), toInsert.end(), 0); + ShuffleRange(toInsert); + toInsert.resize(INIT_SIZE / 3); + + for (auto i : toInsert) { + table.insert(i); + } + + auto bc = table.bucket_count(); + table.rehash(bc * 2); + UNIT_ASSERT(bc * 2 <= table.bucket_count()); + + UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); + UNIT_ASSERT_EQUAL((size_t)std::distance(table.begin(), table.end()), toInsert.size()); + for (auto i : toInsert) { + UNIT_ASSERT(table.contains(i)); + UNIT_ASSERT_EQUAL(table.count(i), 1); + } + + TVector<int> tmp(table.begin(), table.end()); + Sort(toInsert.begin(), toInsert.end()); + Sort(tmp.begin(), tmp.end()); + + UNIT_ASSERT_VALUES_EQUAL(tmp, toInsert); + + table.rehash(0); + UNIT_ASSERT_EQUAL(table.size(), toInsert.size()); + UNIT_ASSERT(table.bucket_count() > table.size()); + + table.clear(); + UNIT_ASSERT(table.empty()); + table.rehash(INIT_SIZE); + UNIT_ASSERT(table.bucket_count() >= INIT_SIZE); + + table.rehash(0); + UNIT_ASSERT(table.bucket_count() > 0); + }, TContainers{}); + } + + Y_UNIT_TEST(EraseTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ INIT_SIZE }; + + int value = RandomNumber<ui32>(); + table.insert(value); + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(value), 1); + + auto it = table.find(value); + table.erase(it); + + UNIT_ASSERT_EQUAL(table.size(), 0); + UNIT_ASSERT_EQUAL(table.count(value), 0); + + table.insert(value); + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(value), 1); + + table.erase(value); + + UNIT_ASSERT_EQUAL(table.size(), 0); + UNIT_ASSERT_EQUAL(table.count(value), 0); + + table.insert(value); + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(value), 1); + + table.erase(table.find(value), table.end()); + + UNIT_ASSERT_EQUAL(table.size(), 0); + UNIT_ASSERT_EQUAL(table.count(value), 0); + + table.erase(value); + + UNIT_ASSERT_EQUAL(table.size(), 0); + UNIT_ASSERT_EQUAL(table.count(value), 0); + }, TRemovalContainers{}); + } + + Y_UNIT_TEST(EraseBigTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ BIG_INIT_SIZE }; + + for (int i = 0; i < 1000; ++i) { + for (int j = 0; j < static_cast<int>(BIG_INIT_SIZE); ++j) { + table.emplace(j); + } + for (int j = 0; j < static_cast<int>(BIG_INIT_SIZE); ++j) { + table.erase(j); + } + } + UNIT_ASSERT(table.bucket_count() <= BIG_INIT_SIZE * 8); + }, TRemovalContainers{}); + } + + Y_UNIT_TEST(ConstructWithSizeTest) { + ForEachTable<int>([](auto t) { + GET_TYPE(t) table{ 1000 }; + UNIT_ASSERT(table.bucket_count() >= 1000); + + int value = RandomNumber<ui32>(); + table.insert(value); + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(value), 1); + UNIT_ASSERT(table.bucket_count() >= 1000); + + table.rehash(10); + UNIT_ASSERT_EQUAL(table.size(), 1); + UNIT_ASSERT_EQUAL(table.count(value), 1); + UNIT_ASSERT(table.bucket_count() < 1000); + UNIT_ASSERT(table.bucket_count() >= 10); + }, TContainers{}); + } +} diff --git a/library/cpp/containers/flat_hash/lib/ut/ya.make b/library/cpp/containers/flat_hash/lib/ut/ya.make index 5ffbfb2dd8..04d65a8c6e 100644 --- a/library/cpp/containers/flat_hash/lib/ut/ya.make +++ b/library/cpp/containers/flat_hash/lib/ut/ya.make @@ -1,17 +1,17 @@ -UNITTEST() - -OWNER(tender-bum) - -SRCS( - size_fitters_ut.cpp - probings_ut.cpp - containers_ut.cpp - iterator_ut.cpp - table_ut.cpp -) - -PEERDIR( +UNITTEST() + +OWNER(tender-bum) + +SRCS( + size_fitters_ut.cpp + probings_ut.cpp + containers_ut.cpp + iterator_ut.cpp + table_ut.cpp +) + +PEERDIR( library/cpp/containers/flat_hash/lib -) - -END() +) + +END() |