blob: 3d2be811f0c12ed11fcf34f0916476c831558d3a [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LIB_FASYNC_TESTS_TEST_UTILS_H_
#define SRC_LIB_FASYNC_TESTS_TEST_UTILS_H_
#include <lib/fasync/future.h>
namespace fasync {
namespace testing {
class immediate_executor final : public executor {
public:
class abort_context : public context {
public:
abort_context(immediate_executor& executor) : executor_(executor) {}
immediate_executor& executor() const override { return executor_; }
suspended_task suspend_task() override {
__builtin_abort();
return suspended_task();
}
private:
immediate_executor& executor_;
};
immediate_executor() : context_(*this) {}
abort_context& context() { return context_; }
template <typename F, ::fasync::internal::requires_conditions<
is_future<F>, cpp17::negation<is_void_future<F>>> = true>
constexpr future_output_t<F> invoke(F&& future) {
future_poll_t<F> p = cpp20::invoke(future, context_);
LIB_FASYNC_UNLIKELY if (p.is_pending()) { __builtin_abort(); }
return std::move(p).output();
}
template <typename F, ::fasync::internal::requires_conditions<is_void_future<F>> = true>
constexpr void invoke(F&& future) {
future_poll_t<F> p = cpp20::invoke(future, context_);
LIB_FASYNC_UNLIKELY if (p.is_pending()) { __builtin_abort(); }
}
template <typename F, ::fasync::internal::requires_conditions<is_future<F>> = true>
constexpr future_poll_t<F> poll(F&& future) {
return cpp20::invoke(future, context_);
}
template <typename F, ::fasync::internal::requires_conditions<is_future<F>> = true>
constexpr void schedule(F&& future) {
invoke(std::forward<F>(future));
}
void schedule(pending_task&& task) override { schedule(std::move(task).take_future()); }
private:
abort_context context_;
};
class invoke_closure final : public ::fasync::internal::future_adaptor_closure<invoke_closure> {
public:
template <typename F, ::fasync::internal::requires_conditions<is_future<F>> = true>
LIB_FASYNC_NODISCARD constexpr auto operator()(F&& future) const {
return immediate_executor().invoke(std::forward<F>(future));
}
};
LIB_FASYNC_INLINE_CONSTANT constexpr invoke_closure invoke;
class poll_closure final : public ::fasync::internal::future_adaptor_closure<poll_closure> {
public:
template <typename F, ::fasync::internal::requires_conditions<is_future<F>> = true>
LIB_FASYNC_NODISCARD constexpr auto operator()(F&& future) const {
return immediate_executor().poll(std::forward<F>(future));
}
};
LIB_FASYNC_INLINE_CONSTANT constexpr poll_closure poll;
} // namespace testing
} // namespace fasync
#endif // SRC_LIB_FASYNC_TESTS_TEST_UTILS_H_