storage_entity.cpp 25 KB

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