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