utils: add timeout error injection with lambda

Even though calling then() on a ready future does not allocate a
continuation, calling then on the result of it will allocate.

This error injection only adds a continuation in the dependency
chain if error injections are enabled at compile timeand this particular
error injection is enabled.

Signed-off-by: Alejo Sanchez <alejo.sanchez@scylladb.com>
This commit is contained in:
Alejo Sanchez
2020-05-07 12:43:01 +02:00
parent 0321172677
commit a8b14b0227
2 changed files with 44 additions and 0 deletions

View File

@@ -134,6 +134,22 @@ SEASTAR_TEST_CASE(test_inject_sleep_deadline_manual_clock) {
});
}
SEASTAR_TEST_CASE(test_inject_sleep_deadline_manual_clock_lambda) {
return do_with_cql_env_thread([] (cql_test_env& e) {
utils::error_injection<true> errinj;
// Inject sleep, deadline short-circuit
auto deadline = seastar::manual_clock::now() + sleep_msec;
errinj.enable("future_deadline");
auto f = errinj.inject("future_deadline", deadline, [deadline] {
BOOST_REQUIRE_GE(std::chrono::duration_cast<std::chrono::milliseconds>(seastar::manual_clock::now() - deadline).count(), 0);
return make_ready_future<>();
});
manual_clock::advance(sleep_msec);
f.get();
});
}
SEASTAR_TEST_CASE(test_inject_sleep_deadline_db_clock) {
return do_with_cql_env_thread([] (cql_test_env& e) {
utils::error_injection<true> errinj;

View File

@@ -224,6 +224,25 @@ public:
return seastar::sleep<Clock>(duration);
}
// \brief Inject a sleep to deadline with lambda(timeout)
// Avoid adding a sleep continuation in the chain for disabled error injection
template <typename Clock, typename Duration, typename Func>
[[gnu::always_inline]]
std::result_of_t<Func()> inject(const std::string_view& name, std::chrono::time_point<Clock, Duration> deadline,
Func&& func) {
if (is_enabled(name)) {
if (is_one_shot(name)) {
disable(name);
}
std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(deadline - Clock::now());
errinj_logger.debug("Triggering sleep injection \"{}\" ({}ms)", name, duration.count());
return seastar::sleep<Clock>(duration).then([func = std::move(func)] {
return func(); });
} else {
return func();
}
}
// \brief Inject exception
// \param exception_factory function returning an exception pointer
template <typename Func>
@@ -316,6 +335,15 @@ public:
return make_ready_future<>();
}
// \brief Inject a sleep to deadline (timeout) with lambda
// Avoid adding a continuation in the chain for disabled error injections
template <typename Clock, typename Duration, typename Func>
[[gnu::always_inline]]
std::result_of_t<Func()> inject(const std::string_view& name, std::chrono::time_point<Clock, Duration> deadline,
Func&& func) {
return func();
}
// Inject exception
template <typename Func>
[[gnu::always_inline]]