sparse_set.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. #include <cstdint>
  2. #include <utility>
  3. #include <iterator>
  4. #include <algorithm>
  5. #include <functional>
  6. #include <type_traits>
  7. #include <gtest/gtest.h>
  8. #include <entt/entity/entity.hpp>
  9. #include <entt/entity/sparse_set.hpp>
  10. #include <entt/entity/fwd.hpp>
  11. #include "throwing_allocator.hpp"
  12. struct empty_type {};
  13. struct boxed_int { int value; };
  14. TEST(SparseSet, Functionalities) {
  15. entt::sparse_set set;
  16. ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
  17. set.reserve(42);
  18. ASSERT_EQ(set.capacity(), 42u);
  19. ASSERT_TRUE(set.empty());
  20. ASSERT_EQ(set.size(), 0u);
  21. ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
  22. ASSERT_EQ(set.begin(), set.end());
  23. ASSERT_FALSE(set.contains(entt::entity{0}));
  24. ASSERT_FALSE(set.contains(entt::entity{42}));
  25. set.reserve(0);
  26. ASSERT_EQ(set.capacity(), 42u);
  27. ASSERT_TRUE(set.empty());
  28. ASSERT_EQ(set.emplace(entt::entity{42}), 0u);
  29. ASSERT_FALSE(set.empty());
  30. ASSERT_EQ(set.size(), 1u);
  31. ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
  32. ASSERT_NE(set.begin(), set.end());
  33. ASSERT_FALSE(set.contains(entt::entity{0}));
  34. ASSERT_TRUE(set.contains(entt::entity{42}));
  35. ASSERT_EQ(set.index(entt::entity{42}), 0u);
  36. ASSERT_EQ(set.at(0u), entt::entity{42});
  37. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  38. ASSERT_EQ(set[0u], entt::entity{42});
  39. set.erase(entt::entity{42});
  40. ASSERT_TRUE(set.empty());
  41. ASSERT_EQ(set.size(), 0u);
  42. ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
  43. ASSERT_EQ(set.begin(), set.end());
  44. ASSERT_FALSE(set.contains(entt::entity{0}));
  45. ASSERT_FALSE(set.contains(entt::entity{42}));
  46. ASSERT_EQ(set.at(0u), static_cast<entt::entity>(entt::null));
  47. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  48. ASSERT_EQ(set.emplace(entt::entity{42}), 0u);
  49. ASSERT_FALSE(set.empty());
  50. ASSERT_EQ(set.index(entt::entity{42}), 0u);
  51. ASSERT_EQ(set.at(0u), entt::entity{42});
  52. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  53. ASSERT_EQ(set[0u], entt::entity{42});
  54. set.clear();
  55. ASSERT_TRUE(set.empty());
  56. ASSERT_EQ(set.size(), 0u);
  57. ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
  58. ASSERT_EQ(set.begin(), set.end());
  59. ASSERT_FALSE(set.contains(entt::entity{0}));
  60. ASSERT_FALSE(set.contains(entt::entity{42}));
  61. }
  62. TEST(SparseSet, Contains) {
  63. entt::sparse_set set{entt::deletion_policy::in_place};
  64. set.emplace(entt::entity{0});
  65. set.emplace(entt::entity{3});
  66. set.emplace(entt::entity{42});
  67. set.emplace(entt::entity{99});
  68. set.emplace(entt::entity{1});
  69. ASSERT_TRUE(set.contains(entt::entity{0}));
  70. ASSERT_TRUE(set.contains(entt::entity{3}));
  71. ASSERT_TRUE(set.contains(entt::entity{42}));
  72. ASSERT_TRUE(set.contains(entt::entity{99}));
  73. ASSERT_TRUE(set.contains(entt::entity{1}));
  74. set.erase(entt::entity{0});
  75. set.erase(entt::entity{3});
  76. set.remove(entt::entity{42});
  77. set.remove(entt::entity{99});
  78. ASSERT_FALSE(set.contains(entt::entity{0}));
  79. ASSERT_FALSE(set.contains(entt::entity{3}));
  80. ASSERT_FALSE(set.contains(entt::entity{42}));
  81. ASSERT_FALSE(set.contains(entt::entity{99}));
  82. ASSERT_TRUE(set.contains(entt::entity{1}));
  83. ASSERT_DEATH(static_cast<void>(set.contains(entt::null)), "");
  84. ASSERT_DEATH(static_cast<void>(set.contains(entt::tombstone)), "");
  85. }
  86. TEST(SparseSet, Move) {
  87. entt::sparse_set set;
  88. set.emplace(entt::entity{42});
  89. ASSERT_TRUE(std::is_move_constructible_v<decltype(set)>);
  90. ASSERT_TRUE(std::is_move_assignable_v<decltype(set)>);
  91. entt::sparse_set other{std::move(set)};
  92. ASSERT_TRUE(set.empty());
  93. ASSERT_FALSE(other.empty());
  94. ASSERT_EQ(set.at(0u), static_cast<entt::entity>(entt::null));
  95. ASSERT_EQ(other.at(0u), entt::entity{42});
  96. set = std::move(other);
  97. ASSERT_FALSE(set.empty());
  98. ASSERT_TRUE(other.empty());
  99. ASSERT_EQ(set.at(0u), entt::entity{42});
  100. ASSERT_EQ(other.at(0u), static_cast<entt::entity>(entt::null));
  101. other = entt::sparse_set{};
  102. other.emplace(entt::entity{3});
  103. other = std::move(set);
  104. ASSERT_TRUE(set.empty());
  105. ASSERT_FALSE(other.empty());
  106. ASSERT_EQ(set.at(0u), static_cast<entt::entity>(entt::null));
  107. ASSERT_EQ(other.at(0u), entt::entity{42});
  108. }
  109. TEST(SparseSet, Pagination) {
  110. entt::sparse_set set;
  111. ASSERT_EQ(set.extent(), 0u);
  112. set.emplace(entt::entity{ENTT_SPARSE_PAGE-1u});
  113. ASSERT_EQ(set.extent(), ENTT_SPARSE_PAGE);
  114. ASSERT_TRUE(set.contains(entt::entity{ENTT_SPARSE_PAGE-1u}));
  115. set.emplace(entt::entity{ENTT_SPARSE_PAGE});
  116. ASSERT_EQ(set.extent(), 2 * ENTT_SPARSE_PAGE);
  117. ASSERT_TRUE(set.contains(entt::entity{ENTT_SPARSE_PAGE-1u}));
  118. ASSERT_TRUE(set.contains(entt::entity{ENTT_SPARSE_PAGE}));
  119. ASSERT_FALSE(set.contains(entt::entity{ENTT_SPARSE_PAGE+1u}));
  120. set.erase(entt::entity{ENTT_SPARSE_PAGE-1u});
  121. ASSERT_EQ(set.extent(), 2 * ENTT_SPARSE_PAGE);
  122. ASSERT_FALSE(set.contains(entt::entity{ENTT_SPARSE_PAGE-1u}));
  123. ASSERT_TRUE(set.contains(entt::entity{ENTT_SPARSE_PAGE}));
  124. set.shrink_to_fit();
  125. set.erase(entt::entity{ENTT_SPARSE_PAGE});
  126. ASSERT_EQ(set.extent(), 2 * ENTT_SPARSE_PAGE);
  127. ASSERT_FALSE(set.contains(entt::entity{ENTT_SPARSE_PAGE-1u}));
  128. ASSERT_FALSE(set.contains(entt::entity{ENTT_SPARSE_PAGE}));
  129. set.shrink_to_fit();
  130. ASSERT_EQ(set.extent(), 2 * ENTT_SPARSE_PAGE);
  131. }
  132. TEST(SparseSet, Emplace) {
  133. entt::sparse_set set{entt::deletion_policy::in_place};
  134. entt::entity entities[2u];
  135. entities[0u] = entt::entity{3};
  136. entities[1u] = entt::entity{42};
  137. ASSERT_TRUE(set.empty());
  138. set.emplace(entities[0u]);
  139. set.erase(entities[0u]);
  140. set.emplace_back(entities[0u]);
  141. set.emplace(entities[1u]);
  142. ASSERT_DEATH(set.emplace_back(entities[1u]), "");
  143. ASSERT_DEATH(set.emplace(entities[0u]), "");
  144. ASSERT_EQ(set.at(0u), entities[1u]);
  145. ASSERT_EQ(set.at(1u), entities[0u]);
  146. ASSERT_EQ(set.index(entities[0u]), 1u);
  147. ASSERT_EQ(set.index(entities[1u]), 0u);
  148. set.erase(std::begin(entities), std::end(entities));
  149. set.emplace(entities[1u]);
  150. set.emplace_back(entities[0u]);
  151. ASSERT_EQ(set.at(0u), entities[1u]);
  152. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  153. ASSERT_EQ(set.at(2u), entities[0u]);
  154. ASSERT_EQ(set.index(entities[0u]), 2u);
  155. ASSERT_EQ(set.index(entities[1u]), 0u);
  156. }
  157. TEST(SparseSet, EmplaceOutOfBounds) {
  158. entt::sparse_set set{entt::deletion_policy::in_place};
  159. entt::entity entities[2u]{entt::entity{0}, entt::entity{ENTT_SPARSE_PAGE}};
  160. ASSERT_EQ(set.emplace(entities[0u]), 0u);
  161. ASSERT_EQ(set.extent(), ENTT_SPARSE_PAGE);
  162. set.erase(entities[0u]);
  163. ASSERT_EQ(set.emplace(entities[1u]), 0u);
  164. ASSERT_EQ(set.extent(), 2u * ENTT_SPARSE_PAGE);
  165. }
  166. TEST(SparseSet, Insert) {
  167. entt::sparse_set set{entt::deletion_policy::in_place};
  168. entt::entity entities[2u];
  169. entities[0u] = entt::entity{3};
  170. entities[1u] = entt::entity{42};
  171. set.emplace(entt::entity{12});
  172. set.insert(std::end(entities), std::end(entities));
  173. set.insert(std::begin(entities), std::end(entities));
  174. set.emplace(entt::entity{24});
  175. ASSERT_TRUE(set.contains(entities[0u]));
  176. ASSERT_TRUE(set.contains(entities[1u]));
  177. ASSERT_FALSE(set.contains(entt::entity{0}));
  178. ASSERT_FALSE(set.contains(entt::entity{9}));
  179. ASSERT_TRUE(set.contains(entt::entity{12}));
  180. ASSERT_TRUE(set.contains(entt::entity{24}));
  181. ASSERT_FALSE(set.empty());
  182. ASSERT_EQ(set.size(), 4u);
  183. ASSERT_EQ(set.index(entt::entity{12}), 0u);
  184. ASSERT_EQ(set.index(entities[0u]), 1u);
  185. ASSERT_EQ(set.index(entities[1u]), 2u);
  186. ASSERT_EQ(set.index(entt::entity{24}), 3u);
  187. ASSERT_EQ(set.data()[set.index(entt::entity{12})], entt::entity{12});
  188. ASSERT_EQ(set.data()[set.index(entities[0u])], entities[0u]);
  189. ASSERT_EQ(set.data()[set.index(entities[1u])], entities[1u]);
  190. ASSERT_EQ(set.data()[set.index(entt::entity{24})], entt::entity{24});
  191. set.erase(std::begin(entities), std::end(entities));
  192. set.insert(std::rbegin(entities), std::rend(entities));
  193. ASSERT_EQ(set.size(), 6u);
  194. ASSERT_TRUE(set.at(1u) == entt::tombstone);
  195. ASSERT_TRUE(set.at(2u) == entt::tombstone);
  196. ASSERT_EQ(set.at(4u), entities[1u]);
  197. ASSERT_EQ(set.at(5u), entities[0u]);
  198. ASSERT_EQ(set.index(entities[0u]), 5u);
  199. ASSERT_EQ(set.index(entities[1u]), 4u);
  200. }
  201. TEST(SparseSet, Erase) {
  202. entt::sparse_set set;
  203. entt::entity entities[3u];
  204. entities[0u] = entt::entity{3};
  205. entities[1u] = entt::entity{42};
  206. entities[2u] = entt::entity{9};
  207. ASSERT_EQ(set.policy(), entt::deletion_policy::swap_and_pop);
  208. ASSERT_TRUE(set.empty());
  209. ASSERT_DEATH(set.erase(std::begin(entities), std::end(entities)), "");
  210. ASSERT_DEATH(set.erase(entities[1u]), "");
  211. ASSERT_TRUE(set.empty());
  212. set.insert(std::begin(entities), std::end(entities));
  213. set.erase(set.begin(), set.end());
  214. ASSERT_TRUE(set.empty());
  215. set.insert(std::begin(entities), std::end(entities));
  216. set.erase(entities, entities + 2u);
  217. ASSERT_FALSE(set.empty());
  218. ASSERT_EQ(*set.begin(), entities[2u]);
  219. set.erase(entities[2u]);
  220. ASSERT_DEATH(set.erase(entities[2u]), "");
  221. ASSERT_TRUE(set.empty());
  222. set.insert(std::begin(entities), std::end(entities));
  223. std::swap(entities[1u], entities[2u]);
  224. set.erase(entities, entities + 2u);
  225. ASSERT_FALSE(set.empty());
  226. ASSERT_EQ(*set.begin(), entities[2u]);
  227. }
  228. TEST(SparseSet, StableErase) {
  229. entt::sparse_set set{entt::deletion_policy::in_place};
  230. entt::entity entities[3u];
  231. entities[0u] = entt::entity{3};
  232. entities[1u] = entt::entity{42};
  233. entities[2u] = entt::entity{9};
  234. ASSERT_EQ(set.policy(), entt::deletion_policy::in_place);
  235. ASSERT_TRUE(set.empty());
  236. ASSERT_EQ(set.size(), 0u);
  237. ASSERT_DEATH(set.erase(std::begin(entities), std::end(entities)), "");
  238. ASSERT_DEATH(set.erase(entities[1u]), "");
  239. ASSERT_TRUE(set.empty());
  240. ASSERT_EQ(set.size(), 0u);
  241. set.insert(std::begin(entities), std::end(entities));
  242. set.erase(set.begin(), set.end());
  243. ASSERT_FALSE(set.empty());
  244. ASSERT_EQ(set.size(), 3u);
  245. ASSERT_TRUE(set.at(0u) == entt::tombstone);
  246. ASSERT_TRUE(set.at(1u) == entt::tombstone);
  247. ASSERT_TRUE(set.at(2u) == entt::tombstone);
  248. ASSERT_EQ(set.slot(), 0u);
  249. set.insert(std::begin(entities), std::end(entities));
  250. set.erase(entities, entities + 2u);
  251. ASSERT_FALSE(set.empty());
  252. ASSERT_EQ(set.size(), 6u);
  253. ASSERT_EQ(*set.begin(), entities[2u]);
  254. ASSERT_TRUE(set.at(3u) == entt::tombstone);
  255. ASSERT_TRUE(set.at(4u) == entt::tombstone);
  256. ASSERT_EQ(set.slot(), 4u);
  257. set.erase(entities[2u]);
  258. ASSERT_DEATH(set.erase(entities[2u]), "");
  259. ASSERT_FALSE(set.empty());
  260. ASSERT_EQ(set.size(), 6u);
  261. ASSERT_EQ(set.slot(), 5u);
  262. set.insert(std::begin(entities), std::end(entities));
  263. std::swap(entities[1u], entities[2u]);
  264. set.erase(entities, entities + 2u);
  265. ASSERT_FALSE(set.empty());
  266. ASSERT_EQ(set.size(), 9u);
  267. ASSERT_TRUE(set.at(6u) == entt::tombstone);
  268. ASSERT_EQ(set.at(7u), entities[2u]);
  269. ASSERT_EQ(*++set.begin(), entities[2u]);
  270. ASSERT_TRUE(set.at(8u) == entt::tombstone);
  271. ASSERT_EQ(set.slot(), 8u);
  272. set.compact();
  273. ASSERT_FALSE(set.empty());
  274. ASSERT_EQ(set.size(), 1u);
  275. ASSERT_EQ(*set.begin(), entities[2u]);
  276. ASSERT_EQ(set.slot(), 1u);
  277. set.clear();
  278. ASSERT_EQ(set.size(), 0u);
  279. ASSERT_EQ(set.slot(), 0u);
  280. set.insert(std::begin(entities), std::end(entities));
  281. set.erase(entities[2u]);
  282. ASSERT_DEATH(set.erase(entities[2u]), "");
  283. ASSERT_EQ(set.slot(), 2u);
  284. set.erase(entities[0u]);
  285. set.erase(entities[1u]);
  286. ASSERT_DEATH(set.erase(entities, entities + 2u), "");
  287. ASSERT_EQ(set.size(), 3u);
  288. ASSERT_TRUE(*set.begin() == entt::tombstone);
  289. ASSERT_EQ(set.slot(), 1u);
  290. ASSERT_EQ(set.emplace(entities[0u]), 1u);
  291. ASSERT_EQ(*++set.begin(), entities[0u]);
  292. ASSERT_EQ(set.emplace(entities[1u]), 0u);
  293. ASSERT_EQ(set.emplace(entities[2u]), 2u);
  294. ASSERT_EQ(set.emplace(entt::entity{0}), 3u);
  295. ASSERT_EQ(set.size(), 4u);
  296. ASSERT_EQ(*set.begin(), entt::entity{0});
  297. ASSERT_EQ(set.at(0u), entities[1u]);
  298. ASSERT_EQ(set.at(1u), entities[0u]);
  299. ASSERT_EQ(set.at(2u), entities[2u]);
  300. }
  301. TEST(SparseSet, Remove) {
  302. entt::sparse_set set;
  303. entt::entity entities[3u];
  304. entities[0u] = entt::entity{3};
  305. entities[1u] = entt::entity{42};
  306. entities[2u] = entt::entity{9};
  307. ASSERT_EQ(set.policy(), entt::deletion_policy::swap_and_pop);
  308. ASSERT_TRUE(set.empty());
  309. ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 0u);
  310. ASSERT_EQ(set.remove(entities[1u]), 0u);
  311. ASSERT_TRUE(set.empty());
  312. set.insert(std::begin(entities), std::end(entities));
  313. ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
  314. ASSERT_TRUE(set.empty());
  315. set.insert(std::begin(entities), std::end(entities));
  316. ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
  317. ASSERT_FALSE(set.empty());
  318. ASSERT_EQ(*set.begin(), entities[2u]);
  319. ASSERT_EQ(set.remove(entities[2u]), 1u);
  320. ASSERT_EQ(set.remove(entities[2u]), 0u);
  321. ASSERT_TRUE(set.empty());
  322. set.insert(entities, entities + 2u);
  323. ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 2u);
  324. ASSERT_TRUE(set.empty());
  325. set.insert(std::begin(entities), std::end(entities));
  326. std::swap(entities[1u], entities[2u]);
  327. ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
  328. ASSERT_FALSE(set.empty());
  329. ASSERT_EQ(*set.begin(), entities[2u]);
  330. }
  331. TEST(SparseSet, StableRemove) {
  332. entt::sparse_set set{entt::deletion_policy::in_place};
  333. entt::entity entities[3u];
  334. entities[0u] = entt::entity{3};
  335. entities[1u] = entt::entity{42};
  336. entities[2u] = entt::entity{9};
  337. ASSERT_EQ(set.policy(), entt::deletion_policy::in_place);
  338. ASSERT_TRUE(set.empty());
  339. ASSERT_EQ(set.size(), 0u);
  340. ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 0u);
  341. ASSERT_EQ(set.remove(entities[1u]), 0u);
  342. ASSERT_TRUE(set.empty());
  343. ASSERT_EQ(set.size(), 0u);
  344. set.insert(std::begin(entities), std::end(entities));
  345. ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
  346. ASSERT_FALSE(set.empty());
  347. ASSERT_EQ(set.size(), 3u);
  348. ASSERT_TRUE(set.at(0u) == entt::tombstone);
  349. ASSERT_TRUE(set.at(1u) == entt::tombstone);
  350. ASSERT_TRUE(set.at(2u) == entt::tombstone);
  351. ASSERT_EQ(set.slot(), 0u);
  352. set.insert(std::begin(entities), std::end(entities));
  353. ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
  354. ASSERT_FALSE(set.empty());
  355. ASSERT_EQ(set.size(), 6u);
  356. ASSERT_EQ(*set.begin(), entt::entity{9});
  357. ASSERT_TRUE(set.at(3u) == entt::tombstone);
  358. ASSERT_TRUE(set.at(4u) == entt::tombstone);
  359. ASSERT_EQ(set.slot(), 4u);
  360. ASSERT_EQ(set.remove(entities[2u]), 1u);
  361. ASSERT_EQ(set.remove(entities[2u]), 0u);
  362. ASSERT_EQ(set.remove(entities[2u]), 0u);
  363. ASSERT_EQ(set.remove(entities[2u]), 0u);
  364. ASSERT_FALSE(set.empty());
  365. ASSERT_EQ(set.size(), 6u);
  366. ASSERT_TRUE(*set.begin() == entt::tombstone);
  367. ASSERT_EQ(set.slot(), 5u);
  368. set.insert(entities, entities + 2u);
  369. ASSERT_EQ(set.remove(std::begin(entities), std::end(entities)), 2u);
  370. ASSERT_FALSE(set.empty());
  371. ASSERT_EQ(set.size(), 8u);
  372. ASSERT_TRUE(set.at(6u) == entt::tombstone);
  373. ASSERT_TRUE(set.at(7u) == entt::tombstone);
  374. ASSERT_EQ(set.slot(), 7u);
  375. set.insert(std::begin(entities), std::end(entities));
  376. std::swap(entities[1u], entities[2u]);
  377. ASSERT_EQ(set.remove(entities, entities + 2u), 2u);
  378. ASSERT_FALSE(set.empty());
  379. ASSERT_EQ(set.size(), 11u);
  380. ASSERT_TRUE(set.at(8u) == entt::tombstone);
  381. ASSERT_EQ(set.at(9u), entities[2u]);
  382. ASSERT_EQ(*++set.begin(), entities[2u]);
  383. ASSERT_TRUE(set.at(10u) == entt::tombstone);
  384. ASSERT_EQ(set.slot(), 10u);
  385. set.compact();
  386. ASSERT_FALSE(set.empty());
  387. ASSERT_EQ(set.size(), 1u);
  388. ASSERT_EQ(*set.begin(), entities[2u]);
  389. ASSERT_EQ(set.slot(), 1u);
  390. set.clear();
  391. ASSERT_EQ(set.size(), 0u);
  392. ASSERT_EQ(set.slot(), 0u);
  393. set.insert(std::begin(entities), std::end(entities));
  394. ASSERT_EQ(set.remove(entities[2u]), 1u);
  395. ASSERT_EQ(set.remove(entities[2u]), 0u);
  396. ASSERT_EQ(set.remove(entities[0u]), 1u);
  397. ASSERT_EQ(set.remove(entities[1u]), 1u);
  398. ASSERT_EQ(set.remove(entities, entities + 2u), 0u);
  399. ASSERT_EQ(set.size(), 3u);
  400. ASSERT_TRUE(*set.begin() == entt::tombstone);
  401. ASSERT_EQ(set.slot(), 1u);
  402. ASSERT_EQ(set.emplace(entities[0u]), 1u);
  403. ASSERT_EQ(*++set.begin(), entities[0u]);
  404. ASSERT_EQ(set.emplace(entities[1u]), 0u);
  405. ASSERT_EQ(set.emplace(entities[2u]), 2u);
  406. ASSERT_EQ(set.emplace(entt::entity{0}), 3u);
  407. ASSERT_EQ(set.size(), 4u);
  408. ASSERT_EQ(*set.begin(), entt::entity{0});
  409. ASSERT_EQ(set.at(0u), entities[1u]);
  410. ASSERT_EQ(set.at(1u), entities[0u]);
  411. ASSERT_EQ(set.at(2u), entities[2u]);
  412. }
  413. TEST(SparseSet, Compact) {
  414. entt::sparse_set set{entt::deletion_policy::in_place};
  415. ASSERT_TRUE(set.empty());
  416. ASSERT_EQ(set.size(), 0u);
  417. set.compact();
  418. ASSERT_TRUE(set.empty());
  419. ASSERT_EQ(set.size(), 0u);
  420. set.emplace(entt::entity{0});
  421. set.compact();
  422. ASSERT_FALSE(set.empty());
  423. ASSERT_EQ(set.size(), 1u);
  424. set.emplace(entt::entity{42});
  425. set.erase(entt::entity{0});
  426. ASSERT_EQ(set.size(), 2u);
  427. ASSERT_EQ(set.index(entt::entity{42}), 1u);
  428. set.compact();
  429. ASSERT_EQ(set.size(), 1u);
  430. ASSERT_EQ(set.index(entt::entity{42}), 0u);
  431. set.emplace(entt::entity{0});
  432. set.compact();
  433. ASSERT_EQ(set.size(), 2u);
  434. ASSERT_EQ(set.index(entt::entity{42}), 0u);
  435. ASSERT_EQ(set.index(entt::entity{0}), 1u);
  436. set.erase(entt::entity{0});
  437. set.erase(entt::entity{42});
  438. set.compact();
  439. ASSERT_TRUE(set.empty());
  440. }
  441. TEST(SparseSet, Clear) {
  442. entt::sparse_set set;
  443. set.emplace(entt::entity{3});
  444. set.emplace(entt::entity{42});
  445. set.emplace(entt::entity{9});
  446. ASSERT_FALSE(set.empty());
  447. set.clear();
  448. ASSERT_TRUE(set.empty());
  449. }
  450. TEST(SparseSet, Iterator) {
  451. using iterator = typename entt::sparse_set::iterator;
  452. entt::sparse_set set;
  453. set.emplace(entt::entity{3});
  454. iterator end{set.begin()};
  455. iterator begin{};
  456. begin = set.end();
  457. std::swap(begin, end);
  458. ASSERT_EQ(begin, set.begin());
  459. ASSERT_EQ(end, set.end());
  460. ASSERT_NE(begin, end);
  461. ASSERT_EQ(begin++, set.begin());
  462. ASSERT_EQ(begin--, set.end());
  463. ASSERT_EQ(begin+1, set.end());
  464. ASSERT_EQ(end-1, set.begin());
  465. ASSERT_EQ(++begin, set.end());
  466. ASSERT_EQ(--begin, set.begin());
  467. ASSERT_EQ(begin += 1, set.end());
  468. ASSERT_EQ(begin -= 1, set.begin());
  469. ASSERT_EQ(begin + (end - begin), set.end());
  470. ASSERT_EQ(begin - (begin - end), set.end());
  471. ASSERT_EQ(end - (end - begin), set.begin());
  472. ASSERT_EQ(end + (begin - end), set.begin());
  473. ASSERT_EQ(begin[0u], *set.begin());
  474. ASSERT_LT(begin, end);
  475. ASSERT_LE(begin, set.begin());
  476. ASSERT_GT(end, begin);
  477. ASSERT_GE(end, set.end());
  478. ASSERT_EQ(*begin, entt::entity{3});
  479. ASSERT_EQ(*begin.operator->(), entt::entity{3});
  480. }
  481. TEST(SparseSet, ReverseIterator) {
  482. using reverse_iterator = typename entt::sparse_set::reverse_iterator;
  483. entt::sparse_set set;
  484. set.emplace(entt::entity{3});
  485. reverse_iterator end{set.rbegin()};
  486. reverse_iterator begin{};
  487. begin = set.rend();
  488. std::swap(begin, end);
  489. ASSERT_EQ(begin, set.rbegin());
  490. ASSERT_EQ(end, set.rend());
  491. ASSERT_NE(begin, end);
  492. ASSERT_EQ(begin++, set.rbegin());
  493. ASSERT_EQ(begin--, set.rend());
  494. ASSERT_EQ(begin+1, set.rend());
  495. ASSERT_EQ(end-1, set.rbegin());
  496. ASSERT_EQ(++begin, set.rend());
  497. ASSERT_EQ(--begin, set.rbegin());
  498. ASSERT_EQ(begin += 1, set.rend());
  499. ASSERT_EQ(begin -= 1, set.rbegin());
  500. ASSERT_EQ(begin + (end - begin), set.rend());
  501. ASSERT_EQ(begin - (begin - end), set.rend());
  502. ASSERT_EQ(end - (end - begin), set.rbegin());
  503. ASSERT_EQ(end + (begin - end), set.rbegin());
  504. ASSERT_EQ(begin[0u], *set.rbegin());
  505. ASSERT_LT(begin, end);
  506. ASSERT_LE(begin, set.rbegin());
  507. ASSERT_GT(end, begin);
  508. ASSERT_GE(end, set.rend());
  509. ASSERT_EQ(*begin, entt::entity{3});
  510. }
  511. TEST(SparseSet, Find) {
  512. entt::sparse_set set;
  513. set.emplace(entt::entity{3});
  514. set.emplace(entt::entity{42});
  515. set.emplace(entt::entity{99});
  516. ASSERT_NE(set.find(entt::entity{3}), set.end());
  517. ASSERT_NE(set.find(entt::entity{42}), set.end());
  518. ASSERT_NE(set.find(entt::entity{99}), set.end());
  519. ASSERT_EQ(set.find(entt::entity{0}), set.end());
  520. auto it = set.find(entt::entity{99});
  521. ASSERT_EQ(*it, entt::entity{99});
  522. ASSERT_EQ(*(++it), entt::entity{42});
  523. ASSERT_EQ(*(++it), entt::entity{3});
  524. ASSERT_EQ(++it, set.end());
  525. ASSERT_EQ(++set.find(entt::entity{3}), set.end());
  526. }
  527. TEST(SparseSet, Data) {
  528. entt::sparse_set set;
  529. set.emplace(entt::entity{3});
  530. set.emplace(entt::entity{12});
  531. set.emplace(entt::entity{42});
  532. ASSERT_EQ(set.index(entt::entity{3}), 0u);
  533. ASSERT_EQ(set.index(entt::entity{12}), 1u);
  534. ASSERT_EQ(set.index(entt::entity{42}), 2u);
  535. ASSERT_EQ(set.data()[0u], entt::entity{3});
  536. ASSERT_EQ(set.data()[1u], entt::entity{12});
  537. ASSERT_EQ(set.data()[2u], entt::entity{42});
  538. }
  539. TEST(SparseSet, SortOrdered) {
  540. entt::sparse_set set;
  541. entt::entity entities[5u]{entt::entity{42}, entt::entity{12}, entt::entity{9}, entt::entity{7}, entt::entity{3}};
  542. set.insert(std::begin(entities), std::end(entities));
  543. set.sort(std::less{});
  544. ASSERT_TRUE(std::equal(std::rbegin(entities), std::rend(entities), set.begin(), set.end()));
  545. }
  546. TEST(SparseSet, SortReverse) {
  547. entt::sparse_set set;
  548. entt::entity entities[5u]{entt::entity{3}, entt::entity{7}, entt::entity{9}, entt::entity{12}, entt::entity{42}};
  549. set.insert(std::begin(entities), std::end(entities));
  550. set.sort(std::less{});
  551. ASSERT_TRUE(std::equal(std::begin(entities), std::end(entities), set.begin(), set.end()));
  552. }
  553. TEST(SparseSet, SortUnordered) {
  554. entt::sparse_set set;
  555. entt::entity entities[5u]{entt::entity{9}, entt::entity{7}, entt::entity{3}, entt::entity{12}, entt::entity{42}};
  556. set.insert(std::begin(entities), std::end(entities));
  557. set.sort(std::less{});
  558. auto begin = set.begin();
  559. auto end = set.end();
  560. ASSERT_EQ(*(begin++), entt::entity{3});
  561. ASSERT_EQ(*(begin++), entt::entity{7});
  562. ASSERT_EQ(*(begin++), entt::entity{9});
  563. ASSERT_EQ(*(begin++), entt::entity{12});
  564. ASSERT_EQ(*(begin++), entt::entity{42});
  565. ASSERT_EQ(begin, end);
  566. }
  567. TEST(SparseSet, SortRange) {
  568. entt::sparse_set set;
  569. entt::entity entities[5u]{entt::entity{7}, entt::entity{9}, entt::entity{3}, entt::entity{12}, entt::entity{42}};
  570. set.insert(std::begin(entities), std::end(entities));
  571. set.sort_n(0u, std::less{});
  572. ASSERT_TRUE(std::equal(std::rbegin(entities), std::rend(entities), set.begin(), set.end()));
  573. set.sort_n(2u, std::less{});
  574. ASSERT_EQ(set.data()[0u], entt::entity{9});
  575. ASSERT_EQ(set.data()[1u], entt::entity{7});
  576. ASSERT_EQ(set.data()[2u], entt::entity{3});
  577. set.sort_n(5u, std::less{});
  578. auto begin = set.begin();
  579. auto end = set.end();
  580. ASSERT_EQ(*(begin++), entt::entity{3});
  581. ASSERT_EQ(*(begin++), entt::entity{7});
  582. ASSERT_EQ(*(begin++), entt::entity{9});
  583. ASSERT_EQ(*(begin++), entt::entity{12});
  584. ASSERT_EQ(*(begin++), entt::entity{42});
  585. ASSERT_EQ(begin, end);
  586. }
  587. TEST(SparseSet, RespectDisjoint) {
  588. entt::sparse_set lhs;
  589. entt::sparse_set rhs;
  590. entt::entity lhs_entities[3u]{entt::entity{3}, entt::entity{12}, entt::entity{42}};
  591. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  592. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  593. lhs.respect(rhs);
  594. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  595. }
  596. TEST(SparseSet, RespectOverlap) {
  597. entt::sparse_set lhs;
  598. entt::sparse_set rhs;
  599. entt::entity lhs_entities[3u]{entt::entity{3}, entt::entity{12}, entt::entity{42}};
  600. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  601. entt::entity rhs_entities[1u]{entt::entity{12}};
  602. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  603. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  604. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  605. lhs.respect(rhs);
  606. auto begin = lhs.begin();
  607. auto end = lhs.end();
  608. ASSERT_EQ(*(begin++), entt::entity{12});
  609. ASSERT_EQ(*(begin++), entt::entity{42});
  610. ASSERT_EQ(*(begin++), entt::entity{3});
  611. ASSERT_EQ(begin, end);
  612. }
  613. TEST(SparseSet, RespectOrdered) {
  614. entt::sparse_set lhs;
  615. entt::sparse_set rhs;
  616. entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  617. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  618. entt::entity rhs_entities[6u]{entt::entity{6}, entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  619. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  620. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  621. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  622. rhs.respect(lhs);
  623. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  624. }
  625. TEST(SparseSet, RespectReverse) {
  626. entt::sparse_set lhs;
  627. entt::sparse_set rhs;
  628. entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  629. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  630. entt::entity rhs_entities[6u]{entt::entity{5}, entt::entity{4}, entt::entity{3}, entt::entity{2}, entt::entity{1}, entt::entity{6}};
  631. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  632. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  633. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  634. rhs.respect(lhs);
  635. auto begin = rhs.begin();
  636. auto end = rhs.end();
  637. ASSERT_EQ(*(begin++), entt::entity{5});
  638. ASSERT_EQ(*(begin++), entt::entity{4});
  639. ASSERT_EQ(*(begin++), entt::entity{3});
  640. ASSERT_EQ(*(begin++), entt::entity{2});
  641. ASSERT_EQ(*(begin++), entt::entity{1});
  642. ASSERT_EQ(*(begin++), entt::entity{6});
  643. ASSERT_EQ(begin, end);
  644. }
  645. TEST(SparseSet, RespectUnordered) {
  646. entt::sparse_set lhs;
  647. entt::sparse_set rhs;
  648. entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  649. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  650. entt::entity rhs_entities[6u]{entt::entity{3}, entt::entity{2}, entt::entity{6}, entt::entity{1}, entt::entity{4}, entt::entity{5}};
  651. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  652. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  653. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  654. rhs.respect(lhs);
  655. auto begin = rhs.begin();
  656. auto end = rhs.end();
  657. ASSERT_EQ(*(begin++), entt::entity{5});
  658. ASSERT_EQ(*(begin++), entt::entity{4});
  659. ASSERT_EQ(*(begin++), entt::entity{3});
  660. ASSERT_EQ(*(begin++), entt::entity{2});
  661. ASSERT_EQ(*(begin++), entt::entity{1});
  662. ASSERT_EQ(*(begin++), entt::entity{6});
  663. ASSERT_EQ(begin, end);
  664. }
  665. TEST(SparseSet, CanModifyDuringIteration) {
  666. entt::sparse_set set;
  667. set.emplace(entt::entity{0});
  668. ASSERT_EQ(set.capacity(), 1u);
  669. const auto it = set.begin();
  670. set.reserve(2u);
  671. ASSERT_EQ(set.capacity(), 2u);
  672. // this should crash with asan enabled if we break the constraint
  673. [[maybe_unused]] const auto entity = *it;
  674. }
  675. TEST(SparseSet, ThrowingAllocator) {
  676. entt::basic_sparse_set<entt::entity, test::throwing_allocator<entt::entity>> set{};
  677. test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
  678. // strong exception safety
  679. ASSERT_THROW(set.reserve(1u), test::throwing_allocator<entt::entity>::exception_type);
  680. ASSERT_EQ(set.capacity(), 0u);
  681. ASSERT_EQ(set.extent(), 0u);
  682. test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
  683. // strong exception safety
  684. ASSERT_THROW(set.emplace(entt::entity{0}), test::throwing_allocator<entt::entity>::exception_type);
  685. ASSERT_EQ(set.capacity(), 0u);
  686. ASSERT_EQ(set.extent(), 0u);
  687. set.emplace(entt::entity{0});
  688. test::throwing_allocator<entt::entity>::trigger_on_allocate = true;
  689. // strong exception safety
  690. ASSERT_THROW(set.reserve(2u), test::throwing_allocator<entt::entity>::exception_type);
  691. ASSERT_EQ(set.capacity(), 1u);
  692. ASSERT_EQ(set.extent(), ENTT_SPARSE_PAGE);
  693. ASSERT_TRUE(set.contains(entt::entity{0}));
  694. entt::entity entities[2u]{entt::entity{1}, entt::entity{ENTT_SPARSE_PAGE}};
  695. test::throwing_allocator<entt::entity>::trigger_after_allocate = true;
  696. // basic exception safety
  697. ASSERT_THROW(set.insert(std::begin(entities), std::end(entities)), test::throwing_allocator<entt::entity>::exception_type);
  698. ASSERT_EQ(set.capacity(), 3u);
  699. ASSERT_EQ(set.size(), 2u);
  700. ASSERT_EQ(set.extent(), 2 * ENTT_SPARSE_PAGE);
  701. ASSERT_TRUE(set.contains(entt::entity{0}));
  702. ASSERT_TRUE(set.contains(entt::entity{1}));
  703. ASSERT_FALSE(set.contains(entt::entity{ENTT_SPARSE_PAGE}));
  704. set.emplace(entities[1u]);
  705. ASSERT_TRUE(set.contains(entt::entity{ENTT_SPARSE_PAGE}));
  706. // unnecessary but they test a bit of template machinery :)
  707. set.clear();
  708. set.shrink_to_fit();
  709. set = decltype(set){};
  710. }