From 7514bf7e454f93aa84b062be4d82fac1559d7898 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 21 May 2021 16:03:08 +0300 Subject: [PATCH] tests: proper weston_test_surface_create() struct weston_test_surface in the test harness' compositor plugin had no tear down code, which lead to ASan report on alpha-blending test: Direct leak of 64 byte(s) in 2 object(s) allocated from: #0 0x7f8931f10330 in __interceptor_malloc (/lib/x86_64-linux-gnu/libasan.so.5+0xe9330) #1 0x7f892d934425 in move_surface ../../git/weston/tests/weston-test.c:181 #2 0x7f893159d8ed in ffi_call_unix64 (/lib/x86_64-linux-gnu/libffi.so.6+0x68ed) While at it, let's do this properly for once: - put the creation in a new function - hook up to the weston_surface destroy signal so this actually gets freed (fixes the leak) - check that we don't overwrite another surface role - check that committed_private actually is ours - set the surface label func so it gets properly listed in debugs and traces - use the proper surface role setup call, so no-one stomps on anyones toes if a test makes a mistake by using a wrong wl_surface Signed-off-by: Pekka Paalanen --- tests/weston-test.c | 113 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 19 deletions(-) diff --git a/tests/weston-test.c b/tests/weston-test.c index be80bf92..772e5d03 100644 --- a/tests/weston-test.c +++ b/tests/weston-test.c @@ -67,6 +67,7 @@ struct weston_test { struct weston_test_surface { struct weston_surface *surface; + struct wl_listener surface_destroy_listener; struct weston_view *view; int32_t x, y; struct weston_test *test; @@ -167,6 +168,84 @@ test_surface_committed(struct weston_surface *surface, int32_t sx, int32_t sy) test_surface->view->is_mapped = true; } +static int +test_surface_get_label(struct weston_surface *surface, char *buf, size_t len) +{ + return snprintf(buf, len, "test suite surface"); +} + +static void +test_surface_destroy(struct weston_test_surface *test_surface) +{ + weston_view_destroy(test_surface->view); + + test_surface->surface->committed = NULL; + test_surface->surface->committed_private = NULL; + weston_surface_set_label_func(test_surface->surface, NULL); + + wl_list_remove(&test_surface->surface_destroy_listener.link); + free(test_surface); +} + +static void +test_surface_handle_surface_destroy(struct wl_listener *l, void *data) +{ + struct weston_test_surface *test_surface = + wl_container_of(l, test_surface, surface_destroy_listener); + + assert(test_surface->surface == data); + + test_surface_destroy(test_surface); +} + +static struct weston_test_surface * +weston_test_surface_create(struct wl_resource *test_resource, + struct weston_surface *surface) +{ + struct wl_client *client = wl_resource_get_client(test_resource); + struct wl_resource *display_resource; + struct weston_test_surface *test_surface; + + test_surface = zalloc(sizeof *test_surface); + if (!test_surface) + goto err_post_no_mem; + + test_surface->surface = surface; + test_surface->test = wl_resource_get_user_data(test_resource); + + test_surface->view = weston_view_create(surface); + if (!test_surface->view) + goto err_free_surface; + + /* Protocol does not define this error so abuse wl_display */ + display_resource = wl_client_get_object(client, 1); + if (weston_surface_set_role(surface, "weston_test_surface", + display_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT) < 0) + goto err_free_view; + + surface->committed_private = test_surface; + surface->committed = test_surface_committed; + weston_surface_set_label_func(surface, test_surface_get_label); + + test_surface->surface_destroy_listener.notify = + test_surface_handle_surface_destroy; + wl_signal_add(&surface->destroy_signal, + &test_surface->surface_destroy_listener); + + return test_surface; + +err_free_view: + weston_view_destroy(test_surface->view); + +err_free_surface: + free(test_surface); + +err_post_no_mem: + wl_resource_post_no_memory(test_resource); + return NULL; +} + static void move_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, @@ -175,28 +254,24 @@ move_surface(struct wl_client *client, struct wl_resource *resource, struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct weston_test_surface *test_surface; + struct wl_resource *display_resource; + + if (surface->committed && + surface->committed != test_surface_committed) { + display_resource = wl_client_get_object(client, 1); + wl_resource_post_error(display_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "weston_test.move_surface: wl_surface@%u has a role.", + wl_resource_get_id(surface_resource)); + return; + } test_surface = surface->committed_private; - if (!test_surface) { - test_surface = malloc(sizeof *test_surface); - if (!test_surface) { - wl_resource_post_no_memory(resource); - return; - } - - test_surface->view = weston_view_create(surface); - if (!test_surface->view) { - wl_resource_post_no_memory(resource); - free(test_surface); - return; - } - - surface->committed_private = test_surface; - surface->committed = test_surface_committed; - } + if (!test_surface) + test_surface = weston_test_surface_create(resource, surface); + if (!test_surface) + return; - test_surface->surface = surface; - test_surface->test = wl_resource_get_user_data(resource); test_surface->x = x; test_surface->y = y; }