summaryrefslogtreecommitdiff
path: root/tests/common/test_contracts.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 00:09:38 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 00:09:38 +0300
commit624d1371304a5ae4b3429ad5e4267aac7cd03dfd (patch)
tree32de069f6eec83686521fc4bf39cc9874b123e93 /tests/common/test_contracts.c
parente813252e685d761235ad45e170d97c9375f51958 (diff)
missing impls and hardening
Diffstat (limited to 'tests/common/test_contracts.c')
-rw-r--r--tests/common/test_contracts.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/tests/common/test_contracts.c b/tests/common/test_contracts.c
new file mode 100644
index 0000000..65eebcd
--- /dev/null
+++ b/tests/common/test_contracts.c
@@ -0,0 +1,175 @@
+#include "common/backend.h"
+#include "common/input.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void test_queue(void)
+{
+ struct input_queue q = {0};
+ struct yasl_surface surface = {0};
+ const enum yasl_input_kind kinds[] = {
+ YASL_INPUT_TEXT, YASL_INPUT_PASTE, YASL_INPUT_DROP_FILES,
+ };
+ for (size_t k = 0; k < sizeof(kinds) / sizeof(kinds[0]); k++) {
+ char *source = malloc(4);
+ assert(source);
+ memcpy(source, "a\0b", 4);
+ struct yasl_input_event in = {.surface = &surface, .kind = kinds[k]};
+ if (in.kind == YASL_INPUT_TEXT) { in.text.text = source; in.text.len = 3; }
+ if (in.kind == YASL_INPUT_PASTE) { in.paste.text = source; in.paste.len = 3; }
+ if (in.kind == YASL_INPUT_DROP_FILES) { in.drop_files.files = source; in.drop_files.len = 3; }
+ assert(input_queue_push(&q, &in));
+ memset(source, 'x', 4);
+ free(source);
+ struct yasl_input_event out;
+ assert(input_queue_pop(&q, &out));
+ const char *payload = out.kind == YASL_INPUT_TEXT ? out.text.text :
+ out.kind == YASL_INPUT_PASTE ? out.paste.text : out.drop_files.files;
+ assert(out.surface == &surface && out.kind == kinds[k]);
+ assert(memcmp(payload, "a\0b", 4) == 0);
+ assert(!input_queue_pop(&q, &out));
+ assert(memcmp(payload, "a\0b", 4) == 0);
+ /* Growth/wraparound must not invalidate a previously polled payload. */
+ for (unsigned i = 0; i < 4096; i++) {
+ in = (struct yasl_input_event){.kind = YASL_INPUT_KEY, .key.key = i};
+ assert(input_queue_push(&q, &in));
+ }
+ assert(memcmp(payload, "a\0b", 4) == 0);
+ for (unsigned i = 0; i < 2048; i++) {
+ assert(input_queue_pop(&q, &out));
+ assert(out.key.key == i);
+ }
+ for (unsigned i = 4096; i < 6144; i++) {
+ in.key.key = i;
+ assert(input_queue_push(&q, &in));
+ }
+ for (unsigned i = 2048; i < 6144; i++) {
+ assert(input_queue_pop(&q, &out));
+ assert(out.key.key == i);
+ }
+ assert(!input_queue_pop(&q, &out));
+ }
+ struct yasl_input_event empty = {.surface = &surface, .kind = YASL_INPUT_PASTE};
+ struct yasl_input_event out;
+ assert(input_queue_push(&q, &empty));
+ assert(input_queue_pop(&q, &out));
+ assert(out.paste.text && !out.paste.len && out.paste.text[0] == '\0');
+ struct yasl_input_event in = {.surface = &surface, .kind = YASL_INPUT_TEXT,
+ .text = {"owned", 5}};
+ assert(input_queue_push(&q, &in));
+ assert(input_queue_pop(&q, &out));
+ const char *last = out.text.text;
+ assert(input_queue_push(&q, &in));
+ /* Exercise the allocation-failure reset path without allocating huge RAM. */
+ in.text.len = SIZE_MAX;
+ assert(!input_queue_push(&q, &in));
+ assert(strcmp(last, "owned") == 0);
+ in = (struct yasl_input_event){.surface = &surface, .kind = YASL_INPUT_KEY};
+ assert(input_queue_push(&q, &in));
+ assert(input_queue_pop(&q, &out) && out.kind == YASL_INPUT_RESET);
+ assert(out.surface == &surface);
+ assert(input_queue_pop(&q, &out) && out.kind == YASL_INPUT_KEY);
+ assert(!input_queue_pop(&q, &out));
+ in = (struct yasl_input_event){.kind = YASL_INPUT_PASTE, .paste = {"pending", 7}};
+ assert(input_queue_push(&q, &in));
+ input_queue_clear(&q);
+ input_queue_clear(&q);
+ assert(!q.events && !q.last_text && !q.count && !q.reset_pending);
+}
+
+static int presents, copies, pastes, creates;
+static struct yasl_damage_list received;
+static bool present(struct yasl_surface *s, const struct yasl_framebuffer *fb,
+ const struct yasl_damage_list *damage)
+{
+ (void)s; (void)fb;
+ presents++;
+ received = *damage;
+ return true;
+}
+static uint32_t caps(const struct yasl_display *d) { (void)d; return 0; }
+static void copy(struct yasl_display *d, enum yasl_selection sel, const char *text)
+{ (void)d; (void)sel; (void)text; copies++; }
+static void paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *s)
+{ (void)d; (void)sel; (void)s; pastes++; }
+static struct yasl_surface *create(struct yasl_display *d, const struct yasl_surface_spec *spec)
+{ (void)d; (void)spec; creates++; return NULL; }
+
+static void test_validation(void)
+{
+ const struct yasl_backend_ops ops = {.surface_present = present,
+ .display_caps = caps, .display_copy = copy, .display_paste = paste,
+ .surface_create_toplevel = create};
+ struct yasl_display d = {.ops = &ops};
+ struct yasl_surface s = {.display = &d, .frame_generation = 1};
+ struct yasl_framebuffer fb = {.generation = 1, .size = {100, 80}};
+ struct yasl_damage_list damage = {.n = -2};
+ assert(!yasl_surface_present(&s, &fb, &damage));
+ damage.n = YASL_DAMAGE_MAX + 1;
+ assert(!yasl_surface_present(&s, &fb, &damage));
+ damage.n = 1;
+ damage.rects[0] = (struct yasl_rect2i){0, 0, -1, 1};
+ assert(!yasl_surface_present(&s, &fb, &damage));
+ assert(!yasl_surface_present(&s, &fb, NULL));
+ assert(!presents);
+ damage.n = -1;
+ fb.generation = 0;
+ assert(!yasl_surface_present(&s, &fb, &damage));
+ fb.generation = 2;
+ assert(!yasl_surface_present(&s, &fb, &damage));
+ fb.generation = 1;
+ damage.n = 4;
+ damage.rects[0] = (struct yasl_rect2i){-10, -10, 30, 30};
+ damage.rects[1] = (struct yasl_rect2i){90, 70, INT_MAX, INT_MAX};
+ damage.rects[2] = (struct yasl_rect2i){INT_MAX, INT_MAX, INT_MAX, INT_MAX};
+ damage.rects[3] = (struct yasl_rect2i){INT_MIN, INT_MIN, INT_MAX, INT_MAX};
+ assert(yasl_surface_present(&s, &fb, &damage));
+ assert(received.n == 2 && received.rects[0].x == 0 && received.rects[0].width == 20);
+ assert(received.rects[1].width == 10 && received.rects[1].height == 10);
+ assert(damage.n == 4 && damage.rects[0].x == -10);
+ damage.n = -1;
+ assert(yasl_surface_present(&s, &fb, &damage) && received.n == -1);
+ damage.n = 0;
+ assert(yasl_surface_present(&s, &fb, &damage) && received.n == 0);
+ yasl_display_copy(&d, YASL_PRIMARY, "no alias");
+ yasl_display_copy(&d, (enum yasl_selection)255, "invalid");
+ yasl_display_paste(&d, YASL_PRIMARY, &s);
+ yasl_display_paste(&d, (enum yasl_selection)255, &s);
+ assert(!copies && !pastes);
+ yasl_display_copy(&d, YASL_CLIPBOARD, "yes");
+ yasl_display_paste(&d, YASL_CLIPBOARD, &s);
+ assert(copies == 1 && pastes == 1);
+ struct yasl_surface_spec spec = {.size = {100, 80}, .graphics_device = &d};
+ assert(!yasl_surface_create_toplevel(&d, &spec) && errno == ENOTSUP);
+ spec.graphics_device = NULL;
+ spec.size.x = 0;
+ assert(!yasl_surface_create_toplevel(&d, &spec) && errno == EINVAL);
+ assert(!creates);
+}
+
+static void test_scale(void)
+{
+ assert(yasl_scale_to_device(-10, 120) == -10);
+ assert(yasl_scale_to_device(-0.5, 120) == -1);
+ assert(yasl_scale_to_device(0.5, 120) == 1);
+ assert(yasl_scale_to_device(NAN, 120) == 0);
+ assert(yasl_scale_to_device(INFINITY, 120) == 0);
+ assert(yasl_scale_to_device(DBL_MAX, 240) == INT_MAX);
+ assert(yasl_scale_to_logical(-1, 240) == -1);
+ assert(yasl_scale_to_logical(1, 240) == 1);
+ assert(yasl_scale_to_logical(INT_MAX, 1) == INT_MAX);
+ assert(yasl_scale_to_logical(INT_MIN, 1) == INT_MIN);
+ assert(yasl_scale_to_logical(1, 0) == 0);
+}
+
+int main(void)
+{
+ test_queue();
+ test_validation();
+ test_scale();
+ return 0;
+}