BLI_edgehash_test.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /* Apache License, Version 2.0 */
  2. #include "testing/testing.h"
  3. #include <vector>
  4. #include <algorithm>
  5. extern "C" {
  6. #include "BLI_utildefines.h"
  7. #include "BLI_edgehash.h"
  8. }
  9. #define VALUE_1 POINTER_FROM_INT(1)
  10. #define VALUE_2 POINTER_FROM_INT(2)
  11. #define VALUE_3 POINTER_FROM_INT(3)
  12. TEST(edgehash, InsertIncreasesLength)
  13. {
  14. EdgeHash *eh = BLI_edgehash_new(__func__);
  15. ASSERT_EQ(BLI_edgehash_len(eh), 0);
  16. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  17. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  18. BLI_edgehash_free(eh, nullptr);
  19. }
  20. TEST(edgehash, ReinsertNewIncreasesLength)
  21. {
  22. EdgeHash *eh = BLI_edgehash_new(__func__);
  23. ASSERT_EQ(BLI_edgehash_len(eh), 0);
  24. BLI_edgehash_reinsert(eh, 1, 2, VALUE_1);
  25. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  26. BLI_edgehash_free(eh, nullptr);
  27. }
  28. TEST(edgehash, ReinsertExistingDoesNotIncreaseLength)
  29. {
  30. EdgeHash *eh = BLI_edgehash_new(__func__);
  31. ASSERT_EQ(BLI_edgehash_len(eh), 0);
  32. BLI_edgehash_reinsert(eh, 1, 2, VALUE_1);
  33. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  34. BLI_edgehash_reinsert(eh, 1, 2, VALUE_2);
  35. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  36. BLI_edgehash_reinsert(eh, 2, 1, VALUE_2);
  37. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  38. BLI_edgehash_free(eh, nullptr);
  39. }
  40. TEST(edgehash, ReinsertCanChangeValue)
  41. {
  42. EdgeHash *eh = BLI_edgehash_new(__func__);
  43. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  44. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_1);
  45. BLI_edgehash_reinsert(eh, 2, 1, VALUE_2);
  46. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_2);
  47. BLI_edgehash_reinsert(eh, 1, 2, VALUE_3);
  48. ASSERT_EQ(BLI_edgehash_lookup(eh, 2, 1), VALUE_3);
  49. BLI_edgehash_free(eh, nullptr);
  50. }
  51. TEST(edgehash, LookupExisting)
  52. {
  53. EdgeHash *eh = BLI_edgehash_new(__func__);
  54. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  55. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_1);
  56. ASSERT_EQ(BLI_edgehash_lookup(eh, 2, 1), VALUE_1);
  57. BLI_edgehash_free(eh, nullptr);
  58. }
  59. TEST(edgehash, LookupNonExisting)
  60. {
  61. EdgeHash *eh = BLI_edgehash_new(__func__);
  62. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), nullptr);
  63. BLI_edgehash_free(eh, nullptr);
  64. }
  65. TEST(edgehash, LookupNonExistingWithDefault)
  66. {
  67. EdgeHash *eh = BLI_edgehash_new(__func__);
  68. ASSERT_EQ(BLI_edgehash_lookup_default(eh, 1, 2, VALUE_1), VALUE_1);
  69. BLI_edgehash_free(eh, nullptr);
  70. }
  71. TEST(edgehash, LookupExistingWithDefault)
  72. {
  73. EdgeHash *eh = BLI_edgehash_new(__func__);
  74. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  75. ASSERT_EQ(BLI_edgehash_lookup_default(eh, 1, 2, VALUE_2), VALUE_1);
  76. BLI_edgehash_free(eh, nullptr);
  77. }
  78. TEST(edgehash, LookupPExisting)
  79. {
  80. EdgeHash *eh = BLI_edgehash_new(__func__);
  81. void *value = VALUE_1;
  82. BLI_edgehash_insert(eh, 1, 2, value);
  83. void **value_p = BLI_edgehash_lookup_p(eh, 1, 2);
  84. ASSERT_EQ(*value_p, VALUE_1);
  85. *value_p = VALUE_2;
  86. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_2);
  87. BLI_edgehash_free(eh, nullptr);
  88. }
  89. TEST(edgehash, LookupPNonExisting)
  90. {
  91. EdgeHash *eh = BLI_edgehash_new(__func__);
  92. ASSERT_EQ(BLI_edgehash_lookup_p(eh, 1, 2), nullptr);
  93. BLI_edgehash_free(eh, nullptr);
  94. }
  95. TEST(edgehash, EnsurePNonExisting)
  96. {
  97. EdgeHash *eh = BLI_edgehash_new(__func__);
  98. void **value_p;
  99. bool existed = BLI_edgehash_ensure_p(eh, 1, 2, &value_p);
  100. ASSERT_FALSE(existed);
  101. *value_p = VALUE_1;
  102. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_1);
  103. BLI_edgehash_free(eh, nullptr);
  104. }
  105. TEST(edgehash, EnsurePExisting)
  106. {
  107. EdgeHash *eh = BLI_edgehash_new(__func__);
  108. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  109. void **value_p;
  110. bool existed = BLI_edgehash_ensure_p(eh, 1, 2, &value_p);
  111. ASSERT_TRUE(existed);
  112. ASSERT_EQ(*value_p, VALUE_1);
  113. *value_p = VALUE_2;
  114. ASSERT_EQ(BLI_edgehash_lookup(eh, 1, 2), VALUE_2);
  115. BLI_edgehash_free(eh, nullptr);
  116. }
  117. TEST(edgehash, RemoveExistingDecreasesLength)
  118. {
  119. EdgeHash *eh = BLI_edgehash_new(__func__);
  120. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  121. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  122. bool has_been_removed = BLI_edgehash_remove(eh, 1, 2, nullptr);
  123. ASSERT_EQ(BLI_edgehash_len(eh), 0);
  124. ASSERT_TRUE(has_been_removed);
  125. BLI_edgehash_free(eh, nullptr);
  126. }
  127. TEST(edgehash, RemoveNonExistingDoesNotDecreaseLength)
  128. {
  129. EdgeHash *eh = BLI_edgehash_new(__func__);
  130. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  131. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  132. bool has_been_removed = BLI_edgehash_remove(eh, 4, 5, nullptr);
  133. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  134. ASSERT_FALSE(has_been_removed);
  135. BLI_edgehash_free(eh, nullptr);
  136. }
  137. TEST(edgehash, PopKeyTwice)
  138. {
  139. EdgeHash *eh = BLI_edgehash_new(__func__);
  140. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  141. ASSERT_EQ(BLI_edgehash_popkey(eh, 1, 2), VALUE_1);
  142. ASSERT_EQ(BLI_edgehash_popkey(eh, 1, 2), nullptr);
  143. BLI_edgehash_free(eh, nullptr);
  144. }
  145. TEST(edgehash, LookupInvertedIndices)
  146. {
  147. EdgeHash *eh = BLI_edgehash_new(__func__);
  148. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  149. ASSERT_EQ(BLI_edgehash_lookup(eh, 2, 1), VALUE_1);
  150. BLI_edgehash_free(eh, nullptr);
  151. }
  152. TEST(edgehash, HasKeyExisting)
  153. {
  154. EdgeHash *eh = BLI_edgehash_new(__func__);
  155. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  156. ASSERT_TRUE(BLI_edgehash_haskey(eh, 1, 2));
  157. ASSERT_TRUE(BLI_edgehash_haskey(eh, 2, 1));
  158. BLI_edgehash_free(eh, nullptr);
  159. }
  160. TEST(edgehash, HasKeyNonExisting)
  161. {
  162. EdgeHash *eh = BLI_edgehash_new(__func__);
  163. ASSERT_FALSE(BLI_edgehash_haskey(eh, 1, 2));
  164. BLI_edgehash_free(eh, nullptr);
  165. }
  166. TEST(edgehash, ClearSetsLengthToZero)
  167. {
  168. EdgeHash *eh = BLI_edgehash_new(__func__);
  169. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  170. BLI_edgehash_insert(eh, 1, 2, VALUE_2);
  171. ASSERT_EQ(BLI_edgehash_len(eh), 2);
  172. BLI_edgehash_clear(eh, nullptr);
  173. ASSERT_EQ(BLI_edgehash_len(eh), 0);
  174. BLI_edgehash_free(eh, nullptr);
  175. }
  176. TEST(edgehash, IteratorFindsAllValues)
  177. {
  178. EdgeHash *eh = BLI_edgehash_new(__func__);
  179. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  180. BLI_edgehash_insert(eh, 1, 3, VALUE_2);
  181. BLI_edgehash_insert(eh, 1, 4, VALUE_3);
  182. EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh);
  183. auto a = BLI_edgehashIterator_getValue(ehi);
  184. BLI_edgehashIterator_step(ehi);
  185. auto b = BLI_edgehashIterator_getValue(ehi);
  186. BLI_edgehashIterator_step(ehi);
  187. auto c = BLI_edgehashIterator_getValue(ehi);
  188. BLI_edgehashIterator_step(ehi);
  189. ASSERT_NE(a, b);
  190. ASSERT_NE(b, c);
  191. ASSERT_NE(a, c);
  192. ASSERT_TRUE(ELEM(a, VALUE_1, VALUE_2, VALUE_3));
  193. ASSERT_TRUE(ELEM(b, VALUE_1, VALUE_2, VALUE_3));
  194. ASSERT_TRUE(ELEM(c, VALUE_1, VALUE_2, VALUE_3));
  195. BLI_edgehashIterator_free(ehi);
  196. BLI_edgehash_free(eh, nullptr);
  197. }
  198. TEST(edgehash, IterateIsDone)
  199. {
  200. EdgeHash *eh = BLI_edgehash_new(__func__);
  201. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  202. BLI_edgehash_insert(eh, 1, 3, VALUE_2);
  203. BLI_edgehash_insert(eh, 1, 4, VALUE_3);
  204. EdgeHashIterator *ehi = BLI_edgehashIterator_new(eh);
  205. ASSERT_FALSE(BLI_edgehashIterator_isDone(ehi));
  206. BLI_edgehashIterator_step(ehi);
  207. ASSERT_FALSE(BLI_edgehashIterator_isDone(ehi));
  208. BLI_edgehashIterator_step(ehi);
  209. ASSERT_FALSE(BLI_edgehashIterator_isDone(ehi));
  210. BLI_edgehashIterator_step(ehi);
  211. ASSERT_TRUE(BLI_edgehashIterator_isDone(ehi));
  212. BLI_edgehashIterator_free(ehi);
  213. BLI_edgehash_free(eh, nullptr);
  214. }
  215. TEST(edgehash, DoubleRemove)
  216. {
  217. EdgeHash *eh = BLI_edgehash_new(__func__);
  218. BLI_edgehash_insert(eh, 1, 2, VALUE_1);
  219. BLI_edgehash_insert(eh, 1, 3, VALUE_2);
  220. BLI_edgehash_insert(eh, 1, 4, VALUE_3);
  221. ASSERT_EQ(BLI_edgehash_len(eh), 3);
  222. BLI_edgehash_remove(eh, 1, 2, nullptr);
  223. BLI_edgehash_remove(eh, 1, 3, nullptr);
  224. ASSERT_EQ(BLI_edgehash_len(eh), 1);
  225. BLI_edgehash_free(eh, nullptr);
  226. }
  227. struct Edge {
  228. uint v1, v2;
  229. };
  230. TEST(edgehash, StressTest)
  231. {
  232. std::srand(0);
  233. int amount = 10000;
  234. std::vector<Edge> edges;
  235. for (int i = 0; i < amount; i++) {
  236. edges.push_back({(uint)i, amount + (uint)std::rand() % 12345});
  237. }
  238. EdgeHash *eh = BLI_edgehash_new(__func__);
  239. /* first insert all the edges */
  240. for (int i = 0; i < edges.size(); i++) {
  241. BLI_edgehash_insert(eh, edges[i].v1, edges[i].v2, POINTER_FROM_INT(i));
  242. }
  243. std::vector<Edge> shuffled = edges;
  244. std::random_shuffle(shuffled.begin(), shuffled.end());
  245. /* then remove half of them */
  246. int remove_until = shuffled.size() / 2;
  247. for (int i = 0; i < remove_until; i++) {
  248. BLI_edgehash_remove(eh, shuffled[i].v2, shuffled[i].v1, nullptr);
  249. }
  250. ASSERT_EQ(BLI_edgehash_len(eh), edges.size() - remove_until);
  251. /* check if the right ones have been removed */
  252. for (int i = 0; i < shuffled.size(); i++) {
  253. bool haskey = BLI_edgehash_haskey(eh, shuffled[i].v1, shuffled[i].v2);
  254. if (i < remove_until)
  255. ASSERT_FALSE(haskey);
  256. else
  257. ASSERT_TRUE(haskey);
  258. }
  259. /* reinsert all edges */
  260. for (int i = 0; i < edges.size(); i++) {
  261. BLI_edgehash_reinsert(eh, edges[i].v1, edges[i].v2, POINTER_FROM_INT(i));
  262. }
  263. ASSERT_EQ(BLI_edgehash_len(eh), edges.size());
  264. /* pop all edges */
  265. for (int i = 0; i < edges.size(); i++) {
  266. int value = POINTER_AS_INT(BLI_edgehash_popkey(eh, edges[i].v1, edges[i].v2));
  267. ASSERT_EQ(i, value);
  268. }
  269. ASSERT_EQ(BLI_edgehash_len(eh), 0);
  270. BLI_edgehash_free(eh, nullptr);
  271. }
  272. TEST(edgeset, AddNonExistingIncreasesLength)
  273. {
  274. EdgeSet *es = BLI_edgeset_new(__func__);
  275. ASSERT_EQ(BLI_edgeset_len(es), 0);
  276. BLI_edgeset_add(es, 1, 2);
  277. ASSERT_EQ(BLI_edgeset_len(es), 1);
  278. BLI_edgeset_add(es, 1, 3);
  279. ASSERT_EQ(BLI_edgeset_len(es), 2);
  280. BLI_edgeset_add(es, 1, 4);
  281. ASSERT_EQ(BLI_edgeset_len(es), 3);
  282. BLI_edgeset_free(es);
  283. }
  284. TEST(edgeset, AddExistingDoesNotIncreaseLength)
  285. {
  286. EdgeSet *es = BLI_edgeset_new(__func__);
  287. ASSERT_EQ(BLI_edgeset_len(es), 0);
  288. BLI_edgeset_add(es, 1, 2);
  289. ASSERT_EQ(BLI_edgeset_len(es), 1);
  290. BLI_edgeset_add(es, 2, 1);
  291. ASSERT_EQ(BLI_edgeset_len(es), 1);
  292. BLI_edgeset_add(es, 1, 2);
  293. ASSERT_EQ(BLI_edgeset_len(es), 1);
  294. BLI_edgeset_free(es);
  295. }
  296. TEST(edgeset, HasKeyNonExisting)
  297. {
  298. EdgeSet *es = BLI_edgeset_new(__func__);
  299. ASSERT_FALSE(BLI_edgeset_haskey(es, 1, 2));
  300. BLI_edgeset_free(es);
  301. }
  302. TEST(edgeset, HasKeyExisting)
  303. {
  304. EdgeSet *es = BLI_edgeset_new(__func__);
  305. BLI_edgeset_insert(es, 1, 2);
  306. ASSERT_TRUE(BLI_edgeset_haskey(es, 1, 2));
  307. BLI_edgeset_free(es);
  308. }