blob: c27ba689266129b738d6a04bb7f4eaa0d3fe4fff [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:
46 LockTest()
47 {
48 record = {
49 "xxxxx", "hmc-id", "Read", 234, {{"DontLock", 2}, {"DontLock", 4}}};
50 // lockrequest with multiple lockrequests
51 request = {{"xxxxx",
52 "hmc-id",
53 "Read",
54 234,
55 {{"DontLock", 2}, {"DontLock", 4}}},
56 {"xxxxx",
57 "hmc-id",
58 "Read",
59 234,
60 {{"DontLock", 2}, {"DontLock", 4}}}};
61 request1 = {{"xxxxx",
62 "hmc-id",
63 "Read",
64 234,
65 {{"DontLock", 2}, {"DontLock", 4}}}};
66 request2 = {{"xxxxx",
67 "hmc-id",
68 "Write",
69 234,
70 {{"LockAll", 2}, {"DontLock", 4}}}};
71 }
Ed Tanous3174e4d2020-10-07 11:41:22 -070072
73 ~LockTest() override = default;
Ed Tanousecd6a3a2022-01-07 09:18:40 -080074
75 LockTest(const LockTest&) = delete;
76 LockTest(LockTest&&) = delete;
77 LockTest& operator=(const LockTest&) = delete;
78 LockTest& operator=(const LockTest&&) = delete;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053079};
80
81class MockLock : public crow::ibm_mc_lock::Lock
82{
83 public:
Ed Tanousb5a76932020-09-29 16:16:58 -070084 bool isValidLockRequest(const LockRequest& record1) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053085 {
86 bool status = Lock::isValidLockRequest(record1);
87 return status;
88 }
Ed Tanousb5a76932020-09-29 16:16:58 -070089 bool isConflictRequest(const LockRequests& request) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053090 {
91 bool status = Lock::isConflictRequest(request);
92 return status;
93 }
Ed Tanousb5a76932020-09-29 16:16:58 -070094 Rc isConflictWithTable(const LockRequests& request) override
manojkiraneda4eaf2ee2019-12-13 17:10:41 +053095 {
96 auto conflict = Lock::isConflictWithTable(request);
97 return conflict;
98 }
99 uint32_t generateTransactionId() override
100 {
101 uint32_t tid = Lock::generateTransactionId();
102 return tid;
103 }
104
105 bool validateRids(const ListOfTransactionIds& tids) override
106 {
107 bool status = Lock::validateRids(tids);
108 return status;
109 }
110 RcRelaseLock isItMyLock(const ListOfTransactionIds& tids,
111 const SessionFlags& ids) override
112 {
113 auto status = Lock::isItMyLock(tids, ids);
114 return status;
115 }
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530116 friend class LockTest;
117};
118
119TEST_F(LockTest, ValidationGoodTestCase)
120{
121 MockLock lockManager;
122 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000123 EXPECT_TRUE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530124}
125
126TEST_F(LockTest, ValidationBadTestWithLocktype)
127{
128 MockLock lockManager;
129 // Corrupt the lock type
130 std::get<2>(record) = "rwrite";
131 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000132 EXPECT_FALSE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530133}
134
135TEST_F(LockTest, ValidationBadTestWithlockFlags)
136{
137 MockLock lockManager;
138 // Corrupt the lockflag
139 std::get<4>(record)[0].first = "lock";
140 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000141 EXPECT_FALSE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530142}
143
144TEST_F(LockTest, ValidationBadTestWithSegmentlength)
145{
146 MockLock lockManager;
147 // Corrupt the Segment length
148 std::get<4>(record)[0].second = 7;
149 const LockRequest& t = record;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000150 EXPECT_FALSE(lockManager.isValidLockRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530151}
152
153TEST_F(LockTest, MultiRequestWithoutConflict)
154{
155 MockLock lockManager;
156 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000157 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530158}
159
160TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentLength)
161{
162 MockLock lockManager;
163 // Corrupt the locktype
164 std::get<2>(request[0]) = "Write";
165 // Match the segment lengths to points them to lock similar kind of
166 // resource
167 std::get<4>(request[0])[0].first = "LockAll";
168 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000169 EXPECT_TRUE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530170}
171
172TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentData)
173{
174 MockLock lockManager;
175 // Corrupt the locktype
176 std::get<2>(request[0]) = "Write";
177 // Match the segment lengths to points them to lock similar kind of
178 // resource
179 std::get<4>(request[0])[0].first = "DontLock";
180 std::get<4>(request[0])[1].first = "LockAll";
181
182 // Change the resource id(2nd byte) of first record, so the locks are
183 // different so no conflict
184 std::get<3>(request[0]) = 216179379183550464; // HEX 03 00 06 00 00 00 00 00
185 std::get<3>(request[1]) = 288236973221478400; // HEX 04 00 06 00 00 00 00 00
186 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000187 EXPECT_FALSE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530188}
189
190TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentData)
191{
192 MockLock lockManager;
193 // Corrupt the locktype
194 std::get<2>(request[0]) = "Write";
195 // Match the segment lengths to points them to lock similar kind of
196 // resource
197 std::get<4>(request[0])[0].first = "DontLock";
198 std::get<4>(request[0])[1].first = "LockAll";
Nan Zhoub5a10a22022-07-04 01:18:14 +0000199 // Dont Change the resource id(1st & 2nd byte) at all, so that the
200 // conflict occurs from the second segment which is trying to lock all
201 // the resources.
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530202 std::get<3>(request[0]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
203 std::get<3>(request[1]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
204 const LockRequests& t = request;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000205 EXPECT_TRUE(lockManager.isConflictRequest(t));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530206}
207
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
247TEST_F(LockTest, RequestConflictedWithLockTableEntries)
248{
249 MockLock lockManager;
250 const LockRequests& t = request1;
251 auto rc1 = lockManager.isConflictWithTable(t);
252 // Corrupt the lock type
253 std::get<2>(request[0]) = "Write";
254 // Corrupt the lockflag
255 std::get<4>(request[0])[1].first = "LockAll";
256 const LockRequests& p = request;
257 auto rc2 = lockManager.isConflictWithTable(p);
258 // Return a Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000259 EXPECT_TRUE(rc2.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530260}
261
262TEST_F(LockTest, RequestNotConflictedWithLockTableEntries)
263{
264 MockLock lockManager;
265 const LockRequests& t = request1;
266 // Insert the request1 into the lock table
267 auto rc1 = lockManager.isConflictWithTable(t);
268 // Corrupt the lock type
269 std::get<2>(request[0]) = "Read";
270 // Corrupt the lockflag
271 std::get<4>(request[0])[1].first = "LockAll";
272 const LockRequests& p = request;
273 auto rc2 = lockManager.isConflictWithTable(p);
274 // Return No Conflict
Nan Zhoub5a10a22022-07-04 01:18:14 +0000275 EXPECT_FALSE(rc2.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530276}
277
278TEST_F(LockTest, TestGenerateTransactionIDFunction)
279{
280 MockLock lockManager;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000281 uint32_t transactionId1 = lockManager.generateTransactionId();
282 uint32_t transactionId2 = lockManager.generateTransactionId();
283 EXPECT_EQ(transactionId2, ++transactionId1);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530284}
285
286TEST_F(LockTest, ValidateTransactionIDsGoodTestCase)
287{
288 MockLock lockManager;
289 const LockRequests& t = request1;
290 // Insert the request1 into the lock table
291 auto rc1 = lockManager.isConflictWithTable(t);
292 std::vector<uint32_t> tids = {1};
293 const std::vector<uint32_t>& p = tids;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000294 EXPECT_TRUE(lockManager.validateRids(p));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530295}
296
297TEST_F(LockTest, ValidateTransactionIDsBadTestCase)
298{
299 MockLock lockManager;
300 // Insert the request1 into the lock table
301 const LockRequests& t = request1;
302 auto rc1 = lockManager.isConflictWithTable(t);
Sunitha Harish3e919b52020-10-13 01:21:48 -0500303 std::vector<uint32_t> tids = {10};
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530304 const std::vector<uint32_t>& p = tids;
Nan Zhoub5a10a22022-07-04 01:18:14 +0000305 EXPECT_FALSE(lockManager.validateRids(p));
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530306}
307
308TEST_F(LockTest, ValidateisItMyLockGoodTestCase)
309{
310 MockLock lockManager;
311 // Insert the request1 into the lock table
312 const LockRequests& t = request1;
313 auto rc1 = lockManager.isConflictWithTable(t);
314 std::vector<uint32_t> tids = {1};
315 const std::vector<uint32_t>& p = tids;
316 std::string hmcid = "hmc-id";
317 std::string sessionid = "xxxxx";
318 std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
319 auto rc = lockManager.isItMyLock(p, ids);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000320 EXPECT_TRUE(rc.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530321}
322
323TEST_F(LockTest, ValidateisItMyLockBadTestCase)
324{
325 MockLock lockManager;
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530326 // Corrupt the client identifier
327 std::get<1>(request1[0]) = "randomid";
328 // Insert the request1 into the lock table
329 const LockRequests& t = request1;
330 auto rc1 = lockManager.isConflictWithTable(t);
331 std::vector<uint32_t> tids = {1};
332 const std::vector<uint32_t>& p = tids;
333 std::string hmcid = "hmc-id";
Sunitha Harish3e919b52020-10-13 01:21:48 -0500334 std::string sessionid = "random";
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530335 std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
336 auto rc = lockManager.isItMyLock(p, ids);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000337 EXPECT_FALSE(rc.first);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530338}
339
340TEST_F(LockTest, ValidateSessionIDForGetlocklistBadTestCase)
341{
342 MockLock lockManager;
343 // Insert the request1 into the lock table
344 const LockRequests& t = request1;
345 auto rc1 = lockManager.isConflictWithTable(t);
346 std::vector<std::string> sessionid = {"random"};
347 auto status = lockManager.getLockList(sessionid);
348 auto result =
349 std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000350 EXPECT_THAT(result, IsEmpty());
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530351}
352
353TEST_F(LockTest, ValidateSessionIDForGetlocklistGoodTestCase)
354{
355 MockLock lockManager;
356 // Insert the request1 into the lock table
357 const LockRequests& t = request1;
358 auto rc1 = lockManager.isConflictWithTable(t);
359 std::vector<std::string> sessionid = {"xxxxx"};
360 auto status = lockManager.getLockList(sessionid);
361 auto result =
362 std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
Nan Zhoub5a10a22022-07-04 01:18:14 +0000363 EXPECT_EQ(result.size(), 1);
manojkiraneda4eaf2ee2019-12-13 17:10:41 +0530364}
Sunitha Harish3e919b52020-10-13 01:21:48 -0500365
Nan Zhou38ead5e2022-07-03 23:07:27 +0000366} // namespace
367} // namespace crow::ibm_mc_lock