RIC:1060: Change in PTL
[ric-plt/dbaas.git] / redismodule / tst / src / exstrings_nget_test.cpp
1 /*
2  * Copyright (c) 2018-2020 Nokia.
3  *
4  *   Licensed under the Apache License, Version 2.0 (the "License");
5  *   you may not use this file except in compliance with the License.
6  *   You may obtain a copy of the License at
7  *
8  *       http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *   Unless required by applicable law or agreed to in writing, software
11  *   distributed under the License is distributed on an "AS IS" BASIS,
12  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *   See the License for the specific language governing permissions and
14  *   limitations under the License.
15  */
16
17 /*
18  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19  * platform project (RICP).
20  */
21
22 extern "C" {
23 #include "exstringsStub.h"
24 #include "redismodule.h"
25 }
26
27 #include <string.h>
28
29 #include "CppUTest/TestHarness.h"
30 #include "CppUTestExt/MockSupport.h"
31
32 #include "ut_helpers.hpp"
33
34 TEST_GROUP(exstrings_nget)
35 {
36     void setup()
37     {
38         mock().enable();
39         mock().ignoreOtherCalls();
40     }
41
42     void teardown()
43     {
44         mock().clear();
45         mock().disable();
46     }
47
48 };
49
50 void threadDetachedSuccess()
51 {
52     mock().expectOneCall("pthread_detach")
53         .andReturnValue(0);
54 }
55
56 void nKeysFoundMget(long keys)
57 {
58     for (long i = 0 ; i < keys ; i++) {
59         mock().expectOneCall("RedisModule_CreateStringFromCallReply")
60               .andReturnValue(malloc(UT_DUMMY_BUFFER_SIZE));
61         mock().expectNCalls(2, "RedisModule_ReplyWithString");
62     }
63 }
64
65 void nKeysNotFoundMget(long keys)
66 {
67     void* ptr = NULL;
68     mock().expectNCalls(keys, "RedisModule_CreateStringFromCallReply")
69           .andReturnValue(ptr);
70     mock().expectNoCall("RedisModule_ReplyWithString");
71 }
72
73 void expectNReplies(long count)
74 {
75     mock().expectOneCall("RedisModule_ReplySetArrayLength")
76           .withParameter("len", 2*count);
77 }
78
79 void threadSafeContextLockedAndUnlockedEqualTimes()
80 {
81     int locked = mock().getData("TimesThreadSafeContextWasLocked").getIntValue();
82     int unlocked = mock().getData("TimesThreadSafeContextWasUnlocked").getIntValue();
83     CHECK_EQUAL(locked, unlocked);
84 }
85
86 TEST(exstrings_nget, nget_atomic_automemory_enabled)
87 {
88     RedisModuleCtx ctx;
89     RedisModuleString ** redisStrVec = createRedisStrVec(2);
90     long keys_found_with_scan = 0;
91
92     mock().expectOneCall("RedisModule_AutoMemory");
93     mock().expectOneCall("RedisModule_CallReplyLength")
94           .andReturnValue((int)keys_found_with_scan);
95     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  2);
96     mock().checkExpectations();
97     CHECK_EQUAL(ret, REDISMODULE_OK);
98
99     delete []redisStrVec;
100 }
101
102 TEST(exstrings_nget, nget_atomic_command_parameter_number_incorrect)
103 {
104     RedisModuleCtx ctx;
105     RedisModuleString ** redisStrVec = createRedisStrVec(2);
106
107     mock().expectOneCall("RedisModule_WrongArity");
108     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  3);
109     CHECK_EQUAL(ret, REDISMODULE_ERR);
110     mock().checkExpectations();
111
112     delete []redisStrVec;
113 }
114
115 TEST(exstrings_nget, nget_atomic_command_3rd_parameter_was_not_equal_to_COUNT)
116 {
117     RedisModuleCtx ctx;
118     RedisModuleString ** redisStrVec = createRedisStrVec(4);
119     const char * not_count_literal = "NOT_COUNT";
120     size_t not_count_len = strlen(not_count_literal);
121
122     mock().expectOneCall("RedisModule_StringPtrLen")
123           .withOutputParameterReturning("len", &not_count_len, sizeof(size_t))
124           .andReturnValue((void*)not_count_literal);
125     mock().expectOneCall("RedisModule_ReplyWithError");
126     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  4);
127     CHECK_EQUAL(ret, REDISMODULE_ERR);
128     mock().checkExpectations();
129
130     delete []redisStrVec;
131 }
132
133 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_not_integer)
134 {
135     RedisModuleCtx ctx;
136     RedisModuleString ** redisStrVec = createRedisStrVec(4);
137     const char * count_literal = "COUNT";
138     size_t count_len = strlen(count_literal);
139     size_t count_number = 123;
140
141     mock().expectOneCall("RedisModule_StringPtrLen")
142           .withOutputParameterReturning("len", &count_len, sizeof(size_t))
143           .andReturnValue((void*)count_literal);
144     mock().expectOneCall("RedisModule_StringToLongLong")
145           .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
146           .andReturnValue(REDISMODULE_ERR);
147     mock().expectOneCall("RedisModule_ReplyWithError");
148     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  4);
149     CHECK_EQUAL(ret, REDISMODULE_ERR);
150     mock().checkExpectations();
151
152     delete []redisStrVec;
153 }
154
155 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_negative)
156 {
157     RedisModuleCtx ctx;
158     RedisModuleString ** redisStrVec = createRedisStrVec(4);
159     const char * count_literal = "COUNT";
160     size_t count_len = strlen(count_literal);
161     size_t count_number = -123;
162
163     mock().expectOneCall("RedisModule_StringPtrLen")
164           .withOutputParameterReturning("len", &count_len, sizeof(size_t))
165           .andReturnValue((void*)count_literal);
166     mock().expectOneCall("RedisModule_StringToLongLong")
167           .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
168           .andReturnValue(REDISMODULE_OK);
169     mock().expectOneCall("RedisModule_ReplyWithError");
170     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  4);
171     CHECK_EQUAL(ret, REDISMODULE_ERR);
172     mock().checkExpectations();
173
174     delete []redisStrVec;
175 }
176
177 TEST(exstrings_nget, nget_atomic_command_scan_returned_zero_keys)
178 {
179     RedisModuleCtx ctx;
180     RedisModuleString ** redisStrVec = createRedisStrVec(2);
181
182     mock().expectOneCall("RedisModule_ReplyWithArray")
183           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
184     mock().expectOneCall("RedisModule_Call")
185           .withParameter("cmdname", "SCAN");
186     returnNKeysFromScanSome(0);
187     expectNReplies(0);
188     mock().expectNoCall("RedisModule_Call");
189
190     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  2);
191     CHECK_EQUAL(ret, REDISMODULE_OK);
192     mock().checkExpectations();
193
194     delete []redisStrVec;
195 }
196
197 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_0_keys_mget)
198 {
199     RedisModuleCtx ctx;
200     RedisModuleString ** redisStrVec = createRedisStrVec(2);
201
202     mock().ignoreOtherCalls();
203     mock().expectOneCall("RedisModule_ReplyWithArray")
204           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
205
206     mock().expectOneCall("RedisModule_Call")
207           .withParameter("cmdname", "SCAN");
208     returnNKeysFromScanSome(3);
209     mock().expectOneCall("RedisModule_FreeCallReply");
210     mock().expectOneCall("RedisModule_Call")
211           .withParameter("cmdname", "MGET");
212     nKeysNotFoundMget(3);
213     mock().expectOneCall("RedisModule_FreeCallReply");
214     expectNReplies(0);
215     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  2);
216     CHECK_EQUAL(ret, REDISMODULE_OK);
217     mock().checkExpectations();
218
219     delete []redisStrVec;
220 }
221
222 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_3_keys_mget)
223 {
224     RedisModuleCtx ctx;
225     RedisModuleString ** redisStrVec = createRedisStrVec(2);
226
227     mock().ignoreOtherCalls();
228     mock().expectOneCall("RedisModule_ReplyWithArray")
229           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
230     mock().expectOneCall("RedisModule_Call")
231           .withParameter("cmdname", "SCAN");
232     returnNKeysFromScanSome(3);
233     mock().expectOneCall("RedisModule_FreeCallReply");
234     mock().expectOneCall("RedisModule_Call")
235           .withParameter("cmdname", "MGET");
236     nKeysFoundMget(3);
237     mock().expectOneCall("RedisModule_FreeCallReply");
238     expectNReplies(3);
239     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  2);
240     CHECK_EQUAL(ret, REDISMODULE_OK);
241     mock().checkExpectations();
242
243     delete []redisStrVec;
244 }
245
246 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_2_keys_mget)
247 {
248     RedisModuleCtx ctx;
249     RedisModuleString ** redisStrVec = createRedisStrVec(2);
250
251     mock().ignoreOtherCalls();
252     mock().expectOneCall("RedisModule_ReplyWithArray")
253           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
254     mock().expectOneCall("RedisModule_Call")
255           .withParameter("cmdname", "SCAN");
256     returnNKeysFromScanSome(3);
257     mock().expectOneCall("RedisModule_FreeCallReply");
258     mock().expectOneCall("RedisModule_Call")
259           .withParameter("cmdname", "MGET");
260     nKeysFoundMget(2);
261     nKeysNotFoundMget(1);
262     mock().expectOneCall("RedisModule_FreeCallReply");
263     expectNReplies(2);
264     int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec,  2);
265     CHECK_EQUAL(ret, REDISMODULE_OK);
266     mock().checkExpectations();
267
268     delete []redisStrVec;
269 }
270
271 TEST(exstrings_nget, nget_noatomic_automemory_enabled)
272 {
273     RedisModuleCtx ctx;
274     RedisModuleString ** redisStrVec = createRedisStrVec(2);
275
276     mock().setData("pthread_create_free_block_client_args", 1);
277
278     mock().ignoreOtherCalls();
279     mock().expectOneCall("RedisModule_AutoMemory");
280
281     int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec,  2);
282     CHECK_EQUAL(ret, REDISMODULE_OK);
283     mock().checkExpectations();
284
285     delete []redisStrVec;
286 }
287
288 TEST(exstrings_nget, nget_noatomic_thread_create_success)
289 {
290     RedisModuleCtx ctx;
291     RedisModuleString ** redisStrVec = createRedisStrVec(2);
292
293     mock().setData("pthread_create_free_block_client_args", 1);
294
295     mock().ignoreOtherCalls();
296     mock().expectOneCall("RedisModule_BlockClient");
297     mock().expectOneCall("pthread_create");
298     mock().expectNoCall("RedisModule_AbortBlock");
299
300     int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec,  2);
301     CHECK_EQUAL(ret, REDISMODULE_OK);
302     mock().checkExpectations();
303
304     delete []redisStrVec;
305 }
306
307 TEST(exstrings_nget, nget_noatomic_thread_create_fail)
308 {
309     RedisModuleCtx ctx;
310     RedisModuleString ** redisStrVec = createRedisStrVec(2);
311
312     mock().ignoreOtherCalls();
313     mock().expectOneCall("RedisModule_BlockClient");
314     mock().expectOneCall("pthread_create")
315           .andReturnValue(1);
316     mock().expectOneCall("RedisModule_AbortBlock");
317
318     int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec,  2);
319     CHECK_EQUAL(ret, REDISMODULE_OK);
320     mock().checkExpectations();
321
322     delete []redisStrVec;
323 }
324
325 TEST(exstrings_nget, nget_noatomic_parameter_number_incorrect)
326 {
327     RedisModuleCtx ctx;
328     RedisModuleString ** redisStrVec = createRedisStrVec(4);
329
330     mock().expectOneCall("RedisModule_WrongArity");
331     mock().expectNoCall("RedisModule_BlockClient");
332
333     int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec,  3);
334
335     CHECK_EQUAL(ret, REDISMODULE_ERR);
336     mock().checkExpectations();
337
338     delete []redisStrVec;
339 }
340
341 TEST(exstrings_nget, nget_noatomic_threadmain_3rd_parameter_was_not_equal_to_COUNT)
342 {
343     RedisModuleCtx ctx;
344     RedisModuleString ** redisStrVec = createRedisStrVec(4);
345     const char * not_count_literal = "NOT_COUNT";
346     size_t not_count_len = strlen(not_count_literal);
347
348     mock().expectOneCall("RedisModule_StringPtrLen")
349           .withOutputParameterReturning("len", &not_count_len, sizeof(size_t))
350           .andReturnValue((void*)not_count_literal);
351     mock().expectOneCall("RedisModule_ReplyWithError");
352     mock().expectNoCall("RedisModule_BlockClient");
353
354     int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec,  4);
355
356     CHECK_EQUAL(ret, REDISMODULE_ERR);
357
358     mock().checkExpectations();
359     threadSafeContextLockedAndUnlockedEqualTimes();
360
361     delete []redisStrVec;
362 }
363
364 TEST(exstrings_nget, nget_noatomic_4th_parameter_was_not_integer)
365 {
366     RedisModuleCtx ctx;
367     const char * count_literal = "COUNT";
368     size_t count_len = strlen(count_literal);
369     size_t count_number = -123;
370     RedisModuleString ** redisStrVec = createRedisStrVec(4);
371
372     mock().expectOneCall("RedisModule_StringPtrLen")
373           .withOutputParameterReturning("len", &count_len, sizeof(size_t))
374           .andReturnValue((void*)count_literal);
375     mock().expectOneCall("RedisModule_StringToLongLong")
376           .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
377           .andReturnValue(REDISMODULE_OK);
378     mock().expectOneCall("RedisModule_ReplyWithError");
379
380     int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec,  4);
381
382     CHECK_EQUAL(ret, REDISMODULE_ERR);
383     mock().checkExpectations();
384     threadSafeContextLockedAndUnlockedEqualTimes();
385
386     delete []redisStrVec;
387 }
388
389 typedef struct RedisModuleBlockedClientArgs {
390     RedisModuleBlockedClient *bc;
391     RedisModuleString **argv;
392     int argc;
393 } RedisModuleBlockedClientArgs;
394
395 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_3_keys_mget)
396 {
397     RedisModuleCtx ctx;
398     RedisModuleBlockedClientArgs *bca =
399         (RedisModuleBlockedClientArgs*)RedisModule_Alloc(sizeof(RedisModuleBlockedClientArgs));
400     RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
401     RedisModuleString ** redisStrVec = createRedisStrVec(2);
402
403     bca->bc = bc;
404     bca->argv = redisStrVec;
405     bca->argc = 2;
406
407     mock().ignoreOtherCalls();
408     threadDetachedSuccess();
409     mock().expectOneCall("RedisModule_ReplyWithArray")
410           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
411     mock().expectOneCall("RedisModule_Call")
412           .withParameter("cmdname", "SCAN");
413     returnNKeysFromScanSome(3);
414     mock().expectOneCall("RedisModule_FreeCallReply");
415     mock().expectOneCall("RedisModule_Call")
416           .withParameter("cmdname", "MGET");
417     nKeysFoundMget(3);
418     mock().expectOneCall("RedisModule_FreeCallReply");
419     expectNReplies(3);
420     mock().expectOneCall("RedisModule_FreeThreadSafeContext");
421     mock().expectOneCall("RedisModule_UnblockClient");
422
423     NGet_NoAtomic_ThreadMain((void*)bca);
424
425     mock().checkExpectations();
426     threadSafeContextLockedAndUnlockedEqualTimes();
427
428     delete []redisStrVec;
429 }
430
431 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_0_keys_mget)
432 {
433     RedisModuleCtx ctx;
434     RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
435     RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
436     RedisModuleString ** redisStrVec = createRedisStrVec(2);
437
438     bca->bc = bc;
439     bca->argv = redisStrVec;
440     bca->argc = 2;
441
442     mock().ignoreOtherCalls();
443     threadDetachedSuccess();
444     mock().expectOneCall("RedisModule_ReplyWithArray")
445           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
446     mock().expectOneCall("RedisModule_Call")
447           .withParameter("cmdname", "SCAN");
448     returnNKeysFromScanSome(3);
449     mock().expectOneCall("RedisModule_FreeCallReply");
450     mock().expectOneCall("RedisModule_Call")
451           .withParameter("cmdname", "MGET");
452     nKeysNotFoundMget(3);
453     mock().expectOneCall("RedisModule_FreeCallReply");
454     expectNReplies(0);
455     mock().expectOneCall("RedisModule_FreeThreadSafeContext");
456     mock().expectOneCall("RedisModule_UnblockClient");
457
458     NGet_NoAtomic_ThreadMain((void*)bca);
459
460     mock().checkExpectations();
461     threadSafeContextLockedAndUnlockedEqualTimes();
462
463     delete []redisStrVec;
464 }
465
466 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_2_keys_mget)
467 {
468     RedisModuleCtx ctx;
469     RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
470     RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
471     RedisModuleString ** redisStrVec = createRedisStrVec(2);
472
473     bca->bc = bc;
474     bca->argv = redisStrVec;
475     bca->argc = 2;
476
477     mock().ignoreOtherCalls();
478     threadDetachedSuccess();
479     mock().expectOneCall("RedisModule_ReplyWithArray")
480           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
481     mock().expectOneCall("RedisModule_Call")
482           .withParameter("cmdname", "SCAN");
483     returnNKeysFromScanSome(3);
484     mock().expectOneCall("RedisModule_FreeCallReply");
485     mock().expectOneCall("RedisModule_Call")
486           .withParameter("cmdname", "MGET");
487     nKeysNotFoundMget(1);
488     nKeysFoundMget(2);
489     mock().expectOneCall("RedisModule_FreeCallReply");
490     expectNReplies(2);
491     mock().expectOneCall("RedisModule_FreeThreadSafeContext");
492     mock().expectOneCall("RedisModule_UnblockClient");
493
494     NGet_NoAtomic_ThreadMain((void*)bca);
495
496     mock().checkExpectations();
497     threadSafeContextLockedAndUnlockedEqualTimes();
498
499     delete []redisStrVec;
500 }
501
502 TEST(exstrings_nget, nget_noatomic_threadmain_scan_returned_zero_keys)
503 {
504     RedisModuleCtx ctx;
505     RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
506     RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
507     RedisModuleString ** redisStrVec = createRedisStrVec(2);
508
509     bca->bc = bc;
510     bca->argv = redisStrVec;
511     bca->argc = 2;
512
513     mock().ignoreOtherCalls();
514     threadDetachedSuccess();
515     mock().expectOneCall("RedisModule_ReplyWithArray")
516           .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
517     mock().expectOneCall("RedisModule_Call")
518           .withParameter("cmdname", "SCAN");
519     returnNKeysFromScanSome(0);
520     mock().expectOneCall("RedisModule_FreeCallReply");
521     mock().expectNoCall("RedisModule_Call");
522     mock().expectOneCall("RedisModule_FreeThreadSafeContext");
523     mock().expectOneCall("RedisModule_UnblockClient");
524
525     NGet_NoAtomic_ThreadMain((void*)bca);
526
527     mock().checkExpectations();
528     threadSafeContextLockedAndUnlockedEqualTimes();
529
530     delete []redisStrVec;
531 }
532
533 TEST(exstrings_nget, nget_noatomic_threadmain_thread_detached)
534 {
535     RedisModuleCtx ctx;
536     RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
537     RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
538     RedisModuleString ** redisStrVec = createRedisStrVec(2);
539
540     bca->bc = bc;
541     bca->argv = redisStrVec;
542     bca->argc = 2;
543
544     mock().ignoreOtherCalls();
545     threadDetachedSuccess();
546
547     NGet_NoAtomic_ThreadMain((void*)bca);
548
549     mock().checkExpectations();
550
551     delete []redisStrVec;
552 }