sparse_set.cpp 73 KB

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