|
|
@@ -2,6 +2,8 @@
|
|
|
#include <gtest/gtest.h>
|
|
|
#include <entt/entity/registry.hpp>
|
|
|
#include <entt/entity/storage.hpp>
|
|
|
+#include "../common/throwing_allocator.hpp"
|
|
|
+#include "../common/throwing_type.hpp"
|
|
|
|
|
|
struct empty_type {};
|
|
|
|
|
|
@@ -31,13 +33,12 @@ TEST(SighStorageMixin, GenericType) {
|
|
|
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
|
|
entt::sigh_storage_mixin<entt::storage<int>> pool;
|
|
|
entt::sparse_set &base = pool;
|
|
|
- entt::registry registry{};
|
|
|
-
|
|
|
- pool.bind(entt::forward_as_any(registry));
|
|
|
+ entt::registry registry;
|
|
|
|
|
|
counter on_construct{};
|
|
|
counter on_destroy{};
|
|
|
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
pool.on_construct().connect<&listener>(on_construct);
|
|
|
pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
|
|
|
@@ -97,13 +98,12 @@ TEST(SighStorageMixin, StableType) {
|
|
|
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
|
|
entt::sigh_storage_mixin<entt::storage<stable_type>> pool;
|
|
|
entt::sparse_set &base = pool;
|
|
|
- entt::registry registry{};
|
|
|
-
|
|
|
- pool.bind(entt::forward_as_any(registry));
|
|
|
+ entt::registry registry;
|
|
|
|
|
|
counter on_construct{};
|
|
|
counter on_destroy{};
|
|
|
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
pool.on_construct().connect<&listener>(on_construct);
|
|
|
pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
|
|
|
@@ -163,13 +163,12 @@ TEST(SighStorageMixin, EmptyType) {
|
|
|
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
|
|
entt::sigh_storage_mixin<entt::storage<empty_type>> pool;
|
|
|
entt::sparse_set &base = pool;
|
|
|
- entt::registry registry{};
|
|
|
-
|
|
|
- pool.bind(entt::forward_as_any(registry));
|
|
|
+ entt::registry registry;
|
|
|
|
|
|
counter on_construct{};
|
|
|
counter on_destroy{};
|
|
|
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
pool.on_construct().connect<&listener>(on_construct);
|
|
|
pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
|
|
|
@@ -229,13 +228,12 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
|
|
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
|
|
entt::sigh_storage_mixin<entt::storage<non_default_constructible>> pool;
|
|
|
entt::sparse_set &base = pool;
|
|
|
- entt::registry registry{};
|
|
|
-
|
|
|
- pool.bind(entt::forward_as_any(registry));
|
|
|
+ entt::registry registry;
|
|
|
|
|
|
counter on_construct{};
|
|
|
counter on_destroy{};
|
|
|
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
pool.on_construct().connect<&listener>(on_construct);
|
|
|
pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
|
|
|
@@ -281,3 +279,329 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
|
|
|
ASSERT_EQ(on_destroy.value, 3);
|
|
|
ASSERT_TRUE(pool.empty());
|
|
|
}
|
|
|
+
|
|
|
+TEST(SighStorageMixin, VoidType) {
|
|
|
+ entt::sigh_storage_mixin<entt::storage<void>> pool;
|
|
|
+ entt::registry registry;
|
|
|
+
|
|
|
+ counter on_construct{};
|
|
|
+ counter on_destroy{};
|
|
|
+
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
+ pool.on_construct().connect<&listener>(on_construct);
|
|
|
+ pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ pool.emplace(entt::entity{99});
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.type(), entt::type_id<void>());
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{99}));
|
|
|
+
|
|
|
+ entt::sigh_storage_mixin<entt::storage<void>> other{std::move(pool)};
|
|
|
+
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{99}));
|
|
|
+ ASSERT_TRUE(other.contains(entt::entity{99}));
|
|
|
+
|
|
|
+ pool = std::move(other);
|
|
|
+
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{99}));
|
|
|
+ ASSERT_FALSE(other.contains(entt::entity{99}));
|
|
|
+
|
|
|
+ pool.clear();
|
|
|
+
|
|
|
+ ASSERT_EQ(on_construct.value, 1);
|
|
|
+ ASSERT_EQ(on_destroy.value, 1);
|
|
|
+}
|
|
|
+
|
|
|
+TEST(SighStorageMixin, Move) {
|
|
|
+ entt::sigh_storage_mixin<entt::storage<int>> pool;
|
|
|
+ entt::registry registry;
|
|
|
+
|
|
|
+ counter on_construct{};
|
|
|
+ counter on_destroy{};
|
|
|
+
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
+ pool.on_construct().connect<&listener>(on_construct);
|
|
|
+ pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ pool.emplace(entt::entity{3}, 3);
|
|
|
+
|
|
|
+ ASSERT_TRUE(std::is_move_constructible_v<decltype(pool)>);
|
|
|
+ ASSERT_TRUE(std::is_move_assignable_v<decltype(pool)>);
|
|
|
+ ASSERT_EQ(pool.type(), entt::type_id<int>());
|
|
|
+
|
|
|
+ entt::sigh_storage_mixin<entt::storage<int>> other{std::move(pool)};
|
|
|
+
|
|
|
+ ASSERT_TRUE(pool.empty());
|
|
|
+ ASSERT_FALSE(other.empty());
|
|
|
+ ASSERT_EQ(other.type(), entt::type_id<int>());
|
|
|
+ ASSERT_EQ(pool.at(0u), static_cast<entt::entity>(entt::null));
|
|
|
+ ASSERT_EQ(other.at(0u), entt::entity{3});
|
|
|
+ ASSERT_EQ(other.get(entt::entity{3}), 3);
|
|
|
+
|
|
|
+ pool = std::move(other);
|
|
|
+
|
|
|
+ ASSERT_FALSE(pool.empty());
|
|
|
+ ASSERT_TRUE(other.empty());
|
|
|
+ ASSERT_EQ(pool.at(0u), entt::entity{3});
|
|
|
+ ASSERT_EQ(pool.get(entt::entity{3}), 3);
|
|
|
+ ASSERT_EQ(other.at(0u), static_cast<entt::entity>(entt::null));
|
|
|
+
|
|
|
+ other = entt::sigh_storage_mixin<entt::storage<int>>{};
|
|
|
+ other.bind(entt::forward_as_any(registry));
|
|
|
+
|
|
|
+ other.emplace(entt::entity{42}, 42);
|
|
|
+ other = std::move(pool);
|
|
|
+
|
|
|
+ ASSERT_TRUE(pool.empty());
|
|
|
+ ASSERT_FALSE(other.empty());
|
|
|
+ ASSERT_EQ(pool.at(0u), static_cast<entt::entity>(entt::null));
|
|
|
+ ASSERT_EQ(other.at(0u), entt::entity{3});
|
|
|
+ ASSERT_EQ(other.get(entt::entity{3}), 3);
|
|
|
+
|
|
|
+ other.clear();
|
|
|
+
|
|
|
+ ASSERT_EQ(on_construct.value, 1);
|
|
|
+ ASSERT_EQ(on_destroy.value, 1);
|
|
|
+}
|
|
|
+
|
|
|
+TEST(SighStorageMixin, Swap) {
|
|
|
+ entt::sigh_storage_mixin<entt::storage<int>> pool;
|
|
|
+ entt::sigh_storage_mixin<entt::storage<int>> other;
|
|
|
+ entt::registry registry;
|
|
|
+
|
|
|
+ counter on_construct{};
|
|
|
+ counter on_destroy{};
|
|
|
+
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
+ pool.on_construct().connect<&listener>(on_construct);
|
|
|
+ pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ other.bind(entt::forward_as_any(registry));
|
|
|
+ other.on_construct().connect<&listener>(on_construct);
|
|
|
+ other.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ pool.emplace(entt::entity{42}, 41);
|
|
|
+
|
|
|
+ other.emplace(entt::entity{9}, 8);
|
|
|
+ other.emplace(entt::entity{3}, 2);
|
|
|
+ other.erase(entt::entity{9});
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.size(), 1u);
|
|
|
+ ASSERT_EQ(other.size(), 1u);
|
|
|
+
|
|
|
+ pool.swap(other);
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.type(), entt::type_id<int>());
|
|
|
+ ASSERT_EQ(other.type(), entt::type_id<int>());
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.size(), 1u);
|
|
|
+ ASSERT_EQ(other.size(), 1u);
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.at(0u), entt::entity{3});
|
|
|
+ ASSERT_EQ(pool.get(entt::entity{3}), 2);
|
|
|
+
|
|
|
+ ASSERT_EQ(other.at(0u), entt::entity{42});
|
|
|
+ ASSERT_EQ(other.get(entt::entity{42}), 41);
|
|
|
+
|
|
|
+ pool.clear();
|
|
|
+ other.clear();
|
|
|
+
|
|
|
+ ASSERT_EQ(on_construct.value, 3);
|
|
|
+ ASSERT_EQ(on_destroy.value, 3);
|
|
|
+}
|
|
|
+
|
|
|
+TEST(SighStorageMixin, CustomAllocator) {
|
|
|
+ auto test = [](auto pool, auto alloc) {
|
|
|
+ entt::registry registry;
|
|
|
+
|
|
|
+ counter on_construct{};
|
|
|
+ counter on_destroy{};
|
|
|
+
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
+ pool.on_construct().connect<&listener>(on_construct);
|
|
|
+ pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ pool.reserve(1u);
|
|
|
+
|
|
|
+ ASSERT_NE(pool.capacity(), 0u);
|
|
|
+
|
|
|
+ pool.emplace(entt::entity{0});
|
|
|
+ pool.emplace(entt::entity{1});
|
|
|
+
|
|
|
+ decltype(pool) other{std::move(pool), alloc};
|
|
|
+
|
|
|
+ ASSERT_TRUE(pool.empty());
|
|
|
+ ASSERT_FALSE(other.empty());
|
|
|
+ ASSERT_EQ(pool.capacity(), 0u);
|
|
|
+ ASSERT_NE(other.capacity(), 0u);
|
|
|
+ ASSERT_EQ(other.size(), 2u);
|
|
|
+
|
|
|
+ pool = std::move(other);
|
|
|
+
|
|
|
+ ASSERT_FALSE(pool.empty());
|
|
|
+ ASSERT_TRUE(other.empty());
|
|
|
+ ASSERT_EQ(other.capacity(), 0u);
|
|
|
+ ASSERT_NE(pool.capacity(), 0u);
|
|
|
+ ASSERT_EQ(pool.size(), 2u);
|
|
|
+
|
|
|
+ pool.swap(other);
|
|
|
+ pool = std::move(other);
|
|
|
+
|
|
|
+ ASSERT_FALSE(pool.empty());
|
|
|
+ ASSERT_TRUE(other.empty());
|
|
|
+ ASSERT_EQ(other.capacity(), 0u);
|
|
|
+ ASSERT_NE(pool.capacity(), 0u);
|
|
|
+ ASSERT_EQ(pool.size(), 2u);
|
|
|
+
|
|
|
+ pool.clear();
|
|
|
+
|
|
|
+ ASSERT_NE(pool.capacity(), 0u);
|
|
|
+ ASSERT_EQ(pool.size(), 0u);
|
|
|
+
|
|
|
+ ASSERT_EQ(on_construct.value, 2);
|
|
|
+ ASSERT_EQ(on_destroy.value, 2);
|
|
|
+ };
|
|
|
+
|
|
|
+ test::throwing_allocator<entt::entity> allocator{};
|
|
|
+
|
|
|
+ test(entt::sigh_storage_mixin<entt::storage<int, test::throwing_allocator<int>>>{allocator}, allocator);
|
|
|
+ test(entt::sigh_storage_mixin<entt::storage<std::true_type, test::throwing_allocator<std::true_type>>>{allocator}, allocator);
|
|
|
+ test(entt::sigh_storage_mixin<entt::storage<stable_type, test::throwing_allocator<stable_type>>>{allocator}, allocator);
|
|
|
+}
|
|
|
+
|
|
|
+TEST(SighStorageMixin, ThrowingAllocator) {
|
|
|
+ auto test = [](auto pool) {
|
|
|
+ using pool_allocator_type = typename decltype(pool)::allocator_type;
|
|
|
+ using value_type = typename decltype(pool)::value_type;
|
|
|
+
|
|
|
+ typename std::decay_t<decltype(pool)>::base_type &base = pool;
|
|
|
+ entt::registry registry;
|
|
|
+
|
|
|
+ counter on_construct{};
|
|
|
+ counter on_destroy{};
|
|
|
+
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
+ pool.on_construct().connect<&listener>(on_construct);
|
|
|
+ pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ pool_allocator_type::trigger_on_allocate = true;
|
|
|
+
|
|
|
+ ASSERT_THROW(pool.reserve(1u), typename pool_allocator_type::exception_type);
|
|
|
+ ASSERT_EQ(pool.capacity(), 0u);
|
|
|
+
|
|
|
+ pool_allocator_type::trigger_after_allocate = true;
|
|
|
+
|
|
|
+ ASSERT_THROW(pool.reserve(2 * ENTT_PACKED_PAGE), typename pool_allocator_type::exception_type);
|
|
|
+ ASSERT_EQ(pool.capacity(), ENTT_PACKED_PAGE);
|
|
|
+
|
|
|
+ pool.shrink_to_fit();
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.capacity(), 0u);
|
|
|
+
|
|
|
+ test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
|
|
+
|
|
|
+ ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator<entt::entity>::exception_type);
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{0}));
|
|
|
+ ASSERT_TRUE(pool.empty());
|
|
|
+
|
|
|
+ test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
|
|
+
|
|
|
+ ASSERT_THROW(base.emplace(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
|
|
|
+ ASSERT_FALSE(base.contains(entt::entity{0}));
|
|
|
+ ASSERT_TRUE(base.empty());
|
|
|
+
|
|
|
+ pool_allocator_type::trigger_on_allocate = true;
|
|
|
+
|
|
|
+ ASSERT_THROW(pool.emplace(entt::entity{0}, 0), typename pool_allocator_type::exception_type);
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{0}));
|
|
|
+ ASSERT_NO_THROW(pool.compact());
|
|
|
+ ASSERT_TRUE(pool.empty());
|
|
|
+
|
|
|
+ pool.emplace(entt::entity{0}, 0);
|
|
|
+ const entt::entity entities[2u]{entt::entity{1}, entt::entity{ENTT_SPARSE_PAGE}};
|
|
|
+ test::throwing_allocator<entt::entity>::trigger_after_allocate = true;
|
|
|
+
|
|
|
+ ASSERT_THROW(pool.insert(std::begin(entities), std::end(entities), value_type{0}), test::throwing_allocator<entt::entity>::exception_type);
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{1}));
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{ENTT_SPARSE_PAGE}));
|
|
|
+
|
|
|
+ pool.erase(entt::entity{1});
|
|
|
+ const value_type components[2u]{value_type{1}, value_type{ENTT_SPARSE_PAGE}};
|
|
|
+ test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
|
|
|
+ pool.compact();
|
|
|
+
|
|
|
+ ASSERT_THROW(pool.insert(std::begin(entities), std::end(entities), std::begin(components)), test::throwing_allocator<entt::entity>::exception_type);
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{1}));
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{ENTT_SPARSE_PAGE}));
|
|
|
+
|
|
|
+ ASSERT_EQ(on_construct.value, 1);
|
|
|
+ ASSERT_EQ(on_destroy.value, 1);
|
|
|
+ };
|
|
|
+
|
|
|
+ test(entt::sigh_storage_mixin<entt::basic_storage<entt::entity, int, test::throwing_allocator<int>>>{});
|
|
|
+ test(entt::sigh_storage_mixin<entt::basic_storage<entt::entity, stable_type, test::throwing_allocator<stable_type>>>{});
|
|
|
+}
|
|
|
+
|
|
|
+TEST(SighStorageMixin, ThrowingComponent) {
|
|
|
+ entt::sigh_storage_mixin<entt::storage<test::throwing_type>> pool;
|
|
|
+ entt::registry registry;
|
|
|
+
|
|
|
+ counter on_construct{};
|
|
|
+ counter on_destroy{};
|
|
|
+
|
|
|
+ pool.bind(entt::forward_as_any(registry));
|
|
|
+ pool.on_construct().connect<&listener>(on_construct);
|
|
|
+ pool.on_destroy().connect<&listener>(on_destroy);
|
|
|
+
|
|
|
+ test::throwing_type::trigger_on_value = 42;
|
|
|
+
|
|
|
+ // strong exception safety
|
|
|
+ ASSERT_THROW(pool.emplace(entt::entity{0}, test::throwing_type{42}), typename test::throwing_type::exception_type);
|
|
|
+ ASSERT_TRUE(pool.empty());
|
|
|
+
|
|
|
+ const entt::entity entities[2u]{entt::entity{42}, entt::entity{1}};
|
|
|
+ const test::throwing_type components[2u]{42, 1};
|
|
|
+
|
|
|
+ // basic exception safety
|
|
|
+ ASSERT_THROW(pool.insert(std::begin(entities), std::end(entities), test::throwing_type{42}), typename test::throwing_type::exception_type);
|
|
|
+ ASSERT_EQ(pool.size(), 0u);
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{1}));
|
|
|
+
|
|
|
+ // basic exception safety
|
|
|
+ ASSERT_THROW(pool.insert(std::begin(entities), std::end(entities), std::begin(components)), typename test::throwing_type::exception_type);
|
|
|
+ ASSERT_EQ(pool.size(), 0u);
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{1}));
|
|
|
+
|
|
|
+ // basic exception safety
|
|
|
+ ASSERT_THROW(pool.insert(std::rbegin(entities), std::rend(entities), std::rbegin(components)), typename test::throwing_type::exception_type);
|
|
|
+ ASSERT_EQ(pool.size(), 1u);
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{1}));
|
|
|
+ ASSERT_EQ(pool.get(entt::entity{1}), 1);
|
|
|
+
|
|
|
+ pool.clear();
|
|
|
+ pool.emplace(entt::entity{1}, 1);
|
|
|
+ pool.emplace(entt::entity{42}, 42);
|
|
|
+
|
|
|
+ // basic exception safety
|
|
|
+ ASSERT_THROW(pool.erase(entt::entity{1}), typename test::throwing_type::exception_type);
|
|
|
+ ASSERT_EQ(pool.size(), 2u);
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{42}));
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{1}));
|
|
|
+ ASSERT_EQ(pool.at(0u), entt::entity{1});
|
|
|
+ ASSERT_EQ(pool.at(1u), entt::entity{42});
|
|
|
+ ASSERT_EQ(pool.get(entt::entity{42}), 42);
|
|
|
+ // the element may have been moved but it's still there
|
|
|
+ ASSERT_EQ(pool.get(entt::entity{1}), test::throwing_type::moved_from_value);
|
|
|
+
|
|
|
+ test::throwing_type::trigger_on_value = 99;
|
|
|
+ pool.erase(entt::entity{1});
|
|
|
+
|
|
|
+ ASSERT_EQ(pool.size(), 1u);
|
|
|
+ ASSERT_TRUE(pool.contains(entt::entity{42}));
|
|
|
+ ASSERT_FALSE(pool.contains(entt::entity{1}));
|
|
|
+ ASSERT_EQ(pool.at(0u), entt::entity{42});
|
|
|
+ ASSERT_EQ(pool.get(entt::entity{42}), 42);
|
|
|
+
|
|
|
+ ASSERT_EQ(on_construct.value, 2);
|
|
|
+ ASSERT_EQ(on_destroy.value, 3);
|
|
|
+}
|