[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

wayland: Changes to 'debian-unstable'



 .gitignore                        |    1 
 Makefile.am                       |    6 
 configure.ac                      |    4 
 debian/changelog                  |   12 
 debian/libwayland-client0.symbols |    2 
 debian/libwayland-server0.symbols |    1 
 doc/publican/Makefile.am          |    2 
 doc/publican/publican.cfg         |    2 
 protocol/wayland.xml              |   49 +++
 src/connection.c                  |    2 
 src/event-loop.c                  |    4 
 src/scanner.c                     |   42 +--
 src/wayland-client.c              |  203 ++++++++++++----
 src/wayland-client.h              |    5 
 src/wayland-server.c              |  228 ++++++++++++------
 src/wayland-server.h              |    5 
 tests/display-test.c              |  465 +++++++++++++++++++++++++++++++++++++
 tests/event-loop-test.c           |   74 +++++
 tests/queue-test.c                |  201 +++++-----------
 tests/socket-test.c               |   90 +++++++
 tests/test-compositor.c           |  472 ++++++++++++++++++++++++++++++++++++++
 tests/test-compositor.h           |   97 +++++++
 22 files changed, 1673 insertions(+), 294 deletions(-)

New commits:
commit 89481aaf2190bd5d053f63a9b4d1d101cf154ab3
Author: Emilio Pozuelo Monfort <pochu@debian.org>
Date:   Fri Sep 5 03:10:27 2014 +0200

    Upload to experimental

diff --git a/debian/changelog b/debian/changelog
index 077abcf..6c5990f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,10 +1,14 @@
-wayland (1.5.91-1) UNRELEASED; urgency=medium
+wayland (1.5.91-1) experimental; urgency=medium
 
+  [ Andreas Henriksson ]
   * New upstream development release.
   * Update debian/libwayland-client0.symbols with two additions
   * Update debian/libwayland-server0.symbols with one addition
 
- -- Andreas Henriksson <andreas@fatal.se>  Sat, 23 Aug 2014 16:03:00 +0200
+  [ Emilio Pozuelo Monfort ]
+  * Upload to experimental.
+
+ -- Emilio Pozuelo Monfort <pochu@debian.org>  Fri, 05 Sep 2014 03:10:22 +0200
 
 wayland (1.5.0-1) unstable; urgency=medium
 

commit 350b32ee80b2bd9534335123bb7ded7acea7ea3c
Author: Andreas Henriksson <andreas@fatal.se>
Date:   Sat Aug 23 16:12:01 2014 +0200

    Update debian/libwayland-server0.symbols with one addition

diff --git a/debian/changelog b/debian/changelog
index 242f40d..077abcf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,7 @@ wayland (1.5.91-1) UNRELEASED; urgency=medium
 
   * New upstream development release.
   * Update debian/libwayland-client0.symbols with two additions
+  * Update debian/libwayland-server0.symbols with one addition
 
  -- Andreas Henriksson <andreas@fatal.se>  Sat, 23 Aug 2014 16:03:00 +0200
 
diff --git a/debian/libwayland-server0.symbols b/debian/libwayland-server0.symbols
index 27cc810..8a2f372 100644
--- a/debian/libwayland-server0.symbols
+++ b/debian/libwayland-server0.symbols
@@ -27,6 +27,7 @@ libwayland-server.so.0 libwayland-server0 #MINVER#
  wl_display_add_global@Base 1.0.2
  wl_display_add_shm_format@Base 1.3.0
  wl_display_add_socket@Base 1.0.2
+ wl_display_add_socket_auto@Base 1.5.91
  wl_display_create@Base 1.0.2
  wl_display_destroy@Base 1.0.2
  wl_display_flush_clients@Base 1.0.2

commit f9855ae74860d318ec048c3541dd8878198450c8
Author: Andreas Henriksson <andreas@fatal.se>
Date:   Sat Aug 23 16:09:51 2014 +0200

    Update debian/libwayland-client0.symbols with two additions

diff --git a/debian/changelog b/debian/changelog
index 9dbce98..242f40d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,7 @@
 wayland (1.5.91-1) UNRELEASED; urgency=medium
 
   * New upstream development release.
+  * Update debian/libwayland-client0.symbols with two additions
 
  -- Andreas Henriksson <andreas@fatal.se>  Sat, 23 Aug 2014 16:03:00 +0200
 
diff --git a/debian/libwayland-client0.symbols b/debian/libwayland-client0.symbols
index 7401d54..15b4f8d 100644
--- a/debian/libwayland-client0.symbols
+++ b/debian/libwayland-client0.symbols
@@ -23,11 +23,13 @@ libwayland-client.so.0 libwayland-client0 #MINVER#
  wl_display_flush@Base 1.0.2
  wl_display_get_error@Base 1.0.2
  wl_display_get_fd@Base 1.0.2
+ wl_display_get_protocol_error@Base 1.5.91
  wl_display_interface@Base 1.0.2
  wl_display_prepare_read@Base 1.2.0
  wl_display_prepare_read_queue@Base 1.2.0
  wl_display_read_events@Base 1.2.0
  wl_display_roundtrip@Base 1.0.2
+ wl_display_roundtrip_queue@Base 1.5.91
  wl_event_queue_destroy@Base 1.0.2
  wl_keyboard_interface@Base 1.0.2
  wl_list_empty@Base 1.0.2

commit 42c3daa4ae31ddf9b7600b404c97e36d6cc7e9fd
Author: Andreas Henriksson <andreas@fatal.se>
Date:   Sat Aug 23 16:05:50 2014 +0200

    New upstream development release.

diff --git a/debian/changelog b/debian/changelog
index b5a1e92..9dbce98 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+wayland (1.5.91-1) UNRELEASED; urgency=medium
+
+  * New upstream development release.
+
+ -- Andreas Henriksson <andreas@fatal.se>  Sat, 23 Aug 2014 16:03:00 +0200
+
 wayland (1.5.0-1) unstable; urgency=medium
 
   * New upstream release.

commit 6d0f298665e0f6b11a18ab6b6ccc49ba990b4b3e
Author: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Date:   Fri Aug 22 18:01:35 2014 +0300

    configure.ac: Bump version to 1.5.91 for the alpha release
    
    Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/configure.ac b/configure.ac
index e16c5b5..d8e42d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ([2.64])
 
 m4_define([wayland_major_version], [1])
 m4_define([wayland_minor_version], [5])
-m4_define([wayland_micro_version], [90])
+m4_define([wayland_micro_version], [91])
 m4_define([wayland_version],
           [wayland_major_version.wayland_minor_version.wayland_micro_version])
 

commit 8c061d1b7e4fcdfe8d12887720ef129b8f921139
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Fri Aug 22 14:28:59 2014 +0200

    client: check for error in wl_display_read_events
    
    This prevents from blocking shown in one display test. Also, it
    makes sense to not proceed further in the code of the function
    when an error ocurred.
    
    v2. set errno
        put note about the errno into wl_display_prepare_read doc
        check for error with mutex locked
    
    v3.
        set errno to display->last_error
    
        check for the error only in wl_display_read_events. It's sufficient
        as prevention for the hanging and programmer doesn't need to
        check if wl_display_prepare_read (that was previously covered by
        this patch too) returned an error or the queue just was not empty.
        Without the check, it could result in indefinite looping.
    
    Thanks to Pekka Paalanen <pekka.paalanen@collabora.co.uk> for
    constant reviewing and discussing this patch.
    
    Signed-off-by: Marek Chalupa <mchqwerty@gmail.com>
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 0f3f3d9..9159ee0 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1200,6 +1200,13 @@ wl_display_read_events(struct wl_display *display)
 
 	pthread_mutex_lock(&display->mutex);
 
+	if (display->last_error) {
+		pthread_mutex_unlock(&display->mutex);
+
+		errno = display->last_error;
+		return -1;
+	}
+
 	ret = read_events(display);
 
 	pthread_mutex_unlock(&display->mutex);

commit 574b710ef8da766019a406801893937a6df9357c
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Tue Aug 5 11:42:01 2014 +0200

    client: broadcast the right pthread_cond variable
    
    In previous commit we removed unused variables. One of them was
    pthread_cond_t that was formerly used when reading from display, but
    later was (erroneously) made unused. This patch fixes this error
    and is a fix for the failing test introduced few patches ago (tests:
    test if thread can block on error)
    
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 4b184d5..0f3f3d9 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -127,6 +127,12 @@ display_fatal_error(struct wl_display *display, int error)
 		error = EFAULT;
 
 	display->last_error = error;
+
+       pthread_cond_broadcast(&display->reader_cond);
+       /* prevent from indefinite looping in read_events()
+	* (when calling pthread_cond_wait under condition
+	* display->read_serial == serial) */
+       ++display->read_serial;
 }
 
 /**
@@ -175,6 +181,16 @@ display_protocol_error(struct wl_display *display, uint32_t code,
 	display->protocol_error.id = id;
 	display->protocol_error.interface = intf;
 
+	/*
+	 * here it is not necessary to broadcast reader's cond like in
+	 * display_fatal_error, because this function is called from
+	 * an event handler and that means that read_events() is done
+	 * and woke up all threads. Since wl_display_prepare_read()
+	 * fails when there are events in the queue, no threads
+	 * can sleep in read_events() during dispatching
+	 * (and therefore during calling this function), so this is safe.
+	 */
+
 	pthread_mutex_unlock(&display->mutex);
 }
 

