• 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 	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