Files
2025-06-28 00:56:58 +02:00

221 lines
5.6 KiB
C

#include <check.h>
#include "ucore/timers.h"
#include "ucore/timers.h"
#include "ucore/clock.h"
struct TimerTest {
int cnt;
};
#define TEST_TIMER_START 1000000
static void timer_test_cb(struct UCTimers *timers, struct UCTimer *timer)
{
struct TimerTest *tt = timer->cookie_ptr;
(void)timers; //get rid of unused param warning
tt->cnt++;
}
static void timer_test_cb_add(struct UCTimers *timers, struct UCTimer *timer)
{
struct TimerTest *tt = timer->cookie_ptr;
tt->cnt++;
uc_timers_add(timers, timer, 10, 0);
}
static void timer_test_cb_remove(struct UCTimers *timers, struct UCTimer *timer)
{
struct UCTimer *timer2 = timer->cookie_ptr;
uc_timers_remove(timers, timer2);
}
static void common_init(struct UCoreSettableClock *clk,
struct TimerTest *tt,
struct UCTimers *timers,
struct UCTimer *timer)
{
uc_settable_clock_init(clk);
uc_settable_clock_set(clk, TEST_TIMER_START, 0);
uc_timers_init_ex(timers, &clk->clock);
tt->cnt = 0;
memset(timer, 0, sizeof *timer);
timer->cookie_ptr = tt;
}
START_TEST (test_timers_simple)
{
struct UCoreSettableClock clk;
struct TimerTest tt;
struct UCTimers timers;
struct UCTimer timer;
int t = TEST_TIMER_START;
int rc;
common_init(&clk, &tt, &timers, &timer);
timer.callback = timer_test_cb;
uc_timers_add(&timers, &timer, 10, 0);
//5 seconds into the future, no timer should fire
t += 5;
uc_settable_clock_set(&clk, t, 0);
rc = uc_timers_run(&timers);
fail_if(rc != 0);
fail_if(tt.cnt != 0);
ck_assert_int_eq(uc_timers_count(&timers), 1);
//10 seconds into the future, our timer should fire
t += 5;
uc_settable_clock_set(&clk, t, 0);
rc = uc_timers_run(&timers);
fail_if(rc != 1);
fail_if(tt.cnt != 1);
//20 seconds into the future, our oneshot timer shouldn't fire
t += 10;
uc_settable_clock_set(&clk, t, 0);
rc = uc_timers_run(&timers);
fail_if(rc != 0);
fail_if(tt.cnt != 1);
ck_assert_int_eq(uc_timers_count(&timers), 0);
fail_if(uc_timer_running(&timer) != 0);
}
END_TEST
START_TEST (test_timers_add_from_callback)
{
struct UCoreSettableClock clk;
struct TimerTest tt;
struct UCTimers timers;
struct UCTimer timer;
int t = TEST_TIMER_START;
int rc;
common_init(&clk, &tt, &timers, &timer);
timer.callback = timer_test_cb_add;
uc_timers_add(&timers, &timer, 10, 0);
//10 seconds into the future, our timer should fire
t += 10;
uc_settable_clock_set(&clk, t, 0);
rc = uc_timers_run(&timers);
fail_if(rc != 1);
fail_if(tt.cnt != 1);
//20 seconds into the future, our timer should fire again
t += 10;
uc_settable_clock_set(&clk, t, 0);
rc = uc_timers_run(&timers);
fail_if(rc != 1);
fail_if(tt.cnt != 2);
fail_if(uc_timer_running(&timer) == 0);
ck_assert_int_eq(uc_timers_count(&timers), 1);
}
END_TEST
START_TEST (test_timers_remove_from_callback)
{
struct UCoreSettableClock clk;
struct TimerTest tt;
struct UCTimers timers;
struct UCTimer timer;
struct UCTimer timer2;
int t = TEST_TIMER_START;
int rc;
struct timeval tv = {0, 0};
common_init(&clk, &tt, &timers, &timer);
timer.callback = timer_test_cb_remove;
timer.cookie_ptr = &timer2;
memset(&timer2, 0, sizeof timer2);
timer2.callback = timer_test_cb;
uc_timers_add(&timers, &timer, 5, 0);
uc_timers_add(&timers, &timer2, 10, 0);
ck_assert_int_eq(uc_timers_count(&timers), 2);
rc = uc_timers_first(&timers, &tv);
fail_if(rc != 0);
fail_if(tv.tv_sec != TEST_TIMER_START + 5);
fail_if(uc_timer_running(&timer) == 0);
fail_if(uc_timer_running(&timer2) == 0);
//5 seconds into the future, our timer should fire
t += 5;
uc_settable_clock_set(&clk, t, 0);
rc = uc_timers_run(&timers);
fail_if(rc != 1);
fail_if(tt.cnt != 0);
//and our timer2 should be removed, and timer has fired so it
//should be removed too
ck_assert_int_eq(uc_timers_count(&timers), 0);
fail_if(uc_timer_running(&timer) != 0);
fail_if(uc_timer_running(&timer2) != 0);
rc = uc_timers_first(&timers, &tv);
fail_if(rc == 0);
}
END_TEST
START_TEST (test_timers_add_remove)
{
struct UCoreSettableClock clk;
struct TimerTest tt;
struct UCTimers timers;
struct UCTimer timer[1023];
struct timeval first;
size_t i;
int toggle = 5;
common_init(&clk, &tt, &timers, &timer[0]);
memset(&timer, 0, sizeof timer);
for (i = 0; i < sizeof timer/sizeof timer[0]; i++) {
timer[i].callback = timer_test_cb_add;
uc_timers_add(&timers, &timer[i], toggle + i , 0);
if (i > 5) //just to add timeouts non-ascending order
toggle = 5 - toggle;
}
fail_if(uc_timers_first(&timers, &first) != 0);
fail_if(first.tv_sec != TEST_TIMER_START + 5);
fail_if(first.tv_usec != 0);
ck_assert_int_eq(uc_timers_count(&timers), sizeof timer/sizeof timer[0]);
for (i = 0; i < sizeof timer/sizeof timer[0]; i++) {
uc_timers_remove(&timers, &timer[i]);
}
ck_assert_int_eq(uc_timers_count(&timers), 0);
fail_if(uc_timers_first(&timers, &first) == 0);
}
END_TEST
Suite *timers_suite(void)
{
Suite *s = suite_create("timers");
TCase *tc = tcase_create("timers tests");
tcase_add_test(tc, test_timers_simple);
tcase_add_test(tc, test_timers_add_from_callback);
tcase_add_test(tc, test_timers_remove_from_callback);
tcase_add_test(tc, test_timers_add_remove);
suite_add_tcase(s, tc);
return s;
}