1 /*
2 * Copyright © 2014 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <config.h>
25
26 #include <check.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <libinput.h>
30 #include <libinput-util.h>
31 #include <unistd.h>
32 #include <stdarg.h>
33
34 #include "litest.h"
35 #include "libinput-util.h"
36
open_restricted(const char * path,int flags,void * data)37 static int open_restricted(const char *path, int flags, void *data)
38 {
39 int fd = open(path, flags);
40 return fd < 0 ? -errno : fd;
41 }
close_restricted(int fd,void * data)42 static void close_restricted(int fd, void *data)
43 {
44 close(fd);
45 }
46
47 static const struct libinput_interface simple_interface = {
48 .open_restricted = open_restricted,
49 .close_restricted = close_restricted,
50 };
51
52 static struct libevdev_uinput *
create_simple_test_device(const char * name,...)53 create_simple_test_device(const char *name, ...)
54 {
55 va_list args;
56 struct libevdev_uinput *uinput;
57 struct libevdev *evdev;
58 unsigned int type, code;
59 int rc;
60 struct input_absinfo abs = {
61 .value = -1,
62 .minimum = 0,
63 .maximum = 100,
64 .fuzz = 0,
65 .flat = 0,
66 .resolution = 100,
67 };
68
69 evdev = libevdev_new();
70 litest_assert_notnull(evdev);
71 libevdev_set_name(evdev, name);
72
73 va_start(args, name);
74
75 while ((type = va_arg(args, unsigned int)) != (unsigned int)-1 &&
76 (code = va_arg(args, unsigned int)) != (unsigned int)-1) {
77 const struct input_absinfo *a = NULL;
78 if (type == EV_ABS)
79 a = &abs;
80 libevdev_enable_event_code(evdev, type, code, a);
81 }
82
83 va_end(args);
84
85 rc = libevdev_uinput_create_from_device(evdev,
86 LIBEVDEV_UINPUT_OPEN_MANAGED,
87 &uinput);
88 litest_assert_int_eq(rc, 0);
89 libevdev_free(evdev);
90
91 return uinput;
92 }
93
START_TEST(event_conversion_device_notify)94 START_TEST(event_conversion_device_notify)
95 {
96 struct libevdev_uinput *uinput;
97 struct libinput *li;
98 struct libinput_event *event;
99 int device_added = 0, device_removed = 0;
100
101 uinput = create_simple_test_device("litest test device",
102 EV_REL, REL_X,
103 EV_REL, REL_Y,
104 EV_KEY, BTN_LEFT,
105 EV_KEY, BTN_MIDDLE,
106 EV_KEY, BTN_LEFT,
107 -1, -1);
108 li = litest_create_context();
109 litest_restore_log_handler(li); /* use the default litest handler */
110 libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
111
112 libinput_dispatch(li);
113 libinput_suspend(li);
114 libinput_resume(li);
115
116 while ((event = libinput_get_event(li))) {
117 enum libinput_event_type type;
118 type = libinput_event_get_type(event);
119
120 if (type == LIBINPUT_EVENT_DEVICE_ADDED ||
121 type == LIBINPUT_EVENT_DEVICE_REMOVED) {
122 struct libinput_event_device_notify *dn;
123 struct libinput_event *base;
124 dn = libinput_event_get_device_notify_event(event);
125 base = libinput_event_device_notify_get_base_event(dn);
126 ck_assert(event == base);
127
128 if (type == LIBINPUT_EVENT_DEVICE_ADDED)
129 device_added++;
130 else if (type == LIBINPUT_EVENT_DEVICE_REMOVED)
131 device_removed++;
132
133 litest_disable_log_handler(li);
134 ck_assert(libinput_event_get_pointer_event(event) == NULL);
135 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
136 ck_assert(libinput_event_get_touch_event(event) == NULL);
137 ck_assert(libinput_event_get_gesture_event(event) == NULL);
138 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
139 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
140 ck_assert(libinput_event_get_switch_event(event) == NULL);
141 litest_restore_log_handler(li);
142 }
143
144 libinput_event_destroy(event);
145 }
146
147 litest_destroy_context(li);
148 libevdev_uinput_destroy(uinput);
149
150 ck_assert_int_gt(device_added, 0);
151 ck_assert_int_gt(device_removed, 0);
152 }
153 END_TEST
154
START_TEST(event_conversion_pointer)155 START_TEST(event_conversion_pointer)
156 {
157 struct litest_device *dev = litest_current_device();
158 struct libinput *li = dev->libinput;
159 struct libinput_event *event;
160 int motion = 0, button = 0;
161
162 /* Queue at least two relative motion events as the first one may
163 * be absorbed by the pointer acceleration filter. */
164 litest_event(dev, EV_REL, REL_X, -1);
165 litest_event(dev, EV_REL, REL_Y, -1);
166 litest_event(dev, EV_SYN, SYN_REPORT, 0);
167 litest_event(dev, EV_REL, REL_X, -1);
168 litest_event(dev, EV_REL, REL_Y, -1);
169 litest_event(dev, EV_KEY, BTN_LEFT, 1);
170 litest_event(dev, EV_SYN, SYN_REPORT, 0);
171
172 libinput_dispatch(li);
173
174 while ((event = libinput_get_event(li))) {
175 enum libinput_event_type type;
176 type = libinput_event_get_type(event);
177
178 if (type == LIBINPUT_EVENT_POINTER_MOTION ||
179 type == LIBINPUT_EVENT_POINTER_BUTTON) {
180 struct libinput_event_pointer *p;
181 struct libinput_event *base;
182 p = libinput_event_get_pointer_event(event);
183 base = libinput_event_pointer_get_base_event(p);
184 ck_assert(event == base);
185
186 if (type == LIBINPUT_EVENT_POINTER_MOTION)
187 motion++;
188 else if (type == LIBINPUT_EVENT_POINTER_BUTTON)
189 button++;
190
191 litest_disable_log_handler(li);
192 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
193 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
194 ck_assert(libinput_event_get_touch_event(event) == NULL);
195 ck_assert(libinput_event_get_gesture_event(event) == NULL);
196 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
197 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
198 ck_assert(libinput_event_get_switch_event(event) == NULL);
199 litest_restore_log_handler(li);
200 }
201 libinput_event_destroy(event);
202 }
203
204 ck_assert_int_gt(motion, 0);
205 ck_assert_int_gt(button, 0);
206 }
207 END_TEST
208
START_TEST(event_conversion_pointer_abs)209 START_TEST(event_conversion_pointer_abs)
210 {
211 struct litest_device *dev = litest_current_device();
212 struct libinput *li = dev->libinput;
213 struct libinput_event *event;
214 int motion = 0, button = 0;
215
216 litest_event(dev, EV_ABS, ABS_X, 10);
217 litest_event(dev, EV_ABS, ABS_Y, 50);
218 litest_event(dev, EV_KEY, BTN_LEFT, 1);
219 litest_event(dev, EV_SYN, SYN_REPORT, 0);
220 litest_event(dev, EV_ABS, ABS_X, 30);
221 litest_event(dev, EV_ABS, ABS_Y, 30);
222 litest_event(dev, EV_SYN, SYN_REPORT, 0);
223
224 libinput_dispatch(li);
225
226 while ((event = libinput_get_event(li))) {
227 enum libinput_event_type type;
228 type = libinput_event_get_type(event);
229
230 if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE ||
231 type == LIBINPUT_EVENT_POINTER_BUTTON) {
232 struct libinput_event_pointer *p;
233 struct libinput_event *base;
234 p = libinput_event_get_pointer_event(event);
235 base = libinput_event_pointer_get_base_event(p);
236 ck_assert(event == base);
237
238 if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE)
239 motion++;
240 else if (type == LIBINPUT_EVENT_POINTER_BUTTON)
241 button++;
242
243 litest_disable_log_handler(li);
244 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
245 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
246 ck_assert(libinput_event_get_touch_event(event) == NULL);
247 ck_assert(libinput_event_get_gesture_event(event) == NULL);
248 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
249 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
250 ck_assert(libinput_event_get_switch_event(event) == NULL);
251 litest_restore_log_handler(li);
252 }
253 libinput_event_destroy(event);
254 }
255
256 ck_assert_int_gt(motion, 0);
257 ck_assert_int_gt(button, 0);
258 }
259 END_TEST
260
START_TEST(event_conversion_key)261 START_TEST(event_conversion_key)
262 {
263 struct litest_device *dev = litest_current_device();
264 struct libinput *li = dev->libinput;
265 struct libinput_event *event;
266 int key = 0;
267
268 litest_event(dev, EV_KEY, KEY_A, 1);
269 litest_event(dev, EV_SYN, SYN_REPORT, 0);
270 litest_event(dev, EV_KEY, KEY_A, 0);
271 litest_event(dev, EV_SYN, SYN_REPORT, 0);
272
273 libinput_dispatch(li);
274
275 while ((event = libinput_get_event(li))) {
276 enum libinput_event_type type;
277 type = libinput_event_get_type(event);
278
279 if (type == LIBINPUT_EVENT_KEYBOARD_KEY) {
280 struct libinput_event_keyboard *k;
281 struct libinput_event *base;
282 k = libinput_event_get_keyboard_event(event);
283 base = libinput_event_keyboard_get_base_event(k);
284 ck_assert(event == base);
285
286 key++;
287
288 litest_disable_log_handler(li);
289 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
290 ck_assert(libinput_event_get_pointer_event(event) == NULL);
291 ck_assert(libinput_event_get_touch_event(event) == NULL);
292 ck_assert(libinput_event_get_gesture_event(event) == NULL);
293 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
294 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
295 ck_assert(libinput_event_get_switch_event(event) == NULL);
296 litest_restore_log_handler(li);
297 }
298 libinput_event_destroy(event);
299 }
300
301 ck_assert_int_gt(key, 0);
302 }
303 END_TEST
304
START_TEST(event_conversion_touch)305 START_TEST(event_conversion_touch)
306 {
307 struct litest_device *dev = litest_current_device();
308 struct libinput *li = dev->libinput;
309 struct libinput_event *event;
310 int touch = 0;
311
312 libinput_dispatch(li);
313
314 litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
315 litest_event(dev, EV_KEY, BTN_TOUCH, 1);
316 litest_event(dev, EV_ABS, ABS_X, 10);
317 litest_event(dev, EV_ABS, ABS_Y, 10);
318 litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
319 litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
320 litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 10);
321 litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 10);
322 litest_event(dev, EV_SYN, SYN_REPORT, 0);
323
324 libinput_dispatch(li);
325
326 while ((event = libinput_get_event(li))) {
327 enum libinput_event_type type;
328 type = libinput_event_get_type(event);
329
330 if (type >= LIBINPUT_EVENT_TOUCH_DOWN &&
331 type <= LIBINPUT_EVENT_TOUCH_FRAME) {
332 struct libinput_event_touch *t;
333 struct libinput_event *base;
334 t = libinput_event_get_touch_event(event);
335 base = libinput_event_touch_get_base_event(t);
336 ck_assert(event == base);
337
338 touch++;
339
340 litest_disable_log_handler(li);
341 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
342 ck_assert(libinput_event_get_pointer_event(event) == NULL);
343 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
344 ck_assert(libinput_event_get_gesture_event(event) == NULL);
345 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
346 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
347 ck_assert(libinput_event_get_switch_event(event) == NULL);
348 litest_restore_log_handler(li);
349 }
350 libinput_event_destroy(event);
351 }
352
353 ck_assert_int_gt(touch, 0);
354 }
355 END_TEST
356
START_TEST(event_conversion_gesture)357 START_TEST(event_conversion_gesture)
358 {
359 struct litest_device *dev = litest_current_device();
360 struct libinput *li = dev->libinput;
361 struct libinput_event *event;
362 int gestures = 0;
363 int i;
364
365 libinput_dispatch(li);
366
367 litest_touch_down(dev, 0, 70, 30);
368 litest_touch_down(dev, 1, 30, 70);
369 for (i = 0; i < 8; i++) {
370 litest_push_event_frame(dev);
371 litest_touch_move(dev, 0, 70 - i * 5, 30 + i * 5);
372 litest_touch_move(dev, 1, 30 + i * 5, 70 - i * 5);
373 litest_pop_event_frame(dev);
374 libinput_dispatch(li);
375 }
376
377 while ((event = libinput_get_event(li))) {
378 enum libinput_event_type type;
379 type = libinput_event_get_type(event);
380
381 if (type >= LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN &&
382 type <= LIBINPUT_EVENT_GESTURE_PINCH_END) {
383 struct libinput_event_gesture *g;
384 struct libinput_event *base;
385 g = libinput_event_get_gesture_event(event);
386 base = libinput_event_gesture_get_base_event(g);
387 ck_assert(event == base);
388
389 gestures++;
390
391 litest_disable_log_handler(li);
392 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
393 ck_assert(libinput_event_get_pointer_event(event) == NULL);
394 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
395 ck_assert(libinput_event_get_touch_event(event) == NULL);
396 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
397 ck_assert(libinput_event_get_switch_event(event) == NULL);
398 litest_restore_log_handler(li);
399 }
400 libinput_event_destroy(event);
401 }
402
403 ck_assert_int_gt(gestures, 0);
404 }
405 END_TEST
406
START_TEST(event_conversion_tablet)407 START_TEST(event_conversion_tablet)
408 {
409 struct litest_device *dev = litest_current_device();
410 struct libinput *li = dev->libinput;
411 struct libinput_event *event;
412 int events = 0;
413 struct axis_replacement axes[] = {
414 { ABS_DISTANCE, 10 },
415 { -1, -1 }
416 };
417
418 litest_tablet_proximity_in(dev, 50, 50, axes);
419 litest_tablet_motion(dev, 60, 50, axes);
420 litest_button_click(dev, BTN_STYLUS, true);
421 litest_button_click(dev, BTN_STYLUS, false);
422
423 libinput_dispatch(li);
424
425 while ((event = libinput_get_event(li))) {
426 enum libinput_event_type type;
427 type = libinput_event_get_type(event);
428
429 if (type >= LIBINPUT_EVENT_TABLET_TOOL_AXIS &&
430 type <= LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
431 struct libinput_event_tablet_tool *t;
432 struct libinput_event *base;
433 t = libinput_event_get_tablet_tool_event(event);
434 base = libinput_event_tablet_tool_get_base_event(t);
435 ck_assert(event == base);
436
437 events++;
438
439 litest_disable_log_handler(li);
440 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
441 ck_assert(libinput_event_get_pointer_event(event) == NULL);
442 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
443 ck_assert(libinput_event_get_touch_event(event) == NULL);
444 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
445 ck_assert(libinput_event_get_switch_event(event) == NULL);
446 litest_restore_log_handler(li);
447 }
448 libinput_event_destroy(event);
449 }
450
451 ck_assert_int_gt(events, 0);
452 }
453 END_TEST
454
START_TEST(event_conversion_tablet_pad)455 START_TEST(event_conversion_tablet_pad)
456 {
457 struct litest_device *dev = litest_current_device();
458 struct libinput *li = dev->libinput;
459 struct libinput_event *event;
460 int events = 0;
461
462 litest_button_click(dev, BTN_0, true);
463 litest_pad_ring_start(dev, 10);
464 litest_pad_ring_end(dev);
465
466 libinput_dispatch(li);
467
468 while ((event = libinput_get_event(li))) {
469 enum libinput_event_type type;
470 type = libinput_event_get_type(event);
471
472 if (type >= LIBINPUT_EVENT_TABLET_PAD_BUTTON &&
473 type <= LIBINPUT_EVENT_TABLET_PAD_STRIP) {
474 struct libinput_event_tablet_pad *p;
475 struct libinput_event *base;
476
477 p = libinput_event_get_tablet_pad_event(event);
478 base = libinput_event_tablet_pad_get_base_event(p);
479 ck_assert(event == base);
480
481 events++;
482
483 litest_disable_log_handler(li);
484 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
485 ck_assert(libinput_event_get_pointer_event(event) == NULL);
486 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
487 ck_assert(libinput_event_get_touch_event(event) == NULL);
488 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
489 ck_assert(libinput_event_get_switch_event(event) == NULL);
490 litest_restore_log_handler(li);
491 }
492 libinput_event_destroy(event);
493 }
494
495 ck_assert_int_gt(events, 0);
496 }
497 END_TEST
498
START_TEST(event_conversion_switch)499 START_TEST(event_conversion_switch)
500 {
501 struct litest_device *dev = litest_current_device();
502 struct libinput *li = dev->libinput;
503 struct libinput_event *event;
504 int sw = 0;
505
506 litest_switch_action(dev,
507 LIBINPUT_SWITCH_LID,
508 LIBINPUT_SWITCH_STATE_ON);
509 litest_switch_action(dev,
510 LIBINPUT_SWITCH_LID,
511 LIBINPUT_SWITCH_STATE_OFF);
512 libinput_dispatch(li);
513
514 while ((event = libinput_get_event(li))) {
515 enum libinput_event_type type;
516 type = libinput_event_get_type(event);
517
518 if (type == LIBINPUT_EVENT_SWITCH_TOGGLE) {
519 struct libinput_event_switch *s;
520 struct libinput_event *base;
521 s = libinput_event_get_switch_event(event);
522 base = libinput_event_switch_get_base_event(s);
523 ck_assert(event == base);
524
525 sw++;
526
527 litest_disable_log_handler(li);
528 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
529 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
530 ck_assert(libinput_event_get_pointer_event(event) == NULL);
531 ck_assert(libinput_event_get_touch_event(event) == NULL);
532 ck_assert(libinput_event_get_gesture_event(event) == NULL);
533 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
534 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
535 litest_restore_log_handler(li);
536 }
537 libinput_event_destroy(event);
538 }
539
540 ck_assert_int_gt(sw, 0);
541 }
542 END_TEST
543
START_TEST(context_ref_counting)544 START_TEST(context_ref_counting)
545 {
546 struct libinput *li;
547
548 /* These tests rely on valgrind to detect memory leak and use after
549 * free errors. */
550
551 li = libinput_path_create_context(&simple_interface, NULL);
552 ck_assert_notnull(li);
553 ck_assert_ptr_eq(libinput_unref(li), NULL);
554
555 li = libinput_path_create_context(&simple_interface, NULL);
556 ck_assert_notnull(li);
557 ck_assert_ptr_eq(libinput_ref(li), li);
558 ck_assert_ptr_eq(libinput_unref(li), li);
559 ck_assert_ptr_eq(libinput_unref(li), NULL);
560 }
561 END_TEST
562
START_TEST(config_status_string)563 START_TEST(config_status_string)
564 {
565 const char *strs[3];
566 const char *invalid;
567 size_t i, j;
568
569 strs[0] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS);
570 strs[1] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
571 strs[2] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID);
572
573 for (i = 0; i < ARRAY_LENGTH(strs) - 1; i++)
574 for (j = i + 1; j < ARRAY_LENGTH(strs); j++)
575 ck_assert_str_ne(strs[i], strs[j]);
576
577 invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID + 1);
578 ck_assert(invalid == NULL);
579 invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS - 1);
580 ck_assert(invalid == NULL);
581 }
582 END_TEST
583
open_restricted_leak(const char * path,int flags,void * data)584 static int open_restricted_leak(const char *path, int flags, void *data)
585 {
586 return *(int*)data;
587 }
588
close_restricted_leak(int fd,void * data)589 static void close_restricted_leak(int fd, void *data)
590 {
591 /* noop */
592 }
593
594 const struct libinput_interface leak_interface = {
595 .open_restricted = open_restricted_leak,
596 .close_restricted = close_restricted_leak,
597 };
598
START_TEST(fd_no_event_leak)599 START_TEST(fd_no_event_leak)
600 {
601 struct libevdev_uinput *uinput;
602 struct libinput *li;
603 struct libinput_device *device;
604 int fd = -1;
605 const char *path;
606 struct libinput_event *event;
607
608 uinput = create_simple_test_device("litest test device",
609 EV_REL, REL_X,
610 EV_REL, REL_Y,
611 EV_KEY, BTN_LEFT,
612 EV_KEY, BTN_MIDDLE,
613 EV_KEY, BTN_LEFT,
614 -1, -1);
615 path = libevdev_uinput_get_devnode(uinput);
616
617 fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
618 ck_assert_int_gt(fd, -1);
619
620 li = libinput_path_create_context(&leak_interface, &fd);
621 litest_restore_log_handler(li); /* use the default litest handler */
622
623 /* Add the device, trigger an event, then remove it again.
624 * Without it, we get a SYN_DROPPED immediately and no events.
625 */
626 device = libinput_path_add_device(li, path);
627 libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1);
628 libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
629 libinput_path_remove_device(device);
630 libinput_dispatch(li);
631 litest_drain_events(li);
632
633 /* Device is removed, but fd is still open. Queue an event, add a
634 * new device with the same fd, the queued event must be discarded
635 * by libinput */
636 libevdev_uinput_write_event(uinput, EV_REL, REL_Y, 1);
637 libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
638 libinput_dispatch(li);
639
640 libinput_path_add_device(li, path);
641 libinput_dispatch(li);
642 event = libinput_get_event(li);
643 ck_assert_int_eq(libinput_event_get_type(event),
644 LIBINPUT_EVENT_DEVICE_ADDED);
645 libinput_event_destroy(event);
646
647 litest_assert_empty_queue(li);
648
649 close(fd);
650 libinput_unref(li);
651 libevdev_uinput_destroy(uinput);
652 }
653 END_TEST
654
timer_offset_warning(struct libinput * libinput,enum libinput_log_priority priority,const char * format,va_list args)655 static void timer_offset_warning(struct libinput *libinput,
656 enum libinput_log_priority priority,
657 const char *format,
658 va_list args)
659 {
660 int *warning_triggered = (int*)libinput_get_user_data(libinput);
661
662 if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
663 strstr(format, "scheduled expiry is in the past"))
664 (*warning_triggered)++;
665 }
666
START_TEST(timer_offset_bug_warning)667 START_TEST(timer_offset_bug_warning)
668 {
669 struct litest_device *dev = litest_current_device();
670 struct libinput *li = dev->libinput;
671 int warning_triggered = 0;
672 void *old_user_data;
673
674 litest_enable_tap(dev->libinput_device);
675 litest_drain_events(li);
676
677 litest_touch_down(dev, 0, 50, 50);
678 litest_touch_up(dev, 0);
679
680 litest_timeout_tap();
681
682 old_user_data = libinput_get_user_data(li);
683 libinput_set_user_data(li, &warning_triggered);
684 libinput_log_set_handler(li, timer_offset_warning);
685 libinput_dispatch(li);
686
687 /* triggered for touch down and touch up */
688 ck_assert_int_eq(warning_triggered, 2);
689 litest_restore_log_handler(li);
690
691 libinput_set_user_data(li, old_user_data);
692 }
693 END_TEST
694
timer_delay_warning(struct libinput * libinput,enum libinput_log_priority priority,const char * format,va_list args)695 static void timer_delay_warning(struct libinput *libinput,
696 enum libinput_log_priority priority,
697 const char *format,
698 va_list args)
699 {
700 int *warning_triggered = (int*)libinput_get_user_data(libinput);
701
702 if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
703 strstr(format, "event processing lagging behind by"))
704 (*warning_triggered)++;
705 }
706
707
START_TEST(timer_delay_bug_warning)708 START_TEST(timer_delay_bug_warning)
709 {
710 struct litest_device *dev = litest_current_device();
711 struct libinput *li = dev->libinput;
712 int warning_triggered = 0;
713 void *old_user_data;
714
715 old_user_data = libinput_get_user_data(li);
716 litest_drain_events(li);
717
718 for (int i = 0; i < 10; i++) {
719 litest_button_click(dev, BTN_LEFT, true);
720 libinput_dispatch(li);
721 litest_button_click(dev, BTN_LEFT, false);
722 msleep(11);
723
724 libinput_set_user_data(li, &warning_triggered);
725 libinput_log_set_handler(li, timer_delay_warning);
726 libinput_dispatch(li);
727 }
728
729
730 ck_assert_int_ge(warning_triggered, 1);
731 litest_restore_log_handler(li);
732 libinput_set_user_data(li, old_user_data);
733 }
734 END_TEST
735
START_TEST(timer_flush)736 START_TEST(timer_flush)
737 {
738 struct libinput *li;
739 struct litest_device *keyboard, *touchpad;
740
741 li = litest_create_context();
742
743 touchpad = litest_add_device(li, LITEST_SYNAPTICS_TOUCHPAD);
744 litest_enable_tap(touchpad->libinput_device);
745 libinput_dispatch(li);
746 keyboard = litest_add_device(li, LITEST_KEYBOARD);
747 libinput_dispatch(li);
748 litest_drain_events(li);
749
750 /* make sure tapping works */
751 litest_touch_down(touchpad, 0, 50, 50);
752 litest_touch_up(touchpad, 0);
753 libinput_dispatch(li);
754 litest_timeout_tap();
755 libinput_dispatch(li);
756
757 litest_assert_button_event(li, BTN_LEFT,
758 LIBINPUT_BUTTON_STATE_PRESSED);
759 litest_assert_button_event(li, BTN_LEFT,
760 LIBINPUT_BUTTON_STATE_RELEASED);
761 litest_assert_empty_queue(li);
762
763 /* make sure dwt-tap is ignored */
764 litest_keyboard_key(keyboard, KEY_A, true);
765 litest_keyboard_key(keyboard, KEY_A, false);
766 libinput_dispatch(li);
767 litest_touch_down(touchpad, 0, 50, 50);
768 litest_touch_up(touchpad, 0);
769 libinput_dispatch(li);
770 litest_timeout_tap();
771 libinput_dispatch(li);
772 litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
773
774 /* Ingore 'timer offset negative' warnings */
775 litest_disable_log_handler(li);
776
777 /* now mess with the timing
778 - send a key event
779 - expire dwt
780 - send a tap
781 and then call libinput_dispatch(). libinput should notice that
782 the tap event came in after the timeout and thus acknowledge the
783 tap.
784 */
785 litest_keyboard_key(keyboard, KEY_A, true);
786 litest_keyboard_key(keyboard, KEY_A, false);
787 litest_timeout_dwt_long();
788 litest_touch_down(touchpad, 0, 50, 50);
789 litest_touch_up(touchpad, 0);
790 libinput_dispatch(li);
791 litest_timeout_tap();
792 libinput_dispatch(li);
793 litest_restore_log_handler(li);
794
795 litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
796 litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
797 litest_assert_button_event(li, BTN_LEFT,
798 LIBINPUT_BUTTON_STATE_PRESSED);
799 litest_assert_button_event(li, BTN_LEFT,
800 LIBINPUT_BUTTON_STATE_RELEASED);
801
802 litest_delete_device(keyboard);
803 litest_delete_device(touchpad);
804
805 litest_destroy_context(li);
806 }
807 END_TEST
808
START_TEST(udev_absinfo_override)809 START_TEST(udev_absinfo_override)
810 {
811 struct litest_device *dev = litest_current_device();
812 struct libevdev *evdev = dev->evdev;
813 const struct input_absinfo *abs;
814 struct udev_device *ud;
815 struct udev_list_entry *entry;
816 bool found_x = false, found_y = false,
817 found_mt_x = false, found_mt_y = false;
818
819 ud = libinput_device_get_udev_device(dev->libinput_device);
820 ck_assert_notnull(ud);
821
822 /* Custom checks for this special litest device only */
823
824 entry = udev_device_get_properties_list_entry(ud);
825 while (entry) {
826 const char *key, *value;
827
828 key = udev_list_entry_get_name(entry);
829 value = udev_list_entry_get_value(entry);
830
831 if (streq(key, "EVDEV_ABS_00")) {
832 found_x = true;
833 ck_assert(streq(value, "1:1000:100:10"));
834 }
835 if (streq(key, "EVDEV_ABS_01")) {
836 found_y = true;
837 ck_assert(streq(value, "2:2000:200:20"));
838 }
839 if (streq(key, "EVDEV_ABS_35")) {
840 found_mt_x = true;
841 ck_assert(streq(value, "3:3000:300:30"));
842 }
843 if (streq(key, "EVDEV_ABS_36")) {
844 found_mt_y = true;
845 ck_assert(streq(value, "4:4000:400:40"));
846 }
847
848 entry = udev_list_entry_get_next(entry);
849 }
850 udev_device_unref(ud);
851
852 ck_assert(found_x);
853 ck_assert(found_y);
854 ck_assert(found_mt_x);
855 ck_assert(found_mt_y);
856
857 abs = libevdev_get_abs_info(evdev, ABS_X);
858 ck_assert_int_eq(abs->minimum, 1);
859 ck_assert_int_eq(abs->maximum, 1000);
860 ck_assert_int_eq(abs->resolution, 100);
861 /* if everything goes well, we override the fuzz to 0 */
862 ck_assert_int_eq(abs->fuzz, 0);
863
864 abs = libevdev_get_abs_info(evdev, ABS_Y);
865 ck_assert_int_eq(abs->minimum, 2);
866 ck_assert_int_eq(abs->maximum, 2000);
867 ck_assert_int_eq(abs->resolution, 200);
868 /* if everything goes well, we override the fuzz to 0 */
869 ck_assert_int_eq(abs->fuzz, 0);
870
871 abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
872 ck_assert_int_eq(abs->minimum, 3);
873 ck_assert_int_eq(abs->maximum, 3000);
874 ck_assert_int_eq(abs->resolution, 300);
875 /* if everything goes well, we override the fuzz to 0 */
876 ck_assert_int_eq(abs->fuzz, 0);
877
878 abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
879 ck_assert_int_eq(abs->minimum, 4);
880 ck_assert_int_eq(abs->maximum, 4000);
881 ck_assert_int_eq(abs->resolution, 400);
882 /* if everything goes well, we override the fuzz to 0 */
883 ck_assert_int_eq(abs->fuzz, 0);
884 }
885 END_TEST
886
TEST_COLLECTION(misc)887 TEST_COLLECTION(misc)
888 {
889 litest_add_no_device("events:conversion", event_conversion_device_notify);
890 litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
891 litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
892 litest_add_for_device("events:conversion", event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER);
893 litest_add_for_device("events:conversion", event_conversion_key, LITEST_KEYBOARD);
894 litest_add_for_device("events:conversion", event_conversion_touch, LITEST_WACOM_TOUCH);
895 litest_add_for_device("events:conversion", event_conversion_gesture, LITEST_BCM5974);
896 litest_add_for_device("events:conversion", event_conversion_tablet, LITEST_WACOM_CINTIQ);
897 litest_add_for_device("events:conversion", event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD);
898 litest_add_for_device("events:conversion", event_conversion_switch, LITEST_LID_SWITCH);
899
900 litest_add_deviceless("context:refcount", context_ref_counting);
901 litest_add_deviceless("config:status string", config_status_string);
902
903 litest_add_for_device("timer:offset-warning", timer_offset_bug_warning, LITEST_SYNAPTICS_TOUCHPAD);
904 litest_add_for_device("timer:delay-warning", timer_delay_bug_warning, LITEST_MOUSE);
905 litest_add_no_device("timer:flush", timer_flush);
906
907 litest_add_no_device("misc:fd", fd_no_event_leak);
908
909 litest_add_for_device("misc:system", udev_absinfo_override, LITEST_ABSINFO_OVERRIDE);
910 }
911