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