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"
27 #include "CppUTest/TestHarness.h"
28 #include "CppUTestExt/MockSupport.h"
30 #include "ut_helpers.hpp"
32 TEST_GROUP(exstrings_nget)
37 mock().ignoreOtherCalls();
48 void nKeysFoundMget(long keys)
50 for (long i = 0 ; i < keys ; i++) {
51 mock().expectOneCall("RedisModule_CreateStringFromCallReply")
52 .andReturnValue(malloc(UT_DUMMY_BUFFER_SIZE));
53 mock().expectNCalls(2, "RedisModule_ReplyWithString");
57 void nKeysNotFoundMget(long keys)
60 mock().expectNCalls(keys, "RedisModule_CreateStringFromCallReply")
62 mock().expectNoCall("RedisModule_ReplyWithString");
65 void expectNReplies(long count)
67 mock().expectOneCall("RedisModule_ReplySetArrayLength")
68 .withParameter("len", 2*count);
71 void threadSafeContextLockedAndUnlockedEqualTimes()
73 int locked = mock().getData("TimesThreadSafeContextWasLocked").getIntValue();
74 int unlocked = mock().getData("TimesThreadSafeContextWasUnlocked").getIntValue();
75 CHECK_EQUAL(locked, unlocked);
78 TEST(exstrings_nget, nget_atomic_automemory_enabled)
81 RedisModuleString ** redisStrVec = createRedisStrVec(2);
82 long keys_found_with_scan = 0;
84 mock().expectOneCall("RedisModule_AutoMemory");
85 mock().expectOneCall("RedisModule_CallReplyLength")
86 .andReturnValue((int)keys_found_with_scan);
87 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
88 mock().checkExpectations();
89 CHECK_EQUAL(ret, REDISMODULE_OK);
94 TEST(exstrings_nget, nget_atomic_command_parameter_number_incorrect)
97 RedisModuleString ** redisStrVec = createRedisStrVec(2);
99 mock().expectOneCall("RedisModule_WrongArity");
100 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 3);
101 CHECK_EQUAL(ret, REDISMODULE_ERR);
102 mock().checkExpectations();
104 delete []redisStrVec;
107 TEST(exstrings_nget, nget_atomic_command_3rd_parameter_was_not_equal_to_COUNT)
110 RedisModuleString ** redisStrVec = createRedisStrVec(4);
111 const char * not_count_literal = "NOT_COUNT";
112 size_t not_count_len = strlen(not_count_literal);
114 mock().expectOneCall("RedisModule_StringPtrLen")
115 .withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
116 .andReturnValue((void*)not_count_literal);
117 mock().expectOneCall("RedisModule_ReplyWithError");
118 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
119 CHECK_EQUAL(ret, REDISMODULE_ERR);
120 mock().checkExpectations();
122 delete []redisStrVec;
125 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_not_integer)
128 RedisModuleString ** redisStrVec = createRedisStrVec(4);
129 const char * count_literal = "COUNT";
130 size_t count_len = strlen(count_literal);
131 size_t count_number = 123;
133 mock().expectOneCall("RedisModule_StringPtrLen")
134 .withOutputParameterReturning("len", &count_len, sizeof(size_t))
135 .andReturnValue((void*)count_literal);
136 mock().expectOneCall("RedisModule_StringToLongLong")
137 .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
138 .andReturnValue(REDISMODULE_ERR);
139 mock().expectOneCall("RedisModule_ReplyWithError");
140 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
141 CHECK_EQUAL(ret, REDISMODULE_ERR);
142 mock().checkExpectations();
144 delete []redisStrVec;
147 TEST(exstrings_nget, nget_atomic_command_4th_parameter_was_negative)
150 RedisModuleString ** redisStrVec = createRedisStrVec(4);
151 const char * count_literal = "COUNT";
152 size_t count_len = strlen(count_literal);
153 size_t count_number = -123;
155 mock().expectOneCall("RedisModule_StringPtrLen")
156 .withOutputParameterReturning("len", &count_len, sizeof(size_t))
157 .andReturnValue((void*)count_literal);
158 mock().expectOneCall("RedisModule_StringToLongLong")
159 .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
160 .andReturnValue(REDISMODULE_OK);
161 mock().expectOneCall("RedisModule_ReplyWithError");
162 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 4);
163 CHECK_EQUAL(ret, REDISMODULE_ERR);
164 mock().checkExpectations();
166 delete []redisStrVec;
169 TEST(exstrings_nget, nget_atomic_command_scan_returned_zero_keys)
172 RedisModuleString ** redisStrVec = createRedisStrVec(2);
174 mock().expectOneCall("RedisModule_ReplyWithArray")
175 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
176 mock().expectOneCall("RedisModule_Call")
177 .withParameter("cmdname", "SCAN");
178 returnNKeysFromScanSome(0);
180 mock().expectNoCall("RedisModule_Call");
182 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
183 CHECK_EQUAL(ret, REDISMODULE_OK);
184 mock().checkExpectations();
186 delete []redisStrVec;
189 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_0_keys_mget)
192 RedisModuleString ** redisStrVec = createRedisStrVec(2);
194 mock().ignoreOtherCalls();
195 mock().expectOneCall("RedisModule_ReplyWithArray")
196 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
198 mock().expectOneCall("RedisModule_Call")
199 .withParameter("cmdname", "SCAN");
200 returnNKeysFromScanSome(3);
201 mock().expectOneCall("RedisModule_FreeCallReply");
202 mock().expectOneCall("RedisModule_Call")
203 .withParameter("cmdname", "MGET");
204 nKeysNotFoundMget(3);
205 mock().expectOneCall("RedisModule_FreeCallReply");
207 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
208 CHECK_EQUAL(ret, REDISMODULE_OK);
209 mock().checkExpectations();
211 delete []redisStrVec;
214 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_3_keys_mget)
217 RedisModuleString ** redisStrVec = createRedisStrVec(2);
219 mock().ignoreOtherCalls();
220 mock().expectOneCall("RedisModule_ReplyWithArray")
221 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
222 mock().expectOneCall("RedisModule_Call")
223 .withParameter("cmdname", "SCAN");
224 returnNKeysFromScanSome(3);
225 mock().expectOneCall("RedisModule_FreeCallReply");
226 mock().expectOneCall("RedisModule_Call")
227 .withParameter("cmdname", "MGET");
229 mock().expectOneCall("RedisModule_FreeCallReply");
231 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
232 CHECK_EQUAL(ret, REDISMODULE_OK);
233 mock().checkExpectations();
235 delete []redisStrVec;
238 TEST(exstrings_nget, nget_atomic_command_3_keys_scanned_2_keys_mget)
241 RedisModuleString ** redisStrVec = createRedisStrVec(2);
243 mock().ignoreOtherCalls();
244 mock().expectOneCall("RedisModule_ReplyWithArray")
245 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
246 mock().expectOneCall("RedisModule_Call")
247 .withParameter("cmdname", "SCAN");
248 returnNKeysFromScanSome(3);
249 mock().expectOneCall("RedisModule_FreeCallReply");
250 mock().expectOneCall("RedisModule_Call")
251 .withParameter("cmdname", "MGET");
253 nKeysNotFoundMget(1);
254 mock().expectOneCall("RedisModule_FreeCallReply");
256 int ret = NGet_Atomic_RedisCommand(&ctx, redisStrVec, 2);
257 CHECK_EQUAL(ret, REDISMODULE_OK);
258 mock().checkExpectations();
260 delete []redisStrVec;
263 TEST(exstrings_nget, nget_noatomic_automemory_enabled)
266 RedisModuleString ** redisStrVec = createRedisStrVec(2);
268 mock().setData("pthread_create_free_block_client_args", 1);
270 mock().ignoreOtherCalls();
271 mock().expectOneCall("RedisModule_AutoMemory");
273 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
274 CHECK_EQUAL(ret, REDISMODULE_OK);
275 mock().checkExpectations();
277 delete []redisStrVec;
280 TEST(exstrings_nget, nget_noatomic_thread_create_success)
283 RedisModuleString ** redisStrVec = createRedisStrVec(2);
285 mock().setData("pthread_create_free_block_client_args", 1);
287 mock().ignoreOtherCalls();
288 mock().expectOneCall("RedisModule_BlockClient");
289 mock().expectOneCall("pthread_create");
290 mock().expectNoCall("RedisModule_AbortBlock");
292 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
293 CHECK_EQUAL(ret, REDISMODULE_OK);
294 mock().checkExpectations();
296 delete []redisStrVec;
299 TEST(exstrings_nget, nget_noatomic_thread_create_fail)
302 RedisModuleString ** redisStrVec = createRedisStrVec(2);
304 mock().ignoreOtherCalls();
305 mock().expectOneCall("RedisModule_BlockClient");
306 mock().expectOneCall("pthread_create")
308 mock().expectOneCall("RedisModule_AbortBlock");
310 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 2);
311 CHECK_EQUAL(ret, REDISMODULE_OK);
312 mock().checkExpectations();
314 delete []redisStrVec;
317 TEST(exstrings_nget, nget_noatomic_parameter_number_incorrect)
320 RedisModuleString ** redisStrVec = createRedisStrVec(4);
322 mock().expectOneCall("RedisModule_WrongArity");
323 mock().expectNoCall("RedisModule_BlockClient");
325 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 3);
327 CHECK_EQUAL(ret, REDISMODULE_ERR);
328 mock().checkExpectations();
330 delete []redisStrVec;
333 TEST(exstrings_nget, nget_noatomic_threadmain_3rd_parameter_was_not_equal_to_COUNT)
336 RedisModuleString ** redisStrVec = createRedisStrVec(4);
337 const char * not_count_literal = "NOT_COUNT";
338 size_t not_count_len = strlen(not_count_literal);
340 mock().expectOneCall("RedisModule_StringPtrLen")
341 .withOutputParameterReturning("len", ¬_count_len, sizeof(size_t))
342 .andReturnValue((void*)not_count_literal);
343 mock().expectOneCall("RedisModule_ReplyWithError");
344 mock().expectNoCall("RedisModule_BlockClient");
346 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
348 CHECK_EQUAL(ret, REDISMODULE_ERR);
350 mock().checkExpectations();
351 threadSafeContextLockedAndUnlockedEqualTimes();
353 delete []redisStrVec;
356 TEST(exstrings_nget, nget_noatomic_4th_parameter_was_not_integer)
359 const char * count_literal = "COUNT";
360 size_t count_len = strlen(count_literal);
361 size_t count_number = -123;
362 RedisModuleString ** redisStrVec = createRedisStrVec(4);
364 mock().expectOneCall("RedisModule_StringPtrLen")
365 .withOutputParameterReturning("len", &count_len, sizeof(size_t))
366 .andReturnValue((void*)count_literal);
367 mock().expectOneCall("RedisModule_StringToLongLong")
368 .withOutputParameterReturning("ll", &count_number, sizeof(size_t))
369 .andReturnValue(REDISMODULE_OK);
370 mock().expectOneCall("RedisModule_ReplyWithError");
372 int ret = NGet_NoAtomic_RedisCommand(&ctx, redisStrVec, 4);
374 CHECK_EQUAL(ret, REDISMODULE_ERR);
375 mock().checkExpectations();
376 threadSafeContextLockedAndUnlockedEqualTimes();
378 delete []redisStrVec;
381 typedef struct RedisModuleBlockedClientArgs {
382 RedisModuleBlockedClient *bc;
383 RedisModuleString **argv;
385 } RedisModuleBlockedClientArgs;
387 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_3_keys_mget)
390 RedisModuleBlockedClientArgs *bca =
391 (RedisModuleBlockedClientArgs*)RedisModule_Alloc(sizeof(RedisModuleBlockedClientArgs));
392 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
393 RedisModuleString ** redisStrVec = createRedisStrVec(2);
396 bca->argv = redisStrVec;
399 mock().ignoreOtherCalls();
400 mock().expectOneCall("RedisModule_ReplyWithArray")
401 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
402 mock().expectOneCall("RedisModule_Call")
403 .withParameter("cmdname", "SCAN");
404 returnNKeysFromScanSome(3);
405 mock().expectOneCall("RedisModule_FreeCallReply");
406 mock().expectOneCall("RedisModule_Call")
407 .withParameter("cmdname", "MGET");
409 mock().expectOneCall("RedisModule_FreeCallReply");
411 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
412 mock().expectOneCall("RedisModule_UnblockClient");
414 NGet_NoAtomic_ThreadMain((void*)bca);
416 mock().checkExpectations();
417 threadSafeContextLockedAndUnlockedEqualTimes();
419 delete []redisStrVec;
422 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_0_keys_mget)
425 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
426 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
427 RedisModuleString ** redisStrVec = createRedisStrVec(2);
430 bca->argv = redisStrVec;
433 mock().ignoreOtherCalls();
434 mock().expectOneCall("RedisModule_ReplyWithArray")
435 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
436 mock().expectOneCall("RedisModule_Call")
437 .withParameter("cmdname", "SCAN");
438 returnNKeysFromScanSome(3);
439 mock().expectOneCall("RedisModule_FreeCallReply");
440 mock().expectOneCall("RedisModule_Call")
441 .withParameter("cmdname", "MGET");
442 nKeysNotFoundMget(3);
443 mock().expectOneCall("RedisModule_FreeCallReply");
445 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
446 mock().expectOneCall("RedisModule_UnblockClient");
448 NGet_NoAtomic_ThreadMain((void*)bca);
450 mock().checkExpectations();
451 threadSafeContextLockedAndUnlockedEqualTimes();
453 delete []redisStrVec;
456 TEST(exstrings_nget, nget_noatomic_threadmain_3_keys_scanned_2_keys_mget)
459 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
460 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
461 RedisModuleString ** redisStrVec = createRedisStrVec(2);
464 bca->argv = redisStrVec;
467 mock().ignoreOtherCalls();
468 mock().expectOneCall("RedisModule_ReplyWithArray")
469 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
470 mock().expectOneCall("RedisModule_Call")
471 .withParameter("cmdname", "SCAN");
472 returnNKeysFromScanSome(3);
473 mock().expectOneCall("RedisModule_FreeCallReply");
474 mock().expectOneCall("RedisModule_Call")
475 .withParameter("cmdname", "MGET");
476 nKeysNotFoundMget(1);
478 mock().expectOneCall("RedisModule_FreeCallReply");
480 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
481 mock().expectOneCall("RedisModule_UnblockClient");
483 NGet_NoAtomic_ThreadMain((void*)bca);
485 mock().checkExpectations();
486 threadSafeContextLockedAndUnlockedEqualTimes();
488 delete []redisStrVec;
491 TEST(exstrings_nget, nget_noatomic_threadmain_scan_returned_zero_keys)
494 RedisModuleBlockedClientArgs *bca = (RedisModuleBlockedClientArgs*)malloc(sizeof(RedisModuleBlockedClientArgs));
495 RedisModuleBlockedClient *bc = RedisModule_BlockClient(&ctx,NULL,NULL,NULL,0);
496 RedisModuleString ** redisStrVec = createRedisStrVec(2);
499 bca->argv = redisStrVec;
502 mock().ignoreOtherCalls();
503 mock().expectOneCall("RedisModule_ReplyWithArray")
504 .withParameter("len", (long)REDISMODULE_POSTPONED_ARRAY_LEN);
505 mock().expectOneCall("RedisModule_Call")
506 .withParameter("cmdname", "SCAN");
507 returnNKeysFromScanSome(0);
508 mock().expectOneCall("RedisModule_FreeCallReply");
509 mock().expectNoCall("RedisModule_Call");
510 mock().expectOneCall("RedisModule_FreeThreadSafeContext");
511 mock().expectOneCall("RedisModule_UnblockClient");
513 NGet_NoAtomic_ThreadMain((void*)bca);
515 mock().checkExpectations();
516 threadSafeContextLockedAndUnlockedEqualTimes();
518 delete []redisStrVec;