commit 0cb9862c938f754dbda5394c56ac09dae3a20201
Author: Olivier Blin <olivier.blin@softathome.com>
Date:   Thu Aug 21 16:54:21 2014 +0200

    client: drop unused event queue cond and list variables
    
    The wl_event_queue cond variable has been replaced by the wl_display
    reader_cond variable (commit 3c7e8bfbb4745315b7bcbf69fa746c3d6718c305).
    This cond variable is never waited for anymore, just
    signaled/broadcasted, and thus can be safely removed.
    
    The wl_display event_queue_list and link from wl_event_queue
    can be removed as well, since it was only used to iterate over
    the event queue list in order to broadcast the now unused cond.
    
    No regression on queue unit tests.
    
    Signed-off-by: Olivier Blin <olivier.blin@softathome.com>
    
    v2: fixed and rebased after 886b09c9a3a9d8672039f09fe7eaf3f2b2b012ca
        added signed-off-by
    
    v3: removed link from wl_event_queue
    
    Signed-off-by: Marek Chalupa <mchqwerty@gmail.com>
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 2252424..4b184d5 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -69,10 +69,8 @@ struct wl_global {
 };
 
 struct wl_event_queue {
-	struct wl_list link;
 	struct wl_list event_list;
 	struct wl_display *display;
-	pthread_cond_t cond;
 };
 
 struct wl_display {
@@ -100,7 +98,6 @@ struct wl_display {
 	struct wl_map objects;
 	struct wl_event_queue display_queue;
 	struct wl_event_queue default_queue;
-	struct wl_list event_queue_list;
 	pthread_mutex_t mutex;
 
 	int reader_count;
@@ -123,8 +120,6 @@ static int debug_client = 0;
 static void
 display_fatal_error(struct wl_display *display, int error)
 {
-	struct wl_event_queue *iter;
-
 	if (display->last_error)
 		return;
 
@@ -132,9 +127,6 @@ display_fatal_error(struct wl_display *display, int error)
 		error = EFAULT;
 
 	display->last_error = error;
-
-	wl_list_for_each(iter, &display->event_queue_list, link)
-		pthread_cond_broadcast(&iter->cond);
 }
 
 /**
@@ -153,7 +145,6 @@ static void
 display_protocol_error(struct wl_display *display, uint32_t code,
 		       uint32_t id, const struct wl_interface *intf)
 {
-	struct wl_event_queue *iter;
 	int err;
 
 	if (display->last_error)
@@ -184,9 +175,6 @@ display_protocol_error(struct wl_display *display, uint32_t code,
 	display->protocol_error.id = id;
 	display->protocol_error.interface = intf;
 
-	wl_list_for_each(iter, &display->event_queue_list, link)
-		pthread_cond_broadcast(&iter->cond);
-
 	pthread_mutex_unlock(&display->mutex);
 }
 
@@ -194,7 +182,6 @@ static void
 wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
 {
 	wl_list_init(&queue->event_list);
-	pthread_cond_init(&queue->cond, NULL);
 	queue->display = display;
 }
 
@@ -209,7 +196,6 @@ wl_event_queue_release(struct wl_event_queue *queue)
 		wl_list_remove(&closure->link);
 		wl_closure_destroy(closure);
 	}
-	pthread_cond_destroy(&queue->cond);
 }
 
 /** Destroy an event queue
@@ -231,7 +217,6 @@ wl_event_queue_destroy(struct wl_event_queue *queue)
 	struct wl_display *display = queue->display;
 
 	pthread_mutex_lock(&display->mutex);
-	wl_list_remove(&queue->link);
 	wl_event_queue_release(queue);
 	free(queue);
 	pthread_mutex_unlock(&display->mutex);
@@ -256,10 +241,6 @@ wl_display_create_queue(struct wl_display *display)
 
 	wl_event_queue_init(queue, display);
 
-	pthread_mutex_lock(&display->mutex);
-	wl_list_insert(&display->event_queue_list, &queue->link);
-	pthread_mutex_unlock(&display->mutex);
-
 	return queue;
 }
 
@@ -767,7 +748,6 @@ wl_display_connect_to_fd(int fd)
 	wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE);
 	wl_event_queue_init(&display->default_queue, display);
 	wl_event_queue_init(&display->display_queue, display);
-	wl_list_init(&display->event_queue_list);
 	pthread_mutex_init(&display->mutex, NULL);
 	pthread_cond_init(&display->reader_cond, NULL);
 	display->reader_count = 0;
@@ -1046,8 +1026,6 @@ queue_event(struct wl_display *display, int len)
 	else
 		queue = proxy->queue;
 
-	if (wl_list_empty(&queue->event_list))
-		pthread_cond_signal(&queue->cond);
 	wl_list_insert(queue->event_list.prev, &closure->link);
 
 	return size;

commit 71141288f0aaf7df9d06469d4a0ee21d7384243b
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Tue Aug 5 11:39:51 2014 +0200

    tests: add test for reading after an error occurred
    
    This test shows that it's possible to successfully call wl_display_prepare_read
    and wl_display_read_events after an error occurred. That may lead to
    deadlock.
    
    When you call prepare read from two threads and then call read_events,
    one thread gets sleeping. The call from the other thread will return -1 and invokes
    display_fatal_error, but since
    we have display->last_error already set, the broadcast is not called and
    the sleeping thread sleeps indefinitely.
    
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/tests/display-test.c b/tests/display-test.c
index 28ef40b..c420cbe 100644
--- a/tests/display-test.c
+++ b/tests/display-test.c
@@ -482,3 +482,63 @@ TEST(threading_cancel_read_tst)
 
 	display_destroy(d);
 }
+
+static void *
+thread_prepare_and_read2(void *data)
+{
+	struct client *c = data;
+
+	while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
+		assert(wl_display_dispatch_pending(c->wl_display) == -1);
+	assert(wl_display_flush(c->wl_display) == -1);
+
+	c->display_stopped = 1;
+
+	assert(wl_display_read_events(c->wl_display) == -1);
+	assert(wl_display_dispatch_pending(c->wl_display) == -1);
+
+	pthread_exit(NULL);
+}
+
+static void
+threading_read_after_error(void)
+{
+	struct client *c = client_connect();
+	pthread_t thread;
+
+	/* create an error */
+	close(wl_display_get_fd(c->wl_display));
+	assert(wl_display_dispatch(c->wl_display) == -1);
+
+	/* try to prepare for reading */
+	while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
+		assert(wl_display_dispatch_pending(c->wl_display) == -1);
+	assert(wl_display_flush(c->wl_display) == -1);
+
+	assert(pthread_create(&thread, NULL,
+			      thread_prepare_and_read2, c) == 0);
+
+	/* make sure thread is sleeping */
+	while (c->display_stopped == 0)
+		usleep(500);
+	usleep(10000);
+
+	assert(wl_display_read_events(c->wl_display) == -1);
+
+	/* kill test in 3 seconds */
+	alarm(3);
+	pthread_join(thread, NULL);
+
+	wl_proxy_destroy((struct wl_proxy *) c->tc);
+	wl_display_disconnect(c->wl_display);
+}
+
+TEST(threading_read_after_error_tst)
+{
+	struct display *d = display_create();
+
+	client_create(d, threading_read_after_error);
+	display_run(d);
+
+	display_destroy(d);
+}

commit 213366e698fedf0caac0e7a0bf2f05e2446ba113
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Tue Aug 5 11:39:50 2014 +0200

    tests: add tests for wl_display_cancel_read
    
    Test if wl_display_cancel_read wakes up other threads.
    
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/tests/display-test.c b/tests/display-test.c
index 26f946b..28ef40b 100644
--- a/tests/display-test.c
+++ b/tests/display-test.c
@@ -413,3 +413,72 @@ TEST(threading_errors_tst)
 
 	display_destroy(d);
 }
