xref: /third_party/libinput/test/test-misc.c (revision a46c0ec8)
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
37static int open_restricted(const char *path, int flags, void *data)
38{
39	int fd = open(path, flags);
40	return fd < 0 ? -errno : fd;
41}
42static void close_restricted(int fd, void *data)
43{
44	close(fd);
45}
46
47static const struct libinput_interface simple_interface = {
48	.open_restricted = open_restricted,
49	.close_restricted = close_restricted,
50};
51
52static struct libevdev_uinput *
53create_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
94START_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}
153END_TEST
154
155START_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}
207END_TEST
208
209START_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}
259END_TEST
260
261START_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}
303END_TEST
304
305START_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}
355END_TEST
356
357START_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}
408END_TEST
409
410START_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}
456END_TEST
457
458START_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}
500END_TEST
501
502START_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}
545END_TEST
546
547START_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}
564END_TEST
565
566START_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}
585END_TEST
586
587static int open_restricted_leak(const char *path, int flags, void *data)
588{
589	return *(int*)data;
590}
591
592static void close_restricted_leak(int fd, void *data)
593{
594	/* noop */
595}
596
597const struct libinput_interface leak_interface = {
598	.open_restricted = open_restricted_leak,
599	.close_restricted = close_restricted_leak,
600};
601
602START_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}
656END_TEST
657
658static 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
671START_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}
694END_TEST
695
696static 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
709START_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(21);
725		libinput_dispatch(li);
726	}
727
728	ck_assert_int_ge(warning_triggered, 1);
729	litest_restore_log_handler(li);
730}
731END_TEST
732
733START_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}
804END_TEST
805
806START_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}
882END_TEST
883
884TEST_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