blob: 10c51d3c140a73e799fa694755d74cce760d0c03 [file] [log] [blame]
manojkiraneda4eaf2ee2019-12-13 17:10:41 +05301#include "ibm/locks.hpp"
manojkiraneda4eaf2ee2019-12-13 17:10:41 +05302
Gunnar Mills1214b7e2020-06-04 10:11:30 -05003#include <string>
4
manojkiraneda4eaf2ee2019-12-13 17:10:41 +05305#include "gmock/gmock.h"
6
Nan Zhou38ead5e2022-07-03 23:07:27 +00007namespace crow::ibm_mc_lock
manojkiraneda4eaf2ee2019-12-13 17:10:41 +05308{
Nan Zhou38ead5e2022-07-03 23:07:27 +00009namespace
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053010{
Nan Zhou38ead5e2022-07-03 23:07:27 +000011
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053012using SType = std::string;
13using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
14using LockRequests = std::vector<LockRequest>;
15using Rc =
16 std::pair<bool, std::variant<uint32_t, std::pair<uint32_t, LockRequest>>>;
17using RcRelaseLock = std::pair<bool, std::pair<uint32_t, LockRequest>>;
18using RcGetLockList =
19 std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
20using ListOfTransactionIds = std::vector<uint32_t>;
21using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>;
22using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>;
23using SessionFlags = std::pair<SType, SType>;
24using ListOfSessionIds = std::vector<std::string>;
25
26class LockTest : public ::testing::Test
27{
28 protected:
29 LockRequests request;
30 LockRequests request1, request2;
31 LockRequest record;
32
33 public:
34 LockTest()
35 {
36 record = {
37 "xxxxx", "hmc-id", "Read", 234, {{"DontLock", 2}, {"DontLock", 4}}};
38 // lockrequest with multiple lockrequests
39 request = {{"xxxxx",
40 "hmc-id",
41 "Read",
42 234,
43 {{"DontLock", 2}, {"DontLock", 4}}},
44 {"xxxxx",
45 "hmc-id",
46 "Read",
47 234,
48 {{"DontLock", 2}, {"DontLock", 4}}}};
49 request1 = {{"xxxxx",
50 "hmc-id",
51 "Read",
52 234,
53 {{"DontLock", 2}, {"DontLock", 4}}}};
54 request2 = {{"xxxxx",
55 "hmc-id",
56 "Write",
57 234,
58 {{"LockAll", 2}, {"DontLock", 4}}}};
59 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070060
61 ~LockTest() override = default;
Ed Tanousecd6a3a2022-01-07 09:18:40 -080062
63 LockTest(const LockTest&) = delete;
64 LockTest(LockTest&&) = delete;
65 LockTest& operator=(const LockTest&) = delete;
66 LockTest& operator=(const LockTest&&) = delete;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053067};
68
69class MockLock : public crow::ibm_mc_lock::Lock
70{
71 public:
Ed Tanousb5a76932020-09-29 16:16:58 -070072 bool isValidLockRequest(const LockRequest& record1) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053073 {
74 bool status = Lock::isValidLockRequest(record1);
75 return status;
76 }
Ed Tanousb5a76932020-09-29 16:16:58 -070077 bool isConflictRequest(const LockRequests& request) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053078 {
79 bool status = Lock::isConflictRequest(request);
80 return status;
81 }
Ed Tanousb5a76932020-09-29 16:16:58 -070082 Rc isConflictWithTable(const LockRequests& request) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053083 {
84 auto conflict = Lock::isConflictWithTable(request);
85 return conflict;
86 }
87 uint32_t generateTransactionId() override
88 {
89 uint32_t tid = Lock::generateTransactionId();
90 return tid;
91 }
92
93 bool validateRids(const ListOfTransactionIds& tids) override
94 {
95 bool status = Lock::validateRids(tids);
96 return status;
97 }
98 RcRelaseLock isItMyLock(const ListOfTransactionIds& tids,
99 const SessionFlags& ids) override
100 {
101 auto status = Lock::isItMyLock(tids, ids);
102 return status;
103 }
Ed Tanous02cad962022-06-30 16:50:15 -0700104 RcGetLockList getList(const std::vector<std::string>& listSessionid)
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530105 {
106 auto status = Lock::getLockList(listSessionid);
107 return status;
108 }
109 friend class LockTest;
110};
111
112TEST_F(LockTest, ValidationGoodTestCase)
113{
114 MockLock lockManager;
115 const LockRequest& t = record;
116 ASSERT_EQ(1, lockManager.isValidLockRequest(t));
117}
118
119TEST_F(LockTest, ValidationBadTestWithLocktype)
120{
121 MockLock lockManager;
122 // Corrupt the lock type
123 std::get<2>(record) = "rwrite";
124 const LockRequest& t = record;
125 ASSERT_EQ(0, lockManager.isValidLockRequest(t));
126}
127
128TEST_F(LockTest, ValidationBadTestWithlockFlags)
129{
130 MockLock lockManager;
131 // Corrupt the lockflag
132 std::get<4>(record)[0].first = "lock";
133 const LockRequest& t = record;
134 ASSERT_EQ(0, lockManager.isValidLockRequest(t));
135}
136
137TEST_F(LockTest, ValidationBadTestWithSegmentlength)
138{
139 MockLock lockManager;
140 // Corrupt the Segment length
141 std::get<4>(record)[0].second = 7;
142 const LockRequest& t = record;
143 ASSERT_EQ(0, lockManager.isValidLockRequest(t));
144}
145
146TEST_F(LockTest, MultiRequestWithoutConflict)
147{
148 MockLock lockManager;
149 const LockRequests& t = request;
150 ASSERT_EQ(0, lockManager.isConflictRequest(t));
151}
152
153TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentLength)
154{
155 MockLock lockManager;
156 // Corrupt the locktype
157 std::get<2>(request[0]) = "Write";
158 // Match the segment lengths to points them to lock similar kind of
159 // resource
160 std::get<4>(request[0])[0].first = "LockAll";
161 const LockRequests& t = request;
162 ASSERT_EQ(1, lockManager.isConflictRequest(t));
163}
164
165TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentData)
166{
167 MockLock lockManager;
168 // Corrupt the locktype
169 std::get<2>(request[0]) = "Write";
170 // Match the segment lengths to points them to lock similar kind of
171 // resource
172 std::get<4>(request[0])[0].first = "DontLock";
173 std::get<4>(request[0])[1].first = "LockAll";
174
175 // Change the resource id(2nd byte) of first record, so the locks are
176 // different so no conflict
177 std::get<3>(request[0]) = 216179379183550464; // HEX 03 00 06 00 00 00 00 00
178 std::get<3>(request[1]) = 288236973221478400; // HEX 04 00 06 00 00 00 00 00
179 const LockRequests& t = request;
180 ASSERT_EQ(0, lockManager.isConflictRequest(t));
181}
182
183TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentData)
184{
185 MockLock lockManager;
186 // Corrupt the locktype
187 std::get<2>(request[0]) = "Write";
188 // Match the segment lengths to points them to lock similar kind of
189 // resource
190 std::get<4>(request[0])[0].first = "DontLock";
191 std::get<4>(request[0])[1].first = "LockAll";
192 // Dont Change the resource id(1st & 2nd byte) at all, so that the conflict
193 // occurs from the second segment which is trying to lock all the resources.
194 std::get<3>(request[0]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
195 std::get<3>(request[1]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
196 const LockRequests& t = request;
197 ASSERT_EQ(1, lockManager.isConflictRequest(t));
198}
199
200TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentLength)
201{
202 MockLock lockManager;
203 // Corrupt the locktype
204 std::get<2>(request[0]) = "Write";
205 // Match the segment lengths to points them to lock similar kind of
206 // resource
207 std::get<4>(request[0])[0].first = "LockSame";
208 // Change the segment length , so that the requests are trying to lock
209 // two different kind of resources
210 std::get<4>(request[0])[0].second = 3;
211 const LockRequests& t = request;
212 // Return No Conflict
213 ASSERT_EQ(0, lockManager.isConflictRequest(t));
214}
215
216TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktype)
217{
218 MockLock lockManager;
219 // Match the segment lengths to points them to lock similar kind of
220 // resource
221 std::get<4>(request[0])[0].first = "LockAll";
222 const LockRequests& t = request;
223 // Return No Conflict
224 ASSERT_EQ(0, lockManager.isConflictRequest(t));
225}
226
227TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktypeAndLockall)
228{
229 MockLock lockManager;
230 // Match the segment lengths to points them to lock similar kind of
231 // resource
232 std::get<4>(request[0])[0].first = "LockAll";
233 std::get<4>(request[0])[1].first = "LockAll";
234 const LockRequests& t = request;
235 // Return No Conflict
236 ASSERT_EQ(0, lockManager.isConflictRequest(t));
237}
238
239TEST_F(LockTest, RequestConflictedWithLockTableEntries)
240{
241 MockLock lockManager;
242 const LockRequests& t = request1;
243 auto rc1 = lockManager.isConflictWithTable(t);
244 // Corrupt the lock type
245 std::get<2>(request[0]) = "Write";
246 // Corrupt the lockflag
247 std::get<4>(request[0])[1].first = "LockAll";
248 const LockRequests& p = request;
249 auto rc2 = lockManager.isConflictWithTable(p);
250 // Return a Conflict
251 ASSERT_EQ(1, rc2.first);
252}
253
254TEST_F(LockTest, RequestNotConflictedWithLockTableEntries)
255{
256 MockLock lockManager;
257 const LockRequests& t = request1;
258 // Insert the request1 into the lock table
259 auto rc1 = lockManager.isConflictWithTable(t);
260 // Corrupt the lock type
261 std::get<2>(request[0]) = "Read";
262 // Corrupt the lockflag
263 std::get<4>(request[0])[1].first = "LockAll";
264 const LockRequests& p = request;
265 auto rc2 = lockManager.isConflictWithTable(p);
266 // Return No Conflict
267 ASSERT_EQ(0, rc2.first);
268}
269
270TEST_F(LockTest, TestGenerateTransactionIDFunction)
271{
272 MockLock lockManager;
273 uint32_t transactionid1 = lockManager.generateTransactionId();
274 uint32_t transactionid2 = lockManager.generateTransactionId();
275 EXPECT_TRUE(transactionid2 == ++transactionid1);
276}
277
278TEST_F(LockTest, ValidateTransactionIDsGoodTestCase)
279{
280 MockLock lockManager;
281 const LockRequests& t = request1;
282 // Insert the request1 into the lock table
283 auto rc1 = lockManager.isConflictWithTable(t);
284 std::vector<uint32_t> tids = {1};
285 const std::vector<uint32_t>& p = tids;
286 ASSERT_EQ(1, lockManager.validateRids(p));
287}
288
289TEST_F(LockTest, ValidateTransactionIDsBadTestCase)
290{
291 MockLock lockManager;
292 // Insert the request1 into the lock table
293 const LockRequests& t = request1;
294 auto rc1 = lockManager.isConflictWithTable(t);
Sunitha Harish3e919b52020-10-13 01:21:48 -0500295 std::vector<uint32_t> tids = {10};
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530296 const std::vector<uint32_t>& p = tids;
297 ASSERT_EQ(0, lockManager.validateRids(p));
298}
299
300TEST_F(LockTest, ValidateisItMyLockGoodTestCase)
301{
302 MockLock lockManager;
303 // Insert the request1 into the lock table
304 const LockRequests& t = request1;
305 auto rc1 = lockManager.isConflictWithTable(t);
306 std::vector<uint32_t> tids = {1};
307 const std::vector<uint32_t>& p = tids;
308 std::string hmcid = "hmc-id";
309 std::string sessionid = "xxxxx";
310 std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
311 auto rc = lockManager.isItMyLock(p, ids);
312 ASSERT_EQ(1, rc.first);
313}
314
315TEST_F(LockTest, ValidateisItMyLockBadTestCase)
316{
317 MockLock lockManager;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530318 // Corrupt the client identifier
319 std::get<1>(request1[0]) = "randomid";
320 // Insert the request1 into the lock table
321 const LockRequests& t = request1;
322 auto rc1 = lockManager.isConflictWithTable(t);
323 std::vector<uint32_t> tids = {1};
324 const std::vector<uint32_t>& p = tids;
325 std::string hmcid = "hmc-id";
Sunitha Harish3e919b52020-10-13 01:21:48 -0500326 std::string sessionid = "random";
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530327 std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
328 auto rc = lockManager.isItMyLock(p, ids);
329 ASSERT_EQ(0, rc.first);
330}
331
332TEST_F(LockTest, ValidateSessionIDForGetlocklistBadTestCase)
333{
334 MockLock lockManager;
335 // Insert the request1 into the lock table
336 const LockRequests& t = request1;
337 auto rc1 = lockManager.isConflictWithTable(t);
338 std::vector<std::string> sessionid = {"random"};
339 auto status = lockManager.getLockList(sessionid);
340 auto result =
341 std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
342 ASSERT_EQ(0, result.size());
343}
344
345TEST_F(LockTest, ValidateSessionIDForGetlocklistGoodTestCase)
346{
347 MockLock lockManager;
348 // Insert the request1 into the lock table
349 const LockRequests& t = request1;
350 auto rc1 = lockManager.isConflictWithTable(t);
351 std::vector<std::string> sessionid = {"xxxxx"};
352 auto status = lockManager.getLockList(sessionid);
353 auto result =
354 std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
355 ASSERT_EQ(1, result.size());
356}
Sunitha Harish3e919b52020-10-13 01:21:48 -0500357
Nan Zhou38ead5e2022-07-03 23:07:27 +0000358} // namespace
359} // namespace crow::ibm_mc_lock