- extracted from a larger commit
- removed coupling with how cache_streamed_mutation is created (the
code went out of sync), used more stable make_reader(). it's simpler too.
- replaced false/true literals with is_continuous/is_dummy where appropraite
- dropped tests for cache::underlying (class is gone)
- reused streamed_mutation_assertions, it has better error messages
- fixed the tests to not create tombstones with missing timestamps
- relaxed range tombstone assertions to only check information relevant for the query range
- print cache on failure for improved debuggability
]
---
configure.py | 1 +
test.py | 1 +
row_cache.hh | 1 +
tests/cache_streamed_mutation_test.cc | 1272 +++++++++++++++++++++++++++++++++
4 files changed, 1275 insertions(+)
create mode 100644 tests/cache_streamed_mutation_test.cc
diff --git a/configure.py b/configure.py
index 77c3c4c..a90c43d 100755
--- a/configure.py
+++ b/configure.py
@@ -184,6 +184,7 @@ scylla_tests = [
'tests/perf/perf_cql_parser',
'tests/perf/perf_simple_query',
'tests/perf/perf_fast_forward',
+ 'tests/cache_streamed_mutation_test',
'tests/memory_footprint',
'tests/perf/perf_sstable',
'tests/cql_query_test',
diff --git a/test.py b/test.py
index e783ed0..5c70753 100755
--- a/test.py
+++ b/test.py
@@ -53,6 +53,7 @@ boost_tests = [
'canonical_mutation_test',
'gossiping_property_file_snitch_test',
'row_cache_test',
+ 'cache_streamed_mutation_test',
'network_topology_strategy_test',
'query_processor_test',
'batchlog_manager_test',
diff --git a/row_cache.hh b/row_cache.hh
index b6e8c5b..c6e822e 100644
--- a/row_cache.hh
+++ b/row_cache.hh
@@ -258,6 +258,7 @@ class row_cache final {
friend class cache::lsa_manager;
friend class cache::read_context;
friend class partition_range_iterator;
+ friend class cache_tester;
public:
struct stats {
utils::timed_rate_moving_average hits;
diff --git a/tests/cache_streamed_mutation_test.cc b/tests/cache_streamed_mutation_test.cc
new file mode 100644
index 0000000..c0c4492
--- /dev/null
+++ b/tests/cache_streamed_mutation_test.cc
@@ -0,0 +1,1272 @@
+
+/*
+ * Copyright (C) 2017 ScyllaDB
+ */
+
+/*
+ * This file is part of Scylla.
+ *
+ * Scylla is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Scylla is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Scylla. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+
+#include <boost/test/unit_test.hpp>
+
+#include "tests/test-utils.hh"
+#include "core/thread.hh"
+#include "schema_builder.hh"
+#include "keys.hh"
+#include "mutation_partition.hh"
+#include "partition_version.hh"
+#include "mutation.hh"
+#include "memtable.hh"
+#include "cache_streamed_mutation.hh"
+#include "row_cache.hh"
+
+#include "disk-error-handler.hh"
+#include "memtable_snapshot_source.hh"
+#include "mutation_assertions.hh"
+
+thread_local disk_error_signal_type commit_error;
+thread_local disk_error_signal_type general_disk_error;
+
+/*
+ * ===================
+ * ====== Utils ======
+ * ===================
+ */
+
+static schema_ptr make_schema() {
+ return schema_builder("ks", "cf")
+ .with_column("pk", int32_type, column_kind::partition_key)
+ .with_column("ck", int32_type, column_kind::clustering_key)
+ .with_column("v", int32_type)
+ .build();
+}
+
+static const thread_local schema_ptr SCHEMA = make_schema();
+
+static partition_key make_pk(int value) {
+ return partition_key::from_exploded(*SCHEMA, { int32_type->decompose(value) });
+}
+
+static const thread_local partition_key PK = make_pk(0);
+static const thread_local dht::decorated_key DK =
+ dht::global_partitioner().decorate_key(*SCHEMA, PK);
+
+static clustering_key make_ck(int value) {
+ return clustering_key_prefix::from_single_value(*SCHEMA, int32_type->decompose(value));
+}
+
+static void add_row(mutation& m, int ck, int value) {
+ m.set_clustered_cell(make_ck(ck), "v", data_value(value), 1);
+}
+
+static void add_tombstone(mutation& m, range_tombstone rt) {
+ m.partition().apply_row_tombstone(*SCHEMA, rt);
+}
+
+static void set_row_continuous(mutation_partition& mp, int ck, is_continuous value) {
+ auto it = mp.clustered_rows().find(make_ck(ck), rows_entry::compare(*SCHEMA));
+ assert(it != mp.clustered_rows().end());
+ it->set_continuous(value);
+}
+
+static query::partition_slice make_slice(std::vector<query::clustering_range> ranges) {
+ return query::partition_slice(std::move(ranges), { }, { }, { });
+}
+
+struct expected_fragment {
+ boost::variant<int, range_tombstone> f;
+
+ expected_fragment(int row_key) : f(row_key) { }
+ expected_fragment(range_tombstone rt) : f(rt) { }
+
+ void check(streamed_mutation_assertions& sm, const query::clustering_row_ranges& ranges) {
+ if (f.which() == 0) {
+ sm.produces_row_with_key(make_ck(boost::get<int>(f)));
+ } else {
+ sm.produces_range_tombstone(boost::get<range_tombstone>(f), ranges);
+ }
+ }
+};
+
+static
+mutation make_incomplete_mutation() {
+ return mutation(SCHEMA, DK, mutation_partition::make_incomplete(*SCHEMA));
+}
+
+static void assert_single_version(lw_shared_ptr<partition_snapshot> snp) {
+ BOOST_REQUIRE(snp->at_latest_version());
+ BOOST_REQUIRE_EQUAL(snp->version_count(), 1);
+}
+
+struct expected_row {
+ int ck;
+ is_continuous continuous;
+ is_dummy dummy;
+
+ struct dummy_tag_t { };
+
+ expected_row(int k, is_continuous cont)
+ : ck(k), continuous(cont), dummy(false) { }
+ expected_row(dummy_tag_t, is_continuous cont)
+ : continuous(cont), dummy(true) { }
+
+ void check(const rows_entry& r) const {
+ clustering_key::equality ck_eq(*SCHEMA);
+ BOOST_REQUIRE_EQUAL(r.continuous(), continuous);
+ BOOST_REQUIRE_EQUAL(r.dummy(), dummy);
+ if (!r.dummy()) {
+ BOOST_REQUIRE(ck_eq(r.key(), make_ck(ck)));
+ }
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, const expected_row& e) {
+ return out << "{ck=" <<
e.ck << ", cont=" << bool(e.continuous) << ", dummy=" << bool(e.dummy) << "}";
+ }
+};
+
+static void assert_cached_rows(lw_shared_ptr<partition_snapshot> snp, std::deque<expected_row> expected) {
+ auto&& rows = snp->version()->partition().clustered_rows();
+ for (auto&& r : rows) {
+ BOOST_REQUIRE(!expected.empty());
+ expected.front().check(r);
+ expected.pop_front();
+ }
+ if (!expected.empty()) {
+ BOOST_FAIL(sprint("Expected %s next, but no more rows", expected.front()));
+ }
+}
+
+struct expected_tombstone {
+ int start;
+ bool start_inclusive;
+ int end;
+ bool end_inclusive;
+
+ expected_tombstone(int s, bool s_i, int e, bool e_i)
+ : start(s)
+ , start_inclusive(s_i)
+ , end(e)
+ , end_inclusive(e_i)
+ { }
+ void check(const range_tombstone& rt) const {
+ clustering_key::equality ck_eq(*SCHEMA);
+ BOOST_REQUIRE(ck_eq(rt.start, make_ck(start)));
+ BOOST_REQUIRE_EQUAL(rt.start_kind, start_inclusive ? bound_kind::incl_start : bound_kind::excl_start);
+ BOOST_REQUIRE(ck_eq(rt.end, make_ck(end)));
+ BOOST_REQUIRE_EQUAL(rt.end_kind, end_inclusive ? bound_kind::incl_end : bound_kind::excl_end);
+ }
+};
+
+static void assert_cached_tombstones(lw_shared_ptr<partition_snapshot> snp, std::deque<range_tombstone> expected) {
+ const range_tombstone_list& rts = snp->version()->partition().row_tombstones();
+ for (auto&& rt : rts) {
+ BOOST_REQUIRE(!expected.empty());
+ if (!expected.front().equal(*SCHEMA, rt)) {
+ BOOST_FAIL(sprint("Expected %s, but found %s", expected.front(), rt));
+ }
+ expected.pop_front();
+ }
+ BOOST_REQUIRE(expected.empty());
+}
+
+class cache_tester {
+public:
+ static lw_shared_ptr<partition_snapshot> snapshot_for_key(row_cache& rc, const dht::decorated_key& dk) {
+ return rc._read_section(rc._tracker.region(), [&] {
+ return with_linearized_managed_bytes([&] {
+ cache_entry& e = rc.find_or_create(dk);
+ return e.partition().read(e.schema());
+ });
+ });
+ }
+};
+
+static void check_produces_only(streamed_mutation sm, std::deque<expected_fragment> expected, const query::clustering_row_ranges& ranges) {
+ auto sa = assert_that_stream(std::move(sm));
+ for (auto&& e : expected) {
+ e.check(sa, ranges);
+ }
+ sa.produces_end_of_stream();
+}
+
+void test_slice_single_version(mutation& underlying,
+ mutation& cache_mutation,
+ const query::partition_slice& slice,
+ std::deque<expected_fragment> expected_sm_fragments,
+ std::deque<expected_row> expected_cache_rows,
+ std::deque<range_tombstone> expected_cache_tombstones) {
+ // Set up underlying
+ memtable_snapshot_source source_mt(SCHEMA);
+ source_mt.apply(underlying);
+ cache_tracker tracker;
+ row_cache cache(SCHEMA, snapshot_source([&] { return source_mt(); }), tracker);
+
+ cache.populate(cache_mutation);
+
+ try {
+ auto range = dht::partition_range::make_singular(DK);
+ auto reader = cache.make_reader(SCHEMA, range, slice);
+ auto smo = reader().get0();
+ BOOST_REQUIRE(bool(smo));
+
+ check_produces_only(std::move(*smo), expected_sm_fragments, slice.row_ranges(*SCHEMA, DK.key()));
+
+ auto snp = cache_tester::snapshot_for_key(cache, DK);
+ assert_single_version(snp);
+ assert_cached_rows(snp, expected_cache_rows);
+ assert_cached_tombstones(snp, expected_cache_tombstones);
+ } catch (...) {
+ std::cerr << "cache: " << cache << "\n";
+ throw;
+ }
+}
+
+/*
+ * ========================================================
+ * ====== Tests for single row with a single version ======
+ * ========================================================
+ */
+void test_single_row(int ck,
+ bool cached,
+ is_continuous continuous,
+ const query::partition_slice& slice,
+ std::deque<int> expected_sm_rows,
+ std::deque<expected_row> expected_cache_rows) {
+ const int value = 12;
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck, value);
+
+ auto m = make_incomplete_mutation();
+ if (cached) {
+ add_row(m, ck, value);
+ set_row_continuous(m.partition(), ck, continuous);
+ }
+
+ std::deque<expected_fragment> expected_sm_fragments;
+ for (int r : expected_sm_rows) {
+ expected_sm_fragments.push_back(expected_fragment(r));
+ }
+ test_slice_single_version(underlying, m, slice, expected_sm_fragments, expected_cache_rows, { });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_full_range) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, query::full_slice, { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_single_row_range) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make_singular(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_range_from_start_to_row) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_range_from_row_to_end) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_exclusive_range_on_the_left) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with({make_ck(1), false}) }),
+ { }, { expected_row(expected_row::dummy_tag_t{}, is_continuous::no) });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_exclusive_range_on_the_right) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with({make_ck(1), false}) }),
+ { }, { expected_row(expected_row::dummy_tag_t{}, is_continuous::no) });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_small_range) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(0), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_small_range_on_left) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(0), make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_not_cached_small_range_on_right) {
+ return seastar::async([] {
+ test_single_row(1, false, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(1), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_full_range) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, query::full_slice, { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_single_row_range) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make_singular(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_range_from_start_to_row) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_range_from_row_to_end) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_exclusive_range_on_the_left) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with({make_ck(1), false}) }), { }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_exclusive_range_on_the_right) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with({make_ck(1), false}) }), { }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_small_range) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(0), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_small_range_on_left) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(0), make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_continuous_small_range_on_right) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(1), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_full_range) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, query::full_slice, { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_single_row_range) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make_singular(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_range_from_start_to_row) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make_ending_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_range_from_row_to_end) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make_starting_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_exclusive_range_on_the_left) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make_ending_with({make_ck(1), false}) }), { }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_exclusive_range_on_the_right) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make_starting_with({make_ck(1), false}) }), { }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_small_range) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_small_range_on_left) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_cached_as_noncontinuous_small_range_on_right) {
+ return seastar::async([] {
+ test_single_row(1, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(1), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+/*
+ * ======================================================
+ * ====== Tests for two rows with a single version ======
+ * ======================================================
+ */
+
+void test_two_rows(int ck1,
+ bool cached1,
+ is_continuous continuous1,
+ int ck2,
+ bool cached2,
+ is_continuous continuous2,
+ const query::partition_slice& slice,
+ std::deque<int> expected_sm_rows,
+ std::deque<expected_row> expected_cache_rows) {
+ const int value1 = 12;
+ const int value2 = 34;
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck1, value1);
+ add_row(underlying, ck2, value2);
+
+ auto cache = make_incomplete_mutation();
+ if (cached1) {
+ add_row(cache, ck1, value1);
+ set_row_continuous(cache.partition(), ck1, continuous1);
+ }
+ if (cached2) {
+ add_row(cache, ck2, value2);
+ set_row_continuous(cache.partition(), ck2, continuous2);
+ }
+ std::deque<expected_fragment> expected_sm_fragments;
+ for (int r : expected_sm_rows) {
+ expected_sm_fragments.push_back(expected_fragment(r));
+ }
+ test_slice_single_version(underlying, cache, slice, expected_sm_fragments, expected_cache_rows, { });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_full_range) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, query::full_slice, { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_single_row_range1) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_singular(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_single_row_range2) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_singular(make_ck(3)) }), { 3 }, {
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_range_from_start_to_row1) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_ending_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_range_from_start_to_row2) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_ending_with(make_ck(3)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_range_from_row1_to_end) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_starting_with(make_ck(1)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_range_from_row2_to_end) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_starting_with(make_ck(3)) }), { 3 }, {
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_exclusive_range_on_the_left) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_ending_with({make_ck(3), false}) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_exclusive_range_on_the_right) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make_starting_with({make_ck(1), false}) }), { 3 }, {
+ expected_row(3, is_continuous::no), // TODO: this should be possible to mark continuous here
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_exclusive_range_between_rows1) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make({make_ck(1), false}, {make_ck(3), false}) }),
+ { }, { expected_row(expected_row::dummy_tag_t{}, is_continuous::no) });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_exclusive_range_between_rows2) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make({make_ck(1), false}, make_ck(3)) }), { 3 }, {
+ expected_row(3, is_continuous::no), // TODO: this should be possible to mark continuous here
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_exclusive_range_between_rows3) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(1), {make_ck(3), false}) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_small_range) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_small_range_row1) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_not_cached_small_range_row2) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_full_range) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, query::full_slice, { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_single_row_range1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_singular(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_single_row_range2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_singular(make_ck(3)) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_range_from_start_to_row1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_range_from_start_to_row2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with(make_ck(3)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_range_from_row1_to_end) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with(make_ck(1)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_range_from_row2_to_end) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with(make_ck(3)) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_exclusive_range_on_the_left) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_ending_with({make_ck(3), false}) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_exclusive_range_on_the_right) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make_starting_with({make_ck(1), false}) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_exclusive_range_between_rows1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make({make_ck(1), false}, {make_ck(3), false}) }), { }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_exclusive_range_between_rows2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make({make_ck(1), false}, make_ck(3)) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_exclusive_range_between_rows3) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(1), {make_ck(3), false}) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_small_range) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_small_range_row1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(0), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_continuous_small_range_row2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, true, is_continuous::yes, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_full_range) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, query::full_slice, { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_single_row_range1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_singular(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_single_row_range2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_singular(make_ck(3)) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_range_from_start_to_row1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_ending_with(make_ck(1)) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_range_from_start_to_row2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_ending_with(make_ck(3)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_range_from_row1_to_end) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_starting_with(make_ck(1)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_range_from_row2_to_end) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_starting_with(make_ck(3)) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_exclusive_range_on_the_left) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_ending_with({make_ck(3), false}) }), { 1 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_exclusive_range_on_the_right) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make_starting_with({make_ck(1), false}) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::yes)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_exclusive_range_between_rows1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make({make_ck(1), false}, {make_ck(3), false}) }), { }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_exclusive_range_between_rows2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make({make_ck(1), false}, make_ck(3)) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_exclusive_range_between_rows3) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(1), {make_ck(3), false}) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_small_range) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_small_range_row1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(2)) }), { 1 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_cached_non_continuous_small_range_row2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_first_not_cached_second_cached_non_continuous1) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_first_not_cached_second_cached_non_continuous2) {
+ return seastar::async([] {
+ test_two_rows(1, false, is_continuous::no, 3, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_first_cached_non_continuous_second_not_cached1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_first_cached_non_continuous_second_not_cached2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::no, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_first_cached_continuous_second_not_cached1) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_two_rows_first_cached_continuous_second_not_cached2) {
+ return seastar::async([] {
+ test_two_rows(1, true, is_continuous::yes, 3, false, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+/*
+ * ========================================================
+ * ====== Tests for three rows with a single version ======
+ * ========================================================
+ */
+
+void test_three_rows(int ck1,
+ bool cached1,
+ is_continuous continuous1,
+ int ck2,
+ bool cached2,
+ is_continuous continuous2,
+ int ck3,
+ bool cached3,
+ is_continuous continuous3,
+ const query::partition_slice& slice,
+ std::deque<int> expected_sm_rows,
+ std::deque<expected_row> expected_cache_rows) {
+ const int value1 = 12;
+ const int value2 = 34;
+ const int value3 = 56;
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck1, value1);
+ add_row(underlying, ck2, value2);
+ add_row(underlying, ck3, value3);
+
+ auto cache = make_incomplete_mutation();
+ if (cached1) {
+ add_row(cache, ck1, value1);
+ set_row_continuous(cache.partition(), ck1, continuous1);
+ }
+ if (cached2) {
+ add_row(cache, ck2, value2);
+ set_row_continuous(cache.partition(), ck2, continuous2);
+ }
+ if (cached3) {
+ add_row(cache, ck3, value3);
+ set_row_continuous(cache.partition(), ck3, continuous3);
+ }
+ std::deque<expected_fragment> expected_sm_fragments;
+ for (int r : expected_sm_rows) {
+ expected_sm_fragments.push_back(expected_fragment(r));
+ }
+ test_slice_single_version(underlying, cache, slice, expected_sm_fragments, expected_cache_rows, { });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_continuous1) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::yes, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(6)) }), { 1, 3, 5 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(5, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_continuous2) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::yes, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(6)) }), { 3, 5 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::no),
+ expected_row(5, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_continuous3) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::yes, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::yes),
+ expected_row(5, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_continuous4) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::yes, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(1, is_continuous::yes),
+ expected_row(3, is_continuous::no),
+ expected_row(5, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_noncontinuous1) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::no, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(6)) }), { 1, 3, 5 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(5, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_noncontinuous2) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::no, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(6)) }), { 3, 5 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(5, is_continuous::yes),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_nonecontinuous3) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::no, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(0), make_ck(4)) }), { 1, 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::yes),
+ expected_row(5, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+SEASTAR_TEST_CASE(test_three_rows_first_nonecontinuous4) {
+ return seastar::async([] {
+ test_three_rows(1, true, is_continuous::no, 3, false, is_continuous::no, 5, true, is_continuous::no, make_slice({ query::clustering_range::make(make_ck(2), make_ck(4)) }), { 3 }, {
+ expected_row(1, is_continuous::no),
+ expected_row(3, is_continuous::no),
+ expected_row(5, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ });
+ });
+}
+
+/*
+ * ================================================================================================
+ * ====== Tests for single rows and range tombstone with single version and single row range ======
+ * ================================================================================================
+ */
+
+static tombstone new_tombstone() {
+ return tombstone(api::new_timestamp(), gc_clock::now());
+}
+
+SEASTAR_TEST_CASE(test_single_row_and_tombstone_not_cached_single_row_range1) {
+ return seastar::async([] {
+ const int ck1 = 1;
+ const int value1 = 12;
+ range_tombstone rt(make_ck(0), bound_kind::incl_start, make_ck(2), bound_kind::incl_end, new_tombstone());
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck1, value1);
+ add_tombstone(underlying, rt);
+
+ auto cache = make_incomplete_mutation();
+ auto slice = make_slice({ query::clustering_range::make_singular(make_ck(ck1)) });
+
+ test_slice_single_version(underlying, cache, slice, {
+ expected_fragment(rt),
+ expected_fragment(1)
+ }, {
+ expected_row(1, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ }, { rt });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_and_tombstone_not_cached_single_row_range2) {
+ return seastar::async([] {
+ const int ck1 = 1;
+ const int value1 = 12;
+ range_tombstone rt(make_ck(0), bound_kind::incl_start, make_ck(2), bound_kind::incl_end, new_tombstone());
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck1, value1);
+ add_tombstone(underlying, rt);
+
+ auto cache = make_incomplete_mutation();
+ auto slice = make_slice({ query::clustering_range::make(make_ck(0), {make_ck(1), false}) });
+
+ test_slice_single_version(underlying, cache, slice, {
+ expected_fragment(rt),
+ }, {
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ }, { rt });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_and_tombstone_not_cached_single_row_range3) {
+ return seastar::async([] {
+ const int ck1 = 4;
+ const int value1 = 12;
+ range_tombstone rt(make_ck(0), bound_kind::incl_start, make_ck(2), bound_kind::incl_end, new_tombstone());
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck1, value1);
+ add_tombstone(underlying, rt);
+
+ auto cache = make_incomplete_mutation();
+ auto slice = make_slice({ query::clustering_range::make(make_ck(0), make_ck(5)) });
+
+ test_slice_single_version(underlying, cache, slice, {
+ expected_fragment(rt),
+ expected_fragment(4)
+ }, {
+ expected_row(4, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ }, { rt });
+ });
+}
+
+SEASTAR_TEST_CASE(test_single_row_and_tombstone_not_cached_single_row_range4) {
+ return seastar::async([] {
+ const int ck1 = 4;
+ const int value1 = 12;
+ range_tombstone rt(make_ck(0), bound_kind::incl_start, make_ck(2), bound_kind::incl_end, new_tombstone());
+
+ mutation underlying(PK, SCHEMA);
+ add_row(underlying, ck1, value1);
+ add_tombstone(underlying, rt);
+
+ auto cache = make_incomplete_mutation();
+ auto slice = make_slice({ query::clustering_range::make(make_ck(3), make_ck(5)) });
+
+ test_slice_single_version(underlying, cache, slice, {
+ expected_fragment(4)
+ }, {
+ expected_row(4, is_continuous::no),
+ expected_row(expected_row::dummy_tag_t{}, is_continuous::no)
+ }, {});