1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique * Copyright © 2012 Intel Corporation
3*84e872a0SLloyd Pique * Copyright © 2012 Jason Ekstrand
4*84e872a0SLloyd Pique *
5*84e872a0SLloyd Pique * Permission is hereby granted, free of charge, to any person obtaining
6*84e872a0SLloyd Pique * a copy of this software and associated documentation files (the
7*84e872a0SLloyd Pique * "Software"), to deal in the Software without restriction, including
8*84e872a0SLloyd Pique * without limitation the rights to use, copy, modify, merge, publish,
9*84e872a0SLloyd Pique * distribute, sublicense, and/or sell copies of the Software, and to
10*84e872a0SLloyd Pique * permit persons to whom the Software is furnished to do so, subject to
11*84e872a0SLloyd Pique * the following conditions:
12*84e872a0SLloyd Pique *
13*84e872a0SLloyd Pique * The above copyright notice and this permission notice (including the
14*84e872a0SLloyd Pique * next paragraph) shall be included in all copies or substantial
15*84e872a0SLloyd Pique * portions of the Software.
16*84e872a0SLloyd Pique *
17*84e872a0SLloyd Pique * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18*84e872a0SLloyd Pique * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*84e872a0SLloyd Pique * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*84e872a0SLloyd Pique * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21*84e872a0SLloyd Pique * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22*84e872a0SLloyd Pique * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23*84e872a0SLloyd Pique * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*84e872a0SLloyd Pique * SOFTWARE.
25*84e872a0SLloyd Pique */
26*84e872a0SLloyd Pique
27*84e872a0SLloyd Pique #define _GNU_SOURCE
28*84e872a0SLloyd Pique #include <stdlib.h>
29*84e872a0SLloyd Pique #include <stdint.h>
30*84e872a0SLloyd Pique #include <assert.h>
31*84e872a0SLloyd Pique #include <unistd.h>
32*84e872a0SLloyd Pique #include <signal.h>
33*84e872a0SLloyd Pique #include <string.h>
34*84e872a0SLloyd Pique #include <sys/time.h>
35*84e872a0SLloyd Pique
36*84e872a0SLloyd Pique #include "wayland-private.h"
37*84e872a0SLloyd Pique #include "wayland-server.h"
38*84e872a0SLloyd Pique #include "test-runner.h"
39*84e872a0SLloyd Pique
40*84e872a0SLloyd Pique static int
fd_dispatch(int fd,uint32_t mask,void * data)41*84e872a0SLloyd Pique fd_dispatch(int fd, uint32_t mask, void *data)
42*84e872a0SLloyd Pique {
43*84e872a0SLloyd Pique int *p = data;
44*84e872a0SLloyd Pique
45*84e872a0SLloyd Pique assert(mask == 0);
46*84e872a0SLloyd Pique ++(*p);
47*84e872a0SLloyd Pique
48*84e872a0SLloyd Pique return 0;
49*84e872a0SLloyd Pique }
50*84e872a0SLloyd Pique
TEST(event_loop_post_dispatch_check)51*84e872a0SLloyd Pique TEST(event_loop_post_dispatch_check)
52*84e872a0SLloyd Pique {
53*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
54*84e872a0SLloyd Pique struct wl_event_source *source;
55*84e872a0SLloyd Pique int dispatch_ran = 0;
56*84e872a0SLloyd Pique int p[2];
57*84e872a0SLloyd Pique
58*84e872a0SLloyd Pique assert(loop);
59*84e872a0SLloyd Pique assert(pipe(p) == 0);
60*84e872a0SLloyd Pique
61*84e872a0SLloyd Pique source = wl_event_loop_add_fd(loop, p[0], WL_EVENT_READABLE,
62*84e872a0SLloyd Pique fd_dispatch, &dispatch_ran);
63*84e872a0SLloyd Pique assert(source);
64*84e872a0SLloyd Pique wl_event_source_check(source);
65*84e872a0SLloyd Pique
66*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 0);
67*84e872a0SLloyd Pique assert(dispatch_ran == 1);
68*84e872a0SLloyd Pique
69*84e872a0SLloyd Pique assert(close(p[0]) == 0);
70*84e872a0SLloyd Pique assert(close(p[1]) == 0);
71*84e872a0SLloyd Pique wl_event_source_remove(source);
72*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
73*84e872a0SLloyd Pique }
74*84e872a0SLloyd Pique
75*84e872a0SLloyd Pique struct free_source_context {
76*84e872a0SLloyd Pique struct wl_event_source *source1, *source2;
77*84e872a0SLloyd Pique int p1[2], p2[2];
78*84e872a0SLloyd Pique int count;
79*84e872a0SLloyd Pique };
80*84e872a0SLloyd Pique
81*84e872a0SLloyd Pique static int
free_source_callback(int fd,uint32_t mask,void * data)82*84e872a0SLloyd Pique free_source_callback(int fd, uint32_t mask, void *data)
83*84e872a0SLloyd Pique {
84*84e872a0SLloyd Pique struct free_source_context *context = data;
85*84e872a0SLloyd Pique
86*84e872a0SLloyd Pique context->count++;
87*84e872a0SLloyd Pique
88*84e872a0SLloyd Pique /* Remove other source */
89*84e872a0SLloyd Pique if (fd == context->p1[0]) {
90*84e872a0SLloyd Pique wl_event_source_remove(context->source2);
91*84e872a0SLloyd Pique context->source2 = NULL;
92*84e872a0SLloyd Pique } else if (fd == context->p2[0]) {
93*84e872a0SLloyd Pique wl_event_source_remove(context->source1);
94*84e872a0SLloyd Pique context->source1 = NULL;
95*84e872a0SLloyd Pique } else {
96*84e872a0SLloyd Pique assert(0);
97*84e872a0SLloyd Pique }
98*84e872a0SLloyd Pique
99*84e872a0SLloyd Pique return 1;
100*84e872a0SLloyd Pique }
101*84e872a0SLloyd Pique
TEST(event_loop_free_source_with_data)102*84e872a0SLloyd Pique TEST(event_loop_free_source_with_data)
103*84e872a0SLloyd Pique {
104*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
105*84e872a0SLloyd Pique struct free_source_context context;
106*84e872a0SLloyd Pique int data;
107*84e872a0SLloyd Pique
108*84e872a0SLloyd Pique /* This test is a little tricky to get right, since we don't
109*84e872a0SLloyd Pique * have any guarantee from the event loop (ie epoll) on the
110*84e872a0SLloyd Pique * order of which it reports events. We want to have one
111*84e872a0SLloyd Pique * source free the other, but we don't know which one is going
112*84e872a0SLloyd Pique * to run first. So we add two fd sources with a callback
113*84e872a0SLloyd Pique * that frees the other source and check that only one of them
114*84e872a0SLloyd Pique * run (and that we don't crash, of course).
115*84e872a0SLloyd Pique */
116*84e872a0SLloyd Pique
117*84e872a0SLloyd Pique assert(loop);
118*84e872a0SLloyd Pique
119*84e872a0SLloyd Pique context.count = 0;
120*84e872a0SLloyd Pique assert(pipe(context.p1) == 0);
121*84e872a0SLloyd Pique assert(pipe(context.p2) == 0);
122*84e872a0SLloyd Pique context.source1 =
123*84e872a0SLloyd Pique wl_event_loop_add_fd(loop, context.p1[0], WL_EVENT_READABLE,
124*84e872a0SLloyd Pique free_source_callback, &context);
125*84e872a0SLloyd Pique assert(context.source1);
126*84e872a0SLloyd Pique context.source2 =
127*84e872a0SLloyd Pique wl_event_loop_add_fd(loop, context.p2[0], WL_EVENT_READABLE,
128*84e872a0SLloyd Pique free_source_callback, &context);
129*84e872a0SLloyd Pique assert(context.source2);
130*84e872a0SLloyd Pique
131*84e872a0SLloyd Pique data = 5;
132*84e872a0SLloyd Pique assert(write(context.p1[1], &data, sizeof data) == sizeof data);
133*84e872a0SLloyd Pique assert(write(context.p2[1], &data, sizeof data) == sizeof data);
134*84e872a0SLloyd Pique
135*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 0);
136*84e872a0SLloyd Pique
137*84e872a0SLloyd Pique assert(context.count == 1);
138*84e872a0SLloyd Pique
139*84e872a0SLloyd Pique if (context.source1)
140*84e872a0SLloyd Pique wl_event_source_remove(context.source1);
141*84e872a0SLloyd Pique if (context.source2)
142*84e872a0SLloyd Pique wl_event_source_remove(context.source2);
143*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
144*84e872a0SLloyd Pique
145*84e872a0SLloyd Pique assert(close(context.p1[0]) == 0);
146*84e872a0SLloyd Pique assert(close(context.p1[1]) == 0);
147*84e872a0SLloyd Pique assert(close(context.p2[0]) == 0);
148*84e872a0SLloyd Pique assert(close(context.p2[1]) == 0);
149*84e872a0SLloyd Pique }
150*84e872a0SLloyd Pique
151*84e872a0SLloyd Pique static int
signal_callback(int signal_number,void * data)152*84e872a0SLloyd Pique signal_callback(int signal_number, void *data)
153*84e872a0SLloyd Pique {
154*84e872a0SLloyd Pique int *got_it = data;
155*84e872a0SLloyd Pique
156*84e872a0SLloyd Pique assert(signal_number == SIGUSR1);
157*84e872a0SLloyd Pique ++(*got_it);
158*84e872a0SLloyd Pique
159*84e872a0SLloyd Pique return 1;
160*84e872a0SLloyd Pique }
161*84e872a0SLloyd Pique
TEST(event_loop_signal)162*84e872a0SLloyd Pique TEST(event_loop_signal)
163*84e872a0SLloyd Pique {
164*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
165*84e872a0SLloyd Pique struct wl_event_source *source;
166*84e872a0SLloyd Pique int got_it = 0;
167*84e872a0SLloyd Pique
168*84e872a0SLloyd Pique source = wl_event_loop_add_signal(loop, SIGUSR1,
169*84e872a0SLloyd Pique signal_callback, &got_it);
170*84e872a0SLloyd Pique assert(source);
171*84e872a0SLloyd Pique
172*84e872a0SLloyd Pique assert(wl_event_loop_dispatch(loop, 0) == 0);
173*84e872a0SLloyd Pique assert(!got_it);
174*84e872a0SLloyd Pique assert(kill(getpid(), SIGUSR1) == 0);
175*84e872a0SLloyd Pique /*
176*84e872a0SLloyd Pique * On Linux the signal will be immediately visible in the epoll_wait()
177*84e872a0SLloyd Pique * call. However, on FreeBSD we may need a small delay between kill()
178*84e872a0SLloyd Pique * call and the signal being visible to the kevent() call. This
179*84e872a0SLloyd Pique * sometimes happens when the signal processing and kevent processing
180*84e872a0SLloyd Pique * runs on different CPUs, so becomes more likely when the system is
181*84e872a0SLloyd Pique * under load (e.g. running all tests in parallel).
182*84e872a0SLloyd Pique * See https://github.com/jiixyj/epoll-shim/pull/32
183*84e872a0SLloyd Pique * Passing 1ms as the timeout appears to avoid this race condition in
184*84e872a0SLloyd Pique * all cases tested so far, but to be safe we use 1000ms which should
185*84e872a0SLloyd Pique * be enough time even on a really slow (or emulated) system.
186*84e872a0SLloyd Pique */
187*84e872a0SLloyd Pique assert(wl_event_loop_dispatch(loop, 1000) == 0);
188*84e872a0SLloyd Pique assert(got_it == 1);
189*84e872a0SLloyd Pique
190*84e872a0SLloyd Pique wl_event_source_remove(source);
191*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
192*84e872a0SLloyd Pique }
193*84e872a0SLloyd Pique
TEST(event_loop_multiple_same_signals)194*84e872a0SLloyd Pique TEST(event_loop_multiple_same_signals)
195*84e872a0SLloyd Pique {
196*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
197*84e872a0SLloyd Pique struct wl_event_source *s1, *s2;
198*84e872a0SLloyd Pique int calls_no = 0;
199*84e872a0SLloyd Pique int i;
200*84e872a0SLloyd Pique
201*84e872a0SLloyd Pique s1 = wl_event_loop_add_signal(loop, SIGUSR1,
202*84e872a0SLloyd Pique signal_callback, &calls_no);
203*84e872a0SLloyd Pique assert(s1);
204*84e872a0SLloyd Pique
205*84e872a0SLloyd Pique s2 = wl_event_loop_add_signal(loop, SIGUSR1,
206*84e872a0SLloyd Pique signal_callback, &calls_no);
207*84e872a0SLloyd Pique assert(s2);
208*84e872a0SLloyd Pique
209*84e872a0SLloyd Pique assert(wl_event_loop_dispatch(loop, 0) == 0);
210*84e872a0SLloyd Pique assert(!calls_no);
211*84e872a0SLloyd Pique
212*84e872a0SLloyd Pique /* Try it more times */
213*84e872a0SLloyd Pique for (i = 0; i < 5; ++i) {
214*84e872a0SLloyd Pique calls_no = 0;
215*84e872a0SLloyd Pique assert(kill(getpid(), SIGUSR1) == 0);
216*84e872a0SLloyd Pique /*
217*84e872a0SLloyd Pique * We need a non-zero timeout here to allow the test to pass
218*84e872a0SLloyd Pique * on non-Linux systems (see comment in event_loop_signal).
219*84e872a0SLloyd Pique */
220*84e872a0SLloyd Pique assert(wl_event_loop_dispatch(loop, 1000) == 0);
221*84e872a0SLloyd Pique assert(calls_no == 2);
222*84e872a0SLloyd Pique }
223*84e872a0SLloyd Pique
224*84e872a0SLloyd Pique wl_event_source_remove(s1);
225*84e872a0SLloyd Pique
226*84e872a0SLloyd Pique /* Try it again with one source */
227*84e872a0SLloyd Pique calls_no = 0;
228*84e872a0SLloyd Pique assert(kill(getpid(), SIGUSR1) == 0);
229*84e872a0SLloyd Pique /*
230*84e872a0SLloyd Pique * We need a non-zero timeout here to allow the test to pass
231*84e872a0SLloyd Pique * on non-Linux systems (see comment in event_loop_signal).
232*84e872a0SLloyd Pique */
233*84e872a0SLloyd Pique assert(wl_event_loop_dispatch(loop, 1000) == 0);
234*84e872a0SLloyd Pique assert(calls_no == 1);
235*84e872a0SLloyd Pique
236*84e872a0SLloyd Pique wl_event_source_remove(s2);
237*84e872a0SLloyd Pique
238*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
239*84e872a0SLloyd Pique }
240*84e872a0SLloyd Pique
241*84e872a0SLloyd Pique static int
timer_callback(void * data)242*84e872a0SLloyd Pique timer_callback(void *data)
243*84e872a0SLloyd Pique {
244*84e872a0SLloyd Pique int *got_it = data;
245*84e872a0SLloyd Pique
246*84e872a0SLloyd Pique ++(*got_it);
247*84e872a0SLloyd Pique
248*84e872a0SLloyd Pique return 1;
249*84e872a0SLloyd Pique }
250*84e872a0SLloyd Pique
TEST(event_loop_timer)251*84e872a0SLloyd Pique TEST(event_loop_timer)
252*84e872a0SLloyd Pique {
253*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
254*84e872a0SLloyd Pique struct wl_event_source *source1, *source2;
255*84e872a0SLloyd Pique int got_it = 0;
256*84e872a0SLloyd Pique
257*84e872a0SLloyd Pique source1 = wl_event_loop_add_timer(loop, timer_callback, &got_it);
258*84e872a0SLloyd Pique assert(source1);
259*84e872a0SLloyd Pique wl_event_source_timer_update(source1, 20);
260*84e872a0SLloyd Pique
261*84e872a0SLloyd Pique source2 = wl_event_loop_add_timer(loop, timer_callback, &got_it);
262*84e872a0SLloyd Pique assert(source2);
263*84e872a0SLloyd Pique wl_event_source_timer_update(source2, 100);
264*84e872a0SLloyd Pique
265*84e872a0SLloyd Pique /* Check that the timer marked for 20 msec from now fires within 30
266*84e872a0SLloyd Pique * msec, and that the timer marked for 100 msec is expected to fire
267*84e872a0SLloyd Pique * within an additional 90 msec. (Some extra wait time is provided to
268*84e872a0SLloyd Pique * account for reasonable code execution / thread preemption delays.) */
269*84e872a0SLloyd Pique
270*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 0);
271*84e872a0SLloyd Pique assert(got_it == 0);
272*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 30);
273*84e872a0SLloyd Pique assert(got_it == 1);
274*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 0);
275*84e872a0SLloyd Pique assert(got_it == 1);
276*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 90);
277*84e872a0SLloyd Pique assert(got_it == 2);
278*84e872a0SLloyd Pique
279*84e872a0SLloyd Pique wl_event_source_remove(source1);
280*84e872a0SLloyd Pique wl_event_source_remove(source2);
281*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
282*84e872a0SLloyd Pique }
283*84e872a0SLloyd Pique
284*84e872a0SLloyd Pique #define MSEC_TO_USEC(msec) ((msec) * 1000)
285*84e872a0SLloyd Pique
286*84e872a0SLloyd Pique struct timer_update_context {
287*84e872a0SLloyd Pique struct wl_event_source *source1, *source2;
288*84e872a0SLloyd Pique int count;
289*84e872a0SLloyd Pique };
290*84e872a0SLloyd Pique
291*84e872a0SLloyd Pique static int
timer_update_callback_1(void * data)292*84e872a0SLloyd Pique timer_update_callback_1(void *data)
293*84e872a0SLloyd Pique {
294*84e872a0SLloyd Pique struct timer_update_context *context = data;
295*84e872a0SLloyd Pique
296*84e872a0SLloyd Pique context->count++;
297*84e872a0SLloyd Pique wl_event_source_timer_update(context->source2, 1000);
298*84e872a0SLloyd Pique return 1;
299*84e872a0SLloyd Pique }
300*84e872a0SLloyd Pique
301*84e872a0SLloyd Pique static int
timer_update_callback_2(void * data)302*84e872a0SLloyd Pique timer_update_callback_2(void *data)
303*84e872a0SLloyd Pique {
304*84e872a0SLloyd Pique struct timer_update_context *context = data;
305*84e872a0SLloyd Pique
306*84e872a0SLloyd Pique context->count++;
307*84e872a0SLloyd Pique wl_event_source_timer_update(context->source1, 1000);
308*84e872a0SLloyd Pique return 1;
309*84e872a0SLloyd Pique }
310*84e872a0SLloyd Pique
TEST(event_loop_timer_updates)311*84e872a0SLloyd Pique TEST(event_loop_timer_updates)
312*84e872a0SLloyd Pique {
313*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
314*84e872a0SLloyd Pique struct timer_update_context context;
315*84e872a0SLloyd Pique struct timeval start_time, end_time, interval;
316*84e872a0SLloyd Pique
317*84e872a0SLloyd Pique /* Create two timers that should expire at the same time (after 10ms).
318*84e872a0SLloyd Pique * The first timer to receive its expiry callback updates the other timer
319*84e872a0SLloyd Pique * with a much larger timeout (1s). This highlights a bug where
320*84e872a0SLloyd Pique * wl_event_source_timer_dispatch would block for this larger timeout
321*84e872a0SLloyd Pique * when reading from the timer fd, before calling the second timer's
322*84e872a0SLloyd Pique * callback.
323*84e872a0SLloyd Pique */
324*84e872a0SLloyd Pique
325*84e872a0SLloyd Pique context.source1 = wl_event_loop_add_timer(loop, timer_update_callback_1,
326*84e872a0SLloyd Pique &context);
327*84e872a0SLloyd Pique assert(context.source1);
328*84e872a0SLloyd Pique assert(wl_event_source_timer_update(context.source1, 10) == 0);
329*84e872a0SLloyd Pique
330*84e872a0SLloyd Pique context.source2 = wl_event_loop_add_timer(loop, timer_update_callback_2,
331*84e872a0SLloyd Pique &context);
332*84e872a0SLloyd Pique assert(context.source2);
333*84e872a0SLloyd Pique assert(wl_event_source_timer_update(context.source2, 10) == 0);
334*84e872a0SLloyd Pique
335*84e872a0SLloyd Pique context.count = 0;
336*84e872a0SLloyd Pique
337*84e872a0SLloyd Pique /* Since calling the functions between source2's update and
338*84e872a0SLloyd Pique * wl_event_loop_dispatch() takes some time, it may happen
339*84e872a0SLloyd Pique * that only one timer expires until we call epoll_wait.
340*84e872a0SLloyd Pique * This naturally means that only one source is dispatched
341*84e872a0SLloyd Pique * and the test fails. To fix that, sleep 15 ms before
342*84e872a0SLloyd Pique * calling wl_event_loop_dispatch(). That should be enough
343*84e872a0SLloyd Pique * for the second timer to expire.
344*84e872a0SLloyd Pique *
345*84e872a0SLloyd Pique * https://bugs.freedesktop.org/show_bug.cgi?id=80594
346*84e872a0SLloyd Pique */
347*84e872a0SLloyd Pique usleep(MSEC_TO_USEC(15));
348*84e872a0SLloyd Pique
349*84e872a0SLloyd Pique gettimeofday(&start_time, NULL);
350*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 20);
351*84e872a0SLloyd Pique gettimeofday(&end_time, NULL);
352*84e872a0SLloyd Pique
353*84e872a0SLloyd Pique assert(context.count == 2);
354*84e872a0SLloyd Pique
355*84e872a0SLloyd Pique /* Dispatching the events should not have taken much more than 20ms,
356*84e872a0SLloyd Pique * since this is the timeout passed to wl_event_loop_dispatch. If it
357*84e872a0SLloyd Pique * blocked, then it will have taken over 1s.
358*84e872a0SLloyd Pique * Of course, it could take over 1s anyway on a very slow or heavily
359*84e872a0SLloyd Pique * loaded system, so this test isn't 100% perfect.
360*84e872a0SLloyd Pique */
361*84e872a0SLloyd Pique
362*84e872a0SLloyd Pique timersub(&end_time, &start_time, &interval);
363*84e872a0SLloyd Pique assert(interval.tv_sec < 1);
364*84e872a0SLloyd Pique
365*84e872a0SLloyd Pique wl_event_source_remove(context.source1);
366*84e872a0SLloyd Pique wl_event_source_remove(context.source2);
367*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
368*84e872a0SLloyd Pique }
369*84e872a0SLloyd Pique
370*84e872a0SLloyd Pique struct timer_order_data {
371*84e872a0SLloyd Pique struct wl_event_source *source;
372*84e872a0SLloyd Pique int *last_number;
373*84e872a0SLloyd Pique int number;
374*84e872a0SLloyd Pique };
375*84e872a0SLloyd Pique
376*84e872a0SLloyd Pique static int
timer_order_callback(void * data)377*84e872a0SLloyd Pique timer_order_callback(void *data)
378*84e872a0SLloyd Pique {
379*84e872a0SLloyd Pique struct timer_order_data *tod = data;
380*84e872a0SLloyd Pique
381*84e872a0SLloyd Pique /* Check that the timers have the correct sequence */
382*84e872a0SLloyd Pique assert(tod->number == *tod->last_number + 2);
383*84e872a0SLloyd Pique *tod->last_number = tod->number;
384*84e872a0SLloyd Pique return 0;
385*84e872a0SLloyd Pique }
386*84e872a0SLloyd Pique
TEST(event_loop_timer_order)387*84e872a0SLloyd Pique TEST(event_loop_timer_order)
388*84e872a0SLloyd Pique {
389*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
390*84e872a0SLloyd Pique struct timer_order_data order[20];
391*84e872a0SLloyd Pique int i, j;
392*84e872a0SLloyd Pique int last = -1;
393*84e872a0SLloyd Pique
394*84e872a0SLloyd Pique /* Configure a set of timers so that only timers 1, 3, 5, ..., 19
395*84e872a0SLloyd Pique * (in that order) will be dispatched when the event loop is run */
396*84e872a0SLloyd Pique
397*84e872a0SLloyd Pique for (i = 0; i < 20; i++) {
398*84e872a0SLloyd Pique order[i].number = i;
399*84e872a0SLloyd Pique order[i].last_number = &last;
400*84e872a0SLloyd Pique order[i].source =
401*84e872a0SLloyd Pique wl_event_loop_add_timer(loop, timer_order_callback,
402*84e872a0SLloyd Pique &order[i]);
403*84e872a0SLloyd Pique assert(order[i].source);
404*84e872a0SLloyd Pique assert(wl_event_source_timer_update(order[i].source, 10) == 0);
405*84e872a0SLloyd Pique }
406*84e872a0SLloyd Pique
407*84e872a0SLloyd Pique for (i = 0; i < 20; i++) {
408*84e872a0SLloyd Pique /* Permute the order in which timers are updated, so as to
409*84e872a0SLloyd Pique * more exhaustively test the underlying priority queue code */
410*84e872a0SLloyd Pique j = ((i + 3) * 17) % 20;
411*84e872a0SLloyd Pique assert(wl_event_source_timer_update(order[j].source, j) == 0);
412*84e872a0SLloyd Pique }
413*84e872a0SLloyd Pique for (i = 0; i < 20; i += 2) {
414*84e872a0SLloyd Pique assert(wl_event_source_timer_update(order[i].source, 0) == 0);
415*84e872a0SLloyd Pique }
416*84e872a0SLloyd Pique
417*84e872a0SLloyd Pique /* Wait until all timers are due */
418*84e872a0SLloyd Pique usleep(MSEC_TO_USEC(21));
419*84e872a0SLloyd Pique wl_event_loop_dispatch(loop, 0);
420*84e872a0SLloyd Pique assert(last == 19);
421*84e872a0SLloyd Pique
422*84e872a0SLloyd Pique for (i = 0; i < 20; i++) {
423*84e872a0SLloyd Pique wl_event_source_remove(order[i].source);
424*84e872a0SLloyd Pique }
425*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
426*84e872a0SLloyd Pique }
427*84e872a0SLloyd Pique
428*84e872a0SLloyd Pique struct timer_cancel_context {
429*84e872a0SLloyd Pique struct wl_event_source *timers[4];
430*84e872a0SLloyd Pique struct timer_cancel_context *back_refs[4];
431*84e872a0SLloyd Pique int order[4];
432*84e872a0SLloyd Pique int called, first;
433*84e872a0SLloyd Pique };
434*84e872a0SLloyd Pique
435*84e872a0SLloyd Pique static int
timer_cancel_callback(void * data)436*84e872a0SLloyd Pique timer_cancel_callback(void *data) {
437*84e872a0SLloyd Pique struct timer_cancel_context **context_ref = data;
438*84e872a0SLloyd Pique struct timer_cancel_context *context = *context_ref;
439*84e872a0SLloyd Pique int i = (int)(context_ref - context->back_refs);
440*84e872a0SLloyd Pique
441*84e872a0SLloyd Pique context->called++;
442*84e872a0SLloyd Pique context->order[i] = context->called;
443*84e872a0SLloyd Pique
444*84e872a0SLloyd Pique if (context->called == 1) {
445*84e872a0SLloyd Pique context->first = i;
446*84e872a0SLloyd Pique /* Removing a timer always prevents its callback from
447*84e872a0SLloyd Pique * being called ... */
448*84e872a0SLloyd Pique wl_event_source_remove(context->timers[(i + 1) % 4]);
449*84e872a0SLloyd Pique /* ... but disarming or rescheduling a timer does not,
450*84e872a0SLloyd Pique * (in the case where the modified timers had already expired
451*84e872a0SLloyd Pique * as of when `wl_event_loop_dispatch` was called.) */
452*84e872a0SLloyd Pique assert(wl_event_source_timer_update(context->timers[(i + 2) % 4],
453*84e872a0SLloyd Pique 0) == 0);
454*84e872a0SLloyd Pique assert(wl_event_source_timer_update(context->timers[(i + 3) % 4],
455*84e872a0SLloyd Pique 2000000000) == 0);
456*84e872a0SLloyd Pique }
457*84e872a0SLloyd Pique
458*84e872a0SLloyd Pique return 0;
459*84e872a0SLloyd Pique }
460*84e872a0SLloyd Pique
TEST(event_loop_timer_cancellation)461*84e872a0SLloyd Pique TEST(event_loop_timer_cancellation)
462*84e872a0SLloyd Pique {
463*84e872a0SLloyd Pique struct wl_event_loop *loop = wl_event_loop_create();
464*84e872a0SLloyd Pique struct timer_cancel_context context;
465*84e872a0SLloyd Pique int i;
466*84e872a0SLloyd Pique
467*84e872a0SLloyd Pique memset(&context, 0, sizeof(context));
468*84e872a0SLloyd Pique
469*84e872a0SLloyd Pique /* Test that when multiple timers are dispatched in a single call
470*84e872a0SLloyd Pique * of `wl_event_loop_dispatch`, that having some timers run code
471*84e872a0SLloyd Pique * to modify the other timers only actually prevents the other timers
472*84e872a0SLloyd Pique * from running their callbacks when the those timers are removed, not
473*84e872a0SLloyd Pique * when they are disarmed or rescheduled. */
474*84e872a0SLloyd Pique
475*84e872a0SLloyd Pique for (i = 0; i < 4; i++) {
476*84e872a0SLloyd Pique context.back_refs[i] = &context;
477*84e872a0SLloyd Pique context.timers[i] =
478*84e872a0SLloyd Pique wl_event_loop_add_timer(loop, timer_cancel_callback,
479*84e872a0SLloyd Pique &context.back_refs[i]);
480*84e872a0SLloyd Pique assert(context.timers[i]);
481*84e872a0SLloyd Pique
482*84e872a0SLloyd Pique assert(wl_event_source_timer_update(context.timers[i], 1) == 0);
483*84e872a0SLloyd Pique }
484*84e872a0SLloyd Pique
485*84e872a0SLloyd Pique usleep(MSEC_TO_USEC(2));
486*84e872a0SLloyd Pique assert(wl_event_loop_dispatch(loop, 0) == 0);
487*84e872a0SLloyd Pique
488*84e872a0SLloyd Pique /* Tracking which timer was first makes this test independent of the
489*84e872a0SLloyd Pique * actual timer dispatch order, which is not guaranteed by the docs */
490*84e872a0SLloyd Pique assert(context.order[context.first] == 1);
491*84e872a0SLloyd Pique assert(context.order[(context.first + 1) % 4] == 0);
492*84e872a0SLloyd Pique assert(context.order[(context.first + 2) % 4] > 1);
493*84e872a0SLloyd Pique assert(context.order[(context.first + 3) % 4] > 1);
494*84e872a0SLloyd Pique
495*84e872a0SLloyd Pique wl_event_source_remove(context.timers[context.first]);
496*84e872a0SLloyd Pique wl_event_source_remove(context.timers[(context.first + 2) % 4]);
497*84e872a0SLloyd Pique wl_event_source_remove(context.timers[(context.first + 3) % 4]);
498*84e872a0SLloyd Pique
499*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
500*84e872a0SLloyd Pique }
501*84e872a0SLloyd Pique
502*84e872a0SLloyd Pique struct event_loop_destroy_listener {
503*84e872a0SLloyd Pique struct wl_listener listener;
504*84e872a0SLloyd Pique int done;
505*84e872a0SLloyd Pique };
506*84e872a0SLloyd Pique
507*84e872a0SLloyd Pique static void
event_loop_destroy_notify(struct wl_listener * l,void * data)508*84e872a0SLloyd Pique event_loop_destroy_notify(struct wl_listener *l, void *data)
509*84e872a0SLloyd Pique {
510*84e872a0SLloyd Pique struct event_loop_destroy_listener *listener =
511*84e872a0SLloyd Pique wl_container_of(l, listener, listener);
512*84e872a0SLloyd Pique
513*84e872a0SLloyd Pique listener->done = 1;
514*84e872a0SLloyd Pique }
515*84e872a0SLloyd Pique
TEST(event_loop_destroy)516*84e872a0SLloyd Pique TEST(event_loop_destroy)
517*84e872a0SLloyd Pique {
518*84e872a0SLloyd Pique struct wl_event_loop *loop;
519*84e872a0SLloyd Pique struct wl_display * display;
520*84e872a0SLloyd Pique struct event_loop_destroy_listener a, b;
521*84e872a0SLloyd Pique
522*84e872a0SLloyd Pique loop = wl_event_loop_create();
523*84e872a0SLloyd Pique assert(loop);
524*84e872a0SLloyd Pique
525*84e872a0SLloyd Pique a.listener.notify = &event_loop_destroy_notify;
526*84e872a0SLloyd Pique a.done = 0;
527*84e872a0SLloyd Pique wl_event_loop_add_destroy_listener(loop, &a.listener);
528*84e872a0SLloyd Pique
529*84e872a0SLloyd Pique assert(wl_event_loop_get_destroy_listener(loop,
530*84e872a0SLloyd Pique event_loop_destroy_notify) == &a.listener);
531*84e872a0SLloyd Pique
532*84e872a0SLloyd Pique b.listener.notify = &event_loop_destroy_notify;
533*84e872a0SLloyd Pique b.done = 0;
534*84e872a0SLloyd Pique wl_event_loop_add_destroy_listener(loop, &b.listener);
535*84e872a0SLloyd Pique
536*84e872a0SLloyd Pique wl_list_remove(&a.listener.link);
537*84e872a0SLloyd Pique wl_event_loop_destroy(loop);
538*84e872a0SLloyd Pique
539*84e872a0SLloyd Pique assert(!a.done);
540*84e872a0SLloyd Pique assert(b.done);
541*84e872a0SLloyd Pique
542*84e872a0SLloyd Pique /* Test to make sure it gets fired on display destruction */
543*84e872a0SLloyd Pique display = wl_display_create();
544*84e872a0SLloyd Pique assert(display);
545*84e872a0SLloyd Pique loop = wl_display_get_event_loop(display);
546*84e872a0SLloyd Pique assert(loop);
547*84e872a0SLloyd Pique
548*84e872a0SLloyd Pique a.done = 0;
549*84e872a0SLloyd Pique wl_event_loop_add_destroy_listener(loop, &a.listener);
550*84e872a0SLloyd Pique
551*84e872a0SLloyd Pique wl_display_destroy(display);
552*84e872a0SLloyd Pique
553*84e872a0SLloyd Pique assert(a.done);
554*84e872a0SLloyd Pique }
555*84e872a0SLloyd Pique
556