sparse_set.cpp 69 KB

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