tests: plug fd leaks in free_source_with_data
[profile/ivi/wayland.git] / tests / event-loop-test.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <assert.h>
25 #include <unistd.h>
26 #include "../src/wayland-server.h"
27 #include "test-runner.h"
28
29 static int
30 fd_dispatch(int fd, uint32_t mask, void *data)
31 {
32         int *p = data;
33
34         *p = 1;
35
36         return 0;
37 }
38
39 TEST(post_dispatch_check)
40 {
41         struct wl_event_loop *loop = wl_event_loop_create();
42         struct wl_event_source *source;
43         int dispatch_ran = 0;
44
45         source = wl_event_loop_add_fd(loop, 1, WL_EVENT_READABLE,
46                                       fd_dispatch, &dispatch_ran);
47         wl_event_source_check(source);
48
49         wl_event_loop_dispatch(loop, 0);
50         assert(dispatch_ran);
51
52         wl_event_source_remove(source);
53         wl_event_loop_destroy(loop);
54 }
55
56 struct free_source_context {
57         struct wl_event_source *source1, *source2;
58         int p1[2], p2[2];
59         int count;
60 };
61
62 static int
63 free_source_callback(int fd, uint32_t mask, void *data)
64 {
65         struct free_source_context *context = data;
66
67         context->count++;
68
69         /* Remove other source */
70         if (fd == context->p1[0]) {
71                 wl_event_source_remove(context->source2);
72                 context->source2 = NULL;
73         } else if (fd == context->p2[0]) {
74                 wl_event_source_remove(context->source1);
75                 context->source1 = NULL;
76         } else {
77                 assert(0);
78         }
79
80         return 1;
81 }
82
83 TEST(free_source_with_data)
84 {
85         struct wl_event_loop *loop = wl_event_loop_create();
86         struct free_source_context context;
87         int data;
88
89         /* This test is a little tricky to get right, since we don't
90          * have any guarantee from the event loop (ie epoll) on the
91          * order of which it reports events.  We want to have one
92          * source free the other, but we don't know which one is going
93          * to run first.  So we add two fd sources with a callback
94          * that frees the other source and check that only one of them
95          * run (and that we don't crash, of course).
96          */
97
98         context.count = 0;
99         assert(pipe(context.p1) == 0);
100         assert(pipe(context.p2) == 0);
101         context.source1 =
102                 wl_event_loop_add_fd(loop, context.p1[0], WL_EVENT_READABLE,
103                                      free_source_callback, &context);
104         assert(context.source1);
105         context.source2 =
106                 wl_event_loop_add_fd(loop, context.p2[0], WL_EVENT_READABLE,
107                                      free_source_callback, &context);
108         assert(context.source2);
109
110         data = 5;
111         assert(write(context.p1[1], &data, sizeof data) == sizeof data);
112         assert(write(context.p2[1], &data, sizeof data) == sizeof data);
113
114         wl_event_loop_dispatch(loop, 0);
115
116         assert(context.count == 1);
117
118         if (context.source1)
119                 wl_event_source_remove(context.source1);
120         if (context.source2)
121                 wl_event_source_remove(context.source2);
122         wl_event_loop_destroy(loop);
123
124         assert(close(context.p1[0]) == 0);
125         assert(close(context.p1[1]) == 0);
126         assert(close(context.p2[0]) == 0);
127         assert(close(context.p2[1]) == 0);
128 }