Files
scylladb/test/lib/index_reader_assertions.hh
Michał Chojnowski 70a6c9481b test/lib/index_reader_assertions: skip some row index checks for BTI indexes
Block monotonicity checks can't be implemented for BTI row indexes
because they don't store full clustering positions, only some encoded
prefixes.

The emptiness check could be implemented with some effort,
but we currently don't bother.
The two tests which use this `is_empty()` method aren't very
useful anyway. (They check that the promoted index is empty when
there are no clustering keys. That doesn't really need a dedicated
test).
2025-09-29 22:15:25 +02:00

96 lines
3.1 KiB
C++

/*
* Copyright (C) 2017-present ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
*/
#pragma once
#include <boost/test/unit_test.hpp>
#include "dht/i_partitioner.hh"
#include "schema/schema.hh"
#include "sstables/index_reader.hh"
#include "reader_concurrency_semaphore.hh"
#include "test/lib/log.hh"
class index_reader_assertions {
std::unique_ptr<sstables::abstract_index_reader> _r;
public:
// Must be called from a seastar thread
~index_reader_assertions() {
close().get();
}
index_reader_assertions(std::unique_ptr<sstables::abstract_index_reader> r)
: _r(std::move(r))
{ }
index_reader_assertions& has_monotonic_positions(const schema& s) {
tests::reader_concurrency_semaphore_wrapper semaphore;
auto pos_cmp = sstables::promoted_index_block_compare(s);
auto rp_cmp = dht::ring_position_comparator(s);
auto prev = dht::ring_position::min();
_r->read_partition_data().get();
while (!_r->eof()) {
if (auto k = _r->get_partition_key()) {
auto rp = dht::ring_position(dht::decorate_key(s, *k));
if (rp_cmp(prev, rp) >= 0) {
BOOST_FAIL(format("Partitions have invalid order: {} >= {}", prev, rp));
}
prev = rp;
}
if (auto* r = dynamic_cast<sstables::index_reader*>(_r.get())) {
sstables::clustered_index_cursor* cur = r->current_clustered_cursor();
std::optional<sstables::promoted_index_block_position> prev_end;
while (auto ei_opt = cur->next_entry().get()) {
sstables::clustered_index_cursor::entry_info& ei = *ei_opt;
if (prev_end && pos_cmp(ei.start, sstables::to_view(*prev_end))) {
BOOST_FAIL(seastar::format("Index blocks are not monotonic: {} > {}", *prev_end, ei.start));
}
prev_end = sstables::materialize(ei.end);
}
} else {
auto& ref = *_r;
testlog.warn("Skipping row index monotonicity check for index type {}, because iteration over index blocks is not supported", typeid(ref).name());
}
_r->advance_to_next_partition().get();
}
return *this;
}
index_reader_assertions& is_empty(const schema& s) {
if (auto* r = dynamic_cast<sstables::index_reader*>(_r.get())) {
_r->read_partition_data().get();
while (!_r->eof()) {
BOOST_REQUIRE(r->get_promoted_index_size() == 0);
_r->advance_to_next_partition().get();
}
} else {
auto& ref = *_r;
testlog.warn("Skipping row index emptiness check for index type {}, because iteration over index blocks is not supported", typeid(ref).name());
}
return *this;
}
future<> close() noexcept {
if (_r) {
auto r = std::move(_r);
auto f = r->close();
return f.then([r = std::move(r)] {});
}
return make_ready_future<>();
}
};
inline
index_reader_assertions assert_that(std::unique_ptr<sstables::abstract_index_reader> r) {
return { std::move(r) };
}