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