@ -306,10 +306,14 @@ static void test_memory_leak_detection(void) {
ASSERT_NOT_NULL ( ua , " Failed to create uasync instance " ) ;
/* Create and destroy multiple timers without proper cleanup */
test_context_t * timer_ctxs [ 10 ] = { NULL } ;
for ( int i = 0 ; i < 10 ; i + + ) {
test_context_t timer_ctx = { 0 } ;
timer_ctx . timeout_ms = 100 ; // Set proper timeout to avoid immediate timeout
void * timer = uasync_set_timeout ( ua , 100 , & timer_ctx , test_timer_callback , " test_cancel " ) ;
test_context_t * timer_ctx = u_malloc ( sizeof ( test_context_t ) ) ;
ASSERT_NOT_NULL ( timer_ctx , " Failed to allocate timer context " ) ;
memset ( timer_ctx , 0 , sizeof ( * timer_ctx ) ) ;
timer_ctx - > timeout_ms = 100 ;
timer_ctxs [ i ] = timer_ctx ;
void * timer = uasync_set_timeout ( ua , 100 , timer_ctx , test_timer_callback , " test_cancel " ) ;
ASSERT_NOT_NULL ( timer , " Failed to set timer " ) ;
/* Cancel some, leave others to timeout */
@ -323,6 +327,11 @@ static void test_memory_leak_detection(void) {
uasync_poll ( ua , 10 ) ;
}
/* Free allocated contexts */
for ( int i = 0 ; i < 10 ; i + + ) {
if ( timer_ctxs [ i ] ) u_free ( timer_ctxs [ i ] ) ;
}
/* Destroy should detect any leaks and abort if found */
/* This test passes if we don't abort */
uasync_destroy ( ua , 0 ) ;
@ -462,15 +471,16 @@ static void test_concurrent_operations(void) {
/* Create multiple timers with different timeouts */
void * timers [ 10 ] ;
test_context_t * contexts [ 10 ] = { NULL } ;
for ( int i = 0 ; i < 10 ; i + + ) {
// Use unique contexts to avoid all timers having timeout_ms = 0
test_context_t * individual_ctx = u_malloc ( sizeof ( test_context_t ) ) ;
ASSERT_NOT_NULL ( individual_ctx , " Failed to allocate timer context " ) ;
individual_ctx - > callback_count = 0 ;
individual_ctx - > expected_count = 0 ;
individual_ctx - > timeout_ms = ( i + 1 ) * 5 ; // Different timeouts: 5, 10, 15, ..., 50ms
individual_ctx - > timeout_ms = ( i + 1 ) * 5 ;
individual_ctx - > callback_arg = 0 ;
contexts [ i ] = individual_ctx ;
timers [ i ] = uasync_set_timeout ( ua , ( i + 1 ) * 5 , individual_ctx , test_timer_callback , " test_stress " ) ;
ASSERT_NOT_NULL ( timers [ i ] , " Failed to set timer " ) ;
}
@ -490,7 +500,7 @@ static void test_concurrent_operations(void) {
if ( cycle % 3 = = 0 ) {
char data = ' x ' ;
ssize_t wret = write ( sockets [ 0 ] , & data , 1 ) ;
( void ) wret ; /* Suppress warning - best effort write for testing */
( void ) wret ;
}
/* Poll */
@ -510,18 +520,13 @@ static void test_concurrent_operations(void) {
}
for ( int i = 0 ; i < 10 ; i + + ) {
if ( timers [ i ] ) {
// Note: We cannot safely access the context here because the timer might be expired
// The context will be freed by the timeout_heap free callback during uasync_destroy
if ( contexts [ i ] & & contexts [ i ] - > callback_count = = 0 & & timers [ i ] ) {
uasync_cancel_timeout ( ua , timers [ i ] ) ;
timers [ i ] = NULL ;
}
timers [ i ] = NULL ;
if ( contexts [ i ] ) { u_free ( contexts [ i ] ) ; contexts [ i ] = NULL ; }
}
// Free any remaining allocated contexts (for timers that were cancelled)
// This is a simplified approach - in production code, you'd maintain a list of allocated contexts
// For this test, we'll let uasync_destroy handle the cleanup through the timeout heap's free callback
uasync_destroy ( ua , 0 ) ;
TEST_PASS ( ) ;
}