[RFC PATCH wayland v2 4/4] tests: add test for inert objects

Marek Chalupa mchqwerty at gmail.com
Fri Apr 10 06:45:41 PDT 2015


Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
---
 tests/resources-test.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 238 insertions(+)

diff --git a/tests/resources-test.c b/tests/resources-test.c
index a6ce3ae..889f1bb 100644
--- a/tests/resources-test.c
+++ b/tests/resources-test.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2013 Marek Chalupa
+ * Copyright © 2015 Red Hat, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -23,9 +24,13 @@
 #include <assert.h>
 #include <sys/socket.h>
 #include <unistd.h>
+#include <string.h>
+
+#define WL_HIDE_DEPRECATED 1
 
 #include "wayland-server.h"
 #include "test-runner.h"
+#include "test-compositor.h"
 
 TEST(create_resource_tst)
 {
@@ -59,6 +64,10 @@ TEST(create_resource_tst)
 	wl_resource_set_user_data(res, (void *) 0xbee);
 	assert(wl_resource_get_user_data(res) == (void *) 0xbee);
 
+	assert(!wl_resource_is_inert(res));
+	wl_resource_set_inert(res);
+	assert(wl_resource_is_inert(res));
+
 	wl_resource_destroy(res);
 	wl_client_destroy(client);
 	wl_display_destroy(display);
@@ -132,6 +141,57 @@ TEST(destroy_res_tst)
 	close(s[1]);
 }
 
+TEST(destroy_inert_res_tst)
+{
+	struct wl_display *display;
+	struct wl_client *client;
+	struct wl_resource *res;
+	int s[2];
+
+	notify_called = 0;
+	_Bool destroyed = 0;
+	struct wl_listener destroy_listener = {
+		.notify = &destroy_notify
+	};
+
+	assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
+	display = wl_display_create();
+	assert(display);
+	client = wl_client_create(display, s[0]);
+	assert(client);
+
+	res = wl_resource_create(client, &wl_display_interface, 4, 0);
+	assert(res);
+	wl_resource_set_implementation(res, NULL, &destroyed, res_destroy_func);
+	wl_resource_add_destroy_listener(res, &destroy_listener);
+
+	wl_resource_set_inert(res);
+	assert(wl_resource_is_inert(res));
+
+	wl_resource_destroy(res);
+	assert(destroyed);
+	assert(notify_called); /* check if signal was emitted */
+	assert(wl_client_get_object(client, wl_resource_get_id(res)) == NULL);
+
+	res = wl_resource_create(client, &wl_display_interface, 2, 0);
+	assert(res);
+
+	destroyed = 0;
+	notify_called = 0;
+	wl_resource_set_destructor(res, res_destroy_func);
+	wl_resource_set_user_data(res, &destroyed);
+	wl_resource_add_destroy_listener(res, &destroy_listener);
+	wl_resource_set_inert(res);
+
+	/* client should destroy the resource upon its destruction normally */
+	wl_client_destroy(client);
+	assert(destroyed);
+	assert(notify_called);
+
+	wl_display_destroy(display);
+	close(s[1]);
+}
+
 TEST(create_resource_with_same_id)
 {
 	struct wl_display *display;
@@ -163,3 +223,181 @@ TEST(create_resource_with_same_id)
 	wl_display_destroy(display);
 	close(s[1]);
 }
