The various require() and check() methods in test_utils.hh were introduced to replace BOOST_REQUIRE() and BOOST_CHECK() respectively in multi-shard concurrent tests, specifically those in tests/boost/multishard_mutation_query_test.cc. This was done literally, just replacing BOOST_REQUIRE() with require() and BOOST_CHECK() with check(). The problem is that check() is missing a feature BOOST_CHECK() had: while BOOST_CHECK() doesn't cause an immediate test failure, just logging an error if the condition fails, it remembers this failure and will fail the test in the end. check() did not have this feature and this caused potential errors to just be logged while the test could still pass fine, causing false-positive tests passes. This patch fixes this by returning a [[nodiscard]] bool from the check() methods. The caller can & these together over all calls to check() methods and manually fail the test in the end. We choose this method over a hidden global (like BOOST_CHECK() does) for simplicity sake.
73 lines
2.0 KiB
C++
73 lines
2.0 KiB
C++
/*
|
|
* Copyright (C) 2020-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
#include "test/lib/test_utils.hh"
|
|
|
|
#include <seastar/core/print.hh>
|
|
#include <seastar/util/backtrace.hh>
|
|
#include "test/lib/log.hh"
|
|
|
|
#include "seastarx.hh"
|
|
#include <random>
|
|
|
|
namespace tests {
|
|
|
|
namespace {
|
|
|
|
std::string format_msg(std::string_view test_function_name, bool ok, std::experimental::source_location sl, std::string_view msg) {
|
|
return fmt::format("{}(): {} @ {}() {}:{:d}{}{}", test_function_name, ok ? "OK" : "FAIL", sl.function_name(), sl.file_name(), sl.line(), msg.empty() ? "" : ": ", msg);
|
|
}
|
|
|
|
}
|
|
|
|
bool do_check(bool condition, std::experimental::source_location sl, std::string_view msg) {
|
|
if (condition) {
|
|
testlog.trace("{}", format_msg(__FUNCTION__, condition, sl, msg));
|
|
} else {
|
|
testlog.error("{}", format_msg(__FUNCTION__, condition, sl, msg));
|
|
}
|
|
return condition;
|
|
}
|
|
|
|
void do_require(bool condition, std::experimental::source_location sl, std::string_view msg) {
|
|
if (condition) {
|
|
testlog.trace("{}", format_msg(__FUNCTION__, condition, sl, msg));
|
|
} else {
|
|
auto formatted_msg = format_msg(__FUNCTION__, condition, sl, msg);
|
|
testlog.error("{}", formatted_msg);
|
|
throw_with_backtrace<std::runtime_error>(std::move(formatted_msg));
|
|
}
|
|
|
|
}
|
|
|
|
void fail(std::string_view msg, std::experimental::source_location sl) {
|
|
throw_with_backtrace<std::runtime_error>(format_msg(__FUNCTION__, false, sl, msg));
|
|
}
|
|
|
|
}
|
|
|
|
sstring make_random_string(size_t size) {
|
|
static thread_local std::default_random_engine rng;
|
|
std::uniform_int_distribution<char> dist;
|
|
sstring str = uninitialized_string(size);
|
|
for (auto&& b : str) {
|
|
b = dist(rng);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
sstring make_random_numeric_string(size_t size) {
|
|
static thread_local std::default_random_engine rng;
|
|
std::uniform_int_distribution<char> dist('0', '9');
|
|
sstring str = uninitialized_string(size);
|
|
for (auto&& b : str) {
|
|
b = dist(rng);
|
|
}
|
|
return str;
|
|
}
|