2 * Copyright (c) 2018-2020 Nokia.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 * platform project (RICP).
23 #include "exstringsStub.h"
24 #include "redismodule.h"
29 #include "CppUTest/TestHarness.h"
30 #include "CppUTestExt/MockSupport.h"
32 #include "ut_helpers.hpp"
34 TEST_GROUP(exstrings_nget)
39 mock().ignoreOtherCalls();
50 void threadDetachedSuccess()
52 mock().expectOneCall("pthread_detach")
56 void nKeysFoundMget(long keys)
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");
65 void nKeysNotFoundMget(long keys)
68 mock().expectNCalls(keys, "RedisModule_CreateStringFromCallReply")
70 mock().expectNoCall("RedisModule_ReplyWithString");
73 void expectNReplies(long count)
75 mock().expectOneCall("RedisModule_ReplySetArrayLength")
76 .withParameter("len", 2*count);
79 void threadSafeContextLockedAndUnlockedEqualTimes()
81 int locked = mock().getData("TimesThreadSafeContextWasLocked").getIntValue();
82 int unlocked = mock().getData("TimesThreadSafeContextWasUnlocked").getIntValue();
83 CHECK_EQUAL(locked, unlocked);
86 TEST(exstrings_nget, nget_atomic_automemory_enabled)
89 RedisModuleString ** redisStrVec = createRedisStrVec(2);
90 long keys_found_with_scan = 0;
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);
102 TEST(exstrings_nget, nget_atomic_command_parameter_number_incorrect)
105 RedisModuleString ** redisStrVec = createRedisStrVec(2);
107 mock().expectOneCall("RedisModule_WrongArity");
108 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 3);
109 CHECK_EQUAL(ret, REDISMODULE_ERR);
110 mock().checkExpectations();
112 delete []redisStrVec;
115 TEST(exstrings_nget, nget_atomic_command_3rd_parameter_was_not_equal_to_COUNT)
118 RedisModuleString ** redisStrVec = createRedisStrVec(4);
119 const char * not_count_literal = "NOT_COUNT";
120 size_t not_count_len = strlen(not_count_literal);
122 mock().expectOneCall("RedisModule_StringPtrLen")
123 .withOutputParameterReturning("len", ¬_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();
130 delete []redisStrVec;
133 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_not_integer)
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;
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();
152 delete []redisStrVec;
155 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_negative)
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;
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();
174 delete []redisStrVec;
177 TEST(exstrings_nget, nget_atomic_command_scan_returned_zero_keys)
180 RedisModuleString ** redisStrVec = createRedisStrVec(2);
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);
188 mock().expectNoCall("RedisModule_Call");
190 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
191 CHECK_EQUAL(ret, REDISMODULE_OK);
192 mock().checkExpectations();
194 delete []redisStrVec;
197 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_0_keys_mget)
200 RedisModuleString ** redisStrVec = createRedisStrVec(2);
202 mock().ignoreOtherCalls();
203 mock().expectOneCall("RedisModule_ReplyWithArray")
204 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
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");
215 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
216 CHECK_EQUAL(ret, REDISMODULE_OK);
217 mock().checkExpectations();
219 delete []redisStrVec;
222 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_3_keys_mget)
225 RedisModuleString ** redisStrVec = createRedisStrVec(2);
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");
237 mock().expectOneCall("RedisModule_FreeCallReply");
239 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
240 CHECK_EQUAL(ret, REDISMODULE_OK);
241 mock().checkExpectations();
243 delete []redisStrVec;
246 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_2_keys_mget)
249 RedisModuleString ** redisStrVec = createRedisStrVec(2);
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");
261 nKeysNotFoundMget(1);
262 mock().expectOneCall("RedisModule_FreeCallReply");
264 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
265 CHECK_EQUAL(ret, REDISMODULE_OK);
266 mock().checkExpectations();
268 delete []redisStrVec;
271 TEST(exstrings_nget, nget_noatomic_automemory_enabled)
274 RedisModuleString ** redisStrVec = createRedisStrVec(2);
276 mock().setData("pthread_create_free_block_client_args", 1);
278 mock().ignoreOtherCalls();
279 mock().expectOneCall("RedisModule_AutoMemory");
281 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
282 CHECK_EQUAL(ret, REDISMODULE_OK);
283 mock().checkExpectations();
285 delete []redisStrVec;
288 TEST(exstrings_nget, nget_noatomic_thread_create_success)
291 RedisModuleString ** redisStrVec = createRedisStrVec(2);
293 mock().setData("pthread_create_free_block_client_args", 1);
295 mock().ignoreOtherCalls();
296 mock().expectOneCall("RedisModule_BlockClient");
297 mock().expectOneCall("pthread_create");
298 mock().expectNoCall("RedisModule_AbortBlock");
300 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
301 CHECK_EQUAL(ret, REDISMODULE_OK);
302 mock().checkExpectations();
304 delete []redisStrVec;
307 TEST(exstrings_nget, nget_noatomic_thread_create_fail)
310 RedisModuleString ** redisStrVec = createRedisStrVec(2);
312 mock().ignoreOtherCalls();
313 mock().expectOneCall("RedisModule_BlockClient");
314 mock().expectOneCall("pthread_create")
316 mock().expectOneCall("RedisModule_AbortBlock");
318 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
319 CHECK_EQUAL(ret, REDISMODULE_OK);
320 mock().checkExpectations();
322 delete []redisStrVec;
325 TEST(exstrings_nget, nget_noatomic_parameter_number_incorrect)
328 RedisModuleString ** redisStrVec = createRedisStrVec(4);
330 mock().expectOneCall("RedisModule_WrongArity");
331 mock().expectNoCall("RedisModule_BlockClient");
333 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 3);
335 CHECK_EQUAL(ret, REDISMODULE_ERR);
336 mock().checkExpectations();
338 delete []redisStrVec;
341 TEST(exstrings_nget, nget_noatomic_threadmain_3rd_parameter_was_not_equal_to_COUNT)
344 RedisModuleString ** redisStrVec = createRedisStrVec(4);
345 const char * not_count_literal = "NOT_COUNT";
346 size_t not_count_len = strlen(not_count_literal);
348 mock().expectOneCall("RedisModule_StringPtrLen")
349 .withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
350 .andReturnValue((void*)not_count_literal);
351 mock().expectOneCall("RedisModule_ReplyWithError");
352 mock().expectNoCall("RedisModule_BlockClient");
354 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
356 CHECK_EQUAL(ret, REDISMODULE_ERR);
358 mock().checkExpectations();
359 threadSafeContextLockedAndUnlockedEqualTimes();
361 delete []redisStrVec;
364 TEST(exstrings_nget, nget_noatomic_4th_parameter_was_not_integer)
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);
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");
380 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
382 CHECK_EQUAL(ret, REDISMODULE_ERR);
383 mock().checkExpectations();
384 threadSafeContextLockedAndUnlockedEqualTimes();
386 delete []redisStrVec;
389 typedef struct RedisModuleBlockedClientArgs {
390 RedisModuleBlockedClient *bc;
391 RedisModuleString **argv;
393 } RedisModuleBlockedClientArgs;
395 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_3_keys_mget)
398 RedisModuleBlockedClientArgs *bca =
399 (RedisModuleBlockedClientArgs*)RedisModule_Alloc(sizeof(RedisModuleBlockedClientArgs));
400 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
401 RedisModuleString ** redisStrVec = createRedisStrVec(2);
404 bca->argv = redisStrVec;
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");
418 mock().expectOneCall("RedisModule_FreeCallReply");
420 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
421 mock().expectOneCall("RedisModule_UnblockClient");
423 NGet_NoAtomic_ThreadMain((void*)bca);
425 mock().checkExpectations();
426 threadSafeContextLockedAndUnlockedEqualTimes();
428 delete []redisStrVec;
431 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_0_keys_mget)
434 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
435 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
436 RedisModuleString ** redisStrVec = createRedisStrVec(2);
439 bca->argv = redisStrVec;
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");
455 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
456 mock().expectOneCall("RedisModule_UnblockClient");
458 NGet_NoAtomic_ThreadMain((void*)bca);
460 mock().checkExpectations();
461 threadSafeContextLockedAndUnlockedEqualTimes();
463 delete []redisStrVec;
466 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_2_keys_mget)
469 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
470 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
471 RedisModuleString ** redisStrVec = createRedisStrVec(2);
474 bca->argv = redisStrVec;
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);
489 mock().expectOneCall("RedisModule_FreeCallReply");
491 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
492 mock().expectOneCall("RedisModule_UnblockClient");
494 NGet_NoAtomic_ThreadMain((void*)bca);
496 mock().checkExpectations();
497 threadSafeContextLockedAndUnlockedEqualTimes();
499 delete []redisStrVec;
502 TEST(exstrings_nget, nget_noatomic_threadmain_scan_returned_zero_keys)
505 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
506 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
507 RedisModuleString ** redisStrVec = createRedisStrVec(2);
510 bca->argv = redisStrVec;
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");
525 NGet_NoAtomic_ThreadMain((void*)bca);
527 mock().checkExpectations();
528 threadSafeContextLockedAndUnlockedEqualTimes();
530 delete []redisStrVec;
533 TEST(exstrings_nget, nget_noatomic_threadmain_thread_detached)
536 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
537 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
538 RedisModuleString ** redisStrVec = createRedisStrVec(2);
541 bca->argv = redisStrVec;
544 mock().ignoreOtherCalls();
545 threadDetachedSuccess();
547 NGet_NoAtomic_ThreadMain((void*)bca);
549 mock().checkExpectations();
551 delete []redisStrVec;