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 FdioTimedTest : public ::testing::Test
13 {
14 protected:
15 enum class testWriteOperation
16 {
17 writeSync,
18 writeAsync,
19 writeSkip
20 };
21
22 const fs::path path = "/tmp/test_fdio_timed";
23
FdioTimedTest()24 FdioTimedTest()
25 {
26 if (!fs::exists(path))
27 {
28 fs::create_directory(path);
29 }
30
31 fd = inotify_init1(IN_NONBLOCK);
32 EXPECT_NE(fd, -1) << "Error occurred during the inotify_init1, error: "
33 << errno;
34
35 wd = inotify_add_watch(fd, path.c_str(), IN_CLOSE_WRITE);
36 EXPECT_NE(wd, -1)
37 << "Error occurred during the inotify_add_watch, error: " << errno;
38 fdioInstance = std::make_unique<sdbusplus::async::fdio>(
39 *ctx, fd, std::chrono::microseconds(1000));
40 }
41
~FdioTimedTest()42 ~FdioTimedTest() noexcept override
43 {
44 if (fd != -1)
45 {
46 if (wd != -1)
47 {
48 inotify_rm_watch(fd, wd);
49 }
50 close(fd);
51 }
52 ctx.reset();
53
54 if (fs::exists(path))
55 {
56 fs::remove_all(path);
57 }
58 }
59
writeToFile()60 auto writeToFile() -> sdbusplus::async::task<>
61 {
62 std::ofstream outfile((path / "test_fdio.txt").native());
63 EXPECT_TRUE(outfile.is_open())
64 << "Error occurred during file open, error: " << errno;
65 outfile << "Test fdio!" << std::endl;
66 outfile.close();
67 co_return;
68 }
69
testFdTimedEvents(bool & ran,testWriteOperation writeOperation,int testIterations)70 auto testFdTimedEvents(bool& ran, testWriteOperation writeOperation,
71 int testIterations) -> sdbusplus::async::task<>
72 {
73 for (int i = 0; i < testIterations; i++)
74 {
75 switch (writeOperation)
76 {
77 case testWriteOperation::writeSync:
78 co_await writeToFile();
79 break;
80 case testWriteOperation::writeAsync:
81 ctx->spawn(
82 sdbusplus::async::sleep_for(*ctx, 1s) |
83 stdexec::then([&]() { ctx->spawn(writeToFile()); }));
84 break;
85 case testWriteOperation::writeSkip:
86 default:
87 break;
88 }
89
90 bool receivedTimeout = false;
91
92 try
93 {
94 co_await fdioInstance->next();
95 }
96 catch (const sdbusplus::async::fdio_timeout_exception& e)
97 {
98 receivedTimeout = true;
99 }
100
101 switch (writeOperation)
102 {
103 case testWriteOperation::writeSync:
104 EXPECT_FALSE(receivedTimeout) << "Expected event";
105 break;
106 case testWriteOperation::writeAsync:
107 case testWriteOperation::writeSkip:
108 default:
109 EXPECT_TRUE(receivedTimeout) << "Expected timeout";
110 break;
111 }
112 }
113 ran = true;
114
115 co_return;
116 }
117
118 std::unique_ptr<sdbusplus::async::fdio> fdioInstance;
119 std::optional<sdbusplus::async::context> ctx{std::in_place};
120
121 private:
122 int fd = -1;
123 int wd = -1;
124 };
125
TEST_F(FdioTimedTest,TestWriteSkipWithTimeout)126 TEST_F(FdioTimedTest, TestWriteSkipWithTimeout)
127 {
128 bool ran = false;
129 ctx->spawn(testFdTimedEvents(ran, testWriteOperation::writeSkip, 1));
130 ctx->spawn(
131 sdbusplus::async::sleep_for(*ctx, 2s) |
132 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
133 ctx->run();
134 EXPECT_TRUE(ran);
135 }
136
TEST_F(FdioTimedTest,TestWriteAsyncWithTimeout)137 TEST_F(FdioTimedTest, TestWriteAsyncWithTimeout)
138 {
139 bool ran = false;
140 ctx->spawn(testFdTimedEvents(ran, testWriteOperation::writeAsync, 1));
141 ctx->spawn(
142 sdbusplus::async::sleep_for(*ctx, 2s) |
143 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
144 ctx->run();
145 EXPECT_TRUE(ran);
146 }
147
TEST_F(FdioTimedTest,TestWriteAsyncWithTimeoutIterative)148 TEST_F(FdioTimedTest, TestWriteAsyncWithTimeoutIterative)
149 {
150 bool ran = false;
151 ctx->spawn(testFdTimedEvents(ran, testWriteOperation::writeAsync, 100));
152 ctx->spawn(
153 sdbusplus::async::sleep_for(*ctx, 2s) |
154 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
155 ctx->run();
156 EXPECT_TRUE(ran);
157 }
158
TEST_F(FdioTimedTest,TestWriteSync)159 TEST_F(FdioTimedTest, TestWriteSync)
160 {
161 bool ran = false;
162 ctx->spawn(testFdTimedEvents(ran, testWriteOperation::writeSync, 1));
163 ctx->spawn(
164 sdbusplus::async::sleep_for(*ctx, 2s) |
165 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
166 ctx->run();
167 EXPECT_TRUE(ran);
168 }
169
TEST_F(FdioTimedTest,TestWriteSyncIterative)170 TEST_F(FdioTimedTest, TestWriteSyncIterative)
171 {
172 bool ran = false;
173 ctx->spawn(testFdTimedEvents(ran, testWriteOperation::writeSync, 100));
174 ctx->spawn(
175 sdbusplus::async::sleep_for(*ctx, 2s) |
176 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
177 ctx->run();
178 EXPECT_TRUE(ran);
179 }
180