blob: b0874a2badff175603e1bb4570936d6d5f6895f3 [file] [edit]
// include/test/execution.hpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef INCLUDED_TEST_EXECUTION
#define INCLUDED_TEST_EXECUTION
#include <beman/execution/detail/common.hpp>
#undef NDEBUG
#include <cassert>
#include <csignal>
#include <version>
#ifndef _MSC_VER
#include <unistd.h>
#include <sys/wait.h>
#endif
#ifdef BEMAN_HAS_IMPORT_STD
import std;
#else
#include <concepts>
#include <cstddef>
#ifndef _MSC_VER
#include <iostream>
#endif
#include <source_location>
#endif
#define ASSERT(condition) assert(condition)
#define ASSERT_UNREACHABLE() assert(::test::unreachable_helper())
#define TEST(name) auto main() -> int
namespace beman::execution::detail {}
namespace test_std = ::beman::execution;
namespace test_detail = ::beman::execution::detail;
namespace test {
#if 201907L <= __cpp_lib_source_location
using source_location = ::std::source_location;
#else
struct source_location {
static auto current() -> source_location { return {}; }
auto file_name() const -> const char* { return "<unknown:no std::source_location>"; }
auto line() const -> const char* { return "<unknown:no std::source_location>"; }
};
#endif
inline bool unreachable_helper() { return false; }
template <typename>
auto type_exists() {}
template <typename T0, typename T1>
auto check_type(T1&&) {
static_assert(std::same_as<T0, T1>);
}
auto use(auto&&...) noexcept -> void {}
template <typename>
auto use_type() noexcept -> void {}
template <template <typename...> class>
auto use_template() noexcept -> void {}
struct throws {
throws() = default;
throws(throws&&) noexcept(false) = default;
throws(const throws&) noexcept(false) = default;
~throws() = default;
auto operator=(throws&&) noexcept(false) -> throws& = default;
auto operator=(const throws&) noexcept(false) -> throws& = default;
};
inline auto death([[maybe_unused]] auto fun,
[[maybe_unused]] ::std::source_location location = test::source_location::current()) noexcept
-> void {
#ifndef _MSC_VER
switch (::pid_t rc = ::fork()) {
default: {
int stat{};
ASSERT(rc == ::wait(&stat));
if (stat == 0) {
::std::cerr << "failed death test at " << "file=" << location.file_name() << ":" << location.line() << "\n"
<< std::flush;
ASSERT(stat != 0);
}
} break;
case 0: {
::close(2);
fun();
::std::exit(0);
} break;
}
#endif
}
} // namespace test
#endif // INCLUDED_TEST_EXECUTION