storage_no_instance.cpp 24 KB

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