• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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