xref: /aosp_15_r20/external/wayland/tests/event-loop-test.c (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
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