blob: 719f4595072e609d1948be44ef2635f80b84d80b [file] [log] [blame]
Marek Chalupa5fd81402015-03-30 09:21:29 -04001/*
2 * Copyright © 2015 Red Hat, Inc.
3 *
Bryce Harrington2cc92972015-06-11 15:39:40 -07004 * 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:
Marek Chalupa5fd81402015-03-30 09:21:29 -040011 *
Bryce Harrington2cc92972015-06-11 15:39:40 -070012 * 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.
15 *
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
23 * SOFTWARE.
Marek Chalupa5fd81402015-03-30 09:21:29 -040024 */
25
26#include "config.h"
27
28#include <string.h>
29#include "weston-test-client-helper.h"
Pekka Paalanen3fb67932019-11-13 15:35:22 +020030#include "weston-test-fixture-compositor.h"
31
32static enum test_result_code
33fixture_setup(struct weston_test_harness *harness)
34{
35 struct compositor_setup setup;
36
37 compositor_setup_defaults(&setup);
38
39 return weston_test_harness_execute_as_client(harness, &setup);
40}
41DECLARE_FIXTURE_SETUP(fixture_setup);
Marek Chalupa5fd81402015-03-30 09:21:29 -040042
43/**
44 * Test (un)plugging devices
45 *
46 * At the end of each test we must return Weston to the previous state
47 * (add all removed devices and remove extra devices), so that
48 * the environment is prepared for the other tests too
49 */
50
51#define WL_SEAT_CAPABILITY_ALL (WL_SEAT_CAPABILITY_KEYBOARD |\
52 WL_SEAT_CAPABILITY_POINTER |\
53 WL_SEAT_CAPABILITY_TOUCH)
54
55/* simply test if weston sends the right capabilities when
56 * some devices are removed */
57TEST(seat_capabilities_test)
58{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +020059 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -040060 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
61
62 assert(cl->input->pointer);
63 weston_test_device_release(cl->test->weston_test, "pointer");
64 client_roundtrip(cl);
65 assert(!cl->input->pointer);
66 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_POINTER));
67
68 assert(cl->input->keyboard);
69 weston_test_device_release(cl->test->weston_test, "keyboard");
70 client_roundtrip(cl);
71 assert(!cl->input->keyboard);
72 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_KEYBOARD));
73
74 assert(cl->input->touch);
75 weston_test_device_release(cl->test->weston_test, "touch");
76 client_roundtrip(cl);
77 assert(!cl->input->touch);
78 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_TOUCH));
79
80 /* restore previous state */
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");
84 client_roundtrip(cl);
85
86 assert(cl->input->pointer);
87 assert(cl->input->keyboard);
88 assert(cl->input->touch);
89
90 /* add extra devices */
91 weston_test_device_add(cl->test->weston_test, "keyboard");
92 weston_test_device_add(cl->test->weston_test, "pointer");
93 weston_test_device_add(cl->test->weston_test, "touch");
94 client_roundtrip(cl);
95
96 /* remove extra devices */
97 weston_test_device_release(cl->test->weston_test, "keyboard");
98 weston_test_device_release(cl->test->weston_test, "pointer");
99 weston_test_device_release(cl->test->weston_test, "touch");
100 client_roundtrip(cl);
101
102 /* we still should have all the capabilities, since the devices
103 * were doubled */
104 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
105
106 assert(cl->input->pointer);
107 assert(cl->input->keyboard);
108 assert(cl->input->touch);
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300109
110 client_destroy(cl);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400111}
112
113#define COUNT 15
114TEST(multiple_device_add_and_remove)
115{
116 int i;
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200117 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400118
119 /* add device a lot of times */
120 for (i = 0; i < COUNT; ++i) {
121 weston_test_device_add(cl->test->weston_test, "keyboard");
122 weston_test_device_add(cl->test->weston_test, "pointer");
123 weston_test_device_add(cl->test->weston_test, "touch");
124 }
125
126 client_roundtrip(cl);
127
128 assert(cl->input->pointer);
129 assert(cl->input->keyboard);
130 assert(cl->input->touch);
131
132 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
133
134 /* release all new devices */
135 for (i = 0; i < COUNT; ++i) {
136 weston_test_device_release(cl->test->weston_test, "keyboard");
137 weston_test_device_release(cl->test->weston_test, "pointer");
138 weston_test_device_release(cl->test->weston_test, "touch");
139 }
140
141 client_roundtrip(cl);
142
143 /* there is still one from each device left */
144 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
145
146 assert(cl->input->pointer);
147 assert(cl->input->keyboard);
148 assert(cl->input->touch);
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300149
150 client_destroy(cl);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400151}
152
153TEST(device_release_before_destroy)
154{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200155 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400156
157 /* we can release pointer when we won't be using it anymore.
158 * Do it and see what happens if the device is destroyed
159 * right after that */
160 wl_pointer_release(cl->input->pointer->wl_pointer);
161 /* we must free and set to NULL the structures, otherwise
162 * seat capabilities will double-free them */
163 free(cl->input->pointer);
164 cl->input->pointer = NULL;
165
166 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
167 free(cl->input->keyboard);
168 cl->input->keyboard = NULL;
169
170 wl_touch_release(cl->input->touch->wl_touch);
171 free(cl->input->touch);
172 cl->input->touch = NULL;
173
174 weston_test_device_release(cl->test->weston_test, "pointer");
175 weston_test_device_release(cl->test->weston_test, "keyboard");
176 weston_test_device_release(cl->test->weston_test, "touch");
177 client_roundtrip(cl);
178
179 assert(cl->input->caps == 0);
180
181 /* restore previous state */
182 weston_test_device_add(cl->test->weston_test, "pointer");
183 weston_test_device_add(cl->test->weston_test, "keyboard");
184 weston_test_device_add(cl->test->weston_test, "touch");
185 client_roundtrip(cl);
186
187 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300188
189 client_destroy(cl);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400190}
191
192TEST(device_release_before_destroy_multiple)
193{
194 int i;
195
196 /* if weston crashed during this test, then there is
197 * some inconsistency */
198 for (i = 0; i < 30; ++i) {
Marek Chalupa5fd81402015-03-30 09:21:29 -0400199 device_release_before_destroy();
200 }
201}
202
203/* normal work-flow test */
204TEST(device_release_after_destroy)
205{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200206 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400207
208 weston_test_device_release(cl->test->weston_test, "pointer");
209 wl_pointer_release(cl->input->pointer->wl_pointer);
210 /* we must free the memory manually, otherwise seat.capabilities
211 * will try to free it and will use invalid proxy */
212 free(cl->input->pointer);
213 cl->input->pointer = NULL;
214
215 client_roundtrip(cl);
216
217 weston_test_device_release(cl->test->weston_test, "keyboard");
218 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
219 free(cl->input->keyboard);
220 cl->input->keyboard = NULL;
221
222 client_roundtrip(cl);
223
224 weston_test_device_release(cl->test->weston_test, "touch");
225 wl_touch_release(cl->input->touch->wl_touch);
226 free(cl->input->touch);
227 cl->input->touch = NULL;
228
229 client_roundtrip(cl);
230
231 assert(cl->input->caps == 0);
232
233 /* restore previous state */
234 weston_test_device_add(cl->test->weston_test, "pointer");
235 weston_test_device_add(cl->test->weston_test, "keyboard");
236 weston_test_device_add(cl->test->weston_test, "touch");
237 client_roundtrip(cl);
238
239 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300240
241 client_destroy(cl);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400242}
243
244TEST(device_release_after_destroy_multiple)
245{
246 int i;
247
248 /* if weston crashed during this test, then there is
249 * some inconsistency */
250 for (i = 0; i < 30; ++i) {
251 device_release_after_destroy();
252 }
253}
254
255/* see https://bugzilla.gnome.org/show_bug.cgi?id=745008
256 * It is a mutter bug, but highly relevant. Weston does not
257 * suffer from this bug atm, but it is worth of testing. */
258TEST(get_device_after_destroy)
259{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200260 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400261 struct wl_pointer *wl_pointer;
262 struct wl_keyboard *wl_keyboard;
263 struct wl_touch *wl_touch;
264
265 /* There's a race:
Bryce Harrington33598ff2015-10-20 08:35:43 -0700266 * 1) compositor destroys device
267 * 2) client asks for the device, because it has not received
268 * the new capabilities yet
269 * 3) compositor gets the request with a new_id for the
270 * destroyed device
Marek Chalupa5fd81402015-03-30 09:21:29 -0400271 * 4) client uses the new_id
272 * 5) client gets new capabilities, destroying the objects
273 *
Bryce Harrington33598ff2015-10-20 08:35:43 -0700274 * If the compositor just bails out in step 3) and does not
275 * create the resource, then the client gets an error in step 4)
276 * - even though it followed the protocol (it just didn't know
277 * about new capabilities).
Marek Chalupa5fd81402015-03-30 09:21:29 -0400278 *
279 * This test simulates this situation
280 */
281
282 /* connection is buffered, so after calling client_roundtrip(),
283 * this whole batch will be delivered to compositor and will
284 * exactly simulate our situation */
285 weston_test_device_release(cl->test->weston_test, "pointer");
286 wl_pointer = wl_seat_get_pointer(cl->input->wl_seat);
287 assert(wl_pointer);
288
289 /* this should be ignored */
290 wl_pointer_set_cursor(wl_pointer, 0, NULL, 0, 0);
291
292 /* this should not be ignored */
293 wl_pointer_release(wl_pointer);
294 client_roundtrip(cl);
295
296 weston_test_device_release(cl->test->weston_test, "keyboard");
297 wl_keyboard = wl_seat_get_keyboard(cl->input->wl_seat);
298 assert(wl_keyboard);
299 wl_keyboard_release(wl_keyboard);
300 client_roundtrip(cl);
301
302 weston_test_device_release(cl->test->weston_test, "touch");
303 wl_touch = wl_seat_get_touch(cl->input->wl_seat);
304 assert(wl_touch);
305 wl_touch_release(wl_touch);
306 client_roundtrip(cl);
307
308 /* get weston to the previous state */
309 weston_test_device_add(cl->test->weston_test, "pointer");
310 weston_test_device_add(cl->test->weston_test, "keyboard");
311 weston_test_device_add(cl->test->weston_test, "touch");
312 client_roundtrip(cl);
313
314 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300315
316 client_destroy(cl);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400317}
318
Derek Foreman29612052015-05-01 14:30:20 -0500319TEST(get_device_after_destroy_multiple)
Marek Chalupa5fd81402015-03-30 09:21:29 -0400320{
321 int i;
322
323 /* if weston crashed during this test, then there is
324 * some inconsistency */
325 for (i = 0; i < 30; ++i) {
326 get_device_after_destroy();
327 }
328}
Alexandros Frantzis468bd0b2018-02-08 15:37:56 +0200329
330TEST(seats_have_names)
331{
332 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
333 struct input *input;
334
335 wl_list_for_each(input, &cl->inputs, link) {
336 assert(input->seat_name);
337 }
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300338
339 client_destroy(cl);
Alexandros Frantzis468bd0b2018-02-08 15:37:56 +0200340}
Alexandros Frantzis8b964bc2018-02-08 15:37:58 +0200341
342TEST(seat_destroy_and_recreate)
343{
344 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
345
346 weston_test_device_release(cl->test->weston_test, "seat");
347 /* Roundtrip to receive and handle the seat global removal event */
348 client_roundtrip(cl);
349
350 assert(!cl->input);
351
352 weston_test_device_add(cl->test->weston_test, "seat");
353 /* First roundtrip to send request and receive new seat global */
354 client_roundtrip(cl);
355 /* Second roundtrip to handle seat events and set up input devices */
356 client_roundtrip(cl);
357
358 assert(cl->input);
359 assert(cl->input->pointer);
360 assert(cl->input->keyboard);
361 assert(cl->input->touch);
Pekka Paalanen591fa3b2021-06-23 13:56:41 +0300362
363 client_destroy(cl);
Alexandros Frantzis8b964bc2018-02-08 15:37:58 +0200364}