@ -35,50 +35,60 @@ void VerifyFragmentedRangeDels(
iter - > SeekToFirst ( ) ;
for ( size_t i = 0 ; i < expected_tombstones . size ( ) & & iter - > Valid ( ) ;
i + + , iter - > Next ( ) ) {
EXPECT_EQ ( ExtractUserKey ( iter - > key ( ) ) , expected_tombstones [ i ] . start_key_ ) ;
EXPECT_EQ ( iter - > start_ key( ) , expected_tombstones [ i ] . start_key_ ) ;
EXPECT_EQ ( iter - > value ( ) , expected_tombstones [ i ] . end_key_ ) ;
EXPECT_EQ ( GetInternalKeySeqno ( iter - > key ( ) ) , expected_tombstones [ i ] . seq_ ) ;
EXPECT_EQ ( iter - > seq ( ) , expected_tombstones [ i ] . seq_ ) ;
}
EXPECT_FALSE ( iter - > Valid ( ) ) ;
}
struct SeekForPrev TestCase {
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 ( ) ) ;
EXPECT_EQ ( testcase . expected_position . start_key_ , iter - > start_key ( ) ) ;
EXPECT_EQ ( testcase . expected_position . end_key_ , iter - > value ( ) ) ;
EXPECT_EQ ( testcase . expected_position . seq_ , iter - > seq ( ) ) ;
}
}
}
void VerifySeekForPrev ( FragmentedRangeTombstoneIterator * iter ,
const std : : vector < SeekForPrevTestCase > & cases ) {
const std : : vector < SeekTestCase > & cases ) {
for ( const auto & testcase : cases ) {
InternalKey ikey_seek_target ( testcase . seek_target , 0 , kTypeRangeDeletion ) ;
iter - > SeekForPrev ( ikey_seek_target . Encode ( ) ) ;
iter - > SeekForPrev ( testcase . seek_target ) ;
if ( testcase . out_of_range ) {
ASSERT_FALSE ( iter - > Valid ( ) ) ;
} else {
ASSERT_TRUE ( iter - > Valid ( ) ) ;
EXPECT_EQ ( ExtractUserKey ( iter - > key ( ) ) ,
testcase . expected_position . start_key_ ) ;
EXPECT_EQ ( iter - > value ( ) , testcase . expected_position . end_key_ ) ;
EXPECT_EQ ( GetInternalKeySeqno ( iter - > key ( ) ) ,
testcase . expected_position . seq_ ) ;
EXPECT_EQ ( testcase . expected_position . start_key_ , iter - > start_key ( ) ) ;
EXPECT_EQ ( testcase . expected_position . end_key_ , iter - > value ( ) ) ;
EXPECT_EQ ( testcase . expected_position . seq_ , iter - > seq ( ) ) ;
}
}
}
struct MaxCoveringTombstoneSeqnumTestCase {
Slice user_key ;
int result ;
SequenceNumber result ;
} ;
void VerifyMaxCoveringTombstoneSeqnum (
FragmentedRangeTombstoneIterator * iter , const Comparator * ucmp ,
FragmentedRangeTombstoneIterator * iter ,
const std : : vector < MaxCoveringTombstoneSeqnumTestCase > & cases ) {
for ( const auto & testcase : cases ) {
InternalKey key_and_snapshot ( testcase . user_key , kMaxSequenceNumber ,
kTypeValue ) ;
EXPECT_EQ ( testcase . result , MaxCoveringTombstoneSeqnum (
iter , key_and_snapshot . Encode ( ) , ucmp ) ) ;
EXPECT_EQ ( testcase . result ,
iter - > MaxCoveringTombstoneSeqnum ( testcase . user_key ) ) ;
}
}
@ -89,9 +99,10 @@ TEST_F(RangeTombstoneFragmenterTest, NonOverlappingTombstones) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter , { { " a " , " b " , 10 } , { " c " , " d " , 5 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , bytewise_icmp . user_comparator ( ) ,
VerifyMaxCoveringTombstoneSeqnum ( & iter ,
{ { " " , 0 } , { " a " , 10 } , { " b " , 0 } , { " c " , 5 } } ) ;
}
@ -100,10 +111,11 @@ TEST_F(RangeTombstoneFragmenterTest, OverlappingTombstones) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter ,
{ { " a " , " c " , 10 } , { " c " , " e " , 15 } , { " e " , " g " , 15 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , bytewise_icmp . user_comparator ( ) ,
VerifyMaxCoveringTombstoneSeqnum ( & iter ,
{ { " a " , 10 } , { " c " , 15 } , { " e " , 15 } , { " g " , 0 } } ) ;
}
@ -113,10 +125,11 @@ TEST_F(RangeTombstoneFragmenterTest, ContiguousTombstones) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter ,
{ { " a " , " c " , 10 } , { " c " , " e " , 20 } , { " e " , " g " , 15 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , bytewise_icmp . user_comparator ( ) ,
VerifyMaxCoveringTombstoneSeqnum ( & iter ,
{ { " a " , 10 } , { " c " , 20 } , { " e " , 15 } , { " g " , 0 } } ) ;
}
@ -126,10 +139,10 @@ TEST_F(RangeTombstoneFragmenterTest, RepeatedStartAndEndKey) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter , { { " a " , " c " , 10 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , bytewise_icmp . user_comparator ( ) ,
{ { " a " , 10 } , { " b " , 10 } , { " c " , 0 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , { { " a " , 10 } , { " b " , 10 } , { " c " , 0 } } ) ;
}
TEST_F ( RangeTombstoneFragmenterTest , RepeatedStartKeyDifferentEndKeys ) {
@ -138,10 +151,11 @@ TEST_F(RangeTombstoneFragmenterTest, RepeatedStartKeyDifferentEndKeys) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter ,
{ { " a " , " c " , 10 } , { " c " , " e " , 10 } , { " e " , " g " , 7 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , bytewise_icmp . user_comparator ( ) ,
VerifyMaxCoveringTombstoneSeqnum ( & iter ,
{ { " a " , 10 } , { " c " , 10 } , { " e " , 7 } , { " g " , 0 } } ) ;
}
@ -154,10 +168,11 @@ TEST_F(RangeTombstoneFragmenterTest, RepeatedStartKeyMixedEndKeys) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter ,
{ { " a " , " c " , 30 } , { " c " , " e " , 20 } , { " e " , " g " , 20 } } ) ;
VerifyMaxCoveringTombstoneSeqnum ( & iter , bytewise_icmp . user_comparator ( ) ,
VerifyMaxCoveringTombstoneSeqnum ( & iter ,
{ { " a " , 30 } , { " c " , 20 } , { " e " , 20 } , { " g " , 0 } } ) ;
}
@ -170,7 +185,8 @@ TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKey) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels ( & iter , { { " a " , " c " , 10 } ,
{ " c " , " e " , 10 } ,
{ " e " , " g " , 8 } ,
@ -178,8 +194,7 @@ TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKey) {
{ " j " , " l " , 4 } ,
{ " l " , " n " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter , bytewise_icmp . user_comparator ( ) ,
{ { " a " , 10 } , { " c " , 10 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
& iter , { { " a " , 10 } , { " c " , 10 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
}
TEST_F ( RangeTombstoneFragmenterTest , OverlapAndRepeatedStartKeyWithSnapshot ) {
@ -191,12 +206,12 @@ TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyWithSnapshot) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ , 9 ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , 9 /* snapshot */ ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels (
& iter , { { " c " , " g " , 8 } , { " g " , " i " , 6 } , { " j " , " l " , 4 } , { " l " , " n " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter , bytewise_icmp . user_comparator ( ) ,
{ { " a " , 0 } , { " c " , 8 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
& iter , { { " a " , 0 } , { " c " , 8 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
}
TEST_F ( RangeTombstoneFragmenterTest , OverlapAndRepeatedStartKeyUnordered ) {
@ -208,12 +223,12 @@ TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyUnordered) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ , 9 ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , 9 /* snapshot */ ,
bytewise_icmp ) ;
VerifyFragmentedRangeDels (
& iter , { { " c " , " g " , 8 } , { " g " , " i " , 6 } , { " j " , " l " , 4 } , { " l " , " n " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter , bytewise_icmp . user_comparator ( ) ,
{ { " a " , 0 } , { " c " , 8 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
& iter , { { " a " , 0 } , { " c " , 8 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
}
TEST_F ( RangeTombstoneFragmenterTest , OverlapAndRepeatedStartKeyMultiUse ) {
@ -225,23 +240,41 @@ TEST_F(RangeTombstoneFragmenterTest, OverlapAndRepeatedStartKeyMultiUse) {
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , false /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
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 } } ) ;
FragmentedRangeTombstoneIterator iter1 ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter2 ( & fragment_list , 9 /* snapshot */ ,
bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter3 ( & fragment_list , 7 /* snapshot */ ,
bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter4 ( & fragment_list , 5 /* snapshot */ ,
bytewise_icmp ) ;
FragmentedRangeTombstoneIterator iter5 ( & fragment_list , 3 /* snapshot */ ,
bytewise_icmp ) ;
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 } } ) ;
}
VerifyMaxCoveringTombstoneSeqnum (
& iter1 , { { " a " , 10 } , { " c " , 10 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter2 , { { " a " , 0 } , { " c " , 8 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter3 , { { " a " , 0 } , { " c " , 6 } , { " e " , 6 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter4 , { { " a " , 0 } , { " c " , 0 } , { " e " , 0 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
VerifyMaxCoveringTombstoneSeqnum (
& iter , bytewise_icmp . user_comparator ( ) ,
{ { " a " , 10 } , { " c " , 10 } , { " e " , 8 } , { " i " , 0 } , { " j " , 4 } , { " m " , 4 } } ) ;
& iter5 , { { " a " , 0 } , { " c " , 0 } , { " e " , 0 } , { " i " , 0 } , { " j " , 2 } , { " m " , 0 } } ) ;
}
TEST_F ( RangeTombstoneFragmenterTest , SeekForPrevStartKey ) {
TEST_F ( RangeTombstoneFragmenterTest , SeekStartKey ) {
// Same tombstones as OverlapAndRepeatedStartKey.
auto range_del_iter = MakeRangeDelIter ( { { " a " , " e " , 10 } ,
{ " c " , " g " , 8 } ,
@ -250,14 +283,28 @@ TEST_F(RangeTombstoneFragmenterTest, SeekForPrevStartKey) {
{ " j " , " l " , 2 } } ) ;
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
std : : move ( range_del_iter ) , bytewise_icmp , false /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter1 ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifySeek (
& iter1 ,
{ { " a " , { " a " , " c " , 10 } } , { " e " , { " e " , " g " , 8 } } , { " l " , { " l " , " n " , 4 } } } ) ;
VerifySeekForPrev (
& iter ,
& iter1 ,
{ { " a " , { " a " , " c " , 10 } } , { " e " , { " e " , " g " , 8 } } , { " l " , { " l " , " n " , 4 } } } ) ;
FragmentedRangeTombstoneIterator iter2 ( & fragment_list , 3 /* snapshot */ ,
bytewise_icmp ) ;
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 , SeekForPrevCovered ) {
TEST_F ( RangeTombstoneFragmenterTest , SeekCovered ) {
// Same tombstones as OverlapAndRepeatedStartKey.
auto range_del_iter = MakeRangeDelIter ( { { " a " , " e " , 10 } ,
{ " c " , " g " , 8 } ,
@ -266,14 +313,28 @@ TEST_F(RangeTombstoneFragmenterTest, SeekForPrevCovered) {
{ " j " , " l " , 2 } } ) ;
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
std : : move ( range_del_iter ) , bytewise_icmp , false /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter1 ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifySeek (
& iter1 ,
{ { " b " , { " a " , " c " , 10 } } , { " f " , { " e " , " g " , 8 } } , { " m " , { " l " , " n " , 4 } } } ) ;
VerifySeekForPrev (
& iter ,
& iter1 ,
{ { " b " , { " a " , " c " , 10 } } , { " f " , { " e " , " g " , 8 } } , { " m " , { " l " , " n " , 4 } } } ) ;
FragmentedRangeTombstoneIterator iter2 ( & fragment_list , 3 /* snapshot */ ,
bytewise_icmp ) ;
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 , SeekForPrevEndKey ) {
TEST_F ( RangeTombstoneFragmenterTest , SeekEndKey ) {
// Same tombstones as OverlapAndRepeatedStartKey.
auto range_del_iter = MakeRangeDelIter ( { { " a " , " e " , 10 } ,
{ " c " , " g " , 8 } ,
@ -282,15 +343,32 @@ TEST_F(RangeTombstoneFragmenterTest, SeekForPrevEndKey) {
{ " j " , " l " , 2 } } ) ;
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
VerifySeekForPrev ( & iter , { { " c " , { " c " , " e " , 10 } } ,
{ " g " , { " g " , " i " , 6 } } ,
{ " i " , { " g " , " i " , 6 } } ,
{ " n " , { " l " , " n " , 4 } } } ) ;
std : : move ( range_del_iter ) , bytewise_icmp , false /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter1 ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
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 , 3 /* snapshot */ ,
bytewise_icmp ) ;
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 , SeekForPrevOutOfBounds ) {
TEST_F ( RangeTombstoneFragmenterTest , SeekOutOfBounds ) {
// Same tombstones as OverlapAndRepeatedStartKey.
auto range_del_iter = MakeRangeDelIter ( { { " a " , " e " , 10 } ,
{ " c " , " g " , 8 } ,
@ -299,12 +377,47 @@ TEST_F(RangeTombstoneFragmenterTest, SeekForPrevOutOfBounds) {
{ " j " , " l " , 2 } } ) ;
FragmentedRangeTombstoneList fragment_list (
std : : move ( range_del_iter ) , bytewise_icmp , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , bytewise_icmp ) ;
std : : move ( range_del_iter ) , bytewise_icmp , false /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
VerifySeek ( & iter , { { " " , { " a " , " c " , 10 } } , { " z " , { } , true /* out of range */ } } ) ;
VerifySeekForPrev ( & iter ,
{ { " " , { } , true /* out of range */ } , { " z " , { " l " , " n " , 4 } } } ) ;
}
TEST_F ( RangeTombstoneFragmenterTest , SeekOneTimeUse ) {
// 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 , true /* one_time_use */ ) ;
FragmentedRangeTombstoneIterator iter1 ( & fragment_list , kMaxSequenceNumber ,
bytewise_icmp ) ;
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 } } } ) ;
// No tombstone fragments exist at this snapshot because they were dropped
// when the list was created.
FragmentedRangeTombstoneIterator iter2 ( & fragment_list , 3 /* snapshot */ ,
bytewise_icmp ) ;
VerifySeek ( & iter2 , { { " a " , { } , true /* out of range */ } ,
{ " e " , { } , true /* out of range */ } ,
{ " l " , { } , true /* out of range */ } } ) ;
VerifySeekForPrev ( & iter2 , { { " a " , { } , true /* out of range */ } ,
{ " e " , { } , true /* out of range */ } ,
{ " l " , { } , true /* out of range */ } } ) ;
}
} // namespace rocksdb
int main ( int argc , char * * argv ) {