You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
7.0 KiB
201 lines
7.0 KiB
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <time.h> |
|
|
|
#include "../lib/platform_compat.h" |
|
#include "u_async.h" |
|
#include "debug_config.h" |
|
#include "../lib/mem.h" |
|
|
|
#define DEBUG_CATEGORY_TEST 1 |
|
|
|
#define TIMER_COUNT 100 |
|
#define STOP_TIMEOUT_TB 100000 /* 10 seconds in 0.1ms units */ |
|
|
|
typedef struct { |
|
int timer_number; /* номер таймера 0-99 */ |
|
uint64_t fire_time; /* время срабатывания */ |
|
int fired; /* флаг что уже сработал */ |
|
void* timer_id; /* ID таймера в uasync */ |
|
} timer_data_t; |
|
|
|
typedef struct { |
|
int timer_number; /* номер таймера */ |
|
timer_data_t* timer_data; /* указатель на массив данных */ |
|
int* active_count; /* счётчик активных таймеров */ |
|
int* total_fired; /* всего сработало */ |
|
int* stop_flag; /* флаг остановки */ |
|
uasync_t* ua; /* uasync инстанс */ |
|
} timer_ctx_t; |
|
|
|
static int test_passed = 0; |
|
static int test_failed = 0; |
|
|
|
/* Callback для таймера */ |
|
static void timer_callback(void* arg) { |
|
timer_ctx_t* ctx = (timer_ctx_t*)arg; |
|
|
|
/* Записываем время срабатывания */ |
|
ctx->timer_data[ctx->timer_number].fire_time = get_time_tb(); |
|
ctx->timer_data[ctx->timer_number].fired = 1; |
|
(*ctx->total_fired)++; |
|
|
|
/* Если stop_flag установлен - НЕ перезапускаем */ |
|
if (*ctx->stop_flag == 1) { |
|
(*ctx->active_count)--; |
|
return; |
|
} |
|
|
|
/* Перезапускаем с новым случайным таймаутом */ |
|
int random_delay = rand() % 101; /* 0-100 (0-10ms) */ |
|
|
|
timer_ctx_t* new_ctx = u_malloc(sizeof(timer_ctx_t)); |
|
if (new_ctx) { |
|
new_ctx->timer_number = ctx->timer_number; /* тот же номер */ |
|
new_ctx->timer_data = ctx->timer_data; |
|
new_ctx->active_count = ctx->active_count; |
|
new_ctx->total_fired = ctx->total_fired; |
|
new_ctx->stop_flag = ctx->stop_flag; |
|
new_ctx->ua = ctx->ua; |
|
|
|
void* new_timer = uasync_set_timeout(ctx->ua, random_delay, new_ctx, timer_callback); |
|
if (new_timer) { |
|
ctx->timer_data[ctx->timer_number].timer_id = new_timer; |
|
} else { |
|
/* Не удалось создать - уменьшаем active_count */ |
|
(*ctx->active_count)--; |
|
u_free(new_ctx); |
|
} |
|
} else { |
|
(*ctx->active_count)--; |
|
} |
|
} |
|
|
|
/* Callback для стоп-таймера */ |
|
static void stop_callback(void* arg) { |
|
timer_ctx_t* ctx = (timer_ctx_t*)arg; |
|
*ctx->stop_flag = 1; |
|
} |
|
|
|
int main(void) { |
|
debug_config_init(); |
|
debug_set_level(DEBUG_LEVEL_INFO); |
|
debug_set_categories(DEBUG_CATEGORY_ALL); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "=== UASYNC Timeout Test ==="); |
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Timer count: %d, random delay 0-10ms, stop after 10s", TIMER_COUNT); |
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Each timer restarts with new random delay until stop"); |
|
|
|
srand(42); |
|
|
|
/* Создаём uasync */ |
|
uasync_t* ua = uasync_create(); |
|
if (!ua) { |
|
DEBUG_ERROR(DEBUG_CATEGORY_TEST, "Failed to create uasync"); |
|
return 1; |
|
} |
|
|
|
/* Массив данных таймеров - по структуре на каждый таймер */ |
|
timer_data_t timer_data[TIMER_COUNT]; |
|
memset(timer_data, 0, sizeof(timer_data)); |
|
|
|
/* Счётчики */ |
|
int active_count = 0; |
|
int total_fired = 0; |
|
int stop_flag = 0; |
|
|
|
/* Создаём 100 таймеров */ |
|
for (int i = 0; i < TIMER_COUNT; i++) { |
|
timer_ctx_t* ctx = u_malloc(sizeof(timer_ctx_t)); |
|
if (!ctx) { |
|
DEBUG_ERROR(DEBUG_CATEGORY_TEST, "Failed to allocate context for timer %d", i); |
|
uasync_destroy(ua, 0); |
|
return 1; |
|
} |
|
|
|
ctx->timer_number = i; |
|
ctx->timer_data = timer_data; |
|
ctx->active_count = &active_count; |
|
ctx->total_fired = &total_fired; |
|
ctx->stop_flag = &stop_flag; |
|
ctx->ua = ua; |
|
|
|
int random_delay = rand() % 101; /* 0-100 (0-10ms) */ |
|
void* timer_id = uasync_set_timeout(ua, random_delay, ctx, timer_callback); |
|
|
|
if (!timer_id) { |
|
DEBUG_ERROR(DEBUG_CATEGORY_TEST, "Failed to set timer %d", i); |
|
u_free(ctx); |
|
uasync_destroy(ua, 0); |
|
return 1; |
|
} |
|
|
|
timer_data[i].timer_id = timer_id; |
|
active_count++; |
|
} |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Created %d timers, active_count=%d", TIMER_COUNT, active_count); |
|
|
|
/* Создаём стоп-таймер на 10 секунд */ |
|
timer_ctx_t* stop_ctx = u_malloc(sizeof(timer_ctx_t)); |
|
if (!stop_ctx) { |
|
DEBUG_ERROR(DEBUG_CATEGORY_TEST, "Failed to allocate stop context"); |
|
uasync_destroy(ua, 0); |
|
return 1; |
|
} |
|
|
|
stop_ctx->timer_number = -1; |
|
stop_ctx->timer_data = timer_data; |
|
stop_ctx->active_count = &active_count; |
|
stop_ctx->total_fired = &total_fired; |
|
stop_ctx->stop_flag = &stop_flag; |
|
stop_ctx->ua = ua; |
|
|
|
void* stop_timer = uasync_set_timeout(ua, STOP_TIMEOUT_TB, stop_ctx, stop_callback); |
|
if (!stop_timer) { |
|
DEBUG_ERROR(DEBUG_CATEGORY_TEST, "Failed to set stop timer"); |
|
u_free(stop_ctx); |
|
uasync_destroy(ua, 0); |
|
return 1; |
|
} |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Stop timer set for 10 seconds"); |
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Running event loop..."); |
|
|
|
/* Ждём пока active_count станет 0 (все таймеры отработают после stop) */ |
|
int poll_count = 0; |
|
while (active_count > 0 && poll_count < 100000) { |
|
uasync_poll(ua, 100); |
|
poll_count++; |
|
} |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Event loop done: poll_count=%d, active_count=%d, total_fired=%d", |
|
poll_count, active_count, total_fired); |
|
|
|
/* Проверяем что после stop сработало ровно TIMER_COUNT таймеров (без продолжения) */ |
|
/* total_fired - это общее количество срабатываний за всё время */ |
|
/* После установки stop_flag таймеры больше не перезапускаются */ |
|
|
|
if (active_count == 0) { |
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "PASS: active_count=0 (all timers stopped)"); |
|
test_passed = 1; |
|
} else { |
|
DEBUG_ERROR(DEBUG_CATEGORY_TEST, "FAIL: active_count=%d (expected 0)", active_count); |
|
test_failed = 1; |
|
} |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "Total fires during test: %d", total_fired); |
|
|
|
/* Отменяем стоп-таймер если он ещё не сработал */ |
|
if (stop_timer) { |
|
uasync_cancel_timeout(ua, stop_timer); |
|
u_free(stop_ctx); |
|
} |
|
|
|
uasync_destroy(ua, 0); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_TEST, "=== Test Complete ==="); |
|
|
|
return test_failed ? 1 : 0; |
|
}
|
|
|