tests: implement client_destroy()

It turns out that if the client is not explicitly destroyed, it will remain
connected until the compositor shuts down because there is no more a client
process that would terminate.

Usually this is not a problem, but if a test file has multiple screenshooting
tests, the windows from earlier tests in the file will remain on screen. That
is not wanted, hence implement client destruction.

To properly destroy a client, we also need a list of outputs. They used to be
simply leaked. This does not fix wl_registry.global_remove for wl_outputs, that
is left for a time when a test will actually need that.

This patch makes only ivi-shell-app test use the new client_destroy() to show
that it actually works. The added log scopes prove it: destroy requests get
sent. Sprinkling client_destroy() around in all other tests is left for a time
when it is actually necessary.

ivi-shell-app is a nicely simple test doing little else, hence I picked it.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
dev
Pekka Paalanen 5 years ago
parent 444f1a8e22
commit 080d85b8fb
  1. 3
      tests/ivi-shell-app-test.c
  2. 82
      tests/weston-test-client-helper.c
  3. 10
      tests/weston-test-client-helper.h

@ -41,6 +41,7 @@ fixture_setup(struct weston_test_harness *harness)
compositor_setup_defaults(&setup); compositor_setup_defaults(&setup);
setup.shell = SHELL_IVI; setup.shell = SHELL_IVI;
setup.config_file = TESTSUITE_IVI_CONFIG_PATH; setup.config_file = TESTSUITE_IVI_CONFIG_PATH;
setup.logging_scopes = "log,test-harness-plugin,proto";
return weston_test_harness_execute_as_client(harness, &setup); return weston_test_harness_execute_as_client(harness, &setup);
} }
@ -84,4 +85,6 @@ TEST(ivi_application_exists)
client_roundtrip(client); client_roundtrip(client);
testlog("Successful bind: %p\n", iviapp); testlog("Successful bind: %p\n", iviapp);
client_destroy(client);
} }

@ -724,6 +724,15 @@ static const struct wl_output_listener output_listener = {
output_handle_scale, output_handle_scale,
}; };
static void
output_destroy(struct output *output)
{
assert(wl_proxy_get_version((struct wl_proxy *)output->wl_output) >= 3);
wl_output_release(output->wl_output);
wl_list_remove(&output->link);
free(output);
}
static void static void
handle_global(void *data, struct wl_registry *registry, handle_global(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version) uint32_t id, const char *interface, uint32_t version)
@ -741,6 +750,13 @@ handle_global(void *data, struct wl_registry *registry,
global->version = version; global->version = version;
wl_list_insert(client->global_list.prev, &global->link); wl_list_insert(client->global_list.prev, &global->link);
/* We deliberately bind all globals with the maximum (advertised)
* version, because this test suite must be kept up-to-date with
* Weston. We must always implement at least the version advertised
* by Weston. This is not ok for normal clients, but it is ok in
* this test suite.
*/
if (strcmp(interface, "wl_compositor") == 0) { if (strcmp(interface, "wl_compositor") == 0) {
client->wl_compositor = client->wl_compositor =
wl_registry_bind(registry, id, wl_registry_bind(registry, id,
@ -766,6 +782,7 @@ handle_global(void *data, struct wl_registry *registry,
&wl_output_interface, version); &wl_output_interface, version);
wl_output_add_listener(output->wl_output, wl_output_add_listener(output->wl_output,
&output_listener, output); &output_listener, output);
wl_list_insert(&client->output_list, &output->link);
client->output = output; client->output = output;
} else if (strcmp(interface, "weston_test") == 0) { } else if (strcmp(interface, "weston_test") == 0) {
test = xzalloc(sizeof *test); test = xzalloc(sizeof *test);
@ -805,6 +822,14 @@ client_find_input_with_name(struct client *client, uint32_t name)
return NULL; return NULL;
} }
static void
global_destroy(struct global *global)
{
wl_list_remove(&global->link);
free(global->interface);
free(global);
}
static void static void
handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
{ {
@ -824,9 +849,9 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
} }
} }
wl_list_remove(&global->link); /* XXX: handle wl_output */
free(global->interface);
free(global); global_destroy(global);
} }
static const struct wl_registry_listener registry_listener = { static const struct wl_registry_listener registry_listener = {
@ -916,6 +941,7 @@ create_client(void)
assert(client->wl_display); assert(client->wl_display);
wl_list_init(&client->global_list); wl_list_init(&client->global_list);
wl_list_init(&client->inputs); wl_list_init(&client->inputs);
wl_list_init(&client->output_list);
/* setup registry so we can bind to interfaces */ /* setup registry so we can bind to interfaces */
client->wl_registry = wl_display_get_registry(client->wl_display); client->wl_registry = wl_display_get_registry(client->wl_display);
@ -965,6 +991,16 @@ create_test_surface(struct client *client)
return surface; return surface;
} }
void
surface_destroy(struct surface *surface)
{
if (surface->wl_surface)
wl_surface_destroy(surface->wl_surface);
if (surface->buffer)
buffer_destroy(surface->buffer);
free(surface);
}
struct client * struct client *
create_client_and_test_surface(int x, int y, int width, int height) create_client_and_test_surface(int x, int y, int width, int height)
{ {
@ -999,6 +1035,46 @@ create_client_and_test_surface(int x, int y, int width, int height)
return client; return client;
} }
void
client_destroy(struct client *client)
{
if (client->surface)
surface_destroy(client->surface);
while (!wl_list_empty(&client->inputs)) {
input_destroy(container_of(client->inputs.next,
struct input, link));
}
while (!wl_list_empty(&client->output_list)) {
output_destroy(container_of(client->output_list.next,
struct output, link));
}
while (!wl_list_empty(&client->global_list)) {
global_destroy(container_of(client->global_list.next,
struct global, link));
}
if (client->test) {
weston_test_destroy(client->test->weston_test);
free(client->test);
}
if (client->wl_shm)
wl_shm_destroy(client->wl_shm);
if (client->wl_compositor)
wl_compositor_destroy(client->wl_compositor);
if (client->wl_registry)
wl_registry_destroy(client->wl_registry);
client_roundtrip(client);
if (client->wl_display)
wl_display_disconnect(client->wl_display);
free(client);
}
static const char* static const char*
output_path(void) output_path(void)
{ {

@ -57,6 +57,7 @@ struct client {
int has_argb; int has_argb;
struct wl_list global_list; struct wl_list global_list;
bool has_wl_drm; bool has_wl_drm;
struct wl_list output_list; /* struct output::link */
}; };
struct global { struct global {
@ -145,6 +146,7 @@ struct touch {
struct output { struct output {
struct wl_output *wl_output; struct wl_output *wl_output;
struct wl_list link; /* struct client::output_list */
int x; int x;
int y; int y;
int width; int width;
@ -161,7 +163,7 @@ struct buffer {
struct surface { struct surface {
struct wl_surface *wl_surface; struct wl_surface *wl_surface;
struct output *output; struct output *output; /* not owned */
int x; int x;
int y; int y;
int width; int width;
@ -184,9 +186,15 @@ struct range {
struct client * struct client *
create_client(void); create_client(void);
void
client_destroy(struct client *client);
struct surface * struct surface *
create_test_surface(struct client *client); create_test_surface(struct client *client);
void
surface_destroy(struct surface *surface);
struct client * struct client *
create_client_and_test_surface(int x, int y, int width, int height); create_client_and_test_surface(int x, int y, int width, int height);

Loading…
Cancel
Save