test/lib/cql_assertions: introduce columns_assertions

To enable targeted and optionally typed assertions against individual
columns in a row.

(cherry picked from commit aae212a87c)
This commit is contained in:
Botond Dénes
2025-06-20 13:07:59 +03:00
parent 00402cb4c5
commit db07141cea
2 changed files with 88 additions and 0 deletions

View File

@@ -21,6 +21,47 @@ static inline void fail(sstring msg) {
throw std::runtime_error(msg);
}
void columns_assertions::fail(const sstring& msg) {
::fail(msg);
}
columns_assertions& columns_assertions::do_with_raw_column(const char* name, std::function<void(data_type, managed_bytes_view)> func) {
const auto& names = _metadata.get_names();
auto it = std::ranges::find_if(names, [name] (const auto& col) {
return col->name->text() == name;
});
if (it == names.end()) {
::fail(seastar::format("Column {} not found in metadata", name));
}
const size_t index = std::distance(names.begin(), it);
const auto& value = _columns.at(index);
if (!value) {
::fail(seastar::format("Column {} is null", name));
}
func((*it)->type, *value);
return *this;
}
columns_assertions& columns_assertions::with_raw_column(const char* name, std::function<bool(managed_bytes_view)> predicate) {
return do_with_raw_column(name, [name, &predicate] (data_type, managed_bytes_view value) {
if (!predicate(value)) {
::fail(seastar::format("Column {} failed predicate check: value = {}", name, value));
}
});
}
columns_assertions& columns_assertions::with_raw_column(const char* name, managed_bytes_view value) {
return do_with_raw_column(name, [name, &value] (data_type, managed_bytes_view cell_value) {
if (cell_value != value) {
::fail(seastar::format("Expected column {} to have value {}, but got {}", name, value, cell_value));
}
});
}
rows_assertions::rows_assertions(shared_ptr<cql_transport::messages::result_message::rows> rows)
: _rows(rows)
{ }
@@ -165,6 +206,11 @@ rows_assertions::with_rows_ignore_order(std::vector<std::vector<bytes_opt>> rows
return {*this};
}
columns_assertions rows_assertions::with_columns_of_row(size_t row_index) {
const auto& rs = _rows->rs().result_set();
return columns_assertions(rs.get_metadata(), rs.rows().at(row_index));
}
result_msg_assertions::result_msg_assertions(shared_ptr<cql_transport::messages::result_message> msg)
: _msg(msg)
{ }

View File

@@ -10,6 +10,7 @@
#pragma once
#include "utils/assert.hh"
#include "utils/managed_bytes.hh"
#include "test/lib/cql_test_env.hh"
#include "transport/messages/result_message_base.hh"
#include "bytes.hh"
@@ -17,6 +18,45 @@
#include <seastar/core/shared_ptr.hh>
#include <seastar/core/future.hh>
class columns_assertions {
const cql3::metadata& _metadata;
const std::vector<managed_bytes_opt>& _columns;
columns_assertions& do_with_raw_column(const char* name, std::function<void(data_type, managed_bytes_view)> func);
void fail(const sstring& msg);
public:
columns_assertions(const cql3::metadata& metadata, const std::vector<managed_bytes_opt>& columns)
: _metadata(metadata), _columns(columns)
{ }
columns_assertions& with_raw_column(const char* name, std::function<bool(managed_bytes_view)> predicate);
columns_assertions& with_raw_column(const char* name, managed_bytes_view value);
template <typename T>
columns_assertions& with_typed_column(const char* name, std::function<bool(const T& value)> predicate) {
return do_with_raw_column(name, [this, name, predicate] (data_type type, managed_bytes_view value) {
if (type != data_type_for<T>()) {
fail(seastar::format("Column {} is not of type {}, but of type {}", name, data_type_for<T>()->name(), type->name()));
}
if (!predicate(value_cast<T>(type->deserialize(value)))) {
fail(seastar::format("Column {} failed predicate check: value = {}", name, value));
}
});
}
template <typename T>
columns_assertions& with_typed_column(const char* name, const T& value) {
return with_typed_column<T>(name, [this, name, &value] (const T& cell_value) {
if (cell_value != value) {
fail(seastar::format("Expected column {} to have value {}, but got {}", name, value, cell_value));
}
return true;
});
}
};
class rows_assertions {
shared_ptr<cql_transport::messages::result_message::rows> _rows;
public:
@@ -33,6 +73,8 @@ public:
rows_assertions with_rows_ignore_order(std::vector<std::vector<bytes_opt>> rows);
rows_assertions with_serialized_columns_count(size_t columns_count);
columns_assertions with_columns_of_row(size_t row_index);
rows_assertions is_null();
rows_assertions is_not_null();
};