1 #include <sdbusplus/async.hpp> 2 3 #include <gtest/gtest.h> 4 5 struct Context : public testing::Test 6 { 7 ~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 16 void runToStop() 17 { 18 ctx->run(std::execution::just() | 19 std::execution::then([this]() { ctx->request_stop(); })); 20 } 21 22 std::optional<sdbusplus::async::context> ctx{std::in_place}; 23 }; 24 25 TEST_F(Context, RunSimple) 26 { 27 runToStop(); 28 } 29 30 TEST_F(Context, SpawnedTask) 31 { 32 ctx->spawn(std::execution::just()); 33 runToStop(); 34 } 35 36 TEST_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 47 runToStop(); 48 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); 54 } 55 56 TEST_F(Context, DestructMatcherWithPendingAwait) 57 { 58 using namespace std::literals; 59 60 bool ran = false; 61 auto m = std::make_optional<sdbusplus::async::match>( 62 *ctx, sdbusplus::bus::match::rules::interfacesAdded( 63 "/this/is/a/bogus/path/for/SpawnMatcher")); 64 65 // Await the match completion (which will never happen). 66 ctx->spawn(m->next() | std::execution::then([&ran](...) { ran = true; })); 67 68 // Destruct the match. 69 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1ms) | 70 std::execution::then([&m](...) { m.reset(); })); 71 72 runToStop(); 73 74 EXPECT_FALSE(ran); 75 } 76 77 TEST_F(Context, DestructMatcherWithPendingAwaitAsTask) 78 { 79 using namespace std::literals; 80 81 auto m = std::make_optional<sdbusplus::async::match>( 82 *ctx, sdbusplus::bus::match::rules::interfacesAdded( 83 "/this/is/a/bogus/path/for/SpawnMatcher")); 84 85 struct _ 86 { 87 static auto fn(decltype(m->next()) snd, bool& ran) 88 -> sdbusplus::async::task<> 89 { 90 co_await std::move(snd); 91 ran = true; 92 co_return; 93 } 94 }; 95 96 bool ran = false; 97 ctx->spawn(_::fn(m->next(), ran)); 98 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1ms) | 99 std::execution::then([&]() { m.reset(); })); 100 101 runToStop(); 102 103 EXPECT_FALSE(ran); 104 } 105