Browse Source

test: static-less throwing allocator

Michele Caini 2 years ago
parent
commit
c26a24e713

+ 30 - 17
test/entt/common/throwing_allocator.hpp

@@ -2,19 +2,22 @@
 #define ENTT_COMMON_THROWING_ALLOCATOR_HPP
 
 #include <cstddef>
+#include <limits>
 #include <memory>
 #include <type_traits>
+#include <entt/container/dense_map.hpp>
+#include <entt/core/fwd.hpp>
+#include <entt/core/type_info.hpp>
 
 namespace test {
 
+struct throwing_allocator_exception {};
+
 template<typename Type>
-class throwing_allocator: std::allocator<Type> {
+class throwing_allocator {
     template<typename Other>
     friend class throwing_allocator;
 
-    using base = std::allocator<Type>;
-    struct test_exception {};
-
 public:
     using value_type = Type;
     using pointer = value_type *;
@@ -23,33 +26,42 @@ public:
     using const_void_pointer = const void *;
     using propagate_on_container_move_assignment = std::true_type;
     using propagate_on_container_swap = std::true_type;
-    using exception_type = test_exception;
+    using container_type = entt::dense_map<entt::id_type, std::size_t>;
 
     template<typename Other>
     struct rebind {
         using other = throwing_allocator<Other>;
     };
 
-    throwing_allocator() = default;
+    throwing_allocator()
+        : allocator{},
+          config{std::allocate_shared<container_type>(allocator)} {}
 
     template<typename Other>
     throwing_allocator(const throwing_allocator<Other> &other)
-        : base{other} {}
+        : allocator{other.allocator},
+          config{other.config} {}
 
     pointer allocate(std::size_t length) {
-        if(trigger_on_allocate) {
-            trigger_on_allocate = false;
-            throw test_exception{};
+        if(const auto hash = entt::type_id<Type>().hash(); config->contains(hash)) {
+            if(auto &elem = (*config)[hash]; elem == 0u) {
+                config->erase(hash);
+                throw throwing_allocator_exception{};
+            } else {
+                --elem;
+            }
         }
 
-        trigger_on_allocate = trigger_after_allocate;
-        trigger_after_allocate = false;
-
-        return base::allocate(length);
+        return allocator.allocate(length);
     }
 
     void deallocate(pointer mem, std::size_t length) {
-        base::deallocate(mem, length);
+        allocator.deallocate(mem, length);
+    }
+
+    template<typename Other>
+    void throw_counter(const std::size_t len) {
+        (*config)[entt::type_id<Other>().hash()] = len;
     }
 
     bool operator==(const throwing_allocator<Type> &) const {
@@ -60,8 +72,9 @@ public:
         return !(*this == other);
     }
 
-    static inline bool trigger_on_allocate{};
-    static inline bool trigger_after_allocate{};
+private:
+    std::allocator<Type> allocator;
+    std::shared_ptr<container_type> config;
 };
 
 } // namespace test

+ 9 - 12
test/entt/container/dense_map.cpp

@@ -1154,32 +1154,29 @@ TEST(DenseMap, Reserve) {
 }
 
 TEST(DenseMap, ThrowingAllocator) {
-    using allocator = test::throwing_allocator<std::pair<const std::size_t, std::size_t>>;
-    using packed_allocator = test::throwing_allocator<entt::internal::dense_map_node<std::size_t, std::size_t>>;
-    using packed_exception = typename packed_allocator::exception_type;
-
     constexpr std::size_t minimum_bucket_count = 8u;
+    using allocator = test::throwing_allocator<std::pair<const std::size_t, std::size_t>>;
     entt::dense_map<std::size_t, std::size_t, std::hash<std::size_t>, std::equal_to<std::size_t>, allocator> map{};
 
-    packed_allocator::trigger_on_allocate = true;
+    map.get_allocator().throw_counter<entt::internal::dense_map_node<std::size_t, std::size_t>>(0u);
 
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);
-    ASSERT_THROW(map.reserve(2u * map.bucket_count()), packed_exception);
+    ASSERT_THROW(map.reserve(2u * map.bucket_count()), test::throwing_allocator_exception);
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);
 
-    packed_allocator::trigger_on_allocate = true;
+    map.get_allocator().throw_counter<entt::internal::dense_map_node<std::size_t, std::size_t>>(0u);
 
-    ASSERT_THROW(map.emplace(0u, 0u), packed_exception);
+    ASSERT_THROW(map.emplace(0u, 0u), test::throwing_allocator_exception);
     ASSERT_FALSE(map.contains(0u));
 
-    packed_allocator::trigger_on_allocate = true;
+    map.get_allocator().throw_counter<entt::internal::dense_map_node<std::size_t, std::size_t>>(0u);
 
-    ASSERT_THROW(map.emplace(std::piecewise_construct, std::make_tuple(0u), std::make_tuple(0u)), packed_exception);
+    ASSERT_THROW(map.emplace(std::piecewise_construct, std::make_tuple(0u), std::make_tuple(0u)), test::throwing_allocator_exception);
     ASSERT_FALSE(map.contains(0u));
 
-    packed_allocator::trigger_on_allocate = true;
+    map.get_allocator().throw_counter<entt::internal::dense_map_node<std::size_t, std::size_t>>(0u);
 
-    ASSERT_THROW(map.insert_or_assign(0u, 0u), packed_exception);
+    ASSERT_THROW(map.insert_or_assign(0u, 0u), test::throwing_allocator_exception);
     ASSERT_FALSE(map.contains(0u));
 }
 

