sparse_set.cpp 72 KB

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