Selaa lähdekoodia

storage: refine transparent aggregate support

Michele Caini 3 vuotta sitten
vanhempi
commit
a9883f27c6
2 muutettua tiedostoa jossa 92 lisäystä ja 69 poistoa
  1. 1 1
      src/entt/entity/storage.hpp
  2. 91 68
      test/entt/entity/storage.cpp

+ 1 - 1
src/entt/entity/storage.hpp

@@ -675,7 +675,7 @@ public:
      */
     template<typename... Args>
     value_type &emplace(const entity_type entt, Args &&...args) {
-        if constexpr(std::is_aggregate_v<value_type>) {
+        if constexpr(sizeof...(Args) != 0u && std ::is_aggregate_v<value_type>) {
             const auto it = emplace_element(entt, false, Type{std::forward<Args>(args)...});
             return element_at(static_cast<size_type>(it.index()));
         } else {

+ 91 - 68
test/entt/entity/storage.cpp

@@ -31,6 +31,15 @@ struct stable_type {
     int value;
 };
 
+struct aggregate_tracking_type {
+    ~aggregate_tracking_type() {
+        ++counter;
+    }
+
+    static inline int counter;
+    int value;
+};
+
 struct non_default_constructible {
     non_default_constructible() = delete;
 
@@ -87,7 +96,15 @@ inline bool operator==(const boxed_int &lhs, const boxed_int &rhs) {
     return lhs.value == rhs.value;
 }
 
-TEST(Storage, Functionalities) {
+struct Storage: ::testing::Test {
+    void SetUp() override {
+        aggregate_tracking_type::counter = 0;
+    }
+};
+
+using StorageDeathTest = Storage;
+
+TEST_F(Storage, Functionalities) {
     entt::storage<int> pool;
     constexpr auto page_size = decltype(pool)::traits_type::page_size;
 
@@ -155,7 +172,7 @@ TEST(Storage, Functionalities) {
     ASSERT_EQ(pool.capacity(), 0u);
 }
 
-TEST(Storage, Move) {
+TEST_F(Storage, Move) {
     entt::storage<int> pool;
     pool.emplace(entt::entity{3}, 3);
 
@@ -191,7 +208,7 @@ TEST(Storage, Move) {
     ASSERT_EQ(other.get(entt::entity{3}), 3);
 }
 
-TEST(Storage, Swap) {
+TEST_F(Storage, Swap) {
     entt::storage<int> pool;
     entt::storage<int> other;
 
@@ -219,7 +236,7 @@ TEST(Storage, Swap) {
     ASSERT_EQ(other.get(entt::entity{42}), 41);
 }
 
-TEST(Storage, StableSwap) {
+TEST_F(Storage, StableSwap) {
     entt::storage<stable_type> pool;
     entt::storage<stable_type> other;
 
@@ -247,7 +264,7 @@ TEST(Storage, StableSwap) {
     ASSERT_EQ(other.get(entt::entity{42}).value, 41);
 }
 
-TEST(Storage, VoidType) {
+TEST_F(Storage, VoidType) {
     entt::storage<void> pool;
     pool.emplace(entt::entity{99});
 
@@ -265,7 +282,7 @@ TEST(Storage, VoidType) {
     ASSERT_FALSE(other.contains(entt::entity{99}));
 }
 
-TEST(Storage, EmptyType) {
+TEST_F(Storage, EmptyType) {
     entt::storage<empty_stable_type> pool;
     pool.emplace(entt::entity{99});
 
@@ -287,7 +304,7 @@ TEST(Storage, EmptyType) {
     ASSERT_EQ(pool.get_as_tuple(entt::entity{99}), std::tuple<>{});
 }
 
-ENTT_DEBUG_TEST(StorageDeathTest, EmptyType) {
+ENTT_DEBUG_TEST_F(StorageDeathTest, EmptyType) {
     entt::storage<empty_stable_type> pool;
     pool.emplace(entt::entity{99});
 
@@ -295,7 +312,7 @@ ENTT_DEBUG_TEST(StorageDeathTest, EmptyType) {
     ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{3}), "");
 }
 
-TEST(Storage, Insert) {
+TEST_F(Storage, Insert) {
     entt::storage<stable_type> pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
     pool.insert(std::begin(entities), std::end(entities), stable_type{99});
@@ -321,7 +338,7 @@ TEST(Storage, Insert) {
     ASSERT_EQ(pool.get(entities[1u]).value, 42);
 }
 
-TEST(Storage, InsertEmptyType) {
+TEST_F(Storage, InsertEmptyType) {
     entt::storage<empty_stable_type> pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
@@ -344,7 +361,7 @@ TEST(Storage, InsertEmptyType) {
     ASSERT_EQ(pool.index(entities[1u]), 2u);
 }
 
-TEST(Storage, Erase) {
+TEST_F(Storage, Erase) {
     entt::storage<int> pool;
     entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
 
@@ -377,7 +394,7 @@ TEST(Storage, Erase) {
     ASSERT_EQ(*pool.begin(), 1);
 }
 
-TEST(Storage, CrossErase) {
+TEST_F(Storage, CrossErase) {
     entt::sparse_set set;
     entt::storage<int> pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -392,7 +409,7 @@ TEST(Storage, CrossErase) {
     ASSERT_EQ(pool.raw()[0u][0u], 3);
 }
 
-TEST(Storage, StableErase) {
+TEST_F(Storage, StableErase) {
     entt::storage<stable_type> pool;
     entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
 
@@ -486,7 +503,7 @@ TEST(Storage, StableErase) {
     ASSERT_EQ(pool.get(entities[2u]).value, 1);
 }
 
-TEST(Storage, CrossStableErase) {
+TEST_F(Storage, CrossStableErase) {
     entt::sparse_set set;
     entt::storage<stable_type> pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -501,7 +518,7 @@ TEST(Storage, CrossStableErase) {
     ASSERT_EQ(pool.raw()[0u][0u].value, 3);
 }
 
-TEST(Storage, Remove) {
+TEST_F(Storage, Remove) {
     entt::storage<int> pool;
     entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
 
@@ -535,7 +552,7 @@ TEST(Storage, Remove) {
     ASSERT_EQ(*pool.begin(), 1);
 }
 
-TEST(Storage, CrossRemove) {
+TEST_F(Storage, CrossRemove) {
     entt::sparse_set set;
     entt::storage<int> pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -550,7 +567,7 @@ TEST(Storage, CrossRemove) {
     ASSERT_EQ(pool.raw()[0u][0u], 3);
 }
 
-TEST(Storage, StableRemove) {
+TEST_F(Storage, StableRemove) {
     entt::storage<stable_type> pool;
     entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
 
@@ -647,7 +664,7 @@ TEST(Storage, StableRemove) {
     ASSERT_EQ(pool.get(entities[2u]).value, 1);
 }
 
-TEST(Storage, CrossStableRemove) {
+TEST_F(Storage, CrossStableRemove) {
     entt::sparse_set set;
     entt::storage<stable_type> pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -662,7 +679,7 @@ TEST(Storage, CrossStableRemove) {
     ASSERT_EQ(pool.raw()[0u][0u].value, 3);
 }
 
-TEST(Storage, TypeFromBase) {
+TEST_F(Storage, TypeFromBase) {
     entt::storage<int> pool;
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -696,7 +713,7 @@ TEST(Storage, TypeFromBase) {
     ASSERT_TRUE(pool.empty());
 }
 
-TEST(Storage, EmptyTypeFromBase) {
+TEST_F(Storage, EmptyTypeFromBase) {
     entt::storage<empty_stable_type> pool;
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -747,7 +764,7 @@ TEST(Storage, EmptyTypeFromBase) {
     }
 }
 
-TEST(Storage, NonDefaultConstructibleTypeFromBase) {
+TEST_F(Storage, NonDefaultConstructibleTypeFromBase) {
     entt::storage<non_default_constructible> pool;
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -786,7 +803,7 @@ TEST(Storage, NonDefaultConstructibleTypeFromBase) {
     ASSERT_TRUE(pool.empty());
 }
 
-TEST(Storage, NonCopyConstructibleTypeFromBase) {
+TEST_F(Storage, NonCopyConstructibleTypeFromBase) {
     entt::storage<std::unique_ptr<int>> pool;
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
@@ -825,7 +842,7 @@ TEST(Storage, NonCopyConstructibleTypeFromBase) {
     ASSERT_FALSE(pool.empty());
 }
 
-TEST(Storage, Compact) {
+TEST_F(Storage, Compact) {
     entt::storage<stable_type> pool;
 
     ASSERT_TRUE(pool.empty());
@@ -871,7 +888,7 @@ TEST(Storage, Compact) {
     ASSERT_TRUE(pool.empty());
 }
 
-TEST(Storage, ShrinkToFit) {
+TEST_F(Storage, ShrinkToFit) {
     entt::storage<int> pool;
     constexpr auto page_size = decltype(pool)::traits_type::page_size;
 
@@ -901,16 +918,22 @@ TEST(Storage, ShrinkToFit) {
     ASSERT_EQ(pool.size(), 0u);
 }
 
-TEST(Storage, AggregatesMustWork) {
-    struct aggregate_type {
-        int value;
-    };
+TEST_F(Storage, AggregatesMustWork) {
+    static_assert(std::is_aggregate_v<aggregate_tracking_type>);
+    entt::storage<aggregate_tracking_type> storage{};
+
+    // aggregate types with no args enter the non-aggregate path
+    storage.emplace(entt::entity{0});
+
+    ASSERT_EQ(aggregate_tracking_type::counter, 0);
+
+    // aggregate types with args work despite the lack of support in the standard library
+    storage.emplace(entt::entity{1}, 42);
 
-    // the goal of this test is to enforce the requirements for aggregate types
-    entt::storage<aggregate_type>{}.emplace(entt::entity{0}, 42);
+    ASSERT_EQ(aggregate_tracking_type::counter, 1);
 }
 
-TEST(Storage, SelfMoveSupport) {
+TEST_F(Storage, SelfMoveSupport) {
     // see #37 - this test shouldn't crash, that's all
     entt::storage<std::unordered_set<int>> pool;
     entt::entity entity{};
@@ -923,7 +946,7 @@ TEST(Storage, SelfMoveSupport) {
     ASSERT_FALSE(pool.contains(entity));
 }
 
-TEST(Storage, SelfMoveSupportInPlaceDelete) {
+TEST_F(Storage, SelfMoveSupportInPlaceDelete) {
     // see #37 - this test shouldn't crash, that's all
     entt::storage<std::unordered_set<char>> pool;
     entt::entity entity{};
@@ -936,7 +959,7 @@ TEST(Storage, SelfMoveSupportInPlaceDelete) {
     ASSERT_FALSE(pool.contains(entity));
 }
 
-TEST(Storage, Iterator) {
+TEST_F(Storage, Iterator) {
     using iterator = typename entt::storage<boxed_int>::iterator;
 
     static_assert(std::is_same_v<iterator::value_type, boxed_int>);
@@ -997,7 +1020,7 @@ TEST(Storage, Iterator) {
     ASSERT_EQ(begin[1u], boxed_int{42});
 }
 
-TEST(Storage, ConstIterator) {
+TEST_F(Storage, ConstIterator) {
     using iterator = typename entt::storage<boxed_int>::const_iterator;
 
     static_assert(std::is_same_v<iterator::value_type, boxed_int>);
@@ -1060,7 +1083,7 @@ TEST(Storage, ConstIterator) {
     ASSERT_EQ(cbegin[1u], boxed_int{42});
 }
 
-TEST(Storage, ReverseIterator) {
+TEST_F(Storage, ReverseIterator) {
     using reverse_iterator = typename entt::storage<boxed_int>::reverse_iterator;
 
     static_assert(std::is_same_v<reverse_iterator::value_type, boxed_int>);
@@ -1121,7 +1144,7 @@ TEST(Storage, ReverseIterator) {
     ASSERT_EQ(begin[1u], boxed_int{3});
 }
 
-TEST(Storage, ConstReverseIterator) {
+TEST_F(Storage, ConstReverseIterator) {
     using const_reverse_iterator = typename entt::storage<boxed_int>::const_reverse_iterator;
 
     static_assert(std::is_same_v<const_reverse_iterator::value_type, boxed_int>);
@@ -1184,7 +1207,7 @@ TEST(Storage, ConstReverseIterator) {
     ASSERT_EQ(cbegin[1u], boxed_int{3});
 }
 
-TEST(Storage, IteratorConversion) {
+TEST_F(Storage, IteratorConversion) {
     entt::storage<boxed_int> pool;
     pool.emplace(entt::entity{3}, 42);
 
@@ -1207,7 +1230,7 @@ TEST(Storage, IteratorConversion) {
     ASSERT_NE(++cit, it);
 }
 
-TEST(Storage, IteratorPageSizeAwareness) {
+TEST_F(Storage, IteratorPageSizeAwareness) {
     entt::storage<std::unordered_set<char>> pool;
     constexpr auto page_size = decltype(pool)::traits_type::page_size;
     const std::unordered_set<char> check{'c'};
@@ -1222,7 +1245,7 @@ TEST(Storage, IteratorPageSizeAwareness) {
     ASSERT_EQ(*pool.begin(), check);
 }
 
-TEST(Storage, Iterable) {
+TEST_F(Storage, Iterable) {
     using iterator = typename entt::storage<boxed_int>::iterable::iterator;
 
     static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity, boxed_int &>>);
@@ -1266,7 +1289,7 @@ TEST(Storage, Iterable) {
     }
 }
 
-TEST(Storage, ConstIterable) {
+TEST_F(Storage, ConstIterable) {
     using iterator = typename entt::storage<boxed_int>::const_iterable::iterator;
 
     static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity, const boxed_int &>>);
@@ -1310,7 +1333,7 @@ TEST(Storage, ConstIterable) {
     }
 }
 
-TEST(Storage, IterableIteratorConversion) {
+TEST_F(Storage, IterableIteratorConversion) {
     entt::storage<boxed_int> pool;
     pool.emplace(entt::entity{3}, 42);
 
@@ -1324,7 +1347,7 @@ TEST(Storage, IterableIteratorConversion) {
     ASSERT_NE(++cit, it);
 }
 
-TEST(Storage, EmptyTypeIterable) {
+TEST_F(Storage, EmptyTypeIterable) {
     using iterator = typename entt::storage<empty_stable_type>::iterable::iterator;
 
     static_assert(std::is_same_v<iterator::value_type, std::tuple<entt::entity>>);
@@ -1365,7 +1388,7 @@ TEST(Storage, EmptyTypeIterable) {
     }
 }
 
-TEST(Storage, IterableAlgorithmCompatibility) {
+TEST_F(Storage, IterableAlgorithmCompatibility) {
     entt::storage<boxed_int> pool;
     pool.emplace(entt::entity{3}, 42);
 
@@ -1375,7 +1398,7 @@ TEST(Storage, IterableAlgorithmCompatibility) {
     ASSERT_EQ(std::get<0>(*it), entt::entity{3});
 }
 
-TEST(Storage, Raw) {
+TEST_F(Storage, Raw) {
     entt::storage<int> pool;
 
     pool.emplace(entt::entity{3}, 3);
@@ -1391,7 +1414,7 @@ TEST(Storage, Raw) {
     ASSERT_EQ(pool.raw()[0u][2u], 9);
 }
 
-TEST(Storage, SwapElements) {
+TEST_F(Storage, SwapElements) {
     entt::storage<int> pool;
 
     pool.emplace(entt::entity{3}, 3);
@@ -1413,7 +1436,7 @@ TEST(Storage, SwapElements) {
     ASSERT_EQ(pool.index(entt::entity{42}), 0u);
 }
 
-TEST(Storage, StableSwapElements) {
+TEST_F(Storage, StableSwapElements) {
     entt::storage<stable_type> pool;
 
     pool.emplace(entt::entity{3}, 3);
@@ -1435,7 +1458,7 @@ TEST(Storage, StableSwapElements) {
     ASSERT_EQ(pool.index(entt::entity{42}), 0u);
 }
 
-TEST(Storage, SortOrdered) {
+TEST_F(Storage, SortOrdered) {
     entt::storage<boxed_int> pool;
     entt::entity entities[5u]{entt::entity{12}, entt::entity{42}, entt::entity{7}, entt::entity{3}, entt::entity{9}};
     boxed_int values[5u]{{12}, {9}, {6}, {3}, {1}};
@@ -1447,7 +1470,7 @@ TEST(Storage, SortOrdered) {
     ASSERT_TRUE(std::equal(std::rbegin(values), std::rend(values), pool.begin(), pool.end()));
 }
 
-TEST(Storage, SortReverse) {
+TEST_F(Storage, SortReverse) {
     entt::storage<boxed_int> pool;
     entt::entity entities[5u]{entt::entity{12}, entt::entity{42}, entt::entity{7}, entt::entity{3}, entt::entity{9}};
     boxed_int values[5u]{{1}, {3}, {6}, {9}, {12}};
@@ -1459,7 +1482,7 @@ TEST(Storage, SortReverse) {
     ASSERT_TRUE(std::equal(std::begin(values), std::end(values), pool.begin(), pool.end()));
 }
 
-TEST(Storage, SortUnordered) {
+TEST_F(Storage, SortUnordered) {
     entt::storage<boxed_int> pool;
     entt::entity entities[5u]{entt::entity{12}, entt::entity{42}, entt::entity{7}, entt::entity{3}, entt::entity{9}};
     boxed_int values[5u]{{6}, {3}, {1}, {9}, {12}};
@@ -1484,7 +1507,7 @@ TEST(Storage, SortUnordered) {
     ASSERT_EQ(pool.data()[4u], entities[2u]);
 }
 
-TEST(Storage, SortRange) {
+TEST_F(Storage, SortRange) {
     entt::storage<boxed_int> pool;
     entt::entity entities[5u]{entt::entity{12}, entt::entity{42}, entt::entity{7}, entt::entity{3}, entt::entity{9}};
     boxed_int values[5u]{{3}, {6}, {1}, {9}, {12}};
@@ -1524,7 +1547,7 @@ TEST(Storage, SortRange) {
     ASSERT_EQ(pool.data()[4u], entities[2u]);
 }
 
-TEST(Storage, RespectDisjoint) {
+TEST_F(Storage, RespectDisjoint) {
     entt::storage<int> lhs;
     entt::storage<int> rhs;
 
@@ -1541,7 +1564,7 @@ TEST(Storage, RespectDisjoint) {
     ASSERT_TRUE(std::equal(std::rbegin(lhs_values), std::rend(lhs_values), lhs.begin(), lhs.end()));
 }
 
-TEST(Storage, RespectOverlap) {
+TEST_F(Storage, RespectOverlap) {
     entt::storage<int> lhs;
     entt::storage<int> rhs;
 
@@ -1574,7 +1597,7 @@ TEST(Storage, RespectOverlap) {
     ASSERT_EQ(lhs.data()[2u], lhs_entities[1u]);
 }
 
-TEST(Storage, RespectOrdered) {
+TEST_F(Storage, RespectOrdered) {
     entt::storage<int> lhs;
     entt::storage<int> rhs;
 
@@ -1598,7 +1621,7 @@ TEST(Storage, RespectOrdered) {
     ASSERT_TRUE(std::equal(std::rbegin(rhs_values), std::rend(rhs_values), rhs.begin(), rhs.end()));
 }
 
-TEST(Storage, RespectReverse) {
+TEST_F(Storage, RespectReverse) {
     entt::storage<int> lhs;
     entt::storage<int> rhs;
 
@@ -1637,7 +1660,7 @@ TEST(Storage, RespectReverse) {
     ASSERT_EQ(rhs.data()[5u], rhs_entities[0u]);
 }
 
-TEST(Storage, RespectUnordered) {
+TEST_F(Storage, RespectUnordered) {
     entt::storage<int> lhs;
     entt::storage<int> rhs;
 
@@ -1676,7 +1699,7 @@ TEST(Storage, RespectUnordered) {
     ASSERT_EQ(rhs.data()[5u], rhs_entities[5u]);
 }
 
-TEST(Storage, CanModifyDuringIteration) {
+TEST_F(Storage, CanModifyDuringIteration) {
     entt::storage<int> pool;
     auto *ptr = &pool.emplace(entt::entity{0}, 42);
     constexpr auto page_size = decltype(pool)::traits_type::page_size;
@@ -1693,7 +1716,7 @@ TEST(Storage, CanModifyDuringIteration) {
     [[maybe_unused]] const int &value = *it;
 }
 
-TEST(Storage, ReferencesGuaranteed) {
+TEST_F(Storage, ReferencesGuaranteed) {
     entt::storage<boxed_int> pool;
 
     pool.emplace(entt::entity{0}, 0);
@@ -1721,17 +1744,17 @@ TEST(Storage, ReferencesGuaranteed) {
     ASSERT_EQ(pool.get(entt::entity{1}).value, 3);
 }
 
-TEST(Storage, MoveOnlyComponent) {
+TEST_F(Storage, MoveOnlyComponent) {
     // the purpose is to ensure that move only components are always accepted
     [[maybe_unused]] entt::storage<std::unique_ptr<int>> pool;
 }
 
-TEST(Storage, PinnedComponent) {
+TEST_F(Storage, PinnedComponent) {
     // the purpose is to ensure that non-movable components are always accepted
     [[maybe_unused]] entt::storage<pinned_type> pool;
 }
 
-ENTT_DEBUG_TEST(StorageDeathTest, PinnedComponent) {
+ENTT_DEBUG_TEST_F(StorageDeathTest, PinnedComponent) {
     entt::storage<pinned_type> pool;
     const entt::entity entity{0};
     const entt::entity destroy{1};
@@ -1748,7 +1771,7 @@ ENTT_DEBUG_TEST(StorageDeathTest, PinnedComponent) {
     ASSERT_DEATH(pool.sort([](auto &&lhs, auto &&rhs) { return lhs < rhs; }), "");
 }
 
-TEST(Storage, UpdateFromDestructor) {
+TEST_F(Storage, UpdateFromDestructor) {
     auto test = [](const auto target) {
         constexpr auto size = 10u;
 
@@ -1779,7 +1802,7 @@ TEST(Storage, UpdateFromDestructor) {
     test(entt::entity{0u});
 }
 
-TEST(Storage, CreateFromConstructor) {
+TEST_F(Storage, CreateFromConstructor) {
     entt::storage<create_from_constructor> pool;
     const entt::entity entity{0u};
     const entt::entity other{1u};
@@ -1790,7 +1813,7 @@ TEST(Storage, CreateFromConstructor) {
     ASSERT_EQ(pool.get(other).child, static_cast<entt::entity>(entt::null));
 }
 
-TEST(Storage, CustomAllocator) {
+TEST_F(Storage, CustomAllocator) {
     auto test = [](auto pool, auto alloc) {
         pool.reserve(1u);
 
@@ -1837,7 +1860,7 @@ TEST(Storage, CustomAllocator) {
     test(entt::basic_storage<stable_type, entt::entity, test::throwing_allocator<stable_type>>{allocator}, allocator);
 }
 
-TEST(Storage, ThrowingAllocator) {
+TEST_F(Storage, ThrowingAllocator) {
     auto test = [](auto pool) {
         using pool_allocator_type = typename decltype(pool)::allocator_type;
         using value_type = typename decltype(pool)::value_type;
@@ -1901,7 +1924,7 @@ TEST(Storage, ThrowingAllocator) {
     test(entt::basic_storage<stable_type, entt::entity, test::throwing_allocator<stable_type>>{});
 }
 
-TEST(Storage, ThrowingComponent) {
+TEST_F(Storage, ThrowingComponent) {
     entt::storage<test::throwing_type> pool;
     test::throwing_type::trigger_on_value = 42;
 
@@ -1955,7 +1978,7 @@ TEST(Storage, ThrowingComponent) {
 
 #if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)
 
-TEST(Storage, NoUsesAllocatorConstruction) {
+TEST_F(Storage, NoUsesAllocatorConstruction) {
     test::tracked_memory_resource memory_resource{};
     entt::basic_storage<int, entt::entity, std::pmr::polymorphic_allocator<int>> pool{&memory_resource};
     const entt::entity entity{};
@@ -1970,7 +1993,7 @@ TEST(Storage, NoUsesAllocatorConstruction) {
     ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
 }
 
-TEST(Storage, UsesAllocatorConstruction) {
+TEST_F(Storage, UsesAllocatorConstruction) {
     using string_type = typename test::tracked_memory_resource::string_type;
 
     test::tracked_memory_resource memory_resource{};
@@ -1989,13 +2012,13 @@ TEST(Storage, UsesAllocatorConstruction) {
 
 #endif
 
-TEST(Storage, StorageType) {
+TEST_F(Storage, StorageType) {
     // just a bunch of static asserts to avoid regressions
     static_assert(std::is_same_v<entt::storage_type_t<char, entt::entity>, entt::sigh_mixin<entt::basic_storage<char, entt::entity>>>);
     static_assert(std::is_same_v<entt::storage_type_t<int>, entt::sigh_mixin<entt::storage<int>>>);
 }
 
-TEST(Storage, StorageFor) {
+TEST_F(Storage, StorageFor) {
     // just a bunch of static asserts to avoid regressions
     static_assert(std::is_same_v<entt::storage_for_t<const double, entt::entity>, const entt::sigh_mixin<entt::basic_storage<double, entt::entity>>>);
     static_assert(std::is_same_v<entt::storage_for_t<char, entt::entity>, entt::sigh_mixin<entt::basic_storage<char, entt::entity>>>);