+ 9 - 12
test/entt/container/dense_set.cpp

@@ -978,32 +978,29 @@ TEST(DenseSet, Reserve) {
 }
 
 TEST(DenseSet, ThrowingAllocator) {
-    using allocator = test::throwing_allocator<std::size_t>;
-    using packed_allocator = test::throwing_allocator<std::pair<std::size_t, std::size_t>>;
-    using packed_exception = typename packed_allocator::exception_type;
-
     constexpr std::size_t minimum_bucket_count = 8u;
+    using allocator = test::throwing_allocator<std::size_t>;
     entt::dense_set<std::size_t, std::hash<std::size_t>, std::equal_to<std::size_t>, allocator> set{};
 
-    packed_allocator::trigger_on_allocate = true;
+    set.get_allocator().throw_counter<std::pair<std::size_t, std::size_t>>(0u);
 
     ASSERT_EQ(set.bucket_count(), minimum_bucket_count);
-    ASSERT_THROW(set.reserve(2u * set.bucket_count()), packed_exception);
+    ASSERT_THROW(set.reserve(2u * set.bucket_count()), test::throwing_allocator_exception);
     ASSERT_EQ(set.bucket_count(), minimum_bucket_count);
 
-    packed_allocator::trigger_on_allocate = true;
+    set.get_allocator().throw_counter<std::pair<std::size_t, std::size_t>>(0u);
 
-    ASSERT_THROW(set.emplace(), packed_exception);
+    ASSERT_THROW(set.emplace(), test::throwing_allocator_exception);
     ASSERT_FALSE(set.contains(0u));
 
-    packed_allocator::trigger_on_allocate = true;
+    set.get_allocator().throw_counter<std::pair<std::size_t, std::size_t>>(0u);
 
-    ASSERT_THROW(set.emplace(std::size_t{}), packed_exception);
+    ASSERT_THROW(set.emplace(std::size_t{}), test::throwing_allocator_exception);
     ASSERT_FALSE(set.contains(0u));
 
-    packed_allocator::trigger_on_allocate = true;
+    set.get_allocator().throw_counter<std::pair<std::size_t, std::size_t>>(0u);
 
-    ASSERT_THROW(set.insert(0u), packed_exception);
+    ASSERT_THROW(set.insert(0u), test::throwing_allocator_exception);
     ASSERT_FALSE(set.contains(0u));
 }
 

