#include #include #include #include #include #include #include #include TEST(BasicHandle, Assumptions) { static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_assignable_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_copyable_v); static_assert(std::is_trivially_assignable_v); static_assert(std::is_trivially_destructible_v); } TEST(BasicHandle, DeductionGuide) { static_assert(std::is_same_v(), {}}), entt::basic_handle>); static_assert(std::is_same_v(), {}}), entt::basic_handle>); } TEST(BasicHandle, Construction) { entt::registry registry; const auto entity = registry.create(); entt::handle handle{registry, entity}; entt::const_handle chandle{std::as_const(registry), entity}; ASSERT_FALSE(entt::null == handle.entity()); ASSERT_EQ(entity, handle); ASSERT_TRUE(handle); ASSERT_FALSE(entt::null == chandle.entity()); ASSERT_EQ(entity, chandle); ASSERT_TRUE(chandle); ASSERT_EQ(handle, chandle); static_assert(std::is_same_v); static_assert(std::is_same_v); } TEST(BasicHandle, Invalidation) { entt::handle handle; ASSERT_FALSE(handle); ASSERT_EQ(handle.registry(), nullptr); ASSERT_EQ(handle.entity(), entt::entity{entt::null}); entt::registry registry; const auto entity = registry.create(); handle = {registry, entity}; ASSERT_TRUE(handle); ASSERT_NE(handle.registry(), nullptr); ASSERT_NE(handle.entity(), entt::entity{entt::null}); handle = {}; ASSERT_FALSE(handle); ASSERT_EQ(handle.registry(), nullptr); ASSERT_EQ(handle.entity(), entt::entity{entt::null}); } TEST(BasicHandle, Destruction) { using traits_type = entt::entt_traits; entt::registry registry; const auto entity = registry.create(); entt::handle handle{registry, entity}; ASSERT_TRUE(handle); ASSERT_TRUE(handle.valid()); ASSERT_NE(handle.registry(), nullptr); ASSERT_EQ(handle.entity(), entity); handle.destroy(traits_type::to_version(entity)); ASSERT_FALSE(handle); ASSERT_FALSE(handle.valid()); ASSERT_NE(handle.registry(), nullptr); ASSERT_EQ(registry.current(entity), typename entt::registry::version_type{}); ASSERT_EQ(handle.entity(), entt::entity{entt::null}); handle = entt::handle{registry, registry.create()}; ASSERT_TRUE(handle); ASSERT_TRUE(handle.valid()); ASSERT_NE(handle.registry(), nullptr); ASSERT_EQ(handle.entity(), entity); handle.destroy(); ASSERT_FALSE(handle); ASSERT_FALSE(handle.valid()); ASSERT_NE(handle.registry(), nullptr); ASSERT_NE(registry.current(entity), typename entt::registry::version_type{}); ASSERT_EQ(handle.entity(), entt::entity{entt::null}); } TEST(BasicHandle, Comparison) { entt::registry registry; const auto entity = registry.create(); entt::handle handle{registry, entity}; entt::const_handle chandle = handle; ASSERT_NE(handle, entt::handle{}); ASSERT_FALSE(handle == entt::handle{}); ASSERT_TRUE(handle != entt::handle{}); ASSERT_NE(chandle, entt::const_handle{}); ASSERT_FALSE(chandle == entt::const_handle{}); ASSERT_TRUE(chandle != entt::const_handle{}); ASSERT_EQ(handle, chandle); ASSERT_TRUE(handle == chandle); ASSERT_FALSE(handle != chandle); ASSERT_EQ(entt::handle{}, entt::const_handle{}); ASSERT_TRUE(entt::handle{} == entt::const_handle{}); ASSERT_FALSE(entt::handle{} != entt::const_handle{}); handle = {}; chandle = {}; ASSERT_EQ(handle, entt::handle{}); ASSERT_TRUE(handle == entt::handle{}); ASSERT_FALSE(handle != entt::handle{}); ASSERT_EQ(chandle, entt::const_handle{}); ASSERT_TRUE(chandle == entt::const_handle{}); ASSERT_FALSE(chandle != entt::const_handle{}); entt::registry other; const auto entt = other.create(); handle = {registry, entity}; chandle = {other, entt}; ASSERT_NE(handle, chandle); ASSERT_FALSE(chandle == handle); ASSERT_TRUE(chandle != handle); ASSERT_EQ(handle.entity(), chandle.entity()); ASSERT_NE(handle.registry(), chandle.registry()); } TEST(BasicHandle, Component) { entt::registry registry; const auto entity = registry.create(); entt::handle_view handle{registry, entity}; ASSERT_EQ(3, handle.emplace(3)); ASSERT_EQ('c', handle.emplace_or_replace('c')); ASSERT_EQ(.3, handle.emplace_or_replace(.3)); const auto &patched = handle.patch([](auto &comp) { comp = 42; }); ASSERT_EQ(42, patched); ASSERT_EQ('a', handle.replace('a')); ASSERT_TRUE((handle.all_of())); ASSERT_EQ((std::make_tuple(42, 'a', .3)), (handle.get())); handle.erase(); ASSERT_TRUE(registry.storage().empty()); ASSERT_TRUE(registry.storage().empty()); ASSERT_EQ(0u, (handle.remove())); for(auto [id, pool]: handle.storage()) { ASSERT_EQ(id, entt::type_id().hash()); ASSERT_TRUE(pool.contains(handle.entity())); } ASSERT_TRUE((handle.any_of())); ASSERT_FALSE((handle.all_of())); ASSERT_FALSE(handle.orphan()); ASSERT_EQ(1u, (handle.remove())); ASSERT_TRUE(registry.storage().empty()); ASSERT_TRUE(handle.orphan()); ASSERT_EQ(42, handle.get_or_emplace(42)); ASSERT_EQ(42, handle.get_or_emplace(1)); ASSERT_EQ(42, handle.get()); ASSERT_EQ(42, *handle.try_get()); ASSERT_EQ(nullptr, handle.try_get()); ASSERT_EQ(nullptr, std::get<1>(handle.try_get())); } TEST(BasicHandle, FromEntity) { entt::registry registry; const auto entity = registry.create(); registry.emplace(entity, 42); registry.emplace(entity, 'c'); entt::handle handle{registry, entity}; ASSERT_TRUE(handle); ASSERT_EQ(entity, handle.entity()); ASSERT_TRUE((handle.all_of())); ASSERT_EQ(handle.get(), 42); ASSERT_EQ(handle.get(), 'c'); } TEST(BasicHandle, Lifetime) { entt::registry registry; const auto entity = registry.create(); auto *handle = new entt::handle{registry, entity}; handle->emplace(); ASSERT_FALSE(registry.storage().empty()); ASSERT_FALSE(registry.empty()); registry.each([handle](const auto e) { ASSERT_EQ(handle->entity(), e); }); delete handle; ASSERT_FALSE(registry.storage().empty()); ASSERT_FALSE(registry.empty()); } TEST(BasicHandle, ImplicitConversions) { entt::registry registry; const entt::handle handle{registry, registry.create()}; const entt::const_handle chandle = handle; const entt::handle_view vhandle = handle; const entt::const_handle_view cvhandle = vhandle; handle.emplace(42); ASSERT_EQ(handle.get(), chandle.get()); ASSERT_EQ(chandle.get(), vhandle.get()); ASSERT_EQ(vhandle.get(), cvhandle.get()); ASSERT_EQ(cvhandle.get(), 42); } TEST(BasicHandle, Storage) { entt::registry registry; const auto entity = registry.create(); entt::handle handle{registry, entity}; entt::const_handle chandle{std::as_const(registry), entity}; static_assert(std::is_same_v>); static_assert(std::is_same_v>); ASSERT_EQ(handle.storage().begin(), handle.storage().end()); ASSERT_EQ(chandle.storage().begin(), chandle.storage().end()); registry.storage(); registry.emplace(entity); ASSERT_NE(handle.storage().begin(), handle.storage().end()); ASSERT_NE(chandle.storage().begin(), chandle.storage().end()); ASSERT_EQ(++handle.storage().begin(), handle.storage().end()); ASSERT_EQ(++chandle.storage().begin(), chandle.storage().end()); ASSERT_EQ(handle.storage().begin()->second.type(), entt::type_id()); ASSERT_EQ(chandle.storage().begin()->second.type(), entt::type_id()); } TEST(BasicHandle, HandleStorageIterator) { entt::registry registry; const auto entity = registry.create(); registry.emplace(entity); registry.emplace(entity); // required to test the find-first initialization step registry.storage().erase(entity); auto test = [](auto iterable) { auto end{iterable.begin()}; decltype(end) begin{}; begin = iterable.end(); std::swap(begin, end); ASSERT_EQ(begin, iterable.cbegin()); ASSERT_EQ(end, iterable.cend()); ASSERT_NE(begin, end); ASSERT_EQ(begin++, iterable.begin()); ASSERT_EQ(++begin, iterable.end()); }; const auto handle = entt::handle{registry, entity}; const auto chandle = entt::const_handle{std::as_const(registry), entity}; ASSERT_FALSE(registry.valid(entity)); ASSERT_FALSE(handle); ASSERT_FALSE(chandle); test(handle.storage()); test(chandle.storage()); }