xref: /openbmc/sdbusplus/test/async/mutex.cpp (revision bd04c3b26ec121fdcf9715f2173ca986a01ab2e3)
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