xref: /openbmc/sdbusplus/test/async/fdio.cpp (revision 36137e09614746b13603b5fbae79e6f70819c46b)
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 
FdioTest()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 
~FdioTest()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 
writeToFile()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 
testFdEvents(bool & ran,bool sleepBeforeWrite)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 
TEST_F(FdioTest,TestFdEvents)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 
TEST_F(FdioTest,TestFdEventsWithSleep)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