+
+static void *
+thread_prepare_and_read(void *data)
+{
+	struct client *c = data;
+
+	register_reading(c->wl_display);
+
+	c->display_stopped = 1;
+
+	assert(wl_display_read_events(c->wl_display) == 0);
+	assert(wl_display_dispatch_pending(c->wl_display) == 0);
+
+	pthread_exit(NULL);
+}
+
+static pthread_t
+create_thread(struct client *c)
+{
+	pthread_t thread;
+
+	c->display_stopped = 0;
+	assert(pthread_create(&thread, NULL, thread_prepare_and_read, c) == 0);
+
+	/* make sure thread is sleeping */
+	while (c->display_stopped == 0)
+		usleep(500);
+	usleep(10000);
+
+	return thread;
+}
+
+/* test cancel read*/
+static void
+threading_cancel_read(void)
+{
+	struct client *c = client_connect();
+	pthread_t th1, th2, th3;
+
+	register_reading(c->wl_display);
+
+	th1 = create_thread(c);
+	th2 = create_thread(c);
+	th3 = create_thread(c);
+
+	/* all the threads are sleeping, waiting until read or cancel
+	 * is called. Cancel the read and let the threads proceed */
+	wl_display_cancel_read(c->wl_display);
+
+	/* kill test in 3 seconds. This should be enough time for the
+	 * thread to exit if it's not blocking. If everything is OK, than
+	 * the thread was woken up and the test will end before the SIGALRM */
+	alarm(3);
+	pthread_join(th1, NULL);
+	pthread_join(th2, NULL);
+	pthread_join(th3, NULL);
+
+	client_disconnect(c);
+}
+
+TEST(threading_cancel_read_tst)
+{
+	struct display *d = display_create();
+
+	client_create(d, threading_cancel_read);
+	display_run(d);
+
+	display_destroy(d);
+}

