From 624d1371304a5ae4b3429ad5e4267aac7cd03dfd Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Mon, 12 Oct 2026 00:09:38 +0300 Subject: missing impls and hardening --- tests/common/test_backends.c | 92 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 5 deletions(-) (limited to 'tests/common/test_backends.c') diff --git a/tests/common/test_backends.c b/tests/common/test_backends.c index 48a6b68..3372290 100644 --- a/tests/common/test_backends.c +++ b/tests/common/test_backends.c @@ -67,7 +67,24 @@ static void draw(struct yasl_surface *s, struct yasl_frame *frame, void *ud) assert(size.x == frame->target.size.x && size.y == frame->target.size.y); assert(frame->target.pixels); for (int i = 0; i < size.x * size.y; i++) frame->target.pixels[i] = 0xff4080c0; - struct yasl_damage_list damage = {.n = -1}; + struct yasl_damage_list damage = {.n = YASL_DAMAGE_MAX + 1}; + assert(!yasl_surface_present(s, &frame->target, &damage)); + damage.n = -2; + assert(!yasl_surface_present(s, &frame->target, &damage)); + damage.n = 1; + damage.rects[0].width = -1; + assert(!yasl_surface_present(s, &frame->target, &damage)); + damage.n = -1; + struct yasl_framebuffer invalid = frame->target; + invalid.buffer++; + assert(!yasl_surface_present(s, &invalid, &damage)); + invalid = frame->target; + invalid.generation--; + assert(!yasl_surface_present(s, &invalid, &damage)); + invalid = frame->target; + invalid.native_drawable = (void *)(uintptr_t)1; + assert(!yasl_surface_present(s, &invalid, &damage)); + assert(!yasl_surface_present(s, &frame->target, NULL)); assert(yasl_surface_present(s, &frame->target, &damage)); assert(!yasl_surface_present(s, &frame->target, &damage)); w->draws++; @@ -98,12 +115,22 @@ static const struct yasl_surface_cbs callbacks = { .draw = draw, .configure = configure, .close = close_window, }; +static void attach(struct window *w) +{ + struct yasl_surface_cbs temporary = callbacks; + yasl_surface_set_callbacks(w->surface, &temporary, w); + temporary.draw = NULL; + temporary.configure = NULL; + temporary.close = NULL; +} + static struct window create(struct yasl_display *d) { struct yasl_surface_spec spec = {.title = "Backend test", .size = {160, 100}}; struct yasl_surface *s = yasl_surface_create_toplevel(d, &spec); assert(s); assert(yasl_surface_display(s) == d); + assert(yasl_surface_timing(s).source == YASL_TIMING_UNKNOWN); return (struct window){.surface = s, .display = d}; } @@ -153,6 +180,61 @@ static void x11_behavior(struct yasl_loop *loop, struct yasl_display *d, struct } } assert(saw_key && saw_paste); + assert(yasl_surface_timing(w->surface).source == YASL_TIMING_SUBMISSION); + assert(!(yasl_display_caps(d) & YASL_CAP_FRAME_PACING)); + + /* Reuse caller storage, replace the selection, and exceed the old queue + * cap before polling: each paste must retain its own original contents. */ + for (int i = 0; i < 300; i++) { + char text[32]; + snprintf(text, sizeof(text), "owned-%d", i); + yasl_display_copy(d, YASL_CLIPBOARD, text); + yasl_display_paste(d, YASL_CLIPBOARD, w->surface); + memset(text, 'x', sizeof(text)); + } + for (int i = 0; i < 300; i++) { + char text[32]; + snprintf(text, sizeof(text), "owned-%d", i); + assert(yasl_surface_input_poll(w->surface, &event)); + assert(event.kind == YASL_INPUT_PASTE && strcmp(event.paste.text, text) == 0); + } + const char *last = event.paste.text; + assert(!yasl_surface_input_poll(w->surface, &event)); + yasl_display_copy(d, YASL_CLIPBOARD, "changed"); + pump(loop, d, NULL); + assert(strcmp(last, "owned-299") == 0); + yasl_display_copy(d, YASL_CLIPBOARD, ""); + yasl_display_paste(d, YASL_CLIPBOARD, w->surface); + assert(yasl_surface_input_poll(w->surface, &event)); + assert(event.kind == YASL_INPUT_PASTE && !event.paste.len && !event.paste.text[0]); + + /* Concurrent external conversions must not share a mutable target slot. */ + struct yasl_display_spec ds = {.backend = YASL_BACKEND_X11}; + struct yasl_display *owner = yasl_display_open(loop, &ds); + assert(owner); + yasl_display_copy(owner, YASL_CLIPBOARD, "external"); + struct window other = create(d), cancelled = create(d); + yasl_display_paste(d, YASL_CLIPBOARD, w->surface); + yasl_display_paste(d, YASL_CLIPBOARD, other.surface); + yasl_display_paste(d, YASL_CLIPBOARD, cancelled.surface); + yasl_surface_destroy(cancelled.surface); + pump(loop, d, owner); + int first_pastes = 0, second_pastes = 0; + while (yasl_surface_input_poll(w->surface, &event)) { + if (event.kind == YASL_INPUT_PASTE) { + assert(strcmp(event.paste.text, "external") == 0); + first_pastes++; + } + } + while (yasl_surface_input_poll(other.surface, &event)) { + if (event.kind == YASL_INPUT_PASTE) { + assert(strcmp(event.paste.text, "external") == 0); + second_pastes++; + } + } + assert(first_pastes == 1 && second_pastes == 1); + yasl_surface_destroy(other.surface); + yasl_display_close(owner); key.xclient = (XClientMessageEvent){.type = ClientMessage, .display = native, .window = window, .message_type = XInternAtom(native, "WM_PROTOCOLS", False), .format = 32, .data.l = {(long)XInternAtom(native, "WM_DELETE_WINDOW", False)}}; @@ -177,8 +259,8 @@ int main(int argc, char **argv) struct yasl_display *b = yasl_display_open(loop, &spec); assert(a && b); struct window wa = create(a), wb = create(b); - yasl_surface_set_callbacks(wa.surface, &callbacks, &wa); - yasl_surface_set_callbacks(wb.surface, &callbacks, &wb); + attach(&wa); + attach(&wb); pump(loop, a, b); assert(wa.draws && wb.draws); yasl_surface_destroy(wa.surface); @@ -195,7 +277,7 @@ int main(int argc, char **argv) struct window w = create(d); pump(loop, d, NULL); assert(w.draws == 0); - yasl_surface_set_callbacks(w.surface, &callbacks, &w); + attach(&w); yasl_surface_schedule_redraw(w.surface); pump(loop, d, NULL); assert(w.draws > 0); @@ -204,7 +286,7 @@ int main(int argc, char **argv) if (w.surface) yasl_surface_destroy(w.surface); w = create(d); w.destroy_on_draw = true; - yasl_surface_set_callbacks(w.surface, &callbacks, &w); + attach(&w); pump(loop, d, NULL); assert(w.draws && !w.surface); yasl_display_close(d); -- cgit v1.2.3