diff --git a/README.md b/README.md
index 077c5e91..a1bc4328 100644
--- a/README.md
+++ b/README.md
@@ -350,6 +350,24 @@ tests: 0 | 0 failed
asserts: 1 | 0 passed | 1 failed
```
+> That's nice, can I use custom messages and fatal assertions?
+> Yes, stream the `fatal`!
+
+```cpp
+expect(1 == 2_i) << "fatal assertion" << fatal;
+expect(1_i == 2);
+```
+
+```
+FAILED
+in: main.cpp:6 - test condition: [1 == 2]
+
+ fatal assertion
+===============================================================================
+tests: 0 | 2 failed
+asserts: 0 | 0 passed | 2 failed
+```
+
> https://godbolt.org/z/v2PDuU
diff --git a/example/fatal.cpp b/example/fatal.cpp
index 173f2ad5..da135745 100644
--- a/example/fatal.cpp
+++ b/example/fatal.cpp
@@ -23,6 +23,15 @@ int main() {
expect(*o == 42_i);
};
+ "fatal logging"_test = [] {
+ using namespace boost::ut::operators;
+ using boost::ut::expect;
+
+ std::optional o{42};
+ expect(o.has_value()) << "fatal assertion" << fatal;
+ expect(*o == 42_i);
+ };
+
"fatal matcher"_test = [] {
using namespace boost::ut::operators;
using boost::ut::expect;
diff --git a/include/boost/ut.hpp b/include/boost/ut.hpp
index e6639284..6e385a8a 100644
--- a/include/boost/ut.hpp
+++ b/include/boost/ut.hpp
@@ -2358,6 +2358,13 @@ struct expect_ {
return *this;
}
+ auto& operator<<(detail::fatal) {
+ if (not value_) {
+ on(events::fatal_assertion{});
+ }
+ return *this;
+ }
+
[[nodiscard]] constexpr operator bool() const { return value_; }
bool value_{};
diff --git a/test/ut/ut.cpp b/test/ut/ut.cpp
index a5240b7a..20df2a9f 100644
--- a/test/ut/ut.cpp
+++ b/test/ut/ut.cpp
@@ -658,7 +658,7 @@ int main() {
}
{
- auto run = test_runner{};
+ test_runner run;
auto& reporter = run.reporter_;
run.run_ = true;
@@ -819,7 +819,7 @@ int main() {
{
std::size_t summary_count = 0;
{
- auto run = test_summary_runner{};
+ test_summary_runner run;
run.reporter_.count_summaries(summary_count);
test_assert(false == run.run({.report_errors = true}));
}
@@ -1293,6 +1293,24 @@ int main() {
test_assert(std::empty(test_cfg.log_calls));
}
+ {
+ test_cfg = fake_cfg{};
+
+ "fatal assertions logging"_test = [] {
+ expect(2 != 2_i) << "fatal" << fatal;
+ };
+
+ test_assert(1 == std::size(test_cfg.run_calls));
+ test_assert(1 == std::size(test_cfg.assertion_calls));
+ test_assert(not test_cfg.assertion_calls[0].result);
+ test_assert("2 != 2" == test_cfg.assertion_calls[0].expr);
+ test_assert(1 == test_cfg.fatal_assertion_calls);
+ test_assert(2 == std::size(test_cfg.log_calls));
+ test_assert(' ' == std::any_cast(test_cfg.log_calls[0]));
+ test_assert("fatal"sv ==
+ std::any_cast(test_cfg.log_calls[1]));
+ }
+
{
test_cfg = fake_cfg{};