storage_entity.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. #include <algorithm>
  2. #include <array>
  3. #include <functional>
  4. #include <iterator>
  5. #include <memory>
  6. #include <tuple>
  7. #include <type_traits>
  8. #include <utility>
  9. #include <gtest/gtest.h>
  10. #include <entt/core/iterator.hpp>
  11. #include <entt/core/type_info.hpp>
  12. #include <entt/entity/entity.hpp>
  13. #include <entt/entity/storage.hpp>
  14. #include "../../common/config.h"
  15. #include "../../common/linter.hpp"
  16. TEST(StorageEntity, Constructors) {
  17. entt::storage<entt::entity> pool;
  18. ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_only);
  19. ASSERT_NO_THROW([[maybe_unused]] auto alloc = pool.get_allocator());
  20. ASSERT_EQ(pool.info(), entt::type_id<void>());
  21. pool = entt::storage<entt::entity>{std::allocator<entt::entity>{}};
  22. ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_only);
  23. ASSERT_NO_THROW([[maybe_unused]] auto alloc = pool.get_allocator());
  24. ASSERT_EQ(pool.info(), entt::type_id<void>());
  25. }
  26. TEST(StorageEntity, Move) {
  27. entt::storage<entt::entity> pool;
  28. const std::array entity{entt::entity{3}, entt::entity{2}};
  29. pool.generate(entity[0u]);
  30. static_assert(std::is_move_constructible_v<decltype(pool)>, "Move constructible type required");
  31. static_assert(std::is_move_assignable_v<decltype(pool)>, "Move assignable type required");
  32. entt::storage<entt::entity> other{std::move(pool)};
  33. test::is_initialized(pool);
  34. ASSERT_TRUE(pool.empty());
  35. ASSERT_FALSE(other.empty());
  36. ASSERT_EQ(other.info(), entt::type_id<void>());
  37. ASSERT_EQ(other.index(entity[0u]), 0u);
  38. entt::storage<entt::entity> extended{std::move(other), std::allocator<entt::entity>{}};
  39. test::is_initialized(other);
  40. ASSERT_TRUE(other.empty());
  41. ASSERT_FALSE(extended.empty());
  42. ASSERT_EQ(extended.info(), entt::type_id<void>());
  43. ASSERT_EQ(extended.index(entity[0u]), 0u);
  44. pool = std::move(extended);
  45. test::is_initialized(extended);
  46. ASSERT_FALSE(pool.empty());
  47. ASSERT_TRUE(other.empty());
  48. ASSERT_TRUE(extended.empty());
  49. ASSERT_EQ(pool.info(), entt::type_id<void>());
  50. ASSERT_EQ(pool.index(entity[0u]), 0u);
  51. other = entt::storage<entt::entity>{};
  52. other.generate(entity[1u]);
  53. other = std::move(pool);
  54. test::is_initialized(pool);
  55. ASSERT_FALSE(pool.empty());
  56. ASSERT_FALSE(other.empty());
  57. ASSERT_EQ(other.info(), entt::type_id<void>());
  58. ASSERT_EQ(other.index(entity[0u]), 0u);
  59. }
  60. TEST(StorageEntity, Swap) {
  61. using traits_type = entt::entt_traits<entt::entity>;
  62. entt::storage<entt::entity> pool;
  63. entt::storage<entt::entity> other;
  64. ASSERT_EQ(pool.info(), entt::type_id<void>());
  65. ASSERT_EQ(other.info(), entt::type_id<void>());
  66. pool.generate(entt::entity{2});
  67. other.generate(entt::entity{1});
  68. other.generate(entt::entity{0});
  69. other.erase(entt::entity{1});
  70. ASSERT_EQ(pool.size(), 1u);
  71. ASSERT_EQ(other.size(), 2u);
  72. pool.start_from(entt::entity{3});
  73. other.start_from(entt::entity{2});
  74. pool.swap(other);
  75. ASSERT_EQ(pool.info(), entt::type_id<void>());
  76. ASSERT_EQ(other.info(), entt::type_id<void>());
  77. ASSERT_EQ(pool.size(), 2u);
  78. ASSERT_EQ(other.size(), 1u);
  79. ASSERT_EQ(pool.generate(), traits_type::construct(1, 1));
  80. ASSERT_EQ(pool.generate(), entt::entity{2});
  81. ASSERT_EQ(other.generate(), entt::entity{3});
  82. ASSERT_EQ(pool.index(entt::entity{0}), 0u);
  83. ASSERT_EQ(other.index(entt::entity{2}), 0u);
  84. }
  85. TEST(StorageEntity, Getters) {
  86. entt::storage<entt::entity> pool;
  87. const entt::entity entity{4};
  88. pool.generate(entity);
  89. testing::StaticAssertTypeEq<decltype(pool.get({})), void>();
  90. testing::StaticAssertTypeEq<decltype(std::as_const(pool).get({})), void>();
  91. testing::StaticAssertTypeEq<decltype(pool.get_as_tuple({})), std::tuple<>>();
  92. testing::StaticAssertTypeEq<decltype(std::as_const(pool).get_as_tuple({})), std::tuple<>>();
  93. ASSERT_NO_THROW(pool.get(entity));
  94. ASSERT_NO_THROW(std::as_const(pool).get(entity));
  95. ASSERT_EQ(pool.get_as_tuple(entity), std::make_tuple());
  96. ASSERT_EQ(std::as_const(pool).get_as_tuple(entity), std::make_tuple());
  97. }
  98. ENTT_DEBUG_TEST(StorageEntityDeathTest, Getters) {
  99. entt::storage<entt::entity> pool;
  100. const entt::entity entity{4};
  101. ASSERT_DEATH(pool.get(entity), "");
  102. ASSERT_DEATH(std::as_const(pool).get(entity), "");
  103. ASSERT_DEATH([[maybe_unused]] const auto value = pool.get_as_tuple(entity), "");
  104. ASSERT_DEATH([[maybe_unused]] const auto value = std::as_const(pool).get_as_tuple(entity), "");
  105. }
  106. TEST(StorageEntity, Generate) {
  107. using traits_type = entt::entt_traits<entt::entity>;
  108. entt::storage<entt::entity> pool;
  109. std::array<entt::entity, 2u> entity{};
  110. ASSERT_EQ(pool.generate(), entt::entity{0});
  111. ASSERT_EQ(pool.generate(entt::null), entt::entity{1});
  112. ASSERT_EQ(pool.generate(entt::tombstone), entt::entity{2});
  113. ASSERT_EQ(pool.generate(entt::entity{0}), entt::entity{3});
  114. ASSERT_EQ(pool.generate(traits_type::construct(1, 1)), entt::entity{4});
  115. ASSERT_EQ(pool.generate(traits_type::construct(6, 3)), traits_type::construct(6, 3));
  116. ASSERT_LT(pool.index(entt::entity{0}), pool.free_list());
  117. ASSERT_LT(pool.index(entt::entity{1}), pool.free_list());
  118. ASSERT_LT(pool.index(entt::entity{2}), pool.free_list());
  119. ASSERT_LT(pool.index(entt::entity{3}), pool.free_list());
  120. ASSERT_LT(pool.index(entt::entity{4}), pool.free_list());
  121. ASSERT_EQ(pool.current(entt::entity{5}), traits_type::to_version(entt::tombstone));
  122. ASSERT_LT(pool.index(traits_type::construct(6, 3)), pool.free_list());
  123. ASSERT_EQ(pool.generate(traits_type::construct(5, 2)), traits_type::construct(5, 2));
  124. ASSERT_EQ(pool.generate(traits_type::construct(5, 3)), entt::entity{7});
  125. pool.erase(entt::entity{2});
  126. ASSERT_EQ(pool.generate(), traits_type::construct(2, 1));
  127. pool.erase(traits_type::construct(2, 1));
  128. pool.generate(entity.begin(), entity.end());
  129. ASSERT_EQ(entity[0u], traits_type::construct(2, 2));
  130. ASSERT_EQ(entity[1u], entt::entity{8});
  131. }
  132. TEST(StorageEntity, GenerateRange) {
  133. entt::storage<entt::entity> pool;
  134. std::array<entt::entity, 2u> entity{};
  135. pool.generate(entity.begin(), entity.end());
  136. ASSERT_TRUE(pool.contains(entity[0u]));
  137. ASSERT_TRUE(pool.contains(entity[1u]));
  138. ASSERT_FALSE(pool.empty());
  139. ASSERT_EQ(pool.size(), 2u);
  140. ASSERT_EQ(pool.free_list(), 2u);
  141. pool.erase(entity.begin(), entity.end());
  142. ASSERT_FALSE(pool.empty());
  143. ASSERT_EQ(pool.size(), 2u);
  144. ASSERT_EQ(pool.free_list(), 0u);
  145. pool.generate(entity.begin(), entity.begin() + 1u);
  146. ASSERT_TRUE(pool.contains(entity[0u]));
  147. ASSERT_FALSE(pool.contains(entity[1u]));
  148. ASSERT_FALSE(pool.empty());
  149. ASSERT_EQ(pool.size(), 2u);
  150. ASSERT_EQ(pool.free_list(), 1u);
  151. }
  152. TEST(StorageEntity, GenerateFrom) {
  153. entt::storage<entt::entity> pool;
  154. std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}};
  155. ASSERT_EQ(pool.generate(), entity[0u]);
  156. pool.start_from(entity[2u]);
  157. ASSERT_EQ(pool.generate(), entity[2u]);
  158. ASSERT_FALSE(pool.contains(entity[1u]));
  159. }
  160. TEST(StorageEntity, GenerateInUse) {
  161. entt::storage<entt::entity> pool;
  162. std::array<entt::entity, 2u> entity{};
  163. const entt::entity other{1};
  164. ASSERT_EQ(pool.generate(other), other);
  165. ASSERT_EQ(pool.generate(), entt::entity{0});
  166. ASSERT_EQ(pool.generate(), entt::entity{2});
  167. pool.clear();
  168. ASSERT_EQ(pool.generate(other), other);
  169. pool.generate(entity.begin(), entity.end());
  170. ASSERT_EQ(entity[0u], entt::entity{0});
  171. ASSERT_EQ(entity[1u], entt::entity{2});
  172. }
  173. TEST(StorageEntity, TryGenerate) {
  174. using traits_type = entt::entt_traits<entt::entity>;
  175. entt::storage<entt::entity> pool;
  176. ASSERT_EQ(*pool.push(entt::null), entt::entity{0});
  177. ASSERT_EQ(*pool.push(entt::tombstone), entt::entity{1});
  178. ASSERT_EQ(*pool.push(entt::entity{0}), entt::entity{2});
  179. ASSERT_EQ(*pool.push(traits_type::construct(1, 1)), entt::entity{3});
  180. ASSERT_EQ(*pool.push(traits_type::construct(5, 3)), traits_type::construct(5, 3));
  181. ASSERT_LT(pool.index(entt::entity{0}), pool.free_list());
  182. ASSERT_LT(pool.index(entt::entity{1}), pool.free_list());
  183. ASSERT_LT(pool.index(entt::entity{2}), pool.free_list());
  184. ASSERT_LT(pool.index(entt::entity{3}), pool.free_list());
  185. ASSERT_EQ(pool.current(entt::entity{4}), traits_type::to_version(entt::tombstone));
  186. ASSERT_LT(pool.index(traits_type::construct(5, 3)), pool.free_list());
  187. ASSERT_EQ(*pool.push(traits_type::construct(4, 2)), traits_type::construct(4, 2));
  188. ASSERT_EQ(*pool.push(traits_type::construct(4, 3)), entt::entity{6});
  189. const std::array entity{entt::entity{1}, traits_type::construct(5, 3)};
  190. pool.erase(entity.begin(), entity.end());
  191. pool.erase(entt::entity{2});
  192. ASSERT_EQ(pool.current(entity[0u]), 1);
  193. ASSERT_EQ(pool.current(entity[1u]), 4);
  194. ASSERT_EQ(pool.current(entt::entity{2}), 1);
  195. ASSERT_LT(pool.index(entt::entity{0}), pool.free_list());
  196. ASSERT_GE(pool.index(traits_type::construct(1, 1)), pool.free_list());
  197. ASSERT_GE(pool.index(traits_type::construct(2, 1)), pool.free_list());
  198. ASSERT_LT(pool.index(entt::entity{3}), pool.free_list());
  199. ASSERT_LT(pool.index(traits_type::construct(4, 2)), pool.free_list());
  200. ASSERT_GE(pool.index(traits_type::construct(5, 4)), pool.free_list());
  201. ASSERT_EQ(*pool.push(entt::null), traits_type::construct(2, 1));
  202. ASSERT_EQ(*pool.push(traits_type::construct(1, 3)), traits_type::construct(1, 3));
  203. ASSERT_EQ(*pool.push(entt::null), traits_type::construct(5, 4));
  204. ASSERT_EQ(*pool.push(entt::null), entt::entity{7});
  205. }
  206. TEST(StorageEntity, TryGenerateInUse) {
  207. entt::storage<entt::entity> pool;
  208. std::array<entt::entity, 2u> entity{entt::entity{0}, entt::entity{0}};
  209. const entt::entity other{1};
  210. ASSERT_EQ(*pool.push(other), other);
  211. ASSERT_EQ(*pool.push(other), entt::entity{0});
  212. ASSERT_EQ(*pool.push(other), entt::entity{2});
  213. pool.clear();
  214. ASSERT_EQ(*pool.push(other), other);
  215. auto it = pool.push(entity.begin(), entity.end());
  216. ASSERT_EQ(*it, entt::entity{2});
  217. ASSERT_EQ(*(++it), entt::entity{0});
  218. }
  219. TEST(StorageEntity, Patch) {
  220. entt::storage<entt::entity> pool;
  221. const auto entity = pool.generate();
  222. int counter = 0;
  223. auto callback = [&counter]() { ++counter; };
  224. ASSERT_EQ(counter, 0);
  225. pool.patch(entity);
  226. pool.patch(entity, callback);
  227. pool.patch(entity, callback, callback);
  228. ASSERT_EQ(counter, 3);
  229. }
  230. ENTT_DEBUG_TEST(StorageEntityDeathTest, Patch) {
  231. entt::storage<entt::entity> pool;
  232. ASSERT_DEATH(pool.patch(entt::null), "");
  233. }
  234. TEST(StorageEntity, Pack) {
  235. entt::storage<entt::entity> pool;
  236. std::array entity{entt::entity{1}, entt::entity{3}, entt::entity{4}, entt::entity{2}};
  237. pool.push(entity.begin(), entity.end());
  238. pool.erase(entity[3u]);
  239. std::swap(entity[0u], entity[1u]);
  240. const auto to = pool.sort_as(entity.begin() + 1u, entity.end());
  241. auto from = pool.each().cbegin().base();
  242. ASSERT_NE(from, pool.cbegin());
  243. ASSERT_NE(from, pool.cend());
  244. ASSERT_NE(to, pool.cend());
  245. ASSERT_EQ(to + 1u, pool.cend());
  246. ASSERT_EQ(*from++, entity[1u]);
  247. ASSERT_EQ(*from++, entity[2u]);
  248. ASSERT_NE(from, pool.cend());
  249. ASSERT_EQ(*from++, entity[0u]);
  250. ASSERT_EQ(from, pool.cend());
  251. }
  252. TEST(StorageEntity, FreeList) {
  253. entt::storage<entt::entity> pool;
  254. pool.generate(entt::entity{0});
  255. ASSERT_EQ(pool.size(), 1u);
  256. ASSERT_EQ(pool.free_list(), 1u);
  257. pool.free_list(0u);
  258. ASSERT_EQ(pool.size(), 1u);
  259. ASSERT_EQ(pool.free_list(), 0u);
  260. pool.free_list(1u);
  261. ASSERT_EQ(pool.size(), 1u);
  262. ASSERT_EQ(pool.free_list(), 1u);
  263. }
  264. ENTT_DEBUG_TEST(StorageEntityDeathTest, FreeList) {
  265. entt::storage<entt::entity> pool;
  266. pool.generate(entt::entity{0});
  267. ASSERT_DEATH(pool.free_list(2u), "");
  268. }
  269. TEST(StorageEntity, Iterable) {
  270. using iterator = entt::storage<entt::entity>::iterable::iterator;
  271. testing::StaticAssertTypeEq<iterator::value_type, std::tuple<entt::entity>>();
  272. testing::StaticAssertTypeEq<iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  273. testing::StaticAssertTypeEq<iterator::reference, iterator::value_type>();
  274. entt::storage<entt::entity> pool;
  275. pool.generate(entt::entity{1});
  276. pool.generate(entt::entity{3});
  277. pool.generate(entt::entity{4});
  278. pool.erase(entt::entity{3});
  279. auto iterable = pool.each();
  280. iterator end{iterable.begin()};
  281. iterator begin{};
  282. begin = iterable.end();
  283. std::swap(begin, end);
  284. ASSERT_EQ(begin, iterable.begin());
  285. ASSERT_EQ(end, iterable.end());
  286. ASSERT_NE(begin, end);
  287. ASSERT_NE(begin.base(), pool.begin());
  288. ASSERT_EQ(begin.base(), pool.end() - static_cast<iterator::difference_type>(pool.free_list()));
  289. ASSERT_EQ(end.base(), pool.end());
  290. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{4});
  291. ASSERT_EQ(std::get<0>(*begin), entt::entity{4});
  292. ASSERT_EQ(begin++, iterable.begin());
  293. ASSERT_EQ(begin.base(), pool.end() - 1);
  294. ASSERT_EQ(++begin, iterable.end());
  295. ASSERT_EQ(begin.base(), pool.end());
  296. for(auto [entity]: iterable) {
  297. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  298. ASSERT_TRUE(entity != entt::entity{3});
  299. }
  300. }
  301. TEST(StorageEntity, ConstIterable) {
  302. using iterator = entt::storage<entt::entity>::const_iterable::iterator;
  303. testing::StaticAssertTypeEq<iterator::value_type, std::tuple<entt::entity>>();
  304. testing::StaticAssertTypeEq<iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  305. testing::StaticAssertTypeEq<iterator::reference, iterator::value_type>();
  306. entt::storage<entt::entity> pool;
  307. pool.generate(entt::entity{1});
  308. pool.generate(entt::entity{3});
  309. pool.generate(entt::entity{4});
  310. pool.erase(entt::entity{3});
  311. auto iterable = std::as_const(pool).each();
  312. iterator end{iterable.cbegin()};
  313. iterator begin{};
  314. begin = iterable.cend();
  315. std::swap(begin, end);
  316. ASSERT_EQ(begin, iterable.cbegin());
  317. ASSERT_EQ(end, iterable.cend());
  318. ASSERT_NE(begin, end);
  319. ASSERT_NE(begin.base(), pool.begin());
  320. ASSERT_EQ(begin.base(), pool.end() - static_cast<iterator::difference_type>(pool.free_list()));
  321. ASSERT_EQ(end.base(), pool.end());
  322. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{4});
  323. ASSERT_EQ(std::get<0>(*begin), entt::entity{4});
  324. ASSERT_EQ(begin++, iterable.begin());
  325. ASSERT_EQ(begin.base(), pool.end() - 1);
  326. ASSERT_EQ(++begin, iterable.end());
  327. ASSERT_EQ(begin.base(), pool.end());
  328. for(auto [entity]: iterable) {
  329. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  330. ASSERT_TRUE(entity != entt::entity{3});
  331. }
  332. }
  333. TEST(StorageEntity, IterableIteratorConversion) {
  334. entt::storage<entt::entity> pool;
  335. pool.generate(entt::entity{3});
  336. const entt::storage<entt::entity>::iterable::iterator it = pool.each().begin();
  337. entt::storage<entt::entity>::const_iterable::iterator cit = it;
  338. testing::StaticAssertTypeEq<decltype(*it), std::tuple<entt::entity>>();
  339. testing::StaticAssertTypeEq<decltype(*cit), std::tuple<entt::entity>>();
  340. ASSERT_EQ(it, cit);
  341. ASSERT_NE(++cit, it);
  342. }
  343. TEST(StorageEntity, IterableAlgorithmCompatibility) {
  344. entt::storage<entt::entity> pool;
  345. pool.generate(entt::entity{3});
  346. const auto iterable = pool.each();
  347. const auto it = std::find_if(iterable.begin(), iterable.end(), [](auto args) { return std::get<0>(args) == entt::entity{3}; });
  348. ASSERT_EQ(std::get<0>(*it), entt::entity{3});
  349. }
  350. TEST(StorageEntity, ReverseIterable) {
  351. using iterator = entt::storage<entt::entity>::reverse_iterable::iterator;
  352. testing::StaticAssertTypeEq<iterator::value_type, std::tuple<entt::entity>>();
  353. testing::StaticAssertTypeEq<iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  354. testing::StaticAssertTypeEq<iterator::reference, iterator::value_type>();
  355. entt::storage<entt::entity> pool;
  356. pool.generate(entt::entity{1});
  357. pool.generate(entt::entity{3});
  358. pool.generate(entt::entity{4});
  359. pool.erase(entt::entity{3});
  360. auto iterable = pool.reach();
  361. iterator end{iterable.begin()};
  362. iterator begin{};
  363. begin = iterable.end();
  364. std::swap(begin, end);
  365. ASSERT_EQ(begin, iterable.begin());
  366. ASSERT_EQ(end, iterable.end());
  367. ASSERT_NE(begin, end);
  368. ASSERT_EQ(begin.base(), pool.rbegin());
  369. ASSERT_EQ(end.base(), pool.rbegin() + static_cast<iterator::difference_type>(pool.free_list()));
  370. ASSERT_NE(end.base(), pool.rend());
  371. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{1});
  372. ASSERT_EQ(std::get<0>(*begin), entt::entity{1});
  373. ASSERT_EQ(begin++, iterable.begin());
  374. ASSERT_EQ(begin.base(), pool.rbegin() + 1);
  375. ASSERT_EQ(++begin, iterable.end());
  376. ASSERT_EQ(begin.base(), pool.rbegin() + 2);
  377. for(auto [entity]: iterable) {
  378. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  379. ASSERT_TRUE(entity != entt::entity{3});
  380. }
  381. }
  382. TEST(StorageEntity, ReverseConstIterable) {
  383. using iterator = entt::storage<entt::entity>::const_reverse_iterable::iterator;
  384. testing::StaticAssertTypeEq<iterator::value_type, std::tuple<entt::entity>>();
  385. testing::StaticAssertTypeEq<iterator::pointer, entt::input_iterator_pointer<std::tuple<entt::entity>>>();
  386. testing::StaticAssertTypeEq<iterator::reference, iterator::value_type>();
  387. entt::storage<entt::entity> pool;
  388. pool.generate(entt::entity{1});
  389. pool.generate(entt::entity{3});
  390. pool.generate(entt::entity{4});
  391. pool.erase(entt::entity{3});
  392. auto iterable = std::as_const(pool).reach();
  393. iterator end{iterable.cbegin()};
  394. iterator begin{};
  395. begin = iterable.cend();
  396. std::swap(begin, end);
  397. ASSERT_EQ(begin, iterable.cbegin());
  398. ASSERT_EQ(end, iterable.cend());
  399. ASSERT_NE(begin, end);
  400. ASSERT_EQ(begin.base(), pool.rbegin());
  401. ASSERT_EQ(end.base(), pool.rbegin() + static_cast<iterator::difference_type>(pool.free_list()));
  402. ASSERT_NE(end.base(), pool.rend());
  403. ASSERT_EQ(std::get<0>(*begin.operator->().operator->()), entt::entity{1});
  404. ASSERT_EQ(std::get<0>(*begin), entt::entity{1});
  405. ASSERT_EQ(begin++, iterable.begin());
  406. ASSERT_EQ(begin.base(), pool.rbegin() + 1);
  407. ASSERT_EQ(++begin, iterable.end());
  408. ASSERT_EQ(begin.base(), pool.rbegin() + 2);
  409. for(auto [entity]: iterable) {
  410. testing::StaticAssertTypeEq<decltype(entity), entt::entity>();
  411. ASSERT_TRUE(entity != entt::entity{3});
  412. }
  413. }
  414. TEST(StorageEntity, ReverseIterableIteratorConversion) {
  415. entt::storage<entt::entity> pool;
  416. pool.generate(entt::entity{3});
  417. const entt::storage<entt::entity>::reverse_iterable::iterator it = pool.reach().begin();
  418. entt::storage<entt::entity>::const_reverse_iterable::iterator cit = it;
  419. testing::StaticAssertTypeEq<decltype(*it), std::tuple<entt::entity>>();
  420. testing::StaticAssertTypeEq<decltype(*cit), std::tuple<entt::entity>>();
  421. ASSERT_EQ(it, cit);
  422. ASSERT_NE(++cit, it);
  423. }
  424. TEST(StorageEntity, ReverseIterableAlgorithmCompatibility) {
  425. entt::storage<entt::entity> pool;
  426. pool.generate(entt::entity{3});
  427. const auto iterable = pool.reach();
  428. const auto it = std::find_if(iterable.begin(), iterable.end(), [](auto args) { return std::get<0>(args) == entt::entity{3}; });
  429. ASSERT_EQ(std::get<0>(*it), entt::entity{3});
  430. }
  431. TEST(StorageEntity, SortOrdered) {
  432. entt::storage<entt::entity> pool;
  433. const std::array entity{entt::entity{16}, entt::entity{8}, entt::entity{4}, entt::entity{2}, entt::entity{1}};
  434. pool.push(entity.begin(), entity.end());
  435. pool.sort(std::less{});
  436. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), pool.begin(), pool.end()));
  437. }
  438. TEST(StorageEntity, SortReverse) {
  439. entt::storage<entt::entity> pool;
  440. const std::array entity{entt::entity{1}, entt::entity{2}, entt::entity{4}, entt::entity{8}, entt::entity{16}};
  441. pool.push(entity.begin(), entity.end());
  442. pool.sort(std::less{});
  443. ASSERT_TRUE(std::equal(entity.begin(), entity.end(), pool.begin(), pool.end()));
  444. }
  445. TEST(StorageEntity, SortUnordered) {
  446. entt::storage<entt::entity> pool;
  447. const std::array entity{entt::entity{4}, entt::entity{2}, entt::entity{1}, entt::entity{8}, entt::entity{16}};
  448. pool.push(entity.begin(), entity.end());
  449. pool.sort(std::less{});
  450. ASSERT_EQ(pool.data()[0u], entity[4u]);
  451. ASSERT_EQ(pool.data()[1u], entity[3u]);
  452. ASSERT_EQ(pool.data()[2u], entity[0u]);
  453. ASSERT_EQ(pool.data()[3u], entity[1u]);
  454. ASSERT_EQ(pool.data()[4u], entity[2u]);
  455. }
  456. TEST(StorageEntity, SortN) {
  457. entt::storage<entt::entity> pool;
  458. const std::array entity{entt::entity{2}, entt::entity{4}, entt::entity{1}, entt::entity{8}, entt::entity{16}};
  459. pool.push(entity.begin(), entity.end());
  460. pool.sort_n(0u, std::less{});
  461. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), pool.begin(), pool.end()));
  462. pool.sort_n(2u, std::less{});
  463. ASSERT_EQ(pool.data()[0u], entity[1u]);
  464. ASSERT_EQ(pool.data()[1u], entity[0u]);
  465. ASSERT_EQ(pool.data()[2u], entity[2u]);
  466. const auto length = 5u;
  467. pool.sort_n(length, std::less{});
  468. ASSERT_EQ(pool.data()[0u], entity[4u]);
  469. ASSERT_EQ(pool.data()[1u], entity[3u]);
  470. ASSERT_EQ(pool.data()[2u], entity[1u]);
  471. ASSERT_EQ(pool.data()[3u], entity[0u]);
  472. ASSERT_EQ(pool.data()[4u], entity[2u]);
  473. }
  474. TEST(StorageEntity, SortAsDisjoint) {
  475. entt::storage<entt::entity> lhs;
  476. const entt::storage<entt::entity> rhs;
  477. const std::array entity{entt::entity{1}, entt::entity{2}, entt::entity{4}};
  478. lhs.push(entity.begin(), entity.end());
  479. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), lhs.begin(), lhs.end()));
  480. lhs.sort_as(rhs.begin(), rhs.end());
  481. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), lhs.begin(), lhs.end()));
  482. }
  483. TEST(StorageEntity, SortAsOverlap) {
  484. entt::storage<entt::entity> lhs;
  485. entt::storage<entt::entity> rhs;
  486. const std::array lhs_entity{entt::entity{1}, entt::entity{2}, entt::entity{4}};
  487. const std::array rhs_entity{entt::entity{2}};
  488. lhs.push(lhs_entity.begin(), lhs_entity.end());
  489. rhs.push(rhs_entity.begin(), rhs_entity.end());
  490. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  491. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  492. lhs.sort_as(rhs.begin(), rhs.end());
  493. ASSERT_EQ(lhs.data()[0u], lhs_entity[0u]);
  494. ASSERT_EQ(lhs.data()[1u], lhs_entity[2u]);
  495. ASSERT_EQ(lhs.data()[2u], lhs_entity[1u]);
  496. }
  497. TEST(StorageEntity, SortAsOrdered) {
  498. entt::storage<entt::entity> lhs;
  499. entt::storage<entt::entity> rhs;
  500. const std::array lhs_entity{entt::entity{1}, entt::entity{2}, entt::entity{4}, entt::entity{8}, entt::entity{16}};
  501. const std::array rhs_entity{entt::entity{32}, entt::entity{1}, entt::entity{2}, entt::entity{4}, entt::entity{8}, entt::entity{16}};
  502. lhs.push(lhs_entity.begin(), lhs_entity.end());
  503. rhs.push(rhs_entity.begin(), rhs_entity.end());
  504. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  505. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  506. rhs.sort_as(lhs.begin(), lhs.end());
  507. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  508. }
  509. TEST(StorageEntity, SortAsReverse) {
  510. entt::storage<entt::entity> lhs;
  511. entt::storage<entt::entity> rhs;
  512. const std::array lhs_entity{entt::entity{1}, entt::entity{2}, entt::entity{4}, entt::entity{8}, entt::entity{16}};
  513. const std::array rhs_entity{entt::entity{16}, entt::entity{8}, entt::entity{4}, entt::entity{2}, entt::entity{1}, entt::entity{32}};
  514. lhs.push(lhs_entity.begin(), lhs_entity.end());
  515. rhs.push(rhs_entity.begin(), rhs_entity.end());
  516. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  517. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  518. rhs.sort_as(lhs.begin(), lhs.end());
  519. ASSERT_EQ(rhs.data()[0u], rhs_entity[5u]);
  520. ASSERT_EQ(rhs.data()[1u], rhs_entity[4u]);
  521. ASSERT_EQ(rhs.data()[2u], rhs_entity[3u]);
  522. ASSERT_EQ(rhs.data()[3u], rhs_entity[2u]);
  523. ASSERT_EQ(rhs.data()[4u], rhs_entity[1u]);
  524. ASSERT_EQ(rhs.data()[5u], rhs_entity[0u]);
  525. }
  526. TEST(StorageEntity, SortAsUnordered) {
  527. entt::storage<entt::entity> lhs;
  528. entt::storage<entt::entity> rhs;
  529. const std::array lhs_entity{entt::entity{1}, entt::entity{2}, entt::entity{4}, entt::entity{8}, entt::entity{16}};
  530. const std::array rhs_entity{entt::entity{4}, entt::entity{2}, entt::entity{32}, entt::entity{1}, entt::entity{8}, entt::entity{16}};
  531. lhs.push(lhs_entity.begin(), lhs_entity.end());
  532. rhs.push(rhs_entity.begin(), rhs_entity.end());
  533. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  534. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  535. rhs.sort_as(lhs.begin(), lhs.end());
  536. ASSERT_EQ(rhs.data()[0u], rhs_entity[2u]);
  537. ASSERT_EQ(rhs.data()[1u], rhs_entity[3u]);
  538. ASSERT_EQ(rhs.data()[2u], rhs_entity[1u]);
  539. ASSERT_EQ(rhs.data()[3u], rhs_entity[0u]);
  540. ASSERT_EQ(rhs.data()[4u], rhs_entity[4u]);
  541. ASSERT_EQ(rhs.data()[5u], rhs_entity[5u]);
  542. }