1 /*
2  * Copyright © 2013 Red Hat, Inc.
3  * Copyright © 2013 Marcin Slusarz <marcin.slusarz@gmail.com>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include "config.h"
26 
27 #include <check.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <libgen.h>
31 #include <fcntl.h>
32 #include <fnmatch.h>
33 #include <getopt.h>
34 #include <poll.h>
35 #include <signal.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <time.h>
41 #include <unistd.h>
42 #include "linux/input.h"
43 #include <sys/ptrace.h>
44 #include <sys/resource.h>
45 #include <sys/timerfd.h>
46 #include <sys/wait.h>
47 #include <sys/stat.h>
48 #include <sys/types.h>
49 #include <sys/sysinfo.h>
50 #include <libudev.h>
51 #if HAVE_LIBSYSTEMD
52 #include <systemd/sd-bus.h>
53 #endif
54 #ifdef __FreeBSD__
55 #include <termios.h>
56 #endif
57 
58 #include <valgrind/valgrind.h>
59 
60 #include "litest.h"
61 #include "litest-int.h"
62 #include "libinput-util.h"
63 #include "quirks.h"
64 #include "builddir.h"
65 
66 #include <linux/kd.h>
67 
68 #define evbit(t, c) ((t) << 16U | (c & 0xffff))
69 
70 #define UDEV_RULES_D "/run/udev/rules.d"
71 #define UDEV_FUZZ_OVERRIDE_RULE_FILE UDEV_RULES_D \
72 	"/91-litest-fuzz-override-REMOVEME-XXXXXX.rules"
73 #define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \
74 	"/91-litest-test-device-REMOVEME-XXXXXXX.rules"
75 #define UDEV_DEVICE_GROUPS_FILE UDEV_RULES_D \
76 	"/80-libinput-device-groups-litest-XXXXXX.rules"
77 
78 static int jobs;
79 static bool in_debugger = false;
80 static bool verbose = false;
81 static bool run_deviceless = false;
82 static bool use_system_rules_quirks = false;
83 static const char *filter_test = NULL;
84 static const char *filter_device = NULL;
85 static const char *filter_group = NULL;
86 static const char *xml_prefix = NULL;
87 static struct quirks_context *quirks_context;
88 
89 struct created_file {
90 	struct list link;
91 	char *path;
92 };
93 
94 static struct list created_files_list; /* list of all files to remove at the end
95 					  of the test run */
96 
97 static void litest_init_udev_rules(struct list *created_files_list);
98 static void litest_remove_udev_rules(struct list *created_files_list);
99 
100 enum quirks_setup_mode {
101 	QUIRKS_SETUP_USE_SRCDIR,
102 	QUIRKS_SETUP_ONLY_DEVICE,
103 	QUIRKS_SETUP_FULL,
104 };
105 static void litest_setup_quirks(struct list *created_files_list,
106 				enum quirks_setup_mode mode);
107 
108 /* defined for the litest selftest */
109 #ifndef LITEST_DISABLE_BACKTRACE_LOGGING
110 #define litest_log(...) fprintf(stderr, __VA_ARGS__)
111 #define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
112 #else
113 #define litest_log(...) { /* __VA_ARGS__ */ }
114 #define litest_vlog(...) { /* __VA_ARGS__ */ }
115 #endif
116 
117 static void
litest_backtrace(void)118 litest_backtrace(void)
119 {
120 #if HAVE_GSTACK
121 	pid_t parent, child;
122 	int pipefd[2];
123 
124 	if (RUNNING_ON_VALGRIND) {
125 		litest_log("  Using valgrind, omitting backtrace\n");
126 		return;
127 	}
128 
129 	if (pipe(pipefd) == -1)
130 		return;
131 
132 	parent = getpid();
133 	child = fork();
134 
135 	if (child == 0) {
136 		char pid[8];
137 
138 		close(pipefd[0]);
139 		dup2(pipefd[1], STDOUT_FILENO);
140 
141 		sprintf(pid, "%d", parent);
142 
143 		execlp("gstack", "gstack", pid, NULL);
144 		exit(errno);
145 	}
146 
147 	/* parent */
148 	char buf[1024];
149 	int status, nread;
150 
151 	close(pipefd[1]);
152 	waitpid(child, &status, 0);
153 
154 	status = WEXITSTATUS(status);
155 	if (status != 0) {
156 		litest_log("ERROR: gstack failed, no backtrace available: %s\n",
157 			   strerror(status));
158 	} else {
159 		litest_log("\nBacktrace:\n");
160 		while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
161 			buf[nread] = '\0';
162 			litest_log("%s", buf);
163 		}
164 		litest_log("\n");
165 	}
166 	close(pipefd[0]);
167 #endif
168 }
169 
170 LIBINPUT_ATTRIBUTE_PRINTF(5, 6)
171 __attribute__((noreturn))
172 void
litest_fail_condition(const char *file, int line, const char *func, const char *condition, const char *message, ...)173 litest_fail_condition(const char *file,
174 		      int line,
175 		      const char *func,
176 		      const char *condition,
177 		      const char *message,
178 		      ...)
179 {
180 	litest_log("FAILED: %s\n", condition);
181 
182 	if (message) {
183 		va_list args;
184 		va_start(args, message);
185 		litest_vlog(message, args);
186 		va_end(args);
187 	}
188 
189 	litest_log("in %s() (%s:%d)\n", func, file, line);
190 	litest_backtrace();
191 	abort();
192 }
193 
194 __attribute__((noreturn))
195 void
litest_fail_comparison_int(const char *file, int line, const char *func, const char *operator, int a, int b, const char *astr, const char *bstr)196 litest_fail_comparison_int(const char *file,
197 			   int line,
198 			   const char *func,
199 			   const char *operator,
200 			   int a,
201 			   int b,
202 			   const char *astr,
203 			   const char *bstr)
204 {
205 	litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
206 	litest_log("Resolved to: %d %s %d\n", a, operator, b);
207 	litest_log("in %s() (%s:%d)\n", func, file, line);
208 	litest_backtrace();
209 	abort();
210 }
211 
212 __attribute__((noreturn))
213 void
litest_fail_comparison_double(const char *file, int line, const char *func, const char *operator, double a, double b, const char *astr, const char *bstr)214 litest_fail_comparison_double(const char *file,
215 			      int line,
216 			      const char *func,
217 			      const char *operator,
218 			      double a,
219 			      double b,
220 			      const char *astr,
221 			      const char *bstr)
222 {
223 	litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
224 	litest_log("Resolved to: %.3f %s %.3f\n", a, operator, b);
225 	litest_log("in %s() (%s:%d)\n", func, file, line);
226 	litest_backtrace();
227 	abort();
228 }
229 
230 __attribute__((noreturn))
231 void
litest_fail_comparison_ptr(const char *file, int line, const char *func, const char *comparison)232 litest_fail_comparison_ptr(const char *file,
233 			   int line,
234 			   const char *func,
235 			   const char *comparison)
236 {
237 	litest_log("FAILED COMPARISON: %s\n", comparison);
238 	litest_log("in %s() (%s:%d)\n", func, file, line);
239 	litest_backtrace();
240 	abort();
241 }
242 
243 struct test {
244 	struct list node;
245 	char *name;
246 	char *devname;
247 	const void *func;
248 	void *setup;
249 	void *teardown;
250 
251 	struct range range;
252 	bool deviceless;
253 };
254 
255 struct suite {
256 	struct list node;
257 	struct list tests;
258 	char *name;
259 };
260 
261 static struct litest_device *current_device;
262 
litest_current_device(void)263 struct litest_device *litest_current_device(void)
264 {
265 	return current_device;
266 }
267 
268 static void
grab_device(struct litest_device *device, bool mode)269 grab_device(struct litest_device *device, bool mode)
270 {
271 	struct libinput *li = libinput_device_get_context(device->libinput_device);
272 	struct litest_context *ctx = libinput_get_user_data(li);
273 	struct udev_device *udev_device;
274 	const char *devnode;
275 	struct path *p;
276 
277 	udev_device = libinput_device_get_udev_device(device->libinput_device);
278 	litest_assert_ptr_notnull(udev_device);
279 
280 	devnode = udev_device_get_devnode(udev_device);
281 
282 	/* Note: in some tests we create multiple devices for the same path.
283 	 * This will only grab the first device in the list but we're using
284 	 * list_insert() so the first device is the latest that was
285 	 * initialized, so we should be good.
286 	 */
287 	list_for_each(p, &ctx->paths, link) {
288 		if (streq(p->path, devnode)) {
289 			int rc = ioctl(p->fd, EVIOCGRAB, (void*)mode ? 1 : 0);
290 			ck_assert_int_gt(rc, -1);
291 			udev_device_unref(udev_device);
292 			return;
293 		}
294 	}
295 	litest_abort_msg("Failed to find device %s to %sgrab\n",
296 			 devnode, mode ? "" : "un");
297 }
298 
299 void
litest_grab_device(struct litest_device *device)300 litest_grab_device(struct litest_device *device)
301 {
302 	grab_device(device, true);
303 }
304 
305 void
litest_ungrab_device(struct litest_device *device)306 litest_ungrab_device(struct litest_device *device)
307 {
308 	grab_device(device, false);
309 }
310 
litest_set_current_device(struct litest_device *device)311 void litest_set_current_device(struct litest_device *device)
312 {
313 	current_device = device;
314 }
315 
litest_generic_device_teardown(void)316 void litest_generic_device_teardown(void)
317 {
318 	litest_delete_device(current_device);
319 	current_device = NULL;
320 }
321 
322 static struct list devices;
323 
324 static struct list all_tests;
325 
326 static inline void
litest_system(const char *command)327 litest_system(const char *command)
328 {
329 	int ret;
330 
331 	ret = system(command);
332 
333 	if (ret == -1) {
334 		litest_abort_msg("Failed to execute: %s", command);
335 	} else if (WIFEXITED(ret)) {
336 		if (WEXITSTATUS(ret))
337 			litest_abort_msg("'%s' failed with %d",
338 					 command,
339 					 WEXITSTATUS(ret));
340 	} else if (WIFSIGNALED(ret)) {
341 		litest_abort_msg("'%s' terminated with signal %d",
342 				 command,
343 				 WTERMSIG(ret));
344 	}
345 }
346 
347 static void
litest_reload_udev_rules(void)348 litest_reload_udev_rules(void)
349 {
350 	litest_system("udevadm control --reload-rules");
351 }
352 
353 static void
litest_add_tcase_for_device(struct suite *suite, const char *funcname, const void *func, const struct litest_test_device *dev, const struct range *range)354 litest_add_tcase_for_device(struct suite *suite,
355 			    const char *funcname,
356 			    const void *func,
357 			    const struct litest_test_device *dev,
358 			    const struct range *range)
359 {
360 	struct test *t;
361 
362 	t = zalloc(sizeof(*t));
363 	t->name = safe_strdup(funcname);
364 	t->devname = safe_strdup(dev->shortname);
365 	t->func = func;
366 	t->setup = dev->setup;
367 	t->teardown = dev->teardown ?
368 			dev->teardown : litest_generic_device_teardown;
369 	if (range)
370 		t->range = *range;
371 
372 	list_insert(&suite->tests, &t->node);
373 }
374 
375 static void
litest_add_tcase_no_device(struct suite *suite, const void *func, const char *funcname, const struct range *range)376 litest_add_tcase_no_device(struct suite *suite,
377 			   const void *func,
378 			   const char *funcname,
379 			   const struct range *range)
380 {
381 	struct test *t;
382 	const char *test_name = funcname;
383 
384 	if (filter_device &&
385 	    strstr(test_name, filter_device) == NULL &&
386 	    fnmatch(filter_device, test_name, 0) != 0)
387 		return;
388 
389 	t = zalloc(sizeof(*t));
390 	t->name = safe_strdup(test_name);
391 	t->devname = safe_strdup("no device");
392 	t->func = func;
393 	if (range)
394 		t->range = *range;
395 	t->setup = NULL;
396 	t->teardown = NULL;
397 
398 	list_insert(&suite->tests, &t->node);
399 }
400 
401 static void
litest_add_tcase_deviceless(struct suite *suite, const void *func, const char *funcname, const struct range *range)402 litest_add_tcase_deviceless(struct suite *suite,
403 			    const void *func,
404 			    const char *funcname,
405 			    const struct range *range)
406 {
407 	struct test *t;
408 	const char *test_name = funcname;
409 
410 	if (filter_device &&
411 	    strstr(test_name, filter_device) == NULL &&
412 	    fnmatch(filter_device, test_name, 0) != 0)
413 		return;
414 
415 	t = zalloc(sizeof(*t));
416 	t->deviceless = true;
417 	t->name = safe_strdup(test_name);
418 	t->devname = safe_strdup("deviceless");
419 	t->func = func;
420 	if (range)
421 		t->range = *range;
422 	t->setup = NULL;
423 	t->teardown = NULL;
424 
425 	list_insert(&suite->tests, &t->node);
426 }
427 
428 static struct suite *
get_suite(const char *name)429 get_suite(const char *name)
430 {
431 	struct suite *s;
432 
433 	list_for_each(s, &all_tests, node) {
434 		if (streq(s->name, name))
435 			return s;
436 	}
437 
438 	s = zalloc(sizeof(*s));
439 	s->name = safe_strdup(name);
440 
441 	list_init(&s->tests);
442 	list_insert(&all_tests, &s->node);
443 
444 	return s;
445 }
446 
447 static void
create_suite_name(const char *filename, char suitename[64])448 create_suite_name(const char *filename, char suitename[64])
449 {
450 	char *trunk = trunkname(filename);
451 	char *p = trunk;
452 
453 	/* strip the test- prefix */
454 	if (strstartswith(trunk, "test-"))
455 		p += 5;
456 
457 	snprintf(suitename, 64, "%s", p);
458 	free(trunk);
459 }
460 
461 static void
litest_add_tcase(const char *filename, const char *funcname, const void *func, int64_t required, int64_t excluded, const struct range *range)462 litest_add_tcase(const char *filename,
463 		 const char *funcname,
464 		 const void *func,
465 		 int64_t required,
466 		 int64_t excluded,
467 		 const struct range *range)
468 {
469 	char suite_name[65];
470 	struct suite *suite;
471 	bool added = false;
472 
473 	litest_assert(required >= LITEST_DEVICELESS);
474 	litest_assert(excluded >= LITEST_DEVICELESS);
475 
476 	if (filter_test &&
477 	    strstr(funcname, filter_test) == NULL &&
478 	    fnmatch(filter_test, funcname, 0) != 0)
479 		return;
480 
481 	create_suite_name(filename, suite_name);
482 
483 	if (filter_group && fnmatch(filter_group, suite_name, 0) != 0)
484 		return;
485 
486 	suite = get_suite(suite_name);
487 
488 	if (required == LITEST_DEVICELESS &&
489 	    excluded == LITEST_DEVICELESS) {
490 		litest_add_tcase_deviceless(suite, func, funcname, range);
491 		added = true;
492 	} else if (required == LITEST_DISABLE_DEVICE &&
493 	    excluded == LITEST_DISABLE_DEVICE) {
494 		litest_add_tcase_no_device(suite, func, funcname, range);
495 		added = true;
496 	} else if (required != LITEST_ANY || excluded != LITEST_ANY) {
497 		struct litest_test_device *dev;
498 
499 		list_for_each(dev, &devices, node) {
500 			if (dev->features & LITEST_IGNORED)
501 				continue;
502 
503 			if (filter_device &&
504 			    strstr(dev->shortname, filter_device) == NULL &&
505 			    fnmatch(filter_device, dev->shortname, 0) != 0)
506 				continue;
507 			if ((dev->features & required) != required ||
508 			    (dev->features & excluded) != 0)
509 				continue;
510 
511 			litest_add_tcase_for_device(suite,
512 						    funcname,
513 						    func,
514 						    dev,
515 						    range);
516 			added = true;
517 		}
518 	} else {
519 		struct litest_test_device *dev;
520 
521 		list_for_each(dev, &devices, node) {
522 			if (dev->features & LITEST_IGNORED)
523 				continue;
524 
525 			if (filter_device &&
526 			    strstr(dev->shortname, filter_device) == NULL &&
527 			    fnmatch(filter_device, dev->shortname, 0) != 0)
528 				continue;
529 
530 			litest_add_tcase_for_device(suite,
531 						    funcname,
532 						    func,
533 						    dev,
534 						    range);
535 			added = true;
536 		}
537 	}
538 
539 	if (!added &&
540 	    filter_test == NULL &&
541 	    filter_device == NULL &&
542 	    filter_group == NULL) {
543 		fprintf(stderr, "Test '%s' does not match any devices. Aborting.\n", funcname);
544 		abort();
545 	}
546 }
547 
548 void
_litest_add_no_device(const char *name, const char *funcname, const void *func)549 _litest_add_no_device(const char *name, const char *funcname, const void *func)
550 {
551 	_litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
552 }
553 
554 void
_litest_add_ranged_no_device(const char *name, const char *funcname, const void *func, const struct range *range)555 _litest_add_ranged_no_device(const char *name,
556 			     const char *funcname,
557 			     const void *func,
558 			     const struct range *range)
559 {
560 	_litest_add_ranged(name,
561 			   funcname,
562 			   func,
563 			   LITEST_DISABLE_DEVICE,
564 			   LITEST_DISABLE_DEVICE,
565 			   range);
566 }
567 
568 void
_litest_add_deviceless(const char *name, const char *funcname, const void *func)569 _litest_add_deviceless(const char *name,
570 		       const char *funcname,
571 		       const void *func)
572 {
573 	_litest_add_ranged(name,
574 			   funcname,
575 			   func,
576 			   LITEST_DEVICELESS,
577 			   LITEST_DEVICELESS,
578 			   NULL);
579 }
580 
581 void
_litest_add(const char *name, const char *funcname, const void *func, int64_t required, int64_t excluded)582 _litest_add(const char *name,
583 	    const char *funcname,
584 	    const void *func,
585 	    int64_t required,
586 	    int64_t excluded)
587 {
588 	_litest_add_ranged(name,
589 			   funcname,
590 			   func,
591 			   required,
592 			   excluded,
593 			   NULL);
594 }
595 
596 void
_litest_add_ranged(const char *name, const char *funcname, const void *func, int64_t required, int64_t excluded, const struct range *range)597 _litest_add_ranged(const char *name,
598 		   const char *funcname,
599 		   const void *func,
600 		   int64_t required,
601 		   int64_t excluded,
602 		   const struct range *range)
603 {
604 	litest_add_tcase(name, funcname, func, required, excluded, range);
605 }
606 
607 void
_litest_add_for_device(const char *name, const char *funcname, const void *func, enum litest_device_type type)608 _litest_add_for_device(const char *name,
609 		       const char *funcname,
610 		       const void *func,
611 		       enum litest_device_type type)
612 {
613 	_litest_add_ranged_for_device(name, funcname, func, type, NULL);
614 }
615 
616 void
_litest_add_ranged_for_device(const char *filename, const char *funcname, const void *func, enum litest_device_type type, const struct range *range)617 _litest_add_ranged_for_device(const char *filename,
618 			      const char *funcname,
619 			      const void *func,
620 			      enum litest_device_type type,
621 			      const struct range *range)
622 {
623 	struct suite *s;
624 	struct litest_test_device *dev;
625 	bool device_filtered = false;
626 	char suite_name[64];
627 
628 	litest_assert(type < LITEST_NO_DEVICE);
629 
630 	if (filter_test &&
631 	    strstr(funcname, filter_test) == NULL &&
632 	    fnmatch(filter_test, funcname, 0) != 0)
633 		return;
634 
635 	create_suite_name(filename, suite_name);
636 	if (filter_group && fnmatch(filter_group, suite_name, 0) != 0)
637 		return;
638 
639 	s = get_suite(suite_name);
640 	list_for_each(dev, &devices, node) {
641 		if (filter_device &&
642 		    strstr(dev->shortname, filter_device) == NULL &&
643 		    fnmatch(filter_device, dev->shortname, 0) != 0) {
644 			device_filtered = true;
645 			continue;
646 		}
647 
648 		if (dev->type == type) {
649 			litest_add_tcase_for_device(s,
650 						    funcname,
651 						    func,
652 						    dev,
653 						    range);
654 			return;
655 		}
656 	}
657 
658 	/* only abort if no filter was set, that's a bug */
659 	if (!device_filtered)
660 		litest_abort_msg("Invalid test device type\n");
661 }
662 
663 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
664 static void
litest_log_handler(struct libinput *libinput, enum libinput_log_priority pri, const char *format, va_list args)665 litest_log_handler(struct libinput *libinput,
666 		   enum libinput_log_priority pri,
667 		   const char *format,
668 		   va_list args)
669 {
670 	static int is_tty = -1;
671 	const char *priority = NULL;
672 	const char *color;
673 
674 	if (is_tty == -1)
675 		is_tty = isatty(STDERR_FILENO);
676 
677 	switch(pri) {
678 	case LIBINPUT_LOG_PRIORITY_INFO:
679 		priority =  "info ";
680 		color = ANSI_HIGHLIGHT;
681 		break;
682 	case LIBINPUT_LOG_PRIORITY_ERROR:
683 		priority = "error";
684 		color = ANSI_BRIGHT_RED;
685 		break;
686 	case LIBINPUT_LOG_PRIORITY_DEBUG:
687 		priority = "debug";
688 		color = ANSI_NORMAL;
689 		break;
690 	default:
691 		  abort();
692 	}
693 
694 	if (!is_tty)
695 		color = "";
696 	else if (strstr(format, "tap:"))
697 		color = ANSI_BLUE;
698 	else if (strstr(format, "thumb state:"))
699 		color = ANSI_YELLOW;
700 	else if (strstr(format, "button state:"))
701 		color = ANSI_MAGENTA;
702 	else if (strstr(format, "touch-size:") ||
703 		 strstr(format, "pressure:"))
704 		color = ANSI_GREEN;
705 	else if (strstr(format, "palm:") ||
706 		 strstr(format, "thumb:"))
707 		color = ANSI_CYAN;
708 	else if (strstr(format, "edge-scroll:"))
709 		color = ANSI_BRIGHT_GREEN;
710 
711 	fprintf(stderr, "%slitest %s ", color, priority);
712 	vfprintf(stderr, format, args);
713 	if (is_tty)
714 		fprintf(stderr, ANSI_NORMAL);
715 
716 	if (strstr(format, "client bug: ") ||
717 	    strstr(format, "libinput bug: ")) {
718 		/* valgrind is too slow and some of our offsets are too
719 		 * short, don't abort if during a valgrind run we get a
720 		 * negative offset */
721 		if ((RUNNING_ON_VALGRIND && in_debugger) ||
722 		    !strstr(format, "scheduled expiry is in the past")) {
723 			/* noop */
724 		} else if (!strstr(format, "event processing lagging behind")) {
725 			/* noop */
726 		} else {
727 			litest_abort_msg("libinput bug triggered, aborting.\n");
728 		}
729 	}
730 
731 	if (strstr(format, "Touch jump detected and discarded")) {
732 		litest_abort_msg("libinput touch jump triggered, aborting.\n");
733 	}
734 }
735 
736 static void
litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f)737 litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f)
738 {
739 	const struct key_value_str *kv;
740 	static int count;
741 	bool need_keyboard_builtin = false;
742 
743 	if (dev->udev_properties[0].key == NULL)
744 		return;
745 
746 	count++;
747 
748 	fprintf(f, "# %s\n", dev->shortname);
749 	fprintf(f, "ACTION==\"remove\", GOTO=\"rule%d_end\"\n", count);
750 	fprintf(f, "KERNEL!=\"event*\", GOTO=\"rule%d_end\"\n", count);
751 
752 	fprintf(f, "ATTRS{name}==\"litest %s*\"", dev->name);
753 
754 	kv = dev->udev_properties;
755 	while (kv->key) {
756 		fprintf(f, ", \\\n\tENV{%s}=\"%s\"", kv->key, kv->value);
757 		if (strneq(kv->key, "EVDEV_ABS_", 10))
758 			need_keyboard_builtin = true;
759 		kv++;
760 	}
761 	fprintf(f, "\n");
762 
763 	/* Special case: the udev keyboard builtin is only run for hwdb
764 	 * matches but we don't set any up in litest. So instead scan the
765 	 * device's udev properties for any EVDEV_ABS properties and where
766 	 * they exist, force a (re-)run of the keyboard builtin to set up
767 	 * the evdev device correctly.
768 	 * This needs to be done as separate rule apparently, otherwise the
769 	 * ENV variables aren't set yet by the time the builtin runs.
770 	 */
771 	if (need_keyboard_builtin) {
772 		fprintf(f, ""
773 			"ATTRS{name}==\"litest %s*\","
774 			" IMPORT{builtin}=\"keyboard\"\n",
775 			dev->name);
776 	}
777 
778 	fprintf(f, "LABEL=\"rule%d_end\"\n\n", count);;
779 }
780 
781 static void
litest_init_all_device_udev_rules(struct list *created_files)782 litest_init_all_device_udev_rules(struct list *created_files)
783 {
784 	struct created_file *file = zalloc(sizeof(*file));
785 	struct litest_test_device *dev;
786 	char *path = NULL;
787 	FILE *f;
788 	int rc;
789 	int fd;
790 
791 	rc = xasprintf(&path,
792 		      "%s/99-litest-XXXXXX.rules",
793 		      UDEV_RULES_D);
794 	litest_assert_int_gt(rc, 0);
795 
796 	fd = mkstemps(path, 6);
797 	litest_assert_int_ne(fd, -1);
798 	f = fdopen(fd, "w");
799 	litest_assert_notnull(f);
800 
801 	list_for_each(dev, &devices, node)
802 		litest_init_device_udev_rules(dev, f);
803 
804 	fclose(f);
805 
806 	file->path = path;
807 	list_insert(created_files, &file->link);
808 }
809 
810 static int
open_restricted(const char *path, int flags, void *userdata)811 open_restricted(const char *path, int flags, void *userdata)
812 {
813 	const char prefix[] = "/dev/input/event";
814 	struct litest_context *ctx = userdata;
815 	struct path *p;
816 	int fd;
817 
818 	litest_assert_ptr_notnull(ctx);
819 
820 	fd = open(path, flags);
821 	if (fd < 0)
822 		return -errno;
823 
824 	if (strneq(path, prefix, strlen(prefix))) {
825 		p = zalloc(sizeof *p);
826 		p->path = safe_strdup(path);
827 		p->fd = fd;
828 		/* We specifically insert here so that the most-recently
829 		 * opened path is the first one in the list. This helps when
830 		 * we have multiple test devices with the same device path,
831 		 * the fd of the most recent device is the first one to get
832 		 * grabbed
833 		 */
834 		list_insert(&ctx->paths, &p->link);
835 	}
836 
837 	return fd;
838 }
839 
840 static void
close_restricted(int fd, void *userdata)841 close_restricted(int fd, void *userdata)
842 {
843 	struct litest_context *ctx = userdata;
844 	struct path *p;
845 
846 	list_for_each_safe(p, &ctx->paths, link) {
847 		if (p->fd != fd)
848 			continue;
849 		list_remove(&p->link);
850 		free(p->path);
851 		free(p);
852 	}
853 
854 	close(fd);
855 }
856 
857 static struct libinput_interface interface = {
858 	.open_restricted = open_restricted,
859 	.close_restricted = close_restricted,
860 };
861 
862 static void
litest_signal(int sig)863 litest_signal(int sig)
864 {
865 	struct created_file *f;
866 
867 	list_for_each_safe(f, &created_files_list, link) {
868 		list_remove(&f->link);
869 		unlink(f->path);
870 		rmdir(f->path);
871 		/* in the sighandler, we can't free */
872 	}
873 
874 	if (fork() == 0) {
875 		/* child, we can run system() */
876 		litest_reload_udev_rules();
877 		exit(0);
878 	}
879 
880 	exit(1);
881 }
882 
883 static inline void
litest_setup_sighandler(int sig)884 litest_setup_sighandler(int sig)
885 {
886 	struct sigaction act, oact;
887 	int rc;
888 
889 	sigemptyset(&act.sa_mask);
890 	sigaddset(&act.sa_mask, sig);
891 	act.sa_flags = 0;
892 	act.sa_handler = litest_signal;
893 	rc = sigaction(sig, &act, &oact);
894 	litest_assert_int_ne(rc, -1);
895 }
896 
897 static void
litest_free_test_list(struct list *tests)898 litest_free_test_list(struct list *tests)
899 {
900 	struct suite *s;
901 
902 	list_for_each_safe(s, tests, node) {
903 		struct test *t;
904 
905 		list_for_each_safe(t, &s->tests, node) {
906 			free(t->name);
907 			free(t->devname);
908 			list_remove(&t->node);
909 			free(t);
910 		}
911 
912 		list_remove(&s->node);
913 		free(s->name);
914 		free(s);
915 	}
916 }
917 
918 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
919 static inline void
quirk_log_handler(struct libinput *unused, enum libinput_log_priority priority, const char *format, va_list args)920 quirk_log_handler(struct libinput *unused,
921 		  enum libinput_log_priority priority,
922 		  const char *format,
923 		  va_list args)
924 {
925 	if (priority < LIBINPUT_LOG_PRIORITY_ERROR)
926 		return;
927 
928 	vfprintf(stderr, format, args);
929 }
930 
931 static void
litest_export_xml(SRunner *sr, const char *xml_prefix)932 litest_export_xml(SRunner *sr, const char *xml_prefix)
933 {
934 	TestResult **results;
935 	int nresults, nfailed;
936 	char *filename;
937 	int fd;
938 
939 	/* This is the minimum-effort implementation here because its only
940 	 * real purpose is to make test logs look pretty in the gitlab CI.
941 	 *
942 	 * Which means:
943 	 * - there's no filename validation, if you supply a filename that
944 	 *   mkstemps doesn't like, things go boom.
945 	 * - every fork writes out a separate junit.xml file. gitlab is better
946 	 *   at collecting lots of files than I am at writing code to collect
947 	 *   this across forks to write out only one file.
948 	 * - most of the content is pretty useless because libcheck only gives
949 	 *   us minimal information. the libcheck XML file has more info like
950 	 *   the duration of each test but it's more complicated to extract
951 	 *   and we don't need it for now.
952 	 */
953 	filename = safe_strdup(xml_prefix);
954 	fd = mkstemps(filename, 4);
955 
956 	results = srunner_results(sr);
957 	nresults = srunner_ntests_run(sr);
958 	nfailed = srunner_ntests_failed(sr);
959 
960 	dprintf(fd, "<?xml version=\"1.0\"?>\n");
961 	dprintf(fd, "<testsuites id=\"%s\" tests=\"%d\" failures=\"%d\">\n",
962 		filename,
963 		nresults,
964 		nfailed);
965 	dprintf(fd, "  <testsuite>\n");
966 	for (int i = 0; i < nresults; i++) {
967 		TestResult *r = results[i];
968 
969 		dprintf(fd, "    <testcase id=\"%s\" name=\"%s\" %s>\n",
970 			tr_tcname(r),
971 			tr_tcname(r),
972 			tr_rtype(r) == CK_PASS ? "/" : "");
973 		if (tr_rtype(r) != CK_PASS) {
974 			dprintf(fd, "      <failure message=\"%s:%d\">\n",
975 				tr_lfile(r),
976 				tr_lno(r));
977 			dprintf(fd, "        %s:%d\n", tr_lfile(r), tr_lno(r));
978 			dprintf(fd, "        %s\n", tr_tcname(r));
979 			dprintf(fd, "\n");
980 			dprintf(fd, "        %s\n", tr_msg(r));
981 			dprintf(fd, "      </failure>\n");
982 			dprintf(fd, "    </testcase>\n");
983 		}
984 	}
985 	dprintf(fd, "  </testsuite>\n");
986 	dprintf(fd, "</testsuites>\n");
987 
988 	free(results);
989 	close(fd);
990 	free(filename);
991 }
992 
993 static int
litest_run_suite(struct list *tests, int which, int max, int error_fd)994 litest_run_suite(struct list *tests, int which, int max, int error_fd)
995 {
996 	int failed = 0;
997 	SRunner *sr = NULL;
998 	struct suite *s;
999 	struct test *t;
1000 	int count = -1;
1001 	struct name {
1002 		struct list node;
1003 		char *name;
1004 	};
1005 	struct name *n;
1006 	struct list testnames;
1007 	const char *data_path;
1008 
1009 	data_path = getenv("LIBINPUT_QUIRKS_DIR");
1010 	if (!data_path)
1011 		data_path = LIBINPUT_QUIRKS_DIR;
1012 
1013 	quirks_context = quirks_init_subsystem(data_path,
1014 					       NULL,
1015 					       quirk_log_handler,
1016 					       NULL,
1017 					       QLOG_LIBINPUT_LOGGING);
1018 
1019 	/* Check just takes the suite/test name pointers but doesn't strdup
1020 	 * them - we have to keep them around */
1021 	list_init(&testnames);
1022 
1023 	/* For each test, create one test suite with one test case, then
1024 	   add it to the test runner. The only benefit suites give us in
1025 	   check is that we can filter them, but our test runner has a
1026 	   --filter-group anyway. */
1027 	list_for_each(s, tests, node) {
1028 		list_for_each(t, &s->tests, node) {
1029 			Suite *suite;
1030 			TCase *tc;
1031 			char *sname, *tname;
1032 
1033 			/* We run deviceless tests as part of the normal
1034 			 * test suite runner, just in case. Filtering
1035 			 * all the other ones out just for the case where
1036 			 * we can't run the full runner.
1037 			 */
1038 			if (run_deviceless && !t->deviceless)
1039 				continue;
1040 
1041 			count = (count + 1) % max;
1042 			if (max != 1 && (count % max) != which)
1043 				continue;
1044 
1045 			xasprintf(&sname,
1046 				  "%s:%s:%s",
1047 				  s->name,
1048 				  t->name,
1049 				  t->devname);
1050 			litest_assert_ptr_notnull(sname);
1051 			n = zalloc(sizeof(*n));
1052 			n->name = sname;
1053 			list_insert(&testnames, &n->node);
1054 
1055 			xasprintf(&tname,
1056 				  "%s:%s",
1057 				  t->name,
1058 				  t->devname);
1059 			litest_assert_ptr_notnull(tname);
1060 			n = zalloc(sizeof(*n));
1061 			n->name = tname;
1062 			list_insert(&testnames, &n->node);
1063 
1064 			tc = tcase_create(tname);
1065 			tcase_add_checked_fixture(tc,
1066 						  t->setup,
1067 						  t->teardown);
1068 			if (t->range.upper != t->range.lower)
1069 				tcase_add_loop_test(tc,
1070 						    t->func,
1071 						    t->range.lower,
1072 						    t->range.upper);
1073 			else
1074 				tcase_add_test(tc, t->func);
1075 
1076 			suite = suite_create(sname);
1077 			suite_add_tcase(suite, tc);
1078 
1079 			if (!sr)
1080 				sr = srunner_create(suite);
1081 			else
1082 				srunner_add_suite(sr, suite);
1083 		}
1084 	}
1085 
1086 	if (!sr)
1087 		goto out;
1088 
1089 	srunner_run_all(sr, CK_ENV);
1090 	if (xml_prefix)
1091 		litest_export_xml(sr, xml_prefix);
1092 
1093 
1094 	failed = srunner_ntests_failed(sr);
1095 	if (failed) {
1096 		TestResult **trs;
1097 
1098 		trs = srunner_failures(sr);
1099 		for (int i = 0; i < failed; i++) {
1100 			char tname[256];
1101 			char *c = tname;
1102 
1103 			/* tr_tcname is in the form "suite:testcase", let's
1104 			 * convert this to "suite(testcase)" to make
1105 			 * double-click selection in the terminal a bit
1106 			 * easier. */
1107 			snprintf(tname, sizeof(tname), "%s)", tr_tcname(trs[i]));
1108 			if ((c = index(c, ':')))
1109 				*c = '(';
1110 
1111 			dprintf(error_fd,
1112 				":: Failure: %s:%d: %s\n",
1113 				tr_lfile(trs[i]),
1114 				tr_lno(trs[i]),
1115 				tname);
1116 		}
1117 		free(trs);
1118 	}
1119 	srunner_free(sr);
1120 out:
1121 	list_for_each_safe(n, &testnames, node) {
1122 		free(n->name);
1123 		free(n);
1124 	}
1125 
1126 	quirks_context_unref(quirks_context);
1127 
1128 	return failed;
1129 }
1130 
1131 static int
litest_fork_subtests(struct list *tests, int max_forks)1132 litest_fork_subtests(struct list *tests, int max_forks)
1133 {
1134 	int failed = 0;
1135 	int status;
1136 	pid_t pid;
1137 	int f;
1138 	int pipes[max_forks];
1139 
1140 	for (f = 0; f < max_forks; f++) {
1141 		int rc;
1142 		int pipefd[2];
1143 
1144 		rc = pipe2(pipefd, O_NONBLOCK);
1145 		assert(rc != -1);
1146 
1147 		pid = fork();
1148 		if (pid == 0) {
1149 			close(pipefd[0]);
1150 			failed = litest_run_suite(tests,
1151 						  f,
1152 						  max_forks,
1153 						  pipefd[1]);
1154 
1155 			litest_free_test_list(&all_tests);
1156 			exit(failed);
1157 			/* child always exits here */
1158 		} else {
1159 			pipes[f] = pipefd[0];
1160 			close(pipefd[1]);
1161 		}
1162 	}
1163 
1164 	/* parent process only */
1165 	while (wait(&status) != -1 && errno != ECHILD) {
1166 		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
1167 			failed = 1;
1168 	}
1169 
1170 	for (f = 0; f < max_forks; f++) {
1171 		char buf[1024] = {0};
1172 		int rc;
1173 
1174 		while ((rc = read(pipes[f], buf, sizeof(buf) - 1)) > 0) {
1175 			buf[rc] = '\0';
1176 			fprintf(stderr, "%s", buf);
1177 		}
1178 
1179 		close(pipes[f]);
1180 	}
1181 
1182 	return failed;
1183 }
1184 
1185 static inline int
inhibit(void)1186 inhibit(void)
1187 {
1188 	int lock_fd = -1;
1189 #if HAVE_LIBSYSTEMD
1190 	sd_bus_error error = SD_BUS_ERROR_NULL;
1191 	sd_bus_message *m = NULL;
1192 	sd_bus *bus = NULL;
1193 	int rc;
1194 
1195 	if (run_deviceless)
1196 		return -1;
1197 
1198 	rc = sd_bus_open_system(&bus);
1199 	if (rc != 0) {
1200 		fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
1201 		goto out;
1202 	}
1203 
1204 	rc = sd_bus_call_method(bus,
1205 				"org.freedesktop.login1",
1206 				"/org/freedesktop/login1",
1207 				"org.freedesktop.login1.Manager",
1208 				"Inhibit",
1209 				&error,
1210 				&m,
1211 				"ssss",
1212 				"sleep:shutdown:handle-lid-switch:handle-power-key:handle-suspend-key:handle-hibernate-key",
1213 				"libinput test-suite runner",
1214 				"testing in progress",
1215 				"block");
1216 	if (rc < 0) {
1217 		fprintf(stderr, "Warning: inhibit failed: %s\n", error.message);
1218 		goto out;
1219 	}
1220 
1221 	rc = sd_bus_message_read(m, "h", &lock_fd);
1222 	if (rc < 0) {
1223 		fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
1224 		goto out;
1225 	}
1226 
1227 	lock_fd = dup(lock_fd);
1228 out:
1229 	sd_bus_error_free(&error);
1230 	sd_bus_message_unref(m);
1231 	sd_bus_close(bus);
1232 	sd_bus_unref(bus);
1233 #endif
1234 	return lock_fd;
1235 }
1236 
1237 static inline int
litest_run(int argc, char **argv)1238 litest_run(int argc, char **argv)
1239 {
1240 	int failed = 0;
1241 	int inhibit_lock_fd;
1242 
1243 	list_init(&created_files_list);
1244 
1245 	if (list_empty(&all_tests)) {
1246 		fprintf(stderr,
1247 			"Error: filters are too strict, no tests to run.\n");
1248 		return 1;
1249 	}
1250 
1251 	if (getenv("LITEST_VERBOSE"))
1252 		verbose = true;
1253 
1254 	if (run_deviceless) {
1255 		litest_setup_quirks(&created_files_list,
1256 				    QUIRKS_SETUP_USE_SRCDIR);
1257 	} else {
1258 		enum quirks_setup_mode mode;
1259 		litest_init_udev_rules(&created_files_list);
1260 
1261 
1262 		mode = use_system_rules_quirks ?
1263 				QUIRKS_SETUP_ONLY_DEVICE :
1264 				QUIRKS_SETUP_FULL;
1265 		litest_setup_quirks(&created_files_list, mode);
1266 	}
1267 
1268 	litest_setup_sighandler(SIGINT);
1269 
1270 	inhibit_lock_fd = inhibit();
1271 
1272 	if (jobs == 1)
1273 		failed = litest_run_suite(&all_tests, 1, 1, STDERR_FILENO);
1274 	else
1275 		failed = litest_fork_subtests(&all_tests, jobs);
1276 
1277 	close(inhibit_lock_fd);
1278 
1279 	litest_free_test_list(&all_tests);
1280 
1281 	litest_remove_udev_rules(&created_files_list);
1282 
1283 	return failed;
1284 }
1285 
1286 static struct input_absinfo *
merge_absinfo(const struct input_absinfo *orig, const struct input_absinfo *override)1287 merge_absinfo(const struct input_absinfo *orig,
1288 	      const struct input_absinfo *override)
1289 {
1290 	struct input_absinfo *abs;
1291 	unsigned int nelem, i;
1292 	size_t sz = ABS_MAX + 1;
1293 
1294 	if (!orig)
1295 		return NULL;
1296 
1297 	abs = zalloc(sz * sizeof(*abs));
1298 	litest_assert_ptr_notnull(abs);
1299 
1300 	nelem = 0;
1301 	while (orig[nelem].value != -1) {
1302 		abs[nelem] = orig[nelem];
1303 		nelem++;
1304 		litest_assert_int_lt(nelem, sz);
1305 	}
1306 
1307 	/* just append, if the same axis is present twice, libevdev will
1308 	   only use the last value anyway */
1309 	i = 0;
1310 	while (override && override[i].value != -1) {
1311 		abs[nelem++] = override[i++];
1312 		litest_assert_int_lt(nelem, sz);
1313 	}
1314 
1315 	litest_assert_int_lt(nelem, sz);
1316 	abs[nelem].value = -1;
1317 
1318 	return abs;
1319 }
1320 
1321 static int*
merge_events(const int *orig, const int *override)1322 merge_events(const int *orig, const int *override)
1323 {
1324 	int *events;
1325 	unsigned int nelem, i;
1326 	size_t sz = KEY_MAX * 3;
1327 
1328 	if (!orig)
1329 		return NULL;
1330 
1331 	events = zalloc(sz * sizeof(int));
1332 	litest_assert_ptr_notnull(events);
1333 
1334 	nelem = 0;
1335 	while (orig[nelem] != -1) {
1336 		events[nelem] = orig[nelem];
1337 		nelem++;
1338 		litest_assert_int_lt(nelem, sz);
1339 	}
1340 
1341 	/* just append, if the same axis is present twice, libevdev will
1342 	 * ignore the double definition anyway */
1343 	i = 0;
1344 	while (override && override[i] != -1) {
1345 		events[nelem++] = override[i++];
1346 		litest_assert_int_le(nelem, sz);
1347 	}
1348 
1349 	litest_assert_int_lt(nelem, sz);
1350 	events[nelem] = -1;
1351 
1352 	return events;
1353 }
1354 
1355 static inline struct created_file *
litest_copy_file(const char *dest, const char *src, const char *header, bool is_file)1356 litest_copy_file(const char *dest, const char *src, const char *header, bool is_file)
1357 {
1358 	int in, out, length;
1359 	struct created_file *file;
1360 
1361 	file = zalloc(sizeof(*file));
1362 	file->path = safe_strdup(dest);
1363 
1364 	if (strstr(dest, "XXXXXX")) {
1365 		int suffixlen;
1366 
1367 		suffixlen = file->path +
1368 				strlen(file->path) -
1369 				rindex(file->path, '.');
1370 		out = mkstemps(file->path, suffixlen);
1371 	} else {
1372 		out = open(file->path, O_CREAT|O_WRONLY, 0644);
1373 	}
1374 	if (out == -1)
1375 		litest_abort_msg("Failed to write to file %s (%s)\n",
1376 				 file->path,
1377 				 strerror(errno));
1378 	litest_assert_int_ne(chmod(file->path, 0644), -1);
1379 
1380 	if (header) {
1381 		length = strlen(header);
1382 		litest_assert_int_eq(write(out, header, length), length);
1383 	}
1384 
1385 	if (is_file) {
1386 		in = open(src, O_RDONLY);
1387 		if (in == -1)
1388 			litest_abort_msg("Failed to open file %s (%s)\n",
1389 					 src,
1390 					 strerror(errno));
1391 		/* lazy, just check for error and empty file copy */
1392 		litest_assert_int_gt(litest_send_file(out, in), 0);
1393 		close(in);
1394 	} else {
1395 		size_t written = write(out, src, strlen(src));
1396 		litest_assert_int_eq(written, strlen(src));
1397 
1398 	}
1399 	close(out);
1400 
1401 	return file;
1402 }
1403 
1404 static inline void
litest_install_model_quirks(struct list *created_files_list)1405 litest_install_model_quirks(struct list *created_files_list)
1406 {
1407 	const char *warning =
1408 			 "#################################################################\n"
1409 			 "# WARNING: REMOVE THIS FILE\n"
1410 			 "# This is a run-time file for the libinput test suite and\n"
1411 			 "# should be removed on exit. If the test-suite is not currently \n"
1412 			 "# running, remove this file\n"
1413 			 "#################################################################\n\n";
1414 	struct created_file *file;
1415 	const char *test_device_udev_rule = "KERNELS==\"*input*\", "
1416 					    "ATTRS{name}==\"litest *\", "
1417 					    "ENV{LIBINPUT_TEST_DEVICE}=\"1\"";
1418 
1419 	file = litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE,
1420 				test_device_udev_rule,
1421 				warning,
1422 				false);
1423 	list_insert(created_files_list, &file->link);
1424 
1425 	/* Only install the litest device rule when we're running as system
1426 	 * test suite, we expect the others to be in place already */
1427 	if (use_system_rules_quirks)
1428 		return;
1429 
1430 	file = litest_copy_file(UDEV_DEVICE_GROUPS_FILE,
1431 				LIBINPUT_DEVICE_GROUPS_RULES_FILE,
1432 				warning,
1433 				true);
1434 	list_insert(created_files_list, &file->link);
1435 
1436 	file = litest_copy_file(UDEV_FUZZ_OVERRIDE_RULE_FILE,
1437 				LIBINPUT_FUZZ_OVERRIDE_UDEV_RULES_FILE,
1438 				warning,
1439 				true);
1440 	list_insert(created_files_list, &file->link);
1441 }
1442 
1443 static char *
litest_init_device_quirk_file(const char *data_dir, struct litest_test_device *dev)1444 litest_init_device_quirk_file(const char *data_dir,
1445 			      struct litest_test_device *dev)
1446 {
1447 	int fd;
1448 	FILE *f;
1449 	char path[PATH_MAX];
1450 	static int count;
1451 
1452 	if (!dev->quirk_file)
1453 		return NULL;
1454 
1455 	snprintf(path, sizeof(path),
1456 		 "%s/99-%03d-%s.quirks",
1457 		 data_dir,
1458 		 ++count,
1459 		 dev->shortname);
1460 	fd = open(path, O_CREAT|O_WRONLY, 0644);
1461 	litest_assert_int_ne(fd, -1);
1462 	f = fdopen(fd, "w");
1463 	litest_assert_notnull(f);
1464 	litest_assert_int_ge(fputs(dev->quirk_file, f), 0);
1465 	fclose(f);
1466 
1467 	return safe_strdup(path);
1468 }
1469 
is_quirks_file(const struct dirent *dir)1470 static int is_quirks_file(const struct dirent *dir) {
1471 	return strendswith(dir->d_name, ".quirks");
1472 }
1473 
1474 /**
1475  * Install the quirks from the quirks/ source directory.
1476  */
1477 static void
litest_install_source_quirks(struct list *created_files_list, const char *dirname)1478 litest_install_source_quirks(struct list *created_files_list,
1479 			     const char *dirname)
1480 {
1481 	struct dirent **namelist;
1482 	int ndev;
1483 
1484 	ndev = scandir(LIBINPUT_QUIRKS_SRCDIR,
1485 		       &namelist,
1486 		       is_quirks_file,
1487 		       versionsort);
1488 	litest_assert_int_ge(ndev, 0);
1489 
1490 	for (int idx = 0; idx < ndev; idx++) {
1491 		struct created_file *file;
1492 		char *filename;
1493 		char dest[PATH_MAX];
1494 		char src[PATH_MAX];
1495 
1496 		filename = namelist[idx]->d_name;
1497 		snprintf(src, sizeof(src), "%s/%s",
1498 			 LIBINPUT_QUIRKS_SRCDIR, filename);
1499 		snprintf(dest, sizeof(dest), "%s/%s", dirname, filename);
1500 		file = litest_copy_file(dest, src, NULL, true);
1501 		list_append(created_files_list, &file->link);
1502 		free(namelist[idx]);
1503 	}
1504 	free(namelist);
1505 }
1506 
1507 /**
1508  * Install the quirks from the various litest test devices
1509  */
1510 static void
litest_install_device_quirks(struct list *created_files_list, const char *dirname)1511 litest_install_device_quirks(struct list *created_files_list,
1512 			     const char *dirname)
1513 {
1514 	struct litest_test_device *dev;
1515 
1516 	list_for_each(dev, &devices, node) {
1517 		char *path;
1518 
1519 		path = litest_init_device_quirk_file(dirname, dev);
1520 		if (path) {
1521 			struct created_file *file = zalloc(sizeof(*file));
1522 			file->path = path;
1523 			list_insert(created_files_list, &file->link);
1524 		}
1525 	}
1526 }
1527 
1528 static void
litest_setup_quirks(struct list *created_files_list, enum quirks_setup_mode mode)1529 litest_setup_quirks(struct list *created_files_list,
1530 		    enum quirks_setup_mode mode)
1531 {
1532 	struct created_file *file = NULL;
1533 	const char *dirname;
1534 	char tmpdir[] = "/run/litest-XXXXXX";
1535 
1536 	switch (mode) {
1537 	case QUIRKS_SETUP_USE_SRCDIR:
1538 		dirname = LIBINPUT_QUIRKS_SRCDIR;
1539 		break;
1540 	case QUIRKS_SETUP_ONLY_DEVICE:
1541 		dirname = LIBINPUT_QUIRKS_DIR;
1542 		litest_install_device_quirks(created_files_list, dirname);
1543 		break;
1544 	case QUIRKS_SETUP_FULL:
1545 		litest_assert_notnull(mkdtemp(tmpdir));
1546 		litest_assert_int_ne(chmod(tmpdir, 0755), -1);
1547 		file = zalloc(sizeof *file);
1548 		file->path = safe_strdup(tmpdir);
1549 		dirname = tmpdir;
1550 
1551 		litest_install_source_quirks(created_files_list, dirname);
1552 		litest_install_device_quirks(created_files_list, dirname);
1553 		list_append(created_files_list, &file->link);
1554 		break;
1555 	}
1556 
1557 	setenv("LIBINPUT_QUIRKS_DIR", dirname, 1);
1558 }
1559 
1560 static inline void
mkdir_p(const char *dir)1561 mkdir_p(const char *dir)
1562 {
1563 	char *path, *parent;
1564 	int rc;
1565 
1566 	if (streq(dir, "/"))
1567 		return;
1568 
1569 	path = safe_strdup(dir);
1570 	parent = dirname(path);
1571 
1572 	mkdir_p(parent);
1573 	rc = mkdir(dir, 0755);
1574 
1575 	if (rc == -1 && errno != EEXIST) {
1576 		litest_abort_msg("Failed to create directory %s (%s)\n",
1577 				 dir,
1578 				 strerror(errno));
1579 	}
1580 
1581 	free(path);
1582 }
1583 
1584 static inline void
litest_init_udev_rules(struct list *created_files)1585 litest_init_udev_rules(struct list *created_files)
1586 {
1587 	mkdir_p(UDEV_RULES_D);
1588 
1589 	litest_install_model_quirks(created_files);
1590 	litest_init_all_device_udev_rules(created_files);
1591 	litest_reload_udev_rules();
1592 }
1593 
1594 static inline void
litest_remove_udev_rules(struct list *created_files_list)1595 litest_remove_udev_rules(struct list *created_files_list)
1596 {
1597 	struct created_file *f;
1598 	bool reload_udev;
1599 
1600 	reload_udev = !list_empty(created_files_list);
1601 
1602 	list_for_each_safe(f, created_files_list, link) {
1603 		list_remove(&f->link);
1604 		unlink(f->path);
1605 		rmdir(f->path);
1606 		free(f->path);
1607 		free(f);
1608 	}
1609 
1610 	if (reload_udev)
1611 		litest_reload_udev_rules();
1612 }
1613 
1614 /**
1615  * Creates a uinput device but does not add it to a libinput context
1616  */
1617 struct litest_device *
litest_create(enum litest_device_type which, const char *name_override, struct input_id *id_override, const struct input_absinfo *abs_override, const int *events_override)1618 litest_create(enum litest_device_type which,
1619 	      const char *name_override,
1620 	      struct input_id *id_override,
1621 	      const struct input_absinfo *abs_override,
1622 	      const int *events_override)
1623 {
1624 	struct litest_device *d = NULL;
1625 	struct litest_test_device *dev;
1626 	const char *name;
1627 	const struct input_id *id;
1628 	struct input_absinfo *abs;
1629 	int *events, *e;
1630 	const char *path;
1631 	int fd, rc;
1632 	bool found = false;
1633 	bool create_device = true;
1634 
1635 	list_for_each(dev, &devices, node) {
1636 		if (dev->type == which) {
1637 			found = true;
1638 			break;
1639 		}
1640 	}
1641 
1642 	if (!found)
1643 		ck_abort_msg("Invalid device type %d\n", which);
1644 
1645 	d = zalloc(sizeof(*d));
1646 	d->which = which;
1647 
1648 	/* device has custom create method */
1649 	if (dev->create) {
1650 		create_device = dev->create(d);
1651 		if (abs_override || events_override) {
1652 			litest_abort_msg("Custom create cannot be overridden");
1653 		}
1654 	}
1655 
1656 	abs = merge_absinfo(dev->absinfo, abs_override);
1657 	events = merge_events(dev->events, events_override);
1658 	name = name_override ? name_override : dev->name;
1659 	id = id_override ? id_override : dev->id;
1660 
1661 	if (create_device) {
1662 		d->uinput = litest_create_uinput_device_from_description(name,
1663 									 id,
1664 									 abs,
1665 									 events);
1666 		d->interface = dev->interface;
1667 
1668 		for (e = events; *e != -1; e += 2) {
1669 			unsigned int type = *e,
1670 				     code = *(e + 1);
1671 
1672 			if (type == INPUT_PROP_MAX &&
1673 			    code == INPUT_PROP_SEMI_MT) {
1674 				d->semi_mt.is_semi_mt = true;
1675 				break;
1676 			}
1677 		}
1678 	}
1679 
1680 	free(abs);
1681 	free(events);
1682 
1683 	path = libevdev_uinput_get_devnode(d->uinput);
1684 	litest_assert_ptr_notnull(path);
1685 	fd = open(path, O_RDWR|O_NONBLOCK);
1686 	litest_assert_int_ne(fd, -1);
1687 
1688 	rc = libevdev_new_from_fd(fd, &d->evdev);
1689 	litest_assert_int_eq(rc, 0);
1690 
1691 	return d;
1692 
1693 }
1694 
1695 struct libinput *
litest_create_context(void)1696 litest_create_context(void)
1697 {
1698 	struct libinput *libinput;
1699 	struct litest_context *ctx;
1700 
1701 	ctx = zalloc(sizeof *ctx);
1702 	list_init(&ctx->paths);
1703 
1704 	libinput = libinput_path_create_context(&interface, ctx);
1705 	litest_assert_notnull(libinput);
1706 
1707 	libinput_log_set_handler(libinput, litest_log_handler);
1708 	if (verbose)
1709 		libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1710 
1711 	return libinput;
1712 }
1713 
1714 void
litest_destroy_context(struct libinput *li)1715 litest_destroy_context(struct libinput *li)
1716 {
1717 	struct path *p;
1718 	struct litest_context *ctx;
1719 
1720 
1721 	ctx = libinput_get_user_data(li);
1722 	litest_assert_ptr_notnull(ctx);
1723 	libinput_unref(li);
1724 
1725 	list_for_each_safe(p, &ctx->paths, link) {
1726 		litest_abort_msg("Device paths should be removed by now");
1727 	}
1728 	free(ctx);
1729 }
1730 
1731 void
litest_disable_log_handler(struct libinput *libinput)1732 litest_disable_log_handler(struct libinput *libinput)
1733 {
1734 	libinput_log_set_handler(libinput, NULL);
1735 }
1736 
1737 void
litest_restore_log_handler(struct libinput *libinput)1738 litest_restore_log_handler(struct libinput *libinput)
1739 {
1740 	libinput_log_set_handler(libinput, litest_log_handler);
1741 	if (verbose)
1742 		libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1743 }
1744 
1745 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
1746 static void
litest_bug_log_handler(struct libinput *libinput, enum libinput_log_priority pri, const char *format, va_list args)1747 litest_bug_log_handler(struct libinput *libinput,
1748 		       enum libinput_log_priority pri,
1749 		       const char *format,
1750 		       va_list args)
1751 {
1752 	if (strstr(format, "client bug: ") ||
1753 	    strstr(format, "libinput bug: ") ||
1754 	    strstr(format, "kernel bug: "))
1755 		return;
1756 
1757 	litest_abort_msg("Expected bug statement in log msg, aborting.\n");
1758 }
1759 
1760 void
litest_set_log_handler_bug(struct libinput *libinput)1761 litest_set_log_handler_bug(struct libinput *libinput)
1762 {
1763 	libinput_log_set_handler(libinput, litest_bug_log_handler);
1764 }
1765 
1766 struct litest_device *
litest_add_device_with_overrides(struct libinput *libinput, enum litest_device_type which, const char *name_override, struct input_id *id_override, const struct input_absinfo *abs_override, const int *events_override)1767 litest_add_device_with_overrides(struct libinput *libinput,
1768 				 enum litest_device_type which,
1769 				 const char *name_override,
1770 				 struct input_id *id_override,
1771 				 const struct input_absinfo *abs_override,
1772 				 const int *events_override)
1773 {
1774 	struct udev_device *ud;
1775 	struct litest_device *d;
1776 	const char *path;
1777 
1778 	d = litest_create(which,
1779 			  name_override,
1780 			  id_override,
1781 			  abs_override,
1782 			  events_override);
1783 
1784 	path = libevdev_uinput_get_devnode(d->uinput);
1785 	litest_assert_ptr_notnull(path);
1786 
1787 	d->libinput = libinput;
1788 	d->libinput_device = libinput_path_add_device(d->libinput, path);
1789 	litest_assert_ptr_notnull(d->libinput_device);
1790 	ud = libinput_device_get_udev_device(d->libinput_device);
1791 	d->quirks = quirks_fetch_for_device(quirks_context, ud);
1792 	udev_device_unref(ud);
1793 
1794 	libinput_device_ref(d->libinput_device);
1795 
1796 	if (d->interface) {
1797 		unsigned int code;
1798 
1799 		code = ABS_X;
1800 		if (!libevdev_has_event_code(d->evdev, EV_ABS, code))
1801 			code = ABS_MT_POSITION_X;
1802 		if (libevdev_has_event_code(d->evdev, EV_ABS, code)) {
1803 			d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, code);
1804 			d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, code);
1805 		}
1806 
1807 		code = ABS_Y;
1808 		if (!libevdev_has_event_code(d->evdev, EV_ABS, code))
1809 			code = ABS_MT_POSITION_Y;
1810 		if (libevdev_has_event_code(d->evdev, EV_ABS, code)) {
1811 			d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, code);
1812 			d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, code);
1813 		}
1814 		d->interface->tool_type = BTN_TOOL_PEN;
1815 	}
1816 	return d;
1817 }
1818 
1819 struct litest_device *
litest_add_device(struct libinput *libinput, enum litest_device_type which)1820 litest_add_device(struct libinput *libinput,
1821 		  enum litest_device_type which)
1822 {
1823 	return litest_add_device_with_overrides(libinput,
1824 						which,
1825 						NULL,
1826 						NULL,
1827 						NULL,
1828 						NULL);
1829 }
1830 
1831 struct litest_device *
litest_create_device_with_overrides(enum litest_device_type which, const char *name_override, struct input_id *id_override, const struct input_absinfo *abs_override, const int *events_override)1832 litest_create_device_with_overrides(enum litest_device_type which,
1833 				    const char *name_override,
1834 				    struct input_id *id_override,
1835 				    const struct input_absinfo *abs_override,
1836 				    const int *events_override)
1837 {
1838 	struct litest_device *dev =
1839 		litest_add_device_with_overrides(litest_create_context(),
1840 						 which,
1841 						 name_override,
1842 						 id_override,
1843 						 abs_override,
1844 						 events_override);
1845 	dev->owns_context = true;
1846 	return dev;
1847 }
1848 
1849 struct litest_device *
litest_create_device(enum litest_device_type which)1850 litest_create_device(enum litest_device_type which)
1851 {
1852 	return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL);
1853 }
1854 
1855 static struct udev_monitor *
udev_setup_monitor(void)1856 udev_setup_monitor(void)
1857 {
1858 	struct udev *udev;
1859 	struct udev_monitor *udev_monitor;
1860 	int rc;
1861 
1862 	udev = udev_new();
1863 	litest_assert_notnull(udev);
1864 	udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1865 	litest_assert_notnull(udev_monitor);
1866 	udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
1867 							NULL);
1868 
1869 
1870 	/* remove O_NONBLOCK */
1871 	rc = fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
1872 	litest_assert_int_ne(rc, -1);
1873 	litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor),
1874 			     0);
1875 	udev_unref(udev);
1876 
1877 	return udev_monitor;
1878 }
1879 
1880 static struct udev_device *
udev_wait_for_device_event(struct udev_monitor *udev_monitor, const char *udev_event, const char *syspath)1881 udev_wait_for_device_event(struct udev_monitor *udev_monitor,
1882 			   const char *udev_event,
1883 			   const char *syspath)
1884 {
1885 	struct udev_device *udev_device = NULL;
1886 
1887 	/* blocking, we don't want to continue until udev is ready */
1888 	while (1) {
1889 		const char *udev_syspath = NULL;
1890 		const char *udev_action;
1891 
1892 		udev_device = udev_monitor_receive_device(udev_monitor);
1893 		litest_assert_notnull(udev_device);
1894 		udev_action = udev_device_get_action(udev_device);
1895 		if (!udev_action || !streq(udev_action, udev_event)) {
1896 			udev_device_unref(udev_device);
1897 			continue;
1898 		}
1899 
1900 		udev_syspath = udev_device_get_syspath(udev_device);
1901 		if (udev_syspath && strstartswith(udev_syspath, syspath))
1902 			break;
1903 
1904 		udev_device_unref(udev_device);
1905 	}
1906 
1907 	return udev_device;
1908 }
1909 
1910 void
litest_delete_device(struct litest_device *d)1911 litest_delete_device(struct litest_device *d)
1912 {
1913 
1914 	struct udev_monitor *udev_monitor;
1915 	struct udev_device *udev_device;
1916 	char path[PATH_MAX];
1917 
1918 	if (!d)
1919 		return;
1920 
1921 	udev_monitor = udev_setup_monitor();
1922 	snprintf(path, sizeof(path),
1923 		 "%s/event",
1924 		 libevdev_uinput_get_syspath(d->uinput));
1925 
1926 	litest_assert_int_eq(d->skip_ev_syn, 0);
1927 
1928 	quirks_unref(d->quirks);
1929 
1930 	if (d->libinput_device) {
1931 		libinput_path_remove_device(d->libinput_device);
1932 		libinput_device_unref(d->libinput_device);
1933 	}
1934 	if (d->owns_context) {
1935 		libinput_dispatch(d->libinput);
1936 		litest_destroy_context(d->libinput);
1937 	}
1938 	close(libevdev_get_fd(d->evdev));
1939 	libevdev_free(d->evdev);
1940 	libevdev_uinput_destroy(d->uinput);
1941 	free(d->private);
1942 	memset(d,0, sizeof(*d));
1943 	free(d);
1944 
1945 	udev_device = udev_wait_for_device_event(udev_monitor,
1946 						 "remove",
1947 						 path);
1948 	udev_device_unref(udev_device);
1949 	udev_monitor_unref(udev_monitor);
1950 }
1951 
1952 void
litest_event(struct litest_device *d, unsigned int type, unsigned int code, int value)1953 litest_event(struct litest_device *d, unsigned int type,
1954 	     unsigned int code, int value)
1955 {
1956 	int ret;
1957 
1958 	if (!libevdev_has_event_code(d->evdev, type, code))
1959 		return;
1960 
1961 	if (d->skip_ev_syn && type == EV_SYN && code == SYN_REPORT)
1962 		return;
1963 
1964 	ret = libevdev_uinput_write_event(d->uinput, type, code, value);
1965 	litest_assert_int_eq(ret, 0);
1966 }
1967 
1968 static bool
axis_replacement_value(struct litest_device *d, struct axis_replacement *axes, int32_t evcode, int32_t *value)1969 axis_replacement_value(struct litest_device *d,
1970 		       struct axis_replacement *axes,
1971 		       int32_t evcode,
1972 		       int32_t *value)
1973 {
1974 	struct axis_replacement *axis = axes;
1975 
1976 	if (!axes)
1977 		return false;
1978 
1979 	while (axis->evcode != -1) {
1980 		if (axis->evcode == evcode) {
1981 			switch (evcode) {
1982 			case ABS_MT_SLOT:
1983 			case ABS_MT_TRACKING_ID:
1984 			case ABS_MT_TOOL_TYPE:
1985 				*value = axis->value;
1986 				break;
1987 			default:
1988 				*value = litest_scale(d, evcode, axis->value);
1989 				break;
1990 			}
1991 			return true;
1992 		}
1993 		axis++;
1994 	}
1995 
1996 	return false;
1997 }
1998 
1999 int
litest_auto_assign_value(struct litest_device *d, const struct input_event *ev, int slot, double x, double y, struct axis_replacement *axes, bool touching)2000 litest_auto_assign_value(struct litest_device *d,
2001 			 const struct input_event *ev,
2002 			 int slot, double x, double y,
2003 			 struct axis_replacement *axes,
2004 			 bool touching)
2005 {
2006 	static int tracking_id;
2007 	int value = ev->value;
2008 
2009 	if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2010 		return value;
2011 
2012 	switch (ev->code) {
2013 	case ABS_X:
2014 	case ABS_MT_POSITION_X:
2015 		value = litest_scale(d, ABS_X, x);
2016 		break;
2017 	case ABS_Y:
2018 	case ABS_MT_POSITION_Y:
2019 		value = litest_scale(d, ABS_Y, y);
2020 		break;
2021 	case ABS_MT_TRACKING_ID:
2022 		value = ++tracking_id;
2023 		break;
2024 	case ABS_MT_SLOT:
2025 		value = slot;
2026 		break;
2027 	case ABS_MT_DISTANCE:
2028 		value = touching ? 0 : 1;
2029 		break;
2030 	case ABS_MT_TOOL_TYPE:
2031 		if (!axis_replacement_value(d, axes, ev->code, &value))
2032 			value = MT_TOOL_FINGER;
2033 		break;
2034 	default:
2035 		if (!axis_replacement_value(d, axes, ev->code, &value) &&
2036 		    d->interface->get_axis_default) {
2037 			int error = d->interface->get_axis_default(d,
2038 								   ev->code,
2039 								   &value);
2040 			if (error) {
2041 				litest_abort_msg("Failed to get default axis value for %s (%d)\n",
2042 						 libevdev_event_code_get_name(EV_ABS, ev->code),
2043 						 ev->code);
2044 			}
2045 		}
2046 		break;
2047 	}
2048 
2049 	return value;
2050 }
2051 
2052 static void
send_btntool(struct litest_device *d, bool hover)2053 send_btntool(struct litest_device *d, bool hover)
2054 {
2055 	litest_event(d, EV_KEY, BTN_TOUCH, d->ntouches_down != 0 && !hover);
2056 	litest_event(d, EV_KEY, BTN_TOOL_FINGER, d->ntouches_down == 1);
2057 	litest_event(d, EV_KEY, BTN_TOOL_DOUBLETAP, d->ntouches_down == 2);
2058 	litest_event(d, EV_KEY, BTN_TOOL_TRIPLETAP, d->ntouches_down == 3);
2059 	litest_event(d, EV_KEY, BTN_TOOL_QUADTAP, d->ntouches_down == 4);
2060 	litest_event(d, EV_KEY, BTN_TOOL_QUINTTAP, d->ntouches_down == 5);
2061 }
2062 
2063 static void
slot_start(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching, bool filter_abs_xy)2064 slot_start(struct litest_device *d,
2065 	   unsigned int slot,
2066 	   double x,
2067 	   double y,
2068 	   struct axis_replacement *axes,
2069 	   bool touching,
2070 	   bool filter_abs_xy)
2071 {
2072 	struct input_event *ev;
2073 
2074 	litest_assert_int_ge(d->ntouches_down, 0);
2075 	d->ntouches_down++;
2076 
2077 	send_btntool(d, !touching);
2078 
2079 	/* If the test device overrides touch_down and says it didn't
2080 	 * handle the event, let's continue normally */
2081 	if (d->interface->touch_down &&
2082 	    d->interface->touch_down(d, slot, x, y))
2083 	    return;
2084 
2085 	for (ev = d->interface->touch_down_events;
2086 	     ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2087 	     ev++) {
2088 		int value = litest_auto_assign_value(d,
2089 						     ev,
2090 						     slot,
2091 						     x,
2092 						     y,
2093 						     axes,
2094 						     touching);
2095 		if (value == LITEST_AUTO_ASSIGN)
2096 			continue;
2097 
2098 		if (filter_abs_xy && ev->type == EV_ABS &&
2099 		    (ev->code == ABS_X || ev->code == ABS_Y))
2100 			continue;
2101 
2102 		litest_event(d, ev->type, ev->code, value);
2103 	}
2104 }
2105 
2106 static void
slot_move(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching, bool filter_abs_xy)2107 slot_move(struct litest_device *d,
2108 	  unsigned int slot,
2109 	  double x,
2110 	  double y,
2111 	  struct axis_replacement *axes,
2112 	  bool touching,
2113 	  bool filter_abs_xy)
2114 {
2115 	struct input_event *ev;
2116 
2117 	if (d->interface->touch_move &&
2118 	    d->interface->touch_move(d, slot, x, y))
2119 		return;
2120 
2121 	for (ev = d->interface->touch_move_events;
2122 	     ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2123 	     ev++) {
2124 		int value = litest_auto_assign_value(d,
2125 						     ev,
2126 						     slot,
2127 						     x,
2128 						     y,
2129 						     axes,
2130 						     touching);
2131 		if (value == LITEST_AUTO_ASSIGN)
2132 			continue;
2133 
2134 		if (filter_abs_xy && ev->type == EV_ABS &&
2135 		    (ev->code == ABS_X || ev->code == ABS_Y))
2136 			continue;
2137 
2138 		litest_event(d, ev->type, ev->code, value);
2139 	}
2140 }
2141 
2142 static void
touch_up(struct litest_device *d, unsigned int slot)2143 touch_up(struct litest_device *d, unsigned int slot)
2144 {
2145 	struct input_event *ev;
2146 	struct input_event up[] = {
2147 		{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
2148 		{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
2149 		{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
2150 		{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 0 },
2151 		{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 0 },
2152 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2153 		{ .type = -1, .code = -1 }
2154 	};
2155 
2156 	litest_assert_int_gt(d->ntouches_down, 0);
2157 	d->ntouches_down--;
2158 
2159 	send_btntool(d, false);
2160 
2161 	if (d->interface->touch_up &&
2162 	    d->interface->touch_up(d, slot)) {
2163 		return;
2164 	} else if (d->interface->touch_up_events) {
2165 		ev = d->interface->touch_up_events;
2166 	} else
2167 		ev = up;
2168 
2169 	for ( /* */;
2170 	     ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2171 	     ev++) {
2172 		int value = litest_auto_assign_value(d,
2173 						     ev,
2174 						     slot,
2175 						     0,
2176 						     0,
2177 						     NULL,
2178 						     false);
2179 		litest_event(d, ev->type, ev->code, value);
2180 	}
2181 }
2182 
2183 static void
litest_slot_start(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching)2184 litest_slot_start(struct litest_device *d,
2185 		  unsigned int slot,
2186 		  double x,
2187 		  double y,
2188 		  struct axis_replacement *axes,
2189 		  bool touching)
2190 {
2191 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
2192 	bool filter_abs_xy = false;
2193 
2194 	if (!d->semi_mt.is_semi_mt) {
2195 		slot_start(d, slot, x, y, axes, touching, filter_abs_xy);
2196 		return;
2197 	}
2198 
2199 	if (d->ntouches_down >= 2 || slot > 1)
2200 		return;
2201 
2202 	slot = d->ntouches_down;
2203 
2204 	if (d->ntouches_down == 0) {
2205 		l = x;
2206 		t = y;
2207 	} else {
2208 		int other = (slot + 1) % 2;
2209 		l = min(x, d->semi_mt.touches[other].x);
2210 		t = min(y, d->semi_mt.touches[other].y);
2211 		r = max(x, d->semi_mt.touches[other].x);
2212 		b = max(y, d->semi_mt.touches[other].y);
2213 	}
2214 
2215 	litest_push_event_frame(d);
2216 	if (d->ntouches_down == 0)
2217 		slot_start(d, 0, l, t, axes, touching, filter_abs_xy);
2218 	else
2219 		slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
2220 
2221 	if (slot == 1) {
2222 		filter_abs_xy = true;
2223 		slot_start(d, 1, r, b, axes, touching, filter_abs_xy);
2224 	}
2225 
2226 	litest_pop_event_frame(d);
2227 
2228 	d->semi_mt.touches[slot].x = x;
2229 	d->semi_mt.touches[slot].y = y;
2230 }
2231 
2232 void
litest_touch_sequence(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, int steps)2233 litest_touch_sequence(struct litest_device *d,
2234 		      unsigned int slot,
2235 		      double x_from,
2236 		      double y_from,
2237 		      double x_to,
2238 		      double y_to,
2239 		      int steps)
2240 {
2241 	litest_touch_down(d, slot, x_from, y_from);
2242 	litest_touch_move_to(d, slot,
2243 			     x_from, y_from,
2244 			     x_to, y_to,
2245 			     steps);
2246 	litest_touch_up(d, slot);
2247 }
2248 
2249 void
litest_touch_down(struct litest_device *d, unsigned int slot, double x, double y)2250 litest_touch_down(struct litest_device *d,
2251 		  unsigned int slot,
2252 		  double x,
2253 		  double y)
2254 {
2255 	litest_slot_start(d, slot, x, y, NULL, true);
2256 }
2257 
2258 void
litest_touch_down_extended(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes)2259 litest_touch_down_extended(struct litest_device *d,
2260 			   unsigned int slot,
2261 			   double x,
2262 			   double y,
2263 			   struct axis_replacement *axes)
2264 {
2265 	litest_slot_start(d, slot, x, y, axes, true);
2266 }
2267 
2268 static void
litest_slot_move(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching)2269 litest_slot_move(struct litest_device *d,
2270 		 unsigned int slot,
2271 		 double x,
2272 		 double y,
2273 		 struct axis_replacement *axes,
2274 		 bool touching)
2275 {
2276 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
2277 	bool filter_abs_xy = false;
2278 
2279 	if (!d->semi_mt.is_semi_mt) {
2280 		slot_move(d, slot, x, y, axes, touching, filter_abs_xy);
2281 		return;
2282 	}
2283 
2284 	if (d->ntouches_down > 2 || slot > 1)
2285 		return;
2286 
2287 	if (d->ntouches_down == 1) {
2288 		l = x;
2289 		t = y;
2290 	} else {
2291 		int other = (slot + 1) % 2;
2292 		l = min(x, d->semi_mt.touches[other].x);
2293 		t = min(y, d->semi_mt.touches[other].y);
2294 		r = max(x, d->semi_mt.touches[other].x);
2295 		b = max(y, d->semi_mt.touches[other].y);
2296 	}
2297 
2298 	litest_push_event_frame(d);
2299 	slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
2300 
2301 	if (d->ntouches_down == 2) {
2302 		filter_abs_xy = true;
2303 		slot_move(d, 1, r, b, axes, touching, filter_abs_xy);
2304 	}
2305 
2306 	litest_pop_event_frame(d);
2307 
2308 	d->semi_mt.touches[slot].x = x;
2309 	d->semi_mt.touches[slot].y = y;
2310 }
2311 
2312 void
litest_touch_up(struct litest_device *d, unsigned int slot)2313 litest_touch_up(struct litest_device *d, unsigned int slot)
2314 {
2315 	if (!d->semi_mt.is_semi_mt) {
2316 		touch_up(d, slot);
2317 		return;
2318 	}
2319 
2320 	if (d->ntouches_down > 2 || slot > 1)
2321 		return;
2322 
2323 	litest_push_event_frame(d);
2324 	touch_up(d, d->ntouches_down - 1);
2325 
2326 	/* if we have one finger left, send x/y coords for that finger left.
2327 	   this is likely to happen with a real touchpad */
2328 	if (d->ntouches_down == 1) {
2329 		bool touching = true;
2330 		bool filter_abs_xy = false;
2331 
2332 		int other = (slot + 1) % 2;
2333 		slot_move(d,
2334 			  0,
2335 			  d->semi_mt.touches[other].x,
2336 			  d->semi_mt.touches[other].y,
2337 			  NULL,
2338 			  touching,
2339 			  filter_abs_xy);
2340 	}
2341 
2342 	litest_pop_event_frame(d);
2343 }
2344 
2345 void
litest_touch_move(struct litest_device *d, unsigned int slot, double x, double y)2346 litest_touch_move(struct litest_device *d,
2347 		  unsigned int slot,
2348 		  double x,
2349 		  double y)
2350 {
2351 	litest_slot_move(d, slot, x, y, NULL, true);
2352 }
2353 
2354 void
litest_touch_move_extended(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes)2355 litest_touch_move_extended(struct litest_device *d,
2356 			   unsigned int slot,
2357 			   double x,
2358 			   double y,
2359 			   struct axis_replacement *axes)
2360 {
2361 	litest_slot_move(d, slot, x, y, axes, true);
2362 }
2363 
2364 void
litest_touch_move_to(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, int steps)2365 litest_touch_move_to(struct litest_device *d,
2366 		     unsigned int slot,
2367 		     double x_from, double y_from,
2368 		     double x_to, double y_to,
2369 		     int steps)
2370 {
2371 	litest_touch_move_to_extended(d, slot,
2372 				      x_from, y_from,
2373 				      x_to, y_to,
2374 				      NULL,
2375 				      steps);
2376 }
2377 
2378 void
litest_touch_move_to_extended(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, struct axis_replacement *axes, int steps)2379 litest_touch_move_to_extended(struct litest_device *d,
2380 			      unsigned int slot,
2381 			      double x_from, double y_from,
2382 			      double x_to, double y_to,
2383 			      struct axis_replacement *axes,
2384 			      int steps)
2385 {
2386 	int sleep_ms = 10;
2387 
2388 	for (int i = 1; i < steps; i++) {
2389 		litest_touch_move_extended(d, slot,
2390 					   x_from + (x_to - x_from)/steps * i,
2391 					   y_from + (y_to - y_from)/steps * i,
2392 					   axes);
2393 		libinput_dispatch(d->libinput);
2394 		msleep(sleep_ms);
2395 		libinput_dispatch(d->libinput);
2396 	}
2397 	litest_touch_move_extended(d, slot, x_to, y_to, axes);
2398 }
2399 
2400 static int
auto_assign_tablet_value(struct litest_device *d, const struct input_event *ev, int x, int y, struct axis_replacement *axes)2401 auto_assign_tablet_value(struct litest_device *d,
2402 			 const struct input_event *ev,
2403 			 int x, int y,
2404 			 struct axis_replacement *axes)
2405 {
2406 	static int tracking_id;
2407 	int value = ev->value;
2408 
2409 	if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2410 		return value;
2411 
2412 	switch (ev->code) {
2413 	case ABS_MT_TRACKING_ID:
2414 		value = ++tracking_id;
2415 		break;
2416 	case ABS_X:
2417 	case ABS_MT_POSITION_X:
2418 		value = litest_scale(d, ABS_X, x);
2419 		break;
2420 	case ABS_Y:
2421 	case ABS_MT_POSITION_Y:
2422 		value = litest_scale(d, ABS_Y, y);
2423 		break;
2424 	default:
2425 		if (!axis_replacement_value(d, axes, ev->code, &value) &&
2426 		    d->interface->get_axis_default) {
2427 			int error = d->interface->get_axis_default(d, ev->code, &value);
2428 			if (error) {
2429 				litest_abort_msg("Failed to get default axis value for %s (%d)\n",
2430 						 libevdev_event_code_get_name(EV_ABS, ev->code),
2431 						 ev->code);
2432 			}
2433 		}
2434 		break;
2435 	}
2436 
2437 	return value;
2438 }
2439 
2440 static int
tablet_ignore_event(const struct input_event *ev, int value)2441 tablet_ignore_event(const struct input_event *ev, int value)
2442 {
2443 	return value == -1 && (ev->code == ABS_PRESSURE || ev->code == ABS_DISTANCE);
2444 }
2445 
2446 void
litest_tablet_set_tool_type(struct litest_device *d, unsigned int code)2447 litest_tablet_set_tool_type(struct litest_device *d, unsigned int code)
2448 {
2449 	switch (code) {
2450 	case BTN_TOOL_PEN:
2451 	case BTN_TOOL_RUBBER:
2452 	case BTN_TOOL_BRUSH:
2453 	case BTN_TOOL_PENCIL:
2454 	case BTN_TOOL_AIRBRUSH:
2455 	case BTN_TOOL_MOUSE:
2456 	case BTN_TOOL_LENS:
2457 		break;
2458 	default:
2459 		abort();
2460 	}
2461 
2462 	d->interface->tool_type = code;
2463 }
2464 
2465 static void
litest_tool_event(struct litest_device *d, int value)2466 litest_tool_event(struct litest_device *d, int value)
2467 {
2468 	unsigned int tool = d->interface->tool_type;
2469 
2470 	litest_event(d, EV_KEY, tool, value);
2471 }
2472 
2473 void
litest_tablet_proximity_in(struct litest_device *d, double x, double y, struct axis_replacement *axes)2474 litest_tablet_proximity_in(struct litest_device *d,
2475 			   double x, double y,
2476 			   struct axis_replacement *axes)
2477 {
2478 	struct input_event *ev;
2479 
2480 	/* If the test device overrides proximity_in and says it didn't
2481 	 * handle the event, let's continue normally */
2482 	if (d->interface->tablet_proximity_in &&
2483 	    d->interface->tablet_proximity_in(d, d->interface->tool_type, &x, &y, axes))
2484 		return;
2485 
2486 	ev = d->interface->tablet_proximity_in_events;
2487 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2488 		int value;
2489 
2490 		switch (evbit(ev->type, ev->code)) {
2491 		case evbit(EV_KEY, LITEST_BTN_TOOL_AUTO):
2492 			litest_tool_event(d, ev->value);
2493 			break;
2494 		default:
2495 			value = auto_assign_tablet_value(d, ev, x, y, axes);
2496 			if (!tablet_ignore_event(ev, value))
2497 				litest_event(d, ev->type, ev->code, value);
2498 		}
2499 		ev++;
2500 	}
2501 }
2502 
2503 void
litest_tablet_proximity_out(struct litest_device *d)2504 litest_tablet_proximity_out(struct litest_device *d)
2505 {
2506 	struct input_event *ev;
2507 
2508 	/* If the test device overrides proximity_out and says it didn't
2509 	 * handle the event, let's continue normally */
2510 	if (d->interface->tablet_proximity_out &&
2511 	    d->interface->tablet_proximity_out(d, d->interface->tool_type))
2512 		return;
2513 
2514 	ev = d->interface->tablet_proximity_out_events;
2515 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2516 		int value;
2517 
2518 		switch (evbit(ev->type, ev->code)) {
2519 		case evbit(EV_KEY, LITEST_BTN_TOOL_AUTO):
2520 			litest_tool_event(d, ev->value);
2521 			break;
2522 		default:
2523 			value = auto_assign_tablet_value(d, ev, -1, -1, NULL);
2524 			if (!tablet_ignore_event(ev, value))
2525 				litest_event(d, ev->type, ev->code, value);
2526 			break;
2527 		}
2528 		ev++;
2529 	}
2530 }
2531 
2532 void
litest_tablet_motion(struct litest_device *d, double x, double y, struct axis_replacement *axes)2533 litest_tablet_motion(struct litest_device *d,
2534 		     double x, double y,
2535 		     struct axis_replacement *axes)
2536 {
2537 	struct input_event *ev;
2538 
2539 	/* If the test device overrides proximity_out and says it didn't
2540 	 * handle the event, let's continue normally */
2541 	if (d->interface->tablet_motion &&
2542 	    d->interface->tablet_motion(d, &x, &y, axes))
2543 		return;
2544 
2545 	ev = d->interface->tablet_motion_events;
2546 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2547 		int value = auto_assign_tablet_value(d, ev, x, y, axes);
2548 		if (!tablet_ignore_event(ev, value))
2549 			litest_event(d, ev->type, ev->code, value);
2550 		ev++;
2551 	}
2552 }
2553 
2554 void
litest_tablet_tip_down(struct litest_device *d, double x, double y, struct axis_replacement *axes)2555 litest_tablet_tip_down(struct litest_device *d,
2556 		       double x, double y,
2557 		       struct axis_replacement *axes)
2558 {
2559 	/* If the test device overrides tip_down and says it didn't
2560 	 * handle the event, let's continue normally */
2561 	if (d->interface->tablet_tip_down &&
2562 	    d->interface->tablet_tip_down(d, &x, &y, axes))
2563 		return;
2564 
2565 	litest_event(d, EV_KEY, BTN_TOUCH, 1);
2566 	litest_tablet_motion(d, x, y, axes);
2567 }
2568 
2569 void
litest_tablet_tip_up(struct litest_device *d, double x, double y, struct axis_replacement *axes)2570 litest_tablet_tip_up(struct litest_device *d,
2571 		     double x, double y,
2572 		     struct axis_replacement *axes)
2573 {
2574 	/* If the test device overrides tip_down and says it didn't
2575 	 * handle the event, let's continue normally */
2576 	if (d->interface->tablet_tip_up &&
2577 	    d->interface->tablet_tip_up(d, &x, &y, axes))
2578 		return;
2579 
2580 	litest_event(d, EV_KEY, BTN_TOUCH, 0);
2581 	litest_tablet_motion(d, x, y, axes);
2582 }
2583 
2584 void
litest_touch_move_two_touches(struct litest_device *d, double x0, double y0, double x1, double y1, double dx, double dy, int steps)2585 litest_touch_move_two_touches(struct litest_device *d,
2586 			      double x0, double y0,
2587 			      double x1, double y1,
2588 			      double dx, double dy,
2589 			      int steps)
2590 {
2591 	int sleep_ms = 10;
2592 
2593 	for (int i = 1; i < steps; i++) {
2594 		litest_push_event_frame(d);
2595 		litest_touch_move(d, 0, x0 + dx / steps * i,
2596 					y0 + dy / steps * i);
2597 		litest_touch_move(d, 1, x1 + dx / steps * i,
2598 					y1 + dy / steps * i);
2599 		litest_pop_event_frame(d);
2600 		libinput_dispatch(d->libinput);
2601 		msleep(sleep_ms);
2602 		libinput_dispatch(d->libinput);
2603 	}
2604 	litest_push_event_frame(d);
2605 	litest_touch_move(d, 0, x0 + dx, y0 + dy);
2606 	litest_touch_move(d, 1, x1 + dx, y1 + dy);
2607 	litest_pop_event_frame(d);
2608 }
2609 
2610 void
litest_touch_move_three_touches(struct litest_device *d, double x0, double y0, double x1, double y1, double x2, double y2, double dx, double dy, int steps)2611 litest_touch_move_three_touches(struct litest_device *d,
2612 				double x0, double y0,
2613 				double x1, double y1,
2614 				double x2, double y2,
2615 				double dx, double dy,
2616 				int steps)
2617 {
2618 	int sleep_ms = 10;
2619 
2620 	for (int i = 1; i <= steps; i++) {
2621 		double step_x = dx / steps * i;
2622 		double step_y = dy / steps * i;
2623 
2624 		litest_push_event_frame(d);
2625 		litest_touch_move(d, 0, x0 + step_x, y0 + step_y);
2626 		litest_touch_move(d, 1, x1 + step_x, y1 + step_y);
2627 		litest_touch_move(d, 2, x2 + step_x, y2 + step_y);
2628 		litest_pop_event_frame(d);
2629 
2630 		libinput_dispatch(d->libinput);
2631 		msleep(sleep_ms);
2632 	}
2633 	libinput_dispatch(d->libinput);
2634 }
2635 
2636 void
litest_hover_start(struct litest_device *d, unsigned int slot, double x, double y)2637 litest_hover_start(struct litest_device *d,
2638 		   unsigned int slot,
2639 		   double x,
2640 		   double y)
2641 {
2642 	struct axis_replacement axes[] = {
2643 		{ABS_MT_PRESSURE, 0 },
2644 		{ABS_PRESSURE, 0 },
2645 		{-1, -1 },
2646 	};
2647 
2648 	litest_slot_start(d, slot, x, y, axes, 0);
2649 }
2650 
2651 void
litest_hover_end(struct litest_device *d, unsigned int slot)2652 litest_hover_end(struct litest_device *d, unsigned int slot)
2653 {
2654 	struct input_event *ev;
2655 	struct input_event up[] = {
2656 		{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
2657 		{ .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 },
2658 		{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
2659 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2660 		{ .type = -1, .code = -1 }
2661 	};
2662 
2663 	litest_assert_int_gt(d->ntouches_down, 0);
2664 	d->ntouches_down--;
2665 
2666 	send_btntool(d, true);
2667 
2668 	if (d->interface->touch_up) {
2669 		d->interface->touch_up(d, slot);
2670 		return;
2671 	} else if (d->interface->touch_up_events) {
2672 		ev = d->interface->touch_up_events;
2673 	} else
2674 		ev = up;
2675 
2676 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2677 		int value = litest_auto_assign_value(d, ev, slot, 0, 0, NULL, false);
2678 		litest_event(d, ev->type, ev->code, value);
2679 		ev++;
2680 	}
2681 }
2682 
2683 void
litest_hover_move(struct litest_device *d, unsigned int slot, double x, double y)2684 litest_hover_move(struct litest_device *d, unsigned int slot,
2685 		  double x, double y)
2686 {
2687 	struct axis_replacement axes[] = {
2688 		{ABS_MT_PRESSURE, 0 },
2689 		{ABS_PRESSURE, 0 },
2690 		{-1, -1 },
2691 	};
2692 
2693 	litest_slot_move(d, slot, x, y, axes, false);
2694 }
2695 
2696 void
litest_hover_move_to(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, int steps)2697 litest_hover_move_to(struct litest_device *d,
2698 		     unsigned int slot,
2699 		     double x_from, double y_from,
2700 		     double x_to, double y_to,
2701 		     int steps)
2702 {
2703 	int sleep_ms = 10;
2704 
2705 	for (int i = 0; i < steps - 1; i++) {
2706 		litest_hover_move(d, slot,
2707 				  x_from + (x_to - x_from)/steps * i,
2708 				  y_from + (y_to - y_from)/steps * i);
2709 		libinput_dispatch(d->libinput);
2710 		msleep(sleep_ms);
2711 		libinput_dispatch(d->libinput);
2712 	}
2713 	litest_hover_move(d, slot, x_to, y_to);
2714 }
2715 
2716 void
litest_hover_move_two_touches(struct litest_device *d, double x0, double y0, double x1, double y1, double dx, double dy, int steps)2717 litest_hover_move_two_touches(struct litest_device *d,
2718 			      double x0, double y0,
2719 			      double x1, double y1,
2720 			      double dx, double dy,
2721 			      int steps)
2722 {
2723 	int sleep_ms = 10;
2724 
2725 	for (int i = 0; i < steps - 1; i++) {
2726 		litest_push_event_frame(d);
2727 		litest_hover_move(d, 0, x0 + dx / steps * i,
2728 					y0 + dy / steps * i);
2729 		litest_hover_move(d, 1, x1 + dx / steps * i,
2730 					y1 + dy / steps * i);
2731 		litest_pop_event_frame(d);
2732 		libinput_dispatch(d->libinput);
2733 		msleep(sleep_ms);
2734 		libinput_dispatch(d->libinput);
2735 	}
2736 	litest_push_event_frame(d);
2737 	litest_hover_move(d, 0, x0 + dx, y0 + dy);
2738 	litest_hover_move(d, 1, x1 + dx, y1 + dy);
2739 	litest_pop_event_frame(d);
2740 }
2741 
2742 void
litest_button_click(struct litest_device *d, unsigned int button, bool is_press)2743 litest_button_click(struct litest_device *d,
2744 		    unsigned int button,
2745 		    bool is_press)
2746 {
2747 	struct input_event click[] = {
2748 		{ .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
2749 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2750 	};
2751 
2752 	ARRAY_FOR_EACH(click, ev)
2753 		litest_event(d, ev->type, ev->code, ev->value);
2754 }
2755 
2756 void
litest_button_click_debounced(struct litest_device *d, struct libinput *li, unsigned int button, bool is_press)2757 litest_button_click_debounced(struct litest_device *d,
2758 			      struct libinput *li,
2759 			      unsigned int button,
2760 			      bool is_press)
2761 {
2762 	litest_button_click(d, button, is_press);
2763 
2764 	libinput_dispatch(li);
2765 	litest_timeout_debounce();
2766 	libinput_dispatch(li);
2767 }
2768 
2769 void
litest_button_scroll(struct litest_device *dev, unsigned int button, double dx, double dy)2770 litest_button_scroll(struct litest_device *dev,
2771 		     unsigned int button,
2772 		     double dx, double dy)
2773 {
2774 	struct libinput *li = dev->libinput;
2775 
2776 	litest_button_click_debounced(dev, li, button, 1);
2777 
2778 	libinput_dispatch(li);
2779 	litest_timeout_buttonscroll();
2780 	libinput_dispatch(li);
2781 
2782 	litest_event(dev, EV_REL, REL_X, dx);
2783 	litest_event(dev, EV_REL, REL_Y, dy);
2784 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2785 
2786 	litest_button_click_debounced(dev, li, button, 0);
2787 
2788 	libinput_dispatch(li);
2789 }
2790 
2791 void
litest_button_scroll_locked(struct litest_device *dev, unsigned int button, double dx, double dy)2792 litest_button_scroll_locked(struct litest_device *dev,
2793 			    unsigned int button,
2794 			    double dx, double dy)
2795 {
2796 	struct libinput *li = dev->libinput;
2797 
2798 	litest_button_click_debounced(dev, li, button, 1);
2799 	litest_button_click_debounced(dev, li, button, 0);
2800 
2801 	libinput_dispatch(li);
2802 	litest_timeout_buttonscroll();
2803 	libinput_dispatch(li);
2804 
2805 	litest_event(dev, EV_REL, REL_X, dx);
2806 	litest_event(dev, EV_REL, REL_Y, dy);
2807 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2808 
2809 	libinput_dispatch(li);
2810 }
2811 
2812 void
litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)2813 litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
2814 {
2815 	struct input_event click[] = {
2816 		{ .type = EV_KEY, .code = key, .value = is_press ? 1 : 0 },
2817 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2818 	};
2819 
2820 	ARRAY_FOR_EACH(click, ev)
2821 		litest_event(d, ev->type, ev->code, ev->value);
2822 }
2823 
2824 void
litest_switch_action(struct litest_device *dev, enum libinput_switch sw, enum libinput_switch_state state)2825 litest_switch_action(struct litest_device *dev,
2826 		     enum libinput_switch sw,
2827 		     enum libinput_switch_state state)
2828 {
2829 	unsigned int code;
2830 
2831 	switch (sw) {
2832 	case LIBINPUT_SWITCH_LID:
2833 		code = SW_LID;
2834 		break;
2835 	case LIBINPUT_SWITCH_TABLET_MODE:
2836 		code = SW_TABLET_MODE;
2837 		break;
2838 	default:
2839 		litest_abort_msg("Invalid switch %d", sw);
2840 		break;
2841 	}
2842 	litest_event(dev, EV_SW, code, state);
2843 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2844 }
2845 
2846 static int
litest_scale_axis(const struct litest_device *d, unsigned int axis, double val)2847 litest_scale_axis(const struct litest_device *d,
2848 		  unsigned int axis,
2849 		  double val)
2850 {
2851 	const struct input_absinfo *abs;
2852 
2853 	litest_assert_double_ge(val, 0.0);
2854 	/* major/minor must be able to beyond 100% for large fingers */
2855 	if (axis != ABS_MT_TOUCH_MAJOR &&
2856 	    axis != ABS_MT_TOUCH_MINOR) {
2857 		litest_assert_double_le(val, 100.0);
2858 	}
2859 
2860 	abs = libevdev_get_abs_info(d->evdev, axis);
2861 	litest_assert_notnull(abs);
2862 
2863 	return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum;
2864 }
2865 
2866 static inline int
litest_scale_range(int min, int max, double val)2867 litest_scale_range(int min, int max, double val)
2868 {
2869 	litest_assert_int_ge((int)val, 0);
2870 	litest_assert_int_le((int)val, 100);
2871 
2872 	return (max - min) * val/100.0 + min;
2873 }
2874 
2875 int
litest_scale(const struct litest_device *d, unsigned int axis, double val)2876 litest_scale(const struct litest_device *d, unsigned int axis, double val)
2877 {
2878 	int min, max;
2879 
2880 	litest_assert_double_ge(val, 0.0);
2881 	/* major/minor must be able to beyond 100% for large fingers */
2882 	if (axis != ABS_MT_TOUCH_MAJOR &&
2883 	    axis != ABS_MT_TOUCH_MINOR)
2884 		litest_assert_double_le(val, 100.0);
2885 
2886 	if (axis <= ABS_Y) {
2887 		min = d->interface->min[axis];
2888 		max = d->interface->max[axis];
2889 
2890 		return litest_scale_range(min, max, val);
2891 	} else {
2892 		return litest_scale_axis(d, axis, val);
2893 	}
2894 }
2895 
2896 static inline int
auto_assign_pad_value(struct litest_device *dev, struct input_event *ev, double value)2897 auto_assign_pad_value(struct litest_device *dev,
2898 		      struct input_event *ev,
2899 		      double value)
2900 {
2901 	const struct input_absinfo *abs;
2902 
2903 	if (ev->value != LITEST_AUTO_ASSIGN ||
2904 	    ev->type != EV_ABS)
2905 		return value;
2906 
2907 	abs = libevdev_get_abs_info(dev->evdev, ev->code);
2908 	litest_assert_notnull(abs);
2909 
2910 	if (ev->code == ABS_RX || ev->code == ABS_RY) {
2911 		double min = abs->minimum != 0 ? log2(abs->minimum) : 0,
2912 		       max = abs->maximum != 0 ? log2(abs->maximum) : 0;
2913 
2914 		/* Value 0 is reserved for finger up, so a value of 0% is
2915 		 * actually 1 */
2916 		if (value == 0.0) {
2917 			return 1;
2918 		} else {
2919 			value = litest_scale_range(min, max, value);
2920 			return pow(2, value);
2921 		}
2922 	} else {
2923 		return litest_scale_range(abs->minimum, abs->maximum, value);
2924 	}
2925 }
2926 
2927 void
litest_pad_ring_start(struct litest_device *d, double value)2928 litest_pad_ring_start(struct litest_device *d, double value)
2929 {
2930 	struct input_event *ev;
2931 
2932 	ev = d->interface->pad_ring_start_events;
2933 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2934 		value = auto_assign_pad_value(d, ev, value);
2935 		litest_event(d, ev->type, ev->code, value);
2936 		ev++;
2937 	}
2938 }
2939 
2940 void
litest_pad_ring_change(struct litest_device *d, double value)2941 litest_pad_ring_change(struct litest_device *d, double value)
2942 {
2943 	struct input_event *ev;
2944 
2945 	ev = d->interface->pad_ring_change_events;
2946 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2947 		value = auto_assign_pad_value(d, ev, value);
2948 		litest_event(d, ev->type, ev->code, value);
2949 		ev++;
2950 	}
2951 }
2952 
2953 void
litest_pad_ring_end(struct litest_device *d)2954 litest_pad_ring_end(struct litest_device *d)
2955 {
2956 	struct input_event *ev;
2957 
2958 	ev = d->interface->pad_ring_end_events;
2959 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2960 		litest_event(d, ev->type, ev->code, ev->value);
2961 		ev++;
2962 	}
2963 }
2964 
2965 void
litest_pad_strip_start(struct litest_device *d, double value)2966 litest_pad_strip_start(struct litest_device *d, double value)
2967 {
2968 	struct input_event *ev;
2969 
2970 	ev = d->interface->pad_strip_start_events;
2971 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2972 		value = auto_assign_pad_value(d, ev, value);
2973 		litest_event(d, ev->type, ev->code, value);
2974 		ev++;
2975 	}
2976 }
2977 
2978 void
litest_pad_strip_change(struct litest_device *d, double value)2979 litest_pad_strip_change(struct litest_device *d, double value)
2980 {
2981 	struct input_event *ev;
2982 
2983 	ev = d->interface->pad_strip_change_events;
2984 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2985 		value = auto_assign_pad_value(d, ev, value);
2986 		litest_event(d, ev->type, ev->code, value);
2987 		ev++;
2988 	}
2989 }
2990 
2991 void
litest_pad_strip_end(struct litest_device *d)2992 litest_pad_strip_end(struct litest_device *d)
2993 {
2994 	struct input_event *ev;
2995 
2996 	ev = d->interface->pad_strip_end_events;
2997 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2998 		litest_event(d, ev->type, ev->code, ev->value);
2999 		ev++;
3000 	}
3001 }
3002 
3003 void
litest_wait_for_event(struct libinput *li)3004 litest_wait_for_event(struct libinput *li)
3005 {
3006 	return litest_wait_for_event_of_type(li, -1);
3007 }
3008 
3009 void
litest_wait_for_event_of_type(struct libinput *li, ...)3010 litest_wait_for_event_of_type(struct libinput *li, ...)
3011 {
3012 	va_list args;
3013 	enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE};
3014 	size_t ntypes = 0;
3015 	enum libinput_event_type type;
3016 	struct pollfd fds;
3017 
3018 	va_start(args, li);
3019 	type = va_arg(args, int);
3020 	while ((int)type != -1) {
3021 		litest_assert_int_gt(type, 0U);
3022 		litest_assert_int_lt(ntypes, ARRAY_LENGTH(types));
3023 		types[ntypes++] = type;
3024 		type = va_arg(args, int);
3025 	}
3026 	va_end(args);
3027 
3028 	fds.fd = libinput_get_fd(li);
3029 	fds.events = POLLIN;
3030 	fds.revents = 0;
3031 
3032 	while (1) {
3033 		size_t i;
3034 		struct libinput_event *event;
3035 
3036 		while ((type = libinput_next_event_type(li)) == LIBINPUT_EVENT_NONE) {
3037 			int rc = poll(&fds, 1, 2000);
3038 			litest_assert_int_gt(rc, 0);
3039 			libinput_dispatch(li);
3040 		}
3041 
3042 		/* no event mask means wait for any event */
3043 		if (ntypes == 0)
3044 			return;
3045 
3046 		for (i = 0; i < ntypes; i++) {
3047 			if (type == types[i])
3048 				return;
3049 		}
3050 
3051 		event = libinput_get_event(li);
3052 		libinput_event_destroy(event);
3053 	}
3054 }
3055 
3056 void
litest_drain_events(struct libinput *li)3057 litest_drain_events(struct libinput *li)
3058 {
3059 	struct libinput_event *event;
3060 
3061 	libinput_dispatch(li);
3062 	while ((event = libinput_get_event(li))) {
3063 		libinput_event_destroy(event);
3064 		libinput_dispatch(li);
3065 	}
3066 }
3067 
3068 
3069 void
litest_drain_events_of_type(struct libinput *li, ...)3070 litest_drain_events_of_type(struct libinput *li, ...)
3071 {
3072 	enum libinput_event_type type;
3073 	enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE};
3074 	size_t ntypes = 0;
3075 	va_list args;
3076 
3077 	va_start(args, li);
3078 	type = va_arg(args, int);
3079 	while ((int)type != -1) {
3080 		litest_assert_int_gt(type, 0U);
3081 		litest_assert_int_lt(ntypes, ARRAY_LENGTH(types));
3082 		types[ntypes++] = type;
3083 		type = va_arg(args, int);
3084 	}
3085 	va_end(args);
3086 
3087 	libinput_dispatch(li);
3088 	type = libinput_next_event_type(li);
3089 	while (type !=  LIBINPUT_EVENT_NONE) {
3090 		struct libinput_event *event;
3091 		bool found = false;
3092 
3093 		type = libinput_next_event_type(li);
3094 
3095 		for (size_t i = 0; i < ntypes; i++) {
3096 			if (type == types[i]) {
3097 				found = true;
3098 				break;
3099 			}
3100 		}
3101 		if (!found)
3102 			return;
3103 
3104 		event = libinput_get_event(li);
3105 		libinput_event_destroy(event);
3106 		libinput_dispatch(li);
3107 	}
3108 }
3109 
3110 static const char *
litest_event_type_str(enum libinput_event_type type)3111 litest_event_type_str(enum libinput_event_type type)
3112 {
3113 	const char *str = NULL;
3114 
3115 	switch (type) {
3116 	case LIBINPUT_EVENT_NONE:
3117 		abort();
3118 	case LIBINPUT_EVENT_DEVICE_ADDED:
3119 		str = "ADDED";
3120 		break;
3121 	case LIBINPUT_EVENT_DEVICE_REMOVED:
3122 		str = "REMOVED";
3123 		break;
3124 	case LIBINPUT_EVENT_KEYBOARD_KEY:
3125 		str = "KEY";
3126 		break;
3127 	case LIBINPUT_EVENT_POINTER_MOTION:
3128 		str = "MOTION";
3129 		break;
3130 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
3131 		str = "ABSOLUTE";
3132 		break;
3133 	case LIBINPUT_EVENT_POINTER_BUTTON:
3134 		str = "BUTTON";
3135 		break;
3136 	case LIBINPUT_EVENT_POINTER_AXIS:
3137 		str = "AXIS";
3138 		break;
3139 	case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
3140 		str = "SCROLL_WHEEL";
3141 		break;
3142 	case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
3143 		str = "SCROLL_FINGER";
3144 		break;
3145 	case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
3146 		str = "SCROLL_CONTINUOUS";
3147 		break;
3148 	case LIBINPUT_EVENT_TOUCH_DOWN:
3149 		str = "TOUCH DOWN";
3150 		break;
3151 	case LIBINPUT_EVENT_TOUCH_UP:
3152 		str = "TOUCH UP";
3153 		break;
3154 	case LIBINPUT_EVENT_TOUCH_MOTION:
3155 		str = "TOUCH MOTION";
3156 		break;
3157 	case LIBINPUT_EVENT_TOUCH_CANCEL:
3158 		str = "TOUCH CANCEL";
3159 		break;
3160 	case LIBINPUT_EVENT_TOUCH_FRAME:
3161 		str = "TOUCH FRAME";
3162 		break;
3163 	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
3164 		str = "GESTURE SWIPE BEGIN";
3165 		break;
3166 	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
3167 		str = "GESTURE SWIPE UPDATE";
3168 		break;
3169 	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
3170 		str = "GESTURE SWIPE END";
3171 		break;
3172 	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
3173 		str = "GESTURE PINCH BEGIN";
3174 		break;
3175 	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
3176 		str = "GESTURE PINCH UPDATE";
3177 		break;
3178 	case LIBINPUT_EVENT_GESTURE_PINCH_END:
3179 		str = "GESTURE PINCH END";
3180 		break;
3181 	case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
3182 		str = "GESTURE HOLD BEGIN";
3183 		break;
3184 	case LIBINPUT_EVENT_GESTURE_HOLD_END:
3185 		str = "GESTURE HOLD END";
3186 		break;
3187 	case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
3188 		str = "TABLET TOOL AXIS";
3189 		break;
3190 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
3191 		str = "TABLET TOOL PROX";
3192 		break;
3193 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
3194 		str = "TABLET TOOL TIP";
3195 		break;
3196 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
3197 		str = "TABLET TOOL BUTTON";
3198 		break;
3199 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
3200 		str = "TABLET PAD BUTTON";
3201 		break;
3202 	case LIBINPUT_EVENT_TABLET_PAD_RING:
3203 		str = "TABLET PAD RING";
3204 		break;
3205 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
3206 		str = "TABLET PAD STRIP";
3207 		break;
3208 	case LIBINPUT_EVENT_TABLET_PAD_KEY:
3209 		str = "TABLET PAD KEY";
3210 		break;
3211 	case LIBINPUT_EVENT_SWITCH_TOGGLE:
3212 		str = "SWITCH TOGGLE";
3213 		break;
3214 	}
3215 	return str;
3216 }
3217 
3218 static const char *
litest_event_get_type_str(struct libinput_event *event)3219 litest_event_get_type_str(struct libinput_event *event)
3220 {
3221 	return litest_event_type_str(libinput_event_get_type(event));
3222 }
3223 
3224 static void
litest_print_event(struct libinput_event *event)3225 litest_print_event(struct libinput_event *event)
3226 {
3227 	struct libinput_event_pointer *p;
3228 	struct libinput_event_tablet_tool *t;
3229 	struct libinput_event_tablet_pad *pad;
3230 	struct libinput_device *dev;
3231 	enum libinput_event_type type;
3232 	double x, y;
3233 
3234 	dev = libinput_event_get_device(event);
3235 	type = libinput_event_get_type(event);
3236 
3237 	fprintf(stderr,
3238 		"device %s (%s) type %s ",
3239 		libinput_device_get_sysname(dev),
3240 		libinput_device_get_name(dev),
3241 		litest_event_get_type_str(event));
3242 	switch (type) {
3243 	case LIBINPUT_EVENT_POINTER_MOTION:
3244 		p = libinput_event_get_pointer_event(event);
3245 		x = libinput_event_pointer_get_dx(p);
3246 		y = libinput_event_pointer_get_dy(p);
3247 		fprintf(stderr, "%.2f/%.2f", x, y);
3248 		break;
3249 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
3250 		p = libinput_event_get_pointer_event(event);
3251 		x = libinput_event_pointer_get_absolute_x(p);
3252 		y = libinput_event_pointer_get_absolute_y(p);
3253 		fprintf(stderr, "%.2f/%.2f", x, y);
3254 		break;
3255 	case LIBINPUT_EVENT_POINTER_BUTTON:
3256 		p = libinput_event_get_pointer_event(event);
3257 		fprintf(stderr,
3258 			"button %d state %d",
3259 			libinput_event_pointer_get_button(p),
3260 			libinput_event_pointer_get_button_state(p));
3261 		break;
3262 	case LIBINPUT_EVENT_POINTER_AXIS:
3263 		p = libinput_event_get_pointer_event(event);
3264 		x = 0.0;
3265 		y = 0.0;
3266 		if (libinput_event_pointer_has_axis(p,
3267 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
3268 			y = libinput_event_pointer_get_axis_value(p,
3269 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
3270 		if (libinput_event_pointer_has_axis(p,
3271 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
3272 			x = libinput_event_pointer_get_axis_value(p,
3273 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
3274 		fprintf(stderr, "vert %.2f horiz %.2f", y, x);
3275 		break;
3276 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
3277 		t = libinput_event_get_tablet_tool_event(event);
3278 		fprintf(stderr, "proximity %d",
3279 			libinput_event_tablet_tool_get_proximity_state(t));
3280 		break;
3281 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
3282 		t = libinput_event_get_tablet_tool_event(event);
3283 		fprintf(stderr, "tip %d",
3284 			libinput_event_tablet_tool_get_tip_state(t));
3285 		break;
3286 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
3287 		t = libinput_event_get_tablet_tool_event(event);
3288 		fprintf(stderr, "button %d state %d",
3289 			libinput_event_tablet_tool_get_button(t),
3290 			libinput_event_tablet_tool_get_button_state(t));
3291 		break;
3292 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
3293 		pad = libinput_event_get_tablet_pad_event(event);
3294 		fprintf(stderr, "button %d state %d",
3295 			libinput_event_tablet_pad_get_button_number(pad),
3296 			libinput_event_tablet_pad_get_button_state(pad));
3297 		break;
3298 	case LIBINPUT_EVENT_TABLET_PAD_RING:
3299 		pad = libinput_event_get_tablet_pad_event(event);
3300 		fprintf(stderr, "ring %d position %.2f source %d",
3301 			libinput_event_tablet_pad_get_ring_number(pad),
3302 			libinput_event_tablet_pad_get_ring_position(pad),
3303 			libinput_event_tablet_pad_get_ring_source(pad));
3304 		break;
3305 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
3306 		pad = libinput_event_get_tablet_pad_event(event);
3307 		fprintf(stderr, "strip %d position %.2f source %d",
3308 			libinput_event_tablet_pad_get_ring_number(pad),
3309 			libinput_event_tablet_pad_get_ring_position(pad),
3310 			libinput_event_tablet_pad_get_ring_source(pad));
3311 		break;
3312 	default:
3313 		break;
3314 	}
3315 
3316 	fprintf(stderr, "\n");
3317 }
3318 
3319 #define litest_assert_event_type_is_one_of(...) \
3320     _litest_assert_event_type_is_one_of(__VA_ARGS__, -1)
3321 
3322 static void
_litest_assert_event_type_is_one_of(struct libinput_event *event, ...)3323 _litest_assert_event_type_is_one_of(struct libinput_event *event, ...)
3324 {
3325 	va_list args;
3326 	enum libinput_event_type expected_type;
3327 	enum libinput_event_type actual_type = libinput_event_get_type(event);
3328 	bool match = false;
3329 
3330 	va_start(args, event);
3331 	expected_type = va_arg(args, int);
3332 	while ((int)expected_type != -1 && !match) {
3333 		match = (actual_type == expected_type);
3334 		expected_type = va_arg(args, int);
3335 	}
3336 	va_end(args);
3337 
3338 	if (match)
3339 		return;
3340 
3341 	fprintf(stderr,
3342 		"FAILED EVENT TYPE: %s: have %s (%d) but want ",
3343 		libinput_device_get_name(libinput_event_get_device(event)),
3344 		litest_event_get_type_str(event),
3345 		libinput_event_get_type(event));
3346 
3347 	va_start(args, event);
3348 	expected_type = va_arg(args, int);
3349 	while ((int)expected_type != -1) {
3350 		fprintf(stderr,
3351 			"%s (%d)",
3352 			litest_event_type_str(expected_type),
3353 			expected_type);
3354 		expected_type = va_arg(args, int);
3355 
3356 		if ((int)expected_type != -1)
3357 			fprintf(stderr, " || ");
3358 	}
3359 
3360 	fprintf(stderr, "\nWrong event is: ");
3361 	litest_print_event(event);
3362 	litest_backtrace();
3363 	abort();
3364 }
3365 
3366 void
litest_assert_event_type(struct libinput_event *event, enum libinput_event_type want)3367 litest_assert_event_type(struct libinput_event *event,
3368 			 enum libinput_event_type want)
3369 {
3370 	litest_assert_event_type_is_one_of(event, want);
3371 }
3372 
3373 void
litest_assert_empty_queue(struct libinput *li)3374 litest_assert_empty_queue(struct libinput *li)
3375 {
3376 	bool empty_queue = true;
3377 	struct libinput_event *event;
3378 
3379 	libinput_dispatch(li);
3380 	while ((event = libinput_get_event(li))) {
3381 		empty_queue = false;
3382 		fprintf(stderr,
3383 			"Unexpected event: ");
3384 		litest_print_event(event);
3385 		libinput_event_destroy(event);
3386 		libinput_dispatch(li);
3387 	}
3388 
3389 	litest_assert(empty_queue);
3390 }
3391 
3392 static struct libevdev_uinput *
litest_create_uinput(const char *name, const struct input_id *id, const struct input_absinfo *abs_info, const int *events)3393 litest_create_uinput(const char *name,
3394 		     const struct input_id *id,
3395 		     const struct input_absinfo *abs_info,
3396 		     const int *events)
3397 {
3398 	struct libevdev_uinput *uinput;
3399 	struct libevdev *dev;
3400 	int type, code;
3401 	int rc, fd;
3402 	const struct input_absinfo *abs;
3403 	const struct input_absinfo default_abs = {
3404 		.value = 0,
3405 		.minimum = 0,
3406 		.maximum = 100,
3407 		.fuzz = 0,
3408 		.flat = 0,
3409 		.resolution = 100
3410 	};
3411 	char buf[512];
3412 	const char *devnode;
3413 
3414 	dev = libevdev_new();
3415 	litest_assert_ptr_notnull(dev);
3416 
3417 	snprintf(buf, sizeof(buf), "litest %s", name);
3418 	libevdev_set_name(dev, buf);
3419 	if (id) {
3420 		libevdev_set_id_bustype(dev, id->bustype);
3421 		libevdev_set_id_vendor(dev, id->vendor);
3422 		libevdev_set_id_product(dev, id->product);
3423 		libevdev_set_id_version(dev, id->version);
3424 	}
3425 
3426 	abs = abs_info;
3427 	while (abs && abs->value != -1) {
3428 		struct input_absinfo a = *abs;
3429 
3430 		/* abs_info->value is used for the code and may be outside
3431 		   of [min, max] */
3432 		a.value = abs->minimum;
3433 		rc = libevdev_enable_event_code(dev, EV_ABS, abs->value, &a);
3434 		litest_assert_int_eq(rc, 0);
3435 		abs++;
3436 	}
3437 
3438 	while (events &&
3439 	       (type = *events++) != -1 &&
3440 	       (code = *events++) != -1) {
3441 		if (type == INPUT_PROP_MAX) {
3442 			rc = libevdev_enable_property(dev, code);
3443 		} else {
3444 			rc = libevdev_enable_event_code(dev, type, code,
3445 							type == EV_ABS ? &default_abs : NULL);
3446 		}
3447 		litest_assert_int_eq(rc, 0);
3448 	}
3449 
3450 	rc = libevdev_uinput_create_from_device(dev,
3451 					        LIBEVDEV_UINPUT_OPEN_MANAGED,
3452 						&uinput);
3453 	/* workaround for a bug in libevdev pre-1.3
3454 	   http://cgit.freedesktop.org/libevdev/commit/?id=debe9b030c8069cdf78307888ef3b65830b25122 */
3455 	if (rc == -EBADF)
3456 		rc = -EACCES;
3457 	litest_assert_msg(rc == 0, "Failed to create uinput device: %s\n", strerror(-rc));
3458 
3459 	libevdev_free(dev);
3460 
3461 	devnode = libevdev_uinput_get_devnode(uinput);
3462 	litest_assert_notnull(devnode);
3463 	fd = open(devnode, O_RDONLY);
3464 	litest_assert_int_gt(fd, -1);
3465 	rc = libevdev_new_from_fd(fd, &dev);
3466 	litest_assert_int_eq(rc, 0);
3467 
3468 	/* uinput before kernel 4.5 + libevdev 1.5.0 does not support
3469 	 * setting the resolution, so we set it afterwards. This is of
3470 	 * course racy as hell but the way we _generally_ use this function
3471 	 * by the time libinput uses the device, we're finished here.
3472 	 *
3473 	 * If you have kernel 4.5 and libevdev 1.5.0 or later, this code
3474 	 * just keeps the room warm.
3475 	 */
3476 	abs = abs_info;
3477 	while (abs && abs->value != -1) {
3478 		if (abs->resolution != 0) {
3479 			if (libevdev_get_abs_resolution(dev, abs->value) ==
3480 			    abs->resolution)
3481 				break;
3482 
3483 			rc = libevdev_kernel_set_abs_info(dev,
3484 							  abs->value,
3485 							  abs);
3486 			litest_assert_int_eq(rc, 0);
3487 		}
3488 		abs++;
3489 	}
3490 	close(fd);
3491 	libevdev_free(dev);
3492 
3493 	return uinput;
3494 }
3495 
3496 struct libevdev_uinput *
litest_create_uinput_device_from_description(const char *name, const struct input_id *id, const struct input_absinfo *abs_info, const int *events)3497 litest_create_uinput_device_from_description(const char *name,
3498 					     const struct input_id *id,
3499 					     const struct input_absinfo *abs_info,
3500 					     const int *events)
3501 {
3502 	struct libevdev_uinput *uinput;
3503 	const char *syspath;
3504 	char path[PATH_MAX];
3505 
3506 	struct udev_monitor *udev_monitor;
3507 	struct udev_device *udev_device;
3508 
3509 	udev_monitor = udev_setup_monitor();
3510 
3511 	uinput = litest_create_uinput(name, id, abs_info, events);
3512 
3513 	syspath = libevdev_uinput_get_syspath(uinput);
3514 	snprintf(path, sizeof(path), "%s/event", syspath);
3515 
3516 	udev_device = udev_wait_for_device_event(udev_monitor, "add", path);
3517 
3518 	litest_assert(udev_device_get_property_value(udev_device, "ID_INPUT"));
3519 
3520 	udev_device_unref(udev_device);
3521 	udev_monitor_unref(udev_monitor);
3522 
3523 	return uinput;
3524 }
3525 
3526 static struct libevdev_uinput *
litest_create_uinput_abs_device_v(const char *name, struct input_id *id, const struct input_absinfo *abs, va_list args)3527 litest_create_uinput_abs_device_v(const char *name,
3528 				  struct input_id *id,
3529 				  const struct input_absinfo *abs,
3530 				  va_list args)
3531 {
3532 	int events[KEY_MAX * 2 + 2]; /* increase this if not sufficient */
3533 	int *event = events;
3534 	int type, code;
3535 
3536 	while ((type = va_arg(args, int)) != -1 &&
3537 	       (code = va_arg(args, int)) != -1) {
3538 		*event++ = type;
3539 		*event++ = code;
3540 		litest_assert(event < &events[ARRAY_LENGTH(events) - 2]);
3541 	}
3542 
3543 	*event++ = -1;
3544 	*event++ = -1;
3545 
3546 	return litest_create_uinput_device_from_description(name, id,
3547 							    abs, events);
3548 }
3549 
3550 struct libevdev_uinput *
litest_create_uinput_abs_device(const char *name, struct input_id *id, const struct input_absinfo *abs, ...)3551 litest_create_uinput_abs_device(const char *name,
3552 				struct input_id *id,
3553 				const struct input_absinfo *abs,
3554 				...)
3555 {
3556 	struct libevdev_uinput *uinput;
3557 	va_list args;
3558 
3559 	va_start(args, abs);
3560 	uinput = litest_create_uinput_abs_device_v(name, id, abs, args);
3561 	va_end(args);
3562 
3563 	return uinput;
3564 }
3565 
3566 struct libevdev_uinput *
litest_create_uinput_device(const char *name, struct input_id *id, ...)3567 litest_create_uinput_device(const char *name, struct input_id *id, ...)
3568 {
3569 	struct libevdev_uinput *uinput;
3570 	va_list args;
3571 
3572 	va_start(args, id);
3573 	uinput = litest_create_uinput_abs_device_v(name, id, NULL, args);
3574 	va_end(args);
3575 
3576 	return uinput;
3577 }
3578 
3579 struct libinput_event_pointer*
litest_is_button_event(struct libinput_event *event, unsigned int button, enum libinput_button_state state)3580 litest_is_button_event(struct libinput_event *event,
3581 		       unsigned int button,
3582 		       enum libinput_button_state state)
3583 {
3584 	struct libinput_event_pointer *ptrev;
3585 	enum libinput_event_type type = LIBINPUT_EVENT_POINTER_BUTTON;
3586 
3587 	litest_assert_ptr_notnull(event);
3588 	litest_assert_event_type(event, type);
3589 	ptrev = libinput_event_get_pointer_event(event);
3590 	litest_assert_int_eq(libinput_event_pointer_get_button(ptrev),
3591 			     button);
3592 	litest_assert_int_eq(libinput_event_pointer_get_button_state(ptrev),
3593 			     state);
3594 
3595 	return ptrev;
3596 }
3597 
3598 struct libinput_event_pointer *
litest_is_axis_event(struct libinput_event *event, enum libinput_event_type axis_type, enum libinput_pointer_axis axis, enum libinput_pointer_axis_source source)3599 litest_is_axis_event(struct libinput_event *event,
3600 		     enum libinput_event_type axis_type,
3601 		     enum libinput_pointer_axis axis,
3602 		     enum libinput_pointer_axis_source source)
3603 {
3604 	struct libinput_event_pointer *ptrev;
3605 
3606 	litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL ||
3607 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER ||
3608 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
3609 
3610 	litest_assert_ptr_notnull(event);
3611 	litest_assert_event_type_is_one_of(event,
3612 					   LIBINPUT_EVENT_POINTER_AXIS,
3613 					   axis_type);
3614 	ptrev = libinput_event_get_pointer_event(event);
3615 	litest_assert(libinput_event_pointer_has_axis(ptrev, axis));
3616 
3617 	if (source != 0)
3618 		litest_assert_int_eq(litest_event_pointer_get_axis_source(ptrev),
3619 				     source);
3620 
3621 	return ptrev;
3622 }
3623 
3624 bool
litest_is_high_res_axis_event(struct libinput_event *event)3625 litest_is_high_res_axis_event(struct libinput_event *event)
3626 {
3627 	litest_assert_event_type_is_one_of(event,
3628 					   LIBINPUT_EVENT_POINTER_AXIS,
3629 					   LIBINPUT_EVENT_POINTER_SCROLL_WHEEL,
3630 					   LIBINPUT_EVENT_POINTER_SCROLL_FINGER,
3631 					   LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
3632 
3633 	return (libinput_event_get_type(event) != LIBINPUT_EVENT_POINTER_AXIS);
3634 }
3635 
3636 struct libinput_event_pointer *
litest_is_motion_event(struct libinput_event *event)3637 litest_is_motion_event(struct libinput_event *event)
3638 {
3639 	struct libinput_event_pointer *ptrev;
3640 	enum libinput_event_type type = LIBINPUT_EVENT_POINTER_MOTION;
3641 	double x, y, ux, uy;
3642 
3643 	litest_assert_ptr_notnull(event);
3644 	litest_assert_event_type(event, type);
3645 	ptrev = libinput_event_get_pointer_event(event);
3646 
3647 	x = libinput_event_pointer_get_dx(ptrev);
3648 	y = libinput_event_pointer_get_dy(ptrev);
3649 	ux = libinput_event_pointer_get_dx_unaccelerated(ptrev);
3650 	uy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
3651 
3652 	/* No 0 delta motion events */
3653 	litest_assert(x != 0.0 || y != 0.0 ||
3654 		      ux != 0.0 || uy != 0.0);
3655 
3656 	return ptrev;
3657 }
3658 
3659 void
litest_assert_key_event(struct libinput *li, unsigned int key, enum libinput_key_state state)3660 litest_assert_key_event(struct libinput *li, unsigned int key,
3661 			enum libinput_key_state state)
3662 {
3663 	struct libinput_event *event;
3664 
3665 	litest_wait_for_event(li);
3666 	event = libinput_get_event(li);
3667 
3668 	litest_is_keyboard_event(event, key, state);
3669 
3670 	libinput_event_destroy(event);
3671 }
3672 
3673 void
litest_assert_button_event(struct libinput *li, unsigned int button, enum libinput_button_state state)3674 litest_assert_button_event(struct libinput *li, unsigned int button,
3675 			   enum libinput_button_state state)
3676 {
3677 	struct libinput_event *event;
3678 
3679 	litest_wait_for_event(li);
3680 	event = libinput_get_event(li);
3681 
3682 	litest_is_button_event(event, button, state);
3683 
3684 	libinput_event_destroy(event);
3685 }
3686 
3687 struct libinput_event_touch *
litest_is_touch_event(struct libinput_event *event, enum libinput_event_type type)3688 litest_is_touch_event(struct libinput_event *event,
3689 		      enum libinput_event_type type)
3690 {
3691 	struct libinput_event_touch *touch;
3692 
3693 	litest_assert_ptr_notnull(event);
3694 
3695 	if (type == 0)
3696 		type = libinput_event_get_type(event);
3697 
3698 	switch (type) {
3699 	case LIBINPUT_EVENT_TOUCH_DOWN:
3700 	case LIBINPUT_EVENT_TOUCH_UP:
3701 	case LIBINPUT_EVENT_TOUCH_MOTION:
3702 	case LIBINPUT_EVENT_TOUCH_FRAME:
3703 	case LIBINPUT_EVENT_TOUCH_CANCEL:
3704 		litest_assert_event_type(event, type);
3705 		break;
3706 	default:
3707 		ck_abort_msg("%s: invalid touch type %d\n", __func__, type);
3708 	}
3709 
3710 	touch = libinput_event_get_touch_event(event);
3711 
3712 	return touch;
3713 }
3714 
3715 struct libinput_event_keyboard *
litest_is_keyboard_event(struct libinput_event *event, unsigned int key, enum libinput_key_state state)3716 litest_is_keyboard_event(struct libinput_event *event,
3717 			 unsigned int key,
3718 			 enum libinput_key_state state)
3719 {
3720 	struct libinput_event_keyboard *kevent;
3721 	enum libinput_event_type type = LIBINPUT_EVENT_KEYBOARD_KEY;
3722 
3723 	litest_assert_ptr_notnull(event);
3724 	litest_assert_event_type(event, type);
3725 
3726 	kevent = libinput_event_get_keyboard_event(event);
3727 	litest_assert_ptr_notnull(kevent);
3728 
3729 	litest_assert_int_eq(libinput_event_keyboard_get_key(kevent), key);
3730 	litest_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
3731 			     state);
3732 	return kevent;
3733 }
3734 
3735 struct libinput_event_gesture *
litest_is_gesture_event(struct libinput_event *event, enum libinput_event_type type, int nfingers)3736 litest_is_gesture_event(struct libinput_event *event,
3737 			enum libinput_event_type type,
3738 			int nfingers)
3739 {
3740 	struct libinput_event_gesture *gevent;
3741 
3742 	litest_assert_ptr_notnull(event);
3743 	litest_assert_event_type(event, type);
3744 
3745 	gevent = libinput_event_get_gesture_event(event);
3746 	litest_assert_ptr_notnull(gevent);
3747 
3748 	if (nfingers != -1)
3749 		litest_assert_int_eq(libinput_event_gesture_get_finger_count(gevent),
3750 				     nfingers);
3751 	return gevent;
3752 }
3753 
3754 void
litest_assert_gesture_event(struct libinput *li, enum libinput_event_type type, int nfingers)3755 litest_assert_gesture_event(struct libinput *li,
3756 			    enum libinput_event_type type,
3757 			    int nfingers)
3758 {
3759 	struct libinput_event *event;
3760 
3761 	litest_wait_for_event(li);
3762 	event = libinput_get_event(li);
3763 
3764 	litest_is_gesture_event(event, type, nfingers);
3765 	libinput_event_destroy(event);
3766 }
3767 
3768 struct libinput_event_tablet_tool *
litest_is_tablet_event(struct libinput_event *event, enum libinput_event_type type)3769 litest_is_tablet_event(struct libinput_event *event,
3770 		       enum libinput_event_type type)
3771 {
3772 	struct libinput_event_tablet_tool *tevent;
3773 
3774 	litest_assert_ptr_notnull(event);
3775 	litest_assert_event_type(event, type);
3776 
3777 	tevent = libinput_event_get_tablet_tool_event(event);
3778 	litest_assert_ptr_notnull(tevent);
3779 
3780 	return tevent;
3781 }
3782 
3783 void
litest_assert_tablet_button_event(struct libinput *li, unsigned int button, enum libinput_button_state state)3784 litest_assert_tablet_button_event(struct libinput *li, unsigned int button,
3785 				  enum libinput_button_state state)
3786 {
3787 	struct libinput_event *event;
3788 	struct libinput_event_tablet_tool *tev;
3789 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_BUTTON;
3790 
3791 	litest_wait_for_event(li);
3792 	event = libinput_get_event(li);
3793 
3794 	litest_assert_notnull(event);
3795 	litest_assert_event_type(event, type);
3796 	tev = libinput_event_get_tablet_tool_event(event);
3797 	litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
3798 			     button);
3799 	litest_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
3800 			     state);
3801 	libinput_event_destroy(event);
3802 }
3803 
3804 
3805 struct libinput_event_tablet_tool *
litest_is_proximity_event(struct libinput_event *event, enum libinput_tablet_tool_proximity_state state)3806 litest_is_proximity_event(struct libinput_event *event,
3807 			  enum libinput_tablet_tool_proximity_state state)
3808 {
3809 	struct libinput_event_tablet_tool *tev;
3810 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY;
3811 
3812 	litest_assert_notnull(event);
3813 	litest_assert_event_type(event, type);
3814 	tev = libinput_event_get_tablet_tool_event(event);
3815 	litest_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3816 			     state);
3817 	return tev;
3818 }
3819 
3820 double
litest_event_pointer_get_value(struct libinput_event_pointer *ptrev, enum libinput_pointer_axis axis)3821 litest_event_pointer_get_value(struct libinput_event_pointer *ptrev,
3822 			       enum libinput_pointer_axis axis)
3823 {
3824 	struct libinput_event *event;
3825 	enum libinput_event_type type;
3826 
3827 	event = libinput_event_pointer_get_base_event(ptrev);
3828 	type = libinput_event_get_type(event);
3829 
3830 	switch (type) {
3831 	case LIBINPUT_EVENT_POINTER_AXIS:
3832 		return libinput_event_pointer_get_axis_value(ptrev, axis);
3833 	case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
3834 		return libinput_event_pointer_get_scroll_value_v120(ptrev, axis);
3835 	case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
3836 	case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
3837 		return libinput_event_pointer_get_scroll_value(ptrev, axis);
3838 	default:
3839 		abort();
3840 	}
3841 }
3842 
3843 enum libinput_pointer_axis_source
litest_event_pointer_get_axis_source(struct libinput_event_pointer *ptrev)3844 litest_event_pointer_get_axis_source(struct libinput_event_pointer *ptrev)
3845 {
3846 	struct libinput_event *event;
3847 	enum libinput_event_type type;
3848 
3849 	event = libinput_event_pointer_get_base_event(ptrev);
3850 	type = libinput_event_get_type(event);
3851 
3852 	if (type == LIBINPUT_EVENT_POINTER_AXIS)
3853 		return libinput_event_pointer_get_axis_source(ptrev);
3854 
3855 	switch (type) {
3856 	case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
3857 		return LIBINPUT_POINTER_AXIS_SOURCE_WHEEL;
3858 	case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
3859 		return LIBINPUT_POINTER_AXIS_SOURCE_FINGER;
3860 	case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
3861 		return LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS;
3862 	default:
3863 		abort();
3864 	}
3865 }
3866 
litest_assert_tablet_proximity_event(struct libinput *li, enum libinput_tablet_tool_proximity_state state)3867 void litest_assert_tablet_proximity_event(struct libinput *li,
3868 					  enum libinput_tablet_tool_proximity_state state)
3869 {
3870 	struct libinput_event *event;
3871 
3872 	litest_wait_for_event(li);
3873 	event = libinput_get_event(li);
3874 	litest_is_proximity_event(event, state);
3875 	libinput_event_destroy(event);
3876 }
3877 
litest_assert_tablet_tip_event(struct libinput *li, enum libinput_tablet_tool_tip_state state)3878 void litest_assert_tablet_tip_event(struct libinput *li,
3879 				    enum libinput_tablet_tool_tip_state state)
3880 {
3881 	struct libinput_event *event;
3882 	struct libinput_event_tablet_tool *tev;
3883 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_TIP;
3884 
3885 	litest_wait_for_event(li);
3886 	event = libinput_get_event(li);
3887 
3888 	litest_assert_notnull(event);
3889 	litest_assert_event_type(event, type);
3890 	tev = libinput_event_get_tablet_tool_event(event);
3891 	litest_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tev),
3892 			     state);
3893 	libinput_event_destroy(event);
3894 }
3895 
3896 struct libinput_event_tablet_pad *
litest_is_pad_button_event(struct libinput_event *event, unsigned int button, enum libinput_button_state state)3897 litest_is_pad_button_event(struct libinput_event *event,
3898 			   unsigned int button,
3899 			   enum libinput_button_state state)
3900 {
3901 	struct libinput_event_tablet_pad *p;
3902 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_BUTTON;
3903 
3904 	litest_assert_ptr_notnull(event);
3905 	litest_assert_event_type(event, type);
3906 
3907 	p = libinput_event_get_tablet_pad_event(event);
3908 	litest_assert_ptr_notnull(p);
3909 
3910 	litest_assert_int_eq(libinput_event_tablet_pad_get_button_number(p),
3911 			     button);
3912 	litest_assert_int_eq(libinput_event_tablet_pad_get_button_state(p),
3913 			     state);
3914 
3915 	return p;
3916 }
3917 
3918 struct libinput_event_tablet_pad *
litest_is_pad_ring_event(struct libinput_event *event, unsigned int number, enum libinput_tablet_pad_ring_axis_source source)3919 litest_is_pad_ring_event(struct libinput_event *event,
3920 			 unsigned int number,
3921 			 enum libinput_tablet_pad_ring_axis_source source)
3922 {
3923 	struct libinput_event_tablet_pad *p;
3924 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_RING;
3925 
3926 	litest_assert_ptr_notnull(event);
3927 	litest_assert_event_type(event, type);
3928 	p = libinput_event_get_tablet_pad_event(event);
3929 
3930 	litest_assert_int_eq(libinput_event_tablet_pad_get_ring_number(p),
3931 			     number);
3932 	litest_assert_int_eq(libinput_event_tablet_pad_get_ring_source(p),
3933 			     source);
3934 
3935 	return p;
3936 }
3937 
3938 struct libinput_event_tablet_pad *
litest_is_pad_strip_event(struct libinput_event *event, unsigned int number, enum libinput_tablet_pad_strip_axis_source source)3939 litest_is_pad_strip_event(struct libinput_event *event,
3940 			  unsigned int number,
3941 			  enum libinput_tablet_pad_strip_axis_source source)
3942 {
3943 	struct libinput_event_tablet_pad *p;
3944 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_STRIP;
3945 
3946 	litest_assert_ptr_notnull(event);
3947 	litest_assert_event_type(event, type);
3948 	p = libinput_event_get_tablet_pad_event(event);
3949 
3950 	litest_assert_int_eq(libinput_event_tablet_pad_get_strip_number(p),
3951 			     number);
3952 	litest_assert_int_eq(libinput_event_tablet_pad_get_strip_source(p),
3953 			     source);
3954 
3955 	return p;
3956 }
3957 
3958 struct libinput_event_tablet_pad *
litest_is_pad_key_event(struct libinput_event *event, unsigned int key, enum libinput_key_state state)3959 litest_is_pad_key_event(struct libinput_event *event,
3960 			unsigned int key,
3961 			enum libinput_key_state state)
3962 {
3963 	struct libinput_event_tablet_pad *p;
3964 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_KEY;
3965 
3966 	litest_assert(event != NULL);
3967 	litest_assert_event_type(event, type);
3968 
3969 	p = libinput_event_get_tablet_pad_event(event);
3970 	litest_assert(p != NULL);
3971 
3972 	litest_assert_int_eq(libinput_event_tablet_pad_get_key(p), key);
3973 	litest_assert_int_eq(libinput_event_tablet_pad_get_key_state(p),
3974 			     state);
3975 
3976 	return p;
3977 }
3978 
3979 struct libinput_event_switch *
litest_is_switch_event(struct libinput_event *event, enum libinput_switch sw, enum libinput_switch_state state)3980 litest_is_switch_event(struct libinput_event *event,
3981 		       enum libinput_switch sw,
3982 		       enum libinput_switch_state state)
3983 {
3984 	struct libinput_event_switch *swev;
3985 	enum libinput_event_type type = LIBINPUT_EVENT_SWITCH_TOGGLE;
3986 
3987 	litest_assert_notnull(event);
3988 	litest_assert_event_type(event, type);
3989 	swev = libinput_event_get_switch_event(event);
3990 
3991 	litest_assert_int_eq(libinput_event_switch_get_switch(swev), sw);
3992 	litest_assert_int_eq(libinput_event_switch_get_switch_state(swev),
3993 			     state);
3994 
3995 	return swev;
3996 }
3997 
3998 void
litest_assert_switch_event(struct libinput *li, enum libinput_switch sw, enum libinput_switch_state state)3999 litest_assert_switch_event(struct libinput *li,
4000 			   enum libinput_switch sw,
4001 			   enum libinput_switch_state state)
4002 {
4003 	struct libinput_event *event;
4004 
4005 	litest_wait_for_event(li);
4006 	event = libinput_get_event(li);
4007 
4008 	litest_is_switch_event(event, sw, state);
4009 
4010 	libinput_event_destroy(event);
4011 }
4012 
4013 void
litest_assert_pad_button_event(struct libinput *li, unsigned int button, enum libinput_button_state state)4014 litest_assert_pad_button_event(struct libinput *li,
4015 			       unsigned int button,
4016 			       enum libinput_button_state state)
4017 {
4018 	struct libinput_event *event;
4019 
4020 	litest_wait_for_event(li);
4021 	event = libinput_get_event(li);
4022 
4023 	litest_is_pad_button_event(event, button, state);
4024 	libinput_event_destroy(event);
4025 }
4026 
4027 void
litest_assert_pad_key_event(struct libinput *li, unsigned int key, enum libinput_key_state state)4028 litest_assert_pad_key_event(struct libinput *li,
4029 			    unsigned int key,
4030 			    enum libinput_key_state state)
4031 {
4032 	struct libinput_event *event;
4033 
4034 	litest_wait_for_event(li);
4035 	event = libinput_get_event(li);
4036 
4037 	litest_is_pad_key_event(event, key, state);
4038 	libinput_event_destroy(event);
4039 }
4040 
4041 void
litest_assert_scroll(struct libinput *li, enum libinput_event_type axis_type, enum libinput_pointer_axis axis, int minimum_movement)4042 litest_assert_scroll(struct libinput *li,
4043 		     enum libinput_event_type axis_type,
4044 		     enum libinput_pointer_axis axis,
4045 		     int minimum_movement)
4046 {
4047 	struct libinput_event *event;
4048 	struct libinput_event_pointer *ptrev;
4049 	bool last_hi_res_event_found, last_low_res_event_found;
4050 	int value;
4051 	int nevents = 0;
4052 
4053 	litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL ||
4054 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER ||
4055 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
4056 
4057 	last_hi_res_event_found = false;
4058 	last_low_res_event_found = false;
4059 	event = libinput_get_event(li);
4060 	litest_assert_ptr_notnull(event);
4061 
4062 	while (event) {
4063 		int min = minimum_movement;
4064 
4065 		ptrev = litest_is_axis_event(event, axis_type, axis, 0);
4066 		nevents++;
4067 
4068 		/* Due to how the hysteresis works on touchpad
4069 		 * events, the first event is reduced by the
4070 		 * hysteresis margin that can cause the first event
4071 		 * go under the minimum we expect for all other
4072 		 * events */
4073 		if (nevents == 1)
4074 			min = minimum_movement/2;
4075 
4076 		value = litest_event_pointer_get_value(ptrev, axis);
4077 		if (litest_is_high_res_axis_event(event)) {
4078 			litest_assert(!last_hi_res_event_found);
4079 
4080 			if (axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL)
4081 				min *= 120;
4082 
4083 			if (value == 0)
4084 				last_hi_res_event_found = true;
4085 		} else {
4086 			litest_assert(!last_low_res_event_found);
4087 
4088 			if (value == 0)
4089 				last_low_res_event_found = true;
4090 		}
4091 
4092 		if (value != 0) {
4093 			if (minimum_movement > 0)
4094 				litest_assert_int_ge(value, min);
4095 			else
4096 				litest_assert_int_le(value, min);
4097 		}
4098 
4099 		libinput_event_destroy(event);
4100 		event = libinput_get_event(li);
4101 	}
4102 
4103 	litest_assert(last_low_res_event_found);
4104 	litest_assert(last_hi_res_event_found);
4105 }
4106 
4107 void
litest_assert_axis_end_sequence(struct libinput *li, enum libinput_event_type axis_type, enum libinput_pointer_axis axis, enum libinput_pointer_axis_source source)4108 litest_assert_axis_end_sequence(struct libinput *li,
4109 				enum libinput_event_type axis_type,
4110 				enum libinput_pointer_axis axis,
4111 				enum libinput_pointer_axis_source source)
4112 {
4113 	struct libinput_event *event;
4114 	struct libinput_event_pointer *ptrev;
4115 	bool last_hi_res_event_found, last_low_res_event_found;
4116 	double val;
4117 	int i;
4118 
4119 	litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL ||
4120 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER ||
4121 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
4122 
4123 	last_hi_res_event_found = false;
4124 	last_low_res_event_found = false;
4125 
4126 	/* both high and low scroll end events must be sent */
4127 	for (i = 0; i < 2; i++) {
4128 		event = libinput_get_event(li);
4129 		ptrev = litest_is_axis_event(event, axis_type, axis, source);
4130 		val = litest_event_pointer_get_value(ptrev, axis);
4131 		ck_assert(val == 0.0);
4132 
4133 		if (litest_is_high_res_axis_event(event)) {
4134 			litest_assert(!last_hi_res_event_found);
4135 			last_hi_res_event_found = true;
4136 		} else {
4137 			litest_assert(!last_low_res_event_found);
4138 			last_low_res_event_found = true;
4139 		}
4140 
4141 		libinput_event_destroy(event);
4142 	}
4143 
4144 	litest_assert(last_low_res_event_found);
4145 	litest_assert(last_hi_res_event_found);
4146 }
4147 
4148 void
litest_assert_only_typed_events(struct libinput *li, enum libinput_event_type type)4149 litest_assert_only_typed_events(struct libinput *li,
4150 				enum libinput_event_type type)
4151 {
4152 	struct libinput_event *event;
4153 
4154 	litest_assert(type != LIBINPUT_EVENT_NONE);
4155 
4156 	libinput_dispatch(li);
4157 	event = libinput_get_event(li);
4158 	litest_assert_notnull(event);
4159 
4160 	while (event) {
4161 		litest_assert_event_type(event, type);
4162 		libinput_event_destroy(event);
4163 		libinput_dispatch(li);
4164 		event = libinput_get_event(li);
4165 	}
4166 }
4167 
4168 void
litest_assert_only_axis_events(struct libinput *li, enum libinput_event_type axis_type)4169 litest_assert_only_axis_events(struct libinput *li,
4170 			       enum libinput_event_type axis_type)
4171 {
4172 	struct libinput_event *event;
4173 
4174 	litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL ||
4175 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER ||
4176 		      axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
4177 
4178 	libinput_dispatch(li);
4179 	event = libinput_get_event(li);
4180 	litest_assert_notnull(event);
4181 
4182 	while (event) {
4183 		litest_assert_event_type_is_one_of(event,
4184 						   LIBINPUT_EVENT_POINTER_AXIS,
4185 						   axis_type);
4186 		libinput_event_destroy(event);
4187 		libinput_dispatch(li);
4188 		event = libinput_get_event(li);
4189 	}
4190 }
4191 
4192 void
litest_assert_no_typed_events(struct libinput *li, enum libinput_event_type type)4193 litest_assert_no_typed_events(struct libinput *li,
4194 			      enum libinput_event_type type)
4195 {
4196 	struct libinput_event *event;
4197 
4198 	litest_assert(type != LIBINPUT_EVENT_NONE);
4199 
4200 	libinput_dispatch(li);
4201 	event = libinput_get_event(li);
4202 
4203 	while (event) {
4204 		litest_assert_int_ne(libinput_event_get_type(event),
4205                                      type);
4206 		libinput_event_destroy(event);
4207 		libinput_dispatch(li);
4208 		event = libinput_get_event(li);
4209 	}
4210 }
4211 
4212 void
litest_assert_touch_sequence(struct libinput *li)4213 litest_assert_touch_sequence(struct libinput *li)
4214 {
4215 	struct libinput_event *event;
4216 	struct libinput_event_touch *tev;
4217 	int slot;
4218 
4219 	event = libinput_get_event(li);
4220 	tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
4221 	slot = libinput_event_touch_get_slot(tev);
4222 	libinput_event_destroy(event);
4223 
4224 	event = libinput_get_event(li);
4225 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4226 	libinput_event_destroy(event);
4227 
4228 	event = libinput_get_event(li);
4229 	do {
4230 		tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
4231 		litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev));
4232 		libinput_event_destroy(event);
4233 
4234 		event = libinput_get_event(li);
4235 		litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4236 		libinput_event_destroy(event);
4237 
4238 		event = libinput_get_event(li);
4239 		litest_assert_notnull(event);
4240 	} while (libinput_event_get_type(event) != LIBINPUT_EVENT_TOUCH_UP);
4241 
4242 	tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
4243 	litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev));
4244 	libinput_event_destroy(event);
4245 	event = libinput_get_event(li);
4246 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4247 	libinput_event_destroy(event);
4248 }
4249 
4250 void
litest_assert_touch_motion_frame(struct libinput *li)4251 litest_assert_touch_motion_frame(struct libinput *li)
4252 {
4253 	struct libinput_event *event;
4254 
4255 	/* expect at least one, but maybe more */
4256 	event = libinput_get_event(li);
4257 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
4258 	libinput_event_destroy(event);
4259 
4260 	event = libinput_get_event(li);
4261 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4262 	libinput_event_destroy(event);
4263 
4264 	event = libinput_get_event(li);
4265 	while (event) {
4266 		litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
4267 		libinput_event_destroy(event);
4268 
4269 		event = libinput_get_event(li);
4270 		litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4271 		libinput_event_destroy(event);
4272 
4273 		event = libinput_get_event(li);
4274 	}
4275 }
4276 
4277 void
litest_assert_touch_down_frame(struct libinput *li)4278 litest_assert_touch_down_frame(struct libinput *li)
4279 {
4280 	struct libinput_event *event;
4281 
4282 	event = libinput_get_event(li);
4283 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
4284 	libinput_event_destroy(event);
4285 
4286 	event = libinput_get_event(li);
4287 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4288 	libinput_event_destroy(event);
4289 }
4290 
4291 void
litest_assert_touch_up_frame(struct libinput *li)4292 litest_assert_touch_up_frame(struct libinput *li)
4293 {
4294 	struct libinput_event *event;
4295 
4296 	event = libinput_get_event(li);
4297 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
4298 	libinput_event_destroy(event);
4299 
4300 	event = libinput_get_event(li);
4301 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4302 	libinput_event_destroy(event);
4303 }
4304 
4305 void
litest_assert_touch_cancel(struct libinput *li)4306 litest_assert_touch_cancel(struct libinput *li)
4307 {
4308 	struct libinput_event *event;
4309 
4310 	event = libinput_get_event(li);
4311 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_CANCEL);
4312 	libinput_event_destroy(event);
4313 
4314 	event = libinput_get_event(li);
4315 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
4316 	libinput_event_destroy(event);
4317 }
4318 
4319 void
litest_timeout_tap(void)4320 litest_timeout_tap(void)
4321 {
4322 	msleep(300);
4323 }
4324 
4325 void
litest_timeout_tapndrag(void)4326 litest_timeout_tapndrag(void)
4327 {
4328 	msleep(520);
4329 }
4330 
4331 void
litest_timeout_debounce(void)4332 litest_timeout_debounce(void)
4333 {
4334 	msleep(30);
4335 }
4336 
4337 void
litest_timeout_softbuttons(void)4338 litest_timeout_softbuttons(void)
4339 {
4340 	msleep(300);
4341 }
4342 
4343 void
litest_timeout_buttonscroll(void)4344 litest_timeout_buttonscroll(void)
4345 {
4346 	msleep(300);
4347 }
4348 
4349 void
litest_timeout_finger_switch(void)4350 litest_timeout_finger_switch(void)
4351 {
4352 	msleep(120);
4353 }
4354 
4355 void
litest_timeout_wheel_scroll(void)4356 litest_timeout_wheel_scroll(void)
4357 {
4358 	msleep(600);
4359 }
4360 
4361 void
litest_timeout_edgescroll(void)4362 litest_timeout_edgescroll(void)
4363 {
4364 	msleep(300);
4365 }
4366 
4367 void
litest_timeout_middlebutton(void)4368 litest_timeout_middlebutton(void)
4369 {
4370 	msleep(70);
4371 }
4372 
4373 void
litest_timeout_dwt_short(void)4374 litest_timeout_dwt_short(void)
4375 {
4376 	msleep(220);
4377 }
4378 
4379 void
litest_timeout_dwt_long(void)4380 litest_timeout_dwt_long(void)
4381 {
4382 	msleep(520);
4383 }
4384 
4385 void
litest_timeout_gesture(void)4386 litest_timeout_gesture(void)
4387 {
4388 	msleep(120);
4389 }
4390 
4391 void
litest_timeout_gesture_scroll(void)4392 litest_timeout_gesture_scroll(void)
4393 {
4394 	msleep(180);
4395 }
4396 
4397 void
litest_timeout_gesture_hold(void)4398 litest_timeout_gesture_hold(void)
4399 {
4400 	msleep(300);
4401 }
4402 
4403 void
litest_timeout_gesture_quick_hold(void)4404 litest_timeout_gesture_quick_hold(void)
4405 {
4406 	msleep(60);
4407 }
4408 
4409 void
litest_timeout_trackpoint(void)4410 litest_timeout_trackpoint(void)
4411 {
4412 	msleep(320);
4413 }
4414 
4415 void
litest_timeout_tablet_proxout(void)4416 litest_timeout_tablet_proxout(void)
4417 {
4418 	msleep(170);
4419 }
4420 
4421 void
litest_timeout_touch_arbitration(void)4422 litest_timeout_touch_arbitration(void)
4423 {
4424 	msleep(100);
4425 }
4426 
4427 void
litest_timeout_hysteresis(void)4428 litest_timeout_hysteresis(void)
4429 {
4430 	msleep(90);
4431 }
4432 
4433 void
litest_push_event_frame(struct litest_device *dev)4434 litest_push_event_frame(struct litest_device *dev)
4435 {
4436 	litest_assert_int_ge(dev->skip_ev_syn, 0);
4437 	dev->skip_ev_syn++;
4438 }
4439 
4440 void
litest_pop_event_frame(struct litest_device *dev)4441 litest_pop_event_frame(struct litest_device *dev)
4442 {
4443 	litest_assert_int_gt(dev->skip_ev_syn, 0);
4444 	dev->skip_ev_syn--;
4445 	if (dev->skip_ev_syn == 0)
4446 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
4447 }
4448 
4449 void
litest_filter_event(struct litest_device *dev, unsigned int type, unsigned int code)4450 litest_filter_event(struct litest_device *dev,
4451 		    unsigned int type,
4452 		    unsigned int code)
4453 {
4454 	libevdev_disable_event_code(dev->evdev, type, code);
4455 }
4456 
4457 void
litest_unfilter_event(struct litest_device *dev, unsigned int type, unsigned int code)4458 litest_unfilter_event(struct litest_device *dev,
4459 		      unsigned int type,
4460 		      unsigned int code)
4461 {
4462 	/* would need an non-NULL argument for re-enabling, so simply abort
4463 	 * until we need to be more sophisticated */
4464 	litest_assert_int_ne(type, (unsigned int)EV_ABS);
4465 
4466 	libevdev_enable_event_code(dev->evdev, type, code, NULL);
4467 }
4468 
4469 static void
send_abs_xy(struct litest_device *d, double x, double y)4470 send_abs_xy(struct litest_device *d, double x, double y)
4471 {
4472 	struct input_event e;
4473 	int val;
4474 
4475 	e.type = EV_ABS;
4476 	e.code = ABS_X;
4477 	e.value = LITEST_AUTO_ASSIGN;
4478 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4479 	litest_event(d, EV_ABS, ABS_X, val);
4480 
4481 	e.code = ABS_Y;
4482 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4483 	litest_event(d, EV_ABS, ABS_Y, val);
4484 }
4485 
4486 static void
send_abs_mt_xy(struct litest_device *d, double x, double y)4487 send_abs_mt_xy(struct litest_device *d, double x, double y)
4488 {
4489 	struct input_event e;
4490 	int val;
4491 
4492 	e.type = EV_ABS;
4493 	e.code = ABS_MT_POSITION_X;
4494 	e.value = LITEST_AUTO_ASSIGN;
4495 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4496 	litest_event(d, EV_ABS, ABS_MT_POSITION_X, val);
4497 
4498 	e.code = ABS_MT_POSITION_Y;
4499 	e.value = LITEST_AUTO_ASSIGN;
4500 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
4501 	litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val);
4502 }
4503 
4504 void
litest_semi_mt_touch_down(struct litest_device *d, struct litest_semi_mt *semi_mt, unsigned int slot, double x, double y)4505 litest_semi_mt_touch_down(struct litest_device *d,
4506 			  struct litest_semi_mt *semi_mt,
4507 			  unsigned int slot,
4508 			  double x, double y)
4509 {
4510 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
4511 
4512 	if (d->ntouches_down > 2 || slot > 1)
4513 		return;
4514 
4515 	if (d->ntouches_down == 1) {
4516 		l = x;
4517 		t = y;
4518 	} else {
4519 		int other = (slot + 1) % 2;
4520 		l = min(x, semi_mt->touches[other].x);
4521 		t = min(y, semi_mt->touches[other].y);
4522 		r = max(x, semi_mt->touches[other].x);
4523 		b = max(y, semi_mt->touches[other].y);
4524 	}
4525 
4526 	send_abs_xy(d, l, t);
4527 
4528 	litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
4529 
4530 	if (d->ntouches_down == 1)
4531 		litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
4532 
4533 	send_abs_mt_xy(d, l, t);
4534 
4535 	if (d->ntouches_down == 2) {
4536 		litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
4537 		litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
4538 
4539 		send_abs_mt_xy(d, r, b);
4540 	}
4541 
4542 	litest_event(d, EV_SYN, SYN_REPORT, 0);
4543 
4544 	semi_mt->touches[slot].x = x;
4545 	semi_mt->touches[slot].y = y;
4546 }
4547 
4548 void
litest_semi_mt_touch_move(struct litest_device *d, struct litest_semi_mt *semi_mt, unsigned int slot, double x, double y)4549 litest_semi_mt_touch_move(struct litest_device *d,
4550 			  struct litest_semi_mt *semi_mt,
4551 			  unsigned int slot,
4552 			  double x, double y)
4553 {
4554 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
4555 
4556 	if (d->ntouches_down > 2 || slot > 1)
4557 		return;
4558 
4559 	if (d->ntouches_down == 1) {
4560 		l = x;
4561 		t = y;
4562 	} else {
4563 		int other = (slot + 1) % 2;
4564 		l = min(x, semi_mt->touches[other].x);
4565 		t = min(y, semi_mt->touches[other].y);
4566 		r = max(x, semi_mt->touches[other].x);
4567 		b = max(y, semi_mt->touches[other].y);
4568 	}
4569 
4570 	send_abs_xy(d, l, t);
4571 
4572 	litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
4573 	send_abs_mt_xy(d, l, t);
4574 
4575 	if (d->ntouches_down == 2) {
4576 		litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
4577 		send_abs_mt_xy(d, r, b);
4578 	}
4579 
4580 	litest_event(d, EV_SYN, SYN_REPORT, 0);
4581 
4582 	semi_mt->touches[slot].x = x;
4583 	semi_mt->touches[slot].y = y;
4584 }
4585 
4586 void
litest_semi_mt_touch_up(struct litest_device *d, struct litest_semi_mt *semi_mt, unsigned int slot)4587 litest_semi_mt_touch_up(struct litest_device *d,
4588 			struct litest_semi_mt *semi_mt,
4589 			unsigned int slot)
4590 {
4591 	/* note: ntouches_down is decreased before we get here */
4592 	if (d->ntouches_down >= 2 || slot > 1)
4593 		return;
4594 
4595 	litest_event(d, EV_ABS, ABS_MT_SLOT, d->ntouches_down);
4596 	litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, -1);
4597 
4598 	/* if we have one finger left, send x/y coords for that finger left.
4599 	   this is likely to happen with a real touchpad */
4600 	if (d->ntouches_down == 1) {
4601 		int other = (slot + 1) % 2;
4602 		send_abs_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
4603 		litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
4604 		send_abs_mt_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
4605 	}
4606 
4607 	litest_event(d, EV_SYN, SYN_REPORT, 0);
4608 }
4609 
4610 enum litest_mode {
4611 	LITEST_MODE_ERROR,
4612 	LITEST_MODE_TEST,
4613 	LITEST_MODE_LIST,
4614 };
4615 
4616 static inline enum litest_mode
litest_parse_argv(int argc, char **argv)4617 litest_parse_argv(int argc, char **argv)
4618 {
4619 	enum {
4620 		OPT_FILTER_TEST,
4621 		OPT_FILTER_DEVICE,
4622 		OPT_FILTER_GROUP,
4623 		OPT_FILTER_DEVICELESS,
4624 		OPT_XML_PREFIX,
4625 		OPT_JOBS,
4626 		OPT_LIST,
4627 		OPT_VERBOSE,
4628 	};
4629 	static const struct option opts[] = {
4630 		{ "filter-test", 1, 0, OPT_FILTER_TEST },
4631 		{ "filter-device", 1, 0, OPT_FILTER_DEVICE },
4632 		{ "filter-group", 1, 0, OPT_FILTER_GROUP },
4633 		{ "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS },
4634 		{ "xml-output", 1, 0, OPT_XML_PREFIX },
4635 		{ "jobs", 1, 0, OPT_JOBS },
4636 		{ "list", 0, 0, OPT_LIST },
4637 		{ "verbose", 0, 0, OPT_VERBOSE },
4638 		{ "help", 0, 0, 'h'},
4639 		{ 0, 0, 0, 0}
4640 	};
4641 	enum {
4642 		JOBS_DEFAULT,
4643 		JOBS_SINGLE,
4644 		JOBS_CUSTOM
4645 	} want_jobs = JOBS_DEFAULT;
4646 	char *builddir;
4647 	char *jobs_env;
4648 
4649 	/* If we are not running from the builddir, we assume we're running
4650 	 * against the system as installed */
4651 	builddir = builddir_lookup();
4652 	if (!builddir)
4653 		use_system_rules_quirks = true;
4654 	free(builddir);
4655 
4656 	if (in_debugger)
4657 		want_jobs = JOBS_SINGLE;
4658 
4659 	if ((jobs_env = getenv("LITEST_JOBS"))) {
4660 		if (!safe_atoi(jobs_env, &jobs)) {
4661 			fprintf(stderr, "LITEST_JOBS environment variable must be positive integer\n");
4662 			exit(EXIT_FAILURE);
4663 		}
4664 	}
4665 
4666 	while(1) {
4667 		int c;
4668 		int option_index = 0;
4669 
4670 		c = getopt_long(argc, argv, "j:", opts, &option_index);
4671 		if (c == -1)
4672 			break;
4673 		switch(c) {
4674 		default:
4675 		case 'h':
4676 			printf("Usage: %s [--verbose] [--jobs] [--filter-...]\n"
4677 			       "\n"
4678 			       "Options:\n"
4679 			       "    --filter-test=.... \n"
4680 			       "          Glob to filter on test names\n"
4681 			       "    --filter-device=.... \n"
4682 			       "          Glob to filter on device names\n"
4683 			       "    --filter-group=.... \n"
4684 			       "          Glob to filter on test groups\n"
4685 			       "    --filter-deviceless=.... \n"
4686 			       "          Glob to filter on tests that do not create test devices\n"
4687 			       "    --xml-output=/path/to/file-XXXXXXX.xml\n"
4688 			       "          Write test output in libcheck's XML format\n"
4689 			       "          to the given files. The file must match the format\n"
4690 			       "          prefix-XXXXXX.xml and only the prefix is your choice.\n"
4691 			       "    --verbose\n"
4692 			       "          Enable verbose output\n"
4693 			       "    --jobs 8\n"
4694 			       "          Number of parallel test suites to run (default: 8).\n"
4695 			       "	  This overrides the LITEST_JOBS environment variable.\n"
4696 			       "    --list\n"
4697 			       "          List all tests\n"
4698 			       "\n"
4699 			       "See the libinput-test-suite(1) man page for details.\n",
4700 			       program_invocation_short_name);
4701 			exit(c != 'h');
4702 			break;
4703 		case OPT_FILTER_TEST:
4704 			filter_test = optarg;
4705 			if (want_jobs == JOBS_DEFAULT)
4706 				want_jobs = JOBS_SINGLE;
4707 			break;
4708 		case OPT_FILTER_DEVICE:
4709 			filter_device = optarg;
4710 			if (want_jobs == JOBS_DEFAULT)
4711 				want_jobs = JOBS_SINGLE;
4712 			break;
4713 		case OPT_FILTER_GROUP:
4714 			filter_group = optarg;
4715 			break;
4716 		case OPT_XML_PREFIX:
4717 			xml_prefix = optarg;
4718 			break;
4719 		case 'j':
4720 		case OPT_JOBS:
4721 			jobs = atoi(optarg);
4722 			want_jobs = JOBS_CUSTOM;
4723 			break;
4724 		case OPT_LIST:
4725 			return LITEST_MODE_LIST;
4726 		case OPT_VERBOSE:
4727 			verbose = true;
4728 			break;
4729 		case OPT_FILTER_DEVICELESS:
4730 			run_deviceless = true;
4731 			break;
4732 		}
4733 	}
4734 
4735 	if (want_jobs == JOBS_SINGLE)
4736 		jobs = 1;
4737 
4738 	return LITEST_MODE_TEST;
4739 }
4740 
4741 #ifndef LITEST_NO_MAIN
4742 static bool
is_debugger_attached(void)4743 is_debugger_attached(void)
4744 {
4745 	int status;
4746 	bool rc;
4747 	int pid = fork();
4748 
4749 	if (pid == -1)
4750 		return 0;
4751 
4752 	if (pid == 0) {
4753 		int ppid = getppid();
4754 		if (ptrace(PTRACE_ATTACH, ppid, NULL, 0) == 0) {
4755 			waitpid(ppid, NULL, 0);
4756 			ptrace(PTRACE_CONT, ppid, NULL, 0);
4757 			ptrace(PTRACE_DETACH, ppid, NULL, 0);
4758 			rc = false;
4759 		} else {
4760 			rc = true;
4761 		}
4762 		_exit(rc);
4763 	} else {
4764 		waitpid(pid, &status, 0);
4765 		rc = WEXITSTATUS(status);
4766 	}
4767 
4768 	return !!rc;
4769 }
4770 
4771 static void
litest_list_tests(struct list *tests)4772 litest_list_tests(struct list *tests)
4773 {
4774 	struct suite *s;
4775 	const char *last_test_name = NULL;
4776 
4777 	list_for_each(s, tests, node) {
4778 		struct test *t;
4779 		printf("%s:\n", s->name);
4780 		list_for_each(t, &s->tests, node) {
4781 			if (!last_test_name ||
4782 			    !streq(last_test_name, t->name))
4783 				printf("	%s:\n", t->name);
4784 
4785 			last_test_name = t->name;
4786 
4787 			printf("		%s\n", t->devname);
4788 		}
4789 	}
4790 }
4791 
4792 extern const struct test_device __start_test_section, __stop_test_section;
4793 
4794 static void
litest_init_test_devices(void)4795 litest_init_test_devices(void)
4796 {
4797 	const struct test_device *t;
4798 
4799 	list_init(&devices);
4800 
4801 	for (t = &__start_test_section; t < &__stop_test_section; t++)
4802 		list_append(&devices, &t->device->node);
4803 }
4804 
4805 extern const struct test_collection __start_test_collection_section,
4806 				    __stop_test_collection_section;
4807 
4808 static void
setup_tests(void)4809 setup_tests(void)
4810 {
4811 	const struct test_collection *c;
4812 
4813 	for (c = &__start_test_collection_section;
4814 	     c < &__stop_test_collection_section;
4815 	     c++) {
4816 		c->setup();
4817 	}
4818 }
4819 
4820 static int
check_device_access(void)4821 check_device_access(void)
4822 {
4823 	if (getuid() != 0) {
4824 		fprintf(stderr,
4825 			"%s must be run as root.\n",
4826 			program_invocation_short_name);
4827 		return 77;
4828 	}
4829 
4830 	if (access("/dev/uinput", F_OK) == -1 &&
4831 	    access("/dev/input/uinput", F_OK) == -1) {
4832 		fprintf(stderr,
4833 			"uinput device is missing, skipping tests.\n");
4834 		return 77;
4835 	}
4836 
4837 	return 0;
4838 }
4839 
4840 static int
disable_tty(void)4841 disable_tty(void)
4842 {
4843 	int tty_mode = -1;
4844 
4845 	/* If we're running 'normally' on the VT, disable the keyboard to
4846 	 * avoid messing up our host. But if we're inside gdb or running
4847 	 * without forking, leave it as-is.
4848 	 */
4849 	if (!run_deviceless &&
4850 	    jobs > 1 &&
4851 	    !in_debugger &&
4852 	    getenv("CK_FORK") == NULL &&
4853 	    isatty(STDIN_FILENO) &&
4854 	    ioctl(STDIN_FILENO, KDGKBMODE, &tty_mode) == 0) {
4855 #ifdef __linux__
4856 		ioctl(STDIN_FILENO, KDSKBMODE, K_OFF);
4857 #elif __FreeBSD__
4858 		ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
4859 
4860 		/* Put the tty into raw mode */
4861 		struct termios tios;
4862 		if (tcgetattr(STDIN_FILENO, &tios))
4863 				fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno));
4864 		cfmakeraw(&tios);
4865 		if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios))
4866 				fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno));
4867 #endif
4868 	}
4869 
4870 	return tty_mode;
4871 }
4872 
4873 int
main(int argc, char **argv)4874 main(int argc, char **argv)
4875 {
4876 	const struct rlimit corelimit = { 0, 0 };
4877 	enum litest_mode mode;
4878 	int tty_mode = -1;
4879 	int failed_tests;
4880 	int rc;
4881 	const char *meson_testthreads;
4882 
4883 	in_debugger = is_debugger_attached();
4884 	if (in_debugger || RUNNING_ON_VALGRIND)
4885 		setenv("CK_FORK", "no", 0);
4886 
4887 	if ((meson_testthreads = getenv("MESON_TESTTHREADS")) == NULL ||
4888 	     !safe_atoi(meson_testthreads, &jobs)) {
4889 		jobs = get_nprocs();
4890 		if (!RUNNING_ON_VALGRIND)
4891 			jobs *= 2;
4892 	}
4893 
4894 	mode = litest_parse_argv(argc, argv);
4895 	if (mode == LITEST_MODE_ERROR)
4896 		return EXIT_FAILURE;
4897 
4898 	litest_init_test_devices();
4899 	list_init(&all_tests);
4900 	setup_tests();
4901 	if (mode == LITEST_MODE_LIST) {
4902 		litest_list_tests(&all_tests);
4903 		return EXIT_SUCCESS;
4904 	}
4905 
4906 	if (!run_deviceless && (rc = check_device_access()) != 0)
4907 		return rc;
4908 
4909 	setenv("CK_DEFAULT_TIMEOUT", "30", 0);
4910 	setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1);
4911 
4912 	if (setrlimit(RLIMIT_CORE, &corelimit) != 0)
4913 		perror("WARNING: Core dumps not disabled");
4914 
4915 	tty_mode = disable_tty();
4916 
4917 	failed_tests = litest_run(argc, argv);
4918 
4919 	if (tty_mode != -1) {
4920 		ioctl(STDIN_FILENO, KDSKBMODE, tty_mode);
4921 #ifdef __FreeBSD__
4922 		/* Put the tty into "sane" mode */
4923 		struct termios tios;
4924 		if (tcgetattr(STDIN_FILENO, &tios))
4925 				fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno));
4926 		cfmakesane(&tios);
4927 		if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios))
4928 				fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno));
4929 #endif
4930 	}
4931 
4932 	return min(failed_tests, 255);
4933 }
4934 #endif
4935