light/modules/test/expects.cppm

203 lines
3.9 KiB
Text
Raw Normal View History

export module test.expects;
2026-01-20 09:58:35 +03:30
import preliminary;
namespace lt::test {
template<typename T>
concept Formattable = requires(T &v, std::format_context ctx) {
std::formatter<std::remove_cvref_t<T>>().format(v, ctx);
};
template<typename T>
concept Printable = Formattable<T> || requires(std::ostream &stream, T value) {
{ stream << std::to_underlying<T>(value) } -> std::same_as<std::ostream &>;
};
template<typename T>
concept Testable = Printable<T> && std::equality_comparable<T>;
export void expect_unreachable(
std::source_location source_location = std::source_location::current()
)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"unreachable reached: {}:{}",
source_location.file_name(),
source_location.line()
),
};
};
2026-01-09 21:53:37 +03:30
/** @todo(Light7734): Check exception type. */
export constexpr void expect_throw(
std::invocable auto invocable,
std::source_location source_location = std::source_location::current()
)
{
try
{
invocable();
}
2026-01-09 21:53:37 +03:30
catch (const std::exception &)
{
return;
}
throw std::runtime_error {
2026-02-02 13:56:25 +03:30
std::format("did not throw: {}:{}", source_location.file_name(), source_location.line()),
};
}
export constexpr void expect_eq(
Testable auto lhs,
Testable auto rhs,
std::source_location source_location = std::source_location::current()
)
{
if constexpr (std::is_enum_v<decltype(lhs)>)
{
if (lhs != rhs)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_eq: {} == {} @ {}:{}",
std::to_underlying<decltype(lhs)>(lhs),
std::to_underlying<decltype(rhs)>(rhs),
source_location.file_name(),
source_location.line()
),
};
}
}
else if (lhs != rhs)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_eq: {} == {} @ {}:{}",
lhs,
rhs,
source_location.file_name(),
source_location.line()
),
};
}
}
export constexpr void expect_ne(
Testable auto lhs,
Testable auto rhs,
std::source_location source_location = std::source_location::current()
)
{
if (lhs == rhs)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_ne: {} != {} @ {}:{}",
lhs,
rhs,
source_location.file_name(),
source_location.line()
),
};
}
}
2026-02-02 13:56:25 +03:30
export constexpr void expect_le(
Testable auto lhs,
Testable auto rhs,
std::source_location source_location = std::source_location::current()
)
{
2026-02-02 13:56:25 +03:30
if (lhs > rhs)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_le: {} <= {} @ {}:{}",
lhs,
rhs,
source_location.file_name(),
source_location.line()
),
};
}
}
2026-02-02 13:56:25 +03:30
export constexpr void expect_ge(
Testable auto lhs,
Testable auto rhs,
std::source_location source_location = std::source_location::current()
)
{
if (lhs < rhs)
{
throw std::runtime_error {
std::format(
"expect_ge: {} >= {} @ {}:{}",
lhs,
rhs,
source_location.file_name(),
source_location.line()
),
};
}
}
export constexpr void expect_true(
bool expression,
std::source_location source_location = std::source_location::current()
)
{
2026-02-02 13:56:25 +03:30
if (!expression)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_true: {} @ {}:{}",
expression,
source_location.file_name(),
source_location.line()
),
};
}
}
2026-02-02 13:56:25 +03:30
export constexpr void expect_false(
bool expression,
std::source_location source_location = std::source_location::current()
)
{
2026-02-02 13:56:25 +03:30
if (expression)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_false: {} @ {}:{}",
expression,
source_location.file_name(),
source_location.line()
),
};
}
}
2026-02-02 13:56:25 +03:30
export constexpr void expect_not_nullptr(
auto *pointer,
std::source_location source_location = std::source_location::current()
)
{
2026-02-02 13:56:25 +03:30
if (pointer == nullptr)
{
throw std::runtime_error {
std::format(
2026-02-02 13:56:25 +03:30
"expect_not_nullptr: @ {}:{}",
source_location.file_name(),
source_location.line()
),
};
}
}
} // namespace lt::test