blob: 327ce6869cc11efd35cf1181f7797dca5b575824 [file] [log] [blame]
manojkiraneda4eaf2ee2019-12-13 17:10:41 +05301#include "ibm/locks.hpp"
manojkiraneda4eaf2ee2019-12-13 17:10:41 +05302
Nan Zhoud5c80ad2022-07-11 01:16:31 +00003#include <cstdint>
4#include <memory>
Gunnar Mills1214b7e2020-06-04 10:11:30 -05005#include <string>
Nan Zhoud5c80ad2022-07-11 01:16:31 +00006#include <tuple>
7#include <utility>
8#include <variant>
9#include <vector>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050010
Nan Zhoud5c80ad2022-07-11 01:16:31 +000011#include <gmock/gmock.h> // IWYU pragma: keep
12#include <gtest/gtest.h> // IWYU pragma: keep
13
14// IWYU pragma: no_include <gtest/gtest-message.h>
15// IWYU pragma: no_include <gtest/gtest-test-part.h>
16// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053017
Nan Zhou38ead5e2022-07-03 23:07:27 +000018namespace crow::ibm_mc_lock
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053019{
Nan Zhou38ead5e2022-07-03 23:07:27 +000020namespace
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053021{
Nan Zhou38ead5e2022-07-03 23:07:27 +000022
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053023using SType = std::string;
24using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
25using LockRequests = std::vector<LockRequest>;
26using Rc =
27 std::pair<bool, std::variant<uint32_t, std::pair<uint32_t, LockRequest>>>;
28using RcRelaseLock = std::pair<bool, std::pair<uint32_t, LockRequest>>;
29using RcGetLockList =
30 std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
31using ListOfTransactionIds = std::vector<uint32_t>;
32using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>;
33using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>;
34using SessionFlags = std::pair<SType, SType>;
35using ListOfSessionIds = std::vector<std::string>;
Nan Zhoub5a10a22022-07-04 01:18:14 +000036using ::testing::IsEmpty;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053037
38class LockTest : public ::testing::Test
39{
40 protected:
41 LockRequests request;
42 LockRequests request1, request2;
43 LockRequest record;
44
45 public:
Ed Tanousb31cef62022-06-30 17:51:46 -070046 LockTest() :
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053047 // lockrequest with multiple lockrequests
Ed Tanousb31cef62022-06-30 17:51:46 -070048 request{{"xxxxx",
49 "hmc-id",
50 "Read",
51 234,
52 {{"DontLock", 2}, {"DontLock", 4}}},
53 {"xxxxx",
54 "hmc-id",
55 "Read",
56 234,
57 {{"DontLock", 2}, {"DontLock", 4}}}},
58 request1{{"xxxxx",
59 "hmc-id",
60 "Read",
61 234,
62 {{"DontLock", 2}, {"DontLock", 4}}}},
63 request2{{"xxxxx",
64 "hmc-id",
65 "Write",
66 234,
67 {{"LockAll", 2}, {"DontLock", 4}}}},
68 record{
69 "xxxxx", "hmc-id", "Read", 234, {{"DontLock", 2}, {"DontLock", 4}}}
70 {}
Ed Tanous3174e4d2020-10-07 11:41:22 -070071
72 ~LockTest() override = default;
Ed Tanousecd6a3a2022-01-07 09:18:40 -080073
74 LockTest(const LockTest&) = delete;
75 LockTest(LockTest&&) = delete;
76 LockTest& operator=(const LockTest&) = delete;
77 LockTest& operator=(const LockTest&&) = delete;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053078};
79
80class MockLock : public crow::ibm_mc_lock::Lock
81{
82 public:
Ed Tanousb5a76932020-09-29 16:16:58 -070083 bool isValidLockRequest(const LockRequest& record1) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053084 {
85 bool status = Lock::isValidLockRequest(record1);
86 return status;
87 }
Ed Tanousb5a76932020-09-29 16:16:58 -070088 bool isConflictRequest(const LockRequests& request) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053089 {
90 bool status = Lock::isConflictRequest(request);
91 return status;
92 }
Ed Tanousb5a76932020-09-29 16:16:58 -070093 Rc isConflictWithTable(const LockRequests& request) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053094 {
95 auto conflict = Lock::isConflictWithTable(request);
96 return conflict;
97 }
98 uint32_t generateTransactionId() override
99 {
100 uint32_t tid = Lock::generateTransactionId();
101 return tid;
102 }
103
104 bool validateRids(const ListOfTransactionIds& tids) override
105 {
106 bool status = Lock::validateRids(tids);
107 return status;
108 }
109 RcRelaseLock isItMyLock(const ListOfTransactionIds& tids,
110 const SessionFlags& ids) override
111 {
112 auto status = Lock::isItMyLock(tids, ids);
113 return status;
114 }
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530115 friend class LockTest;
116};
117
118TEST_F(LockTest, ValidationGoodTestCase)
119{
120 MockLock lockManager;
121 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000122 EXPECT_TRUE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530123}
124
125TEST_F(LockTest, ValidationBadTestWithLocktype)
126{
127 MockLock lockManager;
128 // Corrupt the lock type
129 std::get<2>(record) = "rwrite";
130 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000131 EXPECT_FALSE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530132}
133
134TEST_F(LockTest, ValidationBadTestWithlockFlags)
135{
136 MockLock lockManager;
137 // Corrupt the lockflag
138 std::get<4>(record)[0].first = "lock";
139 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000140 EXPECT_FALSE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530141}
142
143TEST_F(LockTest, ValidationBadTestWithSegmentlength)
144{
145 MockLock lockManager;
146 // Corrupt the Segment length
147 std::get<4>(record)[0].second = 7;
148 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000149 EXPECT_FALSE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530150}
151
152TEST_F(LockTest, MultiRequestWithoutConflict)
153{
154 MockLock lockManager;
155 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000156 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530157}
158
159TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentLength)
160{
161 MockLock lockManager;
162 // Corrupt the locktype
163 std::get<2>(request[0]) = "Write";
164 // Match the segment lengths to points them to lock similar kind of
165 // resource
166 std::get<4>(request[0])[0].first = "LockAll";
167 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000168 EXPECT_TRUE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530169}
Patrick Williams26b36302023-05-10 17:29:00 -0500170#if 0 // Comment out due to bad code in include/ibm/locks.hpp
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530171TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentData)
172{
173 MockLock lockManager;
174 // Corrupt the locktype
175 std::get<2>(request[0]) = "Write";
176 // Match the segment lengths to points them to lock similar kind of
177 // resource
178 std::get<4>(request[0])[0].first = "DontLock";
179 std::get<4>(request[0])[1].first = "LockAll";
180
181 // Change the resource id(2nd byte) of first record, so the locks are
182 // different so no conflict
183 std::get<3>(request[0]) = 216179379183550464; // HEX 03 00 06 00 00 00 00 00
184 std::get<3>(request[1]) = 288236973221478400; // HEX 04 00 06 00 00 00 00 00
185 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000186 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530187}
188
189TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentData)
190{
191 MockLock lockManager;
192 // Corrupt the locktype
193 std::get<2>(request[0]) = "Write";
194 // Match the segment lengths to points them to lock similar kind of
195 // resource
196 std::get<4>(request[0])[0].first = "DontLock";
197 std::get<4>(request[0])[1].first = "LockAll";
Nan Zhoub5a10a22022-07-04 01:18:14 +0000198 // Dont Change the resource id(1st & 2nd byte) at all, so that the
199 // conflict occurs from the second segment which is trying to lock all
200 // the resources.
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530201 std::get<3>(request[0]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
202 std::get<3>(request[1]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
203 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000204 EXPECT_TRUE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530205}
Patrick Williams26b36302023-05-10 17:29:00 -0500206#endif
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530207
208TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentLength)
209{
210 MockLock lockManager;
211 // Corrupt the locktype
212 std::get<2>(request[0]) = "Write";
213 // Match the segment lengths to points them to lock similar kind of
214 // resource
215 std::get<4>(request[0])[0].first = "LockSame";
216 // Change the segment length , so that the requests are trying to lock
217 // two different kind of resources
218 std::get<4>(request[0])[0].second = 3;
219 const LockRequests& t = request;
220 // Return No Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000221 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530222}
223
224TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktype)
225{
226 MockLock lockManager;
227 // Match the segment lengths to points them to lock similar kind of
228 // resource
229 std::get<4>(request[0])[0].first = "LockAll";
230 const LockRequests& t = request;
231 // Return No Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000232 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530233}
234
235TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktypeAndLockall)
236{
237 MockLock lockManager;
238 // Match the segment lengths to points them to lock similar kind of
239 // resource
240 std::get<4>(request[0])[0].first = "LockAll";
241 std::get<4>(request[0])[1].first = "LockAll";
242 const LockRequests& t = request;
243 // Return No Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000244 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530245}
246
Patrick Williams26b36302023-05-10 17:29:00 -0500247#if 0 // Comment out due to bad code in include/ibm/locks.hpp
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530248TEST_F(LockTest, RequestConflictedWithLockTableEntries)
249{
250 MockLock lockManager;
251 const LockRequests& t = request1;
252 auto rc1 = lockManager.isConflictWithTable(t);
253 // Corrupt the lock type
254 std::get<2>(request[0]) = "Write";
255 // Corrupt the lockflag
256 std::get<4>(request[0])[1].first = "LockAll";
257 const LockRequests& p = request;
258 auto rc2 = lockManager.isConflictWithTable(p);
259 // Return a Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000260 EXPECT_TRUE(rc2.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530261}
Patrick Williams26b36302023-05-10 17:29:00 -0500262#endif
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530263
264TEST_F(LockTest, RequestNotConflictedWithLockTableEntries)
265{
266 MockLock lockManager;
267 const LockRequests& t = request1;
268 // Insert the request1 into the lock table
269 auto rc1 = lockManager.isConflictWithTable(t);
270 // Corrupt the lock type
271 std::get<2>(request[0]) = "Read";
272 // Corrupt the lockflag
273 std::get<4>(request[0])[1].first = "LockAll";
274 const LockRequests& p = request;
275 auto rc2 = lockManager.isConflictWithTable(p);
276 // Return No Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000277 EXPECT_FALSE(rc2.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530278}
279
280TEST_F(LockTest, TestGenerateTransactionIDFunction)
281{
282 MockLock lockManager;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000283 uint32_t transactionId1 = lockManager.generateTransactionId();
284 uint32_t transactionId2 = lockManager.generateTransactionId();
285 EXPECT_EQ(transactionId2, ++transactionId1);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530286}
287
288TEST_F(LockTest, ValidateTransactionIDsGoodTestCase)
289{
290 MockLock lockManager;
291 const LockRequests& t = request1;
292 // Insert the request1 into the lock table
293 auto rc1 = lockManager.isConflictWithTable(t);
294 std::vector<uint32_t> tids = {1};
295 const std::vector<uint32_t>& p = tids;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000296 EXPECT_TRUE(lockManager.validateRids(p));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530297}
298
299TEST_F(LockTest, ValidateTransactionIDsBadTestCase)
300{
301 MockLock lockManager;
302 // Insert the request1 into the lock table
303 const LockRequests& t = request1;
304 auto rc1 = lockManager.isConflictWithTable(t);
Sunitha Harish3e919b52020-10-13 01:21:48 -0500305 std::vector<uint32_t> tids = {10};
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530306 const std::vector<uint32_t>& p = tids;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000307 EXPECT_FALSE(lockManager.validateRids(p));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530308}
309
310TEST_F(LockTest, ValidateisItMyLockGoodTestCase)
311{
312 MockLock lockManager;
313 // Insert the request1 into the lock table
314 const LockRequests& t = request1;
315 auto rc1 = lockManager.isConflictWithTable(t);
316 std::vector<uint32_t> tids = {1};
317 const std::vector<uint32_t>& p = tids;
318 std::string hmcid = "hmc-id";
319 std::string sessionid = "xxxxx";
320 std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
321 auto rc = lockManager.isItMyLock(p, ids);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000322 EXPECT_TRUE(rc.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530323}
324
325TEST_F(LockTest, ValidateisItMyLockBadTestCase)
326{
327 MockLock lockManager;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530328 // Corrupt the client identifier
329 std::get<1>(request1[0]) = "randomid";
330 // Insert the request1 into the lock table
331 const LockRequests& t = request1;
332 auto rc1 = lockManager.isConflictWithTable(t);
333 std::vector<uint32_t> tids = {1};
334 const std::vector<uint32_t>& p = tids;
335 std::string hmcid = "hmc-id";
Sunitha Harish3e919b52020-10-13 01:21:48 -0500336 std::string sessionid = "random";
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530337 std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
338 auto rc = lockManager.isItMyLock(p, ids);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000339 EXPECT_FALSE(rc.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530340}
341
342TEST_F(LockTest, ValidateSessionIDForGetlocklistBadTestCase)
343{
344 MockLock lockManager;
345 // Insert the request1 into the lock table
346 const LockRequests& t = request1;
347 auto rc1 = lockManager.isConflictWithTable(t);
348 std::vector<std::string> sessionid = {"random"};
349 auto status = lockManager.getLockList(sessionid);
350 auto result =
351 std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000352 EXPECT_THAT(result, IsEmpty());
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530353}
354
355TEST_F(LockTest, ValidateSessionIDForGetlocklistGoodTestCase)
356{
357 MockLock lockManager;
358 // Insert the request1 into the lock table
359 const LockRequests& t = request1;
360 auto rc1 = lockManager.isConflictWithTable(t);
361 std::vector<std::string> sessionid = {"xxxxx"};
362 auto status = lockManager.getLockList(sessionid);
363 auto result =
364 std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000365 EXPECT_EQ(result.size(), 1);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530366}
Sunitha Harish3e919b52020-10-13 01:21:48 -0500367
Nan Zhou38ead5e2022-07-03 23:07:27 +0000368} // namespace
369} // namespace crow::ibm_mc_lock