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