range_tombstone_fragmenter_test.cc 24 KB

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