[PATCH wayland v3] tests/queue-test: Add tests for proxy wrappers

Jonas Ådahl jadahl at gmail.com
Thu Apr 28 07:31:32 UTC 2016


Test that doing wl_display.sync on a wrapped proxy with a special queue
works as expected.

Test that creating a wrapper on a destroyed but not freed proxy fails.

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---

Changes since v1:

 - Made the test single threaded, instead pretending to be multi threaded.
 - Added a negative-test for illustrating how NOT to do thread safe queue
   assignment.
 - Changed create-wrapper-failed test to be less confusing

Jonas



 tests/queue-test.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 157 insertions(+)

diff --git a/tests/queue-test.c b/tests/queue-test.c
index 02865ae..a6f82ac 100644
--- a/tests/queue-test.c
+++ b/tests/queue-test.c
@@ -205,6 +205,127 @@ client_test_queue_roundtrip(void)
 }
 
 static void
+client_test_queue_proxy_wrapper(void)
+{
+	struct wl_event_queue *queue;
+	struct wl_display *display;
+	struct wl_display *display_wrapper;
+	struct wl_callback *callback;
+	bool done = false;
+
+	/*
+	 * For an illustration of what usage would normally fail without using
+	 * proxy wrappers, see the `client_test_queue_set_queue_race' test case.
+	 */
+
+	display = wl_display_connect(NULL);
+	assert(display);
+
+	/* Pretend we are in a separate thread where a thread-local queue is
+	 * used. */
+	queue = wl_display_create_queue(display);
+	assert(queue);
+
+	display_wrapper = wl_proxy_create_wrapper(display);
+	assert(display_wrapper);
+	wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
+	callback = wl_display_sync(display_wrapper);
+	wl_proxy_wrapper_destroy(display_wrapper);
+	assert(callback != NULL);
+
+	/* Pretend we are now another thread and dispatch the dispatch the main
+	 * queue while also knowing our callback is read and queued. */
+	wl_display_roundtrip(display);
+
+	/* Make sure that the pretend-to-be main thread didn't dispatch our
+	 * callback, behind our back. */
+	wl_callback_add_listener(callback, &sync_listener_roundtrip, &done);
+	wl_display_flush(display);
+
+	assert(!done);
+
+	/* Make sure that we eventually end up dispatching our callback. */
+	while (!done)
+		assert(wl_display_dispatch_queue(display, queue) != -1);
+
+	wl_callback_destroy(callback);
+	wl_event_queue_destroy(queue);
+
+	wl_display_disconnect(display);
+}
+
+static void
+client_test_queue_set_queue_race(void)
+{
+	struct wl_event_queue *queue;
+	struct wl_display *display;
+	struct wl_callback *callback;
+	bool done = false;
+
+	/*
+	 * This test illustrates the multi threading scenario which would fail
+	 * without doing what is done in the `client_test_queue_proxy_wrapper'
+	 * test.
+	 */
+
+	display = wl_display_connect(NULL);
+	assert(display);
+
+	/* Pretend we are in a separate thread where a thread-local queue is
+	 * used. */
+	queue = wl_display_create_queue(display);
+	assert(queue);
+
+	callback = wl_display_sync(display);
+	assert(callback != NULL);
+
+	/* Pretend we are now another thread and dispatch the dispatch the main
+	 * queue while also knowing our callback is read, queued on the wrong
+	 * queue, and dispatched. */
+	wl_display_roundtrip(display);
+
+	/* Pretend we are back in the separate thread, and continue with setting
+	 * up our callback. */
+	wl_callback_add_listener(callback, &sync_listener_roundtrip, &done);
+	wl_proxy_set_queue((struct wl_proxy *) callback, queue);
+
+	/* Roundtrip our separate thread queue to make sure any events are
+	 * dispatched. */
+	wl_display_roundtrip_queue(display, queue);
+
+	/* Verify that the callback has indeed been dropped. */
+	assert(!done);
+
+	wl_callback_destroy(callback);
+	wl_event_queue_destroy(queue);
+
+	wl_display_disconnect(display);
+}
+
+static void
+client_test_queue_wrap_destroyed_proxy(void)
+{
+	struct wl_display *display;
+	struct wl_callback *callback;
+	struct wl_callback *callback_wrapper;
+
+	display = wl_display_connect(NULL);
+	assert(display);
+
+	callback = wl_display_sync(display);
+	assert(callback);
+
+	wl_display_roundtrip(display);
+
+	/* The callback will now been removed. */
+	callback_wrapper = wl_proxy_create_wrapper(callback);
+	assert(!callback_wrapper);
+
+	wl_callback_destroy(callback);
+	wl_display_disconnect(display);
+}
+
+static void
 dummy_bind(struct wl_client *client,
 	   void *data, uint32_t version, uint32_t id)
 {
@@ -259,3 +380,39 @@ TEST(queue_roundtrip)
 
 	display_destroy(d);
 }
+
+TEST(queue_set_queue_proxy_wrapper)
+{
+	struct display *d = display_create();
+
+	test_set_timeout(2);
+
+	client_create_noarg(d, client_test_queue_proxy_wrapper);
+	display_run(d);
+
+	display_destroy(d);
+}
+
+TEST(queue_set_queue_race)
+{
+	struct display *d = display_create();
+
+	test_set_timeout(2);
+
+	client_create_noarg(d, client_test_queue_set_queue_race);
+	display_run(d);
+
+	display_destroy(d);
+}
+
+TEST(queue_wrap_destroyed_proxy)
+{
+	struct display *d = display_create();
+
+	test_set_timeout(2);
+
+	client_create_noarg(d, client_test_queue_wrap_destroyed_proxy);
+	display_run(d);
+
+	display_destroy(d);
+}
-- 
2.5.5



More information about the wayland-devel mailing list