+ 6 - 4
test/entt/core/memory.cpp

@@ -85,10 +85,10 @@ TEST(FastMod, Functionalities) {
 
 TEST(AllocateUnique, Functionalities) {
     test::throwing_allocator<test::throwing_type> allocator{};
-    test::throwing_allocator<test::throwing_type>::trigger_on_allocate = true;
 
-    ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, false)), test::throwing_allocator<test::throwing_type>::exception_type);
+    allocator.throw_counter<test::throwing_type>(0u);
 
+    ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, false)), test::throwing_allocator_exception);
     ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, test::throwing_type{true})), test::throwing_type_exception);
 
     std::unique_ptr<test::throwing_type, entt::allocation_deleter<test::throwing_allocator<test::throwing_type>>> ptr = entt::allocate_unique<test::throwing_type>(allocator, false);
@@ -201,9 +201,11 @@ TEST(UsesAllocatorConstructionArgs, PairRValueReference) {
 
 TEST(MakeObjUsingAllocator, Functionalities) {
     const auto size = 42u;
-    test::throwing_allocator<int>::trigger_on_allocate = true;
+    test::throwing_allocator<int> allocator{};
 
-    ASSERT_THROW((entt::make_obj_using_allocator<std::vector<int, test::throwing_allocator<int>>>(test::throwing_allocator<int>{}, size)), test::throwing_allocator<int>::exception_type);
+    allocator.throw_counter<int>(0u);
+
+    ASSERT_THROW((entt::make_obj_using_allocator<std::vector<int, test::throwing_allocator<int>>>(allocator, size)), test::throwing_allocator_exception);
 
     const auto vec = entt::make_obj_using_allocator<std::vector<int>>(std::allocator<int>{}, size);
 

+ 14 - 15
test/entt/entity/sigh_mixin.cpp

@@ -472,7 +472,6 @@ TYPED_TEST(SighMixin, CustomAllocator) {
 
 TYPED_TEST(SighMixin, ThrowingAllocator) {
     using value_type = typename TestFixture::type;
-    using allocator_type = test::throwing_allocator<value_type>;
     entt::sigh_mixin<entt::basic_storage<value_type, entt::entity, test::throwing_allocator<value_type>>> pool{};
     typename std::decay_t<decltype(pool)>::base_type &base = pool;
 
@@ -489,53 +488,53 @@ TYPED_TEST(SighMixin, ThrowingAllocator) {
     pool.on_construct().template connect<&listener<registry_type>>(on_construct);
     pool.on_destroy().template connect<&listener<registry_type>>(on_destroy);
 
-    allocator_type::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<value_type>(0u);
 
-    ASSERT_THROW(pool.reserve(1u), typename allocator_type::exception_type);
+    ASSERT_THROW(pool.reserve(1u), test::throwing_allocator_exception);
     ASSERT_EQ(pool.capacity(), 0u);
 
-    allocator_type::trigger_after_allocate = true;
+    pool.get_allocator().template throw_counter<value_type>(1u);
 
-    ASSERT_THROW(pool.reserve(2 * packed_page_size), typename allocator_type::exception_type);
+    ASSERT_THROW(pool.reserve(2 * packed_page_size), test::throwing_allocator_exception);
     ASSERT_EQ(pool.capacity(), packed_page_size);
 
     pool.shrink_to_fit();
 
     ASSERT_EQ(pool.capacity(), 0u);
 
-    test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(0u);
 
-    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator_exception);
     ASSERT_FALSE(pool.contains(entt::entity{0}));
     ASSERT_TRUE(pool.empty());
 
-    test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(0u);
 
-    ASSERT_THROW(base.push(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(base.push(entt::entity{0}), test::throwing_allocator_exception);
     ASSERT_FALSE(base.contains(entt::entity{0}));
     ASSERT_TRUE(base.empty());
 
-    allocator_type::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<value_type>(0u);
 
-    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), typename allocator_type::exception_type);
+    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator_exception);
     ASSERT_FALSE(pool.contains(entt::entity{0}));
     ASSERT_NO_FATAL_FAILURE(pool.compact());
     ASSERT_TRUE(pool.empty());
 
     pool.emplace(entt::entity{0}, 0);
     const entt::entity entity[2u]{entt::entity{1}, entt::entity{sparse_page_size}};
-    test::throwing_allocator<entt::entity>::trigger_after_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(1u);
 
-    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), value_type{0}), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), value_type{0}), test::throwing_allocator_exception);
     ASSERT_TRUE(pool.contains(entt::entity{1}));
     ASSERT_FALSE(pool.contains(entt::entity{sparse_page_size}));
 
     pool.erase(entt::entity{1});
     const value_type components[2u]{value_type{1}, value_type{sparse_page_size}};
