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 nKeysFoundMget(long keys)
52 for (long i = 0 ; i < keys ; i++) {
53 mock().expectOneCall("RedisModule_CreateStringFromCallReply")
54 .andReturnValue(malloc(UT_DUMMY_BUFFER_SIZE));
55 mock().expectNCalls(2, "RedisModule_ReplyWithString");
59 void nKeysNotFoundMget(long keys)
62 mock().expectNCalls(keys, "RedisModule_CreateStringFromCallReply")
64 mock().expectNoCall("RedisModule_ReplyWithString");
67 void expectNReplies(long count)
69 mock().expectOneCall("RedisModule_ReplySetArrayLength")
70 .withParameter("len", 2*count);
73 void threadSafeContextLockedAndUnlockedEqualTimes()
75 int locked = mock().getData("TimesThreadSafeContextWasLocked").getIntValue();
76 int unlocked = mock().getData("TimesThreadSafeContextWasUnlocked").getIntValue();
77 CHECK_EQUAL(locked, unlocked);
80 TEST(exstrings_nget, nget_atomic_automemory_enabled)
83 RedisModuleString ** redisStrVec = createRedisStrVec(2);
84 long keys_found_with_scan = 0;
86 mock().expectOneCall("RedisModule_AutoMemory");
87 mock().expectOneCall("RedisModule_CallReplyLength")
88 .andReturnValue((int)keys_found_with_scan);
89 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
90 mock().checkExpectations();
91 CHECK_EQUAL(ret, REDISMODULE_OK);
96 TEST(exstrings_nget, nget_atomic_command_parameter_number_incorrect)
99 RedisModuleString ** redisStrVec = createRedisStrVec(2);
101 mock().expectOneCall("RedisModule_WrongArity");
102 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 3);
103 CHECK_EQUAL(ret, REDISMODULE_ERR);
104 mock().checkExpectations();
106 delete []redisStrVec;
109 TEST(exstrings_nget, nget_atomic_command_3rd_parameter_was_not_equal_to_COUNT)
112 RedisModuleString ** redisStrVec = createRedisStrVec(4);
113 const char * not_count_literal = "NOT_COUNT";
114 size_t not_count_len = strlen(not_count_literal);
116 mock().expectOneCall("RedisModule_StringPtrLen")
117 .withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
118 .andReturnValue((void*)not_count_literal);
119 mock().expectOneCall("RedisModule_ReplyWithError");
120 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
121 CHECK_EQUAL(ret, REDISMODULE_ERR);
122 mock().checkExpectations();
124 delete []redisStrVec;
127 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_not_integer)
130 RedisModuleString ** redisStrVec = createRedisStrVec(4);
131 const char * count_literal = "COUNT";
132 size_t count_len = strlen(count_literal);
133 size_t count_number = 123;
135 mock().expectOneCall("RedisModule_StringPtrLen")
136 .withOutputParameterReturning("len", &count_len, sizeof(size_t))
137 .andReturnValue((void*)count_literal);
138 mock().expectOneCall("RedisModule_StringToLongLong")
139 .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
140 .andReturnValue(REDISMODULE_ERR);
141 mock().expectOneCall("RedisModule_ReplyWithError");
142 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
143 CHECK_EQUAL(ret, REDISMODULE_ERR);
144 mock().checkExpectations();
146 delete []redisStrVec;
149 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_negative)
152 RedisModuleString ** redisStrVec = createRedisStrVec(4);
153 const char * count_literal = "COUNT";
154 size_t count_len = strlen(count_literal);
155 size_t count_number = -123;
157 mock().expectOneCall("RedisModule_StringPtrLen")
158 .withOutputParameterReturning("len", &count_len, sizeof(size_t))
159 .andReturnValue((void*)count_literal);
160 mock().expectOneCall("RedisModule_StringToLongLong")
161 .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
162 .andReturnValue(REDISMODULE_OK);
163 mock().expectOneCall("RedisModule_ReplyWithError");
164 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
165 CHECK_EQUAL(ret, REDISMODULE_ERR);
166 mock().checkExpectations();
168 delete []redisStrVec;
171 TEST(exstrings_nget, nget_atomic_command_scan_returned_zero_keys)
174 RedisModuleString ** redisStrVec = createRedisStrVec(2);
176 mock().expectOneCall("RedisModule_ReplyWithArray")
177 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
178 mock().expectOneCall("RedisModule_Call")
179 .withParameter("cmdname", "SCAN");
180 returnNKeysFromScanSome(0);
182 mock().expectNoCall("RedisModule_Call");
184 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
185 CHECK_EQUAL(ret, REDISMODULE_OK);
186 mock().checkExpectations();
188 delete []redisStrVec;
191 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_0_keys_mget)
194 RedisModuleString ** redisStrVec = createRedisStrVec(2);
196 mock().ignoreOtherCalls();
197 mock().expectOneCall("RedisModule_ReplyWithArray")
198 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
200 mock().expectOneCall("RedisModule_Call")
201 .withParameter("cmdname", "SCAN");
202 returnNKeysFromScanSome(3);
203 mock().expectOneCall("RedisModule_FreeCallReply");
204 mock().expectOneCall("RedisModule_Call")
205 .withParameter("cmdname", "MGET");
206 nKeysNotFoundMget(3);
207 mock().expectOneCall("RedisModule_FreeCallReply");
209 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
210 CHECK_EQUAL(ret, REDISMODULE_OK);
211 mock().checkExpectations();
213 delete []redisStrVec;
216 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_3_keys_mget)
219 RedisModuleString ** redisStrVec = createRedisStrVec(2);
221 mock().ignoreOtherCalls();
222 mock().expectOneCall("RedisModule_ReplyWithArray")
223 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
224 mock().expectOneCall("RedisModule_Call")
225 .withParameter("cmdname", "SCAN");
226 returnNKeysFromScanSome(3);
227 mock().expectOneCall("RedisModule_FreeCallReply");
228 mock().expectOneCall("RedisModule_Call")
229 .withParameter("cmdname", "MGET");
231 mock().expectOneCall("RedisModule_FreeCallReply");
233 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
234 CHECK_EQUAL(ret, REDISMODULE_OK);
235 mock().checkExpectations();
237 delete []redisStrVec;
240 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_2_keys_mget)
243 RedisModuleString ** redisStrVec = createRedisStrVec(2);
245 mock().ignoreOtherCalls();
246 mock().expectOneCall("RedisModule_ReplyWithArray")
247 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
248 mock().expectOneCall("RedisModule_Call")
249 .withParameter("cmdname", "SCAN");
250 returnNKeysFromScanSome(3);
251 mock().expectOneCall("RedisModule_FreeCallReply");
252 mock().expectOneCall("RedisModule_Call")
253 .withParameter("cmdname", "MGET");
255 nKeysNotFoundMget(1);
256 mock().expectOneCall("RedisModule_FreeCallReply");
258 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
259 CHECK_EQUAL(ret, REDISMODULE_OK);
260 mock().checkExpectations();
262 delete []redisStrVec;
265 TEST(exstrings_nget, nget_noatomic_automemory_enabled)
268 RedisModuleString ** redisStrVec = createRedisStrVec(2);
270 mock().setData("pthread_create_free_block_client_args", 1);
272 mock().ignoreOtherCalls();
273 mock().expectOneCall("RedisModule_AutoMemory");
275 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
276 CHECK_EQUAL(ret, REDISMODULE_OK);
277 mock().checkExpectations();
279 delete []redisStrVec;
282 TEST(exstrings_nget, nget_noatomic_thread_create_success)
285 RedisModuleString ** redisStrVec = createRedisStrVec(2);
287 mock().setData("pthread_create_free_block_client_args", 1);
289 mock().ignoreOtherCalls();
290 mock().expectOneCall("RedisModule_BlockClient");
291 mock().expectOneCall("pthread_create");
292 mock().expectNoCall("RedisModule_AbortBlock");
294 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
295 CHECK_EQUAL(ret, REDISMODULE_OK);
296 mock().checkExpectations();
298 delete []redisStrVec;
301 TEST(exstrings_nget, nget_noatomic_thread_create_fail)
304 RedisModuleString ** redisStrVec = createRedisStrVec(2);
306 mock().ignoreOtherCalls();
307 mock().expectOneCall("RedisModule_BlockClient");
308 mock().expectOneCall("pthread_create")
310 mock().expectOneCall("RedisModule_AbortBlock");
312 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
313 CHECK_EQUAL(ret, REDISMODULE_OK);
314 mock().checkExpectations();
316 delete []redisStrVec;
319 TEST(exstrings_nget, nget_noatomic_parameter_number_incorrect)
322 RedisModuleString ** redisStrVec = createRedisStrVec(4);
324 mock().expectOneCall("RedisModule_WrongArity");
325 mock().expectNoCall("RedisModule_BlockClient");
327 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 3);
329 CHECK_EQUAL(ret, REDISMODULE_ERR);
330 mock().checkExpectations();
332 delete []redisStrVec;
335 TEST(exstrings_nget, nget_noatomic_threadmain_3rd_parameter_was_not_equal_to_COUNT)
338 RedisModuleString ** redisStrVec = createRedisStrVec(4);
339 const char * not_count_literal = "NOT_COUNT";
340 size_t not_count_len = strlen(not_count_literal);
342 mock().expectOneCall("RedisModule_StringPtrLen")
343 .withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
344 .andReturnValue((void*)not_count_literal);
345 mock().expectOneCall("RedisModule_ReplyWithError");
346 mock().expectNoCall("RedisModule_BlockClient");
348 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
350 CHECK_EQUAL(ret, REDISMODULE_ERR);
352 mock().checkExpectations();
353 threadSafeContextLockedAndUnlockedEqualTimes();
355 delete []redisStrVec;
358 TEST(exstrings_nget, nget_noatomic_4th_parameter_was_not_integer)
361 const char * count_literal = "COUNT";
362 size_t count_len = strlen(count_literal);
363 size_t count_number = -123;
364 RedisModuleString ** redisStrVec = createRedisStrVec(4);
366 mock().expectOneCall("RedisModule_StringPtrLen")
367 .withOutputParameterReturning("len", &count_len, sizeof(size_t))
368 .andReturnValue((void*)count_literal);
369 mock().expectOneCall("RedisModule_StringToLongLong")
370 .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
371 .andReturnValue(REDISMODULE_OK);
372 mock().expectOneCall("RedisModule_ReplyWithError");
374 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
376 CHECK_EQUAL(ret, REDISMODULE_ERR);
377 mock().checkExpectations();
378 threadSafeContextLockedAndUnlockedEqualTimes();
380 delete []redisStrVec;
383 typedef struct RedisModuleBlockedClientArgs {
384 RedisModuleBlockedClient *bc;
385 RedisModuleString **argv;
387 } RedisModuleBlockedClientArgs;
389 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_3_keys_mget)
392 RedisModuleBlockedClientArgs *bca =
393 (RedisModuleBlockedClientArgs*)RedisModule_Alloc(sizeof(RedisModuleBlockedClientArgs));
394 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
395 RedisModuleString ** redisStrVec = createRedisStrVec(2);
398 bca->argv = redisStrVec;
401 mock().ignoreOtherCalls();
402 mock().expectOneCall("RedisModule_ReplyWithArray")
403 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
404 mock().expectOneCall("RedisModule_Call")
405 .withParameter("cmdname", "SCAN");
406 returnNKeysFromScanSome(3);
407 mock().expectOneCall("RedisModule_FreeCallReply");
408 mock().expectOneCall("RedisModule_Call")
409 .withParameter("cmdname", "MGET");
411 mock().expectOneCall("RedisModule_FreeCallReply");
413 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
414 mock().expectOneCall("RedisModule_UnblockClient");
416 NGet_NoAtomic_ThreadMain((void*)bca);
418 mock().checkExpectations();
419 threadSafeContextLockedAndUnlockedEqualTimes();
421 delete []redisStrVec;
424 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_0_keys_mget)
427 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
428 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
429 RedisModuleString ** redisStrVec = createRedisStrVec(2);
432 bca->argv = redisStrVec;
435 mock().ignoreOtherCalls();
436 mock().expectOneCall("RedisModule_ReplyWithArray")
437 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
438 mock().expectOneCall("RedisModule_Call")
439 .withParameter("cmdname", "SCAN");
440 returnNKeysFromScanSome(3);
441 mock().expectOneCall("RedisModule_FreeCallReply");
442 mock().expectOneCall("RedisModule_Call")
443 .withParameter("cmdname", "MGET");
444 nKeysNotFoundMget(3);
445 mock().expectOneCall("RedisModule_FreeCallReply");
447 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
448 mock().expectOneCall("RedisModule_UnblockClient");
450 NGet_NoAtomic_ThreadMain((void*)bca);
452 mock().checkExpectations();
453 threadSafeContextLockedAndUnlockedEqualTimes();
455 delete []redisStrVec;
458 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_2_keys_mget)
461 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
462 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
463 RedisModuleString ** redisStrVec = createRedisStrVec(2);
466 bca->argv = redisStrVec;
469 mock().ignoreOtherCalls();
470 mock().expectOneCall("RedisModule_ReplyWithArray")
471 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
472 mock().expectOneCall("RedisModule_Call")
473 .withParameter("cmdname", "SCAN");
474 returnNKeysFromScanSome(3);
475 mock().expectOneCall("RedisModule_FreeCallReply");
476 mock().expectOneCall("RedisModule_Call")
477 .withParameter("cmdname", "MGET");
478 nKeysNotFoundMget(1);
480 mock().expectOneCall("RedisModule_FreeCallReply");
482 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
483 mock().expectOneCall("RedisModule_UnblockClient");
485 NGet_NoAtomic_ThreadMain((void*)bca);
487 mock().checkExpectations();
488 threadSafeContextLockedAndUnlockedEqualTimes();
490 delete []redisStrVec;
493 TEST(exstrings_nget, nget_noatomic_threadmain_scan_returned_zero_keys)
496 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
497 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
498 RedisModuleString ** redisStrVec = createRedisStrVec(2);
501 bca->argv = redisStrVec;
504 mock().ignoreOtherCalls();
505 mock().expectOneCall("RedisModule_ReplyWithArray")
506 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
507 mock().expectOneCall("RedisModule_Call")
508 .withParameter("cmdname", "SCAN");
509 returnNKeysFromScanSome(0);
510 mock().expectOneCall("RedisModule_FreeCallReply");
511 mock().expectNoCall("RedisModule_Call");
512 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
513 mock().expectOneCall("RedisModule_UnblockClient");
515 NGet_NoAtomic_ThreadMain((void*)bca);
517 mock().checkExpectations();
518 threadSafeContextLockedAndUnlockedEqualTimes();
520 delete []redisStrVec;