blob: c04d9c5dc367b3ab98b97a93ac5f248fef67814d [file] [log] [blame]
Marek Chalupa5fd81402015-03-30 09:21:29 -04001/*
2 * Copyright © 2015 Red Hat, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include "config.h"
24
25#include <string.h>
26#include "weston-test-client-helper.h"
27
28/**
29 * Test (un)plugging devices
30 *
31 * At the end of each test we must return Weston to the previous state
32 * (add all removed devices and remove extra devices), so that
33 * the environment is prepared for the other tests too
34 */
35
36#define WL_SEAT_CAPABILITY_ALL (WL_SEAT_CAPABILITY_KEYBOARD |\
37 WL_SEAT_CAPABILITY_POINTER |\
38 WL_SEAT_CAPABILITY_TOUCH)
39
40/* simply test if weston sends the right capabilities when
41 * some devices are removed */
42TEST(seat_capabilities_test)
43{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +020044 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -040045 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
46
47 assert(cl->input->pointer);
48 weston_test_device_release(cl->test->weston_test, "pointer");
49 client_roundtrip(cl);
50 assert(!cl->input->pointer);
51 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_POINTER));
52
53 assert(cl->input->keyboard);
54 weston_test_device_release(cl->test->weston_test, "keyboard");
55 client_roundtrip(cl);
56 assert(!cl->input->keyboard);
57 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_KEYBOARD));
58
59 assert(cl->input->touch);
60 weston_test_device_release(cl->test->weston_test, "touch");
61 client_roundtrip(cl);
62 assert(!cl->input->touch);
63 assert(!(cl->input->caps & WL_SEAT_CAPABILITY_TOUCH));
64
65 /* restore previous state */
66 weston_test_device_add(cl->test->weston_test, "keyboard");
67 weston_test_device_add(cl->test->weston_test, "pointer");
68 weston_test_device_add(cl->test->weston_test, "touch");
69 client_roundtrip(cl);
70
71 assert(cl->input->pointer);
72 assert(cl->input->keyboard);
73 assert(cl->input->touch);
74
75 /* add extra devices */
76 weston_test_device_add(cl->test->weston_test, "keyboard");
77 weston_test_device_add(cl->test->weston_test, "pointer");
78 weston_test_device_add(cl->test->weston_test, "touch");
79 client_roundtrip(cl);
80
81 /* remove extra devices */
82 weston_test_device_release(cl->test->weston_test, "keyboard");
83 weston_test_device_release(cl->test->weston_test, "pointer");
84 weston_test_device_release(cl->test->weston_test, "touch");
85 client_roundtrip(cl);
86
87 /* we still should have all the capabilities, since the devices
88 * were doubled */
89 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
90
91 assert(cl->input->pointer);
92 assert(cl->input->keyboard);
93 assert(cl->input->touch);
94}
95
96#define COUNT 15
97TEST(multiple_device_add_and_remove)
98{
99 int i;
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200100 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400101
102 /* add device a lot of times */
103 for (i = 0; i < COUNT; ++i) {
104 weston_test_device_add(cl->test->weston_test, "keyboard");
105 weston_test_device_add(cl->test->weston_test, "pointer");
106 weston_test_device_add(cl->test->weston_test, "touch");
107 }
108
109 client_roundtrip(cl);
110
111 assert(cl->input->pointer);
112 assert(cl->input->keyboard);
113 assert(cl->input->touch);
114
115 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
116
117 /* release all new devices */
118 for (i = 0; i < COUNT; ++i) {
119 weston_test_device_release(cl->test->weston_test, "keyboard");
120 weston_test_device_release(cl->test->weston_test, "pointer");
121 weston_test_device_release(cl->test->weston_test, "touch");
122 }
123
124 client_roundtrip(cl);
125
126 /* there is still one from each device left */
127 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
128
129 assert(cl->input->pointer);
130 assert(cl->input->keyboard);
131 assert(cl->input->touch);
132}
133
134TEST(device_release_before_destroy)
135{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200136 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400137
138 /* we can release pointer when we won't be using it anymore.
139 * Do it and see what happens if the device is destroyed
140 * right after that */
141 wl_pointer_release(cl->input->pointer->wl_pointer);
142 /* we must free and set to NULL the structures, otherwise
143 * seat capabilities will double-free them */
144 free(cl->input->pointer);
145 cl->input->pointer = NULL;
146
147 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
148 free(cl->input->keyboard);
149 cl->input->keyboard = NULL;
150
151 wl_touch_release(cl->input->touch->wl_touch);
152 free(cl->input->touch);
153 cl->input->touch = NULL;
154
155 weston_test_device_release(cl->test->weston_test, "pointer");
156 weston_test_device_release(cl->test->weston_test, "keyboard");
157 weston_test_device_release(cl->test->weston_test, "touch");
158 client_roundtrip(cl);
159
160 assert(cl->input->caps == 0);
161
162 /* restore previous state */
163 weston_test_device_add(cl->test->weston_test, "pointer");
164 weston_test_device_add(cl->test->weston_test, "keyboard");
165 weston_test_device_add(cl->test->weston_test, "touch");
166 client_roundtrip(cl);
167
168 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
169}
170
171TEST(device_release_before_destroy_multiple)
172{
173 int i;
174
175 /* if weston crashed during this test, then there is
176 * some inconsistency */
177 for (i = 0; i < 30; ++i) {
178 /* Fifty times run the previous test. This will create
179 * fifty clients, because we don't have any
180 * way how to destroy them (worth of adding!). Only one
181 * client will run at a time though and so should have no
182 * effect on the result of the test (after the client
183 * finishes its body, it just 'is' and does nothing). */
184 device_release_before_destroy();
185 }
186}
187
188/* normal work-flow test */
189TEST(device_release_after_destroy)
190{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200191 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400192
193 weston_test_device_release(cl->test->weston_test, "pointer");
194 wl_pointer_release(cl->input->pointer->wl_pointer);
195 /* we must free the memory manually, otherwise seat.capabilities
196 * will try to free it and will use invalid proxy */
197 free(cl->input->pointer);
198 cl->input->pointer = NULL;
199
200 client_roundtrip(cl);
201
202 weston_test_device_release(cl->test->weston_test, "keyboard");
203 wl_keyboard_release(cl->input->keyboard->wl_keyboard);
204 free(cl->input->keyboard);
205 cl->input->keyboard = NULL;
206
207 client_roundtrip(cl);
208
209 weston_test_device_release(cl->test->weston_test, "touch");
210 wl_touch_release(cl->input->touch->wl_touch);
211 free(cl->input->touch);
212 cl->input->touch = NULL;
213
214 client_roundtrip(cl);
215
216 assert(cl->input->caps == 0);
217
218 /* restore previous state */
219 weston_test_device_add(cl->test->weston_test, "pointer");
220 weston_test_device_add(cl->test->weston_test, "keyboard");
221 weston_test_device_add(cl->test->weston_test, "touch");
222 client_roundtrip(cl);
223
224 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
225}
226
227TEST(device_release_after_destroy_multiple)
228{
229 int i;
230
231 /* if weston crashed during this test, then there is
232 * some inconsistency */
233 for (i = 0; i < 30; ++i) {
234 device_release_after_destroy();
235 }
236}
237
238/* see https://bugzilla.gnome.org/show_bug.cgi?id=745008
239 * It is a mutter bug, but highly relevant. Weston does not
240 * suffer from this bug atm, but it is worth of testing. */
241TEST(get_device_after_destroy)
242{
Pekka Paalanen4ac06ff2015-03-26 12:56:10 +0200243 struct client *cl = create_client_and_test_surface(100, 100, 100, 100);
Marek Chalupa5fd81402015-03-30 09:21:29 -0400244 struct wl_pointer *wl_pointer;
245 struct wl_keyboard *wl_keyboard;
246 struct wl_touch *wl_touch;
247
248 /* There's a race:
249 * 1) compositor destroyes device
250 * 2) client asks for the device, because it has not got
251 * new capabilities yet
252 * 3) compositor gets request with new_id for destroyed device
253 * 4) client uses the new_id
254 * 5) client gets new capabilities, destroying the objects
255 *
256 * If compositor just bail out in step 3) and does not create
257 * resource, then client gets error in step 4) - even though
258 * it followed the protocol (it just didn't know about new
259 * capabilities).
260 *
261 * This test simulates this situation
262 */
263
264 /* connection is buffered, so after calling client_roundtrip(),
265 * this whole batch will be delivered to compositor and will
266 * exactly simulate our situation */
267 weston_test_device_release(cl->test->weston_test, "pointer");
268 wl_pointer = wl_seat_get_pointer(cl->input->wl_seat);
269 assert(wl_pointer);
270
271 /* this should be ignored */
272 wl_pointer_set_cursor(wl_pointer, 0, NULL, 0, 0);
273
274 /* this should not be ignored */
275 wl_pointer_release(wl_pointer);
276 client_roundtrip(cl);
277
278 weston_test_device_release(cl->test->weston_test, "keyboard");
279 wl_keyboard = wl_seat_get_keyboard(cl->input->wl_seat);
280 assert(wl_keyboard);
281 wl_keyboard_release(wl_keyboard);
282 client_roundtrip(cl);
283
284 weston_test_device_release(cl->test->weston_test, "touch");
285 wl_touch = wl_seat_get_touch(cl->input->wl_seat);
286 assert(wl_touch);
287 wl_touch_release(wl_touch);
288 client_roundtrip(cl);
289
290 /* get weston to the previous state */
291 weston_test_device_add(cl->test->weston_test, "pointer");
292 weston_test_device_add(cl->test->weston_test, "keyboard");
293 weston_test_device_add(cl->test->weston_test, "touch");
294 client_roundtrip(cl);
295
296 assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
297}
298
299TEST(get_device_afer_destroy_multiple)
300{
301 int i;
302
303 /* if weston crashed during this test, then there is
304 * some inconsistency */
305 for (i = 0; i < 30; ++i) {
306 get_device_after_destroy();
307 }
308}