1 #include <sdbusplus/async.hpp> 2 3 #include <filesystem> 4 #include <fstream> 5 6 #include <gtest/gtest.h> 7 8 using namespace std::literals; 9 10 namespace fs = std::filesystem; 11 12 class FdioTest : public ::testing::Test 13 { 14 protected: 15 const fs::path path = "/tmp"; 16 constexpr static auto testIterations = 5; 17 18 FdioTest() 19 { 20 auto fd = inotify_init1(IN_NONBLOCK); 21 EXPECT_NE(fd, -1) << "Error occurred during the inotify_init1, error: " 22 << errno; 23 24 auto wd = inotify_add_watch(fd, path.c_str(), IN_CLOSE_WRITE); 25 EXPECT_NE(wd, -1) 26 << "Error occurred during the inotify_add_watch, error: " << errno; 27 fdioInstance = std::make_unique<sdbusplus::async::fdio>(*ctx, fd); 28 } 29 30 ~FdioTest() noexcept override 31 { 32 if (fd != -1) 33 { 34 if (wd != -1) 35 { 36 inotify_rm_watch(fd, wd); 37 } 38 close(fd); 39 } 40 ctx.reset(); 41 } 42 43 auto writeToFile() -> sdbusplus::async::task<> 44 { 45 std::ofstream outfile((path / "test_fdio.txt").native()); 46 EXPECT_TRUE(outfile.is_open()) 47 << "Error occurred during file open, error: " << errno; 48 outfile << "Test fdio!" << std::endl; 49 outfile.close(); 50 co_return; 51 } 52 53 auto testFdEvents(bool& ran, bool sleepBeforeWrite) 54 -> sdbusplus::async::task<> 55 { 56 for (int i = 0; i < testIterations; i++) 57 { 58 if (sleepBeforeWrite) 59 { 60 ctx->spawn(sdbusplus::async::sleep_for(*ctx, 1s) | 61 stdexec::then([&]() { ctx->spawn(writeToFile()); })); 62 } 63 else 64 { 65 co_await writeToFile(); 66 } 67 co_await fdioInstance->next(); 68 } 69 ran = true; 70 co_return; 71 } 72 73 std::unique_ptr<sdbusplus::async::fdio> fdioInstance; 74 std::optional<sdbusplus::async::context> ctx{std::in_place}; 75 76 private: 77 int fd = -1; 78 int wd = -1; 79 }; 80 81 TEST_F(FdioTest, TestFdEvents) 82 { 83 bool ran = false; 84 ctx->spawn(testFdEvents(ran, false)); 85 ctx->spawn( 86 sdbusplus::async::sleep_for(*ctx, 1s) | 87 sdbusplus::async::execution::then([&]() { ctx->request_stop(); })); 88 ctx->run(); 89 EXPECT_TRUE(ran); 90 } 91 92 TEST_F(FdioTest, TestFdEventsWithSleep) 93 { 94 bool ran = false; 95 ctx->spawn(testFdEvents(ran, true)); 96 ctx->spawn( 97 sdbusplus::async::sleep_for(*ctx, 5s) | 98 sdbusplus::async::execution::then([&]() { ctx->request_stop(); })); 99 ctx->run(); 100 EXPECT_TRUE(ran); 101 } 102