storage_no_instance.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. #include <iterator>
  2. #include <memory>
  3. #include <tuple>
  4. #include <type_traits>
  5. #include <utility>
  6. #include <gtest/gtest.h>
  7. #include <entt/entity/storage.hpp>
  8. #include "../common/config.h"
  9. struct empty_type {};
  10. template<typename Type>
  11. struct StorageNoInstance: testing::Test {
  12. using type = Type;
  13. };
  14. template<typename Type>
  15. using StorageNoInstanceDeathTest = StorageNoInstance<Type>;
  16. using StorageNoInstanceTypes = ::testing::Types<empty_type, void>;
  17. TYPED_TEST_SUITE(StorageNoInstance, StorageNoInstanceTypes, );
  18. TYPED_TEST_SUITE(StorageNoInstanceDeathTest, StorageNoInstanceTypes, );
  19. TYPED_TEST(StorageNoInstance, Constructors) {
  20. using value_type = typename TestFixture::type;
  21. entt::storage<value_type> pool;
  22. ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_and_pop);
  23. ASSERT_NO_FATAL_FAILURE([[maybe_unused]] auto alloc = pool.get_allocator());
  24. ASSERT_EQ(pool.type(), entt::type_id<value_type>());
  25. pool = entt::storage<value_type>{std::allocator<value_type>{}};
  26. ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_and_pop);
  27. ASSERT_NO_FATAL_FAILURE([[maybe_unused]] auto alloc = pool.get_allocator());
  28. ASSERT_EQ(pool.type(), entt::type_id<value_type>());
  29. }
  30. TYPED_TEST(StorageNoInstance, Getters) {
  31. using value_type = typename TestFixture::type;
  32. entt::storage<value_type> pool;
  33. pool.emplace(entt::entity{41}, 3);
  34. testing::StaticAssertTypeEq<decltype(pool.get({})), void>();
  35. testing::StaticAssertTypeEq<decltype(std::as_const(pool).get({})), void>();
  36. testing::StaticAssertTypeEq<decltype(pool.get_as_tuple({})), std::tuple<>>();
  37. testing::StaticAssertTypeEq<decltype(std::as_const(pool).get_as_tuple({})), std::tuple<>>();
  38. ASSERT_NO_FATAL_FAILURE(pool.get(entt::entity{41}));
  39. ASSERT_NO_FATAL_FAILURE(std::as_const(pool).get(entt::entity{41}));
  40. ASSERT_EQ(pool.get_as_tuple(entt::entity{41}), std::make_tuple());
  41. ASSERT_EQ(std::as_const(pool).get_as_tuple(entt::entity{41}), std::make_tuple());
  42. }
  43. ENTT_DEBUG_TYPED_TEST(StorageNoInstanceDeathTest, Getters) {
  44. using value_type = typename TestFixture::type;
  45. entt::storage<value_type> pool;
  46. ASSERT_DEATH(pool.get(entt::entity{41}), "");
  47. ASSERT_DEATH(std::as_const(pool).get(entt::entity{41}), "");
  48. ASSERT_DEATH([[maybe_unused]] const auto value = pool.get_as_tuple(entt::entity{41}), "");
  49. ASSERT_DEATH([[maybe_unused]] const auto value = std::as_const(pool).get_as_tuple(entt::entity{41}), "");
  50. }
  51. TYPED_TEST(StorageNoInstance, Emplace) {
  52. using value_type = typename TestFixture::type;
  53. entt::storage<value_type> pool;
  54. const entt::entity entity[2u]{entt::entity{3}, entt::entity{42}};
  55. testing::StaticAssertTypeEq<decltype(pool.emplace({})), void>();
  56. if constexpr(std::is_void_v<value_type>) {
  57. ASSERT_NO_FATAL_FAILURE(pool.emplace(entity[0u]));
  58. } else {
  59. ASSERT_NO_FATAL_FAILURE(pool.emplace(entity[0u]));
  60. ASSERT_NO_FATAL_FAILURE(pool.emplace(entity[1u], value_type{}));
  61. }
  62. }
  63. ENTT_DEBUG_TYPED_TEST(StorageNoInstanceDeathTest, Emplace) {
  64. using value_type = typename TestFixture::type;
  65. entt::storage<value_type> pool;
  66. const entt::entity entity{42};
  67. testing::StaticAssertTypeEq<decltype(pool.emplace({})), void>();
  68. pool.emplace(entity);
  69. if constexpr(std::is_void_v<value_type>) {
  70. ASSERT_DEATH(pool.emplace(entity), "");
  71. } else {
  72. ASSERT_DEATH(pool.emplace(entity), "");
  73. ASSERT_DEATH(pool.emplace(entity, value_type{}), "");
  74. }
  75. }
  76. TYPED_TEST(StorageNoInstance, TryEmplace) {
  77. using value_type = typename TestFixture::type;
  78. entt::storage<value_type> pool;
  79. entt::sparse_set &base = pool;
  80. const entt::entity entity[2u]{entt::entity{3}, entt::entity{42}};
  81. if constexpr(std::is_void_v<value_type>) {
  82. ASSERT_NE(base.push(entity[0u], nullptr), base.end());
  83. } else {
  84. value_type instance{};
  85. ASSERT_NE(base.push(entity[0u], &instance), base.end());
  86. }
  87. ASSERT_EQ(pool.size(), 1u);
  88. ASSERT_EQ(base.index(entity[0u]), 0u);
  89. base.erase(entity[0u]);
  90. ASSERT_NE(base.push(std::begin(entity), std::end(entity)), base.end());
  91. ASSERT_EQ(pool.size(), 2u);
  92. ASSERT_EQ(base.index(entity[0u]), 0u);
  93. ASSERT_EQ(base.index(entity[1u]), 1u);
  94. base.erase(std::begin(entity), std::end(entity));
  95. ASSERT_NE(base.push(std::rbegin(entity), std::rend(entity)), base.end());
  96. ASSERT_EQ(pool.size(), 2u);
  97. ASSERT_EQ(base.index(entity[0u]), 1u);
  98. ASSERT_EQ(base.index(entity[1u]), 0u);
  99. }
  100. TYPED_TEST(StorageNoInstance, Patch) {
  101. using value_type = typename TestFixture::type;
  102. entt::storage<value_type> pool;
  103. entt::entity entity{42};
  104. int counter = 0;
  105. auto callback = [&counter]() { ++counter; };
  106. pool.emplace(entity);
  107. ASSERT_EQ(counter, 0);
  108. pool.patch(entity);
  109. pool.patch(entity, callback);
  110. pool.patch(entity, callback, callback);
  111. ASSERT_EQ(counter, 3);
  112. }
  113. ENTT_DEBUG_TYPED_TEST(StorageNoInstanceDeathTest, Patch) {
  114. using value_type = typename TestFixture::type;
  115. entt::storage<value_type> pool;
  116. ASSERT_DEATH(pool.patch(entt::null), "");
  117. }
  118. TYPED_TEST(StorageNoInstance, Insert) {
  119. using value_type = typename TestFixture::type;
  120. entt::storage<value_type> pool;
  121. const entt::entity entity[2u]{entt::entity{3}, entt::entity{42}};
  122. pool.insert(std::begin(entity), std::end(entity));
  123. ASSERT_EQ(pool.size(), 2u);
  124. ASSERT_EQ(pool.index(entity[0u]), 0u);
  125. ASSERT_EQ(pool.index(entity[1u]), 1u);
  126. if constexpr(!std::is_void_v<value_type>) {
  127. const value_type values[2u]{};
  128. pool.erase(std::begin(entity), std::end(entity));
  129. pool.insert(std::rbegin(entity), std::rend(entity), std::begin(values));
  130. ASSERT_EQ(pool.size(), 2u);
  131. ASSERT_EQ(pool.index(entity[0u]), 1u);
  132. ASSERT_EQ(pool.index(entity[1u]), 0u);
  133. }
  134. }
  135. ENTT_DEBUG_TYPED_TEST(StorageNoInstanceDeathTest, Insert) {
  136. using value_type = typename TestFixture::type;
  137. entt::storage<value_type> pool;
  138. const entt::entity entity[2u]{entt::entity{3}, entt::entity{42}};
  139. pool.insert(std::begin(entity), std::end(entity));
  140. if constexpr(std::is_void_v<value_type>) {
  141. ASSERT_DEATH(pool.insert(std::begin(entity), std::end(entity)), "");
  142. } else {
  143. const value_type values[2u]{};
  144. ASSERT_DEATH(pool.insert(std::begin(entity), std::end(entity)), "");
  145. ASSERT_DEATH(pool.insert(std::begin(entity), std::end(entity), std::begin(values)), "");
  146. }
  147. }
  148. TYPED_TEST(StorageNoInstance, Iterable) {
  149. using value_type = typename TestFixture::type;
  150. using iterator = typename entt::storage<value_type>::iterable::iterator;
  151. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  152. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  153. testing::StaticAssertTypeEq<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  154. testing::StaticAssertTypeEq<typename iterator::reference, typename iterator::value_type>();
  155. entt::storage<value_type> pool;
  156. entt::sparse_set &base = pool;
  157. pool.emplace(entt::entity{1});
  158. pool.emplace(entt::entity{3});
  159. auto iterable = pool.each();
  160. iterator end{iterable.begin()};
  161. iterator begin{};
  162. begin = iterable.end();
  163. std::swap(begin, end);
  164. ASSERT_EQ(begin, iterable.begin());
  165. ASSERT_EQ(end, iterable.end());
  166. ASSERT_NE(begin, end);
  167. ASSERT_EQ(begin.base(), base.begin());
  168. ASSERT_EQ(end.base(), base.end());
  169. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{3});
  170. ASSERT_EQ(std::get<0>(*begin), entt::entity{3});
  171. ASSERT_EQ(begin++, iterable.begin());
  172. ASSERT_EQ(begin.base(), ++base.begin());
  173. ASSERT_EQ(++begin, iterable.end());
  174. ASSERT_EQ(begin.base(), base.end());
  175. for(auto [entity]: iterable) {
  176. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  177. ASSERT_TRUE(entity == entt::entity{1} || entity == entt::entity{3});
  178. }
  179. }
  180. TYPED_TEST(StorageNoInstance, ConstIterable) {
  181. using value_type = typename TestFixture::type;
  182. using iterator = typename entt::storage<value_type>::const_iterable::iterator;
  183. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  184. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  185. testing::StaticAssertTypeEq<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  186. testing::StaticAssertTypeEq<typename iterator::reference, typename iterator::value_type>();
  187. entt::storage<value_type> pool;
  188. entt::sparse_set &base = pool;
  189. pool.emplace(entt::entity{1});
  190. pool.emplace(entt::entity{3});
  191. auto iterable = std::as_const(pool).each();
  192. iterator end{iterable.begin()};
  193. iterator begin{};
  194. begin = iterable.end();
  195. std::swap(begin, end);
  196. ASSERT_EQ(begin, iterable.begin());
  197. ASSERT_EQ(end, iterable.end());
  198. ASSERT_NE(begin, end);
  199. ASSERT_EQ(begin.base(), base.begin());
  200. ASSERT_EQ(end.base(), base.end());
  201. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{3});
  202. ASSERT_EQ(std::get<0>(*begin), entt::entity{3});
  203. ASSERT_EQ(begin++, iterable.begin());
  204. ASSERT_EQ(begin.base(), ++base.begin());
  205. ASSERT_EQ(++begin, iterable.end());
  206. ASSERT_EQ(begin.base(), base.end());
  207. for(auto [entity]: iterable) {
  208. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  209. ASSERT_TRUE(entity == entt::entity{1} || entity == entt::entity{3});
  210. }
  211. }
  212. TYPED_TEST(StorageNoInstance, ReverseIterable) {
  213. using value_type = typename TestFixture::type;
  214. using iterator = typename entt::storage<value_type>::reverse_iterable::iterator;
  215. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  216. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  217. testing::StaticAssertTypeEq<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  218. testing::StaticAssertTypeEq<typename iterator::reference, typename iterator::value_type>();
  219. entt::storage<value_type> pool;
  220. entt::sparse_set &base = pool;
  221. pool.emplace(entt::entity{1});
  222. pool.emplace(entt::entity{3});
  223. auto iterable = pool.reach();
  224. iterator end{iterable.begin()};
  225. iterator begin{};
  226. begin = iterable.end();
  227. std::swap(begin, end);
  228. ASSERT_EQ(begin, iterable.begin());
  229. ASSERT_EQ(end, iterable.end());
  230. ASSERT_NE(begin, end);
  231. ASSERT_EQ(begin.base(), base.rbegin());
  232. ASSERT_EQ(end.base(), base.rend());
  233. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{1});
  234. ASSERT_EQ(std::get<0>(*begin), entt::entity{1});
  235. ASSERT_EQ(begin++, iterable.begin());
  236. ASSERT_EQ(begin.base(), ++base.rbegin());
  237. ASSERT_EQ(++begin, iterable.end());
  238. ASSERT_EQ(begin.base(), base.rend());
  239. for(auto [entity]: iterable) {
  240. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  241. ASSERT_TRUE(entity == entt::entity{1} || entity == entt::entity{3});
  242. }
  243. }
  244. TYPED_TEST(StorageNoInstance, ConstReverseIterable) {
  245. using value_type = typename TestFixture::type;
  246. using iterator = typename entt::storage<value_type>::const_reverse_iterable::iterator;
  247. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  248. testing::StaticAssertTypeEq<typename iterator::value_type, std::tuple<entt::entity>>();
  249. testing::StaticAssertTypeEq<typename iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  250. testing::StaticAssertTypeEq<typename iterator::reference, typename iterator::value_type>();
  251. entt::storage<value_type> pool;
  252. entt::sparse_set &base = pool;
  253. pool.emplace(entt::entity{1});
  254. pool.emplace(entt::entity{3});
  255. auto iterable = std::as_const(pool).reach();
  256. iterator end{iterable.begin()};
  257. iterator begin{};
  258. begin = iterable.end();
  259. std::swap(begin, end);
  260. ASSERT_EQ(begin, iterable.begin());
  261. ASSERT_EQ(end, iterable.end());
  262. ASSERT_NE(begin, end);
  263. ASSERT_EQ(begin.base(), base.rbegin());
  264. ASSERT_EQ(end.base(), base.rend());
  265. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{1});
  266. ASSERT_EQ(std::get<0>(*begin), entt::entity{1});
  267. ASSERT_EQ(begin++, iterable.begin());
  268. ASSERT_EQ(begin.base(), ++base.rbegin());
  269. ASSERT_EQ(++begin, iterable.end());
  270. ASSERT_EQ(begin.base(), base.rend());
  271. for(auto [entity]: iterable) {
  272. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  273. ASSERT_TRUE(entity == entt::entity{1} || entity == entt::entity{3});
  274. }
  275. }
  276. TYPED_TEST(StorageNoInstance, IterableIteratorConversion) {
  277. using value_type = typename TestFixture::type;
  278. entt::storage<value_type> pool;
  279. pool.emplace(entt::entity{3});
  280. typename entt::storage<value_type>::iterable::iterator it = pool.each().begin();
  281. typename entt::storage<value_type>::const_iterable::iterator cit = it;
  282. testing::StaticAssertTypeEq<decltype(*it), std::tuple<entt::entity>>();
  283. testing::StaticAssertTypeEq<decltype(*cit), std::tuple<entt::entity>>();
  284. ASSERT_EQ(it, cit);
  285. ASSERT_NE(++cit, it);
  286. }