blob: 8f9feecc0cf3d07654332a365ebd23950c8b4f21 [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:
252 * 1) compositor destroyes device
253 * 2) client asks for the device, because it has not got
254 * new capabilities yet
255 * 3) compositor gets request with new_id for destroyed device
256 * 4) client uses the new_id
257 * 5) client gets new capabilities, destroying the objects
258 *
259 * If compositor just bail out in step 3) and does not create
260 * resource, then client gets error in step 4) - even though
261 * it followed the protocol (it just didn't know about new
262 * capabilities).
263 *
264 * This test simulates this situation
265 */
266
267 /* connection is buffered, so after calling client_roundtrip(),
268 * this whole batch will be delivered to compositor and will
269 * exactly simulate our situation */
270 weston_test_device_release(cl->test->weston_test, "pointer");
271 wl_pointer = wl_seat_get_pointer(cl->input->wl_seat);
272 assert(wl_pointer);
273
274 /* this should be ignored */
275 wl_pointer_set_cursor(wl_pointer, 0, NULL, 0, 0);
276
277 /* this should not be ignored */
278 wl_pointer_release(wl_pointer);
279 client_roundtrip(cl);
280
281 weston_test_device_release(cl->test->weston_test, "keyboard");
282 wl_keyboard = wl_seat_get_keyboard(cl->input->wl_seat);
283 assert(wl_keyboard);
284 wl_keyboard_release(wl_keyboard);
285 client_roundtrip(cl);
286
287 weston_test_device_release(cl->test->weston_test, "touch");
288 wl_touch = wl_seat_get_touch(cl->input->wl_seat);
289 assert(wl_touch);
290 wl_touch_release(wl_touch);
291 client_roundtrip(cl);
292
293 /* get weston to the previous state */
294 weston_test_device_add(cl->test->weston_test, "pointer");
295 weston_test_device_add(cl->test->weston_test, "keyboard");
296 weston_test_device_add(cl->test->weston_test, "touch");
297 client_roundtrip(cl);
298
299 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
300}
301
Derek Foreman29612052015-05-01 14:30:20 -0500302TEST(get_device_after_destroy_multiple)
Marek Chalupa5fd81402015-03-30 09:21:29 -0400303{
304 int i;
305
306 /* if weston crashed during this test, then there is
307 * some inconsistency */
308 for (i = 0; i < 30; ++i) {
309 get_device_after_destroy();
310 }
311}