sparse_set.cpp 72 KB

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