1111 * Tests will call a libvalkeycluster API-function while iterating on a number,
1212 * the number of successful allocations during the call before it hits an OOM.
1313 * The result and the error code is then checked to show "Out of memory".
14- * As a last step the correct number of allocations is prepared to get a
15- * successful API-function call.
16- *
17- * Tip:
18- * When this testcase fails after code changes in the library, run the testcase
19- * in `gdb` to find which API call that failed, and in which iteration.
20- * - Go to the correct stack frame to find which API that triggered a failure.
21- * - Use the gdb command `print i` to find which iteration.
22- * - Investigate if a failure or a success is expected after the code change.
23- * - Set correct `i` in for-loop and the `prepare_allocation_test()` for the test.
24- * Correct `i` can be hard to know, finding the correct number might require trial
25- * and error of running with increased/decreased `i` until the edge is found.
14+ * The required number of allocations for a successful call is discovered at
15+ * runtime rather than hardcoded, making the tests resilient to changes in
16+ * internal allocation patterns.
2617 */
2718#define _XOPEN_SOURCE 600 /* For strdup() */
2819#include "adapters/libevent.h"
@@ -148,15 +139,16 @@ void test_alloc_failure_handling(void) {
148139 valkeyReply * reply ;
149140 const char * cmd = "SET key value" ;
150141
151- for (int i = 0 ; i < 33 ; ++ i ) {
152- prepare_allocation_test (cc , i );
142+ /* Discover the number of allocations required for a successful call. */
143+ int n ;
144+ for (n = 0 ; n < 1000 ; n ++ ) {
145+ prepare_allocation_test (cc , n );
153146 reply = (valkeyReply * )valkeyClusterCommand (cc , cmd );
154- assert (reply == NULL );
147+ if (reply != NULL )
148+ break ;
155149 ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
156150 }
157-
158- prepare_allocation_test (cc , 33 );
159- reply = (valkeyReply * )valkeyClusterCommand (cc , cmd );
151+ assert (n < 1000 );
160152 CHECK_REPLY_OK (cc , reply );
161153 freeReplyObject (reply );
162154 }
@@ -169,17 +161,15 @@ void test_alloc_failure_handling(void) {
169161 valkeyClusterNode * node = valkeyClusterGetNodeByKey (cc , (char * )"key" );
170162 assert (node );
171163
172- // OOM failing commands
173- for (int i = 0 ; i < 32 ; ++ i ) {
174- prepare_allocation_test (cc , i );
164+ int n ;
165+ for (n = 0 ; n < 1000 ; n ++ ) {
166+ prepare_allocation_test (cc , n );
175167 reply = valkeyClusterCommandToNode (cc , node , cmd );
176- assert (reply == NULL );
168+ if (reply != NULL )
169+ break ;
177170 ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
178171 }
179-
180- // Successful command
181- prepare_allocation_test (cc , 32 );
182- reply = valkeyClusterCommandToNode (cc , node , cmd );
172+ assert (n < 1000 );
183173 CHECK_REPLY_OK (cc , reply );
184174 freeReplyObject (reply );
185175 }
@@ -189,37 +179,35 @@ void test_alloc_failure_handling(void) {
189179 valkeyReply * reply ;
190180 const char * cmd = "SET foo one" ;
191181
192- for (int i = 0 ; i < 33 ; ++ i ) {
193- prepare_allocation_test (cc , i );
182+ /* Discover allocations needed for a successful append. */
183+ int na ;
184+ for (na = 0 ; na < 1000 ; na ++ ) {
185+ prepare_allocation_test (cc , na );
194186 result = valkeyClusterAppendCommand (cc , cmd );
195- assert (result == VALKEY_ERR );
187+ if (result == VALKEY_OK )
188+ break ;
196189 ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
197-
198190 valkeyClusterReset (cc );
199191 }
200-
201- for (int i = 0 ; i < 4 ; ++ i ) {
202- // Appended command lost when receiving error from valkey
203- // during a GetReply, needs a new append for each test loop
204- prepare_allocation_test (cc , 33 );
192+ assert (na < 1000 );
193+
194+ /* Discover allocations needed for a successful GetReply. */
195+ int ng ;
196+ for (ng = 0 ; ng < 1000 ; ng ++ ) {
197+ /* Appended command lost when receiving error during a GetReply,
198+ * needs a new append for each test loop. */
199+ prepare_allocation_test (cc , na );
205200 result = valkeyClusterAppendCommand (cc , cmd );
206201 assert (result == VALKEY_OK );
207202
208- prepare_allocation_test (cc , i );
203+ prepare_allocation_test (cc , ng );
209204 result = valkeyClusterGetReply (cc , (void * )& reply );
210- assert (result == VALKEY_ERR );
205+ if (result == VALKEY_OK )
206+ break ;
211207 ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
212-
213208 valkeyClusterReset (cc );
214209 }
215-
216- prepare_allocation_test (cc , 34 );
217- result = valkeyClusterAppendCommand (cc , cmd );
218- assert (result == VALKEY_OK );
219-
220- prepare_allocation_test (cc , 4 );
221- result = valkeyClusterGetReply (cc , (void * )& reply );
222- assert (result == VALKEY_OK );
210+ assert (ng < 1000 );
223211 CHECK_REPLY_OK (cc , reply );
224212 freeReplyObject (reply );
225213 }
@@ -232,39 +220,33 @@ void test_alloc_failure_handling(void) {
232220 valkeyClusterNode * node = valkeyClusterGetNodeByKey (cc , (char * )"foo" );
233221 assert (node );
234222
235- // OOM failing appends
236- for (int i = 0 ; i < 34 ; ++ i ) {
237- prepare_allocation_test (cc , i );
223+ /* Discover allocations needed for a successful append to node. */
224+ int na ;
225+ for (na = 0 ; na < 1000 ; na ++ ) {
226+ prepare_allocation_test (cc , na );
238227 result = valkeyClusterAppendCommandToNode (cc , node , cmd );
239- assert (result == VALKEY_ERR );
228+ if (result == VALKEY_OK )
229+ break ;
240230 ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
241-
242231 valkeyClusterReset (cc );
243232 }
233+ assert (na < 1000 );
244234
245- // OOM failing GetResults
246- for ( int i = 0 ; i < 4 ; ++ i ) {
247- // First a successful append
248- prepare_allocation_test (cc , 34 );
235+ /* Discover allocations needed for a successful GetReply. */
236+ int ng ;
237+ for ( ng = 0 ; ng < 1000 ; ng ++ ) {
238+ prepare_allocation_test (cc , na );
249239 result = valkeyClusterAppendCommandToNode (cc , node , cmd );
250240 assert (result == VALKEY_OK );
251241
252- prepare_allocation_test (cc , i );
242+ prepare_allocation_test (cc , ng );
253243 result = valkeyClusterGetReply (cc , (void * )& reply );
254- assert (result == VALKEY_ERR );
244+ if (result == VALKEY_OK )
245+ break ;
255246 ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
256-
257247 valkeyClusterReset (cc );
258248 }
259-
260- // Successful append and GetReply
261- prepare_allocation_test (cc , 35 );
262- result = valkeyClusterAppendCommandToNode (cc , node , cmd );
263- assert (result == VALKEY_OK );
264-
265- prepare_allocation_test (cc , 4 );
266- result = valkeyClusterGetReply (cc , (void * )& reply );
267- assert (result == VALKEY_OK );
249+ assert (ng < 1000 );
268250 CHECK_REPLY_OK (cc , reply );
269251 freeReplyObject (reply );
270252 }
@@ -318,19 +300,20 @@ void test_alloc_failure_handling(void) {
318300 freeReplyObject (reply );
319301
320302 /* Test ASK reply handling with OOM */
321- for (int i = 0 ; i < 45 ; ++ i ) {
322- prepare_allocation_test (cc , i );
323- reply = valkeyClusterCommand (cc , "GET foo" );
324- assert (reply == NULL );
325- ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
303+ {
304+ int n ;
305+ for (n = 0 ; n < 1000 ; n ++ ) {
306+ prepare_allocation_test (cc , n );
307+ reply = valkeyClusterCommand (cc , "GET foo" );
308+ if (reply != NULL )
309+ break ;
310+ ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
311+ }
312+ assert (n < 1000 );
313+ CHECK_REPLY_STR (cc , reply , "one" );
314+ freeReplyObject (reply );
326315 }
327316
328- /* Test ASK reply handling without OOM */
329- prepare_allocation_test (cc , 45 );
330- reply = valkeyClusterCommand (cc , "GET foo" );
331- CHECK_REPLY_STR (cc , reply , "one" );
332- freeReplyObject (reply );
333-
334317 /* Finalize the migration. Skip OOM testing during these steps by
335318 * allowing a high number of allocations. */
336319 prepare_allocation_test (cc , 1000 );
@@ -347,19 +330,20 @@ void test_alloc_failure_handling(void) {
347330 freeReplyObject (reply );
348331
349332 /* Test MOVED reply handling with OOM */
350- for (int i = 0 ; i < 32 ; ++ i ) {
351- prepare_allocation_test (cc , i );
352- reply = valkeyClusterCommand (cc , "GET foo" );
353- assert (reply == NULL );
354- ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
333+ {
334+ int n ;
335+ for (n = 0 ; n < 1000 ; n ++ ) {
336+ prepare_allocation_test (cc , n );
337+ reply = valkeyClusterCommand (cc , "GET foo" );
338+ if (reply != NULL )
339+ break ;
340+ ASSERT_STR_EQ (cc -> errstr , "Out of memory" );
341+ }
342+ assert (n < 1000 );
343+ CHECK_REPLY_STR (cc , reply , "one" );
344+ freeReplyObject (reply );
355345 }
356346
357- /* Test MOVED reply handling without OOM */
358- prepare_allocation_test (cc , 32 );
359- reply = valkeyClusterCommand (cc , "GET foo" );
360- CHECK_REPLY_STR (cc , reply , "one" );
361- freeReplyObject (reply );
362-
363347 /* MOVED triggers a slotmap update which currently replaces all cluster_node
364348 * objects. We can get the new objects by searching for its server ports.
365349 * This enables us to migrate the slot back to the original node. */
0 commit comments