-    test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(0u);
     pool.compact();
 
-    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), std::begin(components)), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), std::begin(components)), test::throwing_allocator_exception);
     ASSERT_TRUE(pool.contains(entt::entity{1}));
     ASSERT_FALSE(pool.contains(entt::entity{sparse_page_size}));
 

+ 10 - 10
test/entt/entity/sparse_set.cpp

@@ -2108,38 +2108,38 @@ TYPED_TEST(SparseSet, ThrowingAllocator) {
     for(const auto policy: this->deletion_policy) {
         entt::basic_sparse_set<entity_type, test::throwing_allocator<entity_type>> set{policy};
 
-        test::throwing_allocator<entity_type>::trigger_on_allocate = true;
+        set.get_allocator().template throw_counter<entity_type>(0u);
 
-        ASSERT_THROW(set.reserve(1u), typename test::throwing_allocator<entity_type>::exception_type);
+        ASSERT_THROW(set.reserve(1u), test::throwing_allocator_exception);
         ASSERT_EQ(set.capacity(), 0u);
         ASSERT_EQ(set.extent(), 0u);
 
-        test::throwing_allocator<entity_type>::trigger_on_allocate = true;
+        set.get_allocator().template throw_counter<entity_type>(0u);
 
-        ASSERT_THROW(set.push(entity_type{0}), typename test::throwing_allocator<entity_type>::exception_type);
+        ASSERT_THROW(set.push(entity_type{0}), test::throwing_allocator_exception);
         ASSERT_EQ(set.extent(), traits_type::page_size);
         ASSERT_EQ(set.capacity(), 0u);
 
         set.push(entity_type{0});
-        test::throwing_allocator<entity_type>::trigger_on_allocate = true;
+        set.get_allocator().template throw_counter<entity_type>(0u);
 
-        ASSERT_THROW(set.reserve(2u), typename test::throwing_allocator<entity_type>::exception_type);
+        ASSERT_THROW(set.reserve(2u), test::throwing_allocator_exception);
         ASSERT_EQ(set.extent(), traits_type::page_size);
         ASSERT_TRUE(set.contains(entity_type{0}));
         ASSERT_EQ(set.capacity(), 1u);
 
-        test::throwing_allocator<entity_type>::trigger_on_allocate = true;
+        set.get_allocator().template throw_counter<entity_type>(0u);
 
-        ASSERT_THROW(set.push(entity_type{1}), typename test::throwing_allocator<entity_type>::exception_type);
+        ASSERT_THROW(set.push(entity_type{1}), test::throwing_allocator_exception);
         ASSERT_EQ(set.extent(), traits_type::page_size);
         ASSERT_TRUE(set.contains(entity_type{0}));
         ASSERT_FALSE(set.contains(entity_type{1}));
         ASSERT_EQ(set.capacity(), 1u);
 
         entity_type entity[2u]{entity_type{1}, entity_type{traits_type::page_size}};
-        test::throwing_allocator<entity_type>::trigger_after_allocate = true;
+        set.get_allocator().template throw_counter<entity_type>(1u);
 
-        ASSERT_THROW(set.push(std::begin(entity), std::end(entity)), typename test::throwing_allocator<entity_type>::exception_type);
+        ASSERT_THROW(set.push(std::begin(entity), std::end(entity)), test::throwing_allocator_exception);
         ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
         ASSERT_TRUE(set.contains(entity_type{0}));
         ASSERT_TRUE(set.contains(entity_type{1}));

+ 15 - 16
test/entt/entity/storage.cpp

@@ -1738,60 +1738,59 @@ TYPED_TEST(Storage, CustomAllocator) {
 
 TYPED_TEST(Storage, ThrowingAllocator) {
     using value_type = typename TestFixture::type;
-    using allocator_type = test::throwing_allocator<value_type>;
-    entt::basic_storage<value_type, entt::entity, allocator_type> pool{};
+    entt::basic_storage<value_type, entt::entity, test::throwing_allocator<value_type>> pool{};
     typename std::decay_t<decltype(pool)>::base_type &base = pool;
 
     constexpr auto packed_page_size = decltype(pool)::traits_type::page_size;
     constexpr auto sparse_page_size = std::remove_reference_t<decltype(base)>::traits_type::page_size;
 
-    allocator_type::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<value_type>(0u);
 
-    ASSERT_THROW(pool.reserve(1u), typename allocator_type::exception_type);
+    ASSERT_THROW(pool.reserve(1u), test::throwing_allocator_exception);
     ASSERT_EQ(pool.capacity(), 0u);
 
-    allocator_type::trigger_after_allocate = true;
+    pool.get_allocator().template throw_counter<value_type>(1u);
 
-    ASSERT_THROW(pool.reserve(2 * packed_page_size), typename allocator_type::exception_type);
+    ASSERT_THROW(pool.reserve(2 * packed_page_size), test::throwing_allocator_exception);
     ASSERT_EQ(pool.capacity(), packed_page_size);
 
     pool.shrink_to_fit();
 
     ASSERT_EQ(pool.capacity(), 0u);
 
-    test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(0u);
 
-    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator_exception);
     ASSERT_FALSE(pool.contains(entt::entity{0}));
     ASSERT_TRUE(pool.empty());
 
-    test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(0u);
 
-    ASSERT_THROW(base.push(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(base.push(entt::entity{0}), test::throwing_allocator_exception);
     ASSERT_FALSE(base.contains(entt::entity{0}));
     ASSERT_TRUE(base.empty());
 
-    allocator_type::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<value_type>(0u);
 
-    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), typename allocator_type::exception_type);
+    ASSERT_THROW(pool.emplace(entt::entity{0}, 0), test::throwing_allocator_exception);
     ASSERT_FALSE(pool.contains(entt::entity{0}));
     ASSERT_NO_FATAL_FAILURE(pool.compact());
     ASSERT_TRUE(pool.empty());
 
     pool.emplace(entt::entity{0}, 0);
     const entt::entity entity[2u]{entt::entity{1}, entt::entity{sparse_page_size}};
-    test::throwing_allocator<entt::entity>::trigger_after_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(1u);
 
-    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), value_type{0}), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), value_type{0}), test::throwing_allocator_exception);
     ASSERT_TRUE(pool.contains(entt::entity{1}));
     ASSERT_FALSE(pool.contains(entt::entity{sparse_page_size}));
 
     pool.erase(entt::entity{1});
     const value_type components[2u]{value_type{1}, value_type{sparse_page_size}};
