rippled
Loading...
Searching...
No Matches
Mutex.cpp
1#include <xrpl/basics/Mutex.hpp>
2
3#include <gtest/gtest.h>
4
5#include <memory>
6#include <mutex>
7#include <shared_mutex>
8#include <string>
9#include <vector>
10
11using namespace xrpl;
12
13struct MutexMakeTest : ::testing::Test
14{
15};
16
17TEST_F(MutexMakeTest, default_constructor)
18{
19 auto m = Mutex<int>::make();
20 auto lock = m.lock();
21 EXPECT_EQ(*lock, 0);
22}
23
24TEST_F(MutexMakeTest, single_argument)
25{
26 auto m = Mutex<int>::make(42);
27 auto lock = m.lock();
28 EXPECT_EQ(*lock, 42);
29}
30
31TEST_F(MutexMakeTest, string_argument)
32{
33 auto m = Mutex<std::string>::make("test");
34 auto lock = m.lock();
35 EXPECT_EQ(*lock, "test");
36}
37
38TEST_F(MutexMakeTest, move_only_type)
39{
40 auto m = Mutex<std::unique_ptr<int>>::make(std::make_unique<int>(100));
41 auto lock = m.lock();
42 EXPECT_NE(lock->get(), nullptr);
43 EXPECT_EQ(**lock, 100);
44}
45
46struct MutexDirectConstructionTest : ::testing::Test
47{
48};
49
50TEST_F(MutexDirectConstructionTest, default_constructor)
51{
52 // Test default construction with a type that has a non-trivial
53 // default constructor
54 Mutex<std::string> m;
55 auto lock = m.lock();
56 EXPECT_TRUE(lock->empty());
57}
58
59TEST_F(MutexDirectConstructionTest, default_initialization)
60{
61 Mutex<int> m;
62 auto lock = m.lock();
63 EXPECT_EQ(*lock, 0);
64}
65
66TEST_F(MutexDirectConstructionTest, constructor_with_value)
67{
68 Mutex<int> m(42);
69 auto lock = m.lock();
70 EXPECT_EQ(*lock, 42);
71}
72
73TEST_F(MutexDirectConstructionTest, constructor_with_string)
74{
75 Mutex<std::string> m(std::string("hello"));
76 auto lock = m.lock();
77 EXPECT_EQ(*lock, "hello");
78}
79
80struct MutexLockNonConstTest : ::testing::Test
81{
82};
83
84TEST_F(MutexLockNonConstTest, operator_star)
85{
86 Mutex<int> m(10);
87 {
88 auto lock = m.lock();
89 EXPECT_EQ(*lock, 10);
90 *lock = 20;
91 }
92 auto lock = m.lock();
93 EXPECT_EQ(*lock, 20);
94}
95
96TEST_F(MutexLockNonConstTest, get_method)
97{
98 Mutex<int> m(10);
99 {
100 auto lock = m.lock();
101 EXPECT_EQ(lock.get(), 10);
102 lock.get() = 30;
103 }
104 auto lock = m.lock();
105 EXPECT_EQ(lock.get(), 30);
106}
107
108TEST_F(MutexLockNonConstTest, operator_arrow)
109{
110 Mutex<std::string> m(std::string("test"));
111 {
112 auto lock = m.lock();
113 EXPECT_EQ(lock->size(), 4);
114 lock->append(" string");
115 }
116 auto lock = m.lock();
117 EXPECT_EQ(*lock, "test string");
118}
119
120TEST_F(MutexLockNonConstTest, multiple_modifications)
121{
122 Mutex<int> m(10);
123 {
124 auto lock = m.lock();
125 *lock = 20;
126 }
127 {
128 auto lock = m.lock();
129 EXPECT_EQ(lock.get(), 20);
130 lock.get() = 30;
131 }
132 {
133 auto lock = m.lock();
134 EXPECT_EQ(*lock, 30);
135 }
136}
137
138struct MutexLockConstTest : ::testing::Test
139{
140};
141
142TEST_F(MutexLockConstTest, operator_star)
143{
144 Mutex<int> const m(42);
145 auto lock = m.lock();
146 static_assert(std::is_const_v<std::remove_reference_t<decltype(*lock)>>);
147 EXPECT_EQ(*lock, 42);
148}
149
150TEST_F(MutexLockConstTest, get_method)
151{
152 Mutex<int> const m(42);
153 auto lock = m.lock();
154 static_assert(std::is_const_v<std::remove_reference_t<decltype(lock.get())>>);
155 EXPECT_EQ(lock.get(), 42);
156}
157
158TEST_F(MutexLockConstTest, operator_arrow)
159{
160 Mutex<std::string> const m(std::string("test"));
161 auto lock = m.lock();
162 static_assert(std::is_const_v<std::remove_reference_t<decltype(*lock)>>);
163 EXPECT_EQ(lock->size(), 4);
164 EXPECT_EQ(lock->at(0), 't');
165}
166
167struct MutexConstCorrectnessTest : ::testing::Test
168{
169};
170
171TEST_F(MutexConstCorrectnessTest, non_const_allows_modification)
172{
173 Mutex<std::vector<int>> m({1, 2, 3, 4, 5});
174 {
175 auto lock = m.lock();
176 EXPECT_EQ(lock->size(), 5);
177 lock->push_back(6);
178 }
179 auto lock = m.lock();
180 EXPECT_EQ(lock->size(), 6);
181 EXPECT_EQ(lock->back(), 6);
182}
183
184TEST_F(MutexConstCorrectnessTest, const_reference_provides_const_access)
185{
186 Mutex<std::vector<int>> const m({1, 2, 3, 4, 5, 6});
187 Mutex<std::vector<int>> const& const_ref = m;
188 auto lock = const_ref.lock();
189 static_assert(std::is_const_v<std::remove_reference_t<decltype(*lock)>>);
190 EXPECT_EQ(lock->size(), 6);
191 EXPECT_EQ(lock->at(5), 6);
192}
193
194struct MutexDifferentLockTypesTest : ::testing::Test
195{
196};
197
198TEST_F(MutexDifferentLockTypesTest, lock_guard)
199{
200 Mutex<int> m(0);
201 {
202 auto lock = m.lock();
203 *lock = 1;
204 }
205 auto lock = m.lock();
206 EXPECT_EQ(*lock, 1);
207}
208
209TEST_F(MutexDifferentLockTypesTest, unique_lock)
210{
211 Mutex<int> m(0);
212 auto lock = m.lock<std::unique_lock>();
213 EXPECT_EQ(*lock, 0);
214 *lock = 2;
215
217 ul.unlock();
218 ul.lock();
219 EXPECT_EQ(*lock, 2);
220}
221
222struct MutexSharedMutexTest : ::testing::Test
223{
224};
225
226TEST_F(MutexSharedMutexTest, shared_lock_for_const_access)
227{
228 Mutex<int, std::shared_mutex> const m(100);
229 Mutex<int, std::shared_mutex> const& const_ref = m;
230 auto lock = const_ref.lock<std::shared_lock>();
231 EXPECT_EQ(*lock, 100);
232}
233
234TEST_F(MutexSharedMutexTest, unique_lock_for_mutable_access)
235{
236 Mutex<int, std::shared_mutex> m(100);
237 {
238 auto lock = m.lock<std::unique_lock>();
239 *lock = 200;
240 }
241 auto lock = m.lock<std::shared_lock>();
242 EXPECT_EQ(*lock, 200);
243}
244
245struct MutexComplexTypeTest : ::testing::Test
246{
247 struct Data
248 {
249 int x;
251
252 Data(int x_, std::string y_) : x(x_), y(std::move(y_))
253 {
254 }
255 };
256};
257
258TEST_F(MutexComplexTypeTest, construct_and_access)
259{
260 auto m = Mutex<Data>::make(42, "hello");
261 auto lock = m.lock();
262 EXPECT_EQ(lock->x, 42);
263 EXPECT_EQ(lock->y, "hello");
264}
265
266TEST_F(MutexComplexTypeTest, modify_fields)
267{
268 auto m = Mutex<Data>::make(42, "hello");
269 {
270 auto lock = m.lock();
271 lock->x = 100;
272 lock->y = "world";
273 }
274 {
275 auto lock = m.lock();
276 EXPECT_EQ(lock->x, 100);
277 EXPECT_EQ(lock->y, "world");
278 }
279}
280
281TEST_F(MutexComplexTypeTest, const_access_to_fields)
282{
283 auto const m = Mutex<Data>::make(42, "hello");
284 auto lock = m.lock();
285 static_assert(std::is_const_v<std::remove_reference_t<decltype(*lock)>>);
286 EXPECT_EQ(lock->x, 42);
287 EXPECT_EQ(lock->y, "hello");
288}
T is_const_v
T is_same_v
T lock(T... args)
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Data(int x_, std::string y_)
Definition Mutex.cpp:252
T unlock(T... args)