Skip to content

Commit

Permalink
🆕 💥 🎨 [UT] Fatal assertions with expressions
Browse files Browse the repository at this point in the history
Problem:
- fatal assertions are only allowed with `expect` via `!expect` but not for expressions.
- `expect` is considered an operator but it's not really.
- `tags` are using `>>` operator which now colides with `>> fatal`.

Solution:
- Introduce `>> fatal` for expressions.
- Remove operator requirements from `expect`.
- Remove `!expect` syntax.
- Change `tags` to use `/` instead.
  • Loading branch information
kris-jusiak authored and krzysztof-jusiak committed Jul 29, 2020
1 parent 40a4840 commit ce21fa3
Show file tree
Hide file tree
Showing 12 changed files with 2,130 additions and 2,051 deletions.
65 changes: 36 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ asserts: 4 | 0 passed | 4 failed
> Nothing easier, let's just add `!` before the `expect` call to make it fatal.
```cpp
!expect(1 == 2_i); // fatal assertion
expect(1_i == 2); // not executed
expect((1 == 2_i) >> fatal); // fatal assertion
expect(1_i == 2); // not executed
```

```
Expand Down Expand Up @@ -378,14 +378,14 @@ int main() {
"[vector]"_test = [] {
std::vector<int> v(5);

!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

should("resize bigger") = [v] { // or "resize bigger"_test
mut(v).resize(10);
expect(10_ul == std::size(v));
};

!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

should("resize smaller") = [=]() mutable { // or "resize smaller"_test
v.resize(0);
Expand All @@ -410,7 +410,7 @@ int main() {
"vector"_test = [] {
given("I have a vector") = [] {
std::vector<int> v(5);
!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

when("I resize bigger") = [=] {
mut(v).resize(10);
Expand Down Expand Up @@ -438,7 +438,7 @@ int main() {
scenario("size") = [] {
given("I have a vector") = [] {
std::vector<int> v(5);
!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

when("I resize bigger") = [=] {
mut(v).resize(10);
Expand Down Expand Up @@ -469,7 +469,7 @@ int main() {
steps.scenario("*") = [&] {
steps.given("I have a vector") = [&] {
std::vector<int> v(5);
!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

steps.when("I resize bigger") = [&] { v.resize(10); };
steps.then("The size should increase") = [&] { expect(10_ul == std::size(v)); };
Expand Down Expand Up @@ -501,7 +501,7 @@ All tests passed (2 asserts in 1 tests)
int main() {
describe("vector") = [] {
std::vector<int> v(5);
!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

it("should resize bigger") = [v] {
mut(v).resize(10);
Expand Down Expand Up @@ -641,7 +641,7 @@ expect(constant<42_i == compile_time_v> and run_time_v == 99_i);
// fatal
std::vector v{1, 2, 3};
!expect(std::size(v) == 3_ul) << "fatal assertion";
expect((std::size(v) == 3_ul) >> fatal) << "fatal assertion";
expect(v[0] == 1_i);
expect(v[1] == 2_i);
expect(v[2] == 3_i);
Expand Down Expand Up @@ -675,7 +675,7 @@ asserts: 24 | 22 passed | 2 failed
expect(42_i == 42);
};

skip >> "don't run UDL"_test = [] {
skip / "don't run UDL"_test = [] {
expect(42_i == 43) << "should not fire!";
};
```
Expand All @@ -690,7 +690,7 @@ test("run function") = [] {
expect(42_i == 42);
};