-    test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
+    pool.get_allocator().template throw_counter<entt::entity>(0u);
     pool.compact();
 
-    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), std::begin(components)), test::throwing_allocator<entt::entity>::exception_type);
+    ASSERT_THROW(pool.insert(std::begin(entity), std::end(entity), std::begin(components)), test::throwing_allocator_exception);
     ASSERT_TRUE(pool.contains(entt::entity{1}));
     ASSERT_FALSE(pool.contains(entt::entity{sparse_page_size}));
 }

+ 3 - 7
test/entt/graph/adjacency_matrix.cpp

@@ -543,18 +543,14 @@ TEST(AdjacencyMatrix, InEdgesBackwardOnlyUndirected) {
 }
 
 TEST(AdjacencyMatrix, ThrowingAllocator) {
-    using allocator = test::throwing_allocator<std::size_t>;
-    using exception = typename allocator::exception_type;
-
-    entt::adjacency_matrix<entt::directed_tag, allocator> adjacency_matrix{2u};
+    entt::adjacency_matrix<entt::directed_tag, test::throwing_allocator<std::size_t>> adjacency_matrix{2u};
     adjacency_matrix.insert(0u, 1u);
-
-    allocator::trigger_on_allocate = true;
+    adjacency_matrix.get_allocator().throw_counter<std::size_t>(0u);
 
     ASSERT_EQ(adjacency_matrix.size(), 2u);
     ASSERT_TRUE(adjacency_matrix.contains(0u, 1u));
 
-    ASSERT_THROW(adjacency_matrix.resize(4u), exception);
+    ASSERT_THROW(adjacency_matrix.resize(4u), test::throwing_allocator_exception);
 
     ASSERT_EQ(adjacency_matrix.size(), 2u);
     ASSERT_TRUE(adjacency_matrix.contains(0u, 1u));

+ 3 - 7
test/entt/graph/flow.cpp

@@ -326,16 +326,12 @@ TEST(Flow, Loop) {
 }
 
 TEST(Flow, ThrowingAllocator) {
-    using allocator = test::throwing_allocator<entt::id_type>;
-    using task_allocator = test::throwing_allocator<std::pair<std::size_t, entt::id_type>>;
-    using task_exception = typename task_allocator::exception_type;
+    entt::basic_flow<test::throwing_allocator<entt::id_type>> flow{};
 
-    entt::basic_flow<allocator> flow{};
-
-    task_allocator::trigger_on_allocate = true;
+    flow.get_allocator().throw_counter<std::pair<std::size_t, entt::id_type>>(0u);
 
     ASSERT_EQ(flow.size(), 0u);
-    ASSERT_THROW(flow.bind(1), task_exception);
+    ASSERT_THROW(flow.bind(1), test::throwing_allocator_exception);
     ASSERT_EQ(flow.size(), 0u);
 
     flow.bind(1);

+ 5 - 10
test/entt/resource/resource_cache.cpp

@@ -413,19 +413,14 @@ TEST(ResourceCache, BrokenLoader) {
 TEST(ResourceCache, ThrowingAllocator) {
     using namespace entt::literals;
 
-    using allocator = test::throwing_allocator<std::size_t>;
-    using packed_allocator = test::throwing_allocator<entt::internal::dense_map_node<entt::id_type, std::shared_ptr<std::size_t>>>;
-    using packed_exception = typename packed_allocator::exception_type;
+    entt::resource_cache<std::size_t, entt::resource_loader<std::size_t>, test::throwing_allocator<std::size_t>> cache{};
+    cache.get_allocator().throw_counter<entt::internal::dense_map_node<entt::id_type, std::shared_ptr<std::size_t>>>(0u);
 
-    entt::resource_cache<std::size_t, entt::resource_loader<std::size_t>, allocator> cache{};
-
-    packed_allocator::trigger_on_allocate = true;
-
-    ASSERT_THROW(cache.load("resource"_hs), packed_exception);
+    ASSERT_THROW(cache.load("resource"_hs), test::throwing_allocator_exception);
     ASSERT_FALSE(cache.contains("resource"_hs));
 
-    packed_allocator::trigger_on_allocate = true;
+    cache.get_allocator().throw_counter<entt::internal::dense_map_node<entt::id_type, std::shared_ptr<std::size_t>>>(0u);
 
-    ASSERT_THROW(cache.force_load("resource"_hs), packed_exception);
+    ASSERT_THROW(cache.force_load("resource"_hs), test::throwing_allocator_exception);
     ASSERT_FALSE(cache.contains("resource"_hs));
 }