[PATCH] tests: add multiple-queues testcases

Marek Chalupa mchqwerty at gmail.com
Fri Aug 22 00:42:16 PDT 2014


On 21 August 2014 15:15, Pekka Paalanen <ppaalanen at gmail.com> wrote:

> On Wed, 25 Jun 2014 14:35:16 +0200
> Marek Chalupa <mchqwerty at gmail.com> wrote:
>
> > Test if events are going to the right queue and if the queue
> > is interrupted from polling when an error to the main queue comes.
> > The last one is failing.
> > ---
> >  tests/queue-test.c | 128
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 128 insertions(+)
> >
> > diff --git a/tests/queue-test.c b/tests/queue-test.c
> > index 36d7a69..307bae9 100644
> > --- a/tests/queue-test.c
> > +++ b/tests/queue-test.c
> > @@ -27,6 +27,7 @@
> >  #include <sys/types.h>
> >  #include <sys/wait.h>
> >  #include <assert.h>
> > +#include <pthread.h>
> >
> >  #include "wayland-client.h"
> >  #include "wayland-server.h"
> > @@ -139,6 +140,53 @@ client_test_multiple_queues(void)
> >       exit(ret == -1 ? -1 : 0);
> >  }
> >
> > +/* test that events will come to the right queue */
> > +static void
> > +client_test_multiple_queues2(void)
> > +{
> > +     struct wl_event_queue *queue[5], *q;
>
> Instead of using 5 everwhere, how about a #define?
>

Yes, that'll be better.


>
> > +     struct wl_callback *callback;
> > +     struct wl_display *display;
> > +     int i, j;
> > +
> > +     display = wl_display_connect(NULL);
> > +     assert(display);
> > +
> > +     for (i = 0; i < 5; ++i) {
> > +             queue[i] = wl_display_create_queue(display);
> > +             assert(queue[i]);
> > +     }
> > +
> > +     for (i = 0; i < 100; ++i) {
> > +             q = queue[i % 5];
> > +             callback = wl_display_sync(display);
>
> Isn't this 'callback' leaked?
>
> > +             assert(callback != NULL);
> > +             wl_proxy_set_queue((struct wl_proxy *) callback, q);
> > +
> > +             assert(wl_display_flush(display) > 0);
> > +
> > +             /* the callback should come to the q queue */
> > +             assert(wl_display_dispatch_pending(display) == 0);
> > +             assert(wl_display_dispatch_queue(display, q) > 0);
> > +             /* now all queues should be empty */
> > +             for (j = 0; j < 5; ++j)
> > +                     assert(wl_display_dispatch_queue_pending(display,
> > +                                                              queue[j])
> == 0);
> > +     }
> > +
> > +     callback = wl_display_sync(display);
>
> And this?
>

I'll add a listener that will destroy the callbacks.


>
>

>
> +     assert(callback != NULL);
> > +
> > +     assert(wl_display_flush(display) > 0);
> > +     assert(wl_display_dispatch(display) > 0);
> > +     for (j = 0; j < 5; ++j) {
> > +             assert(wl_display_dispatch_queue_pending(display,
> queue[j]) == 0);
> > +             wl_event_queue_destroy(queue[j]);
> > +     }
> > +
> > +     wl_display_disconnect(display);
> > +}
> > +
> >  static void
> >  dummy_bind(struct wl_client *client,
> >          void *data, uint32_t version, uint32_t id)
> > @@ -169,5 +217,85 @@ TEST(queue)
> >       client_create(d, client_test_multiple_queues);
> >       display_run(d);
> >
> > +     client_create(d, client_test_multiple_queues2);
> > +     display_run(d);
> > +
> > +     display_destroy(d);
> > +}
> > +
> > +struct thread_data {
> > +     struct wl_display *display;
> > +     struct wl_event_queue *queue;
> > +};
> > +
> > +static void *
> > +run_new_queue(void *arg)
> > +{
> > +     struct thread_data *data = arg;
> > +     int ret;
> > +
> > +     /* XXX shouldn't it return -1 in the first dispatch?
> > +      * Anyway - the queue keeps polling atm and is not interrupted by
> > +      * the error */
>
> Hmm, yes, I think would probably be good that if wl_display goes into
> error state, all the dispatch calls should return with error, rather
> than hang.
>
>
Actually, this test-case is wrong. When I was writing this, I did not know
anything about threading in Wayland.
Nowadays, I know that this is exactly the case where
wl_display_prepare_read + wl_display_read_events should
be used (more threads are reading from the display's fd), so when
programmer will do what is in this test,
it is his fault. However, I think I could send a path that clarifies this
in the documentation
(I've already sent one, but that is only for wl_display_prepare_read and
there's no note about not using wl_display_dispatch concurrently:
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016296.html)

However, this test-case shows that it is possible to have one thread
polling and the other successfully dispatching events
without interrupting the poll, so I'll try to find out if it can happen in
some correct way.



> > +     do {
> > +             ret = wl_display_dispatch_queue(data->display,
> data->queue);
> > +             /* it definitely cannot dispatch any event */
> > +             assert(ret <= 0);
> > +     } while (ret != -1);
> > +
> > +     pthread_exit(NULL);
> > +}
> > +
> > +static void
> > +client_test_multiple_queues_errors(void)
> > +{
> > +     struct client *c;
> > +     struct wl_event_queue *queue;
> > +     struct thread_data data;
> > +     pthread_t thr;
> > +
> > +     c = client_connect();
> > +
> > +     queue = wl_display_create_queue(c->wl_display);
> > +     assert(queue);
> > +
> > +     data.display = c->wl_display;
> > +     data.queue = queue;
> > +     /* run new thread that will wait for event in
> > +      * the new queue. Then post an error and check
> > +      * if the dispatching was cancelled... */
> > +     assert(pthread_create(&thr, NULL, run_new_queue, &data) == 0);
> > +
> > +     stop_display(c, 1);
> > +
> > +     /* make sure we got the error */
> > +     alarm(3); /* timeout */
> > +     wl_display_roundtrip(c->wl_display);
> > +     assert(wl_display_get_error(c->wl_display) != 0);
> > +
> > +     /* wait for the thread to finish */
> > +     assert(pthread_join(thr, NULL) == 0);
> > +
> > +     /* do not use client_disconnect(c), because it would
> > +      * fail the test since we posted an error */
> > +     wl_event_queue_destroy(queue);
> > +     wl_proxy_destroy((struct wl_proxy *) c->tc);
> > +     wl_display_disconnect(c->wl_display);
> > +}
> > +
> > +TEST(queue_errors)
> > +{
> > +     struct display *d = display_create();
> > +
> > +     client_create(d, client_test_multiple_queues_errors);
> > +     display_run(d);
> > +
> > +     /* get the client */
> > +     struct client_info *ci = wl_container_of(d->clients.next, ci,
> link);
> > +     assert(ci && ci->wl_client != NULL);
> > +
> > +     wl_client_post_no_memory(ci->wl_client);
> > +     display_resume(d);
> > +
> >       display_destroy(d);
> >  }
>
>
> Very nice work! :-)
>
>
> Thanks,
> pq


Regards,
Marek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140822/1453b6f4/attachment-0001.html>


More information about the wayland-devel mailing list