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