skip >> test("don't run function") = [] {
skip / test("don't run function") = [] {
expect(42_i == 43) << "should not fire!";
};
```
Expand All @@ -701,12 +701,12 @@ All tests passed (1 asserts in 1 tests)
```
```cpp
tag("nightly") >> tag("slow") >>
tag("nightly") / tag("slow") /
"performance"_test= [] {
expect(42_i == 42);
};
tag("slow") >>
tag("slow") /
"run slowly"_test= [] {
expect(42_i == 43) << "should not fire!";
};
Expand All @@ -733,14 +733,14 @@ All tests passed (1 asserts in 1 tests)
"[vector]"_test = [] {
std::vector<int> v(5);

!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

should("resize bigger") = [=] { // or "resize bigger"_test
mut(v).resize(10);
expect(10_ul == std::size(v));
};

!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

should("resize smaller") = [=]() mutable { // or "resize smaller"_test
v.resize(0);
Expand Down Expand Up @@ -863,9 +863,9 @@ for (auto i : std::vector{1, 2, 3}) {

"args and types"_test =
[]<class TArg>(TArg arg) {
!expect(std::is_integral_v<TArg>);
expect(42_i == arg or true_b == arg);
expect(type<TArg> == type<int> or type<TArg> == type<bool>);
expect(std::is_integral_v<TArg> >> fatal);
expect(42_i == arg or true_b == arg);
expect(type<TArg> == type<int> or type<TArg> == type<bool>);
}
| std::tuple{true, 42};
```
Expand Down Expand Up @@ -1204,10 +1204,11 @@ namespace boost::inline ext::ut::inline v1_1_7 {
constexpr auto _ld(long double);
/**
* Logical representation of constant values
* Logical representation of constant boolean (true) value
* @example "is set"_b : true
* not "is set"_b : false
*/
constexpr auto true_b; /// true
constexpr auto false_b; /// false
constexpr auto operator ""_b;
} // namespace literals
inline namespace operators {
Expand Down Expand Up @@ -1249,14 +1250,20 @@ namespace boost::inline ext::ut::inline v1_1_7 {
/**
* Creates tags
* @example tag("slow") >> tag("nightly") >> "perf"_test = []{};
* @example tag("slow") / tag("nightly") / "perf"_test = []{};
*/
constexpr auto operator/;
/**
* Creates a `fatal_assertion` from an expression
* @example (42_i == 0) >> fatal
*/
constexpr auto operator>>;
} // namespace operators
/**
* Creates skippable test object
* @example skip >> "don't run"_test = [] { };
* @example skip / "don't run"_test = [] { };
*/
constexpr auto skip = tag("skip");
Expand Down Expand Up @@ -1315,7 +1322,7 @@ namespace boost::inline ext::ut::inline v1_1_7 {
auto on(ut::events::test<Ts...>);
/**
* @example skip | "don't run"_test = []{};
* @example skip / "don't run"_test = []{};
* @param skip.type ["test", "given", "when", "then"]
* @param skip.name "don't run"
* @param skip.arg parameterized argument
Expand All @@ -1333,8 +1340,8 @@ namespace boost::inline ext::ut::inline v1_1_7 {
auto on(ut::events::assertion<TExpr>) -> bool;
/**
* @example !expect(2_i == 1)
* @note triggered by `!expect`
* @example expect((2_i == 1) >> fatal)
* @note triggered by `fatal`
* should std::exit
*/
auto on(ut::events::fatal_assertion);
Expand Down Expand Up @@ -1418,8 +1425,8 @@ namespace boost::inline ext::ut::inline v1_1_7 {
auto on(ut::events::assertion_fail<TExpr>) -> void;
/**
* @example !expect(2_i == 1)
* @note triggered by `!expect`
* @example expect((2_i == 1) >> fatal)
* @note triggered by `fatal`
* should std::exit
*/
auto on(ut::events::fatal_assertion) -> void;
Expand Down Expand Up @@ -1786,7 +1793,7 @@ int main() {
TEST("vector") {
std::vector<int> v(5);

!EXPECT(5u == std::size(v)) << "fatal";
EXPECT((5u == std::size(v)) >> fatal) << "fatal";

TEST("resize bigger") {
v.resize(10);
Expand Down
12 changes: 2 additions & 10 deletions example/expect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@ int main() {
expect(42.10000001 == 42.1_d) << "epsilon=0.1";
};

"fatal"_test = [] {
std::vector v{1, 2, 3};
!expect(std::size(v) == 3_ul) << "fatal assertion";
expect(v[0] == 1_i);
expect(v[1] == 2_i);
expect(v[2] == 3_i);
};

"strings"_test = [] {
using namespace std::literals::string_view_literals;
using namespace std::literals::string_literals;
Expand Down Expand Up @@ -105,7 +97,7 @@ int main() {

"boolean"_test = [] {
expect("true"_b);
expect("true"_b and not false_b);
expect(not"true"_b == false_b);
expect("true"_b or not"true"_b);
expect(not"true"_b != "true"_b);
};
}
40 changes: 30 additions & 10 deletions example/fatal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,45 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/ut.hpp>

auto* ptr() {
static auto i = 42; /// Change i to 0 for fatal assertions
return &i;
}
#include <optional>
#include <vector>

int main() {
using boost::ut::operator""_test;
using boost::ut::expect;
using namespace boost::ut::literals;
using boost::ut::fatal;

static constexpr auto value = 42; // Change to std::nullopt

"fatal"_test = [] {
using namespace boost::ut;
!expect(ptr());
expect(*ptr() != 0_i);
using namespace boost::ut::operators;
using boost::ut::expect;

std::optional<int> o{42};
expect(o.has_value() >> fatal);
expect(*o == 42_i);
};

"fatal matcher"_test = [] {
using namespace boost::ut::operators;
using boost::ut::expect;
using boost::ut::that;

std::optional<int> o{42};
expect(that % o.has_value() >> fatal and that % *o == 42);
};

"fatal terse"_test = [] {
using namespace boost::ut::operators::terse;
!expect(ptr()) and *ptr() != 0_i;

std::optional<int> o{42};
o.has_value() >> fatal and*o == 42_i;
};

using namespace boost::ut::operators;
using boost::ut::expect;

std::vector v{1};
expect((std::size(v) == 1_ul) >> fatal) << "fatal assertion";
expect(v[0] == 1_i);
}
6 changes: 4 additions & 2 deletions example/macro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include <boost/ut.hpp>
#include <vector>

#define EXPECT(...) ::boost::ut::expect(::boost::ut::that % __VA_ARGS__)
#define EXPECT(...) \
using namespace ::boost::ut; \
::boost::ut::expect(::boost::ut::that % __VA_ARGS__)
#define SUITE ::boost::ut::suite _ = []
#define TEST(name) ::boost::ut::detail::test{"test", name} = [=]() mutable
#define TEST_P(name, ...) \
Expand All @@ -30,7 +32,7 @@ int main() {
TEST("vector") {
std::vector<int> v(5);

!EXPECT(5u == std::size(v));
EXPECT((5u == std::size(v)) >> fatal);

TEST("resize bigger") {
v.resize(10);
Expand Down
2 changes: 1 addition & 1 deletion example/mut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ int main() {
auto i = 0; // mutable

"mut"_test = [i] {
!expect(i == 0_i); // immutable
expect((i == 0_i) >> fatal); // immutable

should("++") = [i] {
expect(++mut(i) == 1_i); // mutable
Expand Down
4 changes: 2 additions & 2 deletions example/parameterized.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ int main() {
((test("args and types / " + std::to_string(args)) =
[&] {
using TArgs = decltype(args);
!expect(std::is_integral_v<TArgs>);
expect((std::is_integral_v<TArgs>) >> fatal);
expect(42_i == static_cast<int>(args) or args);
expect(type<TArgs> == type<int> or type<TArgs> == type<bool>);
}),
Expand All @@ -48,7 +48,7 @@ int main() {

/// Alternative syntax
"args and types"_test = []<class TArg>(TArg arg) {
!expect(std::is_integral_v<TArg>);
expect((std::is_integral_v<TArg>) >> fatal);
expect(42_i == static_cast<int>(arg) or arg);
expect(type<TArg> == type<int> or type<TArg> == type<bool>);
}
Expand Down
4 changes: 2 additions & 2 deletions example/section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ int main() {
"[vector]"_test = [] {
std::vector<int> v(5);

!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

should("resize bigger") = [v] { // or "resize bigger"_test
mut(v).resize(10);
expect(10_ul == std::size(v));
};

!expect(5_ul == std::size(v));
expect((5_ul == std::size(v)) >> fatal);

should("resize smaller") = [=]() mutable { // or "resize smaller"_test
v.resize(0);
Expand Down
2 changes: 1 addition & 1 deletion example/should.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int main() {
using namespace boost::ut;

auto i = 0;
!expect(i == 0_i);
expect((i == 0_i) >> fatal);

should("return increased number for ++") = [i] { expect(++mut(i) == 1_i); };
should("return decreased number for --") = [i]() mutable {
Expand Down
4 changes: 2 additions & 2 deletions example/skip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ int main() {
using namespace boost::ut;

// clang-format off
skip >>
skip /
"don't run"_test = [] {
expect(42_i == 43) << "should not fire!";
expect(false) << "should fail!";
};

skip >> test("don't run") = [] {
skip / test("don't run") = [] {
expect(42_i == 43) << "should not fire!";
expect(false) << "should fail!";
};
Expand Down

0 comments on commit ce21fa3

Please sign in to comment.