index_set.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #include "catch2/catch.hpp"
  19. #include "index_set.hpp"
  20. #include "util/index_helpers.hpp"
  21. TEST_CASE("index_set: contains()") {
  22. SECTION("returns false if the index is before the first entry in the set") {
  23. realm::IndexSet set = {1, 2, 5};
  24. REQUIRE_FALSE(set.contains(0));
  25. }
  26. SECTION("returns false if the index is after the last entry in the set") {
  27. realm::IndexSet set = {1, 2, 5};
  28. REQUIRE_FALSE(set.contains(6));
  29. }
  30. SECTION("returns false if the index is between ranges in the set") {
  31. realm::IndexSet set = {1, 2, 5};
  32. REQUIRE_FALSE(set.contains(4));
  33. }
  34. SECTION("returns true if the index is in the set") {
  35. realm::IndexSet set = {1, 2, 5};
  36. REQUIRE(set.contains(1));
  37. REQUIRE(set.contains(2));
  38. REQUIRE(set.contains(5));
  39. }
  40. }
  41. TEST_CASE("index_set: count()") {
  42. SECTION("returns the number of indices in the set in the given range") {
  43. realm::IndexSet set = {1, 2, 3, 5};
  44. REQUIRE(set.count(0, 6) == 4);
  45. REQUIRE(set.count(0, 5) == 3);
  46. REQUIRE(set.count(0, 4) == 3);
  47. REQUIRE(set.count(0, 3) == 2);
  48. REQUIRE(set.count(0, 2) == 1);
  49. REQUIRE(set.count(0, 1) == 0);
  50. REQUIRE(set.count(0, 0) == 0);
  51. REQUIRE(set.count(0, 6) == 4);
  52. REQUIRE(set.count(1, 6) == 4);
  53. REQUIRE(set.count(2, 6) == 3);
  54. REQUIRE(set.count(3, 6) == 2);
  55. REQUIRE(set.count(4, 6) == 1);
  56. REQUIRE(set.count(5, 6) == 1);
  57. REQUIRE(set.count(6, 6) == 0);
  58. }
  59. SECTION("includes full ranges in the middle") {
  60. realm::IndexSet set = {1, 3, 4, 5, 10};
  61. REQUIRE(set.count(0, 11) == 5);
  62. }
  63. SECTION("truncates ranges at the beginning and end") {
  64. realm::IndexSet set = {1, 2, 3, 5, 6, 7, 8, 9};
  65. REQUIRE(set.count(3, 9) == 5);
  66. }
  67. SECTION("handles full chunks well") {
  68. size_t count = realm::_impl::ChunkedRangeVector::max_size * 4;
  69. realm::IndexSet set;
  70. for (size_t i = 0; i < count; ++i) {
  71. set.add(i * 3);
  72. set.add(i * 3 + 1);
  73. }
  74. for (size_t i = 0; i < count * 3; ++i) {
  75. REQUIRE(set.count(i) == 2 * count - (i + 1) * 2 / 3);
  76. REQUIRE(set.count(0, i) == (i + 1) / 3 + (i + 2) / 3);
  77. }
  78. }
  79. }
  80. TEST_CASE("index_set: add()") {
  81. realm::IndexSet set;
  82. SECTION("extends existing ranges when next to an edge") {
  83. set.add(1);
  84. REQUIRE_INDICES(set, 1);
  85. set.add(2);
  86. REQUIRE_INDICES(set, 1, 2);
  87. set.add(0);
  88. REQUIRE_INDICES(set, 0, 1, 2);
  89. }
  90. SECTION("does not extend ranges over gaps") {
  91. set.add(0);
  92. REQUIRE_INDICES(set, 0);
  93. set.add(2);
  94. REQUIRE_INDICES(set, 0, 2);
  95. }
  96. SECTION("does nothing when the index is already in the set") {
  97. set.add(0);
  98. set.add(0);
  99. REQUIRE_INDICES(set, 0);
  100. }
  101. SECTION("merges existing ranges when adding the index between them") {
  102. set = {0, 2, 4};
  103. set.add(1);
  104. REQUIRE_INDICES(set, 0, 1, 2, 4);
  105. }
  106. SECTION("combines multiple index sets without any shifting") {
  107. set = {0, 2, 6};
  108. set.add({1, 4, 5});
  109. REQUIRE_INDICES(set, 0, 1, 2, 4, 5, 6);
  110. }
  111. SECTION("handles front additions of ranges") {
  112. for (size_t i = 20; i > 0; i -= 2)
  113. set.add(i);
  114. REQUIRE_INDICES(set, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20);
  115. }
  116. SECTION("merges ranges even when they are in different chunks") {
  117. realm::IndexSet set2;
  118. for (int i = 0; i < 20; ++i) {
  119. set.add(i * 2);
  120. set2.add(i);
  121. set2.add(i * 2);
  122. }
  123. set.add(set2);
  124. REQUIRE(set.count() == 30);
  125. }
  126. }
  127. TEST_CASE("index_set: add_shifted()") {
  128. realm::IndexSet set;
  129. SECTION("on an empty set is just add()") {
  130. set.add_shifted(5);
  131. REQUIRE_INDICES(set, 5);
  132. }
  133. SECTION("before the first range is just add()") {
  134. set = {10};
  135. set.add_shifted(5);
  136. REQUIRE_INDICES(set, 5, 10);
  137. }
  138. SECTION("on first index of a range extends the range") {
  139. set = {5};
  140. set.add_shifted(5);
  141. REQUIRE_INDICES(set, 5, 6);
  142. set.add_shifted(5);
  143. REQUIRE_INDICES(set, 5, 6, 7);
  144. }
  145. SECTION("in the middle of a range is shifted by that range") {
  146. set = {5, 6, 7};
  147. set.add_shifted(6);
  148. REQUIRE_INDICES(set, 5, 6, 7, 9);
  149. }
  150. SECTION("after the last range adds the total count to the index to be added") {
  151. set = {5};
  152. set.add_shifted(6);
  153. REQUIRE_INDICES(set, 5, 7);
  154. set.add_shifted(10);
  155. REQUIRE_INDICES(set, 5, 7, 12);
  156. }
  157. SECTION("in between ranges can be bumped into the next range") {
  158. set = {5, 7};
  159. set.add_shifted(6);
  160. REQUIRE_INDICES(set, 5, 7, 8);
  161. }
  162. }
  163. TEST_CASE("index_set: add_shifted_by()") {
  164. realm::IndexSet set;
  165. SECTION("does nothing given an empty set to add") {
  166. set = {5, 6, 7};
  167. set.add_shifted_by({5, 6}, {});
  168. REQUIRE_INDICES(set, 5, 6, 7);
  169. }
  170. SECTION("does nothing if values is a subset of shifted_by") {
  171. set = {5, 6, 7};
  172. set.add_shifted_by({3, 4}, {3, 4});
  173. REQUIRE_INDICES(set, 5, 6, 7);
  174. }
  175. SECTION("just adds the indices when they are all before the old indices and the shifted-by set is empty") {
  176. set = {5, 6};
  177. set.add_shifted_by({}, {3, 4});
  178. REQUIRE_INDICES(set, 3, 4, 5, 6);
  179. }
  180. SECTION("adds the indices shifted by the old count when they are all after the old indices and the shifted-by set is empty") {
  181. set = {5, 6};
  182. set.add_shifted_by({}, {7, 9, 11, 13});
  183. REQUIRE_INDICES(set, 5, 6, 9, 11, 13, 15);
  184. }
  185. SECTION("acts like bulk add_shifted() when shifted_by is empty") {
  186. set = {5, 10, 15, 20, 25};
  187. set.add_shifted_by({}, {4, 5, 11});
  188. REQUIRE_INDICES(set, 4, 5, 6, 10, 13, 15, 20, 25);
  189. }
  190. SECTION("shifts indices in values back by the number of indices in shifted_by before them") {
  191. set = {5};
  192. set.add_shifted_by({0, 2, 3}, {6});
  193. REQUIRE_INDICES(set, 3, 5);
  194. set = {5};
  195. set.add_shifted_by({1, 3}, {4});
  196. REQUIRE_INDICES(set, 2, 5);
  197. }
  198. SECTION("discards indices in both shifted_by and values") {
  199. set = {5};
  200. set.add_shifted_by({2}, {2, 4});
  201. REQUIRE_INDICES(set, 3, 5);
  202. }
  203. }
  204. TEST_CASE("index_set: set()") {
  205. realm::IndexSet set;
  206. SECTION("clears the existing indices and replaces with the range [0, value)") {
  207. set = {8, 9};
  208. set.set(5);
  209. REQUIRE_INDICES(set, 0, 1, 2, 3, 4);
  210. }
  211. }
  212. TEST_CASE("index_set: insert_at()") {
  213. realm::IndexSet set;
  214. SECTION("on an empty set is add()") {
  215. set.insert_at(5);
  216. REQUIRE_INDICES(set, 5);
  217. set = {};
  218. set.insert_at({1, 3, 5});
  219. REQUIRE_INDICES(set, 1, 3, 5);
  220. }
  221. SECTION("with an empty set is a no-op") {
  222. set = {5, 6};
  223. set.insert_at(realm::IndexSet{});
  224. REQUIRE_INDICES(set, 5, 6);
  225. }
  226. SECTION("extends ranges containing the target range") {
  227. set = {5, 6};
  228. set.insert_at(5);
  229. REQUIRE_INDICES(set, 5, 6, 7);
  230. set.insert_at(6, 2);
  231. REQUIRE_INDICES(set, 5, 6, 7, 8, 9);
  232. set.insert_at({5, 7, 11});
  233. REQUIRE_INDICES(set, 5, 6, 7, 8, 9, 10, 11, 12);
  234. }
  235. SECTION("shifts ranges after the insertion point") {
  236. set = {5, 6};
  237. set.insert_at(3);
  238. REQUIRE_INDICES(set, 3, 6, 7);
  239. set.insert_at(0, 2);
  240. REQUIRE_INDICES(set, 0, 1, 5, 8, 9);
  241. }
  242. SECTION("does not shift ranges before the insertion point") {
  243. set = {5, 6};
  244. set.insert_at(10);
  245. REQUIRE_INDICES(set, 5, 6, 10);
  246. set.insert_at({15, 16});
  247. REQUIRE_INDICES(set, 5, 6, 10, 15, 16);
  248. }
  249. SECTION("can not join ranges") {
  250. set = {5, 7};
  251. set.insert_at(6);
  252. REQUIRE_INDICES(set, 5, 6, 8);
  253. }
  254. SECTION("adds later ranges after shifting for previous insertions") {
  255. set = {5, 10};
  256. set.insert_at({5, 10});
  257. REQUIRE_INDICES(set, 5, 6, 10, 12);
  258. }
  259. }
  260. TEST_CASE("index_set: shift_for_insert_at()") {
  261. realm::IndexSet set;
  262. SECTION("does nothing given an empty set of insertion points") {
  263. set = {5, 8};
  264. set.shift_for_insert_at(realm::IndexSet{});
  265. REQUIRE_INDICES(set, 5, 8);
  266. }
  267. SECTION("does nothing when called on an empty set") {
  268. set = {};
  269. set.shift_for_insert_at({5, 8});
  270. REQUIRE(set.empty());
  271. }
  272. SECTION("does nothing when the insertion points are all after the current indices") {
  273. set = {10, 20};
  274. set.shift_for_insert_at({30, 40});
  275. REQUIRE_INDICES(set, 10, 20);
  276. }
  277. SECTION("does shift when the insertion points are all before the current indices") {
  278. set = {10, 20};
  279. set.shift_for_insert_at({2, 4});
  280. REQUIRE_INDICES(set, 12, 22);
  281. }
  282. SECTION("shifts indices at or after the insertion points") {
  283. set = {5};
  284. set.shift_for_insert_at(4);
  285. REQUIRE_INDICES(set, 6);
  286. set.shift_for_insert_at(6);
  287. REQUIRE_INDICES(set, 7);
  288. set.shift_for_insert_at({3, 8});
  289. REQUIRE_INDICES(set, 9);
  290. }
  291. SECTION("shifts indices by the count specified") {
  292. set = {5};
  293. set.shift_for_insert_at(3, 10);
  294. REQUIRE_INDICES(set, 15);
  295. }
  296. SECTION("does not shift indices before the insertion points") {
  297. set = {5};
  298. set.shift_for_insert_at(6);
  299. REQUIRE_INDICES(set, 5);
  300. set.shift_for_insert_at({3, 8});
  301. REQUIRE_INDICES(set, 6);
  302. }
  303. SECTION("splits ranges containing the insertion points") {
  304. set = {5, 6, 7, 8};
  305. set.shift_for_insert_at(6);
  306. REQUIRE_INDICES(set, 5, 7, 8, 9);
  307. set.shift_for_insert_at({8, 10, 12});
  308. REQUIRE_INDICES(set, 5, 7, 9, 11);
  309. }
  310. }
  311. TEST_CASE("index_set: erase_at()") {
  312. realm::IndexSet set;
  313. SECTION("is a no-op on an empty set") {
  314. set.erase_at(10);
  315. REQUIRE(set.empty());
  316. set.erase_at({1, 5, 8});
  317. REQUIRE(set.empty());
  318. }
  319. SECTION("does nothing when given an empty set") {
  320. set = {5};
  321. set.erase_at(realm::IndexSet{});
  322. REQUIRE_INDICES(set, 5);
  323. }
  324. SECTION("removes the specified indices") {
  325. set = {5};
  326. set.erase_at(5);
  327. REQUIRE(set.empty());
  328. set = {4, 7};
  329. set.erase_at({4, 7});
  330. REQUIRE(set.empty());
  331. }
  332. SECTION("does not modify indices before the removed one") {
  333. set = {5, 8};
  334. set.erase_at(8);
  335. REQUIRE_INDICES(set, 5);
  336. set = {5, 8, 9};
  337. set.erase_at({8, 9});
  338. REQUIRE_INDICES(set, 5);
  339. }
  340. SECTION("shifts indices after the removed one") {
  341. set = {5, 8};
  342. set.erase_at(5);
  343. REQUIRE_INDICES(set, 7);
  344. set = {5, 10, 15, 20};
  345. set.erase_at({5, 10});
  346. REQUIRE_INDICES(set, 13, 18);
  347. }
  348. SECTION("shrinks ranges when used on one of the edges of them") {
  349. set = {5, 6, 7, 8};
  350. set.erase_at(8);
  351. REQUIRE_INDICES(set, 5, 6, 7);
  352. set.erase_at(5);
  353. REQUIRE_INDICES(set, 5, 6);
  354. set = {5, 6, 7, 8};
  355. set.erase_at({5, 8});
  356. REQUIRE_INDICES(set, 5, 6);
  357. }
  358. SECTION("shrinks ranges when used in the middle of them") {
  359. set = {5, 6, 7, 8};
  360. set.erase_at(7);
  361. REQUIRE_INDICES(set, 5, 6, 7);
  362. set = {5, 6, 7, 8};
  363. set.erase_at({6, 7});
  364. REQUIRE_INDICES(set, 5, 6);
  365. }
  366. SECTION("merges ranges when the gap between them is deleted") {
  367. set = {3, 5};
  368. set.erase_at(4);
  369. REQUIRE_INDICES(set, 3, 4);
  370. set = {3, 5, 7};
  371. set.erase_at({4, 6});
  372. REQUIRE_INDICES(set, 3, 4, 5);
  373. }
  374. }
  375. TEST_CASE("index_set: erase_or_unshift()") {
  376. realm::IndexSet set;
  377. SECTION("removes the given index") {
  378. set = {1, 2};
  379. set.erase_or_unshift(2);
  380. REQUIRE_INDICES(set, 1);
  381. }
  382. SECTION("shifts indexes after the given index") {
  383. set = {1, 5};
  384. set.erase_or_unshift(2);
  385. REQUIRE_INDICES(set, 1, 4);
  386. }
  387. SECTION("returns npos for indices in the set") {
  388. set = {1, 3, 5};
  389. REQUIRE(realm::IndexSet(set).erase_or_unshift(1) == realm::IndexSet::npos);
  390. REQUIRE(realm::IndexSet(set).erase_or_unshift(3) == realm::IndexSet::npos);
  391. REQUIRE(realm::IndexSet(set).erase_or_unshift(5) == realm::IndexSet::npos);
  392. }
  393. SECTION("returns the number of indices in the set before the index for ones not in the set") {
  394. set = {1, 3, 5, 6};
  395. REQUIRE(realm::IndexSet(set).erase_or_unshift(0) == 0);
  396. REQUIRE(realm::IndexSet(set).erase_or_unshift(2) == 1);
  397. REQUIRE(realm::IndexSet(set).erase_or_unshift(4) == 2);
  398. REQUIRE(realm::IndexSet(set).erase_or_unshift(7) == 3);
  399. }
  400. }
  401. TEST_CASE("index_set: remove()") {
  402. realm::IndexSet set;
  403. SECTION("is a no-op if the set is empty") {
  404. set.remove(4);
  405. REQUIRE(set.empty());
  406. set.remove({1, 2, 3});
  407. REQUIRE(set.empty());
  408. }
  409. SECTION("is a no-op if the set to remove is empty") {
  410. set = {5};
  411. set.remove(realm::IndexSet{});
  412. REQUIRE_INDICES(set, 5);
  413. }
  414. SECTION("is a no-op if the index to remove is not in the set") {
  415. set = {5};
  416. set.remove(4);
  417. set.remove(6);
  418. set.remove({4, 6});
  419. REQUIRE_INDICES(set, 5);
  420. }
  421. SECTION("removes one-element ranges") {
  422. set = {5};
  423. set.remove(5);
  424. REQUIRE(set.empty());
  425. set = {5};
  426. set.remove({3, 4, 5});
  427. REQUIRE(set.empty());
  428. }
  429. SECTION("shrinks ranges beginning with the index") {
  430. set = {5, 6, 7};
  431. set.remove(5);
  432. REQUIRE_INDICES(set, 6, 7);
  433. set = {5, 6, 7};
  434. set.remove({3, 5});
  435. REQUIRE_INDICES(set, 6, 7);
  436. }
  437. SECTION("shrinks ranges ending with the index") {
  438. set = {5, 6, 7};
  439. set.remove(7);
  440. REQUIRE_INDICES(set, 5, 6);
  441. set = {5, 6, 7};
  442. set.remove({3, 7});
  443. REQUIRE_INDICES(set, 5, 6);
  444. }
  445. SECTION("splits ranges containing the index") {
  446. set = {5, 6, 7};
  447. set.remove(6);
  448. REQUIRE_INDICES(set, 5, 7);
  449. set = {5, 6, 7};
  450. set.remove({3, 6});
  451. REQUIRE_INDICES(set, 5, 7);
  452. }
  453. SECTION("does not shift other indices and uses unshifted positions") {
  454. set = {5, 6, 7, 10, 11, 12, 13, 15};
  455. set.remove({6, 11, 13});
  456. REQUIRE_INDICES(set, 5, 7, 10, 12, 15);
  457. }
  458. }
  459. TEST_CASE("index_set: shift()") {
  460. realm::IndexSet set;
  461. SECTION("is ind + count(0, ind), but adds the count-so-far to the stop index") {
  462. set = {1, 3, 5, 6};
  463. REQUIRE(set.shift(0) == 0);
  464. REQUIRE(set.shift(1) == 2);
  465. REQUIRE(set.shift(2) == 4);
  466. REQUIRE(set.shift(3) == 7);
  467. REQUIRE(set.shift(4) == 8);
  468. }
  469. }
  470. TEST_CASE("index_set: unshift()") {
  471. realm::IndexSet set;
  472. SECTION("is index - count(0, index)") {
  473. set = {1, 3, 5, 6};
  474. REQUIRE(set.unshift(0) == 0);
  475. REQUIRE(set.unshift(2) == 1);
  476. REQUIRE(set.unshift(4) == 2);
  477. REQUIRE(set.unshift(7) == 3);
  478. REQUIRE(set.unshift(8) == 4);
  479. }
  480. }
  481. TEST_CASE("index_set: clear()") {
  482. realm::IndexSet set;
  483. SECTION("removes all indices from the set") {
  484. set = {1, 2, 3};
  485. set.clear();
  486. REQUIRE(set.empty());
  487. }
  488. }