blob: 39ee28d7337c9aad13f72ad5a47892c0257193ae [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{
Patrick Williams78e436f2022-09-21 10:06:20 -05007 ~Context() noexcept = default;
8
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 Williams1b7b54c2022-09-21 10:49:45 -050016 void runToStop()
17 {
18 ctx->run(std::execution::just() |
19 std::execution::then([this]() { ctx->request_stop(); }));
20 }
21
Patrick Williams78e436f2022-09-21 10:06:20 -050022 std::optional<sdbusplus::async::context> ctx{std::in_place};
23};
24
25TEST_F(Context, RunSimple)
26{
Patrick Williams1b7b54c2022-09-21 10:49:45 -050027 runToStop();
Patrick Williams73e278b2022-09-16 08:31:36 -050028}
Patrick Williams0139cac2022-09-20 17:04:17 -050029
Patrick Williams78e436f2022-09-21 10:06:20 -050030TEST_F(Context, SpawnedTask)
Patrick Williams0139cac2022-09-20 17:04:17 -050031{
Patrick Williams78e436f2022-09-21 10:06:20 -050032 ctx->spawn(std::execution::just());
Patrick Williams1b7b54c2022-09-21 10:49:45 -050033 runToStop();
Patrick Williams78e436f2022-09-21 10:06:20 -050034}
Patrick Williams0139cac2022-09-20 17:04:17 -050035
Patrick Williams78e436f2022-09-21 10:06:20 -050036TEST_F(Context, SpawnDelayedTask)
37{
38 using namespace std::literals;
39 static constexpr auto timeout = 500ms;
40
41 auto start = std::chrono::steady_clock::now();
42
43 bool ran = false;
44 ctx->spawn(sdbusplus::async::sleep_for(*ctx, timeout) |
45 std::execution::then([&ran]() { ran = true; }));
46
Patrick Williams1b7b54c2022-09-21 10:49:45 -050047 runToStop();
Patrick Williams78e436f2022-09-21 10:06:20 -050048
49 auto stop = std::chrono::steady_clock::now();
50
51 EXPECT_TRUE(ran);
52 EXPECT_GT(stop - start, timeout);
53 EXPECT_LT(stop - start, timeout * 2);
Patrick Williams0139cac2022-09-20 17:04:17 -050054}
Patrick Williams1b7b54c2022-09-21 10:49:45 -050055
Patrick Williamsd6b05cc2022-09-23 09:38:38 -050056TEST_F(Context, SpawnRecursiveTask)
57{
58 struct _
59 {
60 static auto one(size_t count, size_t& executed)
61 -> sdbusplus::async::task<size_t>
62 {
63 if (count)
64 {
65 ++executed;
66 co_return (co_await one(count - 1, executed)) + 1;
67 }
68 co_return co_await std::execution::just(0);
69 }
70 };
71
72 static constexpr size_t count = 100;
73 size_t executed = 0;
74
75 ctx->spawn(_::one(count, executed) | std::execution::then([=](auto result) {
76 EXPECT_EQ(result, count);
77 }));
78
79 runToStop();
80
81 EXPECT_EQ(executed, count);
82}
83
Patrick Williams1b7b54c2022-09-21 10:49:45 -050084TEST_F(Context, DestructMatcherWithPendingAwait)
85{
86 using namespace std::literals;
87
88 bool ran = false;
89 auto m = std::make_optional<sdbusplus::async::match>(
90 *ctx, sdbusplus::bus::match::rules::interfacesAdded(
91 "/this/is/a/bogus/path/for/SpawnMatcher"));
92
93 // Await the match completion (which will never happen).
94 ctx->spawn(m->next() | std::execution::then([&ran](...) { ran = true; }));
95
96 // Destruct the match.
97 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1ms) |
98 std::execution::then([&m](...) { m.reset(); }));
99
Patrick Williams4cfc2842022-09-22 09:53:33 -0500100 EXPECT_THROW(runToStop(), sdbusplus::exception::UnhandledStop);
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500101 EXPECT_FALSE(ran);
102}
103
104TEST_F(Context, DestructMatcherWithPendingAwaitAsTask)
105{
106 using namespace std::literals;
107
108 auto m = std::make_optional<sdbusplus::async::match>(
109 *ctx, sdbusplus::bus::match::rules::interfacesAdded(
110 "/this/is/a/bogus/path/for/SpawnMatcher"));
111
112 struct _
113 {
114 static auto fn(decltype(m->next()) snd, bool& ran)
115 -> sdbusplus::async::task<>
116 {
117 co_await std::move(snd);
118 ran = true;
119 co_return;
120 }
121 };
122
123 bool ran = false;
124 ctx->spawn(_::fn(m->next(), ran));
125 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1ms) |
126 std::execution::then([&]() { m.reset(); }));
127
Patrick Williams4cfc2842022-09-22 09:53:33 -0500128 EXPECT_THROW(runToStop(), sdbusplus::exception::UnhandledStop);
Patrick Williams1b7b54c2022-09-21 10:49:45 -0500129 EXPECT_FALSE(ran);
130}