memory.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include <array>
  2. #include <cstddef>
  3. #include <memory>
  4. #include <tuple>
  5. #include <type_traits>
  6. #include <utility>
  7. #include <vector>
  8. #include <gtest/gtest.h>
  9. #include <entt/core/memory.hpp>
  10. #include "../../common/basic_test_allocator.hpp"
  11. #include "../../common/config.h"
  12. #include "../../common/throwing_allocator.hpp"
  13. #include "../../common/throwing_type.hpp"
  14. #include "../../common/tracked_memory_resource.hpp"
  15. TEST(ToAddress, Functionalities) {
  16. const std::shared_ptr<int> shared = std::make_shared<int>();
  17. auto *plain = &*shared;
  18. ASSERT_EQ(entt::to_address(shared), plain);
  19. ASSERT_EQ(entt::to_address(plain), plain);
  20. }
  21. TEST(PoccaPocmaAndPocs, Functionalities) {
  22. test::basic_test_allocator<int> lhs;
  23. test::basic_test_allocator<int> rhs;
  24. test::basic_test_allocator<int, std::false_type> no_pocs;
  25. // code coverage purposes
  26. ASSERT_FALSE(lhs == rhs);
  27. ASSERT_NO_THROW(entt::propagate_on_container_swap(no_pocs, no_pocs));
  28. // honestly, I don't even know how one is supposed to test such a thing :)
  29. entt::propagate_on_container_copy_assignment(lhs, rhs);
  30. entt::propagate_on_container_move_assignment(lhs, rhs);
  31. entt::propagate_on_container_swap(lhs, rhs);
  32. }
  33. ENTT_DEBUG_TEST(PoccaPocmaAndPocsDeathTest, Functionalities) {
  34. test::basic_test_allocator<int, std::false_type> lhs;
  35. test::basic_test_allocator<int, std::false_type> rhs;
  36. ASSERT_DEATH(entt::propagate_on_container_swap(lhs, rhs), "");
  37. }
  38. TEST(AllocateUnique, Functionalities) {
  39. test::throwing_allocator<test::throwing_type> allocator{};
  40. allocator.throw_counter<test::throwing_type>(0u);
  41. ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, false)), test::throwing_allocator_exception);
  42. ASSERT_THROW((entt::allocate_unique<test::throwing_type>(allocator, test::throwing_type{true})), test::throwing_type_exception);
  43. std::unique_ptr<test::throwing_type, entt::allocation_deleter<test::throwing_allocator<test::throwing_type>>> ptr = entt::allocate_unique<test::throwing_type>(allocator, false);
  44. ASSERT_TRUE(ptr);
  45. ASSERT_EQ(*ptr, false);
  46. ptr.reset();
  47. ASSERT_FALSE(ptr);
  48. }
  49. #if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)
  50. TEST(AllocateUnique, NoUsesAllocatorConstruction) {
  51. test::tracked_memory_resource memory_resource{};
  52. std::pmr::polymorphic_allocator<int> allocator{&memory_resource};
  53. using type = std::unique_ptr<int, entt::allocation_deleter<std::pmr::polymorphic_allocator<int>>>;
  54. [[maybe_unused]] const type ptr = entt::allocate_unique<int>(allocator, 0);
  55. ASSERT_EQ(memory_resource.do_allocate_counter(), 1u);
  56. ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
  57. }
  58. TEST(AllocateUnique, UsesAllocatorConstruction) {
  59. using string_type = typename test::tracked_memory_resource::string_type;
  60. test::tracked_memory_resource memory_resource{};
  61. std::pmr::polymorphic_allocator<string_type> allocator{&memory_resource};
  62. using type = std::unique_ptr<string_type, entt::allocation_deleter<std::pmr::polymorphic_allocator<string_type>>>;
  63. [[maybe_unused]] const type ptr = entt::allocate_unique<string_type>(allocator, test::tracked_memory_resource::default_value);
  64. ASSERT_GT(memory_resource.do_allocate_counter(), 1u);
  65. ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
  66. }
  67. #endif
  68. TEST(UsesAllocatorConstructionArgs, NoUsesAllocatorConstruction) {
  69. const auto value = 4;
  70. const auto args = entt::uses_allocator_construction_args<int>(std::allocator<int>{}, value);
  71. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 1u);
  72. testing::StaticAssertTypeEq<decltype(args), const std::tuple<const int &>>();
  73. ASSERT_EQ(std::get<0>(args), value);
  74. }
  75. TEST(UsesAllocatorConstructionArgs, LeadingAllocatorConvention) {
  76. const auto value = 4;
  77. const auto args = entt::uses_allocator_construction_args<std::tuple<int, char>>(std::allocator<int>{}, value, 'c');
  78. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 4u);
  79. testing::StaticAssertTypeEq<decltype(args), const std::tuple<std::allocator_arg_t, const std::allocator<int> &, const int &, char &&>>();
  80. ASSERT_EQ(std::get<2>(args), value);
  81. }
  82. TEST(UsesAllocatorConstructionArgs, TrailingAllocatorConvention) {
  83. const auto size = 4u;
  84. const auto args = entt::uses_allocator_construction_args<std::vector<int>>(std::allocator<int>{}, size);
  85. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 2u);
  86. testing::StaticAssertTypeEq<decltype(args), const std::tuple<const unsigned int &, const std::allocator<int> &>>();
  87. ASSERT_EQ(std::get<0>(args), size);
  88. }
  89. TEST(UsesAllocatorConstructionArgs, PairPiecewiseConstruct) {
  90. const auto size = 4u;
  91. const auto tup = std::make_tuple(size);
  92. const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, std::piecewise_construct, std::make_tuple(3), tup);
  93. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 3u);
  94. testing::StaticAssertTypeEq<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<int &&>, std::tuple<const unsigned int &, const std::allocator<int> &>>>();
  95. ASSERT_EQ(std::get<0>(std::get<2>(args)), size);
  96. }
  97. TEST(UsesAllocatorConstructionArgs, PairNoArgs) {
  98. [[maybe_unused]] const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{});
  99. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 3u);
  100. testing::StaticAssertTypeEq<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<>, std::tuple<const std::allocator<int> &>>>();
  101. }
  102. TEST(UsesAllocatorConstructionArgs, PairValues) {
  103. const auto size = 4u;
  104. const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, 3, size);
  105. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 3u);
  106. testing::StaticAssertTypeEq<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<int &&>, std::tuple<const unsigned int &, const std::allocator<int> &>>>();
  107. ASSERT_EQ(std::get<0>(std::get<2>(args)), size);
  108. }
  109. TEST(UsesAllocatorConstructionArgs, PairConstLValueReference) {
  110. const auto value = std::make_pair(3, 4u);
  111. const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, value);
  112. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 3u);
  113. testing::StaticAssertTypeEq<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<const int &>, std::tuple<const unsigned int &, const std::allocator<int> &>>>();
  114. ASSERT_EQ(std::get<0>(std::get<1>(args)), 3);
  115. ASSERT_EQ(std::get<0>(std::get<2>(args)), 4u);
  116. }
  117. TEST(UsesAllocatorConstructionArgs, PairRValueReference) {
  118. [[maybe_unused]] const auto args = entt::uses_allocator_construction_args<std::pair<int, std::vector<int>>>(std::allocator<int>{}, std::make_pair(3, 4u));
  119. ASSERT_EQ(std::tuple_size_v<decltype(args)>, 3u);
  120. testing::StaticAssertTypeEq<decltype(args), const std::tuple<std::piecewise_construct_t, std::tuple<int &&>, std::tuple<unsigned int &&, const std::allocator<int> &>>>();
  121. }
  122. TEST(MakeObjUsingAllocator, Functionalities) {
  123. const auto size = 4u;
  124. test::throwing_allocator<int> allocator{};
  125. allocator.throw_counter<int>(0u);
  126. ASSERT_THROW((entt::make_obj_using_allocator<std::vector<int, test::throwing_allocator<int>>>(allocator, size)), test::throwing_allocator_exception);
  127. const auto vec = entt::make_obj_using_allocator<std::vector<int>>(std::allocator<int>{}, size);
  128. ASSERT_FALSE(vec.empty());
  129. ASSERT_EQ(vec.size(), size);
  130. }
  131. TEST(UninitializedConstructUsingAllocator, NoUsesAllocatorConstruction) {
  132. alignas(int) std::array<std::byte, sizeof(int)> storage{};
  133. const std::allocator<int> allocator{};
  134. int *value = entt::uninitialized_construct_using_allocator(reinterpret_cast<int *>(storage.data()), allocator, 1);
  135. ASSERT_EQ(*value, 1);
  136. }
  137. #if defined(ENTT_HAS_TRACKED_MEMORY_RESOURCE)
  138. # include <memory_resource>
  139. TEST(UninitializedConstructUsingAllocator, UsesAllocatorConstruction) {
  140. using string_type = typename test::tracked_memory_resource::string_type;
  141. test::tracked_memory_resource memory_resource{};
  142. const std::pmr::polymorphic_allocator<string_type> allocator{&memory_resource};
  143. alignas(string_type) std::array<std::byte, sizeof(string_type)> storage{};
  144. string_type *value = entt::uninitialized_construct_using_allocator(reinterpret_cast<string_type *>(storage.data()), allocator, test::tracked_memory_resource::default_value);
  145. ASSERT_GT(memory_resource.do_allocate_counter(), 0u);
  146. ASSERT_EQ(memory_resource.do_deallocate_counter(), 0u);
  147. ASSERT_EQ(*value, test::tracked_memory_resource::default_value);
  148. value->~string_type();
  149. }
  150. #endif