1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <functional>
6
7 #include <lib/fit/promise.h>
8 #include <lib/fit/single_threaded_executor.h>
9 #include <unittest/unittest.h>
10
11 #include "examples/utils.h"
12 #include "unittest_utils.h"
13
14 namespace {
15
16 class fake_context : public fit::context {
17 public:
executor() const18 fit::executor* executor() const override {
19 ASSERT_CRITICAL(false);
20 }
suspend_task()21 fit::suspended_task suspend_task() override {
22 ASSERT_CRITICAL(false);
23 }
24 };
25
26 template <typename V = void, typename E = void>
27 class capture_result_wrapper {
28 public:
29 template <typename Promise>
wrap(Promise promise)30 decltype(auto) wrap(Promise promise) {
31 static_assert(std::is_same<V, typename Promise::value_type>::value, "");
32 static_assert(std::is_same<E, typename Promise::error_type>::value, "");
33 ASSERT_CRITICAL(promise);
34 return promise.then([this](fit::result<V, E>& result) {
35 last_result = std::move(result);
36 });
37 }
38
39 fit::result<V, E> last_result;
40 };
41
42 struct move_only {
43 move_only(const move_only&) = delete;
44 move_only(move_only&&) = default;
45 move_only& operator=(const move_only&) = delete;
46 move_only& operator=(move_only&&) = default;
47 };
48
49 // Just a simple test to put the promise through its paces.
50 // Other tests go into more detail to cover the API surface.
basics()51 bool basics() {
52 BEGIN_TEST;
53
54 for (int i = 0; i < 5; i++) {
55 // Make a promise that calculates half the square of a number.
56 // Produces an error if the square is odd.
57 auto promise =
58 fit::make_promise([i] {
59 // Pretend that squaring numbers is hard and takes time
60 // to finish...
61 return utils::sleep_for_a_little_while()
62 .then([i](fit::result<>) {
63 return fit::ok(i * i);
64 });
65 }).then([](fit::result<int> square) -> fit::result<int, const char*> {
66 if (square.value() % 2 == 0)
67 return fit::ok(square.value() / 2);
68 return fit::error("square is odd");
69 });
70
71 // Evaluate the promise.
72 fit::result<int, const char*> result =
73 fit::run_single_threaded(std::move(promise));
74 if (i % 2 == 0) {
75 EXPECT_TRUE(result.is_ok());
76 EXPECT_EQ(i * i / 2, result.value());
77 } else {
78 EXPECT_TRUE(result.is_error());
79 EXPECT_STR_EQ("square is odd", result.error());
80 }
81 }
82
83 END_TEST;
84 }
85
86 // An empty promise has no continuation.
87 // We can't do a lot with it but we can check for emptyness.
empty_promise()88 bool empty_promise() {
89 BEGIN_TEST;
90
91 {
92 fit::promise<> promise;
93 EXPECT_FALSE(promise);
94 }
95
96 {
97 fit::promise<> promise(nullptr);
98 EXPECT_FALSE(promise);
99 }
100
101 {
102 fit::function<fit::result<>(fit::context&)> f;
103 fit::promise<> promise(std::move(f));
104 EXPECT_FALSE(promise);
105 }
106
107 {
108 std::function<fit::result<>(fit::context&)> f;
109 fit::promise<> promise(std::move(f));
110 EXPECT_FALSE(promise);
111 }
112
113 END_TEST;
114 }
115
invocation()116 bool invocation() {
117 BEGIN_TEST;
118
119 uint64_t run_count = 0;
120 fake_context fake_context;
121 fit::promise<> promise([&](fit::context& context) -> fit::result<> {
122 ASSERT_CRITICAL(&context == &fake_context);
123 if (++run_count == 2)
124 return fit::ok();
125 return fit::pending();
126 });
127 EXPECT_TRUE(promise);
128
129 fit::result<> result = promise(fake_context);
130 EXPECT_EQ(1, run_count);
131 EXPECT_EQ(fit::result_state::pending, result.state());
132 EXPECT_TRUE(promise);
133
134 result = promise(fake_context);
135 EXPECT_EQ(2, run_count);
136 EXPECT_EQ(fit::result_state::ok, result.state());
137 EXPECT_FALSE(promise);
138
139 END_TEST;
140 }
141
take_continuation()142 bool take_continuation() {
143 BEGIN_TEST;
144
145 uint64_t run_count = 0;
146 fake_context fake_context;
147 fit::promise<> promise([&](fit::context& context) -> fit::result<> {
148 ASSERT_CRITICAL(&context == &fake_context);
149 run_count++;
150 return fit::pending();
151 });
152 EXPECT_TRUE(promise);
153
154 fit::function<fit::result<>(fit::context&)> f = promise.take_continuation();
155 EXPECT_FALSE(promise);
156 EXPECT_EQ(0, run_count);
157
158 fit::result<> result = f(fake_context);
159 EXPECT_EQ(1, run_count);
160 EXPECT_EQ(fit::result_state::pending, result.state());
161
162 END_TEST;
163 }
164
assignment_and_swap()165 bool assignment_and_swap() {
166 BEGIN_TEST;
167
168 fake_context fake_context;
169
170 fit::promise<> empty;
171 EXPECT_FALSE(empty);
172
173 uint64_t run_count = 0;
174 fit::promise<> promise([&](fit::context& context) -> fit::result<> {
175 run_count++;
176 return fit::pending();
177 });
178 EXPECT_TRUE(promise);
179
180 fit::promise<> x(std::move(empty));
181 EXPECT_FALSE(x);
182
183 fit::promise<> y(std::move(promise));
184 EXPECT_TRUE(y);
185 y(fake_context);
186 EXPECT_EQ(1, run_count);
187
188 x.swap(y);
189 EXPECT_TRUE(x);
190 EXPECT_FALSE(y);
191 x(fake_context);
192 EXPECT_EQ(2, run_count);
193
194 x.swap(x);
195 EXPECT_TRUE(x);
196 x(fake_context);
197 EXPECT_EQ(3, run_count);
198
199 y.swap(y);
200 EXPECT_FALSE(y);
201
202 x = nullptr;
203 EXPECT_FALSE(x);
204
205 y = [&](fit::context& context) -> fit::result<> {
206 run_count *= 2;
207 return fit::pending();
208 };
209 EXPECT_TRUE(y);
210 y(fake_context);
211 EXPECT_EQ(6, run_count);
212
213 x = std::move(y);
214 EXPECT_TRUE(x);
215 EXPECT_FALSE(y);
216 x(fake_context);
217 EXPECT_EQ(12, run_count);
218
219 x = std::move(y);
220 EXPECT_FALSE(x);
221
222 END_TEST;
223 }
224
comparison_with_nullptr()225 bool comparison_with_nullptr() {
226 BEGIN_TEST;
227
228 {
229 fit::promise<> promise;
230 EXPECT_TRUE(promise == nullptr);
231 EXPECT_TRUE(nullptr == promise);
232 EXPECT_FALSE(promise != nullptr);
233 EXPECT_FALSE(nullptr != promise);
234 }
235
236 {
237 fit::promise<> promise([&](fit::context& context) -> fit::result<> {
238 return fit::pending();
239 });
240 EXPECT_FALSE(promise == nullptr);
241 EXPECT_FALSE(nullptr == promise);
242 EXPECT_TRUE(promise != nullptr);
243 EXPECT_TRUE(nullptr != promise);
244 }
245
246 END_TEST;
247 }
248
make_promise()249 bool make_promise() {
250 BEGIN_TEST;
251
252 fake_context fake_context;
253
254 // Handler signature: void().
255 {
256 uint64_t run_count = 0;
257 auto p = fit::make_promise([&] {
258 run_count++;
259 });
260 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
261 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
262 fit::result<> result = p(fake_context);
263 EXPECT_EQ(1, run_count);
264 EXPECT_EQ(fit::result_state::ok, result.state());
265 EXPECT_FALSE(p);
266 }
267
268 // Handler signature: fit::result<int, char>().
269 {
270 uint64_t run_count = 0;
271 auto p = fit::make_promise([&]() -> fit::result<int, char> {
272 run_count++;
273 return fit::ok(42);
274 });
275 static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
276 static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
277 fit::result<int, char> result = p(fake_context);
278 EXPECT_EQ(1, run_count);
279 EXPECT_EQ(fit::result_state::ok, result.state());
280 EXPECT_EQ(42, result.value());
281 EXPECT_FALSE(p);
282 }
283
284 // Handler signature: fit::ok<int>().
285 {
286 uint64_t run_count = 0;
287 auto p = fit::make_promise([&] {
288 run_count++;
289 return fit::ok(42);
290 });
291 static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
292 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
293 fit::result<int, void> result = p(fake_context);
294 EXPECT_EQ(1, run_count);
295 EXPECT_EQ(fit::result_state::ok, result.state());
296 EXPECT_EQ(42, result.value());
297 EXPECT_FALSE(p);
298 }
299
300 // Handler signature: fit::error<int>().
301 {
302 uint64_t run_count = 0;
303 auto p = fit::make_promise([&] {
304 run_count++;
305 return fit::error(42);
306 });
307 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
308 static_assert(std::is_same<int, decltype(p)::error_type>::value, "");
309 fit::result<void, int> result = p(fake_context);
310 EXPECT_EQ(1, run_count);
311 EXPECT_EQ(fit::result_state::error, result.state());
312 EXPECT_EQ(42, result.error());
313 EXPECT_FALSE(p);
314 }
315
316 // Handler signature: fit::pending().
317 {
318 uint64_t run_count = 0;
319 auto p = fit::make_promise([&] {
320 run_count++;
321 return fit::pending();
322 });
323 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
324 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
325 fit::result<> result = p(fake_context);
326 EXPECT_EQ(1, run_count);
327 EXPECT_EQ(fit::result_state::pending, result.state());
328 EXPECT_TRUE(p);
329 }
330
331 // Handler signature: fit::promise_impl<...>.
332 {
333 uint64_t run_count = 0;
334 uint64_t run_count2 = 0;
335 auto p = fit::make_promise([&] {
336 run_count++;
337 return fit::make_promise([&]() -> fit::result<int, char> {
338 if (++run_count2 == 2)
339 return fit::ok(42);
340 return fit::pending();
341 });
342 });
343 static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
344 static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
345 fit::result<int, char> result = p(fake_context);
346 EXPECT_EQ(1, run_count);
347 EXPECT_EQ(1, run_count2);
348 EXPECT_EQ(fit::result_state::pending, result.state());
349 EXPECT_TRUE(p);
350 result = p(fake_context);
351 EXPECT_EQ(1, run_count);
352 EXPECT_EQ(2, run_count2);
353 EXPECT_EQ(fit::result_state::ok, result.state());
354 EXPECT_EQ(42, result.value());
355 EXPECT_FALSE(p);
356 }
357
358 // Handler signature: void(context&).
359 {
360 uint64_t run_count = 0;
361 auto p = fit::make_promise([&](fit::context& context) {
362 ASSERT_CRITICAL(&context == &fake_context);
363 run_count++;
364 });
365 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
366 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
367 fit::result<> result = p(fake_context);
368 EXPECT_EQ(1, run_count);
369 EXPECT_EQ(fit::result_state::ok, result.state());
370 EXPECT_FALSE(p);
371 }
372
373 END_TEST;
374 }
375
376 // This is a bit lower level than fit::make_promise() in that there's
377 // no automatic adaptation of the handler type.
make_promise_with_continuation()378 bool make_promise_with_continuation() {
379 BEGIN_TEST;
380
381 uint64_t run_count = 0;
382 fake_context fake_context;
383 auto p = fit::make_promise_with_continuation(
384 [&](fit::context& context) -> fit::result<int, char> {
385 ASSERT_CRITICAL(&context == &fake_context);
386 run_count++;
387 return fit::ok(42);
388 });
389 static_assert(std::is_same<int, decltype(p)::value_type>::value, "");
390 static_assert(std::is_same<char, decltype(p)::error_type>::value, "");
391 EXPECT_TRUE(p);
392
393 fit::result<int, char> result = p(fake_context);
394 EXPECT_EQ(1, run_count);
395 EXPECT_EQ(fit::result_state::ok, result.state());
396 EXPECT_EQ(42, result.value());
397 EXPECT_FALSE(p);
398
399 END_TEST;
400 }
401
make_ok_promise(int value)402 auto make_ok_promise(int value) {
403 return fit::make_promise([value, count = 0]() mutable -> fit::result<int, char> {
404 ASSERT_CRITICAL(count == 0);
405 ++count;
406 return fit::ok(value);
407 });
408 }
409
make_error_promise(char error)410 auto make_error_promise(char error) {
411 return fit::make_promise([error, count = 0]() mutable -> fit::result<int, char> {
412 ASSERT_CRITICAL(count == 0);
413 ++count;
414 return fit::error(error);
415 });
416 }
417
make_delayed_ok_promise(int value)418 auto make_delayed_ok_promise(int value) {
419 return fit::make_promise([value, count = 0]() mutable -> fit::result<int, char> {
420 ASSERT_CRITICAL(count <= 1);
421 if (++count == 2)
422 return fit::ok(value);
423 return fit::pending();
424 });
425 }
426
make_delayed_error_promise(char error)427 auto make_delayed_error_promise(char error) {
428 return fit::make_promise([error, count = 0]() mutable -> fit::result<int, char> {
429 ASSERT_CRITICAL(count <= 1);
430 if (++count == 2)
431 return fit::error(error);
432 return fit::pending();
433 });
434 }
435
436 // To keep these tests manageable, we only focus on argument type adaptation
437 // since return type adaptation logic is already covered by |make_promise()|
438 // and by the examples.
then_combinator()439 bool then_combinator() {
440 BEGIN_TEST;
441
442 fake_context fake_context;
443
444 // Chaining on OK.
445 // Handler signature: fit::result<>(fit::result<int, char>).
446 {
447 uint64_t run_count = 0;
448 auto p =
449 make_delayed_ok_promise(42)
450 .then([&](fit::result<int, char> result) -> fit::result<> {
451 ASSERT_CRITICAL(result.value() == 42);
452 if (++run_count == 2)
453 return fit::ok();
454 return fit::pending();
455 });
456
457 fit::result<> result = p(fake_context);
458 EXPECT_TRUE(p);
459 EXPECT_EQ(0, run_count);
460 EXPECT_EQ(fit::result_state::pending, result.state());
461
462 result = p(fake_context);
463 EXPECT_TRUE(p);
464 EXPECT_EQ(1, run_count);
465 EXPECT_EQ(fit::result_state::pending, result.state());
466
467 result = p(fake_context);
468 EXPECT_FALSE(p);
469 EXPECT_EQ(2, run_count);
470 EXPECT_EQ(fit::result_state::ok, result.state());
471 }
472
473 // Chaining on ERROR.
474 // Handler signature: fit::result<>(fit::result<int, char>).
475 {
476 uint64_t run_count = 0;
477 auto p =
478 make_delayed_error_promise('x')
479 .then([&](fit::result<int, char> result) -> fit::result<> {
480 ASSERT_CRITICAL(result.error() == 'x');
481 if (++run_count == 2)
482 return fit::ok();
483 return fit::pending();
484 });
485
486 fit::result<> result = p(fake_context);
487 EXPECT_TRUE(p);
488 EXPECT_EQ(0, run_count);
489 EXPECT_EQ(fit::result_state::pending, result.state());
490
491 result = p(fake_context);
492 EXPECT_TRUE(p);
493 EXPECT_EQ(1, run_count);
494 EXPECT_EQ(fit::result_state::pending, result.state());
495
496 result = p(fake_context);
497 EXPECT_FALSE(p);
498 EXPECT_EQ(2, run_count);
499 EXPECT_EQ(fit::result_state::ok, result.state());
500 }
501
502 // Cover all handler argument signatures, more briefly.
503 {
504 uint64_t run_count = 0;
505 auto p =
506 make_ok_promise(42)
507 .then([&](fit::result<int, char> result)
508 -> fit::result<int, char> {
509 run_count++;
510 return fit::ok(result.value() + 1);
511 })
512 .then([&](fit::result<int, char>& result)
513 -> fit::result<int, char> {
514 run_count++;
515 return fit::ok(result.value() + 1);
516 })
517 .then([&](const fit::result<int, char>& result)
518 -> fit::result<int, char> {
519 run_count++;
520 return fit::ok(result.value() + 1);
521 })
522 .then([&](fit::context& context, fit::result<int, char> result)
523 -> fit::result<int, char> {
524 ASSERT_CRITICAL(&context == &fake_context);
525 run_count++;
526 return fit::ok(result.value() + 1);
527 })
528 .then([&](fit::context& context, fit::result<int, char>& result)
529 -> fit::result<int, char> {
530 ASSERT_CRITICAL(&context == &fake_context);
531 run_count++;
532 return fit::ok(result.value() + 1);
533 })
534 .then([&](fit::context& context, const fit::result<int, char>& result)
535 -> fit::result<int, char> {
536 ASSERT_CRITICAL(&context == &fake_context);
537 run_count++;
538 return fit::ok(result.value() + 1);
539 });
540
541 fit::result<int, char> result = p(fake_context);
542 EXPECT_FALSE(p);
543 EXPECT_EQ(6, run_count);
544 EXPECT_EQ(fit::result_state::ok, result.state());
545 EXPECT_EQ(48, result.value());
546 }
547
548 END_TEST;
549 }
550
and_then_combinator()551 bool and_then_combinator() {
552 BEGIN_TEST;
553
554 fake_context fake_context;
555
556 // Chaining on OK.
557 // Handler signature: fit::result<>(int).
558 {
559 uint64_t run_count = 0;
560 auto p =
561 make_delayed_ok_promise(42)
562 .and_then([&](int value) -> fit::result<void, char> {
563 ASSERT_CRITICAL(value == 42);
564 if (++run_count == 2)
565 return fit::error('y');
566 return fit::pending();
567 });
568
569 fit::result<void, char> result = p(fake_context);
570 EXPECT_TRUE(p);
571 EXPECT_EQ(0, run_count);
572 EXPECT_EQ(fit::result_state::pending, result.state());
573
574 result = p(fake_context);
575 EXPECT_TRUE(p);
576 EXPECT_EQ(1, run_count);
577 EXPECT_EQ(fit::result_state::pending, result.state());
578
579 result = p(fake_context);
580 EXPECT_FALSE(p);
581 EXPECT_EQ(2, run_count);
582 EXPECT_EQ(fit::result_state::error, result.state());
583 EXPECT_EQ('y', result.error());
584 }
585
586 // Chaining on ERROR.
587 // Handler signature: fit::result<>(int).
588 {
589 uint64_t run_count = 0;
590 auto p =
591 make_delayed_error_promise('x')
592 .and_then([&](int value) -> fit::result<void, char> {
593 run_count++;
594 return fit::pending();
595 });
596
597 fit::result<void, char> result = p(fake_context);
598 EXPECT_TRUE(p);
599 EXPECT_EQ(0, run_count);
600 EXPECT_EQ(fit::result_state::pending, result.state());
601
602 result = p(fake_context);
603 EXPECT_FALSE(p);
604 EXPECT_EQ(0, run_count);
605 EXPECT_EQ(fit::result_state::error, result.state());
606 EXPECT_EQ('x', result.error());
607 }
608
609 // Cover all handler argument signatures, more briefly.
610 {
611 uint64_t run_count = 0;
612 auto p =
613 make_ok_promise(42)
614 .and_then([&](int value)
615 -> fit::result<int, char> {
616 run_count++;
617 return fit::ok(value + 1);
618 })
619 .and_then([&](int& value)
620 -> fit::result<int, char> {
621 run_count++;
622 return fit::ok(value + 1);
623 })
624 .and_then([&](const int& value)
625 -> fit::result<int, char> {
626 run_count++;
627 return fit::ok(value + 1);
628 })
629 .and_then([&](fit::context& context, int value)
630 -> fit::result<int, char> {
631 ASSERT_CRITICAL(&context == &fake_context);
632 run_count++;
633 return fit::ok(value + 1);
634 })
635 .and_then([&](fit::context& context, int& value)
636 -> fit::result<int, char> {
637 ASSERT_CRITICAL(&context == &fake_context);
638 run_count++;
639 return fit::ok(value + 1);
640 })
641 .and_then([&](fit::context& context, const int& value)
642 -> fit::result<int, char> {
643 ASSERT_CRITICAL(&context == &fake_context);
644 run_count++;
645 return fit::ok(value + 1);
646 });
647
648 fit::result<int, char> result = p(fake_context);
649 EXPECT_EQ(6, run_count);
650 EXPECT_EQ(fit::result_state::ok, result.state());
651 EXPECT_EQ(48, result.value());
652 EXPECT_FALSE(p);
653 }
654
655 END_TEST;
656 }
657
or_else_combinator()658 bool or_else_combinator() {
659 BEGIN_TEST;
660
661 fake_context fake_context;
662
663 // Chaining on OK.
664 // Handler signature: fit::result<>(char).
665 {
666 uint64_t run_count = 0;
667 auto p =
668 make_delayed_ok_promise(42)
669 .or_else([&](char error) -> fit::result<int> {
670 run_count++;
671 return fit::pending();
672 });
673
674 fit::result<int> result = p(fake_context);
675 EXPECT_TRUE(p);
676 EXPECT_EQ(0, run_count);
677 EXPECT_EQ(fit::result_state::pending, result.state());
678
679 result = p(fake_context);
680 EXPECT_FALSE(p);
681 EXPECT_EQ(0, run_count);
682 EXPECT_EQ(fit::result_state::ok, result.state());
683 EXPECT_EQ(42, result.value());
684 }
685
686 // Chaining on ERROR.
687 // Handler signature: fit::result<>(char).
688 {
689 uint64_t run_count = 0;
690 auto p =
691 make_delayed_error_promise('x')
692 .or_else([&](char error) -> fit::result<int> {
693 ASSERT_CRITICAL(error == 'x');
694 if (++run_count == 2)
695 return fit::ok(43);
696 return fit::pending();
697 });
698
699 fit::result<int> result = p(fake_context);
700 EXPECT_TRUE(p);
701 EXPECT_EQ(0, run_count);
702 EXPECT_EQ(fit::result_state::pending, result.state());
703
704 result = p(fake_context);
705 EXPECT_TRUE(p);
706 EXPECT_EQ(1, run_count);
707 EXPECT_EQ(fit::result_state::pending, result.state());
708
709 result = p(fake_context);
710 EXPECT_FALSE(p);
711 EXPECT_EQ(2, run_count);
712 EXPECT_EQ(fit::result_state::ok, result.state());
713 EXPECT_EQ(43, result.value());
714 }
715
716 // Cover all handler argument signatures, more briefly.
717 {
718 uint64_t run_count = 0;
719 auto p =
720 make_error_promise('a')
721 .or_else([&](char error)
722 -> fit::result<int, char> {
723 run_count++;
724 return fit::error(error + 1);
725 })
726 .or_else([&](char& error)
727 -> fit::result<int, char> {
728 run_count++;
729 return fit::error(error + 1);
730 })
731 .or_else([&](const char& error)
732 -> fit::result<int, char> {
733 run_count++;
734 return fit::error(error + 1);
735 })
736 .or_else([&](fit::context& context, char error)
737 -> fit::result<int, char> {
738 ASSERT_CRITICAL(&context == &fake_context);
739 run_count++;
740 return fit::error(error + 1);
741 })
742 .or_else([&](fit::context& context, char& error)
743 -> fit::result<int, char> {
744 ASSERT_CRITICAL(&context == &fake_context);
745 run_count++;
746 return fit::error(error + 1);
747 })
748 .or_else([&](fit::context& context, const char& error)
749 -> fit::result<int, char> {
750 ASSERT_CRITICAL(&context == &fake_context);
751 run_count++;
752 return fit::error(error + 1);
753 });
754
755 fit::result<int, char> result = p(fake_context);
756 EXPECT_EQ(6, run_count);
757 EXPECT_EQ(fit::result_state::error, result.state());
758 EXPECT_EQ('g', result.error());
759 EXPECT_FALSE(p);
760 }
761
762 END_TEST;
763 }
764
inspect_combinator()765 bool inspect_combinator() {
766 BEGIN_TEST;
767
768 fake_context fake_context;
769
770 // Chaining on OK.
771 // Handler signature: void(fit::result<int, char>).
772 {
773 uint64_t run_count = 0;
774 auto p =
775 make_delayed_ok_promise(42)
776 .inspect([&](fit::result<int, char> result) {
777 ASSERT_CRITICAL(result.value() == 42);
778 run_count++;
779 });
780
781 fit::result<int, char> result = p(fake_context);
782 EXPECT_TRUE(p);
783 EXPECT_EQ(0, run_count);
784 EXPECT_EQ(fit::result_state::pending, result.state());
785
786 result = p(fake_context);
787 EXPECT_FALSE(p);
788 EXPECT_EQ(1, run_count);
789 EXPECT_EQ(fit::result_state::ok, result.state());
790 EXPECT_EQ(42, result.value());
791 }
792
793 // Chaining on ERROR.
794 // Handler signature: void(fit::result<int, char>).
795 {
796 uint64_t run_count = 0;
797 auto p =
798 make_delayed_error_promise('x')
799 .inspect([&](fit::result<int, char> result) {
800 ASSERT_CRITICAL(result.error() == 'x');
801 run_count++;
802 });
803
804 fit::result<int, char> result = p(fake_context);
805 EXPECT_TRUE(p);
806 EXPECT_EQ(0, run_count);
807 EXPECT_EQ(fit::result_state::pending, result.state());
808
809 result = p(fake_context);
810 EXPECT_FALSE(p);
811 EXPECT_EQ(1, run_count);
812 EXPECT_EQ(fit::result_state::error, result.state());
813 EXPECT_EQ('x', result.error());
814 }
815
816 // Cover all handler argument signatures, more briefly.
817 {
818 uint64_t run_count = 0;
819 auto p =
820 make_ok_promise(42)
821 .inspect([&](fit::result<int, char> result) {
822 ASSERT_CRITICAL(result.value() == 42);
823 run_count++;
824 })
825 .inspect([&](fit::result<int, char>& result) {
826 ASSERT_CRITICAL(result.value() == 42);
827 run_count++;
828 result = fit::ok(result.value() + 1);
829 })
830 .inspect([&](const fit::result<int, char>& result) {
831 ASSERT_CRITICAL(result.value() == 43);
832 run_count++;
833 })
834 .inspect([&](fit::context& context, fit::result<int, char> result) {
835 ASSERT_CRITICAL(result.value() == 43);
836 ASSERT_CRITICAL(&context == &fake_context);
837 run_count++;
838 })
839 .inspect([&](fit::context& context, fit::result<int, char>& result) {
840 ASSERT_CRITICAL(result.value() == 43);
841 ASSERT_CRITICAL(&context == &fake_context);
842 run_count++;
843 result = fit::ok(result.value() + 1);
844 })
845 .inspect([&](fit::context& context, const fit::result<int, char>& result) {
846 ASSERT_CRITICAL(result.value() == 44);
847 ASSERT_CRITICAL(&context == &fake_context);
848 run_count++;
849 });
850
851 fit::result<int, char> result = p(fake_context);
852 EXPECT_FALSE(p);
853 EXPECT_EQ(6, run_count);
854 EXPECT_EQ(fit::result_state::ok, result.state());
855 EXPECT_EQ(44, result.value());
856 }
857
858 END_TEST;
859 }
860
discard_result_combinator()861 bool discard_result_combinator() {
862 BEGIN_TEST;
863
864 fake_context fake_context;
865
866 // Chaining on OK.
867 {
868 auto p = make_delayed_ok_promise(42).discard_result();
869 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
870 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
871
872 fit::result<> result = p(fake_context);
873 EXPECT_TRUE(p);
874 EXPECT_EQ(fit::result_state::pending, result.state());
875
876 result = p(fake_context);
877 EXPECT_FALSE(p);
878 EXPECT_EQ(fit::result_state::ok, result.state());
879 }
880
881 // Chaining on ERROR.
882 {
883 auto p = make_delayed_error_promise('x').discard_result();
884 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
885 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
886
887 fit::result<> result = p(fake_context);
888 EXPECT_TRUE(p);
889 EXPECT_EQ(fit::result_state::pending, result.state());
890
891 result = p(fake_context);
892 EXPECT_FALSE(p);
893 EXPECT_EQ(fit::result_state::ok, result.state());
894 }
895
896 END_TEST;
897 }
898
wrap_with_combinator()899 bool wrap_with_combinator() {
900 BEGIN_TEST;
901
902 fake_context fake_context;
903 capture_result_wrapper<int, char> wrapper;
904 uint64_t successor_run_count = 0;
905
906 // Apply a wrapper which steals a promise's result th
907 auto p = make_delayed_ok_promise(42)
908 .wrap_with(wrapper)
909 .then([&](fit::result<>) { successor_run_count++; });
910 static_assert(std::is_same<void, decltype(p)::value_type>::value, "");
911 static_assert(std::is_same<void, decltype(p)::error_type>::value, "");
912
913 fit::result<> result = p(fake_context);
914 EXPECT_TRUE(p);
915 EXPECT_EQ(fit::result_state::pending, result.state());
916 EXPECT_EQ(fit::result_state::pending, wrapper.last_result.state());
917 EXPECT_EQ(0, successor_run_count);
918
919 result = p(fake_context);
920 EXPECT_FALSE(p);
921 EXPECT_EQ(fit::result_state::ok, result.state());
922 EXPECT_EQ(fit::result_state::ok, wrapper.last_result.state());
923 EXPECT_EQ(42, wrapper.last_result.value());
924 EXPECT_EQ(1, successor_run_count);
925
926 END_TEST;
927 }
928
box_combinator()929 bool box_combinator() {
930 BEGIN_TEST;
931
932 fake_context fake_context;
933
934 auto p = fit::make_promise([&]() -> fit::result<int, char> {
935 return fit::ok(42);
936 });
937 static_assert(!std::is_same<fit::promise<int, char>, decltype(p)>::value, "");
938
939 auto q = p.box();
940 static_assert(std::is_same<fit::promise<int, char>, decltype(q)>::value, "");
941 EXPECT_TRUE(q);
942 EXPECT_FALSE(p);
943
944 fit::result<int, char> result = q(fake_context);
945 EXPECT_FALSE(q);
946 EXPECT_EQ(fit::result_state::ok, result.state());
947 EXPECT_EQ(42, result.value());
948
949 END_TEST;
950 }
951
join_combinator()952 bool join_combinator() {
953 BEGIN_TEST;
954
955 fake_context fake_context;
956
957 auto p = fit::join_promises(
958 make_ok_promise(42),
959 make_error_promise('x').or_else([](char error) {
960 return fit::error('y');
961 }),
962 make_delayed_ok_promise(55));
963 EXPECT_TRUE(p);
964
965 fit::result<std::tuple<
966 fit::result<int, char>,
967 fit::result<int, char>,
968 fit::result<int, char>>>
969 result = p(fake_context);
970 EXPECT_TRUE(p);
971 EXPECT_EQ(fit::result_state::pending, result.state());
972
973 result = p(fake_context);
974 EXPECT_FALSE(p);
975 EXPECT_EQ(fit::result_state::ok, result.state());
976 EXPECT_EQ(42, std::get<0>(result.value()).value());
977 EXPECT_EQ('y', std::get<1>(result.value()).error());
978 EXPECT_EQ(55, std::get<2>(result.value()).value());
979
980 END_TEST;
981 }
982
983 // Ensure that fit::promise is considered nullable so that a promise can be
984 // directly stored as the continuation of another promise without any
985 // additional wrappers, similar to fit::function.
986 static_assert(fit::is_nullable<fit::promise<>>::value, "");
987
988 // Test return type adapation performed by handler invokers.
989 // These tests verify that the necessary specializations can be produced
990 // in all cases for handlers with various signatures.
991 namespace handler_invoker_test {
992
993 // handler returning void...
994 static_assert(std::is_same<
995 fit::result<>,
996 fit::internal::result_handler_invoker<
997 void (*)(fit::result<int, double>&),
998 fit::result<int, double>>::result_type>::value,
999 "");
1000 static_assert(std::is_same<
1001 fit::result<void, double>,
1002 fit::internal::value_handler_invoker<
1003 void (*)(int&),
1004 fit::result<int, double>>::result_type>::value,
1005 "");
1006 static_assert(std::is_same<
1007 fit::result<int, void>,
1008 fit::internal::error_handler_invoker<
1009 void (*)(double&),
1010 fit::result<int, double>>::result_type>::value,
1011 "");
1012
1013 // handler returning fit::pending_result...
1014 static_assert(std::is_same<
1015 fit::result<>,
1016 fit::internal::result_handler_invoker<
1017 fit::pending_result (*)(fit::result<int, double>&),
1018 fit::result<int, double>>::result_type>::value,
1019 "");
1020 static_assert(std::is_same<
1021 fit::result<void, double>,
1022 fit::internal::value_handler_invoker<
1023 fit::pending_result (*)(int&),
1024 fit::result<int, double>>::result_type>::value,
1025 "");
1026 static_assert(std::is_same<
1027 fit::result<int, void>,
1028 fit::internal::error_handler_invoker<
1029 fit::pending_result (*)(double&),
1030 fit::result<int, double>>::result_type>::value,
1031 "");
1032
1033 // handler returning fit::ok_result...
1034 static_assert(std::is_same<
1035 fit::result<unsigned, void>,
1036 fit::internal::result_handler_invoker<
1037 fit::ok_result<unsigned> (*)(fit::result<int, double>&),
1038 fit::result<int, double>>::result_type>::value,
1039 "");
1040 static_assert(std::is_same<
1041 fit::result<unsigned, double>,
1042 fit::internal::value_handler_invoker<
1043 fit::ok_result<unsigned> (*)(int&),
1044 fit::result<int, double>>::result_type>::value,
1045 "");
1046 static_assert(std::is_same<
1047 fit::result<int, void>,
1048 fit::internal::error_handler_invoker<
1049 fit::ok_result<int> (*)(double&),
1050 fit::result<int, double>>::result_type>::value,
1051 "");
1052
1053 // handler returning fit::error_result...
1054 static_assert(std::is_same<
1055 fit::result<void, float>,
1056 fit::internal::result_handler_invoker<
1057 fit::error_result<float> (*)(fit::result<int, double>&),
1058 fit::result<int, double>>::result_type>::value,
1059 "");
1060 static_assert(std::is_same<
1061 fit::result<void, double>,
1062 fit::internal::value_handler_invoker<
1063 fit::error_result<double> (*)(int&),
1064 fit::result<int, double>>::result_type>::value,
1065 "");
1066 static_assert(std::is_same<
1067 fit::result<int, float>,
1068 fit::internal::error_handler_invoker<
1069 fit::error_result<float> (*)(double&),
1070 fit::result<int, double>>::result_type>::value,
1071 "");
1072
1073 // handler returning fit::result...
1074 static_assert(std::is_same<
1075 fit::result<unsigned, float>,
1076 fit::internal::result_handler_invoker<
1077 fit::result<unsigned, float> (*)(fit::result<int, double>&),
1078 fit::result<int, double>>::result_type>::value,
1079 "");
1080 static_assert(std::is_same<
1081 fit::result<unsigned, float>,
1082 fit::internal::value_handler_invoker<
1083 fit::result<unsigned, float> (*)(int&),
1084 fit::result<int, double>>::result_type>::value,
1085 "");
1086 static_assert(std::is_same<
1087 fit::result<unsigned, float>,
1088 fit::internal::error_handler_invoker<
1089 fit::result<unsigned, float> (*)(double&),
1090 fit::result<int, double>>::result_type>::value,
1091 "");
1092
1093 // handler returning fit::promise...
1094 static_assert(std::is_same<
1095 fit::result<unsigned, float>,
1096 fit::internal::result_handler_invoker<
1097 fit::promise<unsigned, float> (*)(fit::result<int, double>&),
1098 fit::result<int, double>>::result_type>::value,
1099 "");
1100 static_assert(std::is_same<
1101 fit::result<unsigned, double>,
1102 fit::internal::value_handler_invoker<
1103 fit::promise<unsigned, double> (*)(int&),
1104 fit::result<int, double>>::result_type>::value,
1105 "");
1106 static_assert(std::is_same<
1107 fit::result<int, float>,
1108 fit::internal::error_handler_invoker<
1109 fit::promise<int, float> (*)(double&),
1110 fit::result<int, double>>::result_type>::value,
1111 "");
1112
1113 // handler returning lambda...
1114 auto result_continuation_lambda = [](fit::result<int, double>&)
__anon5af905b73b02(fit::result<int, double>&) 1115 -> fit::result<unsigned, float> { return fit::pending(); };
1116 auto value_continuation_lambda = [](int&)
__anon5af905b73c02(int&) 1117 -> fit::result<unsigned, double> { return fit::pending(); };
1118 auto error_continuation_lambda = [](double&)
__anon5af905b73d02(double&) 1119 -> fit::result<int, float> { return fit::pending(); };
1120 static_assert(std::is_same<
1121 fit::result<unsigned, float>,
1122 fit::internal::result_handler_invoker<
1123 decltype(result_continuation_lambda),
1124 fit::result<int, double>>::result_type>::value,
1125 "");
1126 static_assert(std::is_same<
1127 fit::result<unsigned, double>,
1128 fit::internal::value_handler_invoker<
1129 decltype(value_continuation_lambda),
1130 fit::result<int, double>>::result_type>::value,
1131 "");
1132 static_assert(std::is_same<
1133 fit::result<int, float>,
1134 fit::internal::error_handler_invoker<
1135 decltype(error_continuation_lambda),
1136 fit::result<int, double>>::result_type>::value,
1137 "");
1138
1139 } // namespace handler_invoker_test
1140
1141 // Test predicate which is used interally to improve the quality of
1142 // compilation errors when an invalid continuation type is encountered.
1143 namespace is_continuation_test {
1144
1145 static_assert(fit::internal::is_continuation<
1146 fit::function<fit::result<>(fit::context&)>>::value,
1147 "");
1148 static_assert(!fit::internal::is_continuation<
1149 fit::function<void(fit::context&)>>::value,
1150 "");
1151 static_assert(!fit::internal::is_continuation<
1152 fit::function<fit::result<>()>>::value,
1153 "");
1154 static_assert(!fit::internal::is_continuation<
1155 void>::value,
1156 "");
1157
1158 auto continuation_lambda = [](fit::context&)
__anon5af905b73e02(fit::context&) 1159 -> fit::result<> { return fit::pending(); };
__anon5af905b73f02null1160 auto invalid_lambda = [] {};
1161
1162 static_assert(fit::internal::is_continuation<
1163 decltype(continuation_lambda)>::value,
1164 "");
1165 static_assert(!fit::internal::is_continuation<
1166 decltype(invalid_lambda)>::value,
1167 "");
1168
1169 } // namespace is_continuation_test
1170 } // namespace
1171
1172 // These are compile-time diagnostic tests.
1173 // We expect the following tests to fail at compile time and produce helpful
1174 // static assertions when enabled manually.
1175 #if 0
1176 void diagnose_handler_with_invalid_return_type() {
1177 // Doesn't work because result isn't fit::result<>, fit::ok_result<>,
1178 // fit::error_result<>, fit::pending_result, a continuation, or void.
1179 fit::make_promise([]() -> int { return 0; });
1180 }
1181 #endif
1182 #if 0
1183 void diagnose_handler_with_too_few_arguments() {
1184 // Expected between 1 and 2 arguments, got 0.
1185 fit::make_promise([] {})
1186 .then([]() {});
1187 }
1188 #endif
1189 #if 0
1190 void diagnose_handler_with_too_many_arguments() {
1191 // Expected between 1 and 2 arguments, got 3.
1192 fit::make_promise([] {})
1193 .then([](fit::context&, fit::result<>, int excess) {});
1194 }
1195 #endif
1196 #if 0
1197 void diagnose_handler_with_invalid_context_arg() {
1198 // When there are two argument, the first must be fit::context&.
1199 fit::make_promise([] {})
1200 .then([](fit::result<>, int excess) {});
1201 }
1202 #endif
1203 #if 0
1204 void diagnose_handler_with_invalid_result_arg() {
1205 // The result type must match that produced by the prior.
1206 fit::make_promise([] {})
1207 .then([](fit::result<int>& result) {});
1208 }
1209 #endif
1210 #if 0
1211 void diagnose_handler_with_invalid_move_only_result_arg() {
1212 // Move-only types must be passed by reference not by value.
1213 fit::make_promise([] { return fit::ok(move_only{}); })
1214 .then([](fit::result<move_only> result) {});
1215 }
1216 #endif
1217 #if 0
1218 void diagnose_handler_with_invalid_value_arg() {
1219 // The value type must match that produced by the prior.
1220 fit::make_promise([] { return fit::ok(3.2f); })
1221 .and_then([](int value) {});
1222 }
1223 #endif
1224 #if 0
1225 void diagnose_handler_with_invalid_move_only_value_arg() {
1226 // The value type must match that produced by the prior.
1227 fit::make_promise([] { return fit::ok(move_only{}); })
1228 .and_then([](move_only value) {});
1229 }
1230 #endif
1231 #if 0
1232 void diagnose_handler_with_invalid_error_arg() {
1233 // The error type must match that produced by the prior.
1234 fit::make_promise([] { return fit::error(3.2f); })
1235 .or_else([](int error) {});
1236 }
1237 #endif
1238 #if 0
1239 void diagnose_handler_with_invalid_move_only_error_arg() {
1240 // The error type must match that produced by the prior.
1241 fit::make_promise([] { return fit::error(move_only{}); })
1242 .or_else([](move_only error) {});
1243 }
1244 #endif
1245
1246 BEGIN_TEST_CASE(promise_tests)
1247 RUN_TEST(basics)
1248 RUN_TEST(empty_promise)
1249 RUN_TEST(invocation)
1250 RUN_TEST(take_continuation)
1251 RUN_TEST(assignment_and_swap)
1252 RUN_TEST(comparison_with_nullptr)
1253 RUN_TEST(make_promise)
1254 RUN_TEST(make_promise_with_continuation)
1255 RUN_TEST(then_combinator)
1256 RUN_TEST(and_then_combinator)
1257 RUN_TEST(or_else_combinator)
1258 RUN_TEST(inspect_combinator)
1259 RUN_TEST(discard_result_combinator)
1260 RUN_TEST(wrap_with_combinator)
1261 RUN_TEST(box_combinator)
1262 RUN_TEST(join_combinator)
1263
1264 // suppress -Wunneeded-internal-declaration
1265 (void)handler_invoker_test::result_continuation_lambda;
1266 (void)handler_invoker_test::value_continuation_lambda;
1267 (void)handler_invoker_test::error_continuation_lambda;
1268 (void)is_continuation_test::continuation_lambda;
1269 (void)is_continuation_test::invalid_lambda;
1270 END_TEST_CASE(promise_tests)
1271