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 libinput_dispatch(li);
370 litest_timeout_gesture_hold();
371
372 for (i = 0; i < 8; i++) {
373 litest_push_event_frame(dev);
374 litest_touch_move(dev, 0, 70 - i * 5, 30 + i * 5);
375 litest_touch_move(dev, 1, 30 + i * 5, 70 - i * 5);
376 litest_pop_event_frame(dev);
377 libinput_dispatch(li);
378 }
379
380 while ((event = libinput_get_event(li))) {
381 enum libinput_event_type type;
382 type = libinput_event_get_type(event);
383
384 if (type >= LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN &&
385 type <= LIBINPUT_EVENT_GESTURE_HOLD_END) {
386 struct libinput_event_gesture *g;
387 struct libinput_event *base;
388 g = libinput_event_get_gesture_event(event);
389 base = libinput_event_gesture_get_base_event(g);
390 ck_assert(event == base);
391
392 gestures++;
393
394 litest_disable_log_handler(li);
395 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
396 ck_assert(libinput_event_get_pointer_event(event) == NULL);
397 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
398 ck_assert(libinput_event_get_touch_event(event) == NULL);
399 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
400 ck_assert(libinput_event_get_switch_event(event) == NULL);
401 litest_restore_log_handler(li);
402 }
403 libinput_event_destroy(event);
404 }
405
406 ck_assert_int_gt(gestures, 0);
407 }
408 END_TEST
409
START_TEST(event_conversion_tablet)410 START_TEST(event_conversion_tablet)
411 {
412 struct litest_device *dev = litest_current_device();
413 struct libinput *li = dev->libinput;
414 struct libinput_event *event;
415 int events = 0;
416 struct axis_replacement axes[] = {
417 { ABS_DISTANCE, 10 },
418 { -1, -1 }
419 };
420
421 litest_tablet_proximity_in(dev, 50, 50, axes);
422 litest_tablet_motion(dev, 60, 50, axes);
423 litest_button_click(dev, BTN_STYLUS, true);
424 litest_button_click(dev, BTN_STYLUS, false);
425
426 libinput_dispatch(li);
427
428 while ((event = libinput_get_event(li))) {
429 enum libinput_event_type type;
430 type = libinput_event_get_type(event);
431
432 if (type >= LIBINPUT_EVENT_TABLET_TOOL_AXIS &&
433 type <= LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
434 struct libinput_event_tablet_tool *t;
435 struct libinput_event *base;
436 t = libinput_event_get_tablet_tool_event(event);
437 base = libinput_event_tablet_tool_get_base_event(t);
438 ck_assert(event == base);
439
440 events++;
441
442 litest_disable_log_handler(li);
443 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
444 ck_assert(libinput_event_get_pointer_event(event) == NULL);
445 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
446 ck_assert(libinput_event_get_touch_event(event) == NULL);
447 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
448 ck_assert(libinput_event_get_switch_event(event) == NULL);
449 litest_restore_log_handler(li);
450 }
451 libinput_event_destroy(event);
452 }
453
454 ck_assert_int_gt(events, 0);
455 }
456 END_TEST
457
START_TEST(event_conversion_tablet_pad)458 START_TEST(event_conversion_tablet_pad)
459 {
460 struct litest_device *dev = litest_current_device();
461 struct libinput *li = dev->libinput;
462 struct libinput_event *event;
463 int events = 0;
464
465 litest_button_click(dev, BTN_0, true);
466 litest_pad_ring_start(dev, 10);
467 litest_pad_ring_end(dev);
468
469 libinput_dispatch(li);
470
471 while ((event = libinput_get_event(li))) {
472 enum libinput_event_type type;
473 type = libinput_event_get_type(event);
474
475 if (type >= LIBINPUT_EVENT_TABLET_PAD_BUTTON &&
476 type <= LIBINPUT_EVENT_TABLET_PAD_STRIP) {
477 struct libinput_event_tablet_pad *p;
478 struct libinput_event *base;
479
480 p = libinput_event_get_tablet_pad_event(event);
481 base = libinput_event_tablet_pad_get_base_event(p);
482 ck_assert(event == base);
483
484 events++;
485
486 litest_disable_log_handler(li);
487 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
488 ck_assert(libinput_event_get_pointer_event(event) == NULL);
489 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
490 ck_assert(libinput_event_get_touch_event(event) == NULL);
491 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
492 ck_assert(libinput_event_get_switch_event(event) == NULL);
493 litest_restore_log_handler(li);
494 }
495 libinput_event_destroy(event);
496 }
497
498 ck_assert_int_gt(events, 0);
499 }
500 END_TEST
501
START_TEST(event_conversion_switch)502 START_TEST(event_conversion_switch)
503 {
504 struct litest_device *dev = litest_current_device();
505 struct libinput *li = dev->libinput;
506 struct libinput_event *event;
507 int sw = 0;
508
509 litest_switch_action(dev,
510 LIBINPUT_SWITCH_LID,
511 LIBINPUT_SWITCH_STATE_ON);
512 litest_switch_action(dev,
513 LIBINPUT_SWITCH_LID,
514 LIBINPUT_SWITCH_STATE_OFF);
515 libinput_dispatch(li);
516
517 while ((event = libinput_get_event(li))) {
518 enum libinput_event_type type;
519 type = libinput_event_get_type(event);
520
521 if (type == LIBINPUT_EVENT_SWITCH_TOGGLE) {
522 struct libinput_event_switch *s;
523 struct libinput_event *base;
524 s = libinput_event_get_switch_event(event);
525 base = libinput_event_switch_get_base_event(s);
526 ck_assert(event == base);
527
528 sw++;
529
530 litest_disable_log_handler(li);
531 ck_assert(libinput_event_get_device_notify_event(event) == NULL);
532 ck_assert(libinput_event_get_keyboard_event(event) == NULL);
533 ck_assert(libinput_event_get_pointer_event(event) == NULL);
534 ck_assert(libinput_event_get_touch_event(event) == NULL);
535 ck_assert(libinput_event_get_gesture_event(event) == NULL);
536 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL);
537 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL);
538 litest_restore_log_handler(li);
539 }
540 libinput_event_destroy(event);
541 }
542
543 ck_assert_int_gt(sw, 0);
544 }
545 END_TEST
546
START_TEST(context_ref_counting)547 START_TEST(context_ref_counting)
548 {
549 struct libinput *li;
550
551 /* These tests rely on valgrind to detect memory leak and use after
552 * free errors. */
553
554 li = libinput_path_create_context(&simple_interface, NULL);
555 ck_assert_notnull(li);
556 ck_assert_ptr_eq(libinput_unref(li), NULL);
557
558 li = libinput_path_create_context(&simple_interface, NULL);
559 ck_assert_notnull(li);
560 ck_assert_ptr_eq(libinput_ref(li), li);
561 ck_assert_ptr_eq(libinput_unref(li), li);
562 ck_assert_ptr_eq(libinput_unref(li), NULL);
563 }
564 END_TEST
565
START_TEST(config_status_string)566 START_TEST(config_status_string)
567 {
568 const char *strs[3];
569 const char *invalid;
570 size_t i, j;
571
572 strs[0] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS);
573 strs[1] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
574 strs[2] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID);
575
576 for (i = 0; i < ARRAY_LENGTH(strs) - 1; i++)
577 for (j = i + 1; j < ARRAY_LENGTH(strs); j++)
578 ck_assert_str_ne(strs[i], strs[j]);
579
580 invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID + 1);
581 ck_assert(invalid == NULL);
582 invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS - 1);
583 ck_assert(invalid == NULL);
584 }
585 END_TEST
586
open_restricted_leak(const char * path,int flags,void * data)587 static int open_restricted_leak(const char *path, int flags, void *data)
588 {
589 return *(int*)data;
590 }
591
close_restricted_leak(int fd,void * data)592 static void close_restricted_leak(int fd, void *data)
593 {
594 /* noop */
595 }
596
597 const struct libinput_interface leak_interface = {
598 .open_restricted = open_restricted_leak,
599 .close_restricted = close_restricted_leak,
600 };
601
START_TEST(fd_no_event_leak)602 START_TEST(fd_no_event_leak)
603 {
604 struct libevdev_uinput *uinput;
605 struct libinput *li;
606 struct libinput_device *device;
607 int fd = -1;
608 const char *path;
609 struct libinput_event *event;
610
611 uinput = create_simple_test_device("litest test device",
612 EV_REL, REL_X,
613 EV_REL, REL_Y,
614 EV_KEY, BTN_LEFT,
615 EV_KEY, BTN_MIDDLE,
616 EV_KEY, BTN_LEFT,
617 -1, -1);
618 path = libevdev_uinput_get_devnode(uinput);
619
620 fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
621 ck_assert_int_gt(fd, -1);
622
623 li = libinput_path_create_context(&leak_interface, &fd);
624 litest_restore_log_handler(li); /* use the default litest handler */
625
626 /* Add the device, trigger an event, then remove it again.
627 * Without it, we get a SYN_DROPPED immediately and no events.
628 */
629 device = libinput_path_add_device(li, path);
630 libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1);
631 libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
632 libinput_path_remove_device(device);
633 libinput_dispatch(li);
634 litest_drain_events(li);
635
636 /* Device is removed, but fd is still open. Queue an event, add a
637 * new device with the same fd, the queued event must be discarded
638 * by libinput */
639 libevdev_uinput_write_event(uinput, EV_REL, REL_Y, 1);
640 libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
641 libinput_dispatch(li);
642
643 libinput_path_add_device(li, path);
644 libinput_dispatch(li);
645 event = libinput_get_event(li);
646 ck_assert_int_eq(libinput_event_get_type(event),
647 LIBINPUT_EVENT_DEVICE_ADDED);
648 libinput_event_destroy(event);
649
650 litest_assert_empty_queue(li);
651
652 close(fd);
653 libinput_unref(li);
654 libevdev_uinput_destroy(uinput);
655 }
656 END_TEST
657
timer_offset_warning(struct libinput * libinput,enum libinput_log_priority priority,const char * format,va_list args)658 static void timer_offset_warning(struct libinput *libinput,
659 enum libinput_log_priority priority,
660 const char *format,
661 va_list args)
662 {
663 struct litest_user_data *user_data = libinput_get_user_data(libinput);
664 int *warning_triggered = user_data->private;
665
666 if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
667 strstr(format, "scheduled expiry is in the past"))
668 (*warning_triggered)++;
669 }
670
START_TEST(timer_offset_bug_warning)671 START_TEST(timer_offset_bug_warning)
672 {
673 struct litest_device *dev = litest_current_device();
674 struct libinput *li = dev->libinput;
675 int warning_triggered = 0;
676 struct litest_user_data *user_data = libinput_get_user_data(li);
677
678 litest_enable_tap(dev->libinput_device);
679 litest_drain_events(li);
680
681 litest_touch_down(dev, 0, 50, 50);
682 litest_touch_up(dev, 0);
683
684 litest_timeout_tap();
685
686 user_data->private = &warning_triggered;
687 libinput_log_set_handler(li, timer_offset_warning);
688 libinput_dispatch(li);
689
690 /* triggered for touch down and touch up */
691 ck_assert_int_eq(warning_triggered, 2);
692 litest_restore_log_handler(li);
693 }
694 END_TEST
695
timer_delay_warning(struct libinput * libinput,enum libinput_log_priority priority,const char * format,va_list args)696 static void timer_delay_warning(struct libinput *libinput,
697 enum libinput_log_priority priority,
698 const char *format,
699 va_list args)
700 {
701 struct litest_user_data *user_data = libinput_get_user_data(libinput);
702 int *warning_triggered = user_data->private;
703
704 if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
705 strstr(format, "event processing lagging behind by"))
706 (*warning_triggered)++;
707 }
708
START_TEST(timer_delay_bug_warning)709 START_TEST(timer_delay_bug_warning)
710 {
711 struct litest_device *dev = litest_current_device();
712 struct libinput *li = dev->libinput;
713 int warning_triggered = 0;
714 struct litest_user_data *user_data = libinput_get_user_data(li);
715
716 litest_drain_events(li);
717
718 user_data->private = &warning_triggered;
719 libinput_log_set_handler(li, timer_delay_warning);
720
721 for (int i = 0; i < 20; i++) {
722 litest_event(dev, EV_REL, REL_X, -1);
723 litest_event(dev, EV_SYN, SYN_REPORT, 0);
724 msleep(11);
725 libinput_dispatch(li);
726 }
727
728 ck_assert_int_ge(warning_triggered, 1);
729 litest_restore_log_handler(li);
730 }
731 END_TEST
732
START_TEST(timer_flush)733 START_TEST(timer_flush)
734 {
735 struct libinput *li;
736 struct litest_device *keyboard, *touchpad;
737
738 li = litest_create_context();
739
740 touchpad = litest_add_device(li, LITEST_SYNAPTICS_TOUCHPAD);
741 litest_enable_tap(touchpad->libinput_device);
742 libinput_dispatch(li);
743 keyboard = litest_add_device(li, LITEST_KEYBOARD);
744 libinput_dispatch(li);
745 litest_drain_events(li);
746
747 /* make sure tapping works */
748 litest_touch_down(touchpad, 0, 50, 50);
749 litest_touch_up(touchpad, 0);
750 libinput_dispatch(li);
751 litest_timeout_tap();
752 libinput_dispatch(li);
753
754 litest_assert_button_event(li, BTN_LEFT,
755 LIBINPUT_BUTTON_STATE_PRESSED);
756 litest_assert_button_event(li, BTN_LEFT,
757 LIBINPUT_BUTTON_STATE_RELEASED);
758 litest_assert_empty_queue(li);
759
760 /* make sure dwt-tap is ignored */
761 litest_keyboard_key(keyboard, KEY_A, true);
762 litest_keyboard_key(keyboard, KEY_A, false);
763 libinput_dispatch(li);
764 litest_touch_down(touchpad, 0, 50, 50);
765 litest_touch_up(touchpad, 0);
766 libinput_dispatch(li);
767 litest_timeout_tap();
768 libinput_dispatch(li);
769 litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
770
771 /* Ignore 'timer offset negative' warnings */
772 litest_disable_log_handler(li);
773
774 /* now mess with the timing
775 - send a key event
776 - expire dwt
777 - send a tap
778 and then call libinput_dispatch(). libinput should notice that
779 the tap event came in after the timeout and thus acknowledge the
780 tap.
781 */
782 litest_keyboard_key(keyboard, KEY_A, true);
783 litest_keyboard_key(keyboard, KEY_A, false);
784 litest_timeout_dwt_long();
785 litest_touch_down(touchpad, 0, 50, 50);
786 litest_touch_up(touchpad, 0);
787 libinput_dispatch(li);
788 litest_timeout_tap();
789 libinput_dispatch(li);
790 litest_restore_log_handler(li);
791
792 litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
793 litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
794 litest_assert_button_event(li, BTN_LEFT,
795 LIBINPUT_BUTTON_STATE_PRESSED);
796 litest_assert_button_event(li, BTN_LEFT,
797 LIBINPUT_BUTTON_STATE_RELEASED);
798
799 litest_delete_device(keyboard);
800 litest_delete_device(touchpad);
801
802 litest_destroy_context(li);
803 }
804 END_TEST
805
START_TEST(udev_absinfo_override)806 START_TEST(udev_absinfo_override)
807 {
808 struct litest_device *dev = litest_current_device();
809 struct libevdev *evdev = dev->evdev;
810 const struct input_absinfo *abs;
811 struct udev_device *ud;
812 struct udev_list_entry *entry;
813 bool found_x = false, found_y = false,
814 found_mt_x = false, found_mt_y = false;
815
816 ud = libinput_device_get_udev_device(dev->libinput_device);
817 ck_assert_notnull(ud);
818
819 /* Custom checks for this special litest device only */
820
821 entry = udev_device_get_properties_list_entry(ud);
822 while (entry) {
823 const char *key, *value;
824
825 key = udev_list_entry_get_name(entry);
826 value = udev_list_entry_get_value(entry);
827
828 if (streq(key, "EVDEV_ABS_00")) {
829 found_x = true;
830 ck_assert(streq(value, "1:1000:100:10"));
831 }
832 if (streq(key, "EVDEV_ABS_01")) {
833 found_y = true;
834 ck_assert(streq(value, "2:2000:200:20"));
835 }
836 if (streq(key, "EVDEV_ABS_35")) {
837 found_mt_x = true;
838 ck_assert(streq(value, "3:3000:300:30"));
839 }
840 if (streq(key, "EVDEV_ABS_36")) {
841 found_mt_y = true;
842 ck_assert(streq(value, "4:4000:400:40"));
843 }
844
845 entry = udev_list_entry_get_next(entry);
846 }
847 udev_device_unref(ud);
848
849 ck_assert(found_x);
850 ck_assert(found_y);
851 ck_assert(found_mt_x);
852 ck_assert(found_mt_y);
853
854 abs = libevdev_get_abs_info(evdev, ABS_X);
855 ck_assert_int_eq(abs->minimum, 1);
856 ck_assert_int_eq(abs->maximum, 1000);
857 ck_assert_int_eq(abs->resolution, 100);
858 /* if everything goes well, we override the fuzz to 0 */
859 ck_assert_int_eq(abs->fuzz, 0);
860
861 abs = libevdev_get_abs_info(evdev, ABS_Y);
862 ck_assert_int_eq(abs->minimum, 2);
863 ck_assert_int_eq(abs->maximum, 2000);
864 ck_assert_int_eq(abs->resolution, 200);
865 /* if everything goes well, we override the fuzz to 0 */
866 ck_assert_int_eq(abs->fuzz, 0);
867
868 abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
869 ck_assert_int_eq(abs->minimum, 3);
870 ck_assert_int_eq(abs->maximum, 3000);
871 ck_assert_int_eq(abs->resolution, 300);
872 /* if everything goes well, we override the fuzz to 0 */
873 ck_assert_int_eq(abs->fuzz, 0);
874
875 abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
876 ck_assert_int_eq(abs->minimum, 4);
877 ck_assert_int_eq(abs->maximum, 4000);
878 ck_assert_int_eq(abs->resolution, 400);
879 /* if everything goes well, we override the fuzz to 0 */
880 ck_assert_int_eq(abs->fuzz, 0);
881 }
882 END_TEST
883
TEST_COLLECTION(misc)884 TEST_COLLECTION(misc)
885 {
886 litest_add_no_device(event_conversion_device_notify);
887 litest_add_for_device(event_conversion_pointer, LITEST_MOUSE);
888 litest_add_for_device(event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER);
889 litest_add_for_device(event_conversion_key, LITEST_KEYBOARD);
890 litest_add_for_device(event_conversion_touch, LITEST_WACOM_TOUCH);
891 litest_add_for_device(event_conversion_gesture, LITEST_BCM5974);
892 litest_add_for_device(event_conversion_tablet, LITEST_WACOM_CINTIQ);
893 litest_add_for_device(event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD);
894 litest_add_for_device(event_conversion_switch, LITEST_LID_SWITCH);
895
896 litest_add_deviceless(context_ref_counting);
897 litest_add_deviceless(config_status_string);
898
899 litest_add_for_device(timer_offset_bug_warning, LITEST_SYNAPTICS_TOUCHPAD);
900 litest_add_for_device(timer_delay_bug_warning, LITEST_MOUSE);
901 litest_add_no_device(timer_flush);
902
903 litest_add_no_device(fd_no_event_leak);
904
905 litest_add_for_device(udev_absinfo_override, LITEST_ABSINFO_OVERRIDE);
906 }
907