Browse Source

test: separate death tests as suggested in the gtest doc

Michele Caini 4 years ago
parent
commit
0795f9a9f2

+ 7 - 2
test/entt/container/dense_map.cpp

@@ -885,8 +885,6 @@ TEST(DenseMap, Indexing) {
     const auto key = 1;
 
     ASSERT_FALSE(map.contains(key));
-    ASSERT_DEATH([[maybe_unused]] auto value = std::as_const(map).at(key), "");
-    ASSERT_DEATH([[maybe_unused]] auto value = map.at(key), "");
 
     map[key] = 99;
 
@@ -896,6 +894,13 @@ TEST(DenseMap, Indexing) {
     ASSERT_EQ(map.at(key), 99);
 }
 
+TEST(DenseMapDeathTest, Indexing) {
+    entt::dense_map<int, int> map;
+
+    ASSERT_DEATH([[maybe_unused]] auto value = std::as_const(map).at(0), "");
+    ASSERT_DEATH([[maybe_unused]] auto value = map.at(42), "");
+}
+
 TEST(DenseMap, LocalIterator) {
     using iterator = typename entt::dense_map<std::size_t, std::size_t, entt::identity>::local_iterator;
 

+ 18 - 4
test/entt/core/any.cpp

@@ -67,6 +67,8 @@ struct Any: ::testing::Test {
     }
 };
 
+using AnyDeathTest = Any;
+
 TEST_F(Any, SBO) {
     entt::any any{'c'};
 
@@ -1174,9 +1176,7 @@ TEST_F(Any, AnyCast) {
     ASSERT_EQ(*entt::any_cast<int>(&any), 42);
     ASSERT_EQ(*entt::any_cast<int>(&cany), 42);
     ASSERT_EQ(entt::any_cast<int &>(any), 42);
-    ASSERT_DEATH(entt::any_cast<double &>(any), "");
     ASSERT_EQ(entt::any_cast<const int &>(cany), 42);
-    ASSERT_DEATH(entt::any_cast<const double &>(cany), "");
 
     not_copyable instance{};
     instance.payload = 42.;
@@ -1184,12 +1184,26 @@ TEST_F(Any, AnyCast) {
     entt::any cref{entt::forward_as_any(std::as_const(instance).payload)};
 
     ASSERT_EQ(entt::any_cast<not_copyable>(std::move(ref)).payload, 42.);
-    ASSERT_DEATH(entt::any_cast<not_copyable>(std::as_const(ref).as_ref()), "");
     ASSERT_EQ(entt::any_cast<double>(std::move(cref)), 42.);
-    ASSERT_DEATH(entt::any_cast<double>(entt::any{42}), "");
     ASSERT_EQ(entt::any_cast<int>(entt::any{42}), 42);
 }
 
+TEST_F(AnyDeathTest, AnyCast) {
+    entt::any any{42};
+    const auto &cany = any;
+
+    ASSERT_DEATH(entt::any_cast<double &>(any), "");
+    ASSERT_DEATH(entt::any_cast<const double &>(cany), "");
+
+    not_copyable instance{};
+    instance.payload = 42.;
+    entt::any ref{entt::forward_as_any(instance)};
+    entt::any cref{entt::forward_as_any(std::as_const(instance).payload)};
+
+    ASSERT_DEATH(entt::any_cast<not_copyable>(std::as_const(ref).as_ref()), "");
+    ASSERT_DEATH(entt::any_cast<double>(entt::any{42}), "");
+}
+
 TEST_F(Any, MakeAny) {
     int value = 42;
     auto any = entt::make_any<int>(value);

+ 3 - 0
test/entt/core/memory.cpp

@@ -60,6 +60,9 @@ TEST(Memory, NextPowerOfTwo) {
     ASSERT_EQ(entt::next_power_of_two(33u), 64u);
     ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16)), std::pow(2, 16));
     ASSERT_EQ(entt::next_power_of_two(std::pow(2, 16) + 1u), std::pow(2, 17));
+}
+
+TEST(MemoryDeathTest, NextPowerOfTwo) {
     ASSERT_DEATH(static_cast<void>(entt::next_power_of_two((std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)) + 1)), "");
 }
 

+ 0 - 2
test/entt/entity/handle.cpp

