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 MutexTest : public ::testing::Test
13 {
14 protected:
15 constexpr static std::string testMutex = "TestMutex";
16 const fs::path path = "/tmp";
17
MutexTest()18 MutexTest() : mutex(testMutex)
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 std::optional<sdbusplus::async::context> ctx{std::in_place};
31
testAsyncAddition(int val=1)32 auto testAsyncAddition(int val = 1) -> sdbusplus::async::task<>
33 {
34 sdbusplus::async::lock_guard lg{mutex};
35 co_await lg.lock();
36
37 sharedVar += val;
38 }
39
testAsyncSubtraction(int val=1)40 auto testAsyncSubtraction(int val = 1) -> sdbusplus::async::task<>
41 {
42 sdbusplus::async::lock_guard lg{mutex};
43 co_await lg.lock();
44
45 sharedVar -= val;
46 }
47
writeToFile()48 auto writeToFile() -> sdbusplus::async::task<>
49 {
50 std::ofstream outfile((path / testMutex).native());
51 EXPECT_TRUE(outfile.is_open())
52 << "Error occurred during file open, error: " << errno;
53
54 outfile << testMutex << std::endl;
55 outfile.close();
56
57 co_return;
58 }
59
readFromFile()60 auto readFromFile() -> sdbusplus::async::task<>
61 {
62 std::ifstream infile((path / testMutex).native());
63 EXPECT_TRUE(infile.is_open())
64 << "Error occurred during file open, error: " << errno;
65
66 std::string line;
67 std::getline(infile, line);
68 EXPECT_EQ(line, testMutex);
69 infile.close();
70
71 co_return;
72 }
73
testFdEvents()74 auto testFdEvents() -> sdbusplus::async::task<>
75 {
76 sdbusplus::async::lock_guard lg{mutex};
77 co_await lg.lock();
78
79 ctx->spawn(writeToFile());
80 co_await fdioInstance->next();
81 co_await readFromFile();
82 ran++;
83
84 co_return;
85 }
86
87 int sharedVar = 0;
88 int ran = 0;
89 sdbusplus::async::mutex mutex;
90
91 private:
92 std::unique_ptr<sdbusplus::async::fdio> fdioInstance;
93 int fd = -1;
94 int wd = -1;
95 };
96
TEST_F(MutexTest,TestAsyncAddition)97 TEST_F(MutexTest, TestAsyncAddition)
98 {
99 constexpr auto testIterations = 10;
100 for (auto i = 0; i < testIterations; i++)
101 {
102 ctx->spawn(testAsyncAddition());
103 }
104
105 ctx->spawn(
106 sdbusplus::async::sleep_for(*ctx, 1s) |
107 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
108
109 ctx->run();
110
111 EXPECT_EQ(sharedVar, testIterations);
112 }
113
TEST_F(MutexTest,TestAsyncMixed)114 TEST_F(MutexTest, TestAsyncMixed)
115 {
116 constexpr auto testIterations = 10;
117 for (auto i = 0; i < testIterations; i++)
118 {
119 ctx->spawn(testAsyncAddition());
120 ctx->spawn(testAsyncSubtraction(2));
121 }
122
123 ctx->spawn(
124 sdbusplus::async::sleep_for(*ctx, 1s) |
125 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
126
127 ctx->run();
128
129 EXPECT_EQ(sharedVar, -testIterations);
130 }
131
TEST_F(MutexTest,TestFdEvents)132 TEST_F(MutexTest, TestFdEvents)
133 {
134 constexpr static auto testIterations = 5;
135
136 for (auto i = 0; i < testIterations; i++)
137 {
138 ctx->spawn(testFdEvents());
139 }
140 ctx->spawn(
141 sdbusplus::async::sleep_for(*ctx, 3s) |
142 sdbusplus::async::execution::then([&]() { ctx->request_stop(); }));
143 ctx->run();
144 EXPECT_EQ(ran, testIterations);
145 }
146
TEST_F(MutexTest,TestLockGuardNoLock)147 TEST_F(MutexTest, TestLockGuardNoLock)
148 {
149 sdbusplus::async::lock_guard lg{mutex};
150 }
151