blob: 7f821ed7deff7b285d4496e356a42587720d070e [file] [log] [blame]
Patrick Williams73e278b2022-09-16 08:31:36 -05001#include <sdbusplus/async.hpp>
2
3#include <gtest/gtest.h>
4
Patrick Williams78e436f2022-09-21 10:06:20 -05005struct Context : public testing::Test
Patrick Williams73e278b2022-09-16 08:31:36 -05006{
Ed Tanous9688ed62023-01-06 13:17:25 -08007 ~Context() noexcept override = default;
Patrick Williams78e436f2022-09-21 10:06:20 -05008
9 void TearDown() override
10 {
11 // Destructing the context can throw, so we have to do it in
12 // the TearDown in order to make our destructor noexcept.
13 ctx.reset();
14 }
15
Patrick Williams115e9b32022-09-23 16:20:59 -050016 void spawnStop()
Patrick Williams1b7b54c2022-09-21 10:49:45 -050017 {
Patrick Williams5e7ef082023-01-05 11:08:53 -060018 ctx->spawn(stdexec::just() |
19 stdexec::then([this]() { ctx->request_stop(); }));
Patrick Williams115e9b32022-09-23 16:20:59 -050020 }
21
22 void runToStop()
23 {
24 spawnStop();
Patrick Williams3c242ba2022-09-23 09:51:55 -050025 ctx->run();
Patrick Williams1b7b54c2022-09-21 10:49:45 -050026 }
27
Patrick Williams78e436f2022-09-21 10:06:20 -050028 std::optional<sdbusplus::async::context> ctx{std::in_place};
29};
30
31TEST_F(Context, RunSimple)
32{
Patrick Williams1b7b54c2022-09-21 10:49:45 -050033 runToStop();
Patrick Williams73e278b2022-09-16 08:31:36 -050034}
Patrick Williams0139cac2022-09-20 17:04:17 -050035
Patrick Williams78e436f2022-09-21 10:06:20 -050036TEST_F(Context, SpawnedTask)
Patrick Williams0139cac2022-09-20 17:04:17 -050037{
Patrick Williams5e7ef082023-01-05 11:08:53 -060038 ctx->spawn(stdexec::just());
Patrick Williams1b7b54c2022-09-21 10:49:45 -050039 runToStop();
Patrick Williams78e436f2022-09-21 10:06:20 -050040}
Patrick Williams0139cac2022-09-20 17:04:17 -050041
Patrick Williams10483c92022-09-23 11:33:39 -050042TEST_F(Context, ReentrantRun)
43{
44 runToStop();
45 for (int i = 0; i < 100; ++i)
46 {
47 ctx->run();
48 }
49}
50
51TEST_F(Context, SpawnThrowingTask)
52{
Patrick Williams5e7ef082023-01-05 11:08:53 -060053 ctx->spawn(stdexec::just() |
54 stdexec::then([]() { throw std::logic_error("Oops"); }));
Patrick Williams10483c92022-09-23 11:33:39 -050055
56 EXPECT_THROW(runToStop(), std::logic_error);
57 ctx->run();
58}
59
Patrick Williams115e9b32022-09-23 16:20:59 -050060TEST_F(Context, SpawnManyThrowingTasks)
61{
62 static constexpr size_t count = 100;
63 for (size_t i = 0; i < count; ++i)
64 {
Patrick Williams5e7ef082023-01-05 11:08:53 -060065 ctx->spawn(stdexec::just() |
66 stdexec::then([]() { throw std::logic_error("Oops"); }));
Patrick Williams115e9b32022-09-23 16:20:59 -050067 }
68 spawnStop();
69
70 for (size_t i = 0; i < count; ++i)
71 {
72 EXPECT_THROW(ctx->run(), std::logic_error);
73 }
74 ctx->run();
75}
76
Patrick Williams78e436f2022-09-21 10:06:20 -050077TEST_F(Context, SpawnDelayedTask)
78{
79 using namespace std::literals;
80 static constexpr auto timeout = 500ms;
81
82 auto start = std::chrono::steady_clock::now();
83
84 bool ran = false;
85 ctx->spawn(sdbusplus::async::sleep_for(*ctx, timeout) |
Patrick Williams5e7ef082023-01-05 11:08:53 -060086 stdexec::then([&ran]() { ran = true; }));
Patrick Williams78e436f2022-09-21 10:06:20 -050087
Patrick Williams1b7b54c2022-09-21 10:49:45 -050088 runToStop();
Patrick Williams78e436f2022-09-21 10:06:20 -050089
90 auto stop = std::chrono::steady_clock::now();
91
92 EXPECT_TRUE(ran);
93 EXPECT_GT(stop - start, timeout);
Patrick Williams6ea246a2022-10-14 07:58:15 -050094 EXPECT_LT(stop - start, timeout * 3);
Patrick Williams0139cac2022-09-20 17:04:17 -050095}
Patrick Williams1b7b54c2022-09-21 10:49:45 -050096
Patrick Williamsd6b05cc2022-09-23 09:38:38 -050097TEST_F(Context, SpawnRecursiveTask)
98{
99 struct _
100 {
101 static auto one(size_t count, size_t& executed)
102 -> sdbusplus::async::task<size_t>
103 {
104 if (count)
105 {
106 ++executed;
107 co_return (co_await one(count - 1, executed)) + 1;
108 }
Patrick Williams5e7ef082023-01-05 11:08:53 -0600109 co_return co_await stdexec::just(0);
Patrick Williamsd6b05cc2022-09-23 09:38:38 -0500110 }
111 };
112
113 static constexpr size_t count = 100;
114 size_t executed = 0;
115
Patrick Williams5e7ef082023-01-05 11:08:53 -0600116 ctx->spawn(_::one(count, executed) |
117 stdexec::then([=](auto result) { EXPECT_EQ(result, count); }));
Patrick Williamsd6b05cc2022-09-23 09:38:38 -0500118
119 runToStop();
120
121 EXPECT_EQ(executed, count);
122}
123
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500124TEST_F(Context, DestructMatcherWithPendingAwait)
125{
126 using namespace std::literals;
127
128 bool ran = false;
129 auto m = std::make_optional<sdbusplus::async::match>(
130 *ctx, sdbusplus::bus::match::rules::interfacesAdded(
131 "/this/is/a/bogus/path/for/SpawnMatcher"));
132
133 // Await the match completion (which will never happen).
Patrick Williams5e7ef082023-01-05 11:08:53 -0600134 ctx->spawn(m->next() | stdexec::then([&ran](...) { ran = true; }));
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500135
136 // Destruct the match.
137 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1ms) |
Patrick Williams5e7ef082023-01-05 11:08:53 -0600138 stdexec::then([&m](...) { m.reset(); }));
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500139
Patrick Williams4cfc2842022-09-22 09:53:33 -0500140 EXPECT_THROW(runToStop(), sdbusplus::exception::UnhandledStop);
Patrick Williams10483c92022-09-23 11:33:39 -0500141 EXPECT_NO_THROW(ctx->run());
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500142 EXPECT_FALSE(ran);
143}
144
145TEST_F(Context, DestructMatcherWithPendingAwaitAsTask)
146{
147 using namespace std::literals;
148
149 auto m = std::make_optional<sdbusplus::async::match>(
150 *ctx, sdbusplus::bus::match::rules::interfacesAdded(
151 "/this/is/a/bogus/path/for/SpawnMatcher"));
152
153 struct _
154 {
155 static auto fn(decltype(m->next()) snd, bool& ran)
156 -> sdbusplus::async::task<>
157 {
158 co_await std::move(snd);
159 ran = true;
160 co_return;
161 }
162 };
163
164 bool ran = false;
165 ctx->spawn(_::fn(m->next(), ran));
166 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1ms) |
Patrick Williams5e7ef082023-01-05 11:08:53 -0600167 stdexec::then([&]() { m.reset(); }));
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500168
Patrick Williams4cfc2842022-09-22 09:53:33 -0500169 EXPECT_THROW(runToStop(), sdbusplus::exception::UnhandledStop);
Patrick Williams10483c92022-09-23 11:33:39 -0500170 EXPECT_NO_THROW(ctx->run());
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500171 EXPECT_FALSE(ran);
172}