-
Notifications
You must be signed in to change notification settings - Fork 6
/
test_expected.cpp
105 lines (89 loc) · 2.48 KB
/
test_expected.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <experimental/expected.hpp>
#include "monad_promise.h"
#include "catch.hpp"
// This makes expected<T, E> useable as a coroutine return type.
namespace std::experimental {
template <typename T, typename E, typename... Args>
struct coroutine_traits<expected<T, E>, Args...> {
using promise_type = monad_promise<expected<T, E>>;
};
} // namespace std::experimental
using std::experimental::expected;
using std::experimental::make_unexpected;
struct error {
int code;
};
expected<int, error> f1() noexcept { return 7; }
expected<double, error> f2(int x) noexcept { return 2.0 * x; }
expected<int, error> f3(int x, double y) noexcept {
return /*int(x + y)*/ make_unexpected(error{42});
}
expected<int, error> test_expected_manual() {
auto x = f1();
if (!x) return make_unexpected(x.error());
auto y = f2(*x);
if (!y) return make_unexpected(y.error());
auto z = f3(*x, *y);
return z;
}
template <typename T>
auto pair_with(T&& x) {
return [x](auto&& y) {
return std::make_pair(std::move(x), std::forward<decltype(y)>(y));
};
}
expected<int, error> test_expected_then() {
// clang-format off
auto z =
f1()
.bind([](int x) { return f2(x).map(pair_with(x)); })
.bind([](auto p) { auto[x, y] = p; return f3(x, y); });
// clang-format on
return z;
}
auto test_expected_coroutine() {
return []() -> expected<int, error> {
auto x = co_await f1();
auto y = co_await f2(x);
auto z = co_await f3(x, y);
co_return z;
}();
}
TEST_CASE("manual") {
auto r = test_expected_manual();
REQUIRE(!r.valid());
REQUIRE(r.error().code == 42);
}
TEST_CASE("then") {
auto r = test_expected_then();
REQUIRE(!r.valid());
REQUIRE(r.error().code == 42);
}
TEST_CASE("expected") {
auto r = test_expected_coroutine();
REQUIRE(!r.valid());
REQUIRE(r.error().code == 42);
}
TEST_CASE("return") {
auto r = []() -> expected<int, error> { co_return 7; }();
REQUIRE(r.valid());
REQUIRE(r.value() == 7);
}
TEST_CASE("await good") {
auto r = []() -> expected<int, error> {
auto x = co_await expected<int, error>(7);
REQUIRE(x == 7);
co_return x;
}();
REQUIRE(r.valid());
REQUIRE(r.value() == 7);
}
TEST_CASE("await error") {
auto r = []() -> expected<int, error> {
auto x = co_await expected<int, error>(make_unexpected(error{42}));
FAIL();
co_return x;
}();
REQUIRE(!r.valid());
REQUIRE(r.error().code == 42);
}