commit 171e0bdace16dca6d532494a076f0970cb8a034c
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Tue Aug 5 11:39:49 2014 +0200

    tests: test if thread can block on error
    
    wl_display_read_events() can make a thread wait until some other thread
    ends reading. Normally it wakes up all threads after the reading is
    done. But there's a place when it does not get to waking up the threads
    - when an error occurs. This test reveals bug that can block programs.
    
    If a thread is waiting in wl_display_read_events() and another thread
    calls wl_display_read_events and the reading fails,
    then the sleeping thread is not woken up. This is because
    display_handle_error is using old pthread_cond instead of new
    display->reader_cond, that was added along with wl_display_read_events().
    
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/tests/display-test.c b/tests/display-test.c
index e212942..26f946b 100644
--- a/tests/display-test.c
+++ b/tests/display-test.c
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <pthread.h>
 
 #include "wayland-private.h"
 #include "wayland-server.h"
@@ -323,3 +324,92 @@ TEST(post_nomem_tst)
 
 	display_destroy(d);
 }
+
+static void
+register_reading(struct wl_display *display)
+{
+	while(wl_display_prepare_read(display) != 0 && errno == EAGAIN)
+		assert(wl_display_dispatch_pending(display) >= 0);
+	assert(wl_display_flush(display) >= 0);
+}
+
+static void *
+thread_read_error(void *data)
+{
+	struct client *c = data;
+
+	register_reading(c->wl_display);
+
+	/*
+	 * Calling the read right now will block this thread
+	 * until the other thread will read the data.
+	 * However, after invoking an error, this
+	 * thread should be woken up or it will block indefinitely.
+	 */
+	c->display_stopped = 1;
+	assert(wl_display_read_events(c->wl_display) == 0);
+
+	wl_display_dispatch_pending(c->wl_display);
+	assert(wl_display_get_error(c->wl_display));
+
+	pthread_exit(NULL);
+}
+
+/* test posting an error in multi-threaded environment. */
+static void
+threading_post_err(void)
+{
+	struct client *c = client_connect();
+	pthread_t thread;
+
+	/* register read intention */
+	register_reading(c->wl_display);
+
+	/* use this var as an indicator that thread is sleeping */
+	c->display_stopped = 0;
+
+	/* create new thread that will register its intention too */
+	assert(pthread_create(&thread, NULL, thread_read_error, c) == 0);
+
+	/* make sure thread is sleeping. It's a little bit racy
+	 * (setting display_stopped to 1 and calling wl_display_read_events)
+	 * so call usleep once again after the loop ends - it should
+	 * be sufficient... */
+	while (c->display_stopped == 0)
+		usleep(500);
+
+	usleep(10000);
+
+	/* so now we have sleeping thread waiting for a pthread_cond signal.
+	 * The main thread must call wl_display_read_events().
+	 * If this call fails, then it won't call broadcast at the
+	 * end of the function and the sleeping thread will block indefinitely.
+	 * Make the call fail and watch if libwayland will unblock the thread! */
+
+	/* create error on fd, so that wl_display_read_events will fail.
+	 * The same can happen when server hangs up */
+	close(wl_display_get_fd(c->wl_display));
+	/* this read events will fail and will
+	 * post an error that should wake the sleeping thread
+	 * and dispatch the incoming events */
+	assert(wl_display_read_events(c->wl_display) == -1);
+
+	/* kill test in 3 seconds. This should be enough time for the
+	 * thread to exit if it's not blocking. If everything is OK, than
+	 * the thread was woken up and the test will end before the SIGALRM */
+	alarm(3);
+	pthread_join(thread, NULL);
+
+	wl_proxy_destroy((struct wl_proxy *) c->tc);
+	wl_display_disconnect(c->wl_display);
+}
+
+TEST(threading_errors_tst)
+{
+	struct display *d = display_create();
+
+	client_create(d, threading_post_err);
+	display_run(d);
+
+	display_destroy(d);
+}

