sparse_set.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  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/sparse_set.hpp>
  9. #include <entt/entity/fwd.hpp>
  10. struct empty_type {};
  11. struct boxed_int { int value; };
  12. TEST(SparseSet, Functionalities) {
  13. entt::sparse_set set;
  14. set.reserve(42);
  15. ASSERT_EQ(set.capacity(), 42u);
  16. ASSERT_TRUE(set.empty());
  17. ASSERT_EQ(set.size(), 0u);
  18. ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
  19. ASSERT_EQ(set.begin(), set.end());
  20. ASSERT_FALSE(set.contains(entt::entity{0}));
  21. ASSERT_FALSE(set.contains(entt::entity{42}));
  22. set.emplace(entt::entity{42});
  23. ASSERT_FALSE(set.empty());
  24. ASSERT_EQ(set.size(), 1u);
  25. ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
  26. ASSERT_NE(set.begin(), set.end());
  27. ASSERT_FALSE(set.contains(entt::entity{0}));
  28. ASSERT_TRUE(set.contains(entt::entity{42}));
  29. ASSERT_EQ(set.index(entt::entity{42}), 0u);
  30. ASSERT_EQ(set.at(0u), entt::entity{42});
  31. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  32. ASSERT_EQ(set[0u], entt::entity{42});
  33. set.remove(entt::entity{42});
  34. ASSERT_TRUE(set.empty());
  35. ASSERT_EQ(set.size(), 0u);
  36. ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
  37. ASSERT_EQ(set.begin(), set.end());
  38. ASSERT_FALSE(set.contains(entt::entity{0}));
  39. ASSERT_FALSE(set.contains(entt::entity{42}));
  40. ASSERT_EQ(set.at(0u), static_cast<entt::entity>(entt::null));
  41. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  42. set.emplace(entt::entity{42});
  43. ASSERT_FALSE(set.empty());
  44. ASSERT_EQ(set.index(entt::entity{42}), 0u);
  45. ASSERT_EQ(set.at(0u), entt::entity{42});
  46. ASSERT_EQ(set.at(1u), static_cast<entt::entity>(entt::null));
  47. ASSERT_EQ(set[0u], entt::entity{42});
  48. ASSERT_TRUE(std::is_move_constructible_v<decltype(set)>);
  49. ASSERT_TRUE(std::is_move_assignable_v<decltype(set)>);
  50. entt::sparse_set other{std::move(set)};
  51. set = std::move(other);
  52. other = std::move(set);
  53. ASSERT_TRUE(set.empty());
  54. ASSERT_EQ(set.at(0u), static_cast<entt::entity>(entt::null));
  55. ASSERT_FALSE(other.empty());
  56. ASSERT_EQ(other.index(entt::entity{42}), 0u);
  57. ASSERT_EQ(other.at(0u), entt::entity{42});
  58. ASSERT_EQ(other.at(1u), static_cast<entt::entity>(entt::null));
  59. ASSERT_EQ(other[0u], entt::entity{42});
  60. other.clear();
  61. ASSERT_TRUE(other.empty());
  62. ASSERT_EQ(other.size(), 0u);
  63. ASSERT_EQ(std::as_const(other).begin(), std::as_const(other).end());
  64. ASSERT_EQ(other.begin(), other.end());
  65. ASSERT_FALSE(other.contains(entt::entity{0}));
  66. ASSERT_FALSE(other.contains(entt::entity{42}));
  67. }
  68. TEST(SparseSet, Pagination) {
  69. entt::sparse_set set;
  70. constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(entt::entity);
  71. ASSERT_EQ(set.extent(), 0u);
  72. set.emplace(entt::entity{entt_per_page-1});
  73. ASSERT_EQ(set.extent(), entt_per_page);
  74. ASSERT_TRUE(set.contains(entt::entity{entt_per_page-1}));
  75. set.emplace(entt::entity{entt_per_page});
  76. ASSERT_EQ(set.extent(), 2 * entt_per_page);
  77. ASSERT_TRUE(set.contains(entt::entity{entt_per_page-1}));
  78. ASSERT_TRUE(set.contains(entt::entity{entt_per_page}));
  79. ASSERT_FALSE(set.contains(entt::entity{entt_per_page+1}));
  80. set.remove(entt::entity{entt_per_page-1});
  81. ASSERT_EQ(set.extent(), 2 * entt_per_page);
  82. ASSERT_FALSE(set.contains(entt::entity{entt_per_page-1}));
  83. ASSERT_TRUE(set.contains(entt::entity{entt_per_page}));
  84. set.shrink_to_fit();
  85. set.remove(entt::entity{entt_per_page});
  86. ASSERT_EQ(set.extent(), 2 * entt_per_page);
  87. ASSERT_FALSE(set.contains(entt::entity{entt_per_page-1}));
  88. ASSERT_FALSE(set.contains(entt::entity{entt_per_page}));
  89. set.shrink_to_fit();
  90. ASSERT_EQ(set.extent(), 0u);
  91. }
  92. TEST(SparseSet, Insert) {
  93. entt::sparse_set set;
  94. entt::entity entities[2];
  95. entities[0] = entt::entity{3};
  96. entities[1] = entt::entity{42};
  97. set.emplace(entt::entity{12});
  98. set.insert(std::begin(entities), std::end(entities));
  99. set.emplace(entt::entity{24});
  100. ASSERT_TRUE(set.contains(entities[0]));
  101. ASSERT_TRUE(set.contains(entities[1]));
  102. ASSERT_FALSE(set.contains(entt::entity{0}));
  103. ASSERT_FALSE(set.contains(entt::entity{9}));
  104. ASSERT_TRUE(set.contains(entt::entity{12}));
  105. ASSERT_TRUE(set.contains(entt::entity{24}));
  106. ASSERT_FALSE(set.empty());
  107. ASSERT_EQ(set.size(), 4u);
  108. ASSERT_EQ(set.index(entt::entity{12}), 0u);
  109. ASSERT_EQ(set.index(entities[0]), 1u);
  110. ASSERT_EQ(set.index(entities[1]), 2u);
  111. ASSERT_EQ(set.index(entt::entity{24}), 3u);
  112. ASSERT_EQ(set.data()[set.index(entt::entity{12})], entt::entity{12});
  113. ASSERT_EQ(set.data()[set.index(entities[0])], entities[0]);
  114. ASSERT_EQ(set.data()[set.index(entities[1])], entities[1]);
  115. ASSERT_EQ(set.data()[set.index(entt::entity{24})], entt::entity{24});
  116. }
  117. TEST(SparseSet, Remove) {
  118. entt::sparse_set set;
  119. entt::entity entities[3];
  120. entities[0] = entt::entity{3};
  121. entities[1] = entt::entity{42};
  122. entities[2] = entt::entity{9};
  123. set.insert(std::begin(entities), std::end(entities));
  124. set.remove(set.begin(), set.end());
  125. ASSERT_TRUE(set.empty());
  126. set.insert(std::begin(entities), std::end(entities));
  127. set.remove(set.begin(), set.end());
  128. ASSERT_TRUE(set.empty());
  129. set.insert(std::begin(entities), std::end(entities));
  130. set.remove(entities, entities + 2u);
  131. ASSERT_FALSE(set.empty());
  132. ASSERT_EQ(*set.begin(), entt::entity{9});
  133. set.clear();
  134. set.insert(std::begin(entities), std::end(entities));
  135. std::swap(entities[1], entities[2]);
  136. set.remove(entities, entities + 2u);
  137. ASSERT_FALSE(set.empty());
  138. ASSERT_EQ(*set.begin(), entt::entity{42});
  139. }
  140. TEST(SparseSet, Clear) {
  141. entt::sparse_set set;
  142. set.emplace(entt::entity{3});
  143. set.emplace(entt::entity{42});
  144. set.emplace(entt::entity{9});
  145. ASSERT_FALSE(set.empty());
  146. set.clear();
  147. ASSERT_TRUE(set.empty());
  148. }
  149. TEST(SparseSet, Iterator) {
  150. using iterator = typename entt::sparse_set::iterator;
  151. entt::sparse_set set;
  152. set.emplace(entt::entity{3});
  153. iterator end{set.begin()};
  154. iterator begin{};
  155. begin = set.end();
  156. std::swap(begin, end);
  157. ASSERT_EQ(begin, set.begin());
  158. ASSERT_EQ(end, set.end());
  159. ASSERT_NE(begin, end);
  160. ASSERT_EQ(begin++, set.begin());
  161. ASSERT_EQ(begin--, set.end());
  162. ASSERT_EQ(begin+1, set.end());
  163. ASSERT_EQ(end-1, set.begin());
  164. ASSERT_EQ(++begin, set.end());
  165. ASSERT_EQ(--begin, set.begin());
  166. ASSERT_EQ(begin += 1, set.end());
  167. ASSERT_EQ(begin -= 1, set.begin());
  168. ASSERT_EQ(begin + (end - begin), set.end());
  169. ASSERT_EQ(begin - (begin - end), set.end());
  170. ASSERT_EQ(end - (end - begin), set.begin());
  171. ASSERT_EQ(end + (begin - end), set.begin());
  172. ASSERT_EQ(begin[0], *set.begin());
  173. ASSERT_LT(begin, end);
  174. ASSERT_LE(begin, set.begin());
  175. ASSERT_GT(end, begin);
  176. ASSERT_GE(end, set.end());
  177. ASSERT_EQ(*begin, entt::entity{3});
  178. ASSERT_EQ(*begin.operator->(), entt::entity{3});
  179. }
  180. TEST(SparseSet, ReverseIterator) {
  181. using reverse_iterator = typename entt::sparse_set::reverse_iterator;
  182. entt::sparse_set set;
  183. set.emplace(entt::entity{3});
  184. reverse_iterator end{set.rbegin()};
  185. reverse_iterator begin{};
  186. begin = set.rend();
  187. std::swap(begin, end);
  188. ASSERT_EQ(begin, set.rbegin());
  189. ASSERT_EQ(end, set.rend());
  190. ASSERT_NE(begin, end);
  191. ASSERT_EQ(begin++, set.rbegin());
  192. ASSERT_EQ(begin--, set.rend());
  193. ASSERT_EQ(begin+1, set.rend());
  194. ASSERT_EQ(end-1, set.rbegin());
  195. ASSERT_EQ(++begin, set.rend());
  196. ASSERT_EQ(--begin, set.rbegin());
  197. ASSERT_EQ(begin += 1, set.rend());
  198. ASSERT_EQ(begin -= 1, set.rbegin());
  199. ASSERT_EQ(begin + (end - begin), set.rend());
  200. ASSERT_EQ(begin - (begin - end), set.rend());
  201. ASSERT_EQ(end - (end - begin), set.rbegin());
  202. ASSERT_EQ(end + (begin - end), set.rbegin());
  203. ASSERT_EQ(begin[0], *set.rbegin());
  204. ASSERT_LT(begin, end);
  205. ASSERT_LE(begin, set.rbegin());
  206. ASSERT_GT(end, begin);
  207. ASSERT_GE(end, set.rend());
  208. ASSERT_EQ(*begin, entt::entity{3});
  209. }
  210. TEST(SparseSet, Find) {
  211. entt::sparse_set set;
  212. set.emplace(entt::entity{3});
  213. set.emplace(entt::entity{42});
  214. set.emplace(entt::entity{99});
  215. ASSERT_NE(set.find(entt::entity{3}), set.end());
  216. ASSERT_NE(set.find(entt::entity{42}), set.end());
  217. ASSERT_NE(set.find(entt::entity{99}), set.end());
  218. ASSERT_EQ(set.find(entt::entity{0}), set.end());
  219. auto it = set.find(entt::entity{99});
  220. ASSERT_EQ(*it, entt::entity{99});
  221. ASSERT_EQ(*(++it), entt::entity{42});
  222. ASSERT_EQ(*(++it), entt::entity{3});
  223. ASSERT_EQ(++it, set.end());
  224. ASSERT_EQ(++set.find(entt::entity{3}), set.end());
  225. }
  226. TEST(SparseSet, Data) {
  227. entt::sparse_set set;
  228. set.emplace(entt::entity{3});
  229. set.emplace(entt::entity{12});
  230. set.emplace(entt::entity{42});
  231. ASSERT_EQ(set.index(entt::entity{3}), 0u);
  232. ASSERT_EQ(set.index(entt::entity{12}), 1u);
  233. ASSERT_EQ(set.index(entt::entity{42}), 2u);
  234. ASSERT_EQ(set.data()[0u], entt::entity{3});
  235. ASSERT_EQ(set.data()[1u], entt::entity{12});
  236. ASSERT_EQ(set.data()[2u], entt::entity{42});
  237. }
  238. TEST(SparseSet, SortOrdered) {
  239. entt::sparse_set set;
  240. entt::entity entities[5u]{entt::entity{42}, entt::entity{12}, entt::entity{9}, entt::entity{7}, entt::entity{3}};
  241. set.insert(std::begin(entities), std::end(entities));
  242. set.sort(std::less{});
  243. ASSERT_TRUE(std::equal(std::rbegin(entities), std::rend(entities), set.begin(), set.end()));
  244. }
  245. TEST(SparseSet, SortReverse) {
  246. entt::sparse_set set;
  247. entt::entity entities[5u]{entt::entity{3}, entt::entity{7}, entt::entity{9}, entt::entity{12}, entt::entity{42}};
  248. set.insert(std::begin(entities), std::end(entities));
  249. set.sort(std::less{});
  250. ASSERT_TRUE(std::equal(std::begin(entities), std::end(entities), set.begin(), set.end()));
  251. }
  252. TEST(SparseSet, SortUnordered) {
  253. entt::sparse_set set;
  254. entt::entity entities[5u]{entt::entity{9}, entt::entity{7}, entt::entity{3}, entt::entity{12}, entt::entity{42}};
  255. set.insert(std::begin(entities), std::end(entities));
  256. set.sort(std::less{});
  257. auto begin = set.begin();
  258. auto end = set.end();
  259. ASSERT_EQ(*(begin++), entt::entity{3});
  260. ASSERT_EQ(*(begin++), entt::entity{7});
  261. ASSERT_EQ(*(begin++), entt::entity{9});
  262. ASSERT_EQ(*(begin++), entt::entity{12});
  263. ASSERT_EQ(*(begin++), entt::entity{42});
  264. ASSERT_EQ(begin, end);
  265. }
  266. TEST(SparseSet, SortRange) {
  267. entt::sparse_set set;
  268. entt::entity entities[5u]{entt::entity{7}, entt::entity{9}, entt::entity{3}, entt::entity{12}, entt::entity{42}};
  269. set.insert(std::begin(entities), std::end(entities));
  270. set.sort_n(0u, std::less{});
  271. ASSERT_TRUE(std::equal(std::rbegin(entities), std::rend(entities), set.begin(), set.end()));
  272. set.sort_n(2u, std::less{});
  273. ASSERT_EQ(set.data()[0u], entt::entity{9});
  274. ASSERT_EQ(set.data()[1u], entt::entity{7});
  275. ASSERT_EQ(set.data()[2u], entt::entity{3});
  276. set.sort_n(5u, std::less{});
  277. auto begin = set.begin();
  278. auto end = set.end();
  279. ASSERT_EQ(*(begin++), entt::entity{3});
  280. ASSERT_EQ(*(begin++), entt::entity{7});
  281. ASSERT_EQ(*(begin++), entt::entity{9});
  282. ASSERT_EQ(*(begin++), entt::entity{12});
  283. ASSERT_EQ(*(begin++), entt::entity{42});
  284. ASSERT_EQ(begin, end);
  285. }
  286. TEST(SparseSet, RespectDisjoint) {
  287. entt::sparse_set lhs;
  288. entt::sparse_set rhs;
  289. entt::entity lhs_entities[3u]{entt::entity{3}, entt::entity{12}, entt::entity{42}};
  290. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  291. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  292. lhs.respect(rhs);
  293. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  294. }
  295. TEST(SparseSet, RespectOverlap) {
  296. entt::sparse_set lhs;
  297. entt::sparse_set rhs;
  298. entt::entity lhs_entities[3u]{entt::entity{3}, entt::entity{12}, entt::entity{42}};
  299. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  300. entt::entity rhs_entities[1u]{entt::entity{12}};
  301. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  302. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  303. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  304. lhs.respect(rhs);
  305. auto begin = lhs.begin();
  306. auto end = lhs.end();
  307. ASSERT_EQ(*(begin++), entt::entity{12});
  308. ASSERT_EQ(*(begin++), entt::entity{42});
  309. ASSERT_EQ(*(begin++), entt::entity{3});
  310. ASSERT_EQ(begin, end);
  311. }
  312. TEST(SparseSet, RespectOrdered) {
  313. entt::sparse_set lhs;
  314. entt::sparse_set rhs;
  315. entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  316. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  317. entt::entity rhs_entities[6u]{entt::entity{6}, entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  318. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  319. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  320. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  321. rhs.respect(lhs);
  322. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  323. }
  324. TEST(SparseSet, RespectReverse) {
  325. entt::sparse_set lhs;
  326. entt::sparse_set rhs;
  327. entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  328. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  329. entt::entity rhs_entities[6u]{entt::entity{5}, entt::entity{4}, entt::entity{3}, entt::entity{2}, entt::entity{1}, entt::entity{6}};
  330. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  331. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  332. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  333. rhs.respect(lhs);
  334. auto begin = rhs.begin();
  335. auto end = rhs.end();
  336. ASSERT_EQ(*(begin++), entt::entity{5});
  337. ASSERT_EQ(*(begin++), entt::entity{4});
  338. ASSERT_EQ(*(begin++), entt::entity{3});
  339. ASSERT_EQ(*(begin++), entt::entity{2});
  340. ASSERT_EQ(*(begin++), entt::entity{1});
  341. ASSERT_EQ(*(begin++), entt::entity{6});
  342. ASSERT_EQ(begin, end);
  343. }
  344. TEST(SparseSet, RespectUnordered) {
  345. entt::sparse_set lhs;
  346. entt::sparse_set rhs;
  347. entt::entity lhs_entities[5u]{entt::entity{1}, entt::entity{2}, entt::entity{3}, entt::entity{4}, entt::entity{5}};
  348. lhs.insert(std::begin(lhs_entities), std::end(lhs_entities));
  349. entt::entity rhs_entities[6u]{entt::entity{3}, entt::entity{2}, entt::entity{6}, entt::entity{1}, entt::entity{4}, entt::entity{5}};
  350. rhs.insert(std::begin(rhs_entities), std::end(rhs_entities));
  351. ASSERT_TRUE(std::equal(std::rbegin(lhs_entities), std::rend(lhs_entities), lhs.begin(), lhs.end()));
  352. ASSERT_TRUE(std::equal(std::rbegin(rhs_entities), std::rend(rhs_entities), rhs.begin(), rhs.end()));
  353. rhs.respect(lhs);
  354. auto begin = rhs.begin();
  355. auto end = rhs.end();
  356. ASSERT_EQ(*(begin++), entt::entity{5});
  357. ASSERT_EQ(*(begin++), entt::entity{4});
  358. ASSERT_EQ(*(begin++), entt::entity{3});
  359. ASSERT_EQ(*(begin++), entt::entity{2});
  360. ASSERT_EQ(*(begin++), entt::entity{1});
  361. ASSERT_EQ(*(begin++), entt::entity{6});
  362. ASSERT_EQ(begin, end);
  363. }
  364. TEST(SparseSet, CanModifyDuringIteration) {
  365. entt::sparse_set set;
  366. set.emplace(entt::entity{0});
  367. ASSERT_EQ(set.capacity(), 1u);
  368. const auto it = set.begin();
  369. set.reserve(2u);
  370. ASSERT_EQ(set.capacity(), 2u);
  371. // this should crash with asan enabled if we break the constraint
  372. const auto entity = *it;
  373. (void)entity;
  374. }