sparse_set.cpp 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163
  1. #include <algorithm>
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <functional>
  6. #include <iterator>
  7. #include <memory>
  8. #include <utility>
  9. #include <gtest/gtest.h>
  10. #include <entt/config/config.h>
  11. #include <entt/core/any.hpp>
  12. #include <entt/core/type_info.hpp>
  13. #include <entt/entity/entity.hpp>
  14. #include <entt/entity/sparse_set.hpp>
  15. #include "../common/config.h"
  16. #include "../common/custom_entity.h"
  17. #include "../common/throwing_allocator.hpp"
  18. struct custom_entity_traits {
  19. using value_type = test::custom_entity;
  20. using entity_type = std::uint32_t;
  21. using version_type = std::uint16_t;
  22. static constexpr entity_type entity_mask = 0x3FFFF; // 18b
  23. static constexpr entity_type version_mask = 0x0FFF; // 12b
  24. };
  25. template<>
  26. struct entt::entt_traits<test::custom_entity>: entt::basic_entt_traits<custom_entity_traits> {
  27. static constexpr std::size_t page_size = ENTT_SPARSE_PAGE;
  28. };
  29. template<typename Type>
  30. struct SparseSet: testing::Test {
  31. using type = Type;
  32. inline static const std::array<entt::deletion_policy, 3u> deletion_policy{
  33. entt::deletion_policy::swap_and_pop,
  34. entt::deletion_policy::in_place,
  35. entt::deletion_policy::swap_only,
  36. };
  37. };
  38. template<typename Type>
  39. using SparseSetDeathTest = SparseSet<Type>;
  40. using SparseSetTypes = ::testing::Types<entt::entity, test::custom_entity>;
  41. TYPED_TEST_SUITE(SparseSet, SparseSetTypes, );
  42. TYPED_TEST_SUITE(SparseSetDeathTest, SparseSetTypes, );
  43. TYPED_TEST(SparseSet, Constructors) {
  44. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  45. using allocator_type = typename sparse_set_type::allocator_type;
  46. for(const auto policy: this->deletion_policy) {
  47. sparse_set_type set{};
  48. ASSERT_EQ(set.policy(), entt::deletion_policy::swap_and_pop);
  49. ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
  50. ASSERT_EQ(set.type(), entt::type_id<void>());
  51. set = sparse_set_type{allocator_type{}};
  52. ASSERT_EQ(set.policy(), entt::deletion_policy::swap_and_pop);
  53. ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
  54. ASSERT_EQ(set.type(), entt::type_id<void>());
  55. set = sparse_set_type{policy, allocator_type{}};
  56. ASSERT_EQ(set.policy(), policy);
  57. ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
  58. ASSERT_EQ(set.type(), entt::type_id<void>());
  59. set = sparse_set_type{entt::type_id<int>(), policy, allocator_type{}};
  60. ASSERT_EQ(set.policy(), policy);
  61. ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
  62. ASSERT_EQ(set.type(), entt::type_id<int>());
  63. }
  64. }
  65. TYPED_TEST(SparseSet, Move) {
  66. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  67. using allocator_type = typename sparse_set_type::allocator_type;
  68. using entity_type = typename sparse_set_type::entity_type;
  69. for(const auto policy: this->deletion_policy) {
  70. sparse_set_type set{policy};
  71. set.push(entity_type{1});
  72. static_assert(std::is_move_constructible_v<decltype(set)>, "Move constructible type required");
  73. static_assert(std::is_move_assignable_v<decltype(set)>, "Move assignable type required");
  74. sparse_set_type other{std::move(set)};
  75. ASSERT_TRUE(set.empty()); // NOLINT
  76. ASSERT_FALSE(other.empty());
  77. ASSERT_EQ(set.policy(), policy); // NOLINT
  78. ASSERT_EQ(other.policy(), policy);
  79. ASSERT_EQ(other.index(entity_type{1}), 0u);
  80. sparse_set_type extended{std::move(other), allocator_type{}};
  81. ASSERT_TRUE(other.empty()); // NOLINT
  82. ASSERT_FALSE(extended.empty());
  83. ASSERT_EQ(other.policy(), policy); // NOLINT
  84. ASSERT_EQ(extended.policy(), policy);
  85. ASSERT_EQ(extended.index(entity_type{1}), 0u);
  86. set = std::move(extended);
  87. ASSERT_FALSE(set.empty());
  88. ASSERT_TRUE(other.empty()); // NOLINT
  89. ASSERT_TRUE(extended.empty()); // NOLINT
  90. ASSERT_EQ(set.policy(), policy);
  91. ASSERT_EQ(other.policy(), policy); // NOLINT
  92. ASSERT_EQ(extended.policy(), policy); // NOLINT
  93. ASSERT_EQ(set.index(entity_type{1}), 0u);
  94. other = sparse_set_type{policy};
  95. other.push(entity_type{3});
  96. other = std::move(set);
  97. ASSERT_TRUE(set.empty()); // NOLINT
  98. ASSERT_FALSE(other.empty());
  99. ASSERT_EQ(set.policy(), policy); // NOLINT
  100. ASSERT_EQ(other.policy(), policy);
  101. ASSERT_EQ(other.index(entity_type{1}), 0u);
  102. }
  103. }
  104. TYPED_TEST(SparseSet, Swap) {
  105. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  106. using entity_type = typename sparse_set_type::entity_type;
  107. for(const auto policy: this->deletion_policy) {
  108. sparse_set_type set{policy};
  109. sparse_set_type other{entt::deletion_policy::in_place};
  110. ASSERT_EQ(set.policy(), policy);
  111. ASSERT_EQ(other.policy(), entt::deletion_policy::in_place);
  112. set.push(entity_type{4});
  113. other.push(entity_type{3});
  114. other.push(entity_type{1});
  115. other.erase(entity_type{3});
  116. ASSERT_EQ(set.size(), 1u);
  117. ASSERT_EQ(other.size(), 2u);
  118. set.swap(other);
  119. ASSERT_EQ(set.policy(), entt::deletion_policy::in_place);
  120. ASSERT_EQ(other.policy(), policy);
  121. ASSERT_EQ(set.size(), 2u);
  122. ASSERT_EQ(other.size(), 1u);
  123. ASSERT_EQ(set.index(entity_type{1}), 1u);
  124. ASSERT_EQ(other.index(entity_type{4}), 0u);
  125. }
  126. }
  127. TYPED_TEST(SparseSet, FreeList) {
  128. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  129. using entity_type = typename sparse_set_type::entity_type;
  130. using traits_type = typename sparse_set_type::traits_type;
  131. for(const auto policy: this->deletion_policy) {
  132. sparse_set_type set{policy};
  133. const entity_type entity{1};
  134. const entity_type other{2};
  135. switch(policy) {
  136. case entt::deletion_policy::swap_and_pop: {
  137. ASSERT_EQ(set.size(), 0u);
  138. ASSERT_EQ(set.free_list(), traits_type::to_entity(entt::tombstone));
  139. set.push(other);
  140. set.push(entity);
  141. set.erase(other);
  142. ASSERT_EQ(set.size(), 1u);
  143. ASSERT_EQ(set.free_list(), traits_type::to_entity(entt::tombstone));
  144. set.clear();
  145. ASSERT_EQ(set.size(), 0u);
  146. ASSERT_EQ(set.free_list(), traits_type::to_entity(entt::tombstone));
  147. } break;
  148. case entt::deletion_policy::in_place: {
  149. ASSERT_EQ(set.size(), 0u);
  150. ASSERT_EQ(set.free_list(), traits_type::to_entity(entt::tombstone));
  151. set.push(other);
  152. set.push(entity);
  153. set.erase(other);
  154. ASSERT_EQ(set.size(), 2u);
  155. ASSERT_EQ(set.free_list(), 0u);
  156. set.clear();
  157. ASSERT_EQ(set.size(), 0u);
  158. ASSERT_EQ(set.free_list(), traits_type::to_entity(entt::tombstone));
  159. } break;
  160. case entt::deletion_policy::swap_only: {
  161. ASSERT_EQ(set.size(), 0u);
  162. ASSERT_EQ(set.free_list(), 0u);
  163. set.push(other);
  164. set.push(entity);
  165. set.erase(other);
  166. ASSERT_EQ(set.size(), 2u);
  167. ASSERT_EQ(set.free_list(), 1u);
  168. set.free_list(0u);
  169. ASSERT_EQ(set.size(), 2u);
  170. ASSERT_EQ(set.free_list(), 0u);
  171. set.free_list(2u);
  172. ASSERT_EQ(set.size(), 2u);
  173. ASSERT_EQ(set.free_list(), 2u);
  174. set.clear();
  175. ASSERT_EQ(set.size(), 0u);
  176. ASSERT_EQ(set.free_list(), 0u);
  177. } break;
  178. }
  179. }
  180. }
  181. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, FreeList) {
  182. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  183. using entity_type = typename sparse_set_type::entity_type;
  184. for(const auto policy: this->deletion_policy) {
  185. sparse_set_type set{policy};
  186. set.push(entity_type{3});
  187. switch(policy) {
  188. case entt::deletion_policy::swap_and_pop:
  189. case entt::deletion_policy::in_place: {
  190. ASSERT_DEATH(set.free_list(0u), "");
  191. } break;
  192. case entt::deletion_policy::swap_only: {
  193. ASSERT_NO_THROW(set.free_list(0u));
  194. ASSERT_NO_THROW(set.free_list(1u));
  195. ASSERT_DEATH(set.free_list(2u), "");
  196. } break;
  197. }
  198. }
  199. }
  200. TYPED_TEST(SparseSet, Capacity) {
  201. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  202. for(const auto policy: this->deletion_policy) {
  203. sparse_set_type set{policy};
  204. set.reserve(64);
  205. ASSERT_EQ(set.capacity(), 64u);
  206. ASSERT_TRUE(set.empty());
  207. set.reserve(0);
  208. ASSERT_EQ(set.capacity(), 64u);
  209. ASSERT_TRUE(set.empty());
  210. }
  211. }
  212. TYPED_TEST(SparseSet, Pagination) {
  213. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  214. using entity_type = typename sparse_set_type::entity_type;
  215. using traits_type = typename sparse_set_type::traits_type;
  216. for(const auto policy: this->deletion_policy) {
  217. sparse_set_type set{policy};
  218. ASSERT_EQ(set.extent(), 0u);
  219. set.push(entity_type{traits_type::page_size - 1u});
  220. ASSERT_EQ(set.extent(), traits_type::page_size);
  221. ASSERT_TRUE(set.contains(entity_type{traits_type::page_size - 1u}));
  222. set.push(entity_type{traits_type::page_size});
  223. ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
  224. ASSERT_TRUE(set.contains(entity_type{traits_type::page_size - 1u}));
  225. ASSERT_TRUE(set.contains(entity_type{traits_type::page_size}));
  226. ASSERT_FALSE(set.contains(entity_type{traits_type::page_size + 1u}));
  227. set.erase(entity_type{traits_type::page_size - 1u});
  228. ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
  229. ASSERT_FALSE(set.contains(entity_type{traits_type::page_size - 1u}));
  230. ASSERT_TRUE(set.contains(entity_type{traits_type::page_size}));
  231. set.shrink_to_fit();
  232. set.erase(entity_type{traits_type::page_size});
  233. ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
  234. ASSERT_FALSE(set.contains(entity_type{traits_type::page_size - 1u}));
  235. ASSERT_FALSE(set.contains(entity_type{traits_type::page_size}));
  236. set.shrink_to_fit();
  237. ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
  238. }
  239. }
  240. TYPED_TEST(SparseSet, Contiguous) {
  241. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  242. using entity_type = typename sparse_set_type::entity_type;
  243. for(const auto policy: this->deletion_policy) {
  244. sparse_set_type set{policy};
  245. const entity_type entity{1};
  246. const entity_type other{2};
  247. ASSERT_TRUE(set.contiguous());
  248. set.push(entity);
  249. set.push(other);
  250. ASSERT_TRUE(set.contiguous());
  251. set.erase(entity);
  252. switch(policy) {
  253. case entt::deletion_policy::swap_and_pop: {
  254. ASSERT_TRUE(set.contiguous());
  255. set.clear();
  256. ASSERT_TRUE(set.contiguous());
  257. } break;
  258. case entt::deletion_policy::in_place: {
  259. ASSERT_FALSE(set.contiguous());
  260. set.compact();
  261. ASSERT_TRUE(set.contiguous());
  262. set.push(entity);
  263. set.erase(entity);
  264. ASSERT_FALSE(set.contiguous());
  265. set.clear();
  266. ASSERT_TRUE(set.contiguous());
  267. } break;
  268. case entt::deletion_policy::swap_only: {
  269. ASSERT_TRUE(set.contiguous());
  270. set.clear();
  271. ASSERT_TRUE(set.contiguous());
  272. } break;
  273. }
  274. }
  275. }
  276. TYPED_TEST(SparseSet, Data) {
  277. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  278. using entity_type = typename sparse_set_type::entity_type;
  279. using traits_type = typename sparse_set_type::traits_type;
  280. for(const auto policy: this->deletion_policy) {
  281. sparse_set_type set{policy};
  282. const entity_type entity{1};
  283. const entity_type other{2};
  284. ASSERT_EQ(set.data(), nullptr);
  285. set.push(entity);
  286. set.push(other);
  287. set.erase(entity);
  288. ASSERT_FALSE(set.contains(entity));
  289. switch(policy) {
  290. case entt::deletion_policy::swap_and_pop: {
  291. ASSERT_FALSE(set.contains(traits_type::next(entity)));
  292. ASSERT_EQ(set.size(), 1u);
  293. ASSERT_EQ(set.index(other), 0u);
  294. ASSERT_EQ(set.data()[0u], other);
  295. } break;
  296. case entt::deletion_policy::in_place: {
  297. ASSERT_FALSE(set.contains(traits_type::next(entity)));
  298. ASSERT_EQ(set.size(), 2u);
  299. ASSERT_EQ(set.index(other), 1u);
  300. ASSERT_EQ(set.data()[0u], static_cast<entity_type>(entt::tombstone));
  301. ASSERT_EQ(set.data()[1u], other);
  302. } break;
  303. case entt::deletion_policy::swap_only: {
  304. ASSERT_TRUE(set.contains(traits_type::next(entity)));
  305. ASSERT_EQ(set.size(), 2u);
  306. ASSERT_EQ(set.index(other), 0u);
  307. ASSERT_EQ(set.index(traits_type::next(entity)), 1u);
  308. ASSERT_EQ(set.data()[0u], other);
  309. ASSERT_EQ(set.data()[1u], traits_type::next(entity));
  310. } break;
  311. }
  312. }
  313. }
  314. TYPED_TEST(SparseSet, Bind) {
  315. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  316. for(const auto policy: this->deletion_policy) {
  317. sparse_set_type set{policy};
  318. ASSERT_NO_THROW(set.bind(entt::any{}));
  319. }
  320. }
  321. TYPED_TEST(SparseSet, Iterator) {
  322. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  323. using entity_type = typename sparse_set_type::entity_type;
  324. using iterator = typename sparse_set_type::iterator;
  325. for(const auto policy: this->deletion_policy) {
  326. sparse_set_type set{policy};
  327. testing::StaticAssertTypeEq<typename iterator::value_type, entity_type>();
  328. testing::StaticAssertTypeEq<typename iterator::pointer, const entity_type *>();
  329. testing::StaticAssertTypeEq<typename iterator::reference, const entity_type &>();
  330. set.push(entity_type{3});
  331. iterator end{set.begin()};
  332. iterator begin{};
  333. ASSERT_EQ(end.data(), set.data());
  334. ASSERT_EQ(begin.data(), nullptr);
  335. begin = set.end();
  336. std::swap(begin, end);
  337. ASSERT_EQ(end.data(), set.data());
  338. ASSERT_EQ(begin.data(), set.data());
  339. ASSERT_EQ(begin, set.cbegin());
  340. ASSERT_EQ(end, set.cend());
  341. ASSERT_NE(begin, end);
  342. ASSERT_EQ(begin.index(), 0);
  343. ASSERT_EQ(end.index(), -1);
  344. ASSERT_EQ(begin++, set.begin());
  345. ASSERT_EQ(begin--, set.end());
  346. ASSERT_EQ(begin + 1, set.end());
  347. ASSERT_EQ(end - 1, set.begin());
  348. ASSERT_EQ(++begin, set.end());
  349. ASSERT_EQ(--begin, set.begin());
  350. ASSERT_EQ(begin += 1, set.end());
  351. ASSERT_EQ(begin -= 1, set.begin());
  352. ASSERT_EQ(begin + (end - begin), set.end());
  353. ASSERT_EQ(begin - (begin - end), set.end());
  354. ASSERT_EQ(end - (end - begin), set.begin());
  355. ASSERT_EQ(end + (begin - end), set.begin());
  356. ASSERT_EQ(begin[0u], *set.begin());
  357. ASSERT_LT(begin, end);
  358. ASSERT_LE(begin, set.begin());
  359. ASSERT_GT(end, begin);
  360. ASSERT_GE(end, set.end());
  361. ASSERT_EQ(*begin, entity_type{3});
  362. ASSERT_EQ(*begin.operator->(), entity_type{3});
  363. ASSERT_EQ(begin.index(), 0);
  364. ASSERT_EQ(end.index(), -1);
  365. set.push(entity_type{1});
  366. begin = set.begin();
  367. ASSERT_EQ(begin.index(), 1);
  368. ASSERT_EQ(end.index(), -1);
  369. ASSERT_EQ(begin[0u], entity_type{1});
  370. ASSERT_EQ(begin[1u], entity_type{3});
  371. }
  372. }
  373. TYPED_TEST(SparseSet, ReverseIterator) {
  374. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  375. using entity_type = typename sparse_set_type::entity_type;
  376. using reverse_iterator = typename sparse_set_type::reverse_iterator;
  377. for(const auto policy: this->deletion_policy) {
  378. sparse_set_type set{policy};
  379. testing::StaticAssertTypeEq<typename reverse_iterator::value_type, entity_type>();
  380. testing::StaticAssertTypeEq<typename reverse_iterator::pointer, const entity_type *>();
  381. testing::StaticAssertTypeEq<typename reverse_iterator::reference, const entity_type &>();
  382. set.push(entity_type{3});
  383. reverse_iterator end{set.rbegin()};
  384. reverse_iterator begin{};
  385. begin = set.rend();
  386. std::swap(begin, end);
  387. ASSERT_EQ(begin, set.crbegin());
  388. ASSERT_EQ(end, set.crend());
  389. ASSERT_NE(begin, end);
  390. ASSERT_EQ(begin.base().index(), -1);
  391. ASSERT_EQ(end.base().index(), 0);
  392. ASSERT_EQ(begin++, set.rbegin());
  393. ASSERT_EQ(begin--, set.rend());
  394. ASSERT_EQ(begin + 1, set.rend());
  395. ASSERT_EQ(end - 1, set.rbegin());
  396. ASSERT_EQ(++begin, set.rend());
  397. ASSERT_EQ(--begin, set.rbegin());
  398. ASSERT_EQ(begin += 1, set.rend());
  399. ASSERT_EQ(begin -= 1, set.rbegin());
  400. ASSERT_EQ(begin + (end - begin), set.rend());
  401. ASSERT_EQ(begin - (begin - end), set.rend());
  402. ASSERT_EQ(end - (end - begin), set.rbegin());
  403. ASSERT_EQ(end + (begin - end), set.rbegin());
  404. ASSERT_EQ(begin[0u], *set.rbegin());
  405. ASSERT_LT(begin, end);
  406. ASSERT_LE(begin, set.rbegin());
  407. ASSERT_GT(end, begin);
  408. ASSERT_GE(end, set.rend());
  409. ASSERT_EQ(*begin, entity_type{3});
  410. ASSERT_EQ(*begin.operator->(), entity_type{3});
  411. ASSERT_EQ(begin.base().index(), -1);
  412. ASSERT_EQ(end.base().index(), 0);
  413. set.push(entity_type{1});
  414. end = set.rend();
  415. ASSERT_EQ(begin.base().index(), -1);
  416. ASSERT_EQ(end.base().index(), 1);
  417. ASSERT_EQ(begin[0u], entity_type{3});
  418. ASSERT_EQ(begin[1u], entity_type{1});
  419. }
  420. }
  421. TYPED_TEST(SparseSet, ScopedIterator) {
  422. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  423. using entity_type = typename sparse_set_type::entity_type;
  424. for(const auto policy: this->deletion_policy) {
  425. sparse_set_type set{policy};
  426. const entity_type entity{1};
  427. const entity_type other{2};
  428. set.push(entity);
  429. set.push(other);
  430. set.erase(entity);
  431. switch(policy) {
  432. case entt::deletion_policy::swap_and_pop:
  433. case entt::deletion_policy::in_place: {
  434. ASSERT_EQ(set.begin(), set.begin(0));
  435. ASSERT_EQ(set.end(), set.end(0));
  436. ASSERT_NE(set.cbegin(0), set.cend(0));
  437. } break;
  438. case entt::deletion_policy::swap_only: {
  439. ASSERT_NE(set.begin(), set.begin(0));
  440. ASSERT_EQ(set.begin() + 1, set.begin(0));
  441. ASSERT_EQ(set.end(), set.end(0));
  442. ASSERT_NE(set.cbegin(0), set.cend(0));
  443. set.free_list(0);
  444. ASSERT_NE(set.begin(), set.begin(0));
  445. ASSERT_EQ(set.begin() + 2, set.begin(0));
  446. ASSERT_EQ(set.end(), set.end(0));
  447. ASSERT_EQ(set.cbegin(0), set.cend(0));
  448. set.free_list(2);
  449. ASSERT_EQ(set.begin(), set.begin(0));
  450. ASSERT_EQ(set.end(), set.end(0));
  451. ASSERT_NE(set.cbegin(0), set.cend(0));
  452. } break;
  453. }
  454. }
  455. }
  456. TYPED_TEST(SparseSet, ScopedReverseIterator) {
  457. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  458. using entity_type = typename sparse_set_type::entity_type;
  459. for(const auto policy: this->deletion_policy) {
  460. sparse_set_type set{policy};
  461. const entity_type entity{1};
  462. const entity_type other{2};
  463. set.push(entity);
  464. set.push(other);
  465. set.erase(entity);
  466. switch(policy) {
  467. case entt::deletion_policy::swap_and_pop:
  468. case entt::deletion_policy::in_place: {
  469. ASSERT_EQ(set.rbegin(), set.rbegin(0));
  470. ASSERT_EQ(set.rend(), set.rend(0));
  471. ASSERT_NE(set.crbegin(0), set.crend(0));
  472. } break;
  473. case entt::deletion_policy::swap_only: {
  474. ASSERT_EQ(set.rbegin(), set.rbegin(0));
  475. ASSERT_NE(set.rend(), set.rend(0));
  476. ASSERT_EQ(set.rend() - 1, set.rend(0));
  477. ASSERT_NE(set.crbegin(0), set.crend(0));
  478. set.free_list(0);
  479. ASSERT_EQ(set.rbegin(), set.rbegin(0));
  480. ASSERT_NE(set.rend(), set.rend(0));
  481. ASSERT_EQ(set.rend() - 2, set.rend(0));
  482. ASSERT_EQ(set.crbegin(0), set.crend(0));
  483. set.free_list(2);
  484. ASSERT_EQ(set.rbegin(), set.rbegin(0));
  485. ASSERT_EQ(set.rend(), set.rend(0));
  486. ASSERT_NE(set.crbegin(0), set.crend(0));
  487. } break;
  488. }
  489. }
  490. }
  491. TYPED_TEST(SparseSet, Find) {
  492. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  493. using entity_type = typename sparse_set_type::entity_type;
  494. using traits_type = typename sparse_set_type::traits_type;
  495. for(const auto policy: this->deletion_policy) {
  496. sparse_set_type set{policy};
  497. ASSERT_EQ(set.find(entt::tombstone), set.cend());
  498. ASSERT_EQ(set.find(entt::null), set.cend());
  499. const entity_type entity{3};
  500. const entity_type other{traits_type::construct(2, 1)};
  501. ASSERT_EQ(set.find(entity), set.cend());
  502. ASSERT_EQ(set.find(other), set.cend());
  503. set.push(entity);
  504. set.push(other);
  505. ASSERT_NE(set.find(entity), set.end());
  506. ASSERT_EQ(set.find(traits_type::next(entity)), set.end());
  507. ASSERT_EQ(*set.find(other), other);
  508. }
  509. }
  510. TYPED_TEST(SparseSet, FindErased) {
  511. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  512. using entity_type = typename sparse_set_type::entity_type;
  513. using traits_type = typename sparse_set_type::traits_type;
  514. for(const auto policy: this->deletion_policy) {
  515. sparse_set_type set{policy};
  516. const entity_type entity{3};
  517. set.push(entity);
  518. set.erase(entity);
  519. switch(policy) {
  520. case entt::deletion_policy::swap_and_pop:
  521. case entt::deletion_policy::in_place: {
  522. ASSERT_EQ(set.find(entity), set.cend());
  523. ASSERT_EQ(set.find(traits_type::next(entity)), set.cend());
  524. } break;
  525. case entt::deletion_policy::swap_only: {
  526. ASSERT_EQ(set.find(entity), set.cend());
  527. ASSERT_NE(set.find(traits_type::next(entity)), set.cend());
  528. } break;
  529. }
  530. }
  531. }
  532. TYPED_TEST(SparseSet, Contains) {
  533. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  534. using entity_type = typename sparse_set_type::entity_type;
  535. using traits_type = typename sparse_set_type::traits_type;
  536. for(const auto policy: this->deletion_policy) {
  537. sparse_set_type set{policy};
  538. const entity_type entity{3};
  539. const entity_type other{traits_type::construct(4, 1)};
  540. set.push(entity);
  541. set.push(other);
  542. ASSERT_FALSE(set.contains(entt::null));
  543. ASSERT_FALSE(set.contains(entt::tombstone));
  544. ASSERT_TRUE(set.contains(entity));
  545. ASSERT_TRUE(set.contains(other));
  546. ASSERT_FALSE(set.contains(entity_type{1}));
  547. ASSERT_FALSE(set.contains(traits_type::construct(3, 1)));
  548. ASSERT_FALSE(set.contains(traits_type::construct(4, traits_type::to_version(entt::tombstone))));
  549. set.erase(entity);
  550. set.remove(other);
  551. ASSERT_FALSE(set.contains(entity));
  552. ASSERT_FALSE(set.contains(other));
  553. if constexpr(traits_type::to_integral(entt::tombstone) != ~typename traits_type::entity_type{}) {
  554. // test reserved bits, if any
  555. constexpr entity_type reserved{traits_type::to_integral(entity) | (traits_type::to_integral(entt::tombstone) + 1u)};
  556. ASSERT_NE(entity, reserved);
  557. set.push(reserved);
  558. ASSERT_TRUE(set.contains(entity));
  559. ASSERT_TRUE(set.contains(reserved));
  560. ASSERT_NE(*set.find(entity), entity);
  561. ASSERT_EQ(*set.find(entity), reserved);
  562. set.bump(entity);
  563. ASSERT_TRUE(set.contains(entity));
  564. ASSERT_TRUE(set.contains(reserved));
  565. ASSERT_NE(*set.find(reserved), reserved);
  566. ASSERT_EQ(*set.find(reserved), entity);
  567. set.erase(reserved);
  568. ASSERT_FALSE(set.contains(entity));
  569. ASSERT_FALSE(set.contains(reserved));
  570. ASSERT_EQ(set.find(reserved), set.end());
  571. }
  572. }
  573. }
  574. TYPED_TEST(SparseSet, ContainsErased) {
  575. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  576. using entity_type = typename sparse_set_type::entity_type;
  577. using traits_type = typename sparse_set_type::traits_type;
  578. for(const auto policy: this->deletion_policy) {
  579. sparse_set_type set{policy};
  580. const entity_type entity{3};
  581. set.push(entity);
  582. set.erase(entity);
  583. switch(policy) {
  584. case entt::deletion_policy::swap_and_pop: {
  585. ASSERT_EQ(set.size(), 0u);
  586. ASSERT_FALSE(set.contains(entity));
  587. ASSERT_FALSE(set.contains(traits_type::next(entity)));
  588. } break;
  589. case entt::deletion_policy::in_place: {
  590. ASSERT_EQ(set.size(), 1u);
  591. ASSERT_FALSE(set.contains(entity));
  592. ASSERT_FALSE(set.contains(traits_type::next(entity)));
  593. } break;
  594. case entt::deletion_policy::swap_only: {
  595. ASSERT_EQ(set.size(), 1u);
  596. ASSERT_FALSE(set.contains(entity));
  597. ASSERT_TRUE(set.contains(traits_type::next(entity)));
  598. } break;
  599. }
  600. }
  601. }
  602. TYPED_TEST(SparseSet, Current) {
  603. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  604. using entity_type = typename sparse_set_type::entity_type;
  605. using traits_type = typename sparse_set_type::traits_type;
  606. for(const auto policy: this->deletion_policy) {
  607. sparse_set_type set{policy};
  608. ASSERT_EQ(set.current(entt::tombstone), traits_type::to_version(entt::tombstone));
  609. ASSERT_EQ(set.current(entt::null), traits_type::to_version(entt::tombstone));
  610. const entity_type entity{traits_type::construct(0, 0)};
  611. const entity_type other{traits_type::construct(3, 3)};
  612. ASSERT_EQ(set.current(entity), traits_type::to_version(entt::tombstone));
  613. ASSERT_EQ(set.current(other), traits_type::to_version(entt::tombstone));
  614. set.push(entity);
  615. set.push(other);
  616. ASSERT_NE(set.current(entity), traits_type::to_version(entt::tombstone));
  617. ASSERT_NE(set.current(other), traits_type::to_version(entt::tombstone));
  618. ASSERT_EQ(set.current(traits_type::next(entity)), traits_type::to_version(entity));
  619. ASSERT_EQ(set.current(traits_type::next(other)), traits_type::to_version(other));
  620. }
  621. }
  622. TYPED_TEST(SparseSet, CurrentErased) {
  623. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  624. using entity_type = typename sparse_set_type::entity_type;
  625. using traits_type = typename sparse_set_type::traits_type;
  626. for(const auto policy: this->deletion_policy) {
  627. sparse_set_type set{policy};
  628. const entity_type entity{traits_type::construct(3, 3)};
  629. set.push(entity);
  630. set.erase(entity);
  631. switch(policy) {
  632. case entt::deletion_policy::swap_and_pop: {
  633. ASSERT_EQ(set.size(), 0u);
  634. ASSERT_EQ(set.current(entity), traits_type::to_version(entt::tombstone));
  635. } break;
  636. case entt::deletion_policy::in_place: {
  637. ASSERT_EQ(set.size(), 1u);
  638. ASSERT_EQ(set.current(entity), traits_type::to_version(entt::tombstone));
  639. } break;
  640. case entt::deletion_policy::swap_only: {
  641. ASSERT_EQ(set.size(), 1u);
  642. ASSERT_EQ(set.current(entity), traits_type::to_version(traits_type::next(entity)));
  643. } break;
  644. }
  645. }
  646. }
  647. TYPED_TEST(SparseSet, Index) {
  648. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  649. using entity_type = typename sparse_set_type::entity_type;
  650. using traits_type = typename sparse_set_type::traits_type;
  651. for(const auto policy: this->deletion_policy) {
  652. sparse_set_type set{policy};
  653. const entity_type entity{1};
  654. const entity_type other{2};
  655. set.push(entity);
  656. set.push(other);
  657. ASSERT_EQ(set.index(entity), 0u);
  658. ASSERT_EQ(set.index(other), 1u);
  659. set.erase(entity);
  660. switch(policy) {
  661. case entt::deletion_policy::swap_and_pop: {
  662. ASSERT_EQ(set.size(), 1u);
  663. ASSERT_FALSE(set.contains(traits_type::next(entity)));
  664. ASSERT_EQ(set.index(other), 0u);
  665. } break;
  666. case entt::deletion_policy::in_place: {
  667. ASSERT_EQ(set.size(), 2u);
  668. ASSERT_FALSE(set.contains(traits_type::next(entity)));
  669. ASSERT_EQ(set.index(other), 1u);
  670. } break;
  671. case entt::deletion_policy::swap_only: {
  672. ASSERT_EQ(set.size(), 2u);
  673. ASSERT_TRUE(set.contains(traits_type::next(entity)));
  674. ASSERT_EQ(set.index(traits_type::next(entity)), 1u);
  675. ASSERT_EQ(set.index(other), 0u);
  676. } break;
  677. }
  678. }
  679. }
  680. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Index) {
  681. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  682. using entity_type = typename sparse_set_type::entity_type;
  683. for(const auto policy: this->deletion_policy) {
  684. const sparse_set_type set{policy};
  685. // index works the same in all cases, test only once
  686. switch(policy) {
  687. case entt::deletion_policy::swap_and_pop:
  688. ASSERT_DEATH([[maybe_unused]] const auto pos = set.index(entity_type{1}), "");
  689. break;
  690. case entt::deletion_policy::in_place:
  691. case entt::deletion_policy::swap_only:
  692. SUCCEED();
  693. break;
  694. }
  695. }
  696. }
  697. TYPED_TEST(SparseSet, Indexing) {
  698. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  699. using entity_type = typename sparse_set_type::entity_type;
  700. for(const auto policy: this->deletion_policy) {
  701. sparse_set_type set{policy};
  702. const std::array entity{entity_type{1}, entity_type{2}};
  703. set.push(entity.begin(), entity.end());
  704. ASSERT_EQ(set[0u], entity[0u]);
  705. ASSERT_EQ(set[1u], entity[1u]);
  706. }
  707. }
  708. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Indexing) {
  709. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  710. for(const auto policy: this->deletion_policy) {
  711. const sparse_set_type set{policy};
  712. // operator[] works the same in all cases, test only once
  713. switch(policy) {
  714. case entt::deletion_policy::swap_and_pop:
  715. ASSERT_DEATH([[maybe_unused]] auto value = set[0u], "");
  716. break;
  717. case entt::deletion_policy::in_place:
  718. case entt::deletion_policy::swap_only:
  719. SUCCEED();
  720. break;
  721. }
  722. }
  723. }
  724. TYPED_TEST(SparseSet, Value) {
  725. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  726. using entity_type = typename sparse_set_type::entity_type;
  727. for(const auto policy: this->deletion_policy) {
  728. sparse_set_type set{policy};
  729. const entity_type entity{3};
  730. set.push(entity);
  731. ASSERT_EQ(set.value(entity), nullptr);
  732. ASSERT_EQ(std::as_const(set).value(entity), nullptr);
  733. }
  734. }
  735. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Value) {
  736. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  737. using entity_type = typename sparse_set_type::entity_type;
  738. for(const auto policy: this->deletion_policy) {
  739. sparse_set_type set{policy};
  740. // value works the same in all cases, test only once
  741. switch(policy) {
  742. case entt::deletion_policy::swap_and_pop:
  743. ASSERT_DEATH([[maybe_unused]] auto *value = set.value(entity_type{3}), "");
  744. break;
  745. case entt::deletion_policy::in_place:
  746. case entt::deletion_policy::swap_only:
  747. SUCCEED();
  748. break;
  749. }
  750. }
  751. }
  752. TYPED_TEST(SparseSet, Push) {
  753. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  754. using entity_type = typename sparse_set_type::entity_type;
  755. for(const auto policy: this->deletion_policy) {
  756. sparse_set_type set{policy};
  757. const std::array entity{entity_type{1}, entity_type{3}};
  758. switch(policy) {
  759. case entt::deletion_policy::swap_and_pop: {
  760. ASSERT_EQ(set.size(), 0u);
  761. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  762. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  763. ASSERT_EQ(set.size(), 2u);
  764. ASSERT_EQ(set.index(entity[0u]), 0u);
  765. ASSERT_EQ(set.index(entity[1u]), 1u);
  766. set.erase(entity.begin(), entity.end());
  767. ASSERT_EQ(set.size(), 0u);
  768. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  769. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  770. ASSERT_EQ(set.size(), 2u);
  771. ASSERT_EQ(set.index(entity[0u]), 0u);
  772. ASSERT_EQ(set.index(entity[1u]), 1u);
  773. set.erase(entity.begin(), entity.end());
  774. ASSERT_EQ(set.size(), 0u);
  775. ASSERT_EQ(*set.push(entity.begin(), entity.end()), entity[0u]);
  776. ASSERT_EQ(set.size(), 2u);
  777. ASSERT_EQ(set.index(entity[0u]), 0u);
  778. ASSERT_EQ(set.index(entity[1u]), 1u);
  779. set.erase(entity.begin(), entity.end());
  780. ASSERT_EQ(set.size(), 0u);
  781. ASSERT_EQ(set.push(entity.begin(), entity.begin()), set.end());
  782. ASSERT_EQ(set.size(), 0u);
  783. } break;
  784. case entt::deletion_policy::in_place: {
  785. ASSERT_EQ(set.size(), 0u);
  786. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  787. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  788. ASSERT_EQ(set.size(), 2u);
  789. ASSERT_EQ(set.index(entity[0u]), 0u);
  790. ASSERT_EQ(set.index(entity[1u]), 1u);
  791. set.erase(entity.begin(), entity.end());
  792. ASSERT_EQ(set.size(), 2u);
  793. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  794. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  795. ASSERT_EQ(set.size(), 2u);
  796. ASSERT_EQ(set.index(entity[0u]), 1u);
  797. ASSERT_EQ(set.index(entity[1u]), 0u);
  798. set.erase(entity.begin(), entity.end());
  799. ASSERT_EQ(set.size(), 2u);
  800. ASSERT_EQ(*set.push(entity.begin(), entity.end()), entity[0u]);
  801. ASSERT_EQ(set.size(), 4u);
  802. ASSERT_EQ(set.index(entity[0u]), 2u);
  803. ASSERT_EQ(set.index(entity[1u]), 3u);
  804. set.erase(entity.begin(), entity.end());
  805. set.compact();
  806. ASSERT_EQ(set.size(), 0u);
  807. ASSERT_EQ(set.push(entity.begin(), entity.begin()), set.end());
  808. ASSERT_EQ(set.size(), 0u);
  809. } break;
  810. case entt::deletion_policy::swap_only: {
  811. ASSERT_EQ(set.size(), 0u);
  812. ASSERT_EQ(set.free_list(), 0u);
  813. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  814. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  815. ASSERT_EQ(set.free_list(), 2u);
  816. ASSERT_EQ(set.size(), 2u);
  817. ASSERT_EQ(set.index(entity[0u]), 0u);
  818. ASSERT_EQ(set.index(entity[1u]), 1u);
  819. set.erase(entity.begin(), entity.end());
  820. ASSERT_EQ(set.size(), 2u);
  821. ASSERT_EQ(set.free_list(), 0u);
  822. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  823. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  824. ASSERT_EQ(set.free_list(), 2u);
  825. ASSERT_EQ(set.size(), 2u);
  826. ASSERT_EQ(set.index(entity[0u]), 0u);
  827. ASSERT_EQ(set.index(entity[1u]), 1u);
  828. set.erase(entity.begin(), entity.end());
  829. ASSERT_EQ(set.size(), 2u);
  830. ASSERT_EQ(set.free_list(), 0u);
  831. ASSERT_EQ(*set.push(entity.begin(), entity.end()), entity[0u]);
  832. ASSERT_EQ(set.free_list(), 2u);
  833. ASSERT_EQ(set.size(), 2u);
  834. ASSERT_EQ(set.index(entity[0u]), 0u);
  835. ASSERT_EQ(set.index(entity[1u]), 1u);
  836. set.erase(entity.begin(), entity.end());
  837. ASSERT_EQ(set.size(), 2u);
  838. ASSERT_EQ(set.free_list(), 0u);
  839. ASSERT_EQ(set.push(entity.begin(), entity.begin()), set.end());
  840. ASSERT_EQ(set.free_list(), 0u);
  841. ASSERT_EQ(set.size(), 2u);
  842. } break;
  843. }
  844. }
  845. }
  846. TYPED_TEST(SparseSet, PushOutOfBounds) {
  847. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  848. using entity_type = typename sparse_set_type::entity_type;
  849. using traits_type = typename sparse_set_type::traits_type;
  850. for(const auto policy: this->deletion_policy) {
  851. sparse_set_type set{policy};
  852. const std::array entity{entity_type{0}, entity_type{traits_type::page_size}};
  853. ASSERT_EQ(*set.push(entity[0u]), entity[0u]);
  854. ASSERT_EQ(set.extent(), traits_type::page_size);
  855. ASSERT_EQ(set.index(entity[0u]), 0u);
  856. set.erase(entity[0u]);
  857. ASSERT_EQ(*set.push(entity[1u]), entity[1u]);
  858. ASSERT_EQ(set.extent(), 2u * traits_type::page_size);
  859. ASSERT_EQ(set.index(entity[1u]), 0u);
  860. }
  861. }
  862. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Push) {
  863. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  864. using entity_type = typename sparse_set_type::entity_type;
  865. for(const auto policy: this->deletion_policy) {
  866. sparse_set_type set{policy};
  867. const std::array entity{entity_type{1}, entity_type{3}};
  868. set.push(entity.begin(), entity.end());
  869. ASSERT_DEATH(set.push(entity[0u]), "");
  870. ASSERT_DEATH(set.push(entity.begin(), entity.end()), "");
  871. }
  872. }
  873. TYPED_TEST(SparseSet, Bump) {
  874. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  875. using entity_type = typename sparse_set_type::entity_type;
  876. using traits_type = typename sparse_set_type::traits_type;
  877. for(const auto policy: this->deletion_policy) {
  878. sparse_set_type set{policy};
  879. const std::array entity{entity_type{1}, entity_type{3}, traits_type::construct(2, 4)};
  880. set.push(entity.begin(), entity.end());
  881. ASSERT_EQ(set.current(entity[0u]), 0u);
  882. ASSERT_EQ(set.current(entity[1u]), 0u);
  883. ASSERT_EQ(set.current(entity[2u]), 4u);
  884. ASSERT_EQ(set.bump(entity[0u]), 0u);
  885. ASSERT_EQ(set.bump(traits_type::construct(traits_type::to_entity(entity[1u]), 1)), 1u);
  886. ASSERT_EQ(set.bump(traits_type::construct(traits_type::to_entity(entity[2u]), 0)), 0u);
  887. ASSERT_EQ(set.current(entity[0u]), 0u);
  888. ASSERT_EQ(set.current(entity[1u]), 1u);
  889. ASSERT_EQ(set.current(entity[2u]), 0u);
  890. }
  891. }
  892. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Bump) {
  893. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  894. using entity_type = typename sparse_set_type::entity_type;
  895. for(const auto policy: this->deletion_policy) {
  896. sparse_set_type set{policy};
  897. // bump works the same in all cases, test only once
  898. switch(policy) {
  899. case entt::deletion_policy::swap_and_pop:
  900. ASSERT_DEATH(set.bump(entt::null), "");
  901. ASSERT_DEATH(set.bump(entt::tombstone), "");
  902. ASSERT_DEATH(set.bump(entity_type{3}), "");
  903. break;
  904. case entt::deletion_policy::in_place:
  905. case entt::deletion_policy::swap_only:
  906. SUCCEED();
  907. break;
  908. }
  909. }
  910. }
  911. TYPED_TEST(SparseSet, Erase) {
  912. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  913. using entity_type = typename sparse_set_type::entity_type;
  914. using traits_type = typename sparse_set_type::traits_type;
  915. for(const auto policy: this->deletion_policy) {
  916. sparse_set_type set{policy};
  917. const std::array entity{entity_type{1}, entity_type{3}, traits_type::construct(2, 4)};
  918. switch(policy) {
  919. case entt::deletion_policy::swap_and_pop: {
  920. ASSERT_EQ(set.size(), 0u);
  921. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  922. set.push(entity.begin(), entity.end());
  923. set.erase(set.begin(), set.end());
  924. ASSERT_EQ(set.size(), 0u);
  925. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  926. set.push(entity.begin(), entity.end());
  927. set.erase(entity.begin(), entity.begin() + 2u);
  928. ASSERT_EQ(set.size(), 1u);
  929. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  930. ASSERT_TRUE(set.contains(entity[2u]));
  931. set.erase(entity[2u]);
  932. ASSERT_EQ(set.size(), 0u);
  933. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  934. ASSERT_FALSE(set.contains(entity[2u]));
  935. } break;
  936. case entt::deletion_policy::in_place: {
  937. ASSERT_EQ(set.size(), 0u);
  938. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  939. set.push(entity.begin(), entity.end());
  940. set.erase(set.begin(), set.end());
  941. ASSERT_EQ(set.size(), 3u);
  942. ASSERT_EQ(set.free_list(), 0u);
  943. ASSERT_EQ(set.current(entity[0u]), traits_type::to_version(entt::tombstone));
  944. ASSERT_EQ(set.current(entity[1u]), traits_type::to_version(entt::tombstone));
  945. ASSERT_EQ(set.current(entity[2u]), traits_type::to_version(entt::tombstone));
  946. set.push(entity[0u]);
  947. set.push(entity.begin() + 1u, entity.end());
  948. set.erase(entity.begin(), entity.begin() + 2u);
  949. ASSERT_EQ(set.size(), 5u);
  950. ASSERT_EQ(set.free_list(), 3u);
  951. ASSERT_EQ(set.current(entity[0u]), traits_type::to_version(entt::tombstone));
  952. ASSERT_EQ(set.current(entity[1u]), traits_type::to_version(entt::tombstone));
  953. ASSERT_TRUE(set.contains(entity[2u]));
  954. set.erase(entity[2u]);
  955. ASSERT_EQ(set.size(), 5u);
  956. ASSERT_EQ(set.free_list(), 4u);
  957. ASSERT_FALSE(set.contains(entity[2u]));
  958. } break;
  959. case entt::deletion_policy::swap_only: {
  960. ASSERT_EQ(set.size(), 0u);
  961. ASSERT_EQ(set.free_list(), 0u);
  962. set.push(entity.begin(), entity.end());
  963. set.erase(set.begin(), set.end());
  964. ASSERT_EQ(set.size(), 3u);
  965. ASSERT_EQ(set.free_list(), 0u);
  966. ASSERT_TRUE(set.contains(traits_type::next(entity[0u])));
  967. ASSERT_TRUE(set.contains(traits_type::next(entity[1u])));
  968. ASSERT_TRUE(set.contains(traits_type::next(entity[2u])));
  969. set.push(entity.begin(), entity.end());
  970. set.erase(entity.begin(), entity.begin() + 2u);
  971. ASSERT_EQ(set.size(), 3u);
  972. ASSERT_EQ(set.free_list(), 1u);
  973. ASSERT_TRUE(set.contains(traits_type::next(entity[0u])));
  974. ASSERT_TRUE(set.contains(traits_type::next(entity[1u])));
  975. ASSERT_TRUE(set.contains(entity[2u]));
  976. ASSERT_LT(set.index(entity[2u]), set.free_list());
  977. set.erase(entity[2u]);
  978. ASSERT_EQ(set.size(), 3u);
  979. ASSERT_EQ(set.free_list(), 0u);
  980. ASSERT_TRUE(set.contains(traits_type::next(entity[2u])));
  981. } break;
  982. }
  983. }
  984. }
  985. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Erase) {
  986. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  987. using entity_type = typename sparse_set_type::entity_type;
  988. using traits_type = typename sparse_set_type::traits_type;
  989. for(const auto policy: this->deletion_policy) {
  990. sparse_set_type set{policy};
  991. const std::array entity{entity_type{3}, traits_type::construct(2, 4)};
  992. ASSERT_DEATH(set.erase(entity.begin(), entity.end()), "");
  993. ASSERT_DEATH(set.erase(entity.begin(), entity.begin() + 2u), "");
  994. }
  995. }
  996. TYPED_TEST(SparseSet, CrossErase) {
  997. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  998. using entity_type = typename sparse_set_type::entity_type;
  999. for(const auto policy: this->deletion_policy) {
  1000. sparse_set_type set{policy};
  1001. sparse_set_type other{policy};
  1002. const std::array entity{entity_type{1}, entity_type{3}};
  1003. set.push(entity.begin(), entity.end());
  1004. other.push(entity[1u]);
  1005. set.erase(other.begin(), other.end());
  1006. ASSERT_TRUE(set.contains(entity[0u]));
  1007. ASSERT_FALSE(set.contains(entity[1u]));
  1008. ASSERT_EQ(set.data()[0u], entity[0u]);
  1009. }
  1010. }
  1011. TYPED_TEST(SparseSet, Remove) {
  1012. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1013. using entity_type = typename sparse_set_type::entity_type;
  1014. using traits_type = typename sparse_set_type::traits_type;
  1015. for(const auto policy: this->deletion_policy) {
  1016. sparse_set_type set{policy};
  1017. const std::array entity{entity_type{1}, entity_type{3}, traits_type::construct(2, 4)};
  1018. switch(policy) {
  1019. case entt::deletion_policy::swap_and_pop: {
  1020. ASSERT_EQ(set.size(), 0u);
  1021. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1022. ASSERT_EQ(set.remove(entity.begin(), entity.end()), 0u);
  1023. ASSERT_FALSE(set.remove(entity[1u]));
  1024. ASSERT_EQ(set.size(), 0u);
  1025. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1026. set.push(entity.begin(), entity.end());
  1027. ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
  1028. ASSERT_EQ(set.size(), 0u);
  1029. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1030. set.push(entity.begin(), entity.end());
  1031. ASSERT_EQ(set.remove(entity.begin(), entity.begin() + 2u), 2u);
  1032. ASSERT_EQ(set.size(), 1u);
  1033. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1034. ASSERT_TRUE(set.contains(entity[2u]));
  1035. ASSERT_TRUE(set.remove(entity[2u]));
  1036. ASSERT_FALSE(set.remove(entity[2u]));
  1037. ASSERT_EQ(set.size(), 0u);
  1038. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1039. ASSERT_FALSE(set.contains(entity[2u]));
  1040. } break;
  1041. case entt::deletion_policy::in_place: {
  1042. ASSERT_EQ(set.size(), 0u);
  1043. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1044. ASSERT_EQ(set.remove(entity.begin(), entity.end()), 0u);
  1045. ASSERT_FALSE(set.remove(entity[1u]));
  1046. ASSERT_EQ(set.size(), 0u);
  1047. ASSERT_EQ(set.free_list(), traits_type::entity_mask);
  1048. set.push(entity.begin(), entity.end());
  1049. ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
  1050. ASSERT_EQ(set.size(), 3u);
  1051. ASSERT_EQ(set.free_list(), 0u);
  1052. ASSERT_EQ(set.current(entity[0u]), traits_type::to_version(entt::tombstone));
  1053. ASSERT_EQ(set.current(entity[1u]), traits_type::to_version(entt::tombstone));
  1054. ASSERT_EQ(set.current(entity[2u]), traits_type::to_version(entt::tombstone));
  1055. set.push(entity[0u]);
  1056. set.push(entity.begin() + 1u, entity.end());
  1057. ASSERT_EQ(set.remove(entity.begin(), entity.begin() + 2u), 2u);
  1058. ASSERT_EQ(set.size(), 5u);
  1059. ASSERT_EQ(set.free_list(), 3u);
  1060. ASSERT_EQ(set.current(entity[0u]), traits_type::to_version(entt::tombstone));
  1061. ASSERT_EQ(set.current(entity[1u]), traits_type::to_version(entt::tombstone));
  1062. ASSERT_TRUE(set.contains(entity[2u]));
  1063. ASSERT_TRUE(set.remove(entity[2u]));
  1064. ASSERT_FALSE(set.remove(entity[2u]));
  1065. ASSERT_EQ(set.size(), 5u);
  1066. ASSERT_EQ(set.free_list(), 4u);
  1067. ASSERT_FALSE(set.contains(entity[2u]));
  1068. } break;
  1069. case entt::deletion_policy::swap_only: {
  1070. ASSERT_EQ(set.size(), 0u);
  1071. ASSERT_EQ(set.free_list(), 0u);
  1072. ASSERT_EQ(set.remove(entity.begin(), entity.end()), 0u);
  1073. ASSERT_FALSE(set.remove(entity[1u]));
  1074. ASSERT_EQ(set.size(), 0u);
  1075. ASSERT_EQ(set.free_list(), 0u);
  1076. set.push(entity.begin(), entity.end());
  1077. ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
  1078. ASSERT_EQ(set.size(), 3u);
  1079. ASSERT_EQ(set.free_list(), 0u);
  1080. ASSERT_TRUE(set.contains(traits_type::next(entity[0u])));
  1081. ASSERT_TRUE(set.contains(traits_type::next(entity[1u])));
  1082. ASSERT_TRUE(set.contains(traits_type::next(entity[2u])));
  1083. set.push(entity.begin(), entity.end());
  1084. ASSERT_EQ(set.remove(entity.begin(), entity.begin() + 2u), 2u);
  1085. ASSERT_EQ(set.size(), 3u);
  1086. ASSERT_EQ(set.free_list(), 1u);
  1087. ASSERT_TRUE(set.contains(traits_type::next(entity[0u])));
  1088. ASSERT_TRUE(set.contains(traits_type::next(entity[1u])));
  1089. ASSERT_TRUE(set.contains(entity[2u]));
  1090. ASSERT_LT(set.index(entity[2u]), set.free_list());
  1091. ASSERT_TRUE(set.remove(entity[2u]));
  1092. ASSERT_FALSE(set.remove(entity[2u]));
  1093. ASSERT_EQ(set.size(), 3u);
  1094. ASSERT_EQ(set.free_list(), 0u);
  1095. ASSERT_TRUE(set.contains(traits_type::next(entity[2u])));
  1096. ASSERT_TRUE(set.remove(traits_type::next(entity[2u])));
  1097. ASSERT_TRUE(set.contains(traits_type::next(traits_type::next(entity[2u]))));
  1098. } break;
  1099. }
  1100. }
  1101. }
  1102. TYPED_TEST(SparseSet, CrossRemove) {
  1103. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1104. using entity_type = typename sparse_set_type::entity_type;
  1105. for(const auto policy: this->deletion_policy) {
  1106. sparse_set_type set{policy};
  1107. sparse_set_type other{policy};
  1108. const std::array entity{entity_type{1}, entity_type{3}};
  1109. set.push(entity.begin(), entity.end());
  1110. other.push(entity[1u]);
  1111. set.remove(other.begin(), other.end());
  1112. ASSERT_TRUE(set.contains(entity[0u]));
  1113. ASSERT_FALSE(set.contains(entity[1u]));
  1114. ASSERT_EQ(set.data()[0u], entity[0u]);
  1115. }
  1116. }
  1117. TYPED_TEST(SparseSet, Compact) {
  1118. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1119. using entity_type = typename sparse_set_type::entity_type;
  1120. using traits_type = typename sparse_set_type::traits_type;
  1121. for(const auto policy: this->deletion_policy) {
  1122. sparse_set_type set{policy};
  1123. const entity_type entity{1};
  1124. const entity_type other{2};
  1125. set.push(entity);
  1126. set.push(other);
  1127. switch(policy) {
  1128. case entt::deletion_policy::swap_and_pop: {
  1129. ASSERT_EQ(set.size(), 2u);
  1130. ASSERT_EQ(set.index(entity), 0u);
  1131. ASSERT_EQ(set.index(other), 1u);
  1132. set.compact();
  1133. ASSERT_EQ(set.size(), 2u);
  1134. ASSERT_EQ(set.index(entity), 0u);
  1135. ASSERT_EQ(set.index(other), 1u);
  1136. set.erase(entity);
  1137. ASSERT_EQ(set.size(), 1u);
  1138. ASSERT_EQ(set.index(other), 0u);
  1139. set.compact();
  1140. ASSERT_EQ(set.size(), 1u);
  1141. ASSERT_EQ(set.index(other), 0u);
  1142. } break;
  1143. case entt::deletion_policy::in_place: {
  1144. ASSERT_EQ(set.size(), 2u);
  1145. ASSERT_EQ(set.index(entity), 0u);
  1146. ASSERT_EQ(set.index(other), 1u);
  1147. set.compact();
  1148. ASSERT_EQ(set.size(), 2u);
  1149. ASSERT_EQ(set.index(entity), 0u);
  1150. ASSERT_EQ(set.index(other), 1u);
  1151. set.erase(other);
  1152. ASSERT_EQ(set.size(), 2u);
  1153. ASSERT_EQ(set.index(entity), 0u);
  1154. set.compact();
  1155. ASSERT_EQ(set.size(), 1u);
  1156. ASSERT_EQ(set.index(entity), 0u);
  1157. set.push(other);
  1158. set.erase(entity);
  1159. ASSERT_EQ(set.size(), 2u);
  1160. ASSERT_EQ(set.index(other), 1u);
  1161. set.compact();
  1162. ASSERT_EQ(set.size(), 1u);
  1163. ASSERT_EQ(set.index(other), 0u);
  1164. set.compact();
  1165. ASSERT_EQ(set.size(), 1u);
  1166. ASSERT_EQ(set.index(other), 0u);
  1167. } break;
  1168. case entt::deletion_policy::swap_only: {
  1169. ASSERT_EQ(set.size(), 2u);
  1170. ASSERT_EQ(set.index(entity), 0u);
  1171. ASSERT_EQ(set.index(other), 1u);
  1172. set.compact();
  1173. ASSERT_EQ(set.size(), 2u);
  1174. ASSERT_EQ(set.index(entity), 0u);
  1175. ASSERT_EQ(set.index(other), 1u);
  1176. set.erase(entity);
  1177. ASSERT_EQ(set.size(), 2u);
  1178. ASSERT_EQ(set.index(other), 0u);
  1179. ASSERT_EQ(set.index(traits_type::next(entity)), 1u);
  1180. set.compact();
  1181. ASSERT_EQ(set.size(), 2u);
  1182. ASSERT_EQ(set.index(other), 0u);
  1183. ASSERT_EQ(set.index(traits_type::next(entity)), 1u);
  1184. } break;
  1185. }
  1186. }
  1187. }
  1188. TYPED_TEST(SparseSet, SwapElements) {
  1189. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1190. using traits_type = typename sparse_set_type::traits_type;
  1191. for(const auto policy: this->deletion_policy) {
  1192. sparse_set_type set{policy};
  1193. const auto entity = traits_type::construct(1, 2);
  1194. const auto other = traits_type::construct(3, 4);
  1195. set.push(entity);
  1196. set.push(other);
  1197. ASSERT_EQ(set.index(entity), 0u);
  1198. ASSERT_EQ(set.index(other), 1u);
  1199. set.swap_elements(entity, other);
  1200. ASSERT_EQ(set.index(entity), 1u);
  1201. ASSERT_EQ(set.index(other), 0u);
  1202. }
  1203. }
  1204. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, SwapElements) {
  1205. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1206. using traits_type = typename sparse_set_type::traits_type;
  1207. for(const auto policy: this->deletion_policy) {
  1208. sparse_set_type set{policy};
  1209. const auto entity = traits_type::construct(1, 2);
  1210. const auto other = traits_type::construct(3, 4);
  1211. // swap_elements works the same in all cases, test only once
  1212. switch(policy) {
  1213. case entt::deletion_policy::swap_and_pop:
  1214. case entt::deletion_policy::in_place:
  1215. SUCCEED();
  1216. break;
  1217. case entt::deletion_policy::swap_only:
  1218. ASSERT_DEATH(set.swap_elements(entity, other), "");
  1219. set.push(entity);
  1220. set.push(other);
  1221. set.erase(entity);
  1222. ASSERT_DEATH(set.swap_elements(entity, other), "");
  1223. }
  1224. }
  1225. }
  1226. TYPED_TEST(SparseSet, Clear) {
  1227. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1228. using entity_type = typename sparse_set_type::entity_type;
  1229. for(const auto policy: this->deletion_policy) {
  1230. sparse_set_type set{policy};
  1231. const std::array entity{entity_type{1}, entity_type{3}, entity_type{2}};
  1232. set.push(entity.begin(), entity.end());
  1233. set.erase(entity[1u]);
  1234. set.clear();
  1235. ASSERT_EQ(set.size(), 0u);
  1236. }
  1237. }
  1238. TYPED_TEST(SparseSet, SortOrdered) {
  1239. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1240. using entity_type = typename sparse_set_type::entity_type;
  1241. for(const auto policy: this->deletion_policy) {
  1242. sparse_set_type set{policy};
  1243. std::array entity{entity_type{16}, entity_type{8}, entity_type{4}, entity_type{2}, entity_type{1}};
  1244. set.push(entity.begin(), entity.end());
  1245. set.sort(std::less{});
  1246. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), set.begin(), set.end()));
  1247. }
  1248. }
  1249. TYPED_TEST(SparseSet, SortReverse) {
  1250. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1251. using entity_type = typename sparse_set_type::entity_type;
  1252. for(const auto policy: this->deletion_policy) {
  1253. sparse_set_type set{policy};
  1254. std::array entity{entity_type{1}, entity_type{2}, entity_type{4}, entity_type{8}, entity_type{16}};
  1255. set.push(entity.begin(), entity.end());
  1256. set.sort(std::less{});
  1257. ASSERT_TRUE(std::equal(entity.begin(), entity.end(), set.begin(), set.end()));
  1258. }
  1259. }
  1260. TYPED_TEST(SparseSet, SortUnordered) {
  1261. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1262. using entity_type = typename sparse_set_type::entity_type;
  1263. for(const auto policy: this->deletion_policy) {
  1264. sparse_set_type set{policy};
  1265. std::array entity{entity_type{4}, entity_type{2}, entity_type{1}, entity_type{8}, entity_type{16}};
  1266. set.push(entity.begin(), entity.end());
  1267. set.sort(std::less{});
  1268. auto begin = set.begin();
  1269. const auto end = set.end();
  1270. ASSERT_EQ(*(begin++), entity[2u]);
  1271. ASSERT_EQ(*(begin++), entity[1u]);
  1272. ASSERT_EQ(*(begin++), entity[0u]);
  1273. ASSERT_EQ(*(begin++), entity[3u]);
  1274. ASSERT_EQ(*(begin++), entity[4u]);
  1275. ASSERT_EQ(begin, end);
  1276. }
  1277. }
  1278. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, Sort) {
  1279. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1280. using entity_type = typename sparse_set_type::entity_type;
  1281. for(const auto policy: this->deletion_policy) {
  1282. sparse_set_type set{policy};
  1283. const entity_type entity{1};
  1284. const entity_type other{2};
  1285. set.push(entity);
  1286. set.push(other);
  1287. set.erase(entity);
  1288. switch(policy) {
  1289. case entt::deletion_policy::swap_and_pop:
  1290. case entt::deletion_policy::swap_only: {
  1291. SUCCEED();
  1292. } break;
  1293. case entt::deletion_policy::in_place: {
  1294. ASSERT_DEATH(set.sort(std::less{}), "");
  1295. } break;
  1296. }
  1297. }
  1298. }
  1299. TYPED_TEST(SparseSet, SortN) {
  1300. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1301. using entity_type = typename sparse_set_type::entity_type;
  1302. for(const auto policy: this->deletion_policy) {
  1303. sparse_set_type set{policy};
  1304. std::array entity{entity_type{2}, entity_type{4}, entity_type{1}, entity_type{8}, entity_type{16}};
  1305. set.push(entity.begin(), entity.end());
  1306. set.sort_n(0u, std::less{});
  1307. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), set.begin(), set.end()));
  1308. set.sort_n(2u, std::less{});
  1309. ASSERT_EQ(set.data()[0u], entity[1u]);
  1310. ASSERT_EQ(set.data()[1u], entity[0u]);
  1311. const auto length = 5u;
  1312. set.sort_n(length, std::less{});
  1313. auto begin = set.begin();
  1314. auto end = set.end();
  1315. ASSERT_EQ(*(begin++), entity[2u]);
  1316. ASSERT_EQ(*(begin++), entity[0u]);
  1317. ASSERT_EQ(*(begin++), entity[1u]);
  1318. ASSERT_EQ(*(begin++), entity[3u]);
  1319. ASSERT_EQ(*(begin++), entity[4u]);
  1320. ASSERT_EQ(begin, end);
  1321. }
  1322. }
  1323. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, SortN) {
  1324. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1325. using entity_type = typename sparse_set_type::entity_type;
  1326. for(const auto policy: this->deletion_policy) {
  1327. sparse_set_type set{policy};
  1328. const entity_type entity{1};
  1329. const entity_type other{2};
  1330. ASSERT_DEATH(set.sort_n(1u, std::less{}), "");
  1331. set.push(entity);
  1332. set.push(other);
  1333. set.erase(entity);
  1334. switch(policy) {
  1335. case entt::deletion_policy::swap_and_pop: {
  1336. SUCCEED();
  1337. } break;
  1338. case entt::deletion_policy::in_place: {
  1339. ASSERT_EQ(set.size(), 2u);
  1340. ASSERT_DEATH(set.sort_n(1u, std::less{}), "");
  1341. } break;
  1342. case entt::deletion_policy::swap_only: {
  1343. ASSERT_EQ(set.size(), 2u);
  1344. ASSERT_NO_THROW(set.sort_n(1u, std::less{}));
  1345. ASSERT_DEATH(set.sort_n(2u, std::less{}), "");
  1346. } break;
  1347. }
  1348. }
  1349. }
  1350. TYPED_TEST(SparseSet, SortAsDisjoint) {
  1351. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1352. using entity_type = typename sparse_set_type::entity_type;
  1353. for(const auto policy: this->deletion_policy) {
  1354. sparse_set_type lhs{policy};
  1355. const sparse_set_type rhs{policy};
  1356. std::array entity{entity_type{1}, entity_type{2}, entity_type{4}};
  1357. lhs.push(entity.begin(), entity.end());
  1358. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), lhs.begin(), lhs.end()));
  1359. lhs.sort_as(rhs.begin(), rhs.end());
  1360. ASSERT_TRUE(std::equal(entity.rbegin(), entity.rend(), lhs.begin(), lhs.end()));
  1361. }
  1362. }
  1363. TYPED_TEST(SparseSet, SortAsOverlap) {
  1364. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1365. using entity_type = typename sparse_set_type::entity_type;
  1366. for(const auto policy: this->deletion_policy) {
  1367. sparse_set_type lhs{policy};
  1368. sparse_set_type rhs{policy};
  1369. std::array lhs_entity{entity_type{1}, entity_type{2}, entity_type{4}};
  1370. std::array rhs_entity{entity_type{2}};
  1371. lhs.push(lhs_entity.begin(), lhs_entity.end());
  1372. rhs.push(rhs_entity.begin(), rhs_entity.end());
  1373. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  1374. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  1375. lhs.sort_as(rhs.begin(), rhs.end());
  1376. auto begin = lhs.begin();
  1377. auto end = lhs.end();
  1378. ASSERT_EQ(*(begin++), lhs_entity[1u]);
  1379. ASSERT_EQ(*(begin++), lhs_entity[2u]);
  1380. ASSERT_EQ(*(begin++), lhs_entity[0u]);
  1381. ASSERT_EQ(begin, end);
  1382. }
  1383. }
  1384. TYPED_TEST(SparseSet, SortAsOrdered) {
  1385. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1386. using entity_type = typename sparse_set_type::entity_type;
  1387. for(const auto policy: this->deletion_policy) {
  1388. sparse_set_type lhs{policy};
  1389. sparse_set_type rhs{policy};
  1390. std::array lhs_entity{entity_type{1}, entity_type{2}, entity_type{4}, entity_type{8}, entity_type{16}};
  1391. std::array rhs_entity{entity_type{32}, entity_type{1}, entity_type{2}, entity_type{4}, entity_type{8}, entity_type{16}};
  1392. lhs.push(lhs_entity.begin(), lhs_entity.end());
  1393. rhs.push(rhs_entity.begin(), rhs_entity.end());
  1394. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  1395. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  1396. rhs.sort_as(lhs.begin(), lhs.end());
  1397. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  1398. }
  1399. }
  1400. TYPED_TEST(SparseSet, SortAsReverse) {
  1401. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1402. using entity_type = typename sparse_set_type::entity_type;
  1403. for(const auto policy: this->deletion_policy) {
  1404. sparse_set_type lhs{policy};
  1405. sparse_set_type rhs{policy};
  1406. std::array lhs_entity{entity_type{1}, entity_type{2}, entity_type{4}, entity_type{8}, entity_type{16}};
  1407. std::array rhs_entity{entity_type{16}, entity_type{8}, entity_type{4}, entity_type{2}, entity_type{1}, entity_type{32}};
  1408. lhs.push(lhs_entity.begin(), lhs_entity.end());
  1409. rhs.push(rhs_entity.begin(), rhs_entity.end());
  1410. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  1411. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  1412. rhs.sort_as(lhs.begin(), lhs.end());
  1413. auto begin = rhs.begin();
  1414. auto end = rhs.end();
  1415. ASSERT_EQ(*(begin++), rhs_entity[0u]);
  1416. ASSERT_EQ(*(begin++), rhs_entity[1u]);
  1417. ASSERT_EQ(*(begin++), rhs_entity[2u]);
  1418. ASSERT_EQ(*(begin++), rhs_entity[3u]);
  1419. ASSERT_EQ(*(begin++), rhs_entity[4u]);
  1420. ASSERT_EQ(*(begin++), rhs_entity[5u]);
  1421. ASSERT_EQ(begin, end);
  1422. }
  1423. }
  1424. TYPED_TEST(SparseSet, SortAsUnordered) {
  1425. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1426. using entity_type = typename sparse_set_type::entity_type;
  1427. for(const auto policy: this->deletion_policy) {
  1428. sparse_set_type lhs{policy};
  1429. sparse_set_type rhs{policy};
  1430. std::array lhs_entity{entity_type{1}, entity_type{2}, entity_type{4}, entity_type{8}, entity_type{16}};
  1431. std::array rhs_entity{entity_type{4}, entity_type{2}, entity_type{32}, entity_type{1}, entity_type{8}, entity_type{16}};
  1432. lhs.push(lhs_entity.begin(), lhs_entity.end());
  1433. rhs.push(rhs_entity.begin(), rhs_entity.end());
  1434. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  1435. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  1436. rhs.sort_as(lhs.begin(), lhs.end());
  1437. auto begin = rhs.begin();
  1438. auto end = rhs.end();
  1439. ASSERT_EQ(*(begin++), rhs_entity[5u]);
  1440. ASSERT_EQ(*(begin++), rhs_entity[4u]);
  1441. ASSERT_EQ(*(begin++), rhs_entity[0u]);
  1442. ASSERT_EQ(*(begin++), rhs_entity[1u]);
  1443. ASSERT_EQ(*(begin++), rhs_entity[3u]);
  1444. ASSERT_EQ(*(begin++), rhs_entity[2u]);
  1445. ASSERT_EQ(begin, end);
  1446. }
  1447. }
  1448. TYPED_TEST(SparseSet, SortAsInvalid) {
  1449. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1450. using entity_type = typename sparse_set_type::entity_type;
  1451. using traits_type = typename sparse_set_type::traits_type;
  1452. for(const auto policy: this->deletion_policy) {
  1453. sparse_set_type lhs{policy};
  1454. sparse_set_type rhs{policy};
  1455. std::array lhs_entity{entity_type{1}, entity_type{2}, traits_type::construct(3, 1)};
  1456. std::array rhs_entity{entity_type{2}, entity_type{1}, traits_type::construct(3, 2)};
  1457. lhs.push(lhs_entity.begin(), lhs_entity.end());
  1458. rhs.push(rhs_entity.begin(), rhs_entity.end());
  1459. ASSERT_TRUE(std::equal(lhs_entity.rbegin(), lhs_entity.rend(), lhs.begin(), lhs.end()));
  1460. ASSERT_TRUE(std::equal(rhs_entity.rbegin(), rhs_entity.rend(), rhs.begin(), rhs.end()));
  1461. rhs.sort_as(lhs.begin(), lhs.end());
  1462. auto begin = rhs.begin();
  1463. auto end = rhs.end();
  1464. ASSERT_EQ(*(begin++), rhs_entity[0u]);
  1465. ASSERT_EQ(*(begin++), rhs_entity[1u]);
  1466. ASSERT_EQ(*(begin++), rhs_entity[2u]);
  1467. ASSERT_EQ(rhs.current(rhs_entity[0u]), 0u);
  1468. ASSERT_EQ(rhs.current(rhs_entity[1u]), 0u);
  1469. ASSERT_EQ(rhs.current(rhs_entity[2u]), 2u);
  1470. ASSERT_EQ(begin, end);
  1471. }
  1472. }
  1473. ENTT_DEBUG_TYPED_TEST(SparseSetDeathTest, SortAs) {
  1474. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1475. using entity_type = typename sparse_set_type::entity_type;
  1476. for(const auto policy: this->deletion_policy) {
  1477. sparse_set_type lhs{policy};
  1478. sparse_set_type rhs{policy};
  1479. switch(policy) {
  1480. case entt::deletion_policy::swap_and_pop: {
  1481. SUCCEED();
  1482. } break;
  1483. case entt::deletion_policy::in_place: {
  1484. const entity_type entity{4};
  1485. lhs.push(entity);
  1486. lhs.erase(entity);
  1487. ASSERT_DEATH(lhs.sort_as(rhs.begin(), rhs.end()), "");
  1488. } break;
  1489. case entt::deletion_policy::swap_only: {
  1490. const std::array entity{entity_type{1}, entity_type{4}, entity_type{2}};
  1491. lhs.push(entity.begin(), entity.end());
  1492. rhs.push(entity.rbegin(), entity.rend());
  1493. lhs.erase(entity[0u]);
  1494. lhs.bump(entity[0u]);
  1495. ASSERT_DEATH(lhs.sort_as(rhs.begin(), rhs.end()), "");
  1496. } break;
  1497. }
  1498. }
  1499. }
  1500. TYPED_TEST(SparseSet, CanModifyDuringIteration) {
  1501. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1502. using entity_type = typename sparse_set_type::entity_type;
  1503. for(const auto policy: this->deletion_policy) {
  1504. sparse_set_type set{policy};
  1505. set.push(entity_type{0});
  1506. ASSERT_EQ(set.capacity(), 1u);
  1507. const auto it = set.begin();
  1508. set.reserve(2u);
  1509. ASSERT_EQ(set.capacity(), 2u);
  1510. // this should crash with asan enabled if we break the constraint
  1511. [[maybe_unused]] const auto entity = *it;
  1512. }
  1513. }
  1514. TYPED_TEST(SparseSet, CustomAllocator) {
  1515. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1516. using entity_type = typename sparse_set_type::entity_type;
  1517. for(const auto policy: this->deletion_policy) {
  1518. const test::throwing_allocator<entity_type> allocator{};
  1519. entt::basic_sparse_set<entity_type, test::throwing_allocator<entity_type>> set{policy, allocator};
  1520. ASSERT_EQ(set.get_allocator(), allocator);
  1521. set.reserve(1u);
  1522. ASSERT_EQ(set.capacity(), 1u);
  1523. set.push(entity_type{0});
  1524. set.push(entity_type{1});
  1525. entt::basic_sparse_set<entity_type, test::throwing_allocator<entity_type>> other{std::move(set), allocator};
  1526. ASSERT_TRUE(set.empty()); // NOLINT
  1527. ASSERT_FALSE(other.empty());
  1528. ASSERT_EQ(set.capacity(), 0u); // NOLINT
  1529. ASSERT_EQ(other.capacity(), 2u);
  1530. ASSERT_EQ(other.size(), 2u);
  1531. set = std::move(other);
  1532. ASSERT_FALSE(set.empty());
  1533. ASSERT_TRUE(other.empty()); // NOLINT
  1534. ASSERT_EQ(other.capacity(), 0u); // NOLINT
  1535. ASSERT_EQ(set.capacity(), 2u);
  1536. ASSERT_EQ(set.size(), 2u);
  1537. set.swap(other);
  1538. set = std::move(other);
  1539. ASSERT_FALSE(set.empty());
  1540. ASSERT_TRUE(other.empty()); // NOLINT
  1541. ASSERT_EQ(other.capacity(), 0u); // NOLINT
  1542. ASSERT_EQ(set.capacity(), 2u);
  1543. ASSERT_EQ(set.size(), 2u);
  1544. set.clear();
  1545. ASSERT_EQ(set.capacity(), 2u);
  1546. ASSERT_EQ(set.size(), 0u);
  1547. set.shrink_to_fit();
  1548. ASSERT_EQ(set.capacity(), 0u);
  1549. }
  1550. }
  1551. TYPED_TEST(SparseSet, ThrowingAllocator) {
  1552. using sparse_set_type = entt::basic_sparse_set<typename TestFixture::type>;
  1553. using entity_type = typename sparse_set_type::entity_type;
  1554. using traits_type = typename sparse_set_type::traits_type;
  1555. for(const auto policy: this->deletion_policy) {
  1556. entt::basic_sparse_set<entity_type, test::throwing_allocator<entity_type>> set{policy};
  1557. set.get_allocator().template throw_counter<entity_type>(0u);
  1558. ASSERT_THROW(set.reserve(1u), test::throwing_allocator_exception);
  1559. ASSERT_EQ(set.capacity(), 0u);
  1560. ASSERT_EQ(set.extent(), 0u);
  1561. set.get_allocator().template throw_counter<entity_type>(0u);
  1562. ASSERT_THROW(set.push(entity_type{0}), test::throwing_allocator_exception);
  1563. ASSERT_EQ(set.extent(), traits_type::page_size);
  1564. ASSERT_EQ(set.capacity(), 0u);
  1565. set.push(entity_type{0});
  1566. set.get_allocator().template throw_counter<entity_type>(0u);
  1567. ASSERT_THROW(set.reserve(2u), test::throwing_allocator_exception);
  1568. ASSERT_EQ(set.extent(), traits_type::page_size);
  1569. ASSERT_TRUE(set.contains(entity_type{0}));
  1570. ASSERT_EQ(set.capacity(), 1u);
  1571. set.get_allocator().template throw_counter<entity_type>(0u);
  1572. ASSERT_THROW(set.push(entity_type{1}), test::throwing_allocator_exception);
  1573. ASSERT_EQ(set.extent(), traits_type::page_size);
  1574. ASSERT_TRUE(set.contains(entity_type{0}));
  1575. ASSERT_FALSE(set.contains(entity_type{1}));
  1576. ASSERT_EQ(set.capacity(), 1u);
  1577. const std::array entity{entity_type{1}, entity_type{traits_type::page_size}};
  1578. set.get_allocator().template throw_counter<entity_type>(1u);
  1579. ASSERT_THROW(set.push(entity.begin(), entity.end()), test::throwing_allocator_exception);
  1580. ASSERT_EQ(set.extent(), 2 * traits_type::page_size);
  1581. ASSERT_TRUE(set.contains(entity_type{0}));
  1582. ASSERT_TRUE(set.contains(entity_type{1}));
  1583. ASSERT_FALSE(set.contains(entity_type{traits_type::page_size}));
  1584. ASSERT_EQ(set.capacity(), 2u);
  1585. ASSERT_EQ(set.size(), 2u);
  1586. set.push(entity[1u]);
  1587. ASSERT_TRUE(set.contains(entity_type{traits_type::page_size}));
  1588. }
  1589. }