[PATCH 3/3 v5] tests: Add a test for global filter

Olivier Fourdan ofourdan at redhat.com
Tue Aug 16 19:28:28 UTC 2016


Test if the global filter is effectively filtering out the global when
the filter returns false.

Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
---
 v3: split out as its own commit
 v4: Follow up on Jonas' comments:
     assert(hi.has_data_offer == false) instead of assert(hi.has_data_offer
     != true)
     Add a test for an illegal bind (bind on hidden global)
 v5: Rework both tests
     Use a shared memory to retrieve the hidden interface name and try
     to bind to that name once it's filtrered out

 tests/display-test.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

diff --git a/tests/display-test.c b/tests/display-test.c
index 0c4df16..b1ada0a 100644
--- a/tests/display-test.c
+++ b/tests/display-test.c
@@ -36,6 +36,8 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
+
 #include <pthread.h>
 #include <poll.h>
 
@@ -926,3 +928,148 @@ TEST(error_on_destroyed_object)
 	display_resume(d);
 	display_destroy(d);
 }
+
+static bool
+global_filter(const struct wl_client *client,
+	      const struct wl_global *global,
+	      void *data)
+{
+	/* Hide the wl_data_offer interface if no data was provided */
+	if (wl_global_get_interface(global) == &wl_data_offer_interface)
+		return data != NULL;
+
+	/* Show all the others */
+	return true;
+}
+
+static void
+bind_data_offer(struct wl_client *client, void *data,
+		uint32_t vers, uint32_t id)
+{
+	struct client_info *allowed_client = data;
+
+	/* Only the allowed client can bind to this interface! */
+	assert(allowed_client);
+}
+
+static void
+registry_handle_filtered(void *data, struct wl_registry *registry,
+			 uint32_t id, const char *intf, uint32_t ver)
+{
+	uint32_t *name = data;
+	bool hidden_interface = (strcmp (intf, "wl_data_offer") == 0);
+
+	if (hidden_interface) {
+		assert(name);
+		*name = id;
+	}
+}
+
+static const struct wl_registry_listener registry_listener_filtered = {
+	registry_handle_filtered,
+	NULL
+};
+
+static void
+get_globals(void *data)
+{
+	struct client *c = client_connect();
+	struct wl_registry *registry;
+
+	registry = wl_display_get_registry(c->wl_display);
+	wl_registry_add_listener(registry, &registry_listener_filtered, data);
+	wl_display_roundtrip(c->wl_display);
+
+	wl_registry_destroy(registry);
+	client_disconnect_nocheck(c);
+}
+
+TEST(filtered_global_is_hidden)
+{
+	struct display *d;
+	struct wl_global *g;
+
+	d = display_create();
+
+	g = wl_global_create(d->wl_display, &wl_data_offer_interface,
+		      1, d, bind_data_offer);
+	wl_display_set_global_filter(d->wl_display, global_filter, NULL);
+
+	client_create_noarg(d, get_globals);
+	display_run(d);
+
+	wl_global_destroy(g);
+
+	display_destroy(d);
+}
+
+static void
+check_bind_error(struct client *c)
+{
+	uint32_t errorcode, id;
+	int err;
+	const struct wl_interface *intf;
+
+	err = wl_display_get_error(c->wl_display);
+	assert(err == EPROTO);
+
+	errorcode = wl_display_get_protocol_error(c->wl_display, &intf, &id);
+	assert(errorcode == WL_DISPLAY_ERROR_INVALID_OBJECT);
+}
+
+static void
+force_bind(void *data)
+{
+	struct client *c = client_connect();
+	struct wl_registry *registry;
+	void *ptr;
+	uint32_t *name = data;
+
+	registry = wl_display_get_registry(c->wl_display);
+
+	ptr = wl_registry_bind (registry, *name, &wl_data_offer_interface, 1);
+	wl_display_roundtrip(c->wl_display);
+	check_bind_error(c);
+
+	wl_proxy_destroy((struct wl_proxy *) ptr);
+	wl_registry_destroy(registry);
+
+	client_disconnect_nocheck(c);
+}
+
+TEST(bind_fails_on_filtered_global)
+{
+	struct display *d;
+	struct wl_global *g;
+	uint32_t *name;
+
+	/* Create a anonymous shared memory to pass the interface name */
+	name = mmap(NULL, sizeof(uint32_t),
+		    PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+
+	d = display_create();
+
+	g = wl_global_create(d->wl_display, &wl_data_offer_interface,
+			     1, d, bind_data_offer);
+	wl_display_set_global_filter(d->wl_display, global_filter, name);
+
+	client_create(d, get_globals, name);
+	*name = 0;
+
+	display_run(d);
+
+	/* Wait for the child process to give us the interface name */
+	while (name == 0)
+		test_usleep(500);
+
+	wl_display_set_global_filter(d->wl_display, global_filter, NULL);
+
+	/* Try to bind to the interface name when a global filter is in place */
+	client_create(d, force_bind, name);
+	display_run(d);
+
+	wl_global_destroy(g);
+
+	display_destroy(d);
+}
+
-- 
2.7.4



More information about the wayland-devel mailing list