@@ -179,8 +179,6 @@ TEST(BasicHandle, Component) {
     ASSERT_FALSE(handle.orphan());
 
     ASSERT_EQ(1u, (handle.remove<int>()));
-    ASSERT_DEATH(handle.erase<int>(), "");
-
     ASSERT_TRUE(registry.storage<int>().empty());
     ASSERT_TRUE(handle.orphan());
 

+ 39 - 16
test/entt/entity/registry.cpp

@@ -237,9 +237,7 @@ TEST(Registry, Functionalities) {
 
     ASSERT_EQ(traits_type::to_version(e2), 0u);
     ASSERT_EQ(registry.current(e2), 0u);
-    ASSERT_DEATH(registry.release(e2), "");
     ASSERT_NO_FATAL_FAILURE(registry.destroy(e2));
-    ASSERT_DEATH(registry.destroy(e2), "");
     ASSERT_EQ(traits_type::to_version(e2), 0u);
     ASSERT_EQ(registry.current(e2), 1u);
 
@@ -528,12 +526,20 @@ TEST(Registry, DestroyVersion) {
     registry.destroy(e0);
     registry.destroy(e1, 3);
 
-    ASSERT_DEATH(registry.destroy(e0), "");
-    ASSERT_DEATH(registry.destroy(e1, 3), "");
     ASSERT_EQ(registry.current(e0), 1u);
     ASSERT_EQ(registry.current(e1), 3u);
 }
 
+TEST(RegistryDeathTest, DestroyVersion) {
+    entt::registry registry;
+    const auto entity = registry.create();
+
+    registry.destroy(entity);
+
+    ASSERT_DEATH(registry.destroy(entity), "");
+    ASSERT_DEATH(registry.destroy(entity, 3), "");
+}
+
 TEST(Registry, RangeDestroy) {
     entt::registry registry;
     const auto iview = registry.view<int>();
@@ -646,12 +652,20 @@ TEST(Registry, ReleaseVersion) {
     registry.release(entities[0u]);
     registry.release(entities[1u], 3);
 
-    ASSERT_DEATH(registry.release(entities[0u]), "");
-    ASSERT_DEATH(registry.release(entities[1u], 3), "");
     ASSERT_EQ(registry.current(entities[0u]), 1u);
     ASSERT_EQ(registry.current(entities[1u]), 3u);
 }
 
+TEST(RegistryDeathTest, ReleaseVersion) {
+    entt::registry registry;
+    entt::entity entity = registry.create();
+
+    registry.release(entity);
+
+    ASSERT_DEATH(registry.release(entity), "");
+    ASSERT_DEATH(registry.release(entity, 3), "");
+}
+
 TEST(Registry, RangeRelease) {
     entt::registry registry;
     entt::entity entities[3u];
@@ -1422,9 +1436,6 @@ TEST(Registry, Erase) {
 
     registry.erase<int>(iview.begin(), iview.end());
 
-    ASSERT_DEATH(registry.erase<int>(entities[0u]), "");
-    ASSERT_DEATH(registry.erase<int>(entities[1u]), "");
-
     ASSERT_FALSE(registry.any_of<int>(entities[2u]));
     ASSERT_NO_FATAL_FAILURE(registry.erase<int>(iview.rbegin(), iview.rend()));
 
@@ -1440,7 +1451,6 @@ TEST(Registry, Erase) {
 
     registry.erase<int, char>(std::begin(entities), std::end(entities));
 
-    ASSERT_DEATH((registry.erase<int, char>(std::begin(entities), std::end(entities))), "");
     ASSERT_EQ(registry.storage<int>().size(), 0u);
     ASSERT_EQ(registry.storage<char>().size(), 0u);
 
@@ -1449,6 +1459,15 @@ TEST(Registry, Erase) {
     ASSERT_TRUE(registry.orphan(entities[2u]));
 }
 
+TEST(RegistryDeathTest, Erase) {
+    entt::registry registry;
+    const entt::entity entities[1u]{registry.create()};
+
+    ASSERT_FALSE((registry.any_of<int>(entities[0u])));
+    ASSERT_DEATH((registry.erase<int>(std::begin(entities), std::end(entities))), "");
+    ASSERT_DEATH(registry.erase<int>(entities[0u]), "");
+}
+
 TEST(Registry, StableErase) {
     entt::registry registry;
     const auto iview = registry.view<int>();
@@ -1484,9 +1503,6 @@ TEST(Registry, StableErase) {
 
     registry.erase<int>(iview.begin(), iview.end());
 
-    ASSERT_DEATH(registry.erase<int>(entities[0u]), "");
-    ASSERT_DEATH(registry.erase<int>(entities[1u]), "");
-
     ASSERT_FALSE(registry.any_of<int>(entities[2u]));
 
     ASSERT_EQ(registry.storage<int>().size(), 0u);
@@ -1875,9 +1891,6 @@ TEST(Registry, RuntimePools) {
     static_assert(std::is_same_v<decltype(registry.storage("other"_hs)->second), typename entt::storage_traits<entt::entity, empty_type>::storage_type::base_type &>);
     static_assert(std::is_same_v<decltype(std::as_const(registry).storage("other"_hs)->second), const typename entt::storage_traits<entt::entity, empty_type>::storage_type::base_type &>);
 
-    ASSERT_DEATH(registry.storage<int>("other"_hs), "");
-    ASSERT_DEATH(std::as_const(registry).storage<int>("other"_hs), "");
-
     ASSERT_NE(registry.storage("other"_hs), registry.storage().end());
     ASSERT_EQ(std::as_const(registry).storage("rehto"_hs), registry.storage().end());
 
@@ -1907,6 +1920,16 @@ TEST(Registry, RuntimePools) {
     ASSERT_FALSE(registry.any_of<empty_type>(entity));
 }
 
+TEST(RegistryDeathTest, RuntimePools) {
+    using namespace entt::literals;
+
+    entt::registry registry;
+    auto &storage = registry.storage<empty_type>("other"_hs);
+
+    ASSERT_DEATH(registry.storage<int>("other"_hs), "");
+    ASSERT_DEATH(std::as_const(registry).storage<int>("other"_hs), "");
+}
+
 TEST(Registry, StorageProxy) {
     using namespace entt::literals;
 

+ 48 - 26
test/entt/entity/sparse_set.cpp

@@ -48,8 +48,6 @@ TEST(SparseSet, Functionalities) {
     ASSERT_EQ(set.at(0u), entt::entity{42});
     ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
     ASSERT_EQ(set[0u], entt::entity{42});
-
-    ASSERT_DEATH(set.get(entt::entity{0}), "");
     ASSERT_EQ(set.get(entt::entity{42}), nullptr);
 
     set.erase(entt::entity{42});
@@ -164,6 +162,13 @@ TEST(SparseSet, Index) {
     set.erase(traits_type::construct(0, 0));
 
     ASSERT_EQ(set.index(traits_type::construct(3, 3)), 0u);
+}
+
+TEST(SparseSetDeathTest, Index) {
+    using traits_type = entt::entt_traits<entt::entity>;
+
+    entt::sparse_set set{};
+
     ASSERT_DEATH(static_cast<void>(set.index(traits_type::construct(3, 0))), "");
     ASSERT_DEATH(static_cast<void>(set.index(entt::null)), "");
 }
@@ -270,9 +275,6 @@ TEST(SparseSet, Emplace) {
     ASSERT_NE(set.emplace(entities[1u]), set.end());
     ASSERT_NE(set.emplace(entities[0u]), set.end());
 
-    ASSERT_DEATH(set.emplace(traits_type::combine(3, 1)), "");
-    ASSERT_DEATH(set.emplace(entities[1u]), "");
-
     ASSERT_EQ(set.at(0u), entities[1u]);
     ASSERT_EQ(set.at(1u), entities[0u]);
     ASSERT_EQ(set.index(entities[0u]), 1u);
@@ -289,6 +291,13 @@ TEST(SparseSet, Emplace) {
     ASSERT_EQ(set.index(entities[1u]), 0u);
 }
 
+TEST(SparseSetDeathTest, Emplace) {
+    entt::sparse_set set{entt::deletion_policy::in_place};
+    set.emplace(entt::entity{42});
+
+    ASSERT_DEATH(set.emplace(entt::entity{42}), "");
+}
+
 TEST(SparseSet, EmplaceOutOfBounds) {
     entt::sparse_set set{entt::deletion_policy::in_place};
     entt::entity entities[2u]{entt::entity{0}, entt::entity{ENTT_SPARSE_PAGE}};
@@ -353,11 +362,6 @@ TEST(SparseSet, Erase) {
     ASSERT_EQ(set.policy(), entt::deletion_policy::swap_and_pop);
     ASSERT_TRUE(set.empty());
 
-    ASSERT_DEATH(set.erase(std::begin(entities), std::end(entities)), "");
-    ASSERT_DEATH(set.erase(entities[1u]), "");
-
-    ASSERT_TRUE(set.empty());
-
     set.insert(std::begin(entities), std::end(entities));
     set.erase(set.begin(), set.end());
 
@@ -377,7 +381,6 @@ TEST(SparseSet, Erase) {
 
     set.erase(entities[2u]);
 
-    ASSERT_DEATH(set.erase(entities[2u]), "");
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
 
@@ -388,8 +391,15 @@ TEST(SparseSet, Erase) {
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entities[2u]));
     ASSERT_EQ(*set.begin(), entities[2u]);
+}
 
-    ASSERT_DEATH(set.erase(traits_type::construct(9, 0)), "");
+TEST(SparseSetDeathTest, Erase) {
+    using traits_type = entt::entt_traits<entt::entity>;
+
+    entt::sparse_set set;
+    entt::entity entities[2u]{entt::entity{42}, traits_type::construct(9, 3)};
+
+    ASSERT_DEATH(set.erase(std::begin(entities), std::end(entities)), "");
     ASSERT_DEATH(set.erase(entt::null), "");
 }
 
@@ -403,12 +413,6 @@ TEST(SparseSet, StableErase) {
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
 
-    ASSERT_DEATH(set.erase(std::begin(entities), std::end(entities)), "");
-    ASSERT_DEATH(set.erase(entities[1u]), "");
-
-    ASSERT_TRUE(set.empty());
-    ASSERT_EQ(set.size(), 0u);
-
     set.emplace(entities[0u]);
     set.emplace(entities[1u]);
     set.emplace(entities[2u]);
@@ -441,7 +445,6 @@ TEST(SparseSet, StableErase) {
 
     set.erase(entities[2u]);
 
-    ASSERT_DEATH(set.erase(entities[2u]), "");
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 3u);
     ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
@@ -482,7 +485,6 @@ TEST(SparseSet, StableErase) {
 
     set.erase(entities[2u]);
 
-    ASSERT_DEATH(set.erase(entities[2u]), "");
     ASSERT_NE(set.current(entities[0u]), traits_type::to_version(entt::tombstone));
     ASSERT_NE(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
     ASSERT_EQ(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
@@ -490,7 +492,6 @@ TEST(SparseSet, StableErase) {
     set.erase(entities[0u]);
     set.erase(entities[1u]);
 
-    ASSERT_DEATH(set.erase(entities, entities + 2u), "");
     ASSERT_EQ(set.size(), 3u);
     ASSERT_EQ(set.current(entities[0u]), traits_type::to_version(entt::tombstone));
     ASSERT_EQ(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
@@ -514,8 +515,15 @@ TEST(SparseSet, StableErase) {
     ASSERT_NE(set.current(entities[0u]), traits_type::to_version(entt::tombstone));
     ASSERT_NE(set.current(entities[1u]), traits_type::to_version(entt::tombstone));
     ASSERT_NE(set.current(entities[2u]), traits_type::to_version(entt::tombstone));
+}
+
+TEST(SparseSetDeathTest, StableErase) {
+    using traits_type = entt::entt_traits<entt::entity>;
+
+    entt::sparse_set set{entt::deletion_policy::in_place};
+    entt::entity entities[2u]{entt::entity{42}, traits_type::construct(9, 3)};
 
-    ASSERT_DEATH(set.erase(traits_type::construct(9, 0)), "");
+    ASSERT_DEATH(set.erase(std::begin(entities), std::end(entities)), "");
     ASSERT_DEATH(set.erase(entt::null), "");
 }
 
@@ -759,9 +767,6 @@ TEST(SparseSet, SwapEntity) {
     ASSERT_EQ(set.index(traits_type::construct(3, 5)), 0u);
     ASSERT_EQ(set.index(traits_type::construct(42, 99)), 1u);
 
-    ASSERT_DEATH(set.swap_elements(traits_type::construct(3, 5), traits_type::construct(42, 98)), "");
-    ASSERT_DEATH(set.swap_elements(traits_type::construct(3, 6), traits_type::construct(42, 99)), "");
-
     set.swap_elements(traits_type::construct(3, 5), traits_type::construct(42, 99));
 
     ASSERT_EQ(set.index(traits_type::construct(3, 5)), 1u);
@@ -773,6 +778,13 @@ TEST(SparseSet, SwapEntity) {
     ASSERT_EQ(set.index(traits_type::construct(42, 99)), 1u);
 }
 
+TEST(SparseSetDeathTest, SwapEntity) {
+    entt::sparse_set set;
+
+    ASSERT_TRUE(set.empty());
+    ASSERT_DEATH(set.swap_elements(entt::entity{0}, entt::entity{1}), "");
+}
+
 TEST(SparseSet, Clear) {
     auto test = [](auto set) {
         set.emplace(entt::entity{3});
@@ -1010,7 +1022,6 @@ TEST(SparseSet, SortRange) {
     set.insert(std::begin(entities), std::end(entities));
     set.erase(entities[0u]);
 
-    ASSERT_DEATH(set.sort_n(0u, std::less{});, "");
     ASSERT_EQ(set.size(), 5u);
 
     set.sort(std::less{});
@@ -1047,6 +1058,17 @@ TEST(SparseSet, SortRange) {
     ASSERT_EQ(begin, end);
 }
 
+TEST(SparseSetDeathTest, SortRange) {
+    entt::sparse_set set{entt::deletion_policy::in_place};
+    entt::entity entity{42};
+
+    set.emplace(entity);
+    set.erase(entity);
+
+    ASSERT_DEATH(set.sort_n(0u, std::less{});, "");
+    ASSERT_DEATH(set.sort_n(3u, std::less{});, "");
+}
+
 TEST(SparseSet, RespectDisjoint) {
     entt::sparse_set lhs;
     entt::sparse_set rhs;

+ 0 - 18
test/entt/entity/storage.cpp

@@ -253,9 +253,7 @@ TEST(Storage, EmptyType) {
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = pool.get_allocator());
     ASSERT_EQ(pool.type(), entt::type_id<empty_stable_type>());
-
     ASSERT_TRUE(pool.contains(entt::entity{99}));
-    ASSERT_DEATH(pool.get(entt::entity{}), "");
 
     entt::storage<empty_stable_type> other{std::move(pool)};
 
@@ -326,7 +324,6 @@ TEST(Storage, Erase) {
     pool.emplace(entities[2u]);
     pool.erase(std::begin(entities), std::end(entities));
 
-    ASSERT_DEATH(pool.erase(std::begin(entities), std::end(entities)), "");
     ASSERT_TRUE(pool.empty());
 
     pool.emplace(entities[0u], 0);
@@ -339,7 +336,6 @@ TEST(Storage, Erase) {
 
     pool.erase(entities[2u]);
 
-    ASSERT_DEATH(pool.erase(entities[2u]), "");
     ASSERT_TRUE(pool.empty());
 
     pool.emplace(entities[0u], 0);
@@ -356,22 +352,15 @@ TEST(Storage, StableErase) {
     entt::storage<stable_type> pool;
     entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
 
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entt::tombstone), "");
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entt::null), "");
-
     pool.emplace(entities[0u], stable_type{0});
     pool.emplace(entities[1u], stable_type{1});
     pool.emplace(entities[2u], stable_type{2});
 
     pool.erase(std::begin(entities), std::end(entities));
 
-    ASSERT_DEATH(pool.erase(std::begin(entities), std::end(entities)), "");
     ASSERT_FALSE(pool.empty());
     ASSERT_EQ(pool.size(), 3u);
     ASSERT_TRUE(pool.at(2u) == entt::tombstone);
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entt::tombstone), "");
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entt::null), "");
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entities[1u]), "");
 
     pool.emplace(entities[2u], stable_type{2});
     pool.emplace(entities[0u], stable_type{0});
@@ -395,7 +384,6 @@ TEST(Storage, StableErase) {
 
     pool.erase(entities[2u]);
 
-    ASSERT_DEATH(pool.erase(entities[2u]), "");
     ASSERT_FALSE(pool.empty());
     ASSERT_EQ(pool.size(), 3u);
     ASSERT_FALSE(pool.contains(entities[0u]));
@@ -429,12 +417,9 @@ TEST(Storage, StableErase) {
     pool.emplace(entities[2u], stable_type{1});
     pool.erase(entities[2u]);
 
-    ASSERT_DEATH(pool.erase(entities[2u]), "");
-
     pool.erase(entities[0u]);
     pool.erase(entities[1u]);
 
-    ASSERT_DEATH(pool.erase(entities, entities + 2u), "");
     ASSERT_EQ(pool.size(), 3u);
     ASSERT_TRUE(pool.at(2u) == entt::tombstone);
 
@@ -504,9 +489,6 @@ TEST(Storage, StableRemove) {
     ASSERT_FALSE(pool.empty());
     ASSERT_EQ(pool.size(), 3u);
     ASSERT_TRUE(pool.at(2u) == entt::tombstone);
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entt::tombstone), "");
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entt::null), "");
-    ASSERT_DEATH([[maybe_unused]] auto &&value = pool.get(entities[1u]), "");
 
     pool.emplace(entities[2u], stable_type{2});
     pool.emplace(entities[0u], stable_type{0});

+ 26 - 6
test/entt/meta/meta_any.cpp

@@ -102,6 +102,8 @@ struct MetaAny: ::testing::Test {
     }
 };
 
+using MetaAnyDeathTest = MetaAny;
+
 TEST_F(MetaAny, SBO) {
     entt::meta_any any{'c'};
 
@@ -204,7 +206,6 @@ TEST_F(MetaAny, SBOAsConstRefConstruction) {
     ASSERT_EQ(any.type(), entt::resolve<int>());
 
     ASSERT_FALSE(any.try_cast<std::size_t>());
-    ASSERT_DEATH(any.cast<int &>() = 3, "");
     ASSERT_EQ(any.cast<const int &>(), 3);
     ASSERT_EQ(any.cast<int>(), 3);
     ASSERT_EQ(any.data(), nullptr);
@@ -230,6 +231,14 @@ TEST_F(MetaAny, SBOAsConstRefConstruction) {
     ASSERT_EQ(other.data(), any.data());
 }
 
+TEST_F(MetaAnyDeathTest, SBOAsConstRefConstruction) {
+    const int value = 3;
+    auto any = entt::forward_as_meta(value);
+
+    ASSERT_TRUE(any);
+    ASSERT_DEATH(any.cast<int &>() = 3, "");
+}
+
 TEST_F(MetaAny, SBOCopyConstruction) {
     entt::meta_any any{42};
     entt::meta_any other{any};
@@ -463,7 +472,6 @@ TEST_F(MetaAny, NoSBOAsConstRefConstruction) {
     ASSERT_EQ(any.type(), entt::resolve<fat_t>());
 
     ASSERT_FALSE(any.try_cast<std::size_t>());
-    ASSERT_DEATH(any.cast<fat_t &>() = {}, "");
     ASSERT_EQ(any.cast<const fat_t &>(), instance);
     ASSERT_EQ(any.cast<fat_t>(), instance);
     ASSERT_EQ(any.data(), nullptr);
@@ -488,6 +496,14 @@ TEST_F(MetaAny, NoSBOAsConstRefConstruction) {
     ASSERT_EQ(other.data(), any.data());
 }
 
+TEST_F(MetaAnyDeathTest, NoSBOAsConstRefConstruction) {
+    const fat_t instance{.1, .2, .3, .4};
+    auto any = entt::forward_as_meta(instance);
+
+    ASSERT_TRUE(any);
+    ASSERT_DEATH(any.cast<fat_t &>() = {}, "");
+}
+
 TEST_F(MetaAny, NoSBOCopyConstruction) {
     fat_t instance{.1, .2, .3, .4};
     entt::meta_any any{instance};
@@ -962,7 +978,6 @@ TEST_F(MetaAny, AsRef) {
     ASSERT_EQ(any.cast<const int &>(), 42);
     ASSERT_EQ(ref.cast<int &>(), 42);
     ASSERT_EQ(ref.cast<const int &>(), 42);
-    ASSERT_DEATH(cref.cast<int &>() = 3, "");
     ASSERT_EQ(cref.cast<const int &>(), 42);
 
     any.cast<int &>() = 3;
@@ -984,9 +999,6 @@ TEST_F(MetaAny, AsRef) {
     ASSERT_EQ(ref.try_cast<const int>(), any.data());
     ASSERT_EQ(cref.try_cast<const int>(), any.data());
 
-    ASSERT_DEATH(ref.cast<int &>() = 3, "");
-    ASSERT_DEATH(cref.cast<int &>() = 3, "");
-
     ASSERT_EQ(ref.cast<const int &>(), 3);
     ASSERT_EQ(cref.cast<const int &>(), 3);
 
@@ -1011,6 +1023,14 @@ TEST_F(MetaAny, AsRef) {
     ASSERT_FALSE(cref);
 }
 
+TEST_F(MetaAnyDeathTest, AsRef) {
+    entt::meta_any any{42};
+    auto cref = std::as_const(any).as_ref();
+
+    ASSERT_TRUE(any);
+    ASSERT_DEATH(cref.cast<int &>() = 3, "");
+}
+
 TEST_F(MetaAny, Comparable) {
     entt::meta_any any{'c'};
 

+ 50 - 6
test/entt/meta/meta_container.cpp

@@ -23,6 +23,8 @@ struct MetaContainer: ::testing::Test {
     }
 };
 
+using MetaContainerDeathTest = MetaContainer;
+
 TEST_F(MetaContainer, InvalidContainer) {
     ASSERT_FALSE(entt::meta_any{42}.as_sequence_container());
     ASSERT_FALSE(entt::meta_any{42}.as_associative_container());
@@ -386,8 +388,6 @@ TEST_F(MetaContainer, ConstSequenceContainer) {
 
     ASSERT_EQ(view.size(), 1u);
     ASSERT_NE(view.begin(), view.end());
-
-    ASSERT_DEATH(view[0].cast<int &>() = 2, "");
     ASSERT_EQ(view[0].cast<const int &>(), 42);
 
     auto it = view.begin();
@@ -408,6 +408,15 @@ TEST_F(MetaContainer, ConstSequenceContainer) {
     ASSERT_EQ(view.size(), 1u);
 }
 
+TEST_F(MetaContainerDeathTest, ConstSequenceContainer) {
+    std::vector<int> vec{};
+    auto any = entt::forward_as_meta(std::as_const(vec));
+    auto view = any.as_sequence_container();
+
+    ASSERT_TRUE(view);
+    ASSERT_DEATH(view[0].cast<int &>() = 2, "");
+}
+
 TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
     std::map<int, char> map{};
     auto any = entt::forward_as_meta(std::as_const(map));
@@ -426,8 +435,6 @@ TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
 
     ASSERT_EQ(view.size(), 1u);
     ASSERT_NE(view.begin(), view.end());
-
-    ASSERT_DEATH(view.find(2)->second.cast<char &>() = 'a', "");
     ASSERT_EQ(view.find(2)->second.cast<const char &>(), 'c');
 
     ASSERT_FALSE(view.insert(0, 'a'));
@@ -443,6 +450,15 @@ TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
     ASSERT_EQ(view.size(), 1u);
 }
 
+TEST_F(MetaContainerDeathTest, ConstKeyValueAssociativeContainer) {
+    std::map<int, char> map{};
+    auto any = entt::forward_as_meta(std::as_const(map));
+    auto view = any.as_associative_container();
+
+    ASSERT_TRUE(view);
+    ASSERT_DEATH(view.find(2)->second.cast<char &>() = 'a', "");
+}
+
 TEST_F(MetaContainer, ConstKeyOnlyAssociativeContainer) {
     std::set<int> set{};
     auto any = entt::forward_as_meta(std::as_const(set));
@@ -486,7 +502,6 @@ TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
 
         ASSERT_TRUE(view);
         ASSERT_EQ(view.value_type(), entt::resolve<int>());
-        ASSERT_DEATH(view[0].cast<int &>() = 2, "");
         ASSERT_EQ(view[0].cast<const int &>(), 42);
     };
 
@@ -497,13 +512,27 @@ TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
     test(entt::forward_as_meta(std::as_const(vec)));
 }
 
+TEST_F(MetaContainerDeathTest, SequenceContainerConstMetaAny) {
+    auto test = [](const entt::meta_any any) {
+        auto view = any.as_sequence_container();
+
+        ASSERT_TRUE(view);
+        ASSERT_DEATH(view[0].cast<int &>() = 2, "");
+    };
+
+    std::vector<int> vec{42};
+
+    test(vec);
+    test(entt::forward_as_meta(vec));
+    test(entt::forward_as_meta(std::as_const(vec)));
+}
+
 TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
     auto test = [](const entt::meta_any any) {
         auto view = any.as_associative_container();
 
         ASSERT_TRUE(view);
         ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
-        ASSERT_DEATH(view.find(2)->second.cast<char &>() = 'a', "");
         ASSERT_EQ(view.find(2)->second.cast<const char &>(), 'c');
     };
 
@@ -514,6 +543,21 @@ TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
     test(entt::forward_as_meta(std::as_const(map)));
 }
 
+TEST_F(MetaContainerDeathTest, KeyValueAssociativeContainerConstMetaAny) {
+    auto test = [](const entt::meta_any any) {
+        auto view = any.as_associative_container();
+
+        ASSERT_TRUE(view);
+        ASSERT_DEATH(view.find(2)->second.cast<char &>() = 'a', "");
+    };
+
+    std::map<int, char> map{{2, 'c'}};
+
+    test(map);
+    test(entt::forward_as_meta(map));
+    test(entt::forward_as_meta(std::as_const(map)));
+}
+
 TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
     auto test = [](const entt::meta_any any) {
         auto view = any.as_associative_container();

+ 15 - 1
test/entt/meta/meta_data.cpp

@@ -153,6 +153,8 @@ struct MetaData: ::testing::Test {
     }
 };
 
+using MetaDataDeathTest = MetaData;
+
 TEST_F(MetaData, Functionalities) {
     using namespace entt::literals;
 
@@ -607,12 +609,20 @@ TEST_F(MetaData, AsConstRef) {
     ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
     ASSERT_EQ(data.arg(0u), entt::resolve<int>());
-    ASSERT_DEATH(data.get(instance).cast<int &>() = 3, "");
     ASSERT_EQ(data.get(instance).cast<const int &>(), 0);
     ASSERT_EQ(data.get(instance).cast<int>(), 0);
     ASSERT_EQ(instance.i, 0);
 }
 
+TEST_F(MetaDataDeathTest, AsConstRef) {
+    using namespace entt::literals;
+
+    clazz_t instance{};
+    auto data = entt::resolve<clazz_t>().data("ci"_hs);
+
+    ASSERT_DEATH(data.get(instance).cast<int &>() = 3, "");
+}
+
 TEST_F(MetaData, SetGetBaseData) {
     using namespace entt::literals;
 
@@ -670,6 +680,10 @@ TEST_F(MetaData, NameCollision) {
     ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::j>("cj"_hs));
     ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs));
     ASSERT_TRUE(entt::resolve<clazz_t>().data("cj"_hs));
+}
+
+TEST_F(MetaDataDeathTest, NameCollision) {
+    using namespace entt::literals;
 
     ASSERT_DEATH(entt::meta<clazz_t>().data<&clazz_t::j>("i"_hs), "");
 }

+ 11 - 1
test/entt/meta/meta_func.cpp

@@ -133,6 +133,8 @@ struct MetaFunc: ::testing::Test {
     }
 };
 
+using MetaFuncDeathTest = MetaFunc;
+
 TEST_F(MetaFunc, Functionalities) {
     using namespace entt::literals;
 
@@ -479,12 +481,20 @@ TEST_F(MetaFunc, AsConstRef) {
     func_t instance{};
     auto func = entt::resolve<func_t>().func("ca"_hs);
 
-    ASSERT_DEATH((func.invoke(instance).cast<int &>() = 3), "");
     ASSERT_EQ(func.ret(), entt::resolve<int>());
     ASSERT_EQ(func.invoke(instance).cast<const int &>(), 3);
     ASSERT_EQ(func.invoke(instance).cast<int>(), 3);
 }
 
+TEST_F(MetaFuncDeathTest, AsConstRef) {
+    using namespace entt::literals;
+
+    func_t instance{};
+    auto func = entt::resolve<func_t>().func("ca"_hs);
+
+    ASSERT_DEATH((func.invoke(instance).cast<int &>() = 3), "");
+}
+
 TEST_F(MetaFunc, InvokeBaseFunction) {
     using namespace entt::literals;
 

+ 29 - 3
test/entt/meta/meta_pointer.cpp

@@ -117,10 +117,18 @@ TEST(MetaPointerLike, DereferenceOperatorConstType) {
 
     ASSERT_EQ(deref.try_cast<int>(), nullptr);
     ASSERT_EQ(deref.try_cast<const int>(), &value);
-    ASSERT_DEATH(deref.cast<int &>() = 0, "");
     ASSERT_EQ(deref.cast<const int &>(), 42);
 }
 
+TEST(MetaPointerLikeDeathTest, DereferenceOperatorConstType) {
+    const int value = 42;
+    entt::meta_any any{&value};
+    auto deref = *any;
+
+    ASSERT_TRUE(deref);
+    ASSERT_DEATH(deref.cast<int &>() = 0, "");
+}
+
 TEST(MetaPointerLike, DereferenceOperatorConstAnyNonConstType) {
     int value = 42;
     const entt::meta_any any{&value};
@@ -149,10 +157,18 @@ TEST(MetaPointerLike, DereferenceOperatorConstAnyConstType) {
 
     ASSERT_EQ(deref.try_cast<int>(), nullptr);
     ASSERT_NE(deref.try_cast<const int>(), nullptr);
-    ASSERT_DEATH(deref.cast<int &>() = 0, "");
     ASSERT_EQ(deref.cast<const int &>(), 42);
 }
 
+TEST(MetaPointerLikeDeathTest, DereferenceOperatorConstAnyConstType) {
+    const int value = 42;
+    const entt::meta_any any{&value};
+    auto deref = *any;
+
+    ASSERT_TRUE(deref);
+    ASSERT_DEATH(deref.cast<int &>() = 0, "");
+}
+
 TEST(MetaPointerLike, DereferenceOperatorRawPointer) {
     int value = 0;
     entt::meta_any any{&value};
@@ -283,9 +299,19 @@ TEST(MetaPointerLike, DereferencePointerToConstOverload) {
         ASSERT_FALSE(deref.type().is_pointer());
         ASSERT_FALSE(deref.type().is_pointer_like());
         ASSERT_EQ(deref.type(), entt::resolve<int>());
+        ASSERT_EQ(deref.cast<const int &>(), 42);
+    };
+
+    test(adl_wrapped_shared_ptr<const int>{42});
+    test(spec_wrapped_shared_ptr<const int>{42});
+}
 
+TEST(MetaPointerLikeDeathTest, DereferencePointerToConstOverload) {
+    auto test = [](entt::meta_any any) {
+        auto deref = *any;
+
+        ASSERT_TRUE(deref);
         ASSERT_DEATH(deref.cast<int &>() = 42, "");
-        ASSERT_EQ(deref.cast<const int &>(), 42);
     };
 
     test(adl_wrapped_shared_ptr<const int>{42});

+ 6 - 0
test/entt/meta/meta_type.cpp

@@ -169,6 +169,8 @@ struct MetaType: ::testing::Test {
     }
 };
 
+using MetaTypeDeathTest = MetaType;
+
 TEST_F(MetaType, Resolve) {
     using namespace entt::literals;
 
@@ -661,6 +663,10 @@ TEST_F(MetaType, NameCollision) {
     ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().type("quux"_hs));
     ASSERT_FALSE(entt::resolve("clazz"_hs));
     ASSERT_TRUE(entt::resolve("quux"_hs));
+}
+
+TEST_F(MetaTypeDeathTest, NameCollision) {
+    using namespace entt::literals;
 
     ASSERT_DEATH(entt::meta<clazz_t>().type("abstract"_hs), "");
 }

+ 8 - 5
test/entt/poly/poly_deduced.cpp

@@ -203,20 +203,23 @@ TEST(PolyDeduced, ConstReference) {
     ASSERT_EQ(instance.value, 0);
     ASSERT_EQ(poly->get(), 0);
 
-    ASSERT_DEATH(poly->set(1), "");
-    ASSERT_DEATH(poly->incr(), "");
-
     ASSERT_EQ(instance.value, 0);
     ASSERT_EQ(poly->get(), 0);
     ASSERT_EQ(poly->mul(3), 0);
 
-    ASSERT_DEATH(poly->decr(), "");
-
     ASSERT_EQ(instance.value, 0);
     ASSERT_EQ(poly->get(), 0);
     ASSERT_EQ(poly->mul(3), 0);
 }
 
+TEST(PolyDeducedDeathTest, ConstReference) {
+    impl instance{};
+    entt::poly<Deduced> poly{std::in_place_type<const impl &>, instance};
+
+    ASSERT_TRUE(poly);
+    ASSERT_DEATH(poly->set(1), "");
+}
+
 TEST(PolyDeduced, AsRef) {
     entt::poly<Deduced> poly{impl{}};
     auto ref = poly.as_ref();

+ 8 - 5
test/entt/poly/poly_defined.cpp

@@ -208,20 +208,23 @@ TEST(PolyDefined, ConstReference) {
     ASSERT_EQ(instance.value, 0);
     ASSERT_EQ(poly->get(), 0);
 
-    ASSERT_DEATH(poly->set(1), "");
-    ASSERT_DEATH(poly->incr(), "");
-
     ASSERT_EQ(instance.value, 0);
     ASSERT_EQ(poly->get(), 0);
     ASSERT_EQ(poly->mul(3), 0);
 
-    ASSERT_DEATH(poly->decr(), "");
-
     ASSERT_EQ(instance.value, 0);
     ASSERT_EQ(poly->get(), 0);
     ASSERT_EQ(poly->mul(3), 0);
 }
 
+TEST(PolyDefinedDeathTest, ConstReference) {
+    impl instance{};
+    entt::poly<Defined> poly{std::in_place_type<const impl &>, instance};
+
+    ASSERT_TRUE(poly);
+    ASSERT_DEATH(poly->set(1), "");
+}
+
 TEST(PolyDefined, AsRef) {
     entt::poly<Defined> poly{impl{}};
     auto ref = poly.as_ref();

+ 9 - 3
test/entt/signal/delegate.cpp

@@ -1,4 +1,5 @@
 #include <memory>
+#include <type_traits>
 #include <gtest/gtest.h>
 #include <entt/signal/delegate.hpp>
 
@@ -63,9 +64,6 @@ TEST(Delegate, Functionalities) {
     entt::delegate<int(int)> lf_del;
     delegate_functor functor;
 
-    ASSERT_DEATH(ff_del(42), "");
-    ASSERT_DEATH(mf_del(42), "");
-
     ASSERT_FALSE(ff_del);
     ASSERT_FALSE(mf_del);
     ASSERT_EQ(ff_del, mf_del);
@@ -109,6 +107,14 @@ TEST(Delegate, Functionalities) {
     ASSERT_NE(mf_del, lf_del);
 }
 
+TEST(DelegateDeathTest, InvokeEmpty) {
+    entt::delegate<int(int)> del;
+
+    ASSERT_FALSE(del);
+    ASSERT_DEATH(del(42), "");
+    ASSERT_DEATH(std::as_const(del)(42), "");
+}
+
 TEST(Delegate, DataMembers) {
     entt::delegate<double()> delegate;
     delegate_functor functor;