summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp')
-rw-r--r--src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp162
1 files changed, 103 insertions, 59 deletions
diff --git a/src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp b/src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp
index 5482c4f899b..27eb855f10f 100644
--- a/src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp
+++ b/src/third_party/wiredtiger/test/cppsuite/tests/cursor_bound_01.cpp
@@ -49,19 +49,18 @@ class cursor_bound_01 : public test {
/* Class helper to represent the lower and uppers bounds for the range cursor. */
class bound {
public:
- bound() = default;
- bound(uint64_t key_size_max, bool lower_bound, std::string key)
- : _lower_bound(lower_bound), _key(key)
+ bound()
{
- bool set_inclusive = random_generator::instance().generate_integer(0, 1);
- // FIXME: Use random strings, once bounds are implemented properly.
- // auto key_size =
- // random_generator::instance().generate_integer(static_cast<uint64_t>(1),
- // key_size_max);
- // auto random_key = random_generator::instance().generate_random_string(
- // key_size, characters_type::ALPHABET);
- // _key = random_key;
- _inclusive = set_inclusive;
+ clear();
+ };
+
+ bound(uint64_t key_size_max, bool lower_bound) : _lower_bound(lower_bound)
+ {
+ auto key_size =
+ random_generator::instance().generate_integer(static_cast<uint64_t>(1), key_size_max);
+ _key = random_generator::instance().generate_random_string(
+ key_size, characters_type::ALPHABET);
+ _inclusive = random_generator::instance().generate_integer(0, 1);
}
std::string
@@ -71,7 +70,7 @@ class cursor_bound_01 : public test {
",inclusive=" + std::string(_inclusive ? "true" : "false");
}
- std::string
+ const std::string &
get_key() const
{
return _key;
@@ -83,6 +82,14 @@ class cursor_bound_01 : public test {
return _inclusive;
}
+ void
+ clear()
+ {
+ _key.clear();
+ _inclusive = false;
+ _lower_bound = false;
+ }
+
private:
std::string _key;
bool _inclusive;
@@ -165,10 +172,27 @@ class cursor_bound_01 : public test {
if (normal_ret == WT_NOTFOUND)
return;
+
+ const char *normal_key;
+ testutil_check(normal_cursor->get_key(normal_cursor.get(), &normal_key));
+ /*
+ * It is possible that there are no keys within the range. Therefore make sure that normal
+ * cursor returns a key that is outside of the range.
+ */
+ if (range_ret == WT_NOTFOUND) {
+ if (next) {
+ testutil_assert(!upper_key.empty());
+ testutil_assert(!custom_lexicographical_compare(normal_key, upper_key, true));
+ } else {
+ testutil_assert(!lower_key.empty());
+ testutil_assert(custom_lexicographical_compare(normal_key, lower_key, false));
+ }
+ return;
+ }
testutil_assert(range_ret == 0 && normal_ret == 0);
/* Retrieve the key the cursor is pointing at. */
- const char *normal_key, *range_key;
+ const char *range_key;
testutil_check(normal_cursor->get_key(normal_cursor.get(), &normal_key));
testutil_check(range_cursor->get_key(range_cursor.get(), &range_key));
testutil_assert(std::string(normal_key).compare(range_key) == 0);
@@ -229,29 +253,40 @@ class cursor_bound_01 : public test {
testutil_check(range_cursor->bound(range_cursor.get(), "action=clear"));
if (set_random_bounds == LOWER_BOUND_SET || set_random_bounds == ALL_BOUNDS_SET) {
- /* Reverse case. */
- if (_reverse_collator_enabled)
- lower_bound = bound(tc->key_size, true, std::string(tc->key_size, 'z'));
- /* Normal case. */
- else
- lower_bound = bound(tc->key_size, true, "0");
+ lower_bound = bound(tc->key_size, true);
range_cursor->set_key(range_cursor.get(), lower_bound.get_key().c_str());
ret = range_cursor->bound(range_cursor.get(), lower_bound.get_config().c_str());
testutil_assert(ret == 0 || ret == EINVAL);
+
+ /*
+ * It is possible that the new lower bound overlaps with the upper bound. In that case,
+ * just clear the lower bound and continue with test.
+ */
+ if (ret == EINVAL)
+ lower_bound.clear();
}
if (set_random_bounds == UPPER_BOUND_SET || set_random_bounds == ALL_BOUNDS_SET) {
- /* Reverse case. */
- if (_reverse_collator_enabled)
- upper_bound = bound(tc->key_size, false, "0");
- /* Normal case. */
- else
- upper_bound = bound(tc->key_size, false, std::string(tc->key_size, 'z'));
+ upper_bound = bound(tc->key_size, false);
range_cursor->set_key(range_cursor.get(), upper_bound.get_key().c_str());
ret = range_cursor->bound(range_cursor.get(), upper_bound.get_config().c_str());
testutil_assert(ret == 0 || ret == EINVAL);
+
+ /*
+ * It is possible that the new upper bound overlaps with the lower bound. In that case,
+ * just clear the upper bound and continue with test.
+ */
+ if (ret == EINVAL)
+ upper_bound.clear();
}
+ /*
+ * It is possible that upper bound and lower bound both get EINVAL, in that case clear all
+ * bounds.
+ */
+ if (upper_bound.get_key().empty() && lower_bound.get_key().empty())
+ testutil_check(range_cursor->bound(range_cursor.get(), "action=clear"));
+
return std::make_pair(lower_bound, upper_bound);
}
@@ -357,7 +392,7 @@ class cursor_bound_01 : public test {
* When exact < 0, the returned key should be less than the search key and performing a
* next() should be greater than the search key.
*/
- } else if (range_exact < 0) {
+ } else {
testutil_assert(custom_lexicographical_compare(key, search_key, false));
/* Check that the next key is greater than the search key. */
@@ -410,7 +445,8 @@ class cursor_bound_01 : public test {
validate_search_near_not_found(
scoped_cursor &normal_cursor, const bound &lower_bound, const bound &upper_bound)
{
- int ret, exact;
+ int ret = 0, exact = 0;
+
auto lower_key = lower_bound.get_key();
auto upper_key = upper_bound.get_key();
logger::log_msg(LOG_TRACE,
@@ -578,30 +614,34 @@ class cursor_bound_01 : public test {
logger::log_msg(
LOG_INFO, type_string(tc->type) + " thread {" + std::to_string(tc->id) + "} commencing.");
- bound lower_bound, upper_bound;
std::map<uint64_t, scoped_cursor> cursors;
-
+ /* Maintain the lower and upper bound for each cursor held in the cursors map. */
+ std::map<uint64_t, std::pair<bound, bound>> bounds;
while (tc->running()) {
/* Get a random collection to work on. */
collection &coll = tc->db.get_random_collection();
/* Find a cached cursor or create one if none exists. */
- if (cursors.find(coll.id) == cursors.end())
+ if (cursors.find(coll.id) == cursors.end()) {
+ bound lower_bound, upper_bound;
cursors.emplace(coll.id, std::move(tc->session.open_scoped_cursor(coll.name)));
+ bounds.emplace(coll.id, std::move(std::make_pair(lower_bound, upper_bound)));
+ }
/* Set random bounds on cached range cursor. */
auto &range_cursor = cursors[coll.id];
- auto bound_pair = set_random_bounds(tc, range_cursor);
+ auto &bound_pair = bounds[coll.id];
+ auto new_bound_pair = set_random_bounds(tc, range_cursor);
/* Only update the bounds when the bounds have a key. */
- if (!bound_pair.first.get_key().empty())
- lower_bound = bound_pair.first;
- if (!bound_pair.second.get_key().empty())
- upper_bound = bound_pair.second;
+ if (!!new_bound_pair.first.get_key().empty())
+ bound_pair.first = new_bound_pair.first;
+ if (!new_bound_pair.second.get_key().empty())
+ bound_pair.second = new_bound_pair.second;
/* Clear all bounds if both bounds don't have a key. */
- if (bound_pair.first.get_key().empty() && bound_pair.second.get_key().empty()) {
- lower_bound = bound_pair.first;
- upper_bound = bound_pair.second;
+ if (new_bound_pair.first.get_key().empty() && new_bound_pair.second.get_key().empty()) {
+ bound_pair.first.clear();
+ bound_pair.second.clear();
}
scoped_cursor normal_cursor = tc->session.open_scoped_cursor(coll.name);
@@ -620,20 +660,19 @@ class cursor_bound_01 : public test {
auto srch_key = random_generator::instance().generate_random_string(
key_size, characters_type::ALPHABET);
- int exact;
+ int exact = 0;
range_cursor->set_key(range_cursor.get(), srch_key.c_str());
auto ret = range_cursor->search_near(range_cursor.get(), &exact);
testutil_assert(ret == 0 || ret == WT_NOTFOUND);
/* Verify the bound search_near result using the normal cursor. */
- validate_bound_search_near(
- ret, exact, range_cursor, normal_cursor, srch_key, lower_bound, upper_bound);
+ validate_bound_search_near(ret, exact, range_cursor, normal_cursor, srch_key,
+ bound_pair.first, bound_pair.second);
tc->txn.add_op();
tc->txn.try_rollback();
tc->sleep();
}
- testutil_check(range_cursor->reset(range_cursor.get()));
}
/* Roll back the last transaction if still active now the work is finished. */
if (tc->txn.active())
@@ -652,28 +691,33 @@ class cursor_bound_01 : public test {
LOG_INFO, type_string(tc->type) + " thread {" + std::to_string(tc->id) + "} commencing.");
std::map<uint64_t, scoped_cursor> cursors;
- bound lower_bound, upper_bound;
+ /* Maintain the lower and upper bound for each cursor held in the cursors map. */
+ std::map<uint64_t, std::pair<bound, bound>> bounds;
while (tc->running()) {
/* Get a random collection to work on. */
collection &coll = tc->db.get_random_collection();
/* Find a cached cursor or create one if none exists. */
- if (cursors.find(coll.id) == cursors.end())
+ if (cursors.find(coll.id) == cursors.end()) {
+ bound lower_bound, upper_bound;
cursors.emplace(coll.id, std::move(tc->session.open_scoped_cursor(coll.name)));
+ bounds.emplace(coll.id, std::move(std::make_pair(lower_bound, upper_bound)));
+ }
/* Set random bounds on cached range cursor. */
auto &range_cursor = cursors[coll.id];
- auto bound_pair = set_random_bounds(tc, range_cursor);
+ auto &bound_pair = bounds[coll.id];
+ auto new_bound_pair = set_random_bounds(tc, range_cursor);
/* Only update the bounds when the bounds have a key. */
- if (!bound_pair.first.get_key().empty())
- lower_bound = bound_pair.first;
- if (!bound_pair.second.get_key().empty())
- upper_bound = bound_pair.second;
-
- /* Clear all bounds if both bounds doesn't have a key. */
- if (bound_pair.first.get_key().empty() && bound_pair.second.get_key().empty()) {
- lower_bound = bound_pair.first;
- upper_bound = bound_pair.second;
+ if (!new_bound_pair.first.get_key().empty())
+ bound_pair.first = new_bound_pair.first;
+ if (!new_bound_pair.second.get_key().empty())
+ bound_pair.second = new_bound_pair.second;
+
+ /* Clear all bounds if both bounds don't have a key. */
+ if (new_bound_pair.first.get_key().empty() && new_bound_pair.second.get_key().empty()) {
+ bound_pair.first.clear();
+ bound_pair.second.clear();
}
scoped_cursor normal_cursor = tc->session.open_scoped_cursor(coll.name);
@@ -685,14 +729,14 @@ class cursor_bound_01 : public test {
tc->txn.begin(
"roundup_timestamps=(read=true),read_timestamp=" + tc->tsm->decimal_to_hex(ts));
while (tc->txn.active() && tc->running()) {
-
- cursor_traversal(range_cursor, normal_cursor, lower_bound, upper_bound, true);
- cursor_traversal(range_cursor, normal_cursor, lower_bound, upper_bound, false);
+ cursor_traversal(
+ range_cursor, normal_cursor, bound_pair.first, bound_pair.second, true);
+ cursor_traversal(
+ range_cursor, normal_cursor, bound_pair.first, bound_pair.second, false);
tc->txn.add_op();
tc->txn.try_rollback();
tc->sleep();
}
- testutil_check(range_cursor->reset(range_cursor.get()));
}
/* Roll back the last transaction if still active now the work is finished. */
if (tc->txn.active())