xref: /openbmc/sdbusplus/test/async/task.cpp (revision 91cb97b5)
1 #include <sdbusplus/async/execution.hpp>
2 #include <sdbusplus/async/task.hpp>
3 
4 #include <gtest/gtest.h>
5 
6 using namespace sdbusplus::async;
7 
TEST(Task,CoAwaitVoid)8 TEST(Task, CoAwaitVoid)
9 {
10     bool value = false;
11     auto t = [&]() -> task<> {
12         value = true;
13         co_return;
14     };
15 
16     // Check to ensure the co-routine hasn't started executing yet.
17     EXPECT_FALSE(value);
18 
19     // Run it and confirm the value is updated.
20     stdexec::sync_wait(t());
21     EXPECT_TRUE(value);
22 }
23 
TEST(Task,CoAwaitInt)24 TEST(Task, CoAwaitInt)
25 {
26     struct _
27     {
28         static auto one() -> task<int>
29         {
30             co_return 42;
31         }
32         static auto two(bool& executed) -> task<>
33         {
34             auto r = co_await one();
35             EXPECT_EQ(r, 42);
36             executed = true;
37             co_return;
38         }
39     };
40 
41     // Add boolean to confirm that co-routine actually executed by the
42     // end.
43     bool executed = false;
44     stdexec::sync_wait(_::two(executed));
45     EXPECT_TRUE(executed);
46 }
47 
TEST(Task,CoAwaitThrow)48 TEST(Task, CoAwaitThrow)
49 {
50     struct _
51     {
52         static auto one() -> task<>
53         {
54             throw std::logic_error("Failed");
55             co_return;
56         }
57 
58         static auto two(bool& caught) -> task<>
59         {
60             try
61             {
62                 co_await (one());
63             }
64             catch (const std::logic_error&)
65             {
66                 caught = true;
67             }
68         }
69     };
70 
71     // Ensure throws surface up.
72     EXPECT_THROW(stdexec::sync_wait(_::one()), std::logic_error);
73 
74     // Ensure throws can be caught inside a co-routine.
75     bool caught = false;
76     stdexec::sync_wait(_::two(caught));
77     EXPECT_TRUE(caught);
78 }
79 
TEST(Task,RecursiveTask)80 TEST(Task, RecursiveTask)
81 {
82     struct _
83     {
84         static auto one(size_t count, size_t& executed) -> task<size_t>
85         {
86             if (count)
87             {
88                 ++executed;
89                 co_return (co_await one(count - 1, executed)) + 1;
90             }
91             co_return co_await stdexec::just(0);
92         }
93     };
94 
95     static constexpr size_t count = 100;
96     size_t executed = 0;
97 
98     stdexec::sync_wait(
99         _::one(count, executed) |
100         stdexec::then([=](auto result) { EXPECT_EQ(result, count); }));
101 
102     EXPECT_EQ(executed, count);
103 }
104