blob: 6630157aa839038f5fc6bba3237ae6b40209e477 [file] [log] [blame]
Jagpal Singh Gillbd04c3b2025-07-07 16:34:20 -07001#include <sdbusplus/async.hpp>
2
3#include <filesystem>
4#include <fstream>
5
6#include <gtest/gtest.h>
7
8using namespace std::literals;
9
10namespace fs = std::filesystem;
11
12class MutexTest : public ::testing::Test
13{
14 protected:
15 constexpr static std::string testMutex = "TestMutex";
16 const fs::path path = "/tmp";
17
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
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
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
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
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
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
97TEST_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
114TEST_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
132TEST_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
147TEST_F(MutexTest, TestLockGuardNoLock)
148{
149 sdbusplus::async::lock_guard lg{mutex};
150}