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