/* * Copyright (C) 2020-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #pragma once #include #include #include #include #include #include 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 replica { class table; } namespace tests { namespace fs = std::filesystem; [[nodiscard]] bool do_check(bool condition, std::source_location sl, std::string_view msg); [[nodiscard]] inline bool check(bool condition, std::source_location sl = std::source_location::current()) { return do_check(condition, sl, {}); } template [[nodiscard]] bool check_equal(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { const auto condition = (lhs == rhs); return do_check(condition, sl, fmt::format("{} {}= {}", lhs, condition ? "=" : "!", rhs)); } void do_require(bool condition, std::source_location sl, std::string_view msg); inline void require(bool condition, std::source_location sl = std::source_location::current()) { do_require(condition, sl, {}); } template void do_require_relation( const LHS& lhs, const RHS& rhs, const Compare& relation, const char* relation_operator, std::source_location sl) { const auto condition = relation(lhs, rhs); do_require(condition, sl, fmt::format("assertion {} {} {} failed", lhs, relation_operator, rhs)); } template void require_less(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { do_require_relation(lhs, rhs, std::less{}, "<", sl); } template void require_less_equal(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { do_require_relation(lhs, rhs, std::less_equal{}, "<=", sl); } template void require_equal(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { do_require_relation(lhs, rhs, std::equal_to{}, "==", sl); } template void require_not_equal(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { do_require_relation(lhs, rhs, std::not_equal_to{}, "!=", sl); } template void require_greater_equal(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { do_require_relation(lhs, rhs, std::greater_equal{}, ">=", sl); } template void require_greater(const LHS& lhs, const RHS& rhs, std::source_location sl = std::source_location::current()) { do_require_relation(lhs, rhs, std::greater{}, ">", sl); } void fail(std::string_view msg, std::source_location sl = std::source_location::current()); std::string getenv_safe(std::string_view name); std::string getenv_or_default(std::string_view name, std::string_view def = {}); std::string getenv_or_default(std::span name_alts, std::string_view def = {}); std::string getenv_or_default(std::initializer_list name_alts, std::string_view def = {}); class tmp_set_env { std::string _var, _old; bool _was_set; public: tmp_set_env(std::string_view var, std::string_view value); tmp_set_env(tmp_set_env&&); tmp_set_env(const tmp_set_env&) = delete; ~tmp_set_env(); }; bool check_run_test(std::string_view var, bool defval = false); inline auto check_run_test_decorator(std::string_view test_var, bool def = false) { return boost::unit_test::precondition(std::bind(&check_run_test, std::string(test_var), def)); } extern boost::test_tools::assertion_result has_scylla_test_env(boost::unit_test::test_unit_id); void adjust_rlimit(); future compare_files(std::string fa, std::string fb); future<> touch_file(std::string name); // Helper to get directory a table keeps its data in. // Only suitable for tests, that work with local storage type. fs::path table_dir(const replica::table& cf); // Recursively copy a directory from src_dir to dst_dir. void copy_directory(fs::path src_dir, fs::path dst_dir, fs::copy_options opts = fs::copy_options::overwrite_existing); extern std::mutex boost_logger_mutex; #define THREADSAFE_BOOST_CHECK( BOOST_CHECK_EXPR ) { \ std::lock_guard 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 internal { template concept has_left_shift = requires(Lhs& lhs, const Rhs& rhs) { { lhs << rhs } -> std::same_as; }; } namespace std { template requires (fmt::is_formattable::value && !::internal::has_left_shift) std::ostream& boost_test_print_type(std::ostream& os, const T& p) { fmt::print(os, "{}", p); return os; } }