db_stress to cover SeekForPrev() (#6022)

Summary:
Right now, db_stress doesn't cover SeekForPrev(). Add the coverage, which mirrors what we do for Seek().
Pull Request resolved: https://github.com/facebook/rocksdb/pull/6022

Test Plan: Run "make crash_test". Do some manual source code hack to simular iterator wrong results and see it caught.

Differential Revision: D18442193

fbshipit-source-id: 879b79000d5e33c625c7e970636de191ccd7776c
main
sdong 5 years ago committed by Facebook Github Bot
parent 03ce7fb292
commit a19de78da5
  1. 31
      tools/db_stress_tool.cc

@ -2479,10 +2479,18 @@ class StressTest {
std::unique_ptr<Iterator> cmp_iter(db_->NewIterator(cmp_ro, cmp_cfh)); std::unique_ptr<Iterator> cmp_iter(db_->NewIterator(cmp_ro, cmp_cfh));
bool diverged = false; bool diverged = false;
LastIterateOp last_op;
if (thread->rand.OneIn(8)) {
iter->SeekForPrev(key);
cmp_iter->SeekForPrev(key);
last_op = kLastOpSeekForPrev;
} else {
iter->Seek(key); iter->Seek(key);
cmp_iter->Seek(key); cmp_iter->Seek(key);
last_op = kLastOpSeek;
}
VerifyIterator(thread, cmp_cfh, readoptionscopy, iter.get(), VerifyIterator(thread, cmp_cfh, readoptionscopy, iter.get(),
cmp_iter.get(), key, &diverged); cmp_iter.get(), last_op, key, &diverged);
bool no_reverse = bool no_reverse =
(FLAGS_memtablerep == "prefix_hash" && !read_opts.total_order_seek && (FLAGS_memtablerep == "prefix_hash" && !read_opts.total_order_seek &&
@ -2501,8 +2509,9 @@ class StressTest {
cmp_iter->Prev(); cmp_iter->Prev();
} }
} }
last_op = kLastOpNextOrPrev;
VerifyIterator(thread, cmp_cfh, readoptionscopy, iter.get(), VerifyIterator(thread, cmp_cfh, readoptionscopy, iter.get(),
cmp_iter.get(), key, &diverged); cmp_iter.get(), last_op, key, &diverged);
} }
if (s.ok()) { if (s.ok()) {
@ -2518,6 +2527,9 @@ class StressTest {
return s; return s;
} }
// Enum used by VerifyIterator() to identify the mode to validate.
enum LastIterateOp { kLastOpSeek, kLastOpSeekForPrev, kLastOpNextOrPrev };
// Compare the two iterator, iter and cmp_iter are in the same position, // Compare the two iterator, iter and cmp_iter are in the same position,
// unless iter might be made invalidate or undefined because of // unless iter might be made invalidate or undefined because of
// upper or lower bounds, or prefix extractor. // upper or lower bounds, or prefix extractor.
@ -2526,12 +2538,12 @@ class StressTest {
// True if verification passed, false if not. // True if verification passed, false if not.
void VerifyIterator(ThreadState* thread, ColumnFamilyHandle* cmp_cfh, void VerifyIterator(ThreadState* thread, ColumnFamilyHandle* cmp_cfh,
const ReadOptions& ro, Iterator* iter, Iterator* cmp_iter, const ReadOptions& ro, Iterator* iter, Iterator* cmp_iter,
const Slice& seek_key, bool* diverged) { LastIterateOp op, const Slice& seek_key, bool* diverged) {
if (*diverged) { if (*diverged) {
return; return;
} }
if (ro.iterate_lower_bound != nullptr && if (op == kLastOpSeek && ro.iterate_lower_bound != nullptr &&
(options_.comparator->Compare(*ro.iterate_lower_bound, seek_key) >= 0 || (options_.comparator->Compare(*ro.iterate_lower_bound, seek_key) >= 0 ||
(ro.iterate_upper_bound != nullptr && (ro.iterate_upper_bound != nullptr &&
options_.comparator->Compare(*ro.iterate_lower_bound, options_.comparator->Compare(*ro.iterate_lower_bound,
@ -2542,6 +2554,17 @@ class StressTest {
return; return;
} }
if (op == kLastOpSeekForPrev && ro.iterate_upper_bound != nullptr &&
(options_.comparator->Compare(*ro.iterate_upper_bound, seek_key) <= 0 ||
(ro.iterate_lower_bound != nullptr &&
options_.comparator->Compare(*ro.iterate_lower_bound,
*ro.iterate_upper_bound) >= 0))) {
// Uppder bound behavior is not well defined if it is smaller than
// seek key or lower bound. Disable the check for now.
*diverged = true;
return;
}
if (iter->Valid() && !cmp_iter->Valid()) { if (iter->Valid() && !cmp_iter->Valid()) {
fprintf(stderr, fprintf(stderr,
"Control interator is invalid but iterator has key %s seek key " "Control interator is invalid but iterator has key %s seek key "

Loading…
Cancel
Save