sparse_set.cpp 67 KB

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