| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- // Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- #include "db/range_tombstone_fragmenter.h"
- #include "db/db_test_util.h"
- #include "rocksdb/comparator.h"
- #include "test_util/testutil.h"
- namespace ROCKSDB_NAMESPACE {
- class RangeTombstoneFragmenterTest : public testing::Test {};
- namespace {
- static auto bytewise_icmp = InternalKeyComparator(BytewiseComparator());
- std::unique_ptr<InternalIterator> MakeRangeDelIter(
- const std::vector<RangeTombstone>& range_dels) {
- std::vector<std::string> keys, values;
- for (const auto& range_del : range_dels) {
- auto key_and_value = range_del.Serialize();
- keys.push_back(key_and_value.first.Encode().ToString());
- values.push_back(key_and_value.second.ToString());
- }
- return std::unique_ptr<test::VectorIterator>(
- new test::VectorIterator(keys, values));
- }
- void CheckIterPosition(const RangeTombstone& tombstone,
- const FragmentedRangeTombstoneIterator* iter) {
- // Test InternalIterator interface.
- EXPECT_EQ(tombstone.start_key_, ExtractUserKey(iter->key()));
- EXPECT_EQ(tombstone.end_key_, iter->value());
- EXPECT_EQ(tombstone.seq_, iter->seq());
- // Test FragmentedRangeTombstoneIterator interface.
- EXPECT_EQ(tombstone.start_key_, iter->start_key());
- EXPECT_EQ(tombstone.end_key_, iter->end_key());
- EXPECT_EQ(tombstone.seq_, GetInternalKeySeqno(iter->key()));
- }
- void VerifyFragmentedRangeDels(
- FragmentedRangeTombstoneIterator* iter,
- const std::vector<RangeTombstone>& expected_tombstones) {
- iter->SeekToFirst();
- for (size_t i = 0; i < expected_tombstones.size(); i++, iter->Next()) {
- ASSERT_TRUE(iter->Valid());
- CheckIterPosition(expected_tombstones[i], iter);
- }
- EXPECT_FALSE(iter->Valid());
- }
- void VerifyVisibleTombstones(
- FragmentedRangeTombstoneIterator* iter,
- const std::vector<RangeTombstone>& expected_tombstones) {
- iter->SeekToTopFirst();
- for (size_t i = 0; i < expected_tombstones.size(); i++, iter->TopNext()) {
- ASSERT_TRUE(iter->Valid());
- CheckIterPosition(expected_tombstones[i], iter);
- }
- EXPECT_FALSE(iter->Valid());
- }
- struct SeekTestCase {
- Slice seek_target;
- RangeTombstone expected_position;
- bool out_of_range;
- };
- void VerifySeek(FragmentedRangeTombstoneIterator* iter,
- const std::vector<SeekTestCase>& cases) {
- for (const auto& testcase : cases) {
- iter->Seek(testcase.seek_target);
- if (testcase.out_of_range) {
- ASSERT_FALSE(iter->Valid());
- } else {
- ASSERT_TRUE(iter->Valid());
- CheckIterPosition(testcase.expected_position, iter);
- }
- }
- }
- void VerifySeekForPrev(FragmentedRangeTombstoneIterator* iter,
- const std::vector<SeekTestCase>& cases) {
- for (const auto& testcase : cases) {
- iter->SeekForPrev(testcase.seek_target);
- if (testcase.out_of_range) {
- ASSERT_FALSE(iter->Valid());
- } else {
- ASSERT_TRUE(iter->Valid());
- CheckIterPosition(testcase.expected_position, iter);
- }
- }
- }
- struct MaxCoveringTombstoneSeqnumTestCase {
- Slice user_key;
- SequenceNumber result;
- };
- void VerifyMaxCoveringTombstoneSeqnum(
- FragmentedRangeTombstoneIterator* iter,
- const std::vector<MaxCoveringTombstoneSeqnumTestCase>& cases) {
- for (const auto& testcase : cases) {
- EXPECT_EQ(testcase.result,
- iter->MaxCoveringTombstoneSeqnum(testcase.user_key));
- }
- }
- } // anonymous namespace
- TEST_F(RangeTombstoneFragmenterTest, NonOverlappingTombstones) {
- auto range_del_iter = MakeRangeDelIter({{"a", "b", 10}, {"c", "d", 5}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
- VerifyFragmentedRangeDels(&iter, {{"a", "b", 10}, {"c", "d", 5}});
- VerifyMaxCoveringTombstoneSeqnum(&iter,
- {{"", 0}, {"a", 10}, {"b", 0}, {"c", 5}});
- }
- TEST_F(RangeTombstoneFragmenterTest, OverlappingTombstones) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10}, {"c", "g", 15}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
- VerifyFragmentedRangeDels(
- &iter, {{"a", "c", 10}, {"c", "e", 15}, {"c", "e", 10}, {"e", "g", 15}});
- VerifyMaxCoveringTombstoneSeqnum(&iter,
- {{"a", 10}, {"c", 15}, {"e", 15}, {"g", 0}});
- }
- TEST_F(RangeTombstoneFragmenterTest, ContiguousTombstones) {
- auto range_del_iter = MakeRangeDelIter(
- {{"a", "c", 10}, {"c", "e", 20}, {"c", "e", 5}, {"e", "g", 15}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
- VerifyFragmentedRangeDels(
- &iter, {{"a", "c", 10}, {"c", "e", 20}, {"c", "e", 5}, {"e", "g", 15}});
- VerifyMaxCoveringTombstoneSeqnum(&iter,
- {{"a", 10}, {"c", 20}, {"e", 15}, {"g", 0}});
- }
- TEST_F(RangeTombstoneFragmenterTest, RepeatedStartAndEndKey) {
- auto range_del_iter =
- MakeRangeDelIter({{"a", "c", 10}, {"a", "c", 7}, {"a", "c", 3}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
- VerifyFragmentedRangeDels(&iter,
- {{"a", "c", 10}, {"a", "c", 7}, {"a", "c", 3}});
- VerifyMaxCoveringTombstoneSeqnum(&iter, {{"a", 10}, {"b", 10}, {"c", 0}});
- }
- TEST_F(RangeTombstoneFragmenterTest, RepeatedStartKeyDifferentEndKeys) {
- auto range_del_iter =
- MakeRangeDelIter({{"a", "e", 10}, {"a", "g", 7}, {"a", "c", 3}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
- VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
- {"a", "c", 7},
- {"a", "c", 3},
- {"c", "e", 10},
- {"c", "e", 7},
- {"e", "g", 7}});
- VerifyMaxCoveringTombstoneSeqnum(&iter,
- {{"a", 10}, {"c", 10}, {"e", 7}, {"g", 0}});
- }
- TEST_F(RangeTombstoneFragmenterTest, RepeatedStartKeyMixedEndKeys) {
- auto range_del_iter = MakeRangeDelIter({{"a", "c", 30},
- {"a", "g", 20},
- {"a", "e", 10},
- {"a", "g", 7},
- {"a", "c", 3}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter.upper_bound());
- VerifyFragmentedRangeDels(&iter, {{"a", "c", 30},
- {"a", "c", 20},
- {"a", "c", 10},
- {"a", "c", 7},
- {"a", "c", 3},
- {"c", "e", 20},
- {"c", "e", 10},
- {"c", "e", 7},
- {"e", "g", 20},
- {"e", "g", 7}});
- VerifyMaxCoveringTombstoneSeqnum(&iter,
- {{"a", 30}, {"c", 20}, {"e", 20}, {"g", 0}});
- }
- TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKey) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"c", "g", 8},
- {"c", "i", 6},
- {"j", "n", 4},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
- 9 /* upper_bound */);
- FragmentedRangeTombstoneIterator iter3(&fragment_list, bytewise_icmp,
- 7 /* upper_bound */);
- FragmentedRangeTombstoneIterator iter4(&fragment_list, bytewise_icmp,
- 5 /* upper_bound */);
- FragmentedRangeTombstoneIterator iter5(&fragment_list, bytewise_icmp,
- 3 /* upper_bound */);
- for (auto* iter : {&iter1, &iter2, &iter3, &iter4, &iter5}) {
- VerifyFragmentedRangeDels(iter, {{"a", "c", 10},
- {"c", "e", 10},
- {"c", "e", 8},
- {"c", "e", 6},
- {"e", "g", 8},
- {"e", "g", 6},
- {"g", "i", 6},
- {"j", "l", 4},
- {"j", "l", 2},
- {"l", "n", 4}});
- }
- ASSERT_EQ(0, iter1.lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, iter1.upper_bound());
- VerifyVisibleTombstones(&iter1, {{"a", "c", 10},
- {"c", "e", 10},
- {"e", "g", 8},
- {"g", "i", 6},
- {"j", "l", 4},
- {"l", "n", 4}});
- VerifyMaxCoveringTombstoneSeqnum(
- &iter1, {{"a", 10}, {"c", 10}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
- ASSERT_EQ(0, iter2.lower_bound());
- ASSERT_EQ(9, iter2.upper_bound());
- VerifyVisibleTombstones(&iter2, {{"c", "e", 8},
- {"e", "g", 8},
- {"g", "i", 6},
- {"j", "l", 4},
- {"l", "n", 4}});
- VerifyMaxCoveringTombstoneSeqnum(
- &iter2, {{"a", 0}, {"c", 8}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
- ASSERT_EQ(0, iter3.lower_bound());
- ASSERT_EQ(7, iter3.upper_bound());
- VerifyVisibleTombstones(&iter3, {{"c", "e", 6},
- {"e", "g", 6},
- {"g", "i", 6},
- {"j", "l", 4},
- {"l", "n", 4}});
- VerifyMaxCoveringTombstoneSeqnum(
- &iter3, {{"a", 0}, {"c", 6}, {"e", 6}, {"i", 0}, {"j", 4}, {"m", 4}});
- ASSERT_EQ(0, iter4.lower_bound());
- ASSERT_EQ(5, iter4.upper_bound());
- VerifyVisibleTombstones(&iter4, {{"j", "l", 4}, {"l", "n", 4}});
- VerifyMaxCoveringTombstoneSeqnum(
- &iter4, {{"a", 0}, {"c", 0}, {"e", 0}, {"i", 0}, {"j", 4}, {"m", 4}});
- ASSERT_EQ(0, iter5.lower_bound());
- ASSERT_EQ(3, iter5.upper_bound());
- VerifyVisibleTombstones(&iter5, {{"j", "l", 2}});
- VerifyMaxCoveringTombstoneSeqnum(
- &iter5, {{"a", 0}, {"c", 0}, {"e", 0}, {"i", 0}, {"j", 2}, {"m", 0}});
- }
- TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyUnordered) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"j", "n", 4},
- {"c", "i", 6},
- {"c", "g", 8},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- 9 /* upper_bound */);
- ASSERT_EQ(0, iter.lower_bound());
- ASSERT_EQ(9, iter.upper_bound());
- VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
- {"c", "e", 10},
- {"c", "e", 8},
- {"c", "e", 6},
- {"e", "g", 8},
- {"e", "g", 6},
- {"g", "i", 6},
- {"j", "l", 4},
- {"j", "l", 2},
- {"l", "n", 4}});
- VerifyMaxCoveringTombstoneSeqnum(
- &iter, {{"a", 0}, {"c", 8}, {"e", 8}, {"i", 0}, {"j", 4}, {"m", 4}});
- }
- TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyForCompaction) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"j", "n", 4},
- {"c", "i", 6},
- {"c", "g", 8},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(
- std::move(range_del_iter), bytewise_icmp, true /* for_compaction */,
- {} /* snapshots */);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber /* upper_bound */);
- VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
- {"c", "e", 10},
- {"e", "g", 8},
- {"g", "i", 6},
- {"j", "l", 4},
- {"l", "n", 4}});
- }
- TEST_F(RangeTombstoneFragmenterTest,
- OverlapAndRepeatedStartKeyForCompactionWithSnapshot) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"j", "n", 4},
- {"c", "i", 6},
- {"c", "g", 8},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(
- std::move(range_del_iter), bytewise_icmp, true /* for_compaction */,
- {20, 9} /* upper_bounds */);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber /* upper_bound */);
- VerifyFragmentedRangeDels(&iter, {{"a", "c", 10},
- {"c", "e", 10},
- {"c", "e", 8},
- {"e", "g", 8},
- {"g", "i", 6},
- {"j", "l", 4},
- {"l", "n", 4}});
- }
- TEST_F(RangeTombstoneFragmenterTest, IteratorSplitNoSnapshots) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"j", "n", 4},
- {"c", "i", 6},
- {"c", "g", 8},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber /* upper_bound */);
- auto split_iters = iter.SplitBySnapshot({} /* snapshots */);
- ASSERT_EQ(1, split_iters.size());
- auto* split_iter = split_iters[kMaxSequenceNumber].get();
- ASSERT_EQ(0, split_iter->lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, split_iter->upper_bound());
- VerifyVisibleTombstones(split_iter, {{"a", "c", 10},
- {"c", "e", 10},
- {"e", "g", 8},
- {"g", "i", 6},
- {"j", "l", 4},
- {"l", "n", 4}});
- }
- TEST_F(RangeTombstoneFragmenterTest, IteratorSplitWithSnapshots) {
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"j", "n", 4},
- {"c", "i", 6},
- {"c", "g", 8},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber /* upper_bound */);
- auto split_iters = iter.SplitBySnapshot({3, 5, 7, 9} /* snapshots */);
- ASSERT_EQ(5, split_iters.size());
- auto* split_iter1 = split_iters[3].get();
- ASSERT_EQ(0, split_iter1->lower_bound());
- ASSERT_EQ(3, split_iter1->upper_bound());
- VerifyVisibleTombstones(split_iter1, {{"j", "l", 2}});
- auto* split_iter2 = split_iters[5].get();
- ASSERT_EQ(4, split_iter2->lower_bound());
- ASSERT_EQ(5, split_iter2->upper_bound());
- VerifyVisibleTombstones(split_iter2, {{"j", "l", 4}, {"l", "n", 4}});
- auto* split_iter3 = split_iters[7].get();
- ASSERT_EQ(6, split_iter3->lower_bound());
- ASSERT_EQ(7, split_iter3->upper_bound());
- VerifyVisibleTombstones(split_iter3,
- {{"c", "e", 6}, {"e", "g", 6}, {"g", "i", 6}});
- auto* split_iter4 = split_iters[9].get();
- ASSERT_EQ(8, split_iter4->lower_bound());
- ASSERT_EQ(9, split_iter4->upper_bound());
- VerifyVisibleTombstones(split_iter4, {{"c", "e", 8}, {"e", "g", 8}});
- auto* split_iter5 = split_iters[kMaxSequenceNumber].get();
- ASSERT_EQ(10, split_iter5->lower_bound());
- ASSERT_EQ(kMaxSequenceNumber, split_iter5->upper_bound());
- VerifyVisibleTombstones(split_iter5, {{"a", "c", 10}, {"c", "e", 10}});
- }
- TEST_F(RangeTombstoneFragmenterTest, SeekStartKey) {
- // Same tombstones as OverlapAndRepeatedStartKey.
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"c", "g", 8},
- {"c", "i", 6},
- {"j", "n", 4},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- VerifySeek(
- &iter1,
- {{"a", {"a", "c", 10}}, {"e", {"e", "g", 8}}, {"l", {"l", "n", 4}}});
- VerifySeekForPrev(
- &iter1,
- {{"a", {"a", "c", 10}}, {"e", {"e", "g", 8}}, {"l", {"l", "n", 4}}});
- FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
- 3 /* upper_bound */);
- VerifySeek(&iter2, {{"a", {"j", "l", 2}},
- {"e", {"j", "l", 2}},
- {"l", {}, true /* out of range */}});
- VerifySeekForPrev(&iter2, {{"a", {}, true /* out of range */},
- {"e", {}, true /* out of range */},
- {"l", {"j", "l", 2}}});
- }
- TEST_F(RangeTombstoneFragmenterTest, SeekCovered) {
- // Same tombstones as OverlapAndRepeatedStartKey.
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"c", "g", 8},
- {"c", "i", 6},
- {"j", "n", 4},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- VerifySeek(
- &iter1,
- {{"b", {"a", "c", 10}}, {"f", {"e", "g", 8}}, {"m", {"l", "n", 4}}});
- VerifySeekForPrev(
- &iter1,
- {{"b", {"a", "c", 10}}, {"f", {"e", "g", 8}}, {"m", {"l", "n", 4}}});
- FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
- 3 /* upper_bound */);
- VerifySeek(&iter2, {{"b", {"j", "l", 2}},
- {"f", {"j", "l", 2}},
- {"m", {}, true /* out of range */}});
- VerifySeekForPrev(&iter2, {{"b", {}, true /* out of range */},
- {"f", {}, true /* out of range */},
- {"m", {"j", "l", 2}}});
- }
- TEST_F(RangeTombstoneFragmenterTest, SeekEndKey) {
- // Same tombstones as OverlapAndRepeatedStartKey.
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"c", "g", 8},
- {"c", "i", 6},
- {"j", "n", 4},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter1(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- VerifySeek(&iter1, {{"c", {"c", "e", 10}},
- {"g", {"g", "i", 6}},
- {"i", {"j", "l", 4}},
- {"n", {}, true /* out of range */}});
- VerifySeekForPrev(&iter1, {{"c", {"c", "e", 10}},
- {"g", {"g", "i", 6}},
- {"i", {"g", "i", 6}},
- {"n", {"l", "n", 4}}});
- FragmentedRangeTombstoneIterator iter2(&fragment_list, bytewise_icmp,
- 3 /* upper_bound */);
- VerifySeek(&iter2, {{"c", {"j", "l", 2}},
- {"g", {"j", "l", 2}},
- {"i", {"j", "l", 2}},
- {"n", {}, true /* out of range */}});
- VerifySeekForPrev(&iter2, {{"c", {}, true /* out of range */},
- {"g", {}, true /* out of range */},
- {"i", {}, true /* out of range */},
- {"n", {"j", "l", 2}}});
- }
- TEST_F(RangeTombstoneFragmenterTest, SeekOutOfBounds) {
- // Same tombstones as OverlapAndRepeatedStartKey.
- auto range_del_iter = MakeRangeDelIter({{"a", "e", 10},
- {"c", "g", 8},
- {"c", "i", 6},
- {"j", "n", 4},
- {"j", "l", 2}});
- FragmentedRangeTombstoneList fragment_list(std::move(range_del_iter),
- bytewise_icmp);
- FragmentedRangeTombstoneIterator iter(&fragment_list, bytewise_icmp,
- kMaxSequenceNumber);
- VerifySeek(&iter, {{"", {"a", "c", 10}}, {"z", {}, true /* out of range */}});
- VerifySeekForPrev(&iter,
- {{"", {}, true /* out of range */}, {"z", {"l", "n", 4}}});
- }
- } // namespace ROCKSDB_NAMESPACE
- int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
- }
|