Files
scylladb/test/lib/test_utils.hh
Kefu Chai 46d993a283 test: revert 4c1b6f04
in 4c1b6f04, we added a concept for fmt::is_formattable<>. but it
was not ncessary. the fmt::is_formattable<> trait was enough. the
reason 4c1b6f04 was actually a leftover of a bigger change which
tried to add trait for the cases where fmt::is_formattable<> was
not able to cover. but that was based on the wrong impression that
fmt::is_formattable<> should be able to work with container types
without including, for instance `fmt/ranges.h`. but in 222dbf2c,
we include `fmt/ranges.h` in tests, where the range-alike formatter
is used, that enables `fmt::is_formattable<>` to tell that container
types are formattable.

in short, 4c1b6f04 was created based on a misunderstanding, and
it was a reduced type trait, which is proved to be not necessary.

so, in this change, it is dropped. but the type constraints is
preserved to make the build failure more explicit, if the fallback
formatter does not match with the type to be formatted by Boost.test.

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#18879
2024-05-27 10:14:59 +03:00

126 lines
4.8 KiB
C++

/*
* Copyright (C) 2020-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#pragma once
#include <seastar/core/future.hh>
#include <seastar/util/source_location-compat.hh>
#include <string>
#include <boost/test/unit_test.hpp>
#include <fmt/core.h>
#include <fmt/format.h>
using namespace seastar;
// Thread safe alternatives to BOOST_REQUIRE_*, BOOST_CHECK_* and BOOST_FAIL().
// Use these if instead of the BOOST provided macros if you want to use them on
// multiple shards, to avoid problems due to the BOOST versions not being thread
// safe.
namespace tests {
[[nodiscard]] bool do_check(bool condition, seastar::compat::source_location sl, std::string_view msg);
[[nodiscard]] inline bool check(bool condition, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
return do_check(condition, sl, {});
}
template <typename LHS, typename RHS>
[[nodiscard]] bool check_equal(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
const auto condition = (lhs == rhs);
return do_check(condition, sl, fmt::format("{} {}= {}", lhs, condition ? "=" : "!", rhs));
}
void do_require(bool condition, seastar::compat::source_location sl, std::string_view msg);
inline void require(bool condition, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require(condition, sl, {});
}
template <typename LHS, typename RHS, typename Compare>
void do_require_relation(
const LHS& lhs,
const RHS& rhs,
const Compare& relation,
const char* relation_operator,
seastar::compat::source_location sl) {
const auto condition = relation(lhs, rhs);
do_require(condition, sl, fmt::format("assertion {} {} {} failed", lhs, relation_operator, rhs));
}
template <typename LHS, typename RHS>
void require_less(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require_relation(lhs, rhs, std::less<LHS>{}, "<", sl);
}
template <typename LHS, typename RHS>
void require_less_equal(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require_relation(lhs, rhs, std::less_equal<LHS>{}, "<=", sl);
}
template <typename LHS, typename RHS>
void require_equal(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require_relation(lhs, rhs, std::equal_to<LHS>{}, "==", sl);
}
template <typename LHS, typename RHS>
void require_not_equal(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require_relation(lhs, rhs, std::not_equal_to<LHS>{}, "!=", sl);
}
template <typename LHS, typename RHS>
void require_greater_equal(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require_relation(lhs, rhs, std::greater_equal<LHS>{}, ">=", sl);
}
template <typename LHS, typename RHS>
void require_greater(const LHS& lhs, const RHS& rhs, seastar::compat::source_location sl = seastar::compat::source_location::current()) {
do_require_relation(lhs, rhs, std::greater<LHS>{}, ">", sl);
}
void fail(std::string_view msg, seastar::compat::source_location sl = seastar::compat::source_location::current());
inline std::string getenv_safe(std::string_view name) {
auto v = ::getenv(name.data());
if (!v) {
throw std::logic_error(fmt::format("Environment variable {} not set", name));
}
return std::string(v);
}
extern boost::test_tools::assertion_result has_scylla_test_env(boost::unit_test::test_unit_id);
future<bool> compare_files(std::string fa, std::string fb);
future<> touch_file(std::string name);
extern std::mutex boost_logger_mutex;
#define THREADSAFE_BOOST_CHECK( BOOST_CHECK_EXPR ) { \
std::lock_guard<std::mutex> guard(tests::boost_logger_mutex); \
BOOST_CHECK_EXPR; \
}
// Thread-safe variants of BOOST macros for unit tests
// This is required to address lack of synchronization in boost test logger, which is susceptible to races
// in multi-threaded tests. Boost's XML printer (see boost/test/utils/xml_printer.hpp) can generate
// unreadable XML files, and therefore cause failure when parsing its content.
#define THREADSAFE_BOOST_REQUIRE( P ) THREADSAFE_BOOST_CHECK(BOOST_REQUIRE( P ))
#define THREADSAFE_BOOST_REQUIRE_EQUAL( L, R ) THREADSAFE_BOOST_CHECK(BOOST_REQUIRE_EQUAL( L, R ))
}
namespace std {
template <typename T>
requires fmt::is_formattable<T>::value
std::ostream& boost_test_print_type(std::ostream& os, const T& p) {
fmt::print(os, "{}", p);
return os;
}
}