+
+static void
+handle_globals(void *data, struct wl_registry *registry,
+	       uint32_t id, const char *intf, uint32_t ver)
+{
+	struct wl_shm_pool **pool = data;
+
+	if (strcmp(intf, "wl_shm_pool") == 0) {
+		(*pool) = wl_registry_bind(registry, id,
+					   &wl_shm_pool_interface, ver);
+		assert(pool);
+	}
+}
+
+static const struct wl_registry_listener registry_listener = {
+	handle_globals, NULL
+};
+
+static void
+inert_resource_main(void)
+{
+	struct client *cli = client_connect();
+	struct wl_shm_pool *pool;
+	struct wl_registry *reg = wl_display_get_registry(cli->wl_display);
+	assert(reg);
+
+	wl_registry_add_listener(reg, &registry_listener, &pool);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+	assert(pool && "Did not bind to the pool");
+
+	wl_registry_destroy(reg);
+
+	/* let the display make the pool resource inert */
+	stop_display(cli, 1);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+
+	/* these requests should be ignored */
+	wl_shm_pool_resize(pool, 100);
+	wl_shm_pool_resize(pool, 200);
+
+	/* this one should be not */
+	wl_shm_pool_destroy(pool);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+
+	client_disconnect(cli);
+}
+
+static void
+pool_resize(struct wl_client *client,
+	    struct wl_resource *resource,
+	    int32_t size)
+{
+	assert(0 && "This event should be never called");
+}
+
+static int destroyed = 0;
+
+static void
+pool_destroy(struct wl_client *client,
+        struct wl_resource *resource)
+{
+	destroyed = 1;
+}
+
+static const struct wl_shm_pool_interface pool_implementation = {
+	.resize = pool_resize,
+	.destroy = pool_destroy
+};
+
+static void
+pool_bind(struct wl_client *client, void *data,
+	  uint32_t version, uint32_t id)
+{
+	struct display *d = data;
+	struct client_info *ci;
+	struct wl_resource *res;
+
+	wl_list_for_each(ci, &d->clients, link)
+		if (ci->wl_client == client)
+			break;
+
+	res = wl_resource_create(client, &wl_shm_pool_interface,
+				 version, id);
+	assert(res);
+	wl_resource_set_implementation(res, &pool_implementation, NULL, NULL);
+
+	ci->data = res;
+}
+
+TEST(inert_resource)
+{
+	struct client_info *ci;
+	struct wl_resource *res;
+	struct display *d = display_create();
+	/* we need some interface with destructor. wl_pointer/keyboard
+	 * has destructor, but we'd need to implement wl_seat for them too,
+	 * so choose rather wl_shm_pool */
+	wl_global_create(d->wl_display, &wl_shm_pool_interface,
+			 wl_shm_pool_interface.version, d, pool_bind);
+
+	ci = client_create(d, inert_resource_main);
+	display_run(d);
+
+	/* display has been stopped, make resource inert */
+	res = ci->data;
+	assert(res && "Client did not bind to the global");
+
+	assert(!wl_resource_is_inert(res));
+	wl_resource_set_inert(res);
+	assert(wl_resource_is_inert(res));
+
+	display_resume(d);
+
+	assert(destroyed == 1 && "Destructor was not called");
+	display_destroy(d);
+}
+
+static void
+inert_parent_resource_main(void)
+{
+	struct client *cli = client_connect();
+	struct wl_shm_pool *pool;
+	struct wl_registry *reg = wl_display_get_registry(cli->wl_display);
+	struct wl_buffer *buffer;
+	assert(reg);
+
+	wl_registry_add_listener(reg, &registry_listener, &pool);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+	assert(pool && "Did not bind to the pool");
+
+	wl_registry_destroy(reg);
+
+	/* let the display make the pool resource inert */
+	stop_display(cli, 1);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+
+	/* these requests should be ignored, but the new_id object
+	 * should be created */
+	buffer = wl_shm_pool_create_buffer(pool, 0, 100, 100, 4, 0);
+	assert(buffer);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+
+	wl_buffer_destroy(buffer);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+
+	/* this one should be not */
+	wl_shm_pool_destroy(pool);
+	assert(wl_display_roundtrip(cli->wl_display) != -1);
+
+	client_disconnect(cli);
+}
+
+/* test creating objects on inert object */
+TEST(inert_parent_resource)
+{
+	struct client_info *ci;
+	struct wl_resource *res;
+	struct display *d = display_create();
+
+	wl_global_create(d->wl_display, &wl_shm_pool_interface,
+			 wl_shm_pool_interface.version, d, pool_bind);
+
+	ci = client_create(d, inert_parent_resource_main);
+	display_run(d);
+
+	/* display has been stopped, make resource inert */
+	res = ci->data;
+	assert(res && "Client did not bind to the global");
+
+	assert(!wl_resource_is_inert(res));
+	wl_resource_set_inert(res);
+	assert(wl_resource_is_inert(res));
+
+	display_resume(d);
+
+	assert(destroyed == 1 && "Destructor was not called");
+	display_destroy(d);
+}
-- 
2.1.0



More information about the wayland-devel mailing list