commit 47208d2ab12c7671e1b8dc80c4d15094f0b310f7
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Mon May 26 17:04:23 2014 +0200

    tests: test posting errors
    
    Test posting errors to one and more clients.
    
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/tests/display-test.c b/tests/display-test.c
index 844a649..e212942 100644
--- a/tests/display-test.c
+++ b/tests/display-test.c
@@ -34,7 +34,9 @@
 
 #include "wayland-private.h"
 #include "wayland-server.h"
+#include "wayland-client.h"
 #include "test-runner.h"
+#include "test-compositor.h"
 
 struct display_destroy_listener {
 	struct wl_listener listener;
@@ -77,3 +79,247 @@ TEST(display_destroy_listener)
 	assert(b.done);
 }
 
+static void
+registry_handle_globals(void *data, struct wl_registry *registry,
+			uint32_t id, const char *intf, uint32_t ver)
+{
+	struct wl_seat **seat = data;
+
+	if (strcmp(intf, "wl_seat") == 0) {
+		*seat = wl_registry_bind(registry, id,
+					 &wl_seat_interface, ver);
+		assert(*seat);
+	}
+}
+
+static const struct wl_registry_listener registry_listener = {
+	registry_handle_globals,
+	NULL
+};
+
+static struct wl_seat *
+client_get_seat(struct client *c)
+{
+	struct wl_seat *seat;
+	struct wl_registry *reg = wl_display_get_registry(c->wl_display);
+	assert(reg);
+
+	wl_registry_add_listener(reg, &registry_listener, &seat);
+	wl_display_roundtrip(c->wl_display);
+	assert(seat);
+
+	wl_registry_destroy(reg);
+
+	return seat;
+}
+
+static void
+check_for_error(struct client *c, struct wl_proxy *proxy)
+{
+	uint32_t ec, id;
+	int err;
+	const struct wl_interface *intf;
+
+	/* client should be disconnected */
+	assert(wl_display_roundtrip(c->wl_display) == -1);
+
+	err = wl_display_get_error(c->wl_display);
+	assert(err == EPROTO);
+
+	ec = wl_display_get_protocol_error(c->wl_display, &intf, &id);
+	assert(ec == 23);
+	assert(intf == &wl_seat_interface);
+	assert(id == wl_proxy_get_id(proxy));
+}
+
+static void
+bind_seat(struct wl_client *client, void *data,
+	  uint32_t vers, uint32_t id)
+{
+	struct display *d = data;
+	struct client_info *ci;
+	struct wl_resource *res;
+
+	/* find the right client_info struct and save the
+	 * resource as its data, so that we can use it later */
+	wl_list_for_each(ci, &d->clients, link) {
+		if (ci->wl_client == client)
+			break;
+	}
+
+	res = wl_resource_create(client, &wl_seat_interface, vers, id);
+	assert(res);
+
+	ci->data = res;
+}
+
+static void
+post_error_main(void)
+{
+	struct client *c = client_connect();
+	struct wl_seat *seat = client_get_seat(c);
+
+	/* stop display so that it can post the error.
+	 * The function should return -1, because of the posted error */
+	assert(stop_display(c, 1) == -1);
+
+	/* display should have posted error, check it! */
+	check_for_error(c, (struct wl_proxy *) seat);
+
+	/* don't call client_disconnect(c), because then the test would be
+	 * aborted due to checks for error in this function */
+	wl_proxy_destroy((struct wl_proxy *) seat);
+	wl_proxy_destroy((struct wl_proxy *) c->tc);
+	wl_display_disconnect(c->wl_display);
+}
+
+TEST(post_error_to_one_client)
+{
+	struct display *d = display_create();
+	struct client_info *cl;
+
+	wl_global_create(d->wl_display, &wl_seat_interface,
+			 1, d, bind_seat);
+
+	cl = client_create(d, post_error_main);
+	display_run(d);
+
+	/* the display was stopped by client, so it can
+	 * proceed in the code and post an error */
+	assert(cl->data);
+	wl_resource_post_error((struct wl_resource *) cl->data,
+			       23, "Dummy error");
+
+	/* this one should be ignored */
+	wl_resource_post_error((struct wl_resource *) cl->data,
+			       21, "Dummy error (ignore)");
+
+	display_resume(d);
+	display_destroy(d);
+}
+
+static void
+post_error_main2(void)
+{
+	struct client *c = client_connect();
+	struct wl_seat *seat = client_get_seat(c);
+
+	/* the error should not be posted for this client */
+	assert(stop_display(c, 2) >= 0);
+
+	wl_proxy_destroy((struct wl_proxy *) seat);
+	client_disconnect(c);
+}
+
+static void
+post_error_main3(void)
+{
+	struct client *c = client_connect();
+	struct wl_seat *seat = client_get_seat(c);
+
+	assert(stop_display(c, 2) == -1);
+	check_for_error(c, (struct wl_proxy *) seat);
+
+	/* don't call client_disconnect(c), because then the test would be
+	 * aborted due to checks for error in this function */
+	wl_proxy_destroy((struct wl_proxy *) seat);
+	wl_proxy_destroy((struct wl_proxy *) c->tc);
+	wl_display_disconnect(c->wl_display);
+}
+
+/* all the testcases could be in one TEST, but splitting it
+ * apart is better for debugging when the test fails */
+TEST(post_error_to_one_from_two_clients)
+{
+	struct display *d = display_create();
+	struct client_info *cl;
+
+	wl_global_create(d->wl_display, &wl_seat_interface,
+			 1, d, bind_seat);
+
+	client_create(d, post_error_main2);
+	cl = client_create(d, post_error_main3);
+	display_run(d);
+
+	/* post error only to the second client */
+	assert(cl->data);
+	wl_resource_post_error((struct wl_resource *) cl->data,
+			       23, "Dummy error");
+	wl_resource_post_error((struct wl_resource *) cl->data,
+			       21, "Dummy error (ignore)");
+
+	display_resume(d);
+	display_destroy(d);
+}
+
+/* all the testcases could be in one TEST, but splitting it
+ * apart is better for debugging when the test fails */
+TEST(post_error_to_two_clients)
+{
+	struct display *d = display_create();
+	struct client_info *cl, *cl2;
+
+	wl_global_create(d->wl_display, &wl_seat_interface,
+			 1, d, bind_seat);
+
+	cl = client_create(d, post_error_main3);
+	cl2 = client_create(d, post_error_main3);
+
+	display_run(d);
+
+	/* Try to send the error to both clients */
+	assert(cl->data && cl2->data);
+	wl_resource_post_error((struct wl_resource *) cl->data,
+			       23, "Dummy error");
+	wl_resource_post_error((struct wl_resource *) cl->data,
+			       21, "Dummy error (ignore)");
+
+	wl_resource_post_error((struct wl_resource *) cl2->data,
+			       23, "Dummy error");
+	wl_resource_post_error((struct wl_resource *) cl2->data,
+			       21, "Dummy error (ignore)");
+
+	display_resume(d);
+	display_destroy(d);
+}
+
+static void
+post_nomem_main(void)
+{
+	struct client *c = client_connect();
+	struct wl_seat *seat = client_get_seat(c);
+
+	assert(stop_display(c, 1) == -1);
+	assert(wl_display_get_error(c->wl_display) == ENOMEM);
+
+	wl_proxy_destroy((struct wl_proxy *) seat);
+	wl_proxy_destroy((struct wl_proxy *) c->tc);
+	wl_display_disconnect(c->wl_display);
+}
+
+TEST(post_nomem_tst)
+{
+	struct display *d = display_create();
+	struct client_info *cl;
+
+	wl_global_create(d->wl_display, &wl_seat_interface,
+			 1, d, bind_seat);
+
+	cl = client_create(d, post_nomem_main);
+	display_run(d);
+
+	assert(cl->data);
+	wl_resource_post_no_memory((struct wl_resource *) cl->data);
+	display_resume(d);
+
+	/* first client terminated. Run it again,
+	 * but post no memory to client */
+	cl = client_create(d, post_nomem_main);
+	display_run(d);
+
+	assert(cl->data);
+	wl_client_post_no_memory(cl->wl_client);
+	display_resume(d);
+
+	display_destroy(d);
+}

commit 93e654061b9497c78b6f89a0b7f54107029e2628
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Thu Aug 21 16:53:14 2014 +0200

    tests: use test compositor in queue-test
    
    Most of the code of the queue-test is covered by the test compositor,
    so we can save few lines and use the test compositor instead.
    I think it's also more readable.
    
    This patch removes timeout from the test. We plan to add timeout
    to all tests later, though.
    
    v2.
      rebased to master
    
    Signed-off-by: Marek Chalupa <mchqwerty@gmail.com>
    Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>

diff --git a/tests/queue-test.c b/tests/queue-test.c
index a7b54d9..96f2100 100644
--- a/tests/queue-test.c
+++ b/tests/queue-test.c
@@ -31,33 +31,17 @@
 #include "wayland-client.h"
 #include "wayland-server.h"


Reply to: