2 * Copyright © 2015 Red Hat, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include "weston-test-client-helper.h"
32 * Test (un)plugging devices
34 * At the end of each test we must return Weston to the previous state
35 * (add all removed devices and remove extra devices), so that
36 * the environment is prepared for the other tests too
39 #define WL_SEAT_CAPABILITY_ALL (WL_SEAT_CAPABILITY_KEYBOARD |\
40 WL_SEAT_CAPABILITY_POINTER |\
41 WL_SEAT_CAPABILITY_TOUCH)
43 char *server_parameters = "--shell=weston-test-desktop-shell.so";
45 /* simply test if weston sends the right capabilities when
46 * some devices are removed */
47 TEST(seat_capabilities_test)
49 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
50 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
52 assert(cl->input->pointer);
53 weston_test_device_release(cl->test->weston_test, "pointer");
55 assert(!cl->input->pointer);
56 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_POINTER));
58 assert(cl->input->keyboard);
59 weston_test_device_release(cl->test->weston_test, "keyboard");
61 assert(!cl->input->keyboard);
62 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_KEYBOARD));
64 assert(cl->input->touch);
65 weston_test_device_release(cl->test->weston_test, "touch");
67 assert(!cl->input->touch);
68 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_TOUCH));
70 /* restore previous state */
71 weston_test_device_add(cl->test->weston_test, "keyboard");
72 weston_test_device_add(cl->test->weston_test, "pointer");
73 weston_test_device_add(cl->test->weston_test, "touch");
76 assert(cl->input->pointer);
77 assert(cl->input->keyboard);
78 assert(cl->input->touch);
80 /* add extra devices */
81 weston_test_device_add(cl->test->weston_test, "keyboard");
82 weston_test_device_add(cl->test->weston_test, "pointer");
83 weston_test_device_add(cl->test->weston_test, "touch");
86 /* remove extra devices */
87 weston_test_device_release(cl->test->weston_test, "keyboard");
88 weston_test_device_release(cl->test->weston_test, "pointer");
89 weston_test_device_release(cl->test->weston_test, "touch");
92 /* we still should have all the capabilities, since the devices
94 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
96 assert(cl->input->pointer);
97 assert(cl->input->keyboard);
98 assert(cl->input->touch);
102 TEST(multiple_device_add_and_remove)
105 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
107 /* add device a lot of times */
108 for (i = 0; i < COUNT; ++i) {
109 weston_test_device_add(cl->test->weston_test, "keyboard");
110 weston_test_device_add(cl->test->weston_test, "pointer");
111 weston_test_device_add(cl->test->weston_test, "touch");
114 client_roundtrip(cl);
116 assert(cl->input->pointer);
117 assert(cl->input->keyboard);
118 assert(cl->input->touch);
120 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
122 /* release all new devices */
123 for (i = 0; i < COUNT; ++i) {
124 weston_test_device_release(cl->test->weston_test, "keyboard");
125 weston_test_device_release(cl->test->weston_test, "pointer");
126 weston_test_device_release(cl->test->weston_test, "touch");
129 client_roundtrip(cl);
131 /* there is still one from each device left */
132 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
134 assert(cl->input->pointer);
135 assert(cl->input->keyboard);
136 assert(cl->input->touch);
139 TEST(device_release_before_destroy)
141 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
143 /* we can release pointer when we won't be using it anymore.
144 * Do it and see what happens if the device is destroyed
145 * right after that */
146 wl_pointer_release(cl->input->pointer->wl_pointer);
147 /* we must free and set to NULL the structures, otherwise
148 * seat capabilities will double-free them */
149 free(cl->input->pointer);
150 cl->input->pointer = NULL;
152 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
153 free(cl->input->keyboard);
154 cl->input->keyboard = NULL;
156 wl_touch_release(cl->input->touch->wl_touch);
157 free(cl->input->touch);
158 cl->input->touch = NULL;
160 weston_test_device_release(cl->test->weston_test, "pointer");
161 weston_test_device_release(cl->test->weston_test, "keyboard");
162 weston_test_device_release(cl->test->weston_test, "touch");
163 client_roundtrip(cl);
165 assert(cl->input->caps == 0);
167 /* restore previous state */
168 weston_test_device_add(cl->test->weston_test, "pointer");
169 weston_test_device_add(cl->test->weston_test, "keyboard");
170 weston_test_device_add(cl->test->weston_test, "touch");
171 client_roundtrip(cl);
173 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
176 TEST(device_release_before_destroy_multiple)
180 /* if weston crashed during this test, then there is
181 * some inconsistency */
182 for (i = 0; i < 30; ++i) {
183 /* Fifty times run the previous test. This will create
184 * fifty clients, because we don't have any
185 * way how to destroy them (worth of adding!). Only one
186 * client will run at a time though and so should have no
187 * effect on the result of the test (after the client
188 * finishes its body, it just 'is' and does nothing). */
189 device_release_before_destroy();
193 /* normal work-flow test */
194 TEST(device_release_after_destroy)
196 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
198 weston_test_device_release(cl->test->weston_test, "pointer");
199 wl_pointer_release(cl->input->pointer->wl_pointer);
200 /* we must free the memory manually, otherwise seat.capabilities
201 * will try to free it and will use invalid proxy */
202 free(cl->input->pointer);
203 cl->input->pointer = NULL;
205 client_roundtrip(cl);
207 weston_test_device_release(cl->test->weston_test, "keyboard");
208 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
209 free(cl->input->keyboard);
210 cl->input->keyboard = NULL;
212 client_roundtrip(cl);
214 weston_test_device_release(cl->test->weston_test, "touch");
215 wl_touch_release(cl->input->touch->wl_touch);
216 free(cl->input->touch);
217 cl->input->touch = NULL;
219 client_roundtrip(cl);
221 assert(cl->input->caps == 0);
223 /* restore previous state */
224 weston_test_device_add(cl->test->weston_test, "pointer");
225 weston_test_device_add(cl->test->weston_test, "keyboard");
226 weston_test_device_add(cl->test->weston_test, "touch");
227 client_roundtrip(cl);
229 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
232 TEST(device_release_after_destroy_multiple)
236 /* if weston crashed during this test, then there is
237 * some inconsistency */
238 for (i = 0; i < 30; ++i) {
239 device_release_after_destroy();
243 /* see https://bugzilla.gnome.org/show_bug.cgi?id=745008
244 * It is a mutter bug, but highly relevant. Weston does not
245 * suffer from this bug atm, but it is worth of testing. */
246 TEST(get_device_after_destroy)
248 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
249 struct wl_pointer *wl_pointer;
250 struct wl_keyboard *wl_keyboard;
251 struct wl_touch *wl_touch;
254 * 1) compositor destroys device
255 * 2) client asks for the device, because it has not received
256 * the new capabilities yet
257 * 3) compositor gets the request with a new_id for the
259 * 4) client uses the new_id
260 * 5) client gets new capabilities, destroying the objects
262 * If the compositor just bails out in step 3) and does not
263 * create the resource, then the client gets an error in step 4)
264 * - even though it followed the protocol (it just didn't know
265 * about new capabilities).
267 * This test simulates this situation
270 /* connection is buffered, so after calling client_roundtrip(),
271 * this whole batch will be delivered to compositor and will
272 * exactly simulate our situation */
273 weston_test_device_release(cl->test->weston_test, "pointer");
274 wl_pointer = wl_seat_get_pointer(cl->input->wl_seat);
277 /* this should be ignored */
278 wl_pointer_set_cursor(wl_pointer, 0, NULL, 0, 0);
280 /* this should not be ignored */
281 wl_pointer_release(wl_pointer);
282 client_roundtrip(cl);
284 weston_test_device_release(cl->test->weston_test, "keyboard");
285 wl_keyboard = wl_seat_get_keyboard(cl->input->wl_seat);
287 wl_keyboard_release(wl_keyboard);
288 client_roundtrip(cl);
290 weston_test_device_release(cl->test->weston_test, "touch");
291 wl_touch = wl_seat_get_touch(cl->input->wl_seat);
293 wl_touch_release(wl_touch);
294 client_roundtrip(cl);
296 /* get weston to the previous state */
297 weston_test_device_add(cl->test->weston_test, "pointer");
298 weston_test_device_add(cl->test->weston_test, "keyboard");
299 weston_test_device_add(cl->test->weston_test, "touch");
300 client_roundtrip(cl);
302 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
305 TEST(get_device_after_destroy_multiple)
309 /* if weston crashed during this test, then there is
310 * some inconsistency */
311 for (i = 0; i < 30; ++i) {
312 get_device_after_destroy();
316 TEST(seats_have_names)
318 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
321 wl_list_for_each(input, &cl->inputs, link) {
322 assert(input->seat_name);
326 TEST(seat_destroy_and_recreate)
328 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
330 weston_test_device_release(cl->test->weston_test, "seat");
331 /* Roundtrip to receive and handle the seat global removal event */
332 client_roundtrip(cl);
336 weston_test_device_add(cl->test->weston_test, "seat");
337 /* First roundtrip to send request and receive new seat global */
338 client_roundtrip(cl);
339 /* Second roundtrip to handle seat events and set up input devices */
340 client_roundtrip(cl);
343 assert(cl->input->pointer);
344 assert(cl->input->keyboard);
345 assert(cl->input->touch);