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).
6 #include "db/range_tombstone_fragmenter.h"
8 #include "db/db_test_util.h"
9 #include "rocksdb/comparator.h"
10 #include "test_util/testutil.h"
12 namespace ROCKSDB_NAMESPACE
{
14 class RangeTombstoneFragmenterTest
: public testing::Test
{};
18 static auto bytewise_icmp
= InternalKeyComparator(BytewiseComparator());
20 std::unique_ptr
<InternalIterator
> MakeRangeDelIter(
21 const std::vector
<RangeTombstone
>& range_dels
) {
22 std::vector
<std::string
> keys
, values
;
23 for (const auto& range_del
: range_dels
) {
24 auto key_and_value
= range_del
.Serialize();
25 keys
.push_back(key_and_value
.first
.Encode().ToString());
26 values
.push_back(key_and_value
.second
.ToString());
28 return std::unique_ptr
<test::VectorIterator
>(
29 new test::VectorIterator(keys
, values
));
32 void CheckIterPosition(const RangeTombstone
& tombstone
,
33 const FragmentedRangeTombstoneIterator
* iter
) {
34 // Test InternalIterator interface.
35 EXPECT_EQ(tombstone
.start_key_
, ExtractUserKey(iter
->key()));
36 EXPECT_EQ(tombstone
.end_key_
, iter
->value());
37 EXPECT_EQ(tombstone
.seq_
, iter
->seq());
39 // Test FragmentedRangeTombstoneIterator interface.
40 EXPECT_EQ(tombstone
.start_key_
, iter
->start_key());
41 EXPECT_EQ(tombstone
.end_key_
, iter
->end_key());
42 EXPECT_EQ(tombstone
.seq_
, GetInternalKeySeqno(iter
->key()));
45 void VerifyFragmentedRangeDels(
46 FragmentedRangeTombstoneIterator
* iter
,
47 const std::vector
<RangeTombstone
>& expected_tombstones
) {
49 for (size_t i
= 0; i
< expected_tombstones
.size(); i
++, iter
->Next()) {
50 ASSERT_TRUE(iter
->Valid());
51 CheckIterPosition(expected_tombstones
[i
], iter
);
53 EXPECT_FALSE(iter
->Valid());
56 void VerifyVisibleTombstones(
57 FragmentedRangeTombstoneIterator
* iter
,
58 const std::vector
<RangeTombstone
>& expected_tombstones
) {
59 iter
->SeekToTopFirst();
60 for (size_t i
= 0; i
< expected_tombstones
.size(); i
++, iter
->TopNext()) {
61 ASSERT_TRUE(iter
->Valid());
62 CheckIterPosition(expected_tombstones
[i
], iter
);
64 EXPECT_FALSE(iter
->Valid());
69 RangeTombstone expected_position
;
73 void VerifySeek(FragmentedRangeTombstoneIterator
* iter
,
74 const std::vector
<SeekTestCase
>& cases
) {
75 for (const auto& testcase
: cases
) {
76 iter
->Seek(testcase
.seek_target
);
77 if (testcase
.out_of_range
) {
78 ASSERT_FALSE(iter
->Valid());
80 ASSERT_TRUE(iter
->Valid());
81 CheckIterPosition(testcase
.expected_position
, iter
);
86 void VerifySeekForPrev(FragmentedRangeTombstoneIterator
* iter
,
87 const std::vector
<SeekTestCase
>& cases
) {
88 for (const auto& testcase
: cases
) {
89 iter
->SeekForPrev(testcase
.seek_target
);
90 if (testcase
.out_of_range
) {
91 ASSERT_FALSE(iter
->Valid());
93 ASSERT_TRUE(iter
->Valid());
94 CheckIterPosition(testcase
.expected_position
, iter
);
99 struct MaxCoveringTombstoneSeqnumTestCase
{
101 SequenceNumber result
;
104 void VerifyMaxCoveringTombstoneSeqnum(
105 FragmentedRangeTombstoneIterator
* iter
,
106 const std::vector
<MaxCoveringTombstoneSeqnumTestCase
>& cases
) {
107 for (const auto& testcase
: cases
) {
108 EXPECT_EQ(testcase
.result
,
109 iter
->MaxCoveringTombstoneSeqnum(testcase
.user_key
));
113 } // anonymous namespace
115 TEST_F(RangeTombstoneFragmenterTest
, NonOverlappingTombstones
) {
116 auto range_del_iter
= MakeRangeDelIter({{"a", "b", 10}, {"c", "d", 5}});
118 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
120 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
122 ASSERT_EQ(0, iter
.lower_bound());
123 ASSERT_EQ(kMaxSequenceNumber
, iter
.upper_bound());
124 VerifyFragmentedRangeDels(&iter
, {{"a", "b", 10}, {"c", "d", 5}});
125 VerifyMaxCoveringTombstoneSeqnum(&iter
,
126 {{"", 0}, {"a", 10}, {"b", 0}, {"c", 5}});
129 TEST_F(RangeTombstoneFragmenterTest
, OverlappingTombstones
) {
130 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10}, {"c", "g", 15}});
132 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
134 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
136 ASSERT_EQ(0, iter
.lower_bound());
137 ASSERT_EQ(kMaxSequenceNumber
, iter
.upper_bound());
138 VerifyFragmentedRangeDels(
139 &iter
, {{"a", "c", 10}, {"c", "e", 15}, {"c", "e", 10}, {"e", "g", 15}});
140 VerifyMaxCoveringTombstoneSeqnum(&iter
,
141 {{"a", 10}, {"c", 15}, {"e", 15}, {"g", 0}});
144 TEST_F(RangeTombstoneFragmenterTest
, ContiguousTombstones
) {
145 auto range_del_iter
= MakeRangeDelIter(
146 {{"a", "c", 10}, {"c", "e", 20}, {"c", "e", 5}, {"e", "g", 15}});
148 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
150 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
152 ASSERT_EQ(0, iter
.lower_bound());
153 ASSERT_EQ(kMaxSequenceNumber
, iter
.upper_bound());
154 VerifyFragmentedRangeDels(
155 &iter
, {{"a", "c", 10}, {"c", "e", 20}, {"c", "e", 5}, {"e", "g", 15}});
156 VerifyMaxCoveringTombstoneSeqnum(&iter
,
157 {{"a", 10}, {"c", 20}, {"e", 15}, {"g", 0}});
160 TEST_F(RangeTombstoneFragmenterTest
, RepeatedStartAndEndKey
) {
161 auto range_del_iter
=
162 MakeRangeDelIter({{"a", "c", 10}, {"a", "c", 7}, {"a", "c", 3}});
164 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
166 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
168 ASSERT_EQ(0, iter
.lower_bound());
169 ASSERT_EQ(kMaxSequenceNumber
, iter
.upper_bound());
170 VerifyFragmentedRangeDels(&iter
,
171 {{"a", "c", 10}, {"a", "c", 7}, {"a", "c", 3}});
172 VerifyMaxCoveringTombstoneSeqnum(&iter
, {{"a", 10}, {"b", 10}, {"c", 0}});
175 TEST_F(RangeTombstoneFragmenterTest
, RepeatedStartKeyDifferentEndKeys
) {
176 auto range_del_iter
=
177 MakeRangeDelIter({{"a", "e", 10}, {"a", "g", 7}, {"a", "c", 3}});
179 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
181 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
183 ASSERT_EQ(0, iter
.lower_bound());
184 ASSERT_EQ(kMaxSequenceNumber
, iter
.upper_bound());
185 VerifyFragmentedRangeDels(&iter
, {{"a", "c", 10},
191 VerifyMaxCoveringTombstoneSeqnum(&iter
,
192 {{"a", 10}, {"c", 10}, {"e", 7}, {"g", 0}});
195 TEST_F(RangeTombstoneFragmenterTest
, RepeatedStartKeyMixedEndKeys
) {
196 auto range_del_iter
= MakeRangeDelIter({{"a", "c", 30},
202 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
204 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
206 ASSERT_EQ(0, iter
.lower_bound());
207 ASSERT_EQ(kMaxSequenceNumber
, iter
.upper_bound());
208 VerifyFragmentedRangeDels(&iter
, {{"a", "c", 30},
218 VerifyMaxCoveringTombstoneSeqnum(&iter
,
219 {{"a", 30}, {"c", 20}, {"e", 20}, {"g", 0}});
222 TEST_F(RangeTombstoneFragmenterTest
, OverlapAndRepeatedStartKey
) {
223 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
229 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
231 FragmentedRangeTombstoneIterator
iter1(&fragment_list
, bytewise_icmp
,
233 FragmentedRangeTombstoneIterator
iter2(&fragment_list
, bytewise_icmp
,
234 9 /* upper_bound */);
235 FragmentedRangeTombstoneIterator
iter3(&fragment_list
, bytewise_icmp
,
236 7 /* upper_bound */);
237 FragmentedRangeTombstoneIterator
iter4(&fragment_list
, bytewise_icmp
,
238 5 /* upper_bound */);
239 FragmentedRangeTombstoneIterator
iter5(&fragment_list
, bytewise_icmp
,
240 3 /* upper_bound */);
241 for (auto* iter
: {&iter1
, &iter2
, &iter3
, &iter4
, &iter5
}) {
242 VerifyFragmentedRangeDels(iter
, {{"a", "c", 10},
254 ASSERT_EQ(0, iter1
.lower_bound());
255 ASSERT_EQ(kMaxSequenceNumber
, iter1
.upper_bound());
256 VerifyVisibleTombstones(&iter1
, {{"a", "c", 10},
262 VerifyMaxCoveringTombstoneSeqnum(
263 &iter1
, {{"a", 10}, {"c", 10}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
265 ASSERT_EQ(0, iter2
.lower_bound());
266 ASSERT_EQ(9, iter2
.upper_bound());
267 VerifyVisibleTombstones(&iter2
, {{"c", "e", 8},
272 VerifyMaxCoveringTombstoneSeqnum(
273 &iter2
, {{"a", 0}, {"c", 8}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
275 ASSERT_EQ(0, iter3
.lower_bound());
276 ASSERT_EQ(7, iter3
.upper_bound());
277 VerifyVisibleTombstones(&iter3
, {{"c", "e", 6},
282 VerifyMaxCoveringTombstoneSeqnum(
283 &iter3
, {{"a", 0}, {"c", 6}, {"e", 6}, {"i", 0}, {"j", 4}, {"m", 4}});
285 ASSERT_EQ(0, iter4
.lower_bound());
286 ASSERT_EQ(5, iter4
.upper_bound());
287 VerifyVisibleTombstones(&iter4
, {{"j", "l", 4}, {"l", "n", 4}});
288 VerifyMaxCoveringTombstoneSeqnum(
289 &iter4
, {{"a", 0}, {"c", 0}, {"e", 0}, {"i", 0}, {"j", 4}, {"m", 4}});
291 ASSERT_EQ(0, iter5
.lower_bound());
292 ASSERT_EQ(3, iter5
.upper_bound());
293 VerifyVisibleTombstones(&iter5
, {{"j", "l", 2}});
294 VerifyMaxCoveringTombstoneSeqnum(
295 &iter5
, {{"a", 0}, {"c", 0}, {"e", 0}, {"i", 0}, {"j", 2}, {"m", 0}});
298 TEST_F(RangeTombstoneFragmenterTest
, OverlapAndRepeatedStartKeyUnordered
) {
299 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
305 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
307 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
308 9 /* upper_bound */);
309 ASSERT_EQ(0, iter
.lower_bound());
310 ASSERT_EQ(9, iter
.upper_bound());
311 VerifyFragmentedRangeDels(&iter
, {{"a", "c", 10},
321 VerifyMaxCoveringTombstoneSeqnum(
322 &iter
, {{"a", 0}, {"c", 8}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
325 TEST_F(RangeTombstoneFragmenterTest
, OverlapAndRepeatedStartKeyForCompaction
) {
326 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
332 FragmentedRangeTombstoneList
fragment_list(
333 std::move(range_del_iter
), bytewise_icmp
, true /* for_compaction */,
335 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
336 kMaxSequenceNumber
/* upper_bound */);
337 VerifyFragmentedRangeDels(&iter
, {{"a", "c", 10},
345 TEST_F(RangeTombstoneFragmenterTest
,
346 OverlapAndRepeatedStartKeyForCompactionWithSnapshot
) {
347 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
353 FragmentedRangeTombstoneList
fragment_list(
354 std::move(range_del_iter
), bytewise_icmp
, true /* for_compaction */,
355 {20, 9} /* upper_bounds */);
356 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
357 kMaxSequenceNumber
/* upper_bound */);
358 VerifyFragmentedRangeDels(&iter
, {{"a", "c", 10},
367 TEST_F(RangeTombstoneFragmenterTest
, IteratorSplitNoSnapshots
) {
368 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
374 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
376 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
377 kMaxSequenceNumber
/* upper_bound */);
379 auto split_iters
= iter
.SplitBySnapshot({} /* snapshots */);
380 ASSERT_EQ(1, split_iters
.size());
382 auto* split_iter
= split_iters
[kMaxSequenceNumber
].get();
383 ASSERT_EQ(0, split_iter
->lower_bound());
384 ASSERT_EQ(kMaxSequenceNumber
, split_iter
->upper_bound());
385 VerifyVisibleTombstones(split_iter
, {{"a", "c", 10},
393 TEST_F(RangeTombstoneFragmenterTest
, IteratorSplitWithSnapshots
) {
394 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
400 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
402 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
403 kMaxSequenceNumber
/* upper_bound */);
405 auto split_iters
= iter
.SplitBySnapshot({3, 5, 7, 9} /* snapshots */);
406 ASSERT_EQ(5, split_iters
.size());
408 auto* split_iter1
= split_iters
[3].get();
409 ASSERT_EQ(0, split_iter1
->lower_bound());
410 ASSERT_EQ(3, split_iter1
->upper_bound());
411 VerifyVisibleTombstones(split_iter1
, {{"j", "l", 2}});
413 auto* split_iter2
= split_iters
[5].get();
414 ASSERT_EQ(4, split_iter2
->lower_bound());
415 ASSERT_EQ(5, split_iter2
->upper_bound());
416 VerifyVisibleTombstones(split_iter2
, {{"j", "l", 4}, {"l", "n", 4}});
418 auto* split_iter3
= split_iters
[7].get();
419 ASSERT_EQ(6, split_iter3
->lower_bound());
420 ASSERT_EQ(7, split_iter3
->upper_bound());
421 VerifyVisibleTombstones(split_iter3
,
422 {{"c", "e", 6}, {"e", "g", 6}, {"g", "i", 6}});
424 auto* split_iter4
= split_iters
[9].get();
425 ASSERT_EQ(8, split_iter4
->lower_bound());
426 ASSERT_EQ(9, split_iter4
->upper_bound());
427 VerifyVisibleTombstones(split_iter4
, {{"c", "e", 8}, {"e", "g", 8}});
429 auto* split_iter5
= split_iters
[kMaxSequenceNumber
].get();
430 ASSERT_EQ(10, split_iter5
->lower_bound());
431 ASSERT_EQ(kMaxSequenceNumber
, split_iter5
->upper_bound());
432 VerifyVisibleTombstones(split_iter5
, {{"a", "c", 10}, {"c", "e", 10}});
435 TEST_F(RangeTombstoneFragmenterTest
, SeekStartKey
) {
436 // Same tombstones as OverlapAndRepeatedStartKey.
437 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
443 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
446 FragmentedRangeTombstoneIterator
iter1(&fragment_list
, bytewise_icmp
,
450 {{"a", {"a", "c", 10}}, {"e", {"e", "g", 8}}, {"l", {"l", "n", 4}}});
453 {{"a", {"a", "c", 10}}, {"e", {"e", "g", 8}}, {"l", {"l", "n", 4}}});
455 FragmentedRangeTombstoneIterator
iter2(&fragment_list
, bytewise_icmp
,
456 3 /* upper_bound */);
457 VerifySeek(&iter2
, {{"a", {"j", "l", 2}},
458 {"e", {"j", "l", 2}},
459 {"l", {}, true /* out of range */}});
460 VerifySeekForPrev(&iter2
, {{"a", {}, true /* out of range */},
461 {"e", {}, true /* out of range */},
462 {"l", {"j", "l", 2}}});
465 TEST_F(RangeTombstoneFragmenterTest
, SeekCovered
) {
466 // Same tombstones as OverlapAndRepeatedStartKey.
467 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
473 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
476 FragmentedRangeTombstoneIterator
iter1(&fragment_list
, bytewise_icmp
,
480 {{"b", {"a", "c", 10}}, {"f", {"e", "g", 8}}, {"m", {"l", "n", 4}}});
483 {{"b", {"a", "c", 10}}, {"f", {"e", "g", 8}}, {"m", {"l", "n", 4}}});
485 FragmentedRangeTombstoneIterator
iter2(&fragment_list
, bytewise_icmp
,
486 3 /* upper_bound */);
487 VerifySeek(&iter2
, {{"b", {"j", "l", 2}},
488 {"f", {"j", "l", 2}},
489 {"m", {}, true /* out of range */}});
490 VerifySeekForPrev(&iter2
, {{"b", {}, true /* out of range */},
491 {"f", {}, true /* out of range */},
492 {"m", {"j", "l", 2}}});
495 TEST_F(RangeTombstoneFragmenterTest
, SeekEndKey
) {
496 // Same tombstones as OverlapAndRepeatedStartKey.
497 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
503 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
506 FragmentedRangeTombstoneIterator
iter1(&fragment_list
, bytewise_icmp
,
508 VerifySeek(&iter1
, {{"c", {"c", "e", 10}},
509 {"g", {"g", "i", 6}},
510 {"i", {"j", "l", 4}},
511 {"n", {}, true /* out of range */}});
512 VerifySeekForPrev(&iter1
, {{"c", {"c", "e", 10}},
513 {"g", {"g", "i", 6}},
514 {"i", {"g", "i", 6}},
515 {"n", {"l", "n", 4}}});
517 FragmentedRangeTombstoneIterator
iter2(&fragment_list
, bytewise_icmp
,
518 3 /* upper_bound */);
519 VerifySeek(&iter2
, {{"c", {"j", "l", 2}},
520 {"g", {"j", "l", 2}},
521 {"i", {"j", "l", 2}},
522 {"n", {}, true /* out of range */}});
523 VerifySeekForPrev(&iter2
, {{"c", {}, true /* out of range */},
524 {"g", {}, true /* out of range */},
525 {"i", {}, true /* out of range */},
526 {"n", {"j", "l", 2}}});
529 TEST_F(RangeTombstoneFragmenterTest
, SeekOutOfBounds
) {
530 // Same tombstones as OverlapAndRepeatedStartKey.
531 auto range_del_iter
= MakeRangeDelIter({{"a", "e", 10},
537 FragmentedRangeTombstoneList
fragment_list(std::move(range_del_iter
),
540 FragmentedRangeTombstoneIterator
iter(&fragment_list
, bytewise_icmp
,
542 VerifySeek(&iter
, {{"", {"a", "c", 10}}, {"z", {}, true /* out of range */}});
543 VerifySeekForPrev(&iter
,
544 {{"", {}, true /* out of range */}, {"z", {"l", "n", 4}}});
547 } // namespace ROCKSDB_NAMESPACE
549 int main(int argc
, char** argv
) {
550 ::testing::InitGoogleTest(&argc
, argv
);
551 return RUN_ALL_TESTS();