blob: 450713e7d890eab6a0098947bf1d8c2c1dbea9c0 [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"
30
31/**
32 * Test (un)plugging devices
33 *
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
37 */
38
39#define WL_SEAT_CAPABILITY_ALL (WL_SEAT_CAPABILITY_KEYBOARD |\
40 WL_SEAT_CAPABILITY_POINTER |\
41 WL_SEAT_CAPABILITY_TOUCH)
42
43/* simply test if weston sends the right capabilities when
44 * some devices are removed */
45TEST(seat_capabilities_test)
46{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +020047 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -040048 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
49
50 assert(cl->input->pointer);
51 weston_test_device_release(cl->test->weston_test, "pointer");
52 client_roundtrip(cl);
53 assert(!cl->input->pointer);
54 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_POINTER));
55
56 assert(cl->input->keyboard);
57 weston_test_device_release(cl->test->weston_test, "keyboard");
58 client_roundtrip(cl);
59 assert(!cl->input->keyboard);
60 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_KEYBOARD));
61
62 assert(cl->input->touch);
63 weston_test_device_release(cl->test->weston_test, "touch");
64 client_roundtrip(cl);
65 assert(!cl->input->touch);
66 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_TOUCH));
67
68 /* restore previous state */
69 weston_test_device_add(cl->test->weston_test, "keyboard");
70 weston_test_device_add(cl->test->weston_test, "pointer");
71 weston_test_device_add(cl->test->weston_test, "touch");
72 client_roundtrip(cl);
73
74 assert(cl->input->pointer);
75 assert(cl->input->keyboard);
76 assert(cl->input->touch);
77
78 /* add extra devices */
79 weston_test_device_add(cl->test->weston_test, "keyboard");
80 weston_test_device_add(cl->test->weston_test, "pointer");
81 weston_test_device_add(cl->test->weston_test, "touch");
82 client_roundtrip(cl);
83
84 /* remove extra devices */
85 weston_test_device_release(cl->test->weston_test, "keyboard");
86 weston_test_device_release(cl->test->weston_test, "pointer");
87 weston_test_device_release(cl->test->weston_test, "touch");
88 client_roundtrip(cl);
89
90 /* we still should have all the capabilities, since the devices
91 * were doubled */
92 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
93
94 assert(cl->input->pointer);
95 assert(cl->input->keyboard);
96 assert(cl->input->touch);
97}
98
99#define COUNT 15
100TEST(multiple_device_add_and_remove)
101{
102 int i;
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200103 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400104
105 /* add device a lot of times */
106 for (i = 0; i < COUNT; ++i) {
107 weston_test_device_add(cl->test->weston_test, "keyboard");
108 weston_test_device_add(cl->test->weston_test, "pointer");
109 weston_test_device_add(cl->test->weston_test, "touch");
110 }
111
112 client_roundtrip(cl);
113
114 assert(cl->input->pointer);
115 assert(cl->input->keyboard);
116 assert(cl->input->touch);
117
118 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
119
120 /* release all new devices */
121 for (i = 0; i < COUNT; ++i) {
122 weston_test_device_release(cl->test->weston_test, "keyboard");
123 weston_test_device_release(cl->test->weston_test, "pointer");
124 weston_test_device_release(cl->test->weston_test, "touch");
125 }
126
127 client_roundtrip(cl);
128
129 /* there is still one from each device left */
130 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
131
132 assert(cl->input->pointer);
133 assert(cl->input->keyboard);
134 assert(cl->input->touch);
135}
136
137TEST(device_release_before_destroy)
138{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200139 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400140
141 /* we can release pointer when we won't be using it anymore.
142 * Do it and see what happens if the device is destroyed
143 * right after that */
144 wl_pointer_release(cl->input->pointer->wl_pointer);
145 /* we must free and set to NULL the structures, otherwise
146 * seat capabilities will double-free them */
147 free(cl->input->pointer);
148 cl->input->pointer = NULL;
149
150 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
151 free(cl->input->keyboard);
152 cl->input->keyboard = NULL;
153
154 wl_touch_release(cl->input->touch->wl_touch);
155 free(cl->input->touch);
156 cl->input->touch = NULL;
157
158 weston_test_device_release(cl->test->weston_test, "pointer");
159 weston_test_device_release(cl->test->weston_test, "keyboard");
160 weston_test_device_release(cl->test->weston_test, "touch");
161 client_roundtrip(cl);
162
163 assert(cl->input->caps == 0);
164
165 /* restore previous state */
166 weston_test_device_add(cl->test->weston_test, "pointer");
167 weston_test_device_add(cl->test->weston_test, "keyboard");
168 weston_test_device_add(cl->test->weston_test, "touch");
169 client_roundtrip(cl);
170
171 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
172}
173
174TEST(device_release_before_destroy_multiple)
175{
176 int i;
177
178 /* if weston crashed during this test, then there is
179 * some inconsistency */
180 for (i = 0; i < 30; ++i) {
181 /* Fifty times run the previous test. This will create
182 * fifty clients, because we don't have any
183 * way how to destroy them (worth of adding!). Only one
184 * client will run at a time though and so should have no
185 * effect on the result of the test (after the client
186 * finishes its body, it just 'is' and does nothing). */
187 device_release_before_destroy();
188 }
189}
190
191/* normal work-flow test */
192TEST(device_release_after_destroy)
193{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200194 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400195
196 weston_test_device_release(cl->test->weston_test, "pointer");
197 wl_pointer_release(cl->input->pointer->wl_pointer);
198 /* we must free the memory manually, otherwise seat.capabilities
199 * will try to free it and will use invalid proxy */
200 free(cl->input->pointer);
201 cl->input->pointer = NULL;
202
203 client_roundtrip(cl);
204
205 weston_test_device_release(cl->test->weston_test, "keyboard");
206 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
207 free(cl->input->keyboard);
208 cl->input->keyboard = NULL;
209
210 client_roundtrip(cl);
211
212 weston_test_device_release(cl->test->weston_test, "touch");
213 wl_touch_release(cl->input->touch->wl_touch);
214 free(cl->input->touch);
215 cl->input->touch = NULL;
216
217 client_roundtrip(cl);
218
219 assert(cl->input->caps == 0);
220
221 /* restore previous state */
222 weston_test_device_add(cl->test->weston_test, "pointer");
223 weston_test_device_add(cl->test->weston_test, "keyboard");
224 weston_test_device_add(cl->test->weston_test, "touch");
225 client_roundtrip(cl);
226
227 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
228}
229
230TEST(device_release_after_destroy_multiple)
231{
232 int i;
233
234 /* if weston crashed during this test, then there is
235 * some inconsistency */
236 for (i = 0; i < 30; ++i) {
237 device_release_after_destroy();
238 }
239}
240
241/* see https://bugzilla.gnome.org/show_bug.cgi?id=745008
242 * It is a mutter bug, but highly relevant. Weston does not
243 * suffer from this bug atm, but it is worth of testing. */
244TEST(get_device_after_destroy)
245{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200246 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400247 struct wl_pointer *wl_pointer;
248 struct wl_keyboard *wl_keyboard;
249 struct wl_touch *wl_touch;
250
251 /* There's a race:
Bryce Harrington33598ff2015-10-20 08:35:43 -0700252 * 1) compositor destroys device
253 * 2) client asks for the device, because it has not received
254 * the new capabilities yet
255 * 3) compositor gets the request with a new_id for the
256 * destroyed device
Marek Chalupa5fd81402015-03-30 09:21:29 -0400257 * 4) client uses the new_id
258 * 5) client gets new capabilities, destroying the objects
259 *
Bryce Harrington33598ff2015-10-20 08:35:43 -0700260 * If the compositor just bails out in step 3) and does not
261 * create the resource, then the client gets an error in step 4)
262 * - even though it followed the protocol (it just didn't know
263 * about new capabilities).
Marek Chalupa5fd81402015-03-30 09:21:29 -0400264 *
265 * This test simulates this situation
266 */
267
268 /* connection is buffered, so after calling client_roundtrip(),
269 * this whole batch will be delivered to compositor and will
270 * exactly simulate our situation */
271 weston_test_device_release(cl->test->weston_test, "pointer");
272 wl_pointer = wl_seat_get_pointer(cl->input->wl_seat);
273 assert(wl_pointer);
274
275 /* this should be ignored */
276 wl_pointer_set_cursor(wl_pointer, 0, NULL, 0, 0);
277
278 /* this should not be ignored */
279 wl_pointer_release(wl_pointer);
280 client_roundtrip(cl);
281
282 weston_test_device_release(cl->test->weston_test, "keyboard");
283 wl_keyboard = wl_seat_get_keyboard(cl->input->wl_seat);
284 assert(wl_keyboard);
285 wl_keyboard_release(wl_keyboard);
286 client_roundtrip(cl);
287
288 weston_test_device_release(cl->test->weston_test, "touch");
289 wl_touch = wl_seat_get_touch(cl->input->wl_seat);
290 assert(wl_touch);
291 wl_touch_release(wl_touch);
292 client_roundtrip(cl);
293
294 /* get weston to the previous state */
295 weston_test_device_add(cl->test->weston_test, "pointer");
296 weston_test_device_add(cl->test->weston_test, "keyboard");
297 weston_test_device_add(cl->test->weston_test, "touch");
298 client_roundtrip(cl);
299
300 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
301}
302
Derek Foreman29612052015-05-01 14:30:20 -0500303TEST(get_device_after_destroy_multiple)
Marek Chalupa5fd81402015-03-30 09:21:29 -0400304{
305 int i;
306
307 /* if weston crashed during this test, then there is
308 * some inconsistency */
309 for (i = 0; i < 30; ++i) {
310 get_device_after_destroy();
311 }
312}