1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique * Copyright © 2013 Marek Chalupa
3*84e872a0SLloyd Pique *
4*84e872a0SLloyd Pique * Permission is hereby granted, free of charge, to any person obtaining
5*84e872a0SLloyd Pique * a copy of this software and associated documentation files (the
6*84e872a0SLloyd Pique * "Software"), to deal in the Software without restriction, including
7*84e872a0SLloyd Pique * without limitation the rights to use, copy, modify, merge, publish,
8*84e872a0SLloyd Pique * distribute, sublicense, and/or sell copies of the Software, and to
9*84e872a0SLloyd Pique * permit persons to whom the Software is furnished to do so, subject to
10*84e872a0SLloyd Pique * the following conditions:
11*84e872a0SLloyd Pique *
12*84e872a0SLloyd Pique * The above copyright notice and this permission notice (including the
13*84e872a0SLloyd Pique * next paragraph) shall be included in all copies or substantial
14*84e872a0SLloyd Pique * portions of the Software.
15*84e872a0SLloyd Pique *
16*84e872a0SLloyd Pique * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*84e872a0SLloyd Pique * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*84e872a0SLloyd Pique * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*84e872a0SLloyd Pique * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20*84e872a0SLloyd Pique * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21*84e872a0SLloyd Pique * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22*84e872a0SLloyd Pique * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*84e872a0SLloyd Pique * SOFTWARE.
24*84e872a0SLloyd Pique */
25*84e872a0SLloyd Pique
26*84e872a0SLloyd Pique #include <assert.h>
27*84e872a0SLloyd Pique #include <sys/socket.h>
28*84e872a0SLloyd Pique #include <unistd.h>
29*84e872a0SLloyd Pique #include <stdint.h>
30*84e872a0SLloyd Pique
31*84e872a0SLloyd Pique #include "wayland-server.h"
32*84e872a0SLloyd Pique #include "test-runner.h"
33*84e872a0SLloyd Pique
TEST(create_resource_tst)34*84e872a0SLloyd Pique TEST(create_resource_tst)
35*84e872a0SLloyd Pique {
36*84e872a0SLloyd Pique struct wl_display *display;
37*84e872a0SLloyd Pique struct wl_client *client;
38*84e872a0SLloyd Pique struct wl_resource *res;
39*84e872a0SLloyd Pique struct wl_list *link;
40*84e872a0SLloyd Pique int s[2];
41*84e872a0SLloyd Pique uint32_t id;
42*84e872a0SLloyd Pique
43*84e872a0SLloyd Pique assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
44*84e872a0SLloyd Pique display = wl_display_create();
45*84e872a0SLloyd Pique assert(display);
46*84e872a0SLloyd Pique client = wl_client_create(display, s[0]);
47*84e872a0SLloyd Pique assert(client);
48*84e872a0SLloyd Pique
49*84e872a0SLloyd Pique res = wl_resource_create(client, &wl_seat_interface, 4, 0);
50*84e872a0SLloyd Pique assert(res);
51*84e872a0SLloyd Pique
52*84e872a0SLloyd Pique /* setters/getters */
53*84e872a0SLloyd Pique assert(wl_resource_get_version(res) == 4);
54*84e872a0SLloyd Pique
55*84e872a0SLloyd Pique assert(client == wl_resource_get_client(res));
56*84e872a0SLloyd Pique id = wl_resource_get_id(res);
57*84e872a0SLloyd Pique assert(wl_client_get_object(client, id) == res);
58*84e872a0SLloyd Pique
59*84e872a0SLloyd Pique link = wl_resource_get_link(res);
60*84e872a0SLloyd Pique assert(link);
61*84e872a0SLloyd Pique assert(wl_resource_from_link(link) == res);
62*84e872a0SLloyd Pique
63*84e872a0SLloyd Pique wl_resource_set_user_data(res, (void *) 0xbee);
64*84e872a0SLloyd Pique assert(wl_resource_get_user_data(res) == (void *) 0xbee);
65*84e872a0SLloyd Pique
66*84e872a0SLloyd Pique wl_resource_destroy(res);
67*84e872a0SLloyd Pique wl_client_destroy(client);
68*84e872a0SLloyd Pique wl_display_destroy(display);
69*84e872a0SLloyd Pique close(s[1]);
70*84e872a0SLloyd Pique }
71*84e872a0SLloyd Pique
72*84e872a0SLloyd Pique static void
res_destroy_func(struct wl_resource * res)73*84e872a0SLloyd Pique res_destroy_func(struct wl_resource *res)
74*84e872a0SLloyd Pique {
75*84e872a0SLloyd Pique assert(res);
76*84e872a0SLloyd Pique
77*84e872a0SLloyd Pique _Bool *destr = wl_resource_get_user_data(res);
78*84e872a0SLloyd Pique *destr = 1;
79*84e872a0SLloyd Pique }
80*84e872a0SLloyd Pique
81*84e872a0SLloyd Pique static _Bool notify_called = 0;
82*84e872a0SLloyd Pique static void
destroy_notify(struct wl_listener * l,void * data)83*84e872a0SLloyd Pique destroy_notify(struct wl_listener *l, void *data)
84*84e872a0SLloyd Pique {
85*84e872a0SLloyd Pique assert(l && data);
86*84e872a0SLloyd Pique notify_called = 1;
87*84e872a0SLloyd Pique
88*84e872a0SLloyd Pique /* In real code it's common to free the structure holding the
89*84e872a0SLloyd Pique * listener at this point, but not to remove it from the list.
90*84e872a0SLloyd Pique *
91*84e872a0SLloyd Pique * That's fine since this is a destruction notification and
92*84e872a0SLloyd Pique * it's the last time this signal can fire. We set these
93*84e872a0SLloyd Pique * to NULL so we can check them later to ensure no write after
94*84e872a0SLloyd Pique * "free" occurred.
95*84e872a0SLloyd Pique */
96*84e872a0SLloyd Pique l->link.prev = NULL;
97*84e872a0SLloyd Pique l->link.next = NULL;
98*84e872a0SLloyd Pique }
99*84e872a0SLloyd Pique
TEST(destroy_res_tst)100*84e872a0SLloyd Pique TEST(destroy_res_tst)
101*84e872a0SLloyd Pique {
102*84e872a0SLloyd Pique struct wl_display *display;
103*84e872a0SLloyd Pique struct wl_client *client;
104*84e872a0SLloyd Pique struct wl_resource *res;
105*84e872a0SLloyd Pique int s[2];
106*84e872a0SLloyd Pique unsigned id;
107*84e872a0SLloyd Pique struct wl_list *link;
108*84e872a0SLloyd Pique
109*84e872a0SLloyd Pique _Bool destroyed = 0;
110*84e872a0SLloyd Pique struct wl_listener destroy_listener = {
111*84e872a0SLloyd Pique .notify = &destroy_notify
112*84e872a0SLloyd Pique };
113*84e872a0SLloyd Pique
114*84e872a0SLloyd Pique assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
115*84e872a0SLloyd Pique display = wl_display_create();
116*84e872a0SLloyd Pique assert(display);
117*84e872a0SLloyd Pique client = wl_client_create(display, s[0]);
118*84e872a0SLloyd Pique assert(client);
119*84e872a0SLloyd Pique
120*84e872a0SLloyd Pique res = wl_resource_create(client, &wl_seat_interface, 4, 0);
121*84e872a0SLloyd Pique assert(res);
122*84e872a0SLloyd Pique wl_resource_set_implementation(res, NULL, &destroyed, res_destroy_func);
123*84e872a0SLloyd Pique wl_resource_add_destroy_listener(res, &destroy_listener);
124*84e872a0SLloyd Pique
125*84e872a0SLloyd Pique id = wl_resource_get_id(res);
126*84e872a0SLloyd Pique link = wl_resource_get_link(res);
127*84e872a0SLloyd Pique assert(link);
128*84e872a0SLloyd Pique
129*84e872a0SLloyd Pique wl_resource_destroy(res);
130*84e872a0SLloyd Pique assert(destroyed);
131*84e872a0SLloyd Pique assert(notify_called); /* check if signal was emitted */
132*84e872a0SLloyd Pique assert(wl_client_get_object(client, id) == NULL);
133*84e872a0SLloyd Pique assert(destroy_listener.link.prev == NULL);
134*84e872a0SLloyd Pique assert(destroy_listener.link.next == NULL);
135*84e872a0SLloyd Pique
136*84e872a0SLloyd Pique res = wl_resource_create(client, &wl_seat_interface, 2, 0);
137*84e872a0SLloyd Pique assert(res);
138*84e872a0SLloyd Pique destroyed = 0;
139*84e872a0SLloyd Pique notify_called = 0;
140*84e872a0SLloyd Pique wl_resource_set_destructor(res, res_destroy_func);
141*84e872a0SLloyd Pique wl_resource_set_user_data(res, &destroyed);
142*84e872a0SLloyd Pique wl_resource_add_destroy_listener(res, &destroy_listener);
143*84e872a0SLloyd Pique /* client should destroy the resource upon its destruction */
144*84e872a0SLloyd Pique wl_client_destroy(client);
145*84e872a0SLloyd Pique assert(destroyed);
146*84e872a0SLloyd Pique assert(notify_called);
147*84e872a0SLloyd Pique assert(destroy_listener.link.prev == NULL);
148*84e872a0SLloyd Pique assert(destroy_listener.link.next == NULL);
149*84e872a0SLloyd Pique
150*84e872a0SLloyd Pique wl_display_destroy(display);
151*84e872a0SLloyd Pique close(s[1]);
152*84e872a0SLloyd Pique }
153*84e872a0SLloyd Pique
TEST(create_resource_with_same_id)154*84e872a0SLloyd Pique TEST(create_resource_with_same_id)
155*84e872a0SLloyd Pique {
156*84e872a0SLloyd Pique struct wl_display *display;
157*84e872a0SLloyd Pique struct wl_client *client;
158*84e872a0SLloyd Pique struct wl_resource *res, *res2;
159*84e872a0SLloyd Pique int s[2];
160*84e872a0SLloyd Pique uint32_t id;
161*84e872a0SLloyd Pique
162*84e872a0SLloyd Pique assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
163*84e872a0SLloyd Pique display = wl_display_create();
164*84e872a0SLloyd Pique assert(display);
165*84e872a0SLloyd Pique client = wl_client_create(display, s[0]);
166*84e872a0SLloyd Pique assert(client);
167*84e872a0SLloyd Pique
168*84e872a0SLloyd Pique res = wl_resource_create(client, &wl_seat_interface, 2, 0);
169*84e872a0SLloyd Pique assert(res);
170*84e872a0SLloyd Pique id = wl_resource_get_id(res);
171*84e872a0SLloyd Pique assert(wl_client_get_object(client, id) == res);
172*84e872a0SLloyd Pique
173*84e872a0SLloyd Pique /* this one should replace the old one */
174*84e872a0SLloyd Pique res2 = wl_resource_create(client, &wl_seat_interface, 1, id);
175*84e872a0SLloyd Pique assert(res2 != NULL);
176*84e872a0SLloyd Pique assert(wl_client_get_object(client, id) == res2);
177*84e872a0SLloyd Pique
178*84e872a0SLloyd Pique wl_resource_destroy(res2);
179*84e872a0SLloyd Pique wl_resource_destroy(res);
180*84e872a0SLloyd Pique
181*84e872a0SLloyd Pique wl_client_destroy(client);
182*84e872a0SLloyd Pique wl_display_destroy(display);
183*84e872a0SLloyd Pique close(s[1]);
184*84e872a0SLloyd Pique }
185*84e872a0SLloyd Pique
186*84e872a0SLloyd Pique static void
display_destroy_notify(struct wl_listener * l,void * data)187*84e872a0SLloyd Pique display_destroy_notify(struct wl_listener *l, void *data)
188*84e872a0SLloyd Pique {
189*84e872a0SLloyd Pique l->link.prev = l->link.next = NULL;
190*84e872a0SLloyd Pique }
191*84e872a0SLloyd Pique
TEST(free_without_remove)192*84e872a0SLloyd Pique TEST(free_without_remove)
193*84e872a0SLloyd Pique {
194*84e872a0SLloyd Pique struct wl_display *display;
195*84e872a0SLloyd Pique struct wl_listener a, b;
196*84e872a0SLloyd Pique
197*84e872a0SLloyd Pique display = wl_display_create();
198*84e872a0SLloyd Pique a.notify = display_destroy_notify;
199*84e872a0SLloyd Pique b.notify = display_destroy_notify;
200*84e872a0SLloyd Pique
201*84e872a0SLloyd Pique wl_display_add_destroy_listener(display, &a);
202*84e872a0SLloyd Pique wl_display_add_destroy_listener(display, &b);
203*84e872a0SLloyd Pique
204*84e872a0SLloyd Pique wl_display_destroy(display);
205*84e872a0SLloyd Pique
206*84e872a0SLloyd Pique assert(a.link.next == a.link.prev && a.link.next == NULL);
207*84e872a0SLloyd Pique assert(b.link.next == b.link.prev && b.link.next == NULL);
208*84e872a0SLloyd Pique }
209