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);
setup.shell = SHELL_IVI;
setup.config_file = TESTSUITE_IVI_CONFIG_PATH;
setup.logging_scopes = "log,test-harness-plugin,proto";
return weston_test_harness_execute_as_client(harness, &setup);
}
@ -84,4 +85,6 @@ TEST(ivi_application_exists)
client_roundtrip(client);
testlog("Successful bind: %p\n", iviapp);
client_destroy(client);
}

@ -724,6 +724,15 @@ static const struct wl_output_listener output_listener = {
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
handle_global(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
@ -741,6 +750,13 @@ handle_global(void *data, struct wl_registry *registry,
global->version = version;
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) {
client->wl_compositor =
wl_registry_bind(registry, id,
@ -766,6 +782,7 @@ handle_global(void *data, struct wl_registry *registry,
&wl_output_interface, version);
wl_output_add_listener(output->wl_output,
&output_listener, output);
wl_list_insert(&client->output_list, &output->link);
client->output = output;
} else if (strcmp(interface, "weston_test") == 0) {
test = xzalloc(sizeof *test);
@ -805,6 +822,14 @@ client_find_input_with_name(struct client *client, uint32_t name)
return NULL;
}
static void
global_destroy(struct global *global)
{
wl_list_remove(&global->link);
free(global->interface);
free(global);
}
static void
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);
free(global->interface);
free(global);
/* XXX: handle wl_output */
global_destroy(global);
}
static const struct wl_registry_listener registry_listener = {
@ -916,6 +941,7 @@ create_client(void)
assert(client->wl_display);
wl_list_init(&client->global_list);
wl_list_init(&client->inputs);
wl_list_init(&client->output_list);
/* setup registry so we can bind to interfaces */
client->wl_registry = wl_display_get_registry(client->wl_display);
@ -965,6 +991,16 @@ create_test_surface(struct client *client)
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 *
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;
}
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*
output_path(void)
{

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

Loading…
Cancel
Save