range_tombstone_fragmenter_test.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #include "db/range_tombstone_fragmenter.h"
  6. #include "db/db_test_util.h"
  7. #include "db/dbformat.h"
  8. #include "rocksdb/comparator.h"
  9. #include "test_util/testutil.h"
  10. #include "util/vector_iterator.h"
  11. namespace ROCKSDB_NAMESPACE {
  12. class RangeTombstoneFragmenterTest : public testing::Test {};
  13. namespace {
  14. static auto bytewise_icmp = InternalKeyComparator(BytewiseComparator());
  15. std::unique_ptr<InternalIterator> MakeRangeDelIter(
  16. const std::vector<RangeTombstone>& range_dels) {
  17. std::vector<std::string> keys, values;
  18. for (const auto& range_del : range_dels) {
  19. auto key_and_value = range_del.Serialize();
  20. keys.push_back(key_and_value.first.Encode().ToString());
  21. values.push_back(key_and_value.second.ToString());
  22. }
  23. return std::unique_ptr<VectorIterator>(
  24. new VectorIterator(keys, values, &bytewise_icmp));
  25. }
  26. void CheckIterPosition(const RangeTombstone& tombstone,
  27. const FragmentedRangeTombstoneIterator* iter) {
  28. // Test InternalIterator interface.
  29. EXPECT_EQ(tombstone.start_key_, ExtractUserKey(iter->key()));
  30. EXPECT_EQ(tombstone.end_key_, iter->value());
  31. EXPECT_EQ(tombstone.seq_, iter->seq());
  32. // Test FragmentedRangeTombstoneIterator interface.
  33. EXPECT_EQ(tombstone.start_key_, iter->start_key());
  34. EXPECT_EQ(tombstone.end_key_, iter->end_key());
  35. EXPECT_EQ(tombstone.seq_, GetInternalKeySeqno(iter->key()));
  36. }
  37. void VerifyFragmentedRangeDels(
  38. FragmentedRangeTombstoneIterator* iter,
  39. const std::vector<RangeTombstone>& expected_tombstones) {
  40. iter->SeekToFirst();
  41. for (size_t i = 0; i < expected_tombstones.size(); i++, iter->Next()) {
  42. ASSERT_TRUE(iter->Valid());
  43. CheckIterPosition(expected_tombstones[i], iter);
  44. }
  45. EXPECT_FALSE(iter->Valid());
  46. }
  47. void VerifyVisibleTombstones(
  48. FragmentedRangeTombstoneIterator* iter,
  49. const std::vector<RangeTombstone>& expected_tombstones) {
  50. iter->SeekToTopFirst();
  51. for (size_t i = 0; i < expected_tombstones.size(); i++, iter->TopNext()) {
  52. ASSERT_TRUE(iter->Valid());
  53. CheckIterPosition(expected_tombstones[i], iter);
  54. }
  55. EXPECT_FALSE(iter->Valid());
  56. }
  57. struct SeekTestCase {
  58. Slice seek_target;
  59. RangeTombstone expected_position;
  60. bool out_of_range;
  61. };
  62. void VerifySeek(FragmentedRangeTombstoneIterator* iter,
  63. const std::vector<SeekTestCase>& cases) {
  64. for (const auto& testcase : cases) {
  65. iter->Seek(testcase.seek_target);
  66. if (testcase.out_of_range) {
  67. ASSERT_FALSE(iter->Valid());
  68. } else {
  69. ASSERT_TRUE(iter->Valid());
  70. CheckIterPosition(testcase.expected_position, iter);
  71. }
  72. }
  73. }
  74. void VerifySeekForPrev(FragmentedRangeTombstoneIterator* iter,
  75. const std::vector<SeekTestCase>& cases) {
  76. for (const auto& testcase : cases) {
  77. iter->SeekForPrev(testcase.seek_target);
  78. if (testcase.out_of_range) {
  79. ASSERT_FALSE(iter->Valid());
  80. } else {
  81. ASSERT_TRUE(iter->Valid());
  82. CheckIterPosition(testcase.expected_position, iter);
  83. }
  84. }
  85. }
  86. struct MaxCoveringTombstoneSeqnumTestCase {
  87. Slice user_key;
  88. SequenceNumber result;
  89. };
  90. void VerifyMaxCoveringTombstoneSeqnum(
  91. FragmentedRangeTombstoneIterator* iter,
  92. const std::vector<MaxCoveringTombstoneSeqnumTestCase>& cases) {
  93. for (const auto& testcase : cases) {
  94. EXPECT_EQ(testcase.result,
  95. iter->MaxCoveringTombstoneSeqnum(testcase.user_key));
  96. }
  97. }
  98. } // anonymous namespace
  99. TEST_F(RangeTombstoneFragmenterTest, NonOverlappingTombstones) {
  100. auto range_del_iter = MakeRangeDelIter({{"a", "b", 10}, {"c", "d", 5}});
  101. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  102. bytewise_icmp);
  103. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  104. kMaxSequenceNumber);
  105. ASSERT_EQ(0, iter.lower_bound());
  106. ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
  107. VerifyFragmentedRangeDels(&iter, {{"a", "b", 10}, {"c", "d", 5}});
  108. VerifyMaxCoveringTombstoneSeqnum(&iter,
  109. {{"", 0}, {"a", 10}, {"b", 0}, {"c", 5}});
  110. }
  111. TEST_F(RangeTombstoneFragmenterTest, OverlappingTombstones) {
  112. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10}, {"c", "g", 15}});
  113. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  114. bytewise_icmp);
  115. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  116. kMaxSequenceNumber);
  117. ASSERT_EQ(0, iter.lower_bound());
  118. ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
  119. VerifyFragmentedRangeDels(
  120. &iter, {{"a", "c", 10}, {"c", "e", 15}, {"c", "e", 10}, {"e", "g", 15}});
  121. VerifyMaxCoveringTombstoneSeqnum(&iter,
  122. {{"a", 10}, {"c", 15}, {"e", 15}, {"g", 0}});
  123. }
  124. TEST_F(RangeTombstoneFragmenterTest, ContiguousTombstones) {
  125. auto range_del_iter = MakeRangeDelIter(
  126. {{"a", "c", 10}, {"c", "e", 20}, {"c", "e", 5}, {"e", "g", 15}});
  127. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  128. bytewise_icmp);
  129. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  130. kMaxSequenceNumber);
  131. ASSERT_EQ(0, iter.lower_bound());
  132. ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
  133. VerifyFragmentedRangeDels(
  134. &iter, {{"a", "c", 10}, {"c", "e", 20}, {"c", "e", 5}, {"e", "g", 15}});
  135. VerifyMaxCoveringTombstoneSeqnum(&iter,
  136. {{"a", 10}, {"c", 20}, {"e", 15}, {"g", 0}});
  137. }
  138. TEST_F(RangeTombstoneFragmenterTest, RepeatedStartAndEndKey) {
  139. auto range_del_iter =
  140. MakeRangeDelIter({{"a", "c", 10}, {"a", "c", 7}, {"a", "c", 3}});
  141. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  142. bytewise_icmp);
  143. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  144. kMaxSequenceNumber);
  145. ASSERT_EQ(0, iter.lower_bound());
  146. ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
  147. VerifyFragmentedRangeDels(&iter,
  148. {{"a", "c", 10}, {"a", "c", 7}, {"a", "c", 3}});
  149. VerifyMaxCoveringTombstoneSeqnum(&iter, {{"a", 10}, {"b", 10}, {"c", 0}});
  150. }
  151. TEST_F(RangeTombstoneFragmenterTest, RepeatedStartKeyDifferentEndKeys) {
  152. auto range_del_iter =
  153. MakeRangeDelIter({{"a", "e", 10}, {"a", "g", 7}, {"a", "c", 3}});
  154. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  155. bytewise_icmp);
  156. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  157. kMaxSequenceNumber);
  158. ASSERT_EQ(0, iter.lower_bound());
  159. ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
  160. VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
  161. {"a", "c", 7},
  162. {"a", "c", 3},
  163. {"c", "e", 10},
  164. {"c", "e", 7},
  165. {"e", "g", 7}});
  166. VerifyMaxCoveringTombstoneSeqnum(&iter,
  167. {{"a", 10}, {"c", 10}, {"e", 7}, {"g", 0}});
  168. }
  169. TEST_F(RangeTombstoneFragmenterTest, RepeatedStartKeyMixedEndKeys) {
  170. auto range_del_iter = MakeRangeDelIter({{"a", "c", 30},
  171. {"a", "g", 20},
  172. {"a", "e", 10},
  173. {"a", "g", 7},
  174. {"a", "c", 3}});
  175. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  176. bytewise_icmp);
  177. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  178. kMaxSequenceNumber);
  179. ASSERT_EQ(0, iter.lower_bound());
  180. ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
  181. VerifyFragmentedRangeDels(&iter, {{"a", "c", 30},
  182. {"a", "c", 20},
  183. {"a", "c", 10},
  184. {"a", "c", 7},
  185. {"a", "c", 3},
  186. {"c", "e", 20},
  187. {"c", "e", 10},
  188. {"c", "e", 7},
  189. {"e", "g", 20},
  190. {"e", "g", 7}});
  191. VerifyMaxCoveringTombstoneSeqnum(&iter,
  192. {{"a", 30}, {"c", 20}, {"e", 20}, {"g", 0}});
  193. }
  194. TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKey) {
  195. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  196. {"c", "g", 8},
  197. {"c", "i", 6},
  198. {"j", "n", 4},
  199. {"j", "l", 2}});
  200. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  201. bytewise_icmp);
  202. FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
  203. kMaxSequenceNumber);
  204. FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
  205. 9 /* upper_bound */);
  206. FragmentedRangeTombstoneIterator iter3(&fragment_list, bytewise_icmp,
  207. 7 /* upper_bound */);
  208. FragmentedRangeTombstoneIterator iter4(&fragment_list, bytewise_icmp,
  209. 5 /* upper_bound */);
  210. FragmentedRangeTombstoneIterator iter5(&fragment_list, bytewise_icmp,
  211. 3 /* upper_bound */);
  212. for (auto* iter : {&iter1, &iter2, &iter3, &iter4, &iter5}) {
  213. VerifyFragmentedRangeDels(iter, {{"a", "c", 10},
  214. {"c", "e", 10},
  215. {"c", "e", 8},
  216. {"c", "e", 6},
  217. {"e", "g", 8},
  218. {"e", "g", 6},
  219. {"g", "i", 6},
  220. {"j", "l", 4},
  221. {"j", "l", 2},
  222. {"l", "n", 4}});
  223. }
  224. ASSERT_EQ(0, iter1.lower_bound());
  225. ASSERT_EQ(kMaxSequenceNumber, iter1.upper_bound());
  226. VerifyVisibleTombstones(&iter1, {{"a", "c", 10},
  227. {"c", "e", 10},
  228. {"e", "g", 8},
  229. {"g", "i", 6},
  230. {"j", "l", 4},
  231. {"l", "n", 4}});
  232. VerifyMaxCoveringTombstoneSeqnum(
  233. &iter1, {{"a", 10}, {"c", 10}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
  234. ASSERT_EQ(0, iter2.lower_bound());
  235. ASSERT_EQ(9, iter2.upper_bound());
  236. VerifyVisibleTombstones(&iter2, {{"c", "e", 8},
  237. {"e", "g", 8},
  238. {"g", "i", 6},
  239. {"j", "l", 4},
  240. {"l", "n", 4}});
  241. VerifyMaxCoveringTombstoneSeqnum(
  242. &iter2, {{"a", 0}, {"c", 8}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
  243. ASSERT_EQ(0, iter3.lower_bound());
  244. ASSERT_EQ(7, iter3.upper_bound());
  245. VerifyVisibleTombstones(&iter3, {{"c", "e", 6},
  246. {"e", "g", 6},
  247. {"g", "i", 6},
  248. {"j", "l", 4},
  249. {"l", "n", 4}});
  250. VerifyMaxCoveringTombstoneSeqnum(
  251. &iter3, {{"a", 0}, {"c", 6}, {"e", 6}, {"i", 0}, {"j", 4}, {"m", 4}});
  252. ASSERT_EQ(0, iter4.lower_bound());
  253. ASSERT_EQ(5, iter4.upper_bound());
  254. VerifyVisibleTombstones(&iter4, {{"j", "l", 4}, {"l", "n", 4}});
  255. VerifyMaxCoveringTombstoneSeqnum(
  256. &iter4, {{"a", 0}, {"c", 0}, {"e", 0}, {"i", 0}, {"j", 4}, {"m", 4}});
  257. ASSERT_EQ(0, iter5.lower_bound());
  258. ASSERT_EQ(3, iter5.upper_bound());
  259. VerifyVisibleTombstones(&iter5, {{"j", "l", 2}});
  260. VerifyMaxCoveringTombstoneSeqnum(
  261. &iter5, {{"a", 0}, {"c", 0}, {"e", 0}, {"i", 0}, {"j", 2}, {"m", 0}});
  262. }
  263. TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyUnordered) {
  264. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  265. {"j", "n", 4},
  266. {"c", "i", 6},
  267. {"c", "g", 8},
  268. {"j", "l", 2}});
  269. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  270. bytewise_icmp);
  271. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  272. 9 /* upper_bound */);
  273. ASSERT_EQ(0, iter.lower_bound());
  274. ASSERT_EQ(9, iter.upper_bound());
  275. VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
  276. {"c", "e", 10},
  277. {"c", "e", 8},
  278. {"c", "e", 6},
  279. {"e", "g", 8},
  280. {"e", "g", 6},
  281. {"g", "i", 6},
  282. {"j", "l", 4},
  283. {"j", "l", 2},
  284. {"l", "n", 4}});
  285. VerifyMaxCoveringTombstoneSeqnum(
  286. &iter, {{"a", 0}, {"c", 8}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
  287. }
  288. TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyForCompaction) {
  289. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  290. {"j", "n", 4},
  291. {"c", "i", 6},
  292. {"c", "g", 8},
  293. {"j", "l", 2}});
  294. FragmentedRangeTombstoneList fragment_list(
  295. std::move(range_del_iter), bytewise_icmp, true /* for_compaction */,
  296. {} /* snapshots */);
  297. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  298. kMaxSequenceNumber /* upper_bound */);
  299. VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
  300. {"c", "e", 10},
  301. {"e", "g", 8},
  302. {"g", "i", 6},
  303. {"j", "l", 4},
  304. {"l", "n", 4}});
  305. }
  306. TEST_F(RangeTombstoneFragmenterTest,
  307. OverlapAndRepeatedStartKeyForCompactionWithSnapshot) {
  308. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  309. {"j", "n", 4},
  310. {"c", "i", 6},
  311. {"c", "g", 8},
  312. {"j", "l", 2}});
  313. FragmentedRangeTombstoneList fragment_list(
  314. std::move(range_del_iter), bytewise_icmp, true /* for_compaction */,
  315. {9, 20} /* snapshots */);
  316. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  317. kMaxSequenceNumber /* upper_bound */);
  318. VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
  319. {"c", "e", 10},
  320. {"c", "e", 8},
  321. {"e", "g", 8},
  322. {"g", "i", 6},
  323. {"j", "l", 4},
  324. {"l", "n", 4}});
  325. }
  326. TEST_F(RangeTombstoneFragmenterTest, IteratorSplitNoSnapshots) {
  327. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  328. {"j", "n", 4},
  329. {"c", "i", 6},
  330. {"c", "g", 8},
  331. {"j", "l", 2}});
  332. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  333. bytewise_icmp);
  334. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  335. kMaxSequenceNumber /* upper_bound */);
  336. auto split_iters = iter.SplitBySnapshot({} /* snapshots */);
  337. ASSERT_EQ(1, split_iters.size());
  338. auto* split_iter = split_iters[kMaxSequenceNumber].get();
  339. ASSERT_EQ(0, split_iter->lower_bound());
  340. ASSERT_EQ(kMaxSequenceNumber, split_iter->upper_bound());
  341. VerifyVisibleTombstones(split_iter, {{"a", "c", 10},
  342. {"c", "e", 10},
  343. {"e", "g", 8},
  344. {"g", "i", 6},
  345. {"j", "l", 4},
  346. {"l", "n", 4}});
  347. }
  348. TEST_F(RangeTombstoneFragmenterTest, IteratorSplitWithSnapshots) {
  349. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  350. {"j", "n", 4},
  351. {"c", "i", 6},
  352. {"c", "g", 8},
  353. {"j", "l", 2}});
  354. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  355. bytewise_icmp);
  356. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  357. kMaxSequenceNumber /* upper_bound */);
  358. auto split_iters = iter.SplitBySnapshot({3, 5, 7, 9} /* snapshots */);
  359. ASSERT_EQ(5, split_iters.size());
  360. auto* split_iter1 = split_iters[3].get();
  361. ASSERT_EQ(0, split_iter1->lower_bound());
  362. ASSERT_EQ(3, split_iter1->upper_bound());
  363. VerifyVisibleTombstones(split_iter1, {{"j", "l", 2}});
  364. auto* split_iter2 = split_iters[5].get();
  365. ASSERT_EQ(4, split_iter2->lower_bound());
  366. ASSERT_EQ(5, split_iter2->upper_bound());
  367. VerifyVisibleTombstones(split_iter2, {{"j", "l", 4}, {"l", "n", 4}});
  368. auto* split_iter3 = split_iters[7].get();
  369. ASSERT_EQ(6, split_iter3->lower_bound());
  370. ASSERT_EQ(7, split_iter3->upper_bound());
  371. VerifyVisibleTombstones(split_iter3,
  372. {{"c", "e", 6}, {"e", "g", 6}, {"g", "i", 6}});
  373. auto* split_iter4 = split_iters[9].get();
  374. ASSERT_EQ(8, split_iter4->lower_bound());
  375. ASSERT_EQ(9, split_iter4->upper_bound());
  376. VerifyVisibleTombstones(split_iter4, {{"c", "e", 8}, {"e", "g", 8}});
  377. auto* split_iter5 = split_iters[kMaxSequenceNumber].get();
  378. ASSERT_EQ(10, split_iter5->lower_bound());
  379. ASSERT_EQ(kMaxSequenceNumber, split_iter5->upper_bound());
  380. VerifyVisibleTombstones(split_iter5, {{"a", "c", 10}, {"c", "e", 10}});
  381. }
  382. TEST_F(RangeTombstoneFragmenterTest, SeekStartKey) {
  383. // Same tombstones as OverlapAndRepeatedStartKey.
  384. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  385. {"c", "g", 8},
  386. {"c", "i", 6},
  387. {"j", "n", 4},
  388. {"j", "l", 2}});
  389. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  390. bytewise_icmp);
  391. FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
  392. kMaxSequenceNumber);
  393. VerifySeek(
  394. &iter1,
  395. {{"a", {"a", "c", 10}}, {"e", {"e", "g", 8}}, {"l", {"l", "n", 4}}});
  396. VerifySeekForPrev(
  397. &iter1,
  398. {{"a", {"a", "c", 10}}, {"e", {"e", "g", 8}}, {"l", {"l", "n", 4}}});
  399. FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
  400. 3 /* upper_bound */);
  401. VerifySeek(&iter2, {{"a", {"j", "l", 2}},
  402. {"e", {"j", "l", 2}},
  403. {"l", {}, true /* out of range */}});
  404. VerifySeekForPrev(&iter2, {{"a", {}, true /* out of range */},
  405. {"e", {}, true /* out of range */},
  406. {"l", {"j", "l", 2}}});
  407. }
  408. TEST_F(RangeTombstoneFragmenterTest, SeekCovered) {
  409. // Same tombstones as OverlapAndRepeatedStartKey.
  410. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  411. {"c", "g", 8},
  412. {"c", "i", 6},
  413. {"j", "n", 4},
  414. {"j", "l", 2}});
  415. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  416. bytewise_icmp);
  417. FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
  418. kMaxSequenceNumber);
  419. VerifySeek(
  420. &iter1,
  421. {{"b", {"a", "c", 10}}, {"f", {"e", "g", 8}}, {"m", {"l", "n", 4}}});
  422. VerifySeekForPrev(
  423. &iter1,
  424. {{"b", {"a", "c", 10}}, {"f", {"e", "g", 8}}, {"m", {"l", "n", 4}}});
  425. FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
  426. 3 /* upper_bound */);
  427. VerifySeek(&iter2, {{"b", {"j", "l", 2}},
  428. {"f", {"j", "l", 2}},
  429. {"m", {}, true /* out of range */}});
  430. VerifySeekForPrev(&iter2, {{"b", {}, true /* out of range */},
  431. {"f", {}, true /* out of range */},
  432. {"m", {"j", "l", 2}}});
  433. }
  434. TEST_F(RangeTombstoneFragmenterTest, SeekEndKey) {
  435. // Same tombstones as OverlapAndRepeatedStartKey.
  436. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  437. {"c", "g", 8},
  438. {"c", "i", 6},
  439. {"j", "n", 4},
  440. {"j", "l", 2}});
  441. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  442. bytewise_icmp);
  443. FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
  444. kMaxSequenceNumber);
  445. VerifySeek(&iter1, {{"c", {"c", "e", 10}},
  446. {"g", {"g", "i", 6}},
  447. {"i", {"j", "l", 4}},
  448. {"n", {}, true /* out of range */}});
  449. VerifySeekForPrev(&iter1, {{"c", {"c", "e", 10}},
  450. {"g", {"g", "i", 6}},
  451. {"i", {"g", "i", 6}},
  452. {"n", {"l", "n", 4}}});
  453. FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
  454. 3 /* upper_bound */);
  455. VerifySeek(&iter2, {{"c", {"j", "l", 2}},
  456. {"g", {"j", "l", 2}},
  457. {"i", {"j", "l", 2}},
  458. {"n", {}, true /* out of range */}});
  459. VerifySeekForPrev(&iter2, {{"c", {}, true /* out of range */},
  460. {"g", {}, true /* out of range */},
  461. {"i", {}, true /* out of range */},
  462. {"n", {"j", "l", 2}}});
  463. }
  464. TEST_F(RangeTombstoneFragmenterTest, SeekOutOfBounds) {
  465. // Same tombstones as OverlapAndRepeatedStartKey.
  466. auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
  467. {"c", "g", 8},
  468. {"c", "i", 6},
  469. {"j", "n", 4},
  470. {"j", "l", 2}});
  471. FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
  472. bytewise_icmp);
  473. FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
  474. kMaxSequenceNumber);
  475. VerifySeek(&iter, {{"", {"a", "c", 10}}, {"z", {}, true /* out of range */}});
  476. VerifySeekForPrev(&iter,
  477. {{"", {}, true /* out of range */}, {"z", {"l", "n", 4}}});
  478. }
  479. } // namespace ROCKSDB_NAMESPACE
  480. int main(int argc, char** argv) {
  481. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  482. ::testing::InitGoogleTest(&argc, argv);
  483. return RUN_ALL_TESTS();
  484. }