summaryrefslogtreecommitdiff
path: root/tests/common/test_timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/common/test_timers.c')
-rw-r--r--tests/common/test_timers.c128
1 files changed, 86 insertions, 42 deletions
diff --git a/tests/common/test_timers.c b/tests/common/test_timers.c
index 2c3542f..3a35819 100644
--- a/tests/common/test_timers.c
+++ b/tests/common/test_timers.c
@@ -3,15 +3,17 @@
#include "common/types.h"
#include <assert.h>
+#include <signal.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
struct test_ctx {
int count;
uint64_t last_time;
yasl_private_timer_id id;
yasl_private_timer_id other_id;
- struct yasl_private_loop *loop;
+ struct yasl_loop *loop;
struct yasl_surface *surface;
bool done;
};
@@ -21,11 +23,32 @@ static uint64_t oneshot_cb(void *ud, yasl_private_timer_id id, uint64_t interval
{
struct test_ctx *ctx = ud;
assert(id == ctx->id);
- assert(interval_ns > 0);
+ (void)interval_ns;
ctx->count++;
return 0; /* Disarm */
}
+static uint64_t count_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
+{
+ (void)id; (void)interval_ns;
+ (*(int *)ud)++;
+ return 0;
+}
+
+/* Adds enough timers to move the timer array, then repeats itself. */
+static uint64_t grow_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
+{
+ struct test_ctx *ctx = ud;
+ assert(id == ctx->id);
+ if (ctx->count++ == 0) {
+ for (int i = 0; i < 64; i++)
+ assert(yasl_loop_add_timer(ctx->loop, YASL_PRIVATE_MS_TO_NS(60000), count_cb, NULL));
+ return YASL_PRIVATE_MS_TO_NS(2);
+ }
+ assert(interval_ns == YASL_PRIVATE_MS_TO_NS(2));
+ return 0;
+}
+
/* 2. Repeating timer: ticks N times, then returns 0. */
static uint64_t repeat_cb(void *ud, yasl_private_timer_id id, uint64_t interval_ns)
{
@@ -73,7 +96,7 @@ static uint64_t parent_timer_cb(void *ud, yasl_private_timer_id id, uint64_t int
struct test_ctx *ctx = ud;
assert(id == ctx->id);
ctx->count += 1;
- ctx->other_id = yasl_private_loop_add_timer(ctx->loop, 1000000ull, child_timer_cb, ctx);
+ ctx->other_id = yasl_loop_add_timer(ctx->loop, 1000000ull, child_timer_cb, ctx);
assert(ctx->other_id > 0);
return 0;
}
@@ -91,7 +114,7 @@ static uint64_t killer_timer_cb(void *ud, yasl_private_timer_id id, uint64_t int
(void)id; (void)interval_ns;
struct test_ctx *ctx = ud;
ctx->count++;
- assert(yasl_private_loop_del_timer(ctx->loop, ctx->other_id));
+ assert(yasl_loop_del_timer(ctx->loop, ctx->other_id));
return 0;
}
@@ -111,90 +134,109 @@ static uint64_t ms_timer_cb(void *ud, yasl_private_timer_id id, uint64_t interva
static void test_loop_timers(void)
{
- struct yasl_private_loop *l = yasl_private_loop_create();
+ struct yasl_loop *l = yasl_loop_create();
assert(l);
/* Invalid arguments */
- assert(yasl_private_loop_add_timer(NULL, 1000, oneshot_cb, NULL) == 0);
- assert(yasl_private_loop_add_timer(l, 0, oneshot_cb, NULL) == 0);
- assert(yasl_private_loop_add_timer(l, 1000, NULL, NULL) == 0);
- assert(!yasl_private_loop_del_timer(NULL, 1));
- assert(!yasl_private_loop_del_timer(l, 0));
- assert(!yasl_private_loop_del_timer(l, 99999));
+ assert(yasl_loop_add_timer(NULL, 1000, oneshot_cb, NULL) == 0);
+ assert(yasl_loop_add_timer(l, 1000, NULL, NULL) == 0);
+ assert(!yasl_loop_del_timer(NULL, 1));
+ assert(!yasl_loop_del_timer(l, 0));
+ assert(!yasl_loop_del_timer(l, 99999));
assert(yasl_private_loop_next_timeout_ms(l) == -1);
/* Test 1: Single-shot */
struct test_ctx ctx1 = { .loop = l };
- ctx1.id = yasl_private_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx1);
+ ctx1.id = yasl_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx1);
assert(ctx1.id > 0);
assert(yasl_private_loop_next_timeout_ms(l) >= 0);
while (ctx1.count == 0) {
- int handled = yasl_private_loop_step(l, 50);
+ int handled = yasl_loop_step(l, 50);
assert(handled >= 0);
}
assert(ctx1.count == 1);
/* Should be disarmed and removed */
- assert(!yasl_private_loop_del_timer(l, ctx1.id));
+ assert(!yasl_loop_del_timer(l, ctx1.id));
assert(yasl_private_loop_next_timeout_ms(l) == -1);
/* Test 2: Repeating */
struct test_ctx ctx2 = { .loop = l };
- ctx2.id = yasl_private_loop_add_timer(l, 2000000ull, repeat_cb, &ctx2);
+ ctx2.id = yasl_loop_add_timer(l, 2000000ull, repeat_cb, &ctx2);
assert(ctx2.id > 0);
while (!ctx2.done) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx2.count == 5);
- assert(!yasl_private_loop_del_timer(l, ctx2.id));
+ assert(!yasl_loop_del_timer(l, ctx2.id));
/* Test 3: Reschedule dynamically */
struct test_ctx ctx3 = { .loop = l };
- ctx3.id = yasl_private_loop_add_timer(l, 2000000ull, reschedule_cb, &ctx3);
+ ctx3.id = yasl_loop_add_timer(l, 2000000ull, reschedule_cb, &ctx3);
assert(ctx3.id > 0);
while (!ctx3.done) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx3.count == 2);
/* Test 4: Timer cancellation before firing */
struct test_ctx ctx4 = { .loop = l };
- yasl_private_timer_id cancel_id = yasl_private_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx4);
+ yasl_private_timer_id cancel_id = yasl_loop_add_timer(l, 5000000ull, oneshot_cb, &ctx4);
assert(cancel_id > 0);
- assert(yasl_private_loop_del_timer(l, cancel_id));
- assert(!yasl_private_loop_del_timer(l, cancel_id));
+ assert(yasl_loop_del_timer(l, cancel_id));
+ assert(!yasl_loop_del_timer(l, cancel_id));
/* Step for 10ms; timer should not fire */
- yasl_private_loop_step(l, 10);
+ yasl_loop_step(l, 10);
assert(ctx4.count == 0);
/* Test 5: Child timer added inside callback */
struct test_ctx ctx5 = { .loop = l };
- ctx5.id = yasl_private_loop_add_timer(l, 2000000ull, parent_timer_cb, &ctx5);
+ ctx5.id = yasl_loop_add_timer(l, 2000000ull, parent_timer_cb, &ctx5);
while (ctx5.count < 11) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx5.count == 11);
/* Test 6: Killer timer deletes victim timer before victim fires */
struct test_ctx ctx6 = { .loop = l };
- ctx6.id = yasl_private_loop_add_timer(l, 1000000ull, killer_timer_cb, &ctx6);
- ctx6.other_id = yasl_private_loop_add_timer(l, 10000000ull, victim_timer_cb, &ctx6);
+ ctx6.id = yasl_loop_add_timer(l, 1000000ull, killer_timer_cb, &ctx6);
+ ctx6.other_id = yasl_loop_add_timer(l, 10000000ull, victim_timer_cb, &ctx6);
while (ctx6.count == 0) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx6.count == 1);
- yasl_private_loop_step(l, 20);
+ yasl_loop_step(l, 20);
+
+ /* Test 8: Zero delay runs in the next step without waiting, and IDs are
+ * never handed out again. */
+ int zero_runs = 0;
+ yasl_private_timer_id zero = yasl_loop_add_timer(l, 0, count_cb, &zero_runs);
+ assert(zero > 0 && yasl_private_loop_next_timeout_ms(l) == 0);
+ assert(yasl_loop_step(l, -1) == 1 && zero_runs == 1);
+ yasl_private_timer_id next = yasl_loop_add_timer(l, 0, count_cb, &zero_runs);
+ assert(next > zero);
+ assert(!yasl_loop_del_timer(l, zero) && yasl_loop_del_timer(l, next));
+
+ /* Test 9: A callback that grows the timer array still reschedules itself. */
+ struct yasl_loop *grown = yasl_loop_create();
+ assert(grown);
+ struct test_ctx ctx9 = { .loop = grown };
+ ctx9.id = yasl_loop_add_timer(grown, 0, grow_cb, &ctx9);
+ while (ctx9.count < 2)
+ assert(yasl_loop_step(grown, 50) >= 0);
+ assert(!yasl_private_loop_timer_armed(grown, ctx9.id));
+ assert(yasl_loop_destroy(grown) == 0);
/* Test 7: Millisecond conversion */
struct test_ctx ctx7 = { .loop = l };
- ctx7.id = yasl_private_loop_add_timer(l, YASL_PRIVATE_MS_TO_NS(5), ms_timer_cb, &ctx7);
+ ctx7.id = yasl_loop_add_timer(l, YASL_PRIVATE_MS_TO_NS(5), ms_timer_cb, &ctx7);
assert(ctx7.id > 0);
while (!ctx7.done) {
- yasl_private_loop_step(l, 50);
+ yasl_loop_step(l, 50);
}
assert(ctx7.count == 3);
- yasl_private_loop_destroy(l);
+ yasl_loop_destroy(l);
}
/* Surface timer tests */
@@ -220,14 +262,14 @@ static uint64_t surface_suicide_cb(void *ud, yasl_private_timer_id id, uint64_t
static void test_surface_timers(void)
{
- struct yasl_private_loop *loop = yasl_private_loop_create();
+ struct yasl_loop *loop = yasl_loop_create();
assert(loop);
struct yasl_private_display_spec spec = { .app_id = "org.yasl.timer_test" };
struct yasl_private_display *d = yasl_private_display_open(loop, &spec);
if (!d) {
/* Headless without display server */
- yasl_private_loop_destroy(loop);
+ yasl_loop_destroy(loop);
return;
}
@@ -243,10 +285,10 @@ static void test_surface_timers(void)
/* Application timers use the display's loop. */
struct test_ctx dctx = {0};
- dctx.id = yasl_private_loop_add_timer(yasl_private_display_loop(d), 2000000ull, oneshot_cb, &dctx);
+ dctx.id = yasl_loop_add_timer(yasl_private_display_loop(d), 2000000ull, oneshot_cb, &dctx);
assert(dctx.id > 0);
while (dctx.count == 0) {
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
}
assert(dctx.count == 1);
@@ -255,12 +297,12 @@ static void test_surface_timers(void)
sctx.id = yasl_private_surface_add_timer(s, 2000000ull, surface_timer_repeat_cb, &sctx);
assert(sctx.id > 0);
while (sctx.count < 3) {
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
}
assert(sctx.count >= 3);
assert(yasl_private_surface_del_timer(s, sctx.id));
int count_before = sctx.count;
- yasl_private_display_dispatch(d, 10);
+ yasl_loop_step(loop, 10);
assert(sctx.count == count_before);
/* A fired one-shot surface timer is retired, as a loop timer is. Many
@@ -270,7 +312,7 @@ static void test_surface_timers(void)
octx.id = yasl_private_surface_add_timer(s, 1000000ull, oneshot_cb, &octx);
assert(octx.id > 0);
while (octx.count == 0)
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
assert(!yasl_private_surface_del_timer(s, octx.id));
}
@@ -280,7 +322,7 @@ static void test_surface_timers(void)
assert(sctx2.id > 0);
yasl_private_surface_destroy(s);
/* Step display/loop; timer must not fire on dead surface */
- yasl_private_display_dispatch(d, 10);
+ yasl_loop_step(loop, 10);
assert(sctx2.count == 0);
/* Surface suicide from timer callback */
@@ -290,17 +332,19 @@ static void test_surface_timers(void)
sctx3.id = yasl_private_surface_add_timer(s, 2000000ull, surface_suicide_cb, &sctx3);
assert(sctx3.id > 0);
while (sctx3.count == 0) {
- yasl_private_display_dispatch(d, 50);
+ yasl_loop_step(loop, 50);
}
assert(sctx3.count == 1);
assert(sctx3.surface == NULL);
yasl_private_display_close(d);
- yasl_private_loop_destroy(loop);
+ yasl_loop_destroy(loop);
}
int main(void)
{
+ /* A wait that never ends fails here, not at the suite timeout. */
+ alarm(10);
test_loop_timers();
test_surface_timers();
printf("Timer tests passed successfully.\n");