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 <libudev.h>
50 #if HAVE_LIBSYSTEMD
51 #include <systemd/sd-bus.h>
52 #endif
53 #ifdef __FreeBSD__
54 #include <termios.h>
55 #endif
56 
57 #include "litest.h"
58 #include "litest-int.h"
59 #include "libinput-util.h"
60 #include "quirks.h"
61 
62 #include <linux/kd.h>
63 
64 #define UDEV_RULES_D "/run/udev/rules.d"
65 #define UDEV_RULE_PREFIX "99-litest-"
66 #define UDEV_HWDB_D "/etc/udev/hwdb.d"
67 #define UDEV_MODEL_QUIRKS_RULE_FILE UDEV_RULES_D \
68 	"/91-litest-model-quirks-REMOVEME-XXXXXX.rules"
69 #define UDEV_MODEL_QUIRKS_HWDB_FILE UDEV_HWDB_D \
70 	"/91-litest-model-quirks-REMOVEME-XXXXXX.hwdb"
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 = 8;
77 static bool in_debugger = false;
78 static bool verbose = false;
79 static bool run_deviceless = false;
80 const char *filter_test = NULL;
81 const char *filter_device = NULL;
82 const char *filter_group = NULL;
83 static struct quirks_context *quirks_context;
84 
85 struct created_file {
86 	struct list link;
87 	char *path;
88 };
89 
90 struct list created_files_list; /* list of all files to remove at the end of
91 				   the test run */
92 
93 static void litest_init_udev_rules(struct list *created_files_list);
94 static void litest_remove_udev_rules(struct list *created_files_list);
95 static inline char *litest_install_quirks(struct list *created_files_list);
96 
97 /* defined for the litest selftest */
98 #ifndef LITEST_DISABLE_BACKTRACE_LOGGING
99 #define litest_log(...) fprintf(stderr, __VA_ARGS__)
100 #define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
101 #else
102 #define litest_log(...) { /* __VA_ARGS__ */ }
103 #define litest_vlog(...) { /* __VA_ARGS__ */ }
104 #endif
105 
106 static void
litest_backtrace(void)107 litest_backtrace(void)
108 {
109 #if HAVE_GSTACK
110 	pid_t parent, child;
111 	int pipefd[2];
112 
113 	if (pipe(pipefd) == -1)
114 		return;
115 
116 	parent = getpid();
117 	child = fork();
118 
119 	if (child == 0) {
120 		char pid[8];
121 
122 		close(pipefd[0]);
123 		dup2(pipefd[1], STDOUT_FILENO);
124 
125 		sprintf(pid, "%d", parent);
126 
127 		execlp("gstack", "gstack", pid, NULL);
128 		exit(errno);
129 	}
130 
131 	/* parent */
132 	char buf[1024];
133 	int status, nread;
134 
135 	close(pipefd[1]);
136 	waitpid(child, &status, 0);
137 
138 	status = WEXITSTATUS(status);
139 	if (status != 0) {
140 		litest_log("ERROR: gstack failed, no backtrace available: %s\n",
141 			   strerror(status));
142 	} else {
143 		litest_log("\nBacktrace:\n");
144 		while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
145 			buf[nread] = '\0';
146 			litest_log("%s", buf);
147 		}
148 		litest_log("\n");
149 	}
150 	close(pipefd[0]);
151 #endif
152 }
153 
154 LIBINPUT_ATTRIBUTE_PRINTF(5, 6)
155 __attribute__((noreturn))
156 void
litest_fail_condition(const char * file,int line,const char * func,const char * condition,const char * message,...)157 litest_fail_condition(const char *file,
158 		      int line,
159 		      const char *func,
160 		      const char *condition,
161 		      const char *message,
162 		      ...)
163 {
164 	litest_log("FAILED: %s\n", condition);
165 
166 	if (message) {
167 		va_list args;
168 		va_start(args, message);
169 		litest_vlog(message, args);
170 		va_end(args);
171 	}
172 
173 	litest_log("in %s() (%s:%d)\n", func, file, line);
174 	litest_backtrace();
175 	abort();
176 }
177 
178 __attribute__((noreturn))
179 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)180 litest_fail_comparison_int(const char *file,
181 			   int line,
182 			   const char *func,
183 			   const char *operator,
184 			   int a,
185 			   int b,
186 			   const char *astr,
187 			   const char *bstr)
188 {
189 	litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
190 	litest_log("Resolved to: %d %s %d\n", a, operator, b);
191 	litest_log("in %s() (%s:%d)\n", func, file, line);
192 	litest_backtrace();
193 	abort();
194 }
195 
196 __attribute__((noreturn))
197 void
litest_fail_comparison_ptr(const char * file,int line,const char * func,const char * comparison)198 litest_fail_comparison_ptr(const char *file,
199 			   int line,
200 			   const char *func,
201 			   const char *comparison)
202 {
203 	litest_log("FAILED COMPARISON: %s\n", comparison);
204 	litest_log("in %s() (%s:%d)\n", func, file, line);
205 	litest_backtrace();
206 	abort();
207 }
208 
209 struct test {
210 	struct list node;
211 	char *name;
212 	char *devname;
213 	void *func;
214 	void *setup;
215 	void *teardown;
216 
217 	struct range range;
218 	bool deviceless;
219 };
220 
221 struct suite {
222 	struct list node;
223 	struct list tests;
224 	char *name;
225 };
226 
227 static struct litest_device *current_device;
228 
litest_current_device(void)229 struct litest_device *litest_current_device(void)
230 {
231 	return current_device;
232 }
233 
litest_set_current_device(struct litest_device * device)234 void litest_set_current_device(struct litest_device *device)
235 {
236 	current_device = device;
237 }
238 
litest_generic_device_teardown(void)239 void litest_generic_device_teardown(void)
240 {
241 	litest_delete_device(current_device);
242 	current_device = NULL;
243 }
244 
245 struct list devices;
246 
247 static struct list all_tests;
248 
249 static inline void
litest_system(const char * command)250 litest_system(const char *command)
251 {
252 	int ret;
253 
254 	ret = system(command);
255 
256 	if (ret == -1) {
257 		litest_abort_msg("Failed to execute: %s", command);
258 	} else if (WIFEXITED(ret)) {
259 		if (WEXITSTATUS(ret))
260 			litest_abort_msg("'%s' failed with %d",
261 					 command,
262 					 WEXITSTATUS(ret));
263 	} else if (WIFSIGNALED(ret)) {
264 		litest_abort_msg("'%s' terminated with signal %d",
265 				 command,
266 				 WTERMSIG(ret));
267 	}
268 }
269 
270 static void
litest_reload_udev_rules(void)271 litest_reload_udev_rules(void)
272 {
273 	litest_system("udevadm control --reload-rules");
274 	litest_system("udevadm hwdb --update");
275 }
276 
277 static void
litest_add_tcase_for_device(struct suite * suite,const char * funcname,void * func,const struct litest_test_device * dev,const struct range * range)278 litest_add_tcase_for_device(struct suite *suite,
279 			    const char *funcname,
280 			    void *func,
281 			    const struct litest_test_device *dev,
282 			    const struct range *range)
283 {
284 	struct test *t;
285 
286 	t = zalloc(sizeof(*t));
287 	t->name = safe_strdup(funcname);
288 	t->devname = safe_strdup(dev->shortname);
289 	t->func = func;
290 	t->setup = dev->setup;
291 	t->teardown = dev->teardown ?
292 			dev->teardown : litest_generic_device_teardown;
293 	if (range)
294 		t->range = *range;
295 
296 	list_insert(&suite->tests, &t->node);
297 }
298 
299 static void
litest_add_tcase_no_device(struct suite * suite,void * func,const char * funcname,const struct range * range)300 litest_add_tcase_no_device(struct suite *suite,
301 			   void *func,
302 			   const char *funcname,
303 			   const struct range *range)
304 {
305 	struct test *t;
306 	const char *test_name = funcname;
307 
308 	if (filter_device &&
309 	    fnmatch(filter_device, test_name, 0) != 0)
310 		return;
311 
312 	t = zalloc(sizeof(*t));
313 	t->name = safe_strdup(test_name);
314 	t->devname = safe_strdup("no device");
315 	t->func = func;
316 	if (range)
317 		t->range = *range;
318 	t->setup = NULL;
319 	t->teardown = NULL;
320 
321 	list_insert(&suite->tests, &t->node);
322 }
323 
324 static void
litest_add_tcase_deviceless(struct suite * suite,void * func,const char * funcname,const struct range * range)325 litest_add_tcase_deviceless(struct suite *suite,
326 			    void *func,
327 			    const char *funcname,
328 			    const struct range *range)
329 {
330 	struct test *t;
331 	const char *test_name = funcname;
332 
333 	if (filter_device &&
334 	    fnmatch(filter_device, test_name, 0) != 0)
335 		return;
336 
337 	t = zalloc(sizeof(*t));
338 	t->deviceless = true;
339 	t->name = safe_strdup(test_name);
340 	t->devname = safe_strdup("deviceless");
341 	t->func = func;
342 	if (range)
343 		t->range = *range;
344 	t->setup = NULL;
345 	t->teardown = NULL;
346 
347 	list_insert(&suite->tests, &t->node);
348 }
349 
350 static struct suite *
get_suite(const char * name)351 get_suite(const char *name)
352 {
353 	struct suite *s;
354 
355 	list_for_each(s, &all_tests, node) {
356 		if (streq(s->name, name))
357 			return s;
358 	}
359 
360 	s = zalloc(sizeof(*s));
361 	s->name = safe_strdup(name);
362 
363 	list_init(&s->tests);
364 	list_insert(&all_tests, &s->node);
365 
366 	return s;
367 }
368 
369 static void
litest_add_tcase(const char * suite_name,const char * funcname,void * func,enum litest_device_feature required,enum litest_device_feature excluded,const struct range * range)370 litest_add_tcase(const char *suite_name,
371 		 const char *funcname,
372 		 void *func,
373 		 enum litest_device_feature required,
374 		 enum litest_device_feature excluded,
375 		 const struct range *range)
376 {
377 	struct suite *suite;
378 	bool added = false;
379 
380 	litest_assert(required >= LITEST_DEVICELESS);
381 	litest_assert(excluded >= LITEST_DEVICELESS);
382 
383 	if (filter_test &&
384 	    fnmatch(filter_test, funcname, 0) != 0)
385 		return;
386 
387 	if (filter_group &&
388 	    fnmatch(filter_group, suite_name, 0) != 0)
389 		return;
390 
391 	suite = get_suite(suite_name);
392 
393 	if (required == LITEST_DEVICELESS &&
394 	    excluded == LITEST_DEVICELESS) {
395 		litest_add_tcase_deviceless(suite, func, funcname, range);
396 		added = true;
397 	} else if (required == LITEST_DISABLE_DEVICE &&
398 	    excluded == LITEST_DISABLE_DEVICE) {
399 		litest_add_tcase_no_device(suite, func, funcname, range);
400 		added = true;
401 	} else if (required != LITEST_ANY || excluded != LITEST_ANY) {
402 		struct litest_test_device *dev;
403 
404 		list_for_each(dev, &devices, node) {
405 			if (dev->features & LITEST_IGNORED)
406 				continue;
407 
408 			if (filter_device &&
409 			    fnmatch(filter_device, dev->shortname, 0) != 0)
410 				continue;
411 			if ((dev->features & required) != required ||
412 			    (dev->features & excluded) != 0)
413 				continue;
414 
415 			litest_add_tcase_for_device(suite,
416 						    funcname,
417 						    func,
418 						    dev,
419 						    range);
420 			added = true;
421 		}
422 	} else {
423 		struct litest_test_device *dev;
424 
425 		list_for_each(dev, &devices, node) {
426 			if (dev->features & LITEST_IGNORED)
427 				continue;
428 
429 			if (filter_device &&
430 			    fnmatch(filter_device, dev->shortname, 0) != 0)
431 				continue;
432 
433 			litest_add_tcase_for_device(suite,
434 						    funcname,
435 						    func,
436 						    dev,
437 						    range);
438 			added = true;
439 		}
440 	}
441 
442 	if (!added &&
443 	    filter_test == NULL &&
444 	    filter_device == NULL &&
445 	    filter_group == NULL) {
446 		fprintf(stderr, "Test '%s' does not match any devices. Aborting.\n", funcname);
447 		abort();
448 	}
449 }
450 
451 void
_litest_add_no_device(const char * name,const char * funcname,void * func)452 _litest_add_no_device(const char *name, const char *funcname, void *func)
453 {
454 	_litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
455 }
456 
457 void
_litest_add_ranged_no_device(const char * name,const char * funcname,void * func,const struct range * range)458 _litest_add_ranged_no_device(const char *name,
459 			     const char *funcname,
460 			     void *func,
461 			     const struct range *range)
462 {
463 	_litest_add_ranged(name,
464 			   funcname,
465 			   func,
466 			   LITEST_DISABLE_DEVICE,
467 			   LITEST_DISABLE_DEVICE,
468 			   range);
469 }
470 
471 void
_litest_add_deviceless(const char * name,const char * funcname,void * func)472 _litest_add_deviceless(const char *name,
473 		       const char *funcname,
474 		       void *func)
475 {
476 	_litest_add_ranged(name,
477 			   funcname,
478 			   func,
479 			   LITEST_DEVICELESS,
480 			   LITEST_DEVICELESS,
481 			   NULL);
482 }
483 
484 void
_litest_add(const char * name,const char * funcname,void * func,enum litest_device_feature required,enum litest_device_feature excluded)485 _litest_add(const char *name,
486 	    const char *funcname,
487 	    void *func,
488 	    enum litest_device_feature required,
489 	    enum litest_device_feature excluded)
490 {
491 	_litest_add_ranged(name,
492 			   funcname,
493 			   func,
494 			   required,
495 			   excluded,
496 			   NULL);
497 }
498 
499 void
_litest_add_ranged(const char * name,const char * funcname,void * func,enum litest_device_feature required,enum litest_device_feature excluded,const struct range * range)500 _litest_add_ranged(const char *name,
501 		   const char *funcname,
502 		   void *func,
503 		   enum litest_device_feature required,
504 		   enum litest_device_feature excluded,
505 		   const struct range *range)
506 {
507 	litest_add_tcase(name, funcname, func, required, excluded, range);
508 }
509 
510 void
_litest_add_for_device(const char * name,const char * funcname,void * func,enum litest_device_type type)511 _litest_add_for_device(const char *name,
512 		       const char *funcname,
513 		       void *func,
514 		       enum litest_device_type type)
515 {
516 	_litest_add_ranged_for_device(name, funcname, func, type, NULL);
517 }
518 
519 void
_litest_add_ranged_for_device(const char * name,const char * funcname,void * func,enum litest_device_type type,const struct range * range)520 _litest_add_ranged_for_device(const char *name,
521 			      const char *funcname,
522 			      void *func,
523 			      enum litest_device_type type,
524 			      const struct range *range)
525 {
526 	struct suite *s;
527 	struct litest_test_device *dev;
528 	bool device_filtered = false;
529 
530 	litest_assert(type < LITEST_NO_DEVICE);
531 
532 	if (filter_test &&
533 	    fnmatch(filter_test, funcname, 0) != 0)
534 		return;
535 
536 	if (filter_group &&
537 	    fnmatch(filter_group, name, 0) != 0)
538 		return;
539 
540 	s = get_suite(name);
541 	list_for_each(dev, &devices, node) {
542 		if (filter_device &&
543 		    fnmatch(filter_device, dev->shortname, 0) != 0) {
544 			device_filtered = true;
545 			continue;
546 		}
547 
548 		if (dev->type == type) {
549 			litest_add_tcase_for_device(s,
550 						    funcname,
551 						    func,
552 						    dev,
553 						    range);
554 			return;
555 		}
556 	}
557 
558 	/* only abort if no filter was set, that's a bug */
559 	if (!device_filtered)
560 		litest_abort_msg("Invalid test device type\n");
561 }
562 
563 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
564 static void
litest_log_handler(struct libinput * libinput,enum libinput_log_priority pri,const char * format,va_list args)565 litest_log_handler(struct libinput *libinput,
566 		   enum libinput_log_priority pri,
567 		   const char *format,
568 		   va_list args)
569 {
570 	static int is_tty = -1;
571 	const char *priority = NULL;
572 	const char *color;
573 
574 	if (is_tty == -1)
575 		is_tty = isatty(STDERR_FILENO);
576 
577 	switch(pri) {
578 	case LIBINPUT_LOG_PRIORITY_INFO:
579 		priority =  "info ";
580 		color = ANSI_HIGHLIGHT;
581 		break;
582 	case LIBINPUT_LOG_PRIORITY_ERROR:
583 		priority = "error";
584 		color = ANSI_BRIGHT_RED;
585 		break;
586 	case LIBINPUT_LOG_PRIORITY_DEBUG:
587 		priority = "debug";
588 		color = ANSI_NORMAL;
589 		break;
590 	default:
591 		  abort();
592 	}
593 
594 	if (!is_tty)
595 		color = "";
596 	else if (strstr(format, "tap:"))
597 		color = ANSI_BLUE;
598 	else if (strstr(format, "thumb state:"))
599 		color = ANSI_YELLOW;
600 	else if (strstr(format, "button state:"))
601 		color = ANSI_MAGENTA;
602 	else if (strstr(format, "touch-size:") ||
603 		 strstr(format, "pressure:"))
604 		color = ANSI_GREEN;
605 	else if (strstr(format, "palm:") ||
606 		 strstr(format, "thumb:"))
607 		color = ANSI_CYAN;
608 	else if (strstr(format, "edge-scroll:"))
609 		color = ANSI_BRIGHT_GREEN;
610 
611 	fprintf(stderr, "%slitest %s ", color, priority);
612 	vfprintf(stderr, format, args);
613 	if (is_tty)
614 		fprintf(stderr, ANSI_NORMAL);
615 
616 	if (strstr(format, "client bug: ") ||
617 	    strstr(format, "libinput bug: ")) {
618 		/* valgrind is too slow and some of our offsets are too
619 		 * short, don't abort if during a valgrind run we get a
620 		 * negative offset */
621 		if (!getenv("USING_VALGRIND") ||
622 		    !strstr(format, "offset negative"))
623 		litest_abort_msg("libinput bug triggered, aborting.\n");
624 	}
625 
626 	if (strstr(format, "Touch jump detected and discarded")) {
627 		litest_abort_msg("libinput touch jump triggered, aborting.\n");
628 	}
629 }
630 
631 static char *
632 litest_init_device_udev_rules(struct litest_test_device *dev);
633 
634 static void
litest_init_all_device_udev_rules(struct list * created_files)635 litest_init_all_device_udev_rules(struct list *created_files)
636 {
637 	struct litest_test_device *dev;
638 
639 	list_for_each(dev, &devices, node) {
640 		char *udev_file;
641 
642 		udev_file = litest_init_device_udev_rules(dev);
643 		if (udev_file) {
644 			struct created_file *file = zalloc(sizeof(*file));
645 			file->path = udev_file;
646 			list_insert(created_files, &file->link);
647 		}
648 	}
649 }
650 
651 static int
open_restricted(const char * path,int flags,void * userdata)652 open_restricted(const char *path, int flags, void *userdata)
653 {
654 	int fd = open(path, flags);
655 	return fd < 0 ? -errno : fd;
656 }
657 
658 static void
close_restricted(int fd,void * userdata)659 close_restricted(int fd, void *userdata)
660 {
661 	close(fd);
662 }
663 
664 struct libinput_interface interface = {
665 	.open_restricted = open_restricted,
666 	.close_restricted = close_restricted,
667 };
668 
669 static void
litest_signal(int sig)670 litest_signal(int sig)
671 {
672 	struct created_file *f, *tmp;
673 
674 	list_for_each_safe(f, tmp, &created_files_list, link) {
675 		list_remove(&f->link);
676 		unlink(f->path);
677 		rmdir(f->path);
678 		/* in the sighandler, we can't free */
679 	}
680 
681 	if (fork() == 0) {
682 		/* child, we can run system() */
683 		litest_reload_udev_rules();
684 		exit(0);
685 	}
686 
687 	exit(1);
688 }
689 
690 static inline void
litest_setup_sighandler(int sig)691 litest_setup_sighandler(int sig)
692 {
693 	struct sigaction act, oact;
694 	int rc;
695 
696 	sigemptyset(&act.sa_mask);
697 	sigaddset(&act.sa_mask, sig);
698 	act.sa_flags = 0;
699 	act.sa_handler = litest_signal;
700 	rc = sigaction(sig, &act, &oact);
701 	litest_assert_int_ne(rc, -1);
702 }
703 
704 static void
litest_free_test_list(struct list * tests)705 litest_free_test_list(struct list *tests)
706 {
707 	struct suite *s, *snext;
708 
709 	list_for_each_safe(s, snext, tests, node) {
710 		struct test *t, *tnext;
711 
712 		list_for_each_safe(t, tnext, &s->tests, node) {
713 			free(t->name);
714 			free(t->devname);
715 			list_remove(&t->node);
716 			free(t);
717 		}
718 
719 		list_remove(&s->node);
720 		free(s->name);
721 		free(s);
722 	}
723 }
724 
725 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
726 static inline void
quirk_log_handler(struct libinput * unused,enum libinput_log_priority priority,const char * format,va_list args)727 quirk_log_handler(struct libinput *unused,
728 		  enum libinput_log_priority priority,
729 		  const char *format,
730 		  va_list args)
731 {
732 	if (priority < LIBINPUT_LOG_PRIORITY_ERROR)
733 		return;
734 
735 	vfprintf(stderr, format, args);
736 }
737 
738 static int
litest_run_suite(struct list * tests,int which,int max,int error_fd)739 litest_run_suite(struct list *tests, int which, int max, int error_fd)
740 {
741 	int failed = 0;
742 	SRunner *sr = NULL;
743 	struct suite *s;
744 	struct test *t;
745 	int count = -1;
746 	struct name {
747 		struct list node;
748 		char *name;
749 	};
750 	struct name *n, *tmp;
751 	struct list testnames;
752 
753 	quirks_context = quirks_init_subsystem(getenv("LIBINPUT_QUIRKS_DIR"),
754 					       NULL,
755 					       quirk_log_handler,
756 					       NULL,
757 					       QLOG_LIBINPUT_LOGGING);
758 
759 	/* Check just takes the suite/test name pointers but doesn't strdup
760 	 * them - we have to keep them around */
761 	list_init(&testnames);
762 
763 	/* For each test, create one test suite with one test case, then
764 	   add it to the test runner. The only benefit suites give us in
765 	   check is that we can filter them, but our test runner has a
766 	   --filter-group anyway. */
767 	list_for_each(s, tests, node) {
768 		list_for_each(t, &s->tests, node) {
769 			Suite *suite;
770 			TCase *tc;
771 			char *sname, *tname;
772 
773 			/* We run deviceless tests as part of the normal
774 			 * test suite runner, just in case. Filtering
775 			 * all the other ones out just for the case where
776 			 * we can't run the full runner.
777 			 */
778 			if (run_deviceless && !t->deviceless)
779 				continue;
780 
781 			count = (count + 1) % max;
782 			if (max != 1 && (count % max) != which)
783 				continue;
784 
785 			xasprintf(&sname,
786 				  "%s:%s:%s",
787 				  s->name,
788 				  t->name,
789 				  t->devname);
790 			litest_assert(sname != NULL);
791 			n = zalloc(sizeof(*n));
792 			n->name = sname;
793 			list_insert(&testnames, &n->node);
794 
795 			xasprintf(&tname,
796 				  "%s:%s",
797 				  t->name,
798 				  t->devname);
799 			litest_assert(tname != NULL);
800 			n = zalloc(sizeof(*n));
801 			n->name = tname;
802 			list_insert(&testnames, &n->node);
803 
804 			tc = tcase_create(tname);
805 			tcase_add_checked_fixture(tc,
806 						  t->setup,
807 						  t->teardown);
808 			if (t->range.upper != t->range.lower)
809 				tcase_add_loop_test(tc,
810 						    t->func,
811 						    t->range.lower,
812 						    t->range.upper);
813 			else
814 				tcase_add_test(tc, t->func);
815 
816 			suite = suite_create(sname);
817 			suite_add_tcase(suite, tc);
818 
819 			if (!sr)
820 				sr = srunner_create(suite);
821 			else
822 				srunner_add_suite(sr, suite);
823 		}
824 	}
825 
826 	if (!sr)
827 		goto out;
828 
829 	srunner_run_all(sr, CK_ENV);
830 	failed = srunner_ntests_failed(sr);
831 	if (failed) {
832 		TestResult **trs;
833 
834 		trs = srunner_failures(sr);
835 		for (int i = 0; i < failed; i++) {
836 			dprintf(error_fd,
837 				":: Failure: %s:%d:%s\n",
838 				tr_lfile(trs[i]),
839 				tr_lno(trs[i]),
840 				tr_tcname(trs[i]));
841 		}
842 		free(trs);
843 	}
844 	srunner_free(sr);
845 out:
846 	list_for_each_safe(n, tmp, &testnames, node) {
847 		free(n->name);
848 		free(n);
849 	}
850 
851 	quirks_context_unref(quirks_context);
852 
853 	return failed;
854 }
855 
856 static int
litest_fork_subtests(struct list * tests,int max_forks)857 litest_fork_subtests(struct list *tests, int max_forks)
858 {
859 	int failed = 0;
860 	int status;
861 	pid_t pid;
862 	int f;
863 	int pipes[max_forks];
864 
865 	for (f = 0; f < max_forks; f++) {
866 		int rc;
867 		int pipefd[2];
868 
869 		rc = pipe2(pipefd, O_NONBLOCK|O_NONBLOCK);
870 		assert(rc != -1);
871 
872 		pid = fork();
873 		if (pid == 0) {
874 			close(pipefd[0]);
875 			failed = litest_run_suite(tests,
876 						  f,
877 						  max_forks,
878 						  pipefd[1]);
879 
880 			litest_free_test_list(&all_tests);
881 			exit(failed);
882 			/* child always exits here */
883 		} else {
884 			pipes[f] = pipefd[0];
885 			close(pipefd[1]);
886 		}
887 	}
888 
889 	/* parent process only */
890 	while (wait(&status) != -1 && errno != ECHILD) {
891 		if (WEXITSTATUS(status) != 0)
892 			failed = 1;
893 	}
894 
895 	for (f = 0; f < max_forks; f++) {
896 		char buf[1024] = {0};
897 		int rc;
898 
899 		while ((rc = read(pipes[f], buf, sizeof(buf) - 1)) > 0) {
900 			buf[rc] = '\0';
901 			fprintf(stderr, "%s", buf);
902 		}
903 
904 		close(pipes[f]);
905 	}
906 
907 	return failed;
908 }
909 
910 static inline int
inhibit(void)911 inhibit(void)
912 {
913 	int lock_fd = -1;
914 #if HAVE_LIBSYSTEMD
915 	sd_bus_error error = SD_BUS_ERROR_NULL;
916 	sd_bus_message *m = NULL;
917 	sd_bus *bus = NULL;
918 	int rc;
919 
920 	if (run_deviceless)
921 		return -1;
922 
923 	rc = sd_bus_open_system(&bus);
924 	if (rc != 0) {
925 		fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
926 		goto out;
927 	}
928 
929 	rc = sd_bus_call_method(bus,
930 				"org.freedesktop.login1",
931 				"/org/freedesktop/login1",
932 				"org.freedesktop.login1.Manager",
933 				"Inhibit",
934 				&error,
935 				&m,
936 				"ssss",
937 				"handle-lid-switch:handle-power-key:handle-suspend-key:handle-hibernate-key",
938 				"libinput test-suite runner",
939 				"testing in progress",
940 				"block");
941 	if (rc < 0) {
942 		fprintf(stderr, "Warning: inhibit failed: %s\n", error.message);
943 		goto out;
944 	}
945 
946 	rc = sd_bus_message_read(m, "h", &lock_fd);
947 	if (rc < 0) {
948 		fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
949 		goto out;
950 	}
951 
952 	lock_fd = dup(lock_fd);
953 out:
954 	sd_bus_error_free(&error);
955 	sd_bus_message_unref(m);
956 	sd_bus_close(bus);
957 	sd_bus_unref(bus);
958 #endif
959 	return lock_fd;
960 }
961 
962 static inline int
litest_run(int argc,char ** argv)963 litest_run(int argc, char **argv)
964 {
965 	int failed = 0;
966 	int inhibit_lock_fd;
967 	char *quirks_dir;
968 
969 	list_init(&created_files_list);
970 
971 	if (list_empty(&all_tests)) {
972 		fprintf(stderr,
973 			"Error: filters are too strict, no tests to run.\n");
974 		return 1;
975 	}
976 
977 	if (getenv("LITEST_VERBOSE"))
978 		verbose = true;
979 
980 	if (run_deviceless) {
981 		quirks_dir = safe_strdup(LIBINPUT_QUIRKS_SRCDIR);
982 	} else {
983 		litest_init_udev_rules(&created_files_list);
984 		quirks_dir = litest_install_quirks(&created_files_list);
985 	}
986 	setenv("LIBINPUT_QUIRKS_DIR", quirks_dir, 1);
987 	free(quirks_dir);
988 
989 	litest_setup_sighandler(SIGINT);
990 
991 	inhibit_lock_fd = inhibit();
992 
993 	if (jobs == 1)
994 		failed = litest_run_suite(&all_tests, 1, 1, STDERR_FILENO);
995 	else
996 		failed = litest_fork_subtests(&all_tests, jobs);
997 
998 	close(inhibit_lock_fd);
999 
1000 	litest_free_test_list(&all_tests);
1001 
1002 	litest_remove_udev_rules(&created_files_list);
1003 
1004 	return failed;
1005 }
1006 
1007 static struct input_absinfo *
merge_absinfo(const struct input_absinfo * orig,const struct input_absinfo * override)1008 merge_absinfo(const struct input_absinfo *orig,
1009 	      const struct input_absinfo *override)
1010 {
1011 	struct input_absinfo *abs;
1012 	unsigned int nelem, i;
1013 	size_t sz = ABS_MAX + 1;
1014 
1015 	if (!orig)
1016 		return NULL;
1017 
1018 	abs = zalloc(sz * sizeof(*abs));
1019 	litest_assert(abs != NULL);
1020 
1021 	nelem = 0;
1022 	while (orig[nelem].value != -1) {
1023 		abs[nelem] = orig[nelem];
1024 		nelem++;
1025 		litest_assert_int_lt(nelem, sz);
1026 	}
1027 
1028 	/* just append, if the same axis is present twice, libevdev will
1029 	   only use the last value anyway */
1030 	i = 0;
1031 	while (override && override[i].value != -1) {
1032 		abs[nelem++] = override[i++];
1033 		litest_assert_int_lt(nelem, sz);
1034 	}
1035 
1036 	litest_assert_int_lt(nelem, sz);
1037 	abs[nelem].value = -1;
1038 
1039 	return abs;
1040 }
1041 
1042 static int*
merge_events(const int * orig,const int * override)1043 merge_events(const int *orig, const int *override)
1044 {
1045 	int *events;
1046 	unsigned int nelem, i;
1047 	size_t sz = KEY_MAX * 3;
1048 
1049 	if (!orig)
1050 		return NULL;
1051 
1052 	events = zalloc(sz * sizeof(int));
1053 	litest_assert(events != NULL);
1054 
1055 	nelem = 0;
1056 	while (orig[nelem] != -1) {
1057 		events[nelem] = orig[nelem];
1058 		nelem++;
1059 		litest_assert_int_lt(nelem, sz);
1060 	}
1061 
1062 	/* just append, if the same axis is present twice, libevdev will
1063 	 * ignore the double definition anyway */
1064 	i = 0;
1065 	while (override && override[i] != -1) {
1066 		events[nelem++] = override[i++];
1067 		litest_assert_int_le(nelem, sz);
1068 	}
1069 
1070 	litest_assert_int_lt(nelem, sz);
1071 	events[nelem] = -1;
1072 
1073 	return events;
1074 }
1075 
1076 static inline struct created_file *
litest_copy_file(const char * dest,const char * src,const char * header)1077 litest_copy_file(const char *dest, const char *src, const char *header)
1078 {
1079 	int in, out, length;
1080 	struct created_file *file;
1081 
1082 	file = zalloc(sizeof(*file));
1083 	file->path = safe_strdup(dest);
1084 
1085 	if (strstr(dest, "XXXXXX")) {
1086 		int suffixlen;
1087 
1088 		suffixlen = file->path +
1089 				strlen(file->path) -
1090 				rindex(file->path, '.');
1091 		out = mkstemps(file->path, suffixlen);
1092 	} else {
1093 		out = open(file->path, O_CREAT|O_WRONLY, 0644);
1094 	}
1095 	if (out == -1)
1096 		litest_abort_msg("Failed to write to file %s (%s)\n",
1097 				 file->path,
1098 				 strerror(errno));
1099 	litest_assert_int_ne(chmod(file->path, 0644), -1);
1100 
1101 	if (header) {
1102 		length = strlen(header);
1103 		litest_assert_int_eq(write(out, header, length), length);
1104 	}
1105 
1106 	in = open(src, O_RDONLY);
1107 	if (in == -1)
1108 		litest_abort_msg("Failed to open file %s (%s)\n",
1109 				 src,
1110 				 strerror(errno));
1111 	/* lazy, just check for error and empty file copy */
1112 	litest_assert_int_gt(litest_send_file(out, in), 0);
1113 	close(out);
1114 	close(in);
1115 
1116 	return file;
1117 }
1118 
1119 static inline void
litest_install_model_quirks(struct list * created_files_list)1120 litest_install_model_quirks(struct list *created_files_list)
1121 {
1122 	const char *warning =
1123 			 "#################################################################\n"
1124 			 "# WARNING: REMOVE THIS FILE\n"
1125 			 "# This is a run-time file for the libinput test suite and\n"
1126 			 "# should be removed on exit. If the test-suite is not currently \n"
1127 			 "# running, remove this file and update your hwdb: \n"
1128 			 "#       sudo udevadm hwdb --update\n"
1129 			 "#################################################################\n\n";
1130 	struct created_file *file;
1131 
1132 	file = litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE,
1133 				LIBINPUT_TEST_DEVICE_RULES_FILE,
1134 				warning);
1135 	list_insert(created_files_list, &file->link);
1136 
1137 	file = litest_copy_file(UDEV_DEVICE_GROUPS_FILE,
1138 				LIBINPUT_DEVICE_GROUPS_RULES_FILE,
1139 				warning);
1140 	list_insert(created_files_list, &file->link);
1141 
1142 	file = litest_copy_file(UDEV_MODEL_QUIRKS_RULE_FILE,
1143 				LIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE,
1144 				warning);
1145 	list_insert(created_files_list, &file->link);
1146 }
1147 
1148 static char *
litest_init_device_quirk_file(const char * data_dir,struct litest_test_device * dev)1149 litest_init_device_quirk_file(const char *data_dir,
1150 			      struct litest_test_device *dev)
1151 {
1152 	int fd;
1153 	FILE *f;
1154 	char path[PATH_MAX];
1155 	static int count;
1156 
1157 	if (!dev->quirk_file)
1158 		return NULL;
1159 
1160 	snprintf(path, sizeof(path),
1161 		 "%s/99-%03d-%s.quirks",
1162 		 data_dir,
1163 		 ++count,
1164 		 dev->shortname);
1165 	fd = open(path, O_CREAT|O_WRONLY, 0644);
1166 	litest_assert_int_ne(fd, -1);
1167 	f = fdopen(fd, "w");
1168 	litest_assert_notnull(f);
1169 	litest_assert_int_ge(fputs(dev->quirk_file, f), 0);
1170 	fclose(f);
1171 
1172 	return safe_strdup(path);
1173 }
1174 
1175 
1176 static char *
litest_install_quirks(struct list * created_files_list)1177 litest_install_quirks(struct list *created_files_list)
1178 {
1179 	struct litest_test_device *dev;
1180 	struct created_file *file;
1181 	char dirname[] = "/run/litest-XXXXXX";
1182 	char **quirks, **q;
1183 
1184 	litest_assert_notnull(mkdtemp(dirname));
1185 	litest_assert_int_ne(chmod(dirname, 0755), -1);
1186 
1187 	quirks = strv_from_string(LIBINPUT_QUIRKS_FILES, ":");
1188 	litest_assert(quirks);
1189 
1190 	q = quirks;
1191 	while (*q) {
1192 		const char *quirksdir = "quirks/";
1193 		char *filename;
1194 		char dest[PATH_MAX];
1195 		char src[PATH_MAX];
1196 
1197 		litest_assert(strneq(*q, quirksdir, strlen(quirksdir)));
1198 		filename = &(*q)[strlen(quirksdir)];
1199 
1200 		snprintf(src, sizeof(src), "%s/%s",
1201 			 LIBINPUT_QUIRKS_SRCDIR, filename);
1202 		snprintf(dest, sizeof(dest), "%s/%s", dirname, filename);
1203 		file = litest_copy_file(dest, src, NULL);
1204 		list_append(created_files_list, &file->link);
1205 		q++;
1206 	}
1207 	strv_free(quirks);
1208 
1209 	/* Now add the per-device special config files */
1210 
1211 	list_for_each(dev, &devices, node) {
1212 		char *path;
1213 
1214 		path = litest_init_device_quirk_file(dirname, dev);
1215 		if (path) {
1216 			struct created_file *file = zalloc(sizeof(*file));
1217 			file->path = path;
1218 			list_insert(created_files_list, &file->link);
1219 		}
1220 	}
1221 
1222 	file = zalloc(sizeof *file);
1223 	file->path = safe_strdup(dirname);
1224 	list_append(created_files_list, &file->link);
1225 
1226 	return safe_strdup(dirname);
1227 }
1228 
1229 static inline void
mkdir_p(const char * dir)1230 mkdir_p(const char *dir)
1231 {
1232 	char *path, *parent;
1233 	int rc;
1234 
1235 	if (streq(dir, "/"))
1236 		return;
1237 
1238 	path = strdup(dir);
1239 	parent = dirname(path);
1240 
1241 	mkdir_p(parent);
1242 	rc = mkdir(dir, 0755);
1243 
1244 	if (rc == -1 && errno != EEXIST) {
1245 		litest_abort_msg("Failed to create directory %s (%s)\n",
1246 				 dir,
1247 				 strerror(errno));
1248 	}
1249 
1250 	free(path);
1251 }
1252 
1253 static inline void
litest_init_udev_rules(struct list * created_files)1254 litest_init_udev_rules(struct list *created_files)
1255 {
1256 	mkdir_p(UDEV_RULES_D);
1257 	mkdir_p(UDEV_HWDB_D);
1258 
1259 	litest_install_model_quirks(created_files);
1260 	litest_init_all_device_udev_rules(created_files);
1261 	litest_reload_udev_rules();
1262 }
1263 
1264 static inline void
litest_remove_udev_rules(struct list * created_files_list)1265 litest_remove_udev_rules(struct list *created_files_list)
1266 {
1267 	struct created_file *f, *tmp;
1268 	bool reload_udev;
1269 
1270 	reload_udev = !list_empty(created_files_list);
1271 
1272 	list_for_each_safe(f, tmp, created_files_list, link) {
1273 		list_remove(&f->link);
1274 		unlink(f->path);
1275 		rmdir(f->path);
1276 		free(f->path);
1277 		free(f);
1278 	}
1279 
1280 	if (reload_udev)
1281 		litest_reload_udev_rules();
1282 }
1283 
1284 static char *
litest_init_device_udev_rules(struct litest_test_device * dev)1285 litest_init_device_udev_rules(struct litest_test_device *dev)
1286 {
1287 	int rc;
1288 	int fd;
1289 	FILE *f;
1290 	char *path = NULL;
1291 	static int count;
1292 
1293 	if (!dev->udev_rule)
1294 		return NULL;
1295 
1296 	rc = xasprintf(&path,
1297 		      "%s/%s%03d-%s-XXXXXX.rules",
1298 		      UDEV_RULES_D,
1299 		      UDEV_RULE_PREFIX,
1300 		      ++count,
1301 		      dev->shortname);
1302 	litest_assert_int_eq(rc,
1303 			     (int)(
1304 				   strlen(UDEV_RULES_D) +
1305 				   strlen(UDEV_RULE_PREFIX) +
1306 				   strlen(dev->shortname) + 18));
1307 
1308 	fd = mkstemps(path, 6);
1309 	litest_assert_int_ne(fd, -1);
1310 	f = fdopen(fd, "w");
1311 	litest_assert_notnull(f);
1312 	litest_assert_int_ge(fputs(dev->udev_rule, f), 0);
1313 	fclose(f);
1314 
1315 	return path;
1316 }
1317 
1318 /**
1319  * Creates a uinput device but does not add it to a libinput context
1320  */
1321 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)1322 litest_create(enum litest_device_type which,
1323 	      const char *name_override,
1324 	      struct input_id *id_override,
1325 	      const struct input_absinfo *abs_override,
1326 	      const int *events_override)
1327 {
1328 	struct litest_device *d = NULL;
1329 	struct litest_test_device *dev;
1330 	const char *name;
1331 	const struct input_id *id;
1332 	struct input_absinfo *abs;
1333 	int *events, *e;
1334 	const char *path;
1335 	int fd, rc;
1336 	bool found = false;
1337 
1338 	list_for_each(dev, &devices, node) {
1339 		if (dev->type == which) {
1340 			found = true;
1341 			break;
1342 		}
1343 	}
1344 
1345 	if (!found)
1346 		ck_abort_msg("Invalid device type %d\n", which);
1347 
1348 	d = zalloc(sizeof(*d));
1349 
1350 	/* device has custom create method */
1351 	if (dev->create) {
1352 		dev->create(d);
1353 		if (abs_override || events_override) {
1354 			litest_abort_msg("Custom create cannot be overridden");
1355 		}
1356 	} else {
1357 		abs = merge_absinfo(dev->absinfo, abs_override);
1358 		events = merge_events(dev->events, events_override);
1359 		name = name_override ? name_override : dev->name;
1360 		id = id_override ? id_override : dev->id;
1361 
1362 		d->uinput = litest_create_uinput_device_from_description(name,
1363 									 id,
1364 									 abs,
1365 									 events);
1366 		d->interface = dev->interface;
1367 
1368 		for (e = events; *e != -1; e += 2) {
1369 			unsigned int type = *e,
1370 				     code = *(e + 1);
1371 
1372 			if (type == INPUT_PROP_MAX &&
1373 			    code == INPUT_PROP_SEMI_MT) {
1374 				d->semi_mt.is_semi_mt = true;
1375 				break;
1376 			}
1377 		}
1378 
1379 		free(abs);
1380 		free(events);
1381 	}
1382 
1383 	path = libevdev_uinput_get_devnode(d->uinput);
1384 	litest_assert(path != NULL);
1385 	fd = open(path, O_RDWR|O_NONBLOCK);
1386 	litest_assert_int_ne(fd, -1);
1387 
1388 	rc = libevdev_new_from_fd(fd, &d->evdev);
1389 	litest_assert_int_eq(rc, 0);
1390 
1391 	return d;
1392 
1393 }
1394 
1395 struct libinput *
litest_create_context(void)1396 litest_create_context(void)
1397 {
1398 	struct libinput *libinput =
1399 		libinput_path_create_context(&interface, NULL);
1400 	litest_assert_notnull(libinput);
1401 
1402 	libinput_log_set_handler(libinput, litest_log_handler);
1403 	if (verbose)
1404 		libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1405 
1406 	return libinput;
1407 }
1408 
1409 void
litest_disable_log_handler(struct libinput * libinput)1410 litest_disable_log_handler(struct libinput *libinput)
1411 {
1412 	libinput_log_set_handler(libinput, NULL);
1413 }
1414 
1415 void
litest_restore_log_handler(struct libinput * libinput)1416 litest_restore_log_handler(struct libinput *libinput)
1417 {
1418 	libinput_log_set_handler(libinput, litest_log_handler);
1419 	if (verbose)
1420 		libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1421 }
1422 
1423 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
1424 static void
litest_bug_log_handler(struct libinput * libinput,enum libinput_log_priority pri,const char * format,va_list args)1425 litest_bug_log_handler(struct libinput *libinput,
1426 		       enum libinput_log_priority pri,
1427 		       const char *format,
1428 		       va_list args)
1429 {
1430 	if (strstr(format, "client bug: ") ||
1431 	    strstr(format, "libinput bug: "))
1432 		return;
1433 
1434 	litest_abort_msg("Expected bug statement in log msg, aborting.\n");
1435 }
1436 
1437 void
litest_set_log_handler_bug(struct libinput * libinput)1438 litest_set_log_handler_bug(struct libinput *libinput)
1439 {
1440 	libinput_log_set_handler(libinput, litest_bug_log_handler);
1441 }
1442 
1443 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)1444 litest_add_device_with_overrides(struct libinput *libinput,
1445 				 enum litest_device_type which,
1446 				 const char *name_override,
1447 				 struct input_id *id_override,
1448 				 const struct input_absinfo *abs_override,
1449 				 const int *events_override)
1450 {
1451 	struct udev_device *ud;
1452 	struct litest_device *d;
1453 	const char *path;
1454 
1455 	d = litest_create(which,
1456 			  name_override,
1457 			  id_override,
1458 			  abs_override,
1459 			  events_override);
1460 
1461 	path = libevdev_uinput_get_devnode(d->uinput);
1462 	litest_assert(path != NULL);
1463 
1464 	d->libinput = libinput;
1465 	d->libinput_device = libinput_path_add_device(d->libinput, path);
1466 	ud = libinput_device_get_udev_device(d->libinput_device);
1467 	d->quirks = quirks_fetch_for_device(quirks_context, ud);
1468 	udev_device_unref(ud);
1469 
1470 	litest_assert(d->libinput_device != NULL);
1471 	libinput_device_ref(d->libinput_device);
1472 
1473 	if (d->interface) {
1474 		d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, ABS_X);
1475 		d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, ABS_X);
1476 		d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, ABS_Y);
1477 		d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, ABS_Y);
1478 	}
1479 	return d;
1480 }
1481 
1482 struct litest_device *
litest_add_device(struct libinput * libinput,enum litest_device_type which)1483 litest_add_device(struct libinput *libinput,
1484 		  enum litest_device_type which)
1485 {
1486 	return litest_add_device_with_overrides(libinput,
1487 						which,
1488 						NULL,
1489 						NULL,
1490 						NULL,
1491 						NULL);
1492 }
1493 
1494 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)1495 litest_create_device_with_overrides(enum litest_device_type which,
1496 				    const char *name_override,
1497 				    struct input_id *id_override,
1498 				    const struct input_absinfo *abs_override,
1499 				    const int *events_override)
1500 {
1501 	struct litest_device *dev =
1502 		litest_add_device_with_overrides(litest_create_context(),
1503 						 which,
1504 						 name_override,
1505 						 id_override,
1506 						 abs_override,
1507 						 events_override);
1508 	dev->owns_context = true;
1509 	return dev;
1510 }
1511 
1512 struct litest_device *
litest_create_device(enum litest_device_type which)1513 litest_create_device(enum litest_device_type which)
1514 {
1515 	return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL);
1516 }
1517 
1518 static struct udev_monitor *
udev_setup_monitor(void)1519 udev_setup_monitor(void)
1520 {
1521 	struct udev *udev;
1522 	struct udev_monitor *udev_monitor;
1523 	int rc;
1524 
1525 	udev = udev_new();
1526 	litest_assert_notnull(udev);
1527 	udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1528 	litest_assert_notnull(udev_monitor);
1529 	udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
1530 							NULL);
1531 
1532 
1533 	/* remove O_NONBLOCK */
1534 	rc = fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
1535 	litest_assert_int_ne(rc, -1);
1536 	litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor),
1537 			     0);
1538 	udev_unref(udev);
1539 
1540 	return udev_monitor;
1541 }
1542 
1543 static struct udev_device *
udev_wait_for_device_event(struct udev_monitor * udev_monitor,const char * udev_event,const char * syspath)1544 udev_wait_for_device_event(struct udev_monitor *udev_monitor,
1545 			   const char *udev_event,
1546 			   const char *syspath)
1547 {
1548 	struct udev_device *udev_device = NULL;
1549 
1550 	/* blocking, we don't want to continue until udev is ready */
1551 	while (1) {
1552 		const char *udev_syspath = NULL;
1553 		const char *udev_action;
1554 
1555 		udev_device = udev_monitor_receive_device(udev_monitor);
1556 		litest_assert_notnull(udev_device);
1557 		udev_action = udev_device_get_action(udev_device);
1558 		if (!streq(udev_action, udev_event)) {
1559 			udev_device_unref(udev_device);
1560 			continue;
1561 		}
1562 
1563 		udev_syspath = udev_device_get_syspath(udev_device);
1564 		if (udev_syspath && strneq(udev_syspath,
1565 					   syspath,
1566 					   strlen(syspath)))
1567 			break;
1568 
1569 		udev_device_unref(udev_device);
1570 	}
1571 
1572 	return udev_device;
1573 }
1574 
1575 void
litest_delete_device(struct litest_device * d)1576 litest_delete_device(struct litest_device *d)
1577 {
1578 
1579 	struct udev_monitor *udev_monitor;
1580 	struct udev_device *udev_device;
1581 	char path[PATH_MAX];
1582 
1583 	if (!d)
1584 		return;
1585 
1586 	udev_monitor = udev_setup_monitor();
1587 	snprintf(path, sizeof(path),
1588 		 "%s/event",
1589 		 libevdev_uinput_get_syspath(d->uinput));
1590 
1591 	litest_assert_int_eq(d->skip_ev_syn, 0);
1592 
1593 	quirks_unref(d->quirks);
1594 
1595 	if (d->libinput_device) {
1596 		libinput_path_remove_device(d->libinput_device);
1597 		libinput_device_unref(d->libinput_device);
1598 	}
1599 	if (d->owns_context)
1600 		libinput_unref(d->libinput);
1601 	close(libevdev_get_fd(d->evdev));
1602 	libevdev_free(d->evdev);
1603 	libevdev_uinput_destroy(d->uinput);
1604 	free(d->private);
1605 	memset(d,0, sizeof(*d));
1606 	free(d);
1607 
1608 	udev_device = udev_wait_for_device_event(udev_monitor,
1609 						 "remove",
1610 						 path);
1611 	udev_device_unref(udev_device);
1612 	udev_monitor_unref(udev_monitor);
1613 }
1614 
1615 void
litest_event(struct litest_device * d,unsigned int type,unsigned int code,int value)1616 litest_event(struct litest_device *d, unsigned int type,
1617 	     unsigned int code, int value)
1618 {
1619 	int ret;
1620 
1621 	if (d->skip_ev_syn && type == EV_SYN && code == SYN_REPORT)
1622 		return;
1623 
1624 	ret = libevdev_uinput_write_event(d->uinput, type, code, value);
1625 	litest_assert_int_eq(ret, 0);
1626 }
1627 
1628 static bool
axis_replacement_value(struct litest_device * d,struct axis_replacement * axes,int32_t evcode,int32_t * value)1629 axis_replacement_value(struct litest_device *d,
1630 		       struct axis_replacement *axes,
1631 		       int32_t evcode,
1632 		       int32_t *value)
1633 {
1634 	struct axis_replacement *axis = axes;
1635 
1636 	if (!axes)
1637 		return false;
1638 
1639 	while (axis->evcode != -1) {
1640 		if (axis->evcode == evcode) {
1641 			switch (evcode) {
1642 			case ABS_MT_SLOT:
1643 			case ABS_MT_TRACKING_ID:
1644 			case ABS_MT_TOOL_TYPE:
1645 				*value = axis->value;
1646 				break;
1647 			default:
1648 				*value = litest_scale(d, evcode, axis->value);
1649 				break;
1650 			}
1651 			return true;
1652 		}
1653 		axis++;
1654 	}
1655 
1656 	return false;
1657 }
1658 
1659 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)1660 litest_auto_assign_value(struct litest_device *d,
1661 			 const struct input_event *ev,
1662 			 int slot, double x, double y,
1663 			 struct axis_replacement *axes,
1664 			 bool touching)
1665 {
1666 	static int tracking_id;
1667 	int value = ev->value;
1668 
1669 	if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
1670 		return value;
1671 
1672 	switch (ev->code) {
1673 	case ABS_X:
1674 	case ABS_MT_POSITION_X:
1675 		value = litest_scale(d, ABS_X, x);
1676 		break;
1677 	case ABS_Y:
1678 	case ABS_MT_POSITION_Y:
1679 		value = litest_scale(d, ABS_Y, y);
1680 		break;
1681 	case ABS_MT_TRACKING_ID:
1682 		value = ++tracking_id;
1683 		break;
1684 	case ABS_MT_SLOT:
1685 		value = slot;
1686 		break;
1687 	case ABS_MT_DISTANCE:
1688 		value = touching ? 0 : 1;
1689 		break;
1690 	case ABS_MT_TOOL_TYPE:
1691 		if (!axis_replacement_value(d, axes, ev->code, &value))
1692 			value = MT_TOOL_FINGER;
1693 		break;
1694 	default:
1695 		if (!axis_replacement_value(d, axes, ev->code, &value) &&
1696 		    d->interface->get_axis_default)
1697 			d->interface->get_axis_default(d, ev->code, &value);
1698 		break;
1699 	}
1700 
1701 	return value;
1702 }
1703 
1704 static void
send_btntool(struct litest_device * d,bool hover)1705 send_btntool(struct litest_device *d, bool hover)
1706 {
1707 	litest_event(d, EV_KEY, BTN_TOUCH, d->ntouches_down != 0 && !hover);
1708 	litest_event(d, EV_KEY, BTN_TOOL_FINGER, d->ntouches_down == 1);
1709 	litest_event(d, EV_KEY, BTN_TOOL_DOUBLETAP, d->ntouches_down == 2);
1710 	litest_event(d, EV_KEY, BTN_TOOL_TRIPLETAP, d->ntouches_down == 3);
1711 	litest_event(d, EV_KEY, BTN_TOOL_QUADTAP, d->ntouches_down == 4);
1712 	litest_event(d, EV_KEY, BTN_TOOL_QUINTTAP, d->ntouches_down == 5);
1713 }
1714 
1715 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)1716 slot_start(struct litest_device *d,
1717 	   unsigned int slot,
1718 	   double x,
1719 	   double y,
1720 	   struct axis_replacement *axes,
1721 	   bool touching,
1722 	   bool filter_abs_xy)
1723 {
1724 	struct input_event *ev;
1725 
1726 	litest_assert(d->ntouches_down >= 0);
1727 	d->ntouches_down++;
1728 
1729 	send_btntool(d, !touching);
1730 
1731 	if (d->interface->touch_down) {
1732 		d->interface->touch_down(d, slot, x, y);
1733 		return;
1734 	}
1735 
1736 	for (ev = d->interface->touch_down_events;
1737 	     ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
1738 	     ev++) {
1739 		int value = litest_auto_assign_value(d,
1740 						     ev,
1741 						     slot,
1742 						     x,
1743 						     y,
1744 						     axes,
1745 						     touching);
1746 		if (value == LITEST_AUTO_ASSIGN)
1747 			continue;
1748 
1749 		if (filter_abs_xy && ev->type == EV_ABS &&
1750 		    (ev->code == ABS_X || ev->code == ABS_Y))
1751 			continue;
1752 
1753 		litest_event(d, ev->type, ev->code, value);
1754 	}
1755 }
1756 
1757 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)1758 slot_move(struct litest_device *d,
1759 	  unsigned int slot,
1760 	  double x,
1761 	  double y,
1762 	  struct axis_replacement *axes,
1763 	  bool touching,
1764 	  bool filter_abs_xy)
1765 {
1766 	struct input_event *ev;
1767 
1768 	if (d->interface->touch_move) {
1769 		d->interface->touch_move(d, slot, x, y);
1770 		return;
1771 	}
1772 
1773 	for (ev = d->interface->touch_move_events;
1774 	     ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
1775 	     ev++) {
1776 		int value = litest_auto_assign_value(d,
1777 						     ev,
1778 						     slot,
1779 						     x,
1780 						     y,
1781 						     axes,
1782 						     touching);
1783 		if (value == LITEST_AUTO_ASSIGN)
1784 			continue;
1785 
1786 		if (filter_abs_xy && ev->type == EV_ABS &&
1787 		    (ev->code == ABS_X || ev->code == ABS_Y))
1788 			continue;
1789 
1790 		litest_event(d, ev->type, ev->code, value);
1791 	}
1792 }
1793 
1794 static void
touch_up(struct litest_device * d,unsigned int slot)1795 touch_up(struct litest_device *d, unsigned int slot)
1796 {
1797 	struct input_event *ev;
1798 	struct input_event up[] = {
1799 		{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
1800 		{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
1801 		{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
1802 		{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 0 },
1803 		{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 0 },
1804 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
1805 		{ .type = -1, .code = -1 }
1806 	};
1807 
1808 	litest_assert_int_gt(d->ntouches_down, 0);
1809 	d->ntouches_down--;
1810 
1811 	send_btntool(d, false);
1812 
1813 	if (d->interface->touch_up) {
1814 		d->interface->touch_up(d, slot);
1815 		return;
1816 	} else if (d->interface->touch_up_events) {
1817 		ev = d->interface->touch_up_events;
1818 	} else
1819 		ev = up;
1820 
1821 	for ( /* */;
1822 	     ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
1823 	     ev++) {
1824 		int value = litest_auto_assign_value(d,
1825 						     ev,
1826 						     slot,
1827 						     0,
1828 						     0,
1829 						     NULL,
1830 						     false);
1831 		litest_event(d, ev->type, ev->code, value);
1832 	}
1833 }
1834 
1835 static void
litest_slot_start(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes,bool touching)1836 litest_slot_start(struct litest_device *d,
1837 		  unsigned int slot,
1838 		  double x,
1839 		  double y,
1840 		  struct axis_replacement *axes,
1841 		  bool touching)
1842 {
1843 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
1844 	bool filter_abs_xy = false;
1845 
1846 	if (!d->semi_mt.is_semi_mt) {
1847 		slot_start(d, slot, x, y, axes, touching, filter_abs_xy);
1848 		return;
1849 	}
1850 
1851 	if (d->ntouches_down >= 2 || slot > 1)
1852 		return;
1853 
1854 	slot = d->ntouches_down;
1855 
1856 	if (d->ntouches_down == 0) {
1857 		l = x;
1858 		t = y;
1859 	} else {
1860 		int other = (slot + 1) % 2;
1861 		l = min(x, d->semi_mt.touches[other].x);
1862 		t = min(y, d->semi_mt.touches[other].y);
1863 		r = max(x, d->semi_mt.touches[other].x);
1864 		b = max(y, d->semi_mt.touches[other].y);
1865 	}
1866 
1867 	litest_push_event_frame(d);
1868 	if (d->ntouches_down == 0)
1869 		slot_start(d, 0, l, t, axes, touching, filter_abs_xy);
1870 	else
1871 		slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
1872 
1873 	if (slot == 1) {
1874 		filter_abs_xy = true;
1875 		slot_start(d, 1, r, b, axes, touching, filter_abs_xy);
1876 	}
1877 
1878 	litest_pop_event_frame(d);
1879 
1880 	d->semi_mt.touches[slot].x = x;
1881 	d->semi_mt.touches[slot].y = y;
1882 }
1883 
1884 void
litest_touch_down(struct litest_device * d,unsigned int slot,double x,double y)1885 litest_touch_down(struct litest_device *d,
1886 		  unsigned int slot,
1887 		  double x,
1888 		  double y)
1889 {
1890 	litest_slot_start(d, slot, x, y, NULL, true);
1891 }
1892 
1893 void
litest_touch_down_extended(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes)1894 litest_touch_down_extended(struct litest_device *d,
1895 			   unsigned int slot,
1896 			   double x,
1897 			   double y,
1898 			   struct axis_replacement *axes)
1899 {
1900 	litest_slot_start(d, slot, x, y, axes, true);
1901 }
1902 
1903 static void
litest_slot_move(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes,bool touching)1904 litest_slot_move(struct litest_device *d,
1905 		 unsigned int slot,
1906 		 double x,
1907 		 double y,
1908 		 struct axis_replacement *axes,
1909 		 bool touching)
1910 {
1911 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
1912 	bool filter_abs_xy = false;
1913 
1914 	if (!d->semi_mt.is_semi_mt) {
1915 		slot_move(d, slot, x, y, axes, touching, filter_abs_xy);
1916 		return;
1917 	}
1918 
1919 	if (d->ntouches_down > 2 || slot > 1)
1920 		return;
1921 
1922 	if (d->ntouches_down == 1) {
1923 		l = x;
1924 		t = y;
1925 	} else {
1926 		int other = (slot + 1) % 2;
1927 		l = min(x, d->semi_mt.touches[other].x);
1928 		t = min(y, d->semi_mt.touches[other].y);
1929 		r = max(x, d->semi_mt.touches[other].x);
1930 		b = max(y, d->semi_mt.touches[other].y);
1931 	}
1932 
1933 	litest_push_event_frame(d);
1934 	slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
1935 
1936 	if (d->ntouches_down == 2) {
1937 		filter_abs_xy = true;
1938 		slot_move(d, 1, r, b, axes, touching, filter_abs_xy);
1939 	}
1940 
1941 	litest_pop_event_frame(d);
1942 
1943 	d->semi_mt.touches[slot].x = x;
1944 	d->semi_mt.touches[slot].y = y;
1945 }
1946 
1947 void
litest_touch_up(struct litest_device * d,unsigned int slot)1948 litest_touch_up(struct litest_device *d, unsigned int slot)
1949 {
1950 	if (!d->semi_mt.is_semi_mt) {
1951 		touch_up(d, slot);
1952 		return;
1953 	}
1954 
1955 	if (d->ntouches_down > 2 || slot > 1)
1956 		return;
1957 
1958 	litest_push_event_frame(d);
1959 	touch_up(d, d->ntouches_down - 1);
1960 
1961 	/* if we have one finger left, send x/y coords for that finger left.
1962 	   this is likely to happen with a real touchpad */
1963 	if (d->ntouches_down == 1) {
1964 		bool touching = true;
1965 		bool filter_abs_xy = false;
1966 
1967 		int other = (slot + 1) % 2;
1968 		slot_move(d,
1969 			  0,
1970 			  d->semi_mt.touches[other].x,
1971 			  d->semi_mt.touches[other].y,
1972 			  NULL,
1973 			  touching,
1974 			  filter_abs_xy);
1975 	}
1976 
1977 	litest_pop_event_frame(d);
1978 }
1979 
1980 void
litest_touch_move(struct litest_device * d,unsigned int slot,double x,double y)1981 litest_touch_move(struct litest_device *d,
1982 		  unsigned int slot,
1983 		  double x,
1984 		  double y)
1985 {
1986 	litest_slot_move(d, slot, x, y, NULL, true);
1987 }
1988 
1989 void
litest_touch_move_extended(struct litest_device * d,unsigned int slot,double x,double y,struct axis_replacement * axes)1990 litest_touch_move_extended(struct litest_device *d,
1991 			   unsigned int slot,
1992 			   double x,
1993 			   double y,
1994 			   struct axis_replacement *axes)
1995 {
1996 	litest_slot_move(d, slot, x, y, axes, true);
1997 }
1998 
1999 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)2000 litest_touch_move_to(struct litest_device *d,
2001 		     unsigned int slot,
2002 		     double x_from, double y_from,
2003 		     double x_to, double y_to,
2004 		     int steps)
2005 {
2006 	litest_touch_move_to_extended(d, slot,
2007 				      x_from, y_from,
2008 				      x_to, y_to,
2009 				      NULL,
2010 				      steps);
2011 }
2012 
2013 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)2014 litest_touch_move_to_extended(struct litest_device *d,
2015 			      unsigned int slot,
2016 			      double x_from, double y_from,
2017 			      double x_to, double y_to,
2018 			      struct axis_replacement *axes,
2019 			      int steps)
2020 {
2021 	int sleep_ms = 10;
2022 
2023 	for (int i = 1; i < steps; i++) {
2024 		litest_touch_move_extended(d, slot,
2025 					   x_from + (x_to - x_from)/steps * i,
2026 					   y_from + (y_to - y_from)/steps * i,
2027 					   axes);
2028 		libinput_dispatch(d->libinput);
2029 		msleep(sleep_ms);
2030 		libinput_dispatch(d->libinput);
2031 	}
2032 	litest_touch_move_extended(d, slot, x_to, y_to, axes);
2033 }
2034 
2035 static int
auto_assign_tablet_value(struct litest_device * d,const struct input_event * ev,int x,int y,struct axis_replacement * axes)2036 auto_assign_tablet_value(struct litest_device *d,
2037 			 const struct input_event *ev,
2038 			 int x, int y,
2039 			 struct axis_replacement *axes)
2040 {
2041 	int value = ev->value;
2042 
2043 	if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2044 		return value;
2045 
2046 	switch (ev->code) {
2047 	case ABS_X:
2048 		value = litest_scale(d, ABS_X, x);
2049 		break;
2050 	case ABS_Y:
2051 		value = litest_scale(d, ABS_Y, y);
2052 		break;
2053 	default:
2054 		if (!axis_replacement_value(d, axes, ev->code, &value) &&
2055 		    d->interface->get_axis_default)
2056 			d->interface->get_axis_default(d, ev->code, &value);
2057 		break;
2058 	}
2059 
2060 	return value;
2061 }
2062 
2063 static int
tablet_ignore_event(const struct input_event * ev,int value)2064 tablet_ignore_event(const struct input_event *ev, int value)
2065 {
2066 	return value == -1 && (ev->code == ABS_PRESSURE || ev->code == ABS_DISTANCE);
2067 }
2068 
2069 void
litest_tablet_proximity_in(struct litest_device * d,int x,int y,struct axis_replacement * axes)2070 litest_tablet_proximity_in(struct litest_device *d, int x, int y, struct axis_replacement *axes)
2071 {
2072 	struct input_event *ev;
2073 
2074 	ev = d->interface->tablet_proximity_in_events;
2075 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2076 		int value = auto_assign_tablet_value(d, ev, x, y, axes);
2077 		if (!tablet_ignore_event(ev, value))
2078 			litest_event(d, ev->type, ev->code, value);
2079 		ev++;
2080 	}
2081 }
2082 
2083 void
litest_tablet_proximity_out(struct litest_device * d)2084 litest_tablet_proximity_out(struct litest_device *d)
2085 {
2086 	struct input_event *ev;
2087 
2088 	ev = d->interface->tablet_proximity_out_events;
2089 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2090 		int value = auto_assign_tablet_value(d, ev, -1, -1, NULL);
2091 		if (!tablet_ignore_event(ev, value))
2092 			litest_event(d, ev->type, ev->code, value);
2093 		ev++;
2094 	}
2095 }
2096 
2097 void
litest_tablet_motion(struct litest_device * d,int x,int y,struct axis_replacement * axes)2098 litest_tablet_motion(struct litest_device *d, int x, int y, struct axis_replacement *axes)
2099 {
2100 	struct input_event *ev;
2101 
2102 	ev = d->interface->tablet_motion_events;
2103 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2104 		int value = auto_assign_tablet_value(d, ev, x, y, axes);
2105 		if (!tablet_ignore_event(ev, value))
2106 			litest_event(d, ev->type, ev->code, value);
2107 		ev++;
2108 	}
2109 }
2110 
2111 void
litest_touch_move_two_touches(struct litest_device * d,double x0,double y0,double x1,double y1,double dx,double dy,int steps)2112 litest_touch_move_two_touches(struct litest_device *d,
2113 			      double x0, double y0,
2114 			      double x1, double y1,
2115 			      double dx, double dy,
2116 			      int steps)
2117 {
2118 	int sleep_ms = 10;
2119 
2120 	for (int i = 1; i < steps; i++) {
2121 		litest_push_event_frame(d);
2122 		litest_touch_move(d, 0, x0 + dx / steps * i,
2123 					y0 + dy / steps * i);
2124 		litest_touch_move(d, 1, x1 + dx / steps * i,
2125 					y1 + dy / steps * i);
2126 		litest_pop_event_frame(d);
2127 		libinput_dispatch(d->libinput);
2128 		msleep(sleep_ms);
2129 		libinput_dispatch(d->libinput);
2130 	}
2131 	litest_push_event_frame(d);
2132 	litest_touch_move(d, 0, x0 + dx, y0 + dy);
2133 	litest_touch_move(d, 1, x1 + dx, y1 + dy);
2134 	litest_pop_event_frame(d);
2135 }
2136 
2137 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)2138 litest_touch_move_three_touches(struct litest_device *d,
2139 				double x0, double y0,
2140 				double x1, double y1,
2141 				double x2, double y2,
2142 				double dx, double dy,
2143 				int steps)
2144 {
2145 	int sleep_ms = 10;
2146 
2147 	for (int i = 0; i < steps - 1; i++) {
2148 		litest_touch_move(d, 0, x0 + dx / steps * i,
2149 					y0 + dy / steps * i);
2150 		litest_touch_move(d, 1, x1 + dx / steps * i,
2151 					y1 + dy / steps * i);
2152 		litest_touch_move(d, 2, x2 + dx / steps * i,
2153 					y2 + dy / steps * i);
2154 
2155 		libinput_dispatch(d->libinput);
2156 		msleep(sleep_ms);
2157 		libinput_dispatch(d->libinput);
2158 	}
2159 	litest_touch_move(d, 0, x0 + dx, y0 + dy);
2160 	litest_touch_move(d, 1, x1 + dx, y1 + dy);
2161 	litest_touch_move(d, 2, x2 + dx, y2 + dy);
2162 }
2163 
2164 void
litest_hover_start(struct litest_device * d,unsigned int slot,double x,double y)2165 litest_hover_start(struct litest_device *d,
2166 		   unsigned int slot,
2167 		   double x,
2168 		   double y)
2169 {
2170 	struct axis_replacement axes[] = {
2171 		{ABS_MT_PRESSURE, 0 },
2172 		{ABS_PRESSURE, 0 },
2173 		{-1, -1 },
2174 	};
2175 
2176 	litest_slot_start(d, slot, x, y, axes, 0);
2177 }
2178 
2179 void
litest_hover_end(struct litest_device * d,unsigned int slot)2180 litest_hover_end(struct litest_device *d, unsigned int slot)
2181 {
2182 	struct input_event *ev;
2183 	struct input_event up[] = {
2184 		{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
2185 		{ .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 },
2186 		{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
2187 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2188 		{ .type = -1, .code = -1 }
2189 	};
2190 
2191 	litest_assert_int_gt(d->ntouches_down, 0);
2192 	d->ntouches_down--;
2193 
2194 	send_btntool(d, true);
2195 
2196 	if (d->interface->touch_up) {
2197 		d->interface->touch_up(d, slot);
2198 		return;
2199 	} else if (d->interface->touch_up_events) {
2200 		ev = d->interface->touch_up_events;
2201 	} else
2202 		ev = up;
2203 
2204 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2205 		int value = litest_auto_assign_value(d, ev, slot, 0, 0, NULL, false);
2206 		litest_event(d, ev->type, ev->code, value);
2207 		ev++;
2208 	}
2209 }
2210 
2211 void
litest_hover_move(struct litest_device * d,unsigned int slot,double x,double y)2212 litest_hover_move(struct litest_device *d, unsigned int slot,
2213 		  double x, double y)
2214 {
2215 	struct axis_replacement axes[] = {
2216 		{ABS_MT_PRESSURE, 0 },
2217 		{ABS_PRESSURE, 0 },
2218 		{-1, -1 },
2219 	};
2220 
2221 	litest_slot_move(d, slot, x, y, axes, false);
2222 }
2223 
2224 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)2225 litest_hover_move_to(struct litest_device *d,
2226 		     unsigned int slot,
2227 		     double x_from, double y_from,
2228 		     double x_to, double y_to,
2229 		     int steps)
2230 {
2231 	int sleep_ms = 10;
2232 
2233 	for (int i = 0; i < steps - 1; i++) {
2234 		litest_hover_move(d, slot,
2235 				  x_from + (x_to - x_from)/steps * i,
2236 				  y_from + (y_to - y_from)/steps * i);
2237 		libinput_dispatch(d->libinput);
2238 		msleep(sleep_ms);
2239 		libinput_dispatch(d->libinput);
2240 	}
2241 	litest_hover_move(d, slot, x_to, y_to);
2242 }
2243 
2244 void
litest_hover_move_two_touches(struct litest_device * d,double x0,double y0,double x1,double y1,double dx,double dy,int steps)2245 litest_hover_move_two_touches(struct litest_device *d,
2246 			      double x0, double y0,
2247 			      double x1, double y1,
2248 			      double dx, double dy,
2249 			      int steps)
2250 {
2251 	int sleep_ms = 10;
2252 
2253 	for (int i = 0; i < steps - 1; i++) {
2254 		litest_push_event_frame(d);
2255 		litest_hover_move(d, 0, x0 + dx / steps * i,
2256 					y0 + dy / steps * i);
2257 		litest_hover_move(d, 1, x1 + dx / steps * i,
2258 					y1 + dy / steps * i);
2259 		litest_pop_event_frame(d);
2260 		libinput_dispatch(d->libinput);
2261 		msleep(sleep_ms);
2262 		libinput_dispatch(d->libinput);
2263 	}
2264 	litest_push_event_frame(d);
2265 	litest_hover_move(d, 0, x0 + dx, y0 + dy);
2266 	litest_hover_move(d, 1, x1 + dx, y1 + dy);
2267 	litest_pop_event_frame(d);
2268 }
2269 
2270 void
litest_button_click(struct litest_device * d,unsigned int button,bool is_press)2271 litest_button_click(struct litest_device *d,
2272 		    unsigned int button,
2273 		    bool is_press)
2274 {
2275 	struct input_event *ev;
2276 	struct input_event click[] = {
2277 		{ .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
2278 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2279 	};
2280 
2281 	ARRAY_FOR_EACH(click, ev)
2282 		litest_event(d, ev->type, ev->code, ev->value);
2283 }
2284 
2285 void
litest_button_click_debounced(struct litest_device * d,struct libinput * li,unsigned int button,bool is_press)2286 litest_button_click_debounced(struct litest_device *d,
2287 			      struct libinput *li,
2288 			      unsigned int button,
2289 			      bool is_press)
2290 {
2291 	litest_button_click(d, button, is_press);
2292 
2293 	libinput_dispatch(li);
2294 	litest_timeout_debounce();
2295 	libinput_dispatch(li);
2296 }
2297 
2298 void
litest_button_scroll(struct litest_device * dev,unsigned int button,double dx,double dy)2299 litest_button_scroll(struct litest_device *dev,
2300 		     unsigned int button,
2301 		     double dx, double dy)
2302 {
2303 	struct libinput *li = dev->libinput;
2304 
2305 	litest_button_click_debounced(dev, li, button, 1);
2306 
2307 	libinput_dispatch(li);
2308 	litest_timeout_buttonscroll();
2309 	libinput_dispatch(li);
2310 
2311 	litest_event(dev, EV_REL, REL_X, dx);
2312 	litest_event(dev, EV_REL, REL_Y, dy);
2313 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2314 
2315 	litest_button_click_debounced(dev, li, button, 0);
2316 
2317 	libinput_dispatch(li);
2318 }
2319 
2320 void
litest_keyboard_key(struct litest_device * d,unsigned int key,bool is_press)2321 litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)
2322 {
2323 	struct input_event *ev;
2324 	struct input_event click[] = {
2325 		{ .type = EV_KEY, .code = key, .value = is_press ? 1 : 0 },
2326 		{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2327 	};
2328 
2329 	ARRAY_FOR_EACH(click, ev)
2330 		litest_event(d, ev->type, ev->code, ev->value);
2331 }
2332 
2333 void
litest_switch_action(struct litest_device * dev,enum libinput_switch sw,enum libinput_switch_state state)2334 litest_switch_action(struct litest_device *dev,
2335 		     enum libinput_switch sw,
2336 		     enum libinput_switch_state state)
2337 {
2338 	unsigned int code;
2339 
2340 	switch (sw) {
2341 	case LIBINPUT_SWITCH_LID:
2342 		code = SW_LID;
2343 		break;
2344 	case LIBINPUT_SWITCH_TABLET_MODE:
2345 		code = SW_TABLET_MODE;
2346 		break;
2347 	default:
2348 		litest_abort_msg("Invalid switch %d", sw);
2349 		break;
2350 	}
2351 	litest_event(dev, EV_SW, code, state);
2352 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2353 }
2354 
2355 static int
litest_scale_axis(const struct litest_device * d,unsigned int axis,double val)2356 litest_scale_axis(const struct litest_device *d,
2357 		  unsigned int axis,
2358 		  double val)
2359 {
2360 	const struct input_absinfo *abs;
2361 
2362 	litest_assert_double_ge(val, 0.0);
2363 	/* major/minor must be able to beyond 100% for large fingers */
2364 	if (axis != ABS_MT_TOUCH_MAJOR &&
2365 	    axis != ABS_MT_TOUCH_MINOR) {
2366 		litest_assert_double_le(val, 100.0);
2367 	}
2368 
2369 	abs = libevdev_get_abs_info(d->evdev, axis);
2370 	litest_assert_notnull(abs);
2371 
2372 	return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum;
2373 }
2374 
2375 static inline int
litest_scale_range(int min,int max,double val)2376 litest_scale_range(int min, int max, double val)
2377 {
2378 	litest_assert_int_ge((int)val, 0);
2379 	litest_assert_int_le((int)val, 100);
2380 
2381 	return (max - min) * val/100.0 + min;
2382 }
2383 
2384 int
litest_scale(const struct litest_device * d,unsigned int axis,double val)2385 litest_scale(const struct litest_device *d, unsigned int axis, double val)
2386 {
2387 	int min, max;
2388 
2389 	litest_assert_double_ge(val, 0.0);
2390 	/* major/minor must be able to beyond 100% for large fingers */
2391 	if (axis != ABS_MT_TOUCH_MAJOR &&
2392 	    axis != ABS_MT_TOUCH_MINOR)
2393 		litest_assert_double_le(val, 100.0);
2394 
2395 	if (axis <= ABS_Y) {
2396 		min = d->interface->min[axis];
2397 		max = d->interface->max[axis];
2398 
2399 		return litest_scale_range(min, max, val);
2400 	} else {
2401 		return litest_scale_axis(d, axis, val);
2402 	}
2403 }
2404 
2405 static inline int
auto_assign_pad_value(struct litest_device * dev,struct input_event * ev,double value)2406 auto_assign_pad_value(struct litest_device *dev,
2407 		      struct input_event *ev,
2408 		      double value)
2409 {
2410 	const struct input_absinfo *abs;
2411 
2412 	if (ev->value != LITEST_AUTO_ASSIGN ||
2413 	    ev->type != EV_ABS)
2414 		return value;
2415 
2416 	abs = libevdev_get_abs_info(dev->evdev, ev->code);
2417 	litest_assert_notnull(abs);
2418 
2419 	if (ev->code == ABS_RX || ev->code == ABS_RY) {
2420 		double min = abs->minimum != 0 ? log2(abs->minimum) : 0,
2421 		       max = abs->maximum != 0 ? log2(abs->maximum) : 0;
2422 
2423 		/* Value 0 is reserved for finger up, so a value of 0% is
2424 		 * actually 1 */
2425 		if (value == 0.0) {
2426 			return 1;
2427 		} else {
2428 			value = litest_scale_range(min, max, value);
2429 			return pow(2, value);
2430 		}
2431 	} else {
2432 		return litest_scale_range(abs->minimum, abs->maximum, value);
2433 	}
2434 }
2435 
2436 void
litest_pad_ring_start(struct litest_device * d,double value)2437 litest_pad_ring_start(struct litest_device *d, double value)
2438 {
2439 	struct input_event *ev;
2440 
2441 	ev = d->interface->pad_ring_start_events;
2442 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2443 		value = auto_assign_pad_value(d, ev, value);
2444 		litest_event(d, ev->type, ev->code, value);
2445 		ev++;
2446 	}
2447 }
2448 
2449 void
litest_pad_ring_change(struct litest_device * d,double value)2450 litest_pad_ring_change(struct litest_device *d, double value)
2451 {
2452 	struct input_event *ev;
2453 
2454 	ev = d->interface->pad_ring_change_events;
2455 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2456 		value = auto_assign_pad_value(d, ev, value);
2457 		litest_event(d, ev->type, ev->code, value);
2458 		ev++;
2459 	}
2460 }
2461 
2462 void
litest_pad_ring_end(struct litest_device * d)2463 litest_pad_ring_end(struct litest_device *d)
2464 {
2465 	struct input_event *ev;
2466 
2467 	ev = d->interface->pad_ring_end_events;
2468 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2469 		litest_event(d, ev->type, ev->code, ev->value);
2470 		ev++;
2471 	}
2472 }
2473 
2474 void
litest_pad_strip_start(struct litest_device * d,double value)2475 litest_pad_strip_start(struct litest_device *d, double value)
2476 {
2477 	struct input_event *ev;
2478 
2479 	ev = d->interface->pad_strip_start_events;
2480 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2481 		value = auto_assign_pad_value(d, ev, value);
2482 		litest_event(d, ev->type, ev->code, value);
2483 		ev++;
2484 	}
2485 }
2486 
2487 void
litest_pad_strip_change(struct litest_device * d,double value)2488 litest_pad_strip_change(struct litest_device *d, double value)
2489 {
2490 	struct input_event *ev;
2491 
2492 	ev = d->interface->pad_strip_change_events;
2493 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2494 		value = auto_assign_pad_value(d, ev, value);
2495 		litest_event(d, ev->type, ev->code, value);
2496 		ev++;
2497 	}
2498 }
2499 
2500 void
litest_pad_strip_end(struct litest_device * d)2501 litest_pad_strip_end(struct litest_device *d)
2502 {
2503 	struct input_event *ev;
2504 
2505 	ev = d->interface->pad_strip_end_events;
2506 	while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
2507 		litest_event(d, ev->type, ev->code, ev->value);
2508 		ev++;
2509 	}
2510 }
2511 
2512 void
litest_wait_for_event(struct libinput * li)2513 litest_wait_for_event(struct libinput *li)
2514 {
2515 	return litest_wait_for_event_of_type(li, -1);
2516 }
2517 
2518 void
litest_wait_for_event_of_type(struct libinput * li,...)2519 litest_wait_for_event_of_type(struct libinput *li, ...)
2520 {
2521 	va_list args;
2522 	enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE};
2523 	size_t ntypes = 0;
2524 	enum libinput_event_type type;
2525 	struct pollfd fds;
2526 
2527 	va_start(args, li);
2528 	type = va_arg(args, int);
2529 	while ((int)type != -1) {
2530 		litest_assert(type > 0);
2531 		litest_assert(ntypes < ARRAY_LENGTH(types));
2532 		types[ntypes++] = type;
2533 		type = va_arg(args, int);
2534 	}
2535 	va_end(args);
2536 
2537 	fds.fd = libinput_get_fd(li);
2538 	fds.events = POLLIN;
2539 	fds.revents = 0;
2540 
2541 	while (1) {
2542 		size_t i;
2543 		struct libinput_event *event;
2544 
2545 		while ((type = libinput_next_event_type(li)) == LIBINPUT_EVENT_NONE) {
2546 			int rc = poll(&fds, 1, 2000);
2547 			litest_assert_int_gt(rc, 0);
2548 			libinput_dispatch(li);
2549 		}
2550 
2551 		/* no event mask means wait for any event */
2552 		if (ntypes == 0)
2553 			return;
2554 
2555 		for (i = 0; i < ntypes; i++) {
2556 			if (type == types[i])
2557 				return;
2558 		}
2559 
2560 		event = libinput_get_event(li);
2561 		libinput_event_destroy(event);
2562 	}
2563 }
2564 
2565 void
litest_drain_events(struct libinput * li)2566 litest_drain_events(struct libinput *li)
2567 {
2568 	struct libinput_event *event;
2569 
2570 	libinput_dispatch(li);
2571 	while ((event = libinput_get_event(li))) {
2572 		libinput_event_destroy(event);
2573 		libinput_dispatch(li);
2574 	}
2575 }
2576 
2577 static const char *
litest_event_type_str(enum libinput_event_type type)2578 litest_event_type_str(enum libinput_event_type type)
2579 {
2580 	const char *str = NULL;
2581 
2582 	switch (type) {
2583 	case LIBINPUT_EVENT_NONE:
2584 		abort();
2585 	case LIBINPUT_EVENT_DEVICE_ADDED:
2586 		str = "ADDED";
2587 		break;
2588 	case LIBINPUT_EVENT_DEVICE_REMOVED:
2589 		str = "REMOVED";
2590 		break;
2591 	case LIBINPUT_EVENT_KEYBOARD_KEY:
2592 		str = "KEY";
2593 		break;
2594 	case LIBINPUT_EVENT_POINTER_MOTION:
2595 		str = "MOTION";
2596 		break;
2597 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
2598 		str = "ABSOLUTE";
2599 		break;
2600 	case LIBINPUT_EVENT_POINTER_BUTTON:
2601 		str = "BUTTON";
2602 		break;
2603 	case LIBINPUT_EVENT_POINTER_AXIS:
2604 		str = "AXIS";
2605 		break;
2606 	case LIBINPUT_EVENT_TOUCH_DOWN:
2607 		str = "TOUCH DOWN";
2608 		break;
2609 	case LIBINPUT_EVENT_TOUCH_UP:
2610 		str = "TOUCH UP";
2611 		break;
2612 	case LIBINPUT_EVENT_TOUCH_MOTION:
2613 		str = "TOUCH MOTION";
2614 		break;
2615 	case LIBINPUT_EVENT_TOUCH_CANCEL:
2616 		str = "TOUCH CANCEL";
2617 		break;
2618 	case LIBINPUT_EVENT_TOUCH_FRAME:
2619 		str = "TOUCH FRAME";
2620 		break;
2621 	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
2622 		str = "GESTURE SWIPE START";
2623 		break;
2624 	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
2625 		str = "GESTURE SWIPE UPDATE";
2626 		break;
2627 	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
2628 		str = "GESTURE SWIPE END";
2629 		break;
2630 	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
2631 		str = "GESTURE PINCH START";
2632 		break;
2633 	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
2634 		str = "GESTURE PINCH UPDATE";
2635 		break;
2636 	case LIBINPUT_EVENT_GESTURE_PINCH_END:
2637 		str = "GESTURE PINCH END";
2638 		break;
2639 	case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
2640 		str = "TABLET TOOL AXIS";
2641 		break;
2642 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
2643 		str = "TABLET TOOL PROX";
2644 		break;
2645 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
2646 		str = "TABLET TOOL TIP";
2647 		break;
2648 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
2649 		str = "TABLET TOOL BUTTON";
2650 		break;
2651 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
2652 		str = "TABLET PAD BUTTON";
2653 		break;
2654 	case LIBINPUT_EVENT_TABLET_PAD_RING:
2655 		str = "TABLET PAD RING";
2656 		break;
2657 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
2658 		str = "TABLET PAD STRIP";
2659 		break;
2660 	case LIBINPUT_EVENT_SWITCH_TOGGLE:
2661 		str = "SWITCH TOGGLE";
2662 		break;
2663 	}
2664 	return str;
2665 }
2666 
2667 static const char *
litest_event_get_type_str(struct libinput_event * event)2668 litest_event_get_type_str(struct libinput_event *event)
2669 {
2670 	return litest_event_type_str(libinput_event_get_type(event));
2671 }
2672 
2673 static void
litest_print_event(struct libinput_event * event)2674 litest_print_event(struct libinput_event *event)
2675 {
2676 	struct libinput_event_pointer *p;
2677 	struct libinput_event_tablet_tool *t;
2678 	struct libinput_event_tablet_pad *pad;
2679 	struct libinput_device *dev;
2680 	enum libinput_event_type type;
2681 	double x, y;
2682 
2683 	dev = libinput_event_get_device(event);
2684 	type = libinput_event_get_type(event);
2685 
2686 	fprintf(stderr,
2687 		"device %s (%s) type %s ",
2688 		libinput_device_get_sysname(dev),
2689 		libinput_device_get_name(dev),
2690 		litest_event_get_type_str(event));
2691 	switch (type) {
2692 	case LIBINPUT_EVENT_POINTER_MOTION:
2693 		p = libinput_event_get_pointer_event(event);
2694 		x = libinput_event_pointer_get_dx(p);
2695 		y = libinput_event_pointer_get_dy(p);
2696 		fprintf(stderr, "%.2f/%.2f", x, y);
2697 		break;
2698 	case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
2699 		p = libinput_event_get_pointer_event(event);
2700 		x = libinput_event_pointer_get_absolute_x(p);
2701 		y = libinput_event_pointer_get_absolute_y(p);
2702 		fprintf(stderr, "%.2f/%.2f", x, y);
2703 		break;
2704 	case LIBINPUT_EVENT_POINTER_BUTTON:
2705 		p = libinput_event_get_pointer_event(event);
2706 		fprintf(stderr,
2707 			"button %d state %d",
2708 			libinput_event_pointer_get_button(p),
2709 			libinput_event_pointer_get_button_state(p));
2710 		break;
2711 	case LIBINPUT_EVENT_POINTER_AXIS:
2712 		p = libinput_event_get_pointer_event(event);
2713 		x = 0.0;
2714 		y = 0.0;
2715 		if (libinput_event_pointer_has_axis(p,
2716 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
2717 			y = libinput_event_pointer_get_axis_value(p,
2718 				LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
2719 		if (libinput_event_pointer_has_axis(p,
2720 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
2721 			x = libinput_event_pointer_get_axis_value(p,
2722 				LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
2723 		fprintf(stderr, "vert %.2f horiz %.2f", y, x);
2724 		break;
2725 	case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
2726 		t = libinput_event_get_tablet_tool_event(event);
2727 		fprintf(stderr, "proximity %d",
2728 			libinput_event_tablet_tool_get_proximity_state(t));
2729 		break;
2730 	case LIBINPUT_EVENT_TABLET_TOOL_TIP:
2731 		t = libinput_event_get_tablet_tool_event(event);
2732 		fprintf(stderr, "tip %d",
2733 			libinput_event_tablet_tool_get_tip_state(t));
2734 		break;
2735 	case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
2736 		t = libinput_event_get_tablet_tool_event(event);
2737 		fprintf(stderr, "button %d state %d",
2738 			libinput_event_tablet_tool_get_button(t),
2739 			libinput_event_tablet_tool_get_button_state(t));
2740 		break;
2741 	case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
2742 		pad = libinput_event_get_tablet_pad_event(event);
2743 		fprintf(stderr, "button %d state %d",
2744 			libinput_event_tablet_pad_get_button_number(pad),
2745 			libinput_event_tablet_pad_get_button_state(pad));
2746 		break;
2747 	case LIBINPUT_EVENT_TABLET_PAD_RING:
2748 		pad = libinput_event_get_tablet_pad_event(event);
2749 		fprintf(stderr, "ring %d position %.2f source %d",
2750 			libinput_event_tablet_pad_get_ring_number(pad),
2751 			libinput_event_tablet_pad_get_ring_position(pad),
2752 			libinput_event_tablet_pad_get_ring_source(pad));
2753 		break;
2754 	case LIBINPUT_EVENT_TABLET_PAD_STRIP:
2755 		pad = libinput_event_get_tablet_pad_event(event);
2756 		fprintf(stderr, "strip %d position %.2f source %d",
2757 			libinput_event_tablet_pad_get_ring_number(pad),
2758 			libinput_event_tablet_pad_get_ring_position(pad),
2759 			libinput_event_tablet_pad_get_ring_source(pad));
2760 		break;
2761 	default:
2762 		break;
2763 	}
2764 
2765 	fprintf(stderr, "\n");
2766 }
2767 
2768 void
litest_assert_event_type(struct libinput_event * event,enum libinput_event_type want)2769 litest_assert_event_type(struct libinput_event *event,
2770 			 enum libinput_event_type want)
2771 {
2772 	if (libinput_event_get_type(event) == want)
2773 		return;
2774 
2775 	fprintf(stderr,
2776 		"FAILED EVENT TYPE: %s: have %s (%d) but want %s (%d)\n",
2777 		libinput_device_get_name(libinput_event_get_device(event)),
2778 		litest_event_get_type_str(event),
2779 		libinput_event_get_type(event),
2780 		litest_event_type_str(want),
2781 		want);
2782 	fprintf(stderr, "Wrong event is: ");
2783 	litest_print_event(event);
2784 	litest_backtrace();
2785 	abort();
2786 }
2787 
2788 void
litest_assert_empty_queue(struct libinput * li)2789 litest_assert_empty_queue(struct libinput *li)
2790 {
2791 	bool empty_queue = true;
2792 	struct libinput_event *event;
2793 
2794 	libinput_dispatch(li);
2795 	while ((event = libinput_get_event(li))) {
2796 		empty_queue = false;
2797 		fprintf(stderr,
2798 			"Unexpected event: ");
2799 		litest_print_event(event);
2800 		libinput_event_destroy(event);
2801 		libinput_dispatch(li);
2802 	}
2803 
2804 	litest_assert(empty_queue);
2805 }
2806 
2807 static struct libevdev_uinput *
litest_create_uinput(const char * name,const struct input_id * id,const struct input_absinfo * abs_info,const int * events)2808 litest_create_uinput(const char *name,
2809 		     const struct input_id *id,
2810 		     const struct input_absinfo *abs_info,
2811 		     const int *events)
2812 {
2813 	struct libevdev_uinput *uinput;
2814 	struct libevdev *dev;
2815 	int type, code;
2816 	int rc, fd;
2817 	const struct input_absinfo *abs;
2818 	const struct input_absinfo default_abs = {
2819 		.value = 0,
2820 		.minimum = 0,
2821 		.maximum = 100,
2822 		.fuzz = 0,
2823 		.flat = 0,
2824 		.resolution = 100
2825 	};
2826 	char buf[512];
2827 	const char *devnode;
2828 
2829 	dev = libevdev_new();
2830 	litest_assert(dev != NULL);
2831 
2832 	snprintf(buf, sizeof(buf), "litest %s", name);
2833 	libevdev_set_name(dev, buf);
2834 	if (id) {
2835 		libevdev_set_id_bustype(dev, id->bustype);
2836 		libevdev_set_id_vendor(dev, id->vendor);
2837 		libevdev_set_id_product(dev, id->product);
2838 		libevdev_set_id_version(dev, id->version);
2839 	}
2840 
2841 	abs = abs_info;
2842 	while (abs && abs->value != -1) {
2843 		struct input_absinfo a = *abs;
2844 
2845 		/* abs_info->value is used for the code and may be outside
2846 		   of [min, max] */
2847 		a.value = abs->minimum;
2848 		rc = libevdev_enable_event_code(dev, EV_ABS, abs->value, &a);
2849 		litest_assert_int_eq(rc, 0);
2850 		abs++;
2851 	}
2852 
2853 	while (events &&
2854 	       (type = *events++) != -1 &&
2855 	       (code = *events++) != -1) {
2856 		if (type == INPUT_PROP_MAX) {
2857 			rc = libevdev_enable_property(dev, code);
2858 		} else {
2859 			rc = libevdev_enable_event_code(dev, type, code,
2860 							type == EV_ABS ? &default_abs : NULL);
2861 		}
2862 		litest_assert_int_eq(rc, 0);
2863 	}
2864 
2865 	rc = libevdev_uinput_create_from_device(dev,
2866 					        LIBEVDEV_UINPUT_OPEN_MANAGED,
2867 						&uinput);
2868 	/* workaround for a bug in libevdev pre-1.3
2869 	   http://cgit.freedesktop.org/libevdev/commit/?id=debe9b030c8069cdf78307888ef3b65830b25122 */
2870 	if (rc == -EBADF)
2871 		rc = -EACCES;
2872 	litest_assert_msg(rc == 0, "Failed to create uinput device: %s\n", strerror(-rc));
2873 
2874 	libevdev_free(dev);
2875 
2876 	devnode = libevdev_uinput_get_devnode(uinput);
2877 	litest_assert_notnull(devnode);
2878 	fd = open(devnode, O_RDONLY);
2879 	litest_assert_int_gt(fd, -1);
2880 	rc = libevdev_new_from_fd(fd, &dev);
2881 	litest_assert_int_eq(rc, 0);
2882 
2883 	/* uinput before kernel 4.5 + libevdev 1.5.0 does not support
2884 	 * setting the resolution, so we set it afterwards. This is of
2885 	 * course racy as hell but the way we _generally_ use this function
2886 	 * by the time libinput uses the device, we're finished here.
2887 	 *
2888 	 * If you have kernel 4.5 and libevdev 1.5.0 or later, this code
2889 	 * just keeps the room warm.
2890 	 */
2891 	abs = abs_info;
2892 	while (abs && abs->value != -1) {
2893 		if (abs->resolution != 0) {
2894 			if (libevdev_get_abs_resolution(dev, abs->value) ==
2895 			    abs->resolution)
2896 				break;
2897 
2898 			rc = libevdev_kernel_set_abs_info(dev,
2899 							  abs->value,
2900 							  abs);
2901 			litest_assert_int_eq(rc, 0);
2902 		}
2903 		abs++;
2904 	}
2905 	close(fd);
2906 	libevdev_free(dev);
2907 
2908 	return uinput;
2909 }
2910 
2911 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)2912 litest_create_uinput_device_from_description(const char *name,
2913 					     const struct input_id *id,
2914 					     const struct input_absinfo *abs_info,
2915 					     const int *events)
2916 {
2917 	struct libevdev_uinput *uinput;
2918 	const char *syspath;
2919 	char path[PATH_MAX];
2920 
2921 	struct udev_monitor *udev_monitor;
2922 	struct udev_device *udev_device;
2923 
2924 	udev_monitor = udev_setup_monitor();
2925 
2926 	uinput = litest_create_uinput(name, id, abs_info, events);
2927 
2928 	syspath = libevdev_uinput_get_syspath(uinput);
2929 	snprintf(path, sizeof(path), "%s/event", syspath);
2930 
2931 	udev_device = udev_wait_for_device_event(udev_monitor, "add", path);
2932 
2933 	litest_assert(udev_device_get_property_value(udev_device, "ID_INPUT"));
2934 
2935 	udev_device_unref(udev_device);
2936 	udev_monitor_unref(udev_monitor);
2937 
2938 	return uinput;
2939 }
2940 
2941 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)2942 litest_create_uinput_abs_device_v(const char *name,
2943 				  struct input_id *id,
2944 				  const struct input_absinfo *abs,
2945 				  va_list args)
2946 {
2947 	int events[KEY_MAX * 2 + 2]; /* increase this if not sufficient */
2948 	int *event = events;
2949 	int type, code;
2950 
2951 	while ((type = va_arg(args, int)) != -1 &&
2952 	       (code = va_arg(args, int)) != -1) {
2953 		*event++ = type;
2954 		*event++ = code;
2955 		litest_assert(event < &events[ARRAY_LENGTH(events) - 2]);
2956 	}
2957 
2958 	*event++ = -1;
2959 	*event++ = -1;
2960 
2961 	return litest_create_uinput_device_from_description(name, id,
2962 							    abs, events);
2963 }
2964 
2965 struct libevdev_uinput *
litest_create_uinput_abs_device(const char * name,struct input_id * id,const struct input_absinfo * abs,...)2966 litest_create_uinput_abs_device(const char *name,
2967 				struct input_id *id,
2968 				const struct input_absinfo *abs,
2969 				...)
2970 {
2971 	struct libevdev_uinput *uinput;
2972 	va_list args;
2973 
2974 	va_start(args, abs);
2975 	uinput = litest_create_uinput_abs_device_v(name, id, abs, args);
2976 	va_end(args);
2977 
2978 	return uinput;
2979 }
2980 
2981 struct libevdev_uinput *
litest_create_uinput_device(const char * name,struct input_id * id,...)2982 litest_create_uinput_device(const char *name, struct input_id *id, ...)
2983 {
2984 	struct libevdev_uinput *uinput;
2985 	va_list args;
2986 
2987 	va_start(args, id);
2988 	uinput = litest_create_uinput_abs_device_v(name, id, NULL, args);
2989 	va_end(args);
2990 
2991 	return uinput;
2992 }
2993 
2994 struct libinput_event_pointer*
litest_is_button_event(struct libinput_event * event,unsigned int button,enum libinput_button_state state)2995 litest_is_button_event(struct libinput_event *event,
2996 		       unsigned int button,
2997 		       enum libinput_button_state state)
2998 {
2999 	struct libinput_event_pointer *ptrev;
3000 	enum libinput_event_type type = LIBINPUT_EVENT_POINTER_BUTTON;
3001 
3002 	litest_assert(event != NULL);
3003 	litest_assert_event_type(event, type);
3004 	ptrev = libinput_event_get_pointer_event(event);
3005 	litest_assert_int_eq(libinput_event_pointer_get_button(ptrev),
3006 			     button);
3007 	litest_assert_int_eq(libinput_event_pointer_get_button_state(ptrev),
3008 			     state);
3009 
3010 	return ptrev;
3011 }
3012 
3013 struct libinput_event_pointer *
litest_is_axis_event(struct libinput_event * event,enum libinput_pointer_axis axis,enum libinput_pointer_axis_source source)3014 litest_is_axis_event(struct libinput_event *event,
3015 		     enum libinput_pointer_axis axis,
3016 		     enum libinput_pointer_axis_source source)
3017 {
3018 	struct libinput_event_pointer *ptrev;
3019 	enum libinput_event_type type = LIBINPUT_EVENT_POINTER_AXIS;
3020 
3021 	litest_assert(event != NULL);
3022 	litest_assert_event_type(event, type);
3023 	ptrev = libinput_event_get_pointer_event(event);
3024 	litest_assert(libinput_event_pointer_has_axis(ptrev, axis));
3025 
3026 	if (source != 0)
3027 		litest_assert_int_eq(libinput_event_pointer_get_axis_source(ptrev),
3028 				     source);
3029 
3030 	return ptrev;
3031 }
3032 
3033 struct libinput_event_pointer *
litest_is_motion_event(struct libinput_event * event)3034 litest_is_motion_event(struct libinput_event *event)
3035 {
3036 	struct libinput_event_pointer *ptrev;
3037 	enum libinput_event_type type = LIBINPUT_EVENT_POINTER_MOTION;
3038 	double x, y, ux, uy;
3039 
3040 	litest_assert(event != NULL);
3041 	litest_assert_event_type(event, type);
3042 	ptrev = libinput_event_get_pointer_event(event);
3043 
3044 	x = libinput_event_pointer_get_dx(ptrev);
3045 	y = libinput_event_pointer_get_dy(ptrev);
3046 	ux = libinput_event_pointer_get_dx_unaccelerated(ptrev);
3047 	uy = libinput_event_pointer_get_dy_unaccelerated(ptrev);
3048 
3049 	/* No 0 delta motion events */
3050 	litest_assert(x != 0.0 || y != 0.0 ||
3051 		      ux != 0.0 || uy != 0.0);
3052 
3053 	return ptrev;
3054 }
3055 
3056 void
litest_assert_key_event(struct libinput * li,unsigned int key,enum libinput_key_state state)3057 litest_assert_key_event(struct libinput *li, unsigned int key,
3058 			enum libinput_key_state state)
3059 {
3060 	struct libinput_event *event;
3061 
3062 	litest_wait_for_event(li);
3063 	event = libinput_get_event(li);
3064 
3065 	litest_is_keyboard_event(event, key, state);
3066 
3067 	libinput_event_destroy(event);
3068 }
3069 
3070 void
litest_assert_button_event(struct libinput * li,unsigned int button,enum libinput_button_state state)3071 litest_assert_button_event(struct libinput *li, unsigned int button,
3072 			   enum libinput_button_state state)
3073 {
3074 	struct libinput_event *event;
3075 
3076 	litest_wait_for_event(li);
3077 	event = libinput_get_event(li);
3078 
3079 	litest_is_button_event(event, button, state);
3080 
3081 	libinput_event_destroy(event);
3082 }
3083 
3084 struct libinput_event_touch *
litest_is_touch_event(struct libinput_event * event,enum libinput_event_type type)3085 litest_is_touch_event(struct libinput_event *event,
3086 		      enum libinput_event_type type)
3087 {
3088 	struct libinput_event_touch *touch;
3089 
3090 	litest_assert(event != NULL);
3091 
3092 	if (type == 0)
3093 		type = libinput_event_get_type(event);
3094 
3095 	switch (type) {
3096 	case LIBINPUT_EVENT_TOUCH_DOWN:
3097 	case LIBINPUT_EVENT_TOUCH_UP:
3098 	case LIBINPUT_EVENT_TOUCH_MOTION:
3099 	case LIBINPUT_EVENT_TOUCH_FRAME:
3100 	case LIBINPUT_EVENT_TOUCH_CANCEL:
3101 		litest_assert_event_type(event, type);
3102 		break;
3103 	default:
3104 		ck_abort_msg("%s: invalid touch type %d\n", __func__, type);
3105 	}
3106 
3107 	touch = libinput_event_get_touch_event(event);
3108 
3109 	return touch;
3110 }
3111 
3112 struct libinput_event_keyboard *
litest_is_keyboard_event(struct libinput_event * event,unsigned int key,enum libinput_key_state state)3113 litest_is_keyboard_event(struct libinput_event *event,
3114 			 unsigned int key,
3115 			 enum libinput_key_state state)
3116 {
3117 	struct libinput_event_keyboard *kevent;
3118 	enum libinput_event_type type = LIBINPUT_EVENT_KEYBOARD_KEY;
3119 
3120 	litest_assert(event != NULL);
3121 	litest_assert_event_type(event, type);
3122 
3123 	kevent = libinput_event_get_keyboard_event(event);
3124 	litest_assert(kevent != NULL);
3125 
3126 	litest_assert_int_eq(libinput_event_keyboard_get_key(kevent), key);
3127 	litest_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
3128 			     state);
3129 	return kevent;
3130 }
3131 
3132 struct libinput_event_gesture *
litest_is_gesture_event(struct libinput_event * event,enum libinput_event_type type,int nfingers)3133 litest_is_gesture_event(struct libinput_event *event,
3134 			enum libinput_event_type type,
3135 			int nfingers)
3136 {
3137 	struct libinput_event_gesture *gevent;
3138 
3139 	litest_assert(event != NULL);
3140 	litest_assert_event_type(event, type);
3141 
3142 	gevent = libinput_event_get_gesture_event(event);
3143 	litest_assert(gevent != NULL);
3144 
3145 	if (nfingers != -1)
3146 		litest_assert_int_eq(libinput_event_gesture_get_finger_count(gevent),
3147 				     nfingers);
3148 	return gevent;
3149 }
3150 
3151 struct libinput_event_tablet_tool *
litest_is_tablet_event(struct libinput_event * event,enum libinput_event_type type)3152 litest_is_tablet_event(struct libinput_event *event,
3153 		       enum libinput_event_type type)
3154 {
3155 	struct libinput_event_tablet_tool *tevent;
3156 
3157 	litest_assert(event != NULL);
3158 	litest_assert_event_type(event, type);
3159 
3160 	tevent = libinput_event_get_tablet_tool_event(event);
3161 	litest_assert(tevent != NULL);
3162 
3163 	return tevent;
3164 }
3165 
3166 void
litest_assert_tablet_button_event(struct libinput * li,unsigned int button,enum libinput_button_state state)3167 litest_assert_tablet_button_event(struct libinput *li, unsigned int button,
3168 				  enum libinput_button_state state)
3169 {
3170 	struct libinput_event *event;
3171 	struct libinput_event_tablet_tool *tev;
3172 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_BUTTON;
3173 
3174 	litest_wait_for_event(li);
3175 	event = libinput_get_event(li);
3176 
3177 	litest_assert_notnull(event);
3178 	litest_assert_event_type(event, type);
3179 	tev = libinput_event_get_tablet_tool_event(event);
3180 	litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
3181 			     button);
3182 	litest_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
3183 			     state);
3184 	libinput_event_destroy(event);
3185 }
3186 
litest_assert_tablet_proximity_event(struct libinput * li,enum libinput_tablet_tool_proximity_state state)3187 void litest_assert_tablet_proximity_event(struct libinput *li,
3188 					  enum libinput_tablet_tool_proximity_state state)
3189 {
3190 	struct libinput_event *event;
3191 	struct libinput_event_tablet_tool *tev;
3192 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY;
3193 
3194 	litest_wait_for_event(li);
3195 	event = libinput_get_event(li);
3196 
3197 	litest_assert_notnull(event);
3198 	litest_assert_event_type(event, type);
3199 	tev = libinput_event_get_tablet_tool_event(event);
3200 	litest_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3201 			     state);
3202 	libinput_event_destroy(event);
3203 }
3204 
3205 struct libinput_event_tablet_pad *
litest_is_pad_button_event(struct libinput_event * event,unsigned int button,enum libinput_button_state state)3206 litest_is_pad_button_event(struct libinput_event *event,
3207 			   unsigned int button,
3208 			   enum libinput_button_state state)
3209 {
3210 	struct libinput_event_tablet_pad *p;
3211 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_BUTTON;
3212 
3213 	litest_assert(event != NULL);
3214 	litest_assert_event_type(event, type);
3215 
3216 	p = libinput_event_get_tablet_pad_event(event);
3217 	litest_assert(p != NULL);
3218 
3219 	litest_assert_int_eq(libinput_event_tablet_pad_get_button_number(p),
3220 			     button);
3221 	litest_assert_int_eq(libinput_event_tablet_pad_get_button_state(p),
3222 			     state);
3223 
3224 	return p;
3225 }
3226 
3227 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)3228 litest_is_pad_ring_event(struct libinput_event *event,
3229 			 unsigned int number,
3230 			 enum libinput_tablet_pad_ring_axis_source source)
3231 {
3232 	struct libinput_event_tablet_pad *p;
3233 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_RING;
3234 
3235 	litest_assert(event != NULL);
3236 	litest_assert_event_type(event, type);
3237 	p = libinput_event_get_tablet_pad_event(event);
3238 
3239 	litest_assert_int_eq(libinput_event_tablet_pad_get_ring_number(p),
3240 			     number);
3241 	litest_assert_int_eq(libinput_event_tablet_pad_get_ring_source(p),
3242 			     source);
3243 
3244 	return p;
3245 }
3246 
3247 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)3248 litest_is_pad_strip_event(struct libinput_event *event,
3249 			  unsigned int number,
3250 			  enum libinput_tablet_pad_strip_axis_source source)
3251 {
3252 	struct libinput_event_tablet_pad *p;
3253 	enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_STRIP;
3254 
3255 	litest_assert(event != NULL);
3256 	litest_assert_event_type(event, type);
3257 	p = libinput_event_get_tablet_pad_event(event);
3258 
3259 	litest_assert_int_eq(libinput_event_tablet_pad_get_strip_number(p),
3260 			     number);
3261 	litest_assert_int_eq(libinput_event_tablet_pad_get_strip_source(p),
3262 			     source);
3263 
3264 	return p;
3265 }
3266 
3267 struct libinput_event_switch *
litest_is_switch_event(struct libinput_event * event,enum libinput_switch sw,enum libinput_switch_state state)3268 litest_is_switch_event(struct libinput_event *event,
3269 		       enum libinput_switch sw,
3270 		       enum libinput_switch_state state)
3271 {
3272 	struct libinput_event_switch *swev;
3273 	enum libinput_event_type type = LIBINPUT_EVENT_SWITCH_TOGGLE;
3274 
3275 	litest_assert_notnull(event);
3276 	litest_assert_event_type(event, type);
3277 	swev = libinput_event_get_switch_event(event);
3278 
3279 	litest_assert_int_eq(libinput_event_switch_get_switch(swev), sw);
3280 	litest_assert_int_eq(libinput_event_switch_get_switch_state(swev),
3281 			     state);
3282 
3283 	return swev;
3284 }
3285 
3286 void
litest_assert_pad_button_event(struct libinput * li,unsigned int button,enum libinput_button_state state)3287 litest_assert_pad_button_event(struct libinput *li,
3288 			       unsigned int button,
3289 			       enum libinput_button_state state)
3290 {
3291 	struct libinput_event *event;
3292 	struct libinput_event_tablet_pad *pev;
3293 
3294 	litest_wait_for_event(li);
3295 	event = libinput_get_event(li);
3296 
3297 	pev = litest_is_pad_button_event(event, button, state);
3298 	libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev));
3299 }
3300 
3301 void
litest_assert_scroll(struct libinput * li,enum libinput_pointer_axis axis,int minimum_movement)3302 litest_assert_scroll(struct libinput *li,
3303 		     enum libinput_pointer_axis axis,
3304 		     int minimum_movement)
3305 {
3306 	struct libinput_event *event, *next_event;
3307 	struct libinput_event_pointer *ptrev;
3308 	int value;
3309 	int nevents = 0;
3310 
3311 	event = libinput_get_event(li);
3312 	next_event = libinput_get_event(li);
3313 	litest_assert(next_event != NULL); /* At least 1 scroll + stop scroll */
3314 
3315 	while (event) {
3316 		ptrev = litest_is_axis_event(event, axis, 0);
3317 		nevents++;
3318 
3319 		if (next_event) {
3320 			int min = minimum_movement;
3321 
3322 			value = libinput_event_pointer_get_axis_value(ptrev,
3323 								      axis);
3324 			/* Due to how the hysteresis works on touchpad
3325 			 * events, the first event is reduced by the
3326 			 * hysteresis margin that can cause the first event
3327 			 * go under the minimum we expect for all other
3328 			 * events */
3329 			if (nevents == 1)
3330 				min = minimum_movement/2;
3331 
3332 			/* Normal scroll event, check dir */
3333 			if (minimum_movement > 0)
3334 				litest_assert_int_ge(value, min);
3335 			else
3336 				litest_assert_int_le(value, min);
3337 		} else {
3338 			/* Last scroll event, must be 0 */
3339 			ck_assert_double_eq(
3340 				libinput_event_pointer_get_axis_value(ptrev, axis),
3341 				0.0);
3342 		}
3343 		libinput_event_destroy(event);
3344 		event = next_event;
3345 		next_event = libinput_get_event(li);
3346 	}
3347 }
3348 
3349 void
litest_assert_only_typed_events(struct libinput * li,enum libinput_event_type type)3350 litest_assert_only_typed_events(struct libinput *li,
3351 				enum libinput_event_type type)
3352 {
3353 	struct libinput_event *event;
3354 
3355 	litest_assert(type != LIBINPUT_EVENT_NONE);
3356 
3357 	libinput_dispatch(li);
3358 	event = libinput_get_event(li);
3359 	litest_assert_notnull(event);
3360 
3361 	while (event) {
3362 		litest_assert_int_eq(libinput_event_get_type(event),
3363                                      type);
3364 		libinput_event_destroy(event);
3365 		libinput_dispatch(li);
3366 		event = libinput_get_event(li);
3367 	}
3368 }
3369 
3370 void
litest_assert_touch_sequence(struct libinput * li)3371 litest_assert_touch_sequence(struct libinput *li)
3372 {
3373 	struct libinput_event *event;
3374 	struct libinput_event_touch *tev;
3375 	int slot;
3376 
3377 	event = libinput_get_event(li);
3378 	tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
3379 	slot = libinput_event_touch_get_slot(tev);
3380 	libinput_event_destroy(event);
3381 
3382 	event = libinput_get_event(li);
3383 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3384 	libinput_event_destroy(event);
3385 
3386 	event = libinput_get_event(li);
3387 	do {
3388 		tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
3389 		litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev));
3390 		libinput_event_destroy(event);
3391 
3392 		event = libinput_get_event(li);
3393 		litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3394 		libinput_event_destroy(event);
3395 
3396 		event = libinput_get_event(li);
3397 		litest_assert_notnull(event);
3398 	} while (libinput_event_get_type(event) != LIBINPUT_EVENT_TOUCH_UP);
3399 
3400 	tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
3401 	litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev));
3402 	libinput_event_destroy(event);
3403 	event = libinput_get_event(li);
3404 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3405 	libinput_event_destroy(event);
3406 }
3407 
3408 void
litest_assert_touch_motion_frame(struct libinput * li)3409 litest_assert_touch_motion_frame(struct libinput *li)
3410 {
3411 	struct libinput_event *event;
3412 
3413 	/* expect at least one, but maybe more */
3414 	event = libinput_get_event(li);
3415 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
3416 	libinput_event_destroy(event);
3417 
3418 	event = libinput_get_event(li);
3419 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3420 	libinput_event_destroy(event);
3421 
3422 	event = libinput_get_event(li);
3423 	while (event) {
3424 		litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION);
3425 		libinput_event_destroy(event);
3426 
3427 		event = libinput_get_event(li);
3428 		litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3429 		libinput_event_destroy(event);
3430 
3431 		event = libinput_get_event(li);
3432 	}
3433 }
3434 
3435 void
litest_assert_touch_down_frame(struct libinput * li)3436 litest_assert_touch_down_frame(struct libinput *li)
3437 {
3438 	struct libinput_event *event;
3439 
3440 	event = libinput_get_event(li);
3441 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
3442 	libinput_event_destroy(event);
3443 
3444 	event = libinput_get_event(li);
3445 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3446 	libinput_event_destroy(event);
3447 }
3448 
3449 void
litest_assert_touch_up_frame(struct libinput * li)3450 litest_assert_touch_up_frame(struct libinput *li)
3451 {
3452 	struct libinput_event *event;
3453 
3454 	event = libinput_get_event(li);
3455 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP);
3456 	libinput_event_destroy(event);
3457 
3458 	event = libinput_get_event(li);
3459 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3460 	libinput_event_destroy(event);
3461 }
3462 
3463 void
litest_assert_touch_cancel(struct libinput * li)3464 litest_assert_touch_cancel(struct libinput *li)
3465 {
3466 	struct libinput_event *event;
3467 
3468 	event = libinput_get_event(li);
3469 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_CANCEL);
3470 	libinput_event_destroy(event);
3471 
3472 	event = libinput_get_event(li);
3473 	litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME);
3474 	libinput_event_destroy(event);
3475 }
3476 
3477 void
litest_timeout_tap(void)3478 litest_timeout_tap(void)
3479 {
3480 	msleep(200);
3481 }
3482 
3483 void
litest_timeout_tapndrag(void)3484 litest_timeout_tapndrag(void)
3485 {
3486 	msleep(520);
3487 }
3488 
3489 void
litest_timeout_debounce(void)3490 litest_timeout_debounce(void)
3491 {
3492 	msleep(30);
3493 }
3494 
3495 void
litest_timeout_softbuttons(void)3496 litest_timeout_softbuttons(void)
3497 {
3498 	msleep(300);
3499 }
3500 
3501 void
litest_timeout_buttonscroll(void)3502 litest_timeout_buttonscroll(void)
3503 {
3504 	msleep(300);
3505 }
3506 
3507 void
litest_timeout_finger_switch(void)3508 litest_timeout_finger_switch(void)
3509 {
3510 	msleep(120);
3511 }
3512 
3513 void
litest_timeout_edgescroll(void)3514 litest_timeout_edgescroll(void)
3515 {
3516 	msleep(300);
3517 }
3518 
3519 void
litest_timeout_middlebutton(void)3520 litest_timeout_middlebutton(void)
3521 {
3522 	msleep(70);
3523 }
3524 
3525 void
litest_timeout_dwt_short(void)3526 litest_timeout_dwt_short(void)
3527 {
3528 	msleep(220);
3529 }
3530 
3531 void
litest_timeout_dwt_long(void)3532 litest_timeout_dwt_long(void)
3533 {
3534 	msleep(520);
3535 }
3536 
3537 void
litest_timeout_gesture(void)3538 litest_timeout_gesture(void)
3539 {
3540 	msleep(120);
3541 }
3542 
3543 void
litest_timeout_gesture_scroll(void)3544 litest_timeout_gesture_scroll(void)
3545 {
3546 	msleep(180);
3547 }
3548 
3549 void
litest_timeout_trackpoint(void)3550 litest_timeout_trackpoint(void)
3551 {
3552 	msleep(320);
3553 }
3554 
3555 void
litest_timeout_tablet_proxout(void)3556 litest_timeout_tablet_proxout(void)
3557 {
3558 	msleep(170);
3559 }
3560 
3561 void
litest_timeout_touch_arbitration(void)3562 litest_timeout_touch_arbitration(void)
3563 {
3564 	msleep(100);
3565 }
3566 
3567 void
litest_timeout_hysteresis(void)3568 litest_timeout_hysteresis(void)
3569 {
3570 	msleep(90);
3571 }
3572 
3573 void
litest_timeout_thumb(void)3574 litest_timeout_thumb(void)
3575 {
3576 	msleep(320);
3577 }
3578 
3579 void
litest_push_event_frame(struct litest_device * dev)3580 litest_push_event_frame(struct litest_device *dev)
3581 {
3582 	litest_assert(dev->skip_ev_syn >= 0);
3583 	dev->skip_ev_syn++;
3584 }
3585 
3586 void
litest_pop_event_frame(struct litest_device * dev)3587 litest_pop_event_frame(struct litest_device *dev)
3588 {
3589 	litest_assert(dev->skip_ev_syn > 0);
3590 	dev->skip_ev_syn--;
3591 	if (dev->skip_ev_syn == 0)
3592 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3593 }
3594 
3595 void
litest_filter_event(struct litest_device * dev,unsigned int type,unsigned int code)3596 litest_filter_event(struct litest_device *dev,
3597 		    unsigned int type,
3598 		    unsigned int code)
3599 {
3600 	libevdev_disable_event_code(dev->evdev, type, code);
3601 }
3602 
3603 void
litest_unfilter_event(struct litest_device * dev,unsigned int type,unsigned int code)3604 litest_unfilter_event(struct litest_device *dev,
3605 		      unsigned int type,
3606 		      unsigned int code)
3607 {
3608 	/* would need an non-NULL argument for re-enabling, so simply abort
3609 	 * until we need to be more sophisticated */
3610 	litest_assert(type != EV_ABS);
3611 
3612 	libevdev_enable_event_code(dev->evdev, type, code, NULL);
3613 }
3614 
3615 static void
send_abs_xy(struct litest_device * d,double x,double y)3616 send_abs_xy(struct litest_device *d, double x, double y)
3617 {
3618 	struct input_event e;
3619 	int val;
3620 
3621 	e.type = EV_ABS;
3622 	e.code = ABS_X;
3623 	e.value = LITEST_AUTO_ASSIGN;
3624 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
3625 	litest_event(d, EV_ABS, ABS_X, val);
3626 
3627 	e.code = ABS_Y;
3628 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
3629 	litest_event(d, EV_ABS, ABS_Y, val);
3630 }
3631 
3632 static void
send_abs_mt_xy(struct litest_device * d,double x,double y)3633 send_abs_mt_xy(struct litest_device *d, double x, double y)
3634 {
3635 	struct input_event e;
3636 	int val;
3637 
3638 	e.type = EV_ABS;
3639 	e.code = ABS_MT_POSITION_X;
3640 	e.value = LITEST_AUTO_ASSIGN;
3641 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
3642 	litest_event(d, EV_ABS, ABS_MT_POSITION_X, val);
3643 
3644 	e.code = ABS_MT_POSITION_Y;
3645 	e.value = LITEST_AUTO_ASSIGN;
3646 	val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true);
3647 	litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val);
3648 }
3649 
3650 void
litest_semi_mt_touch_down(struct litest_device * d,struct litest_semi_mt * semi_mt,unsigned int slot,double x,double y)3651 litest_semi_mt_touch_down(struct litest_device *d,
3652 			  struct litest_semi_mt *semi_mt,
3653 			  unsigned int slot,
3654 			  double x, double y)
3655 {
3656 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
3657 
3658 	if (d->ntouches_down > 2 || slot > 1)
3659 		return;
3660 
3661 	if (d->ntouches_down == 1) {
3662 		l = x;
3663 		t = y;
3664 	} else {
3665 		int other = (slot + 1) % 2;
3666 		l = min(x, semi_mt->touches[other].x);
3667 		t = min(y, semi_mt->touches[other].y);
3668 		r = max(x, semi_mt->touches[other].x);
3669 		b = max(y, semi_mt->touches[other].y);
3670 	}
3671 
3672 	send_abs_xy(d, l, t);
3673 
3674 	litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
3675 
3676 	if (d->ntouches_down == 1)
3677 		litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
3678 
3679 	send_abs_mt_xy(d, l, t);
3680 
3681 	if (d->ntouches_down == 2) {
3682 		litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
3683 		litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id);
3684 
3685 		send_abs_mt_xy(d, r, b);
3686 	}
3687 
3688 	litest_event(d, EV_SYN, SYN_REPORT, 0);
3689 
3690 	semi_mt->touches[slot].x = x;
3691 	semi_mt->touches[slot].y = y;
3692 }
3693 
3694 void
litest_semi_mt_touch_move(struct litest_device * d,struct litest_semi_mt * semi_mt,unsigned int slot,double x,double y)3695 litest_semi_mt_touch_move(struct litest_device *d,
3696 			  struct litest_semi_mt *semi_mt,
3697 			  unsigned int slot,
3698 			  double x, double y)
3699 {
3700 	double t, l, r = 0, b = 0; /* top, left, right, bottom */
3701 
3702 	if (d->ntouches_down > 2 || slot > 1)
3703 		return;
3704 
3705 	if (d->ntouches_down == 1) {
3706 		l = x;
3707 		t = y;
3708 	} else {
3709 		int other = (slot + 1) % 2;
3710 		l = min(x, semi_mt->touches[other].x);
3711 		t = min(y, semi_mt->touches[other].y);
3712 		r = max(x, semi_mt->touches[other].x);
3713 		b = max(y, semi_mt->touches[other].y);
3714 	}
3715 
3716 	send_abs_xy(d, l, t);
3717 
3718 	litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
3719 	send_abs_mt_xy(d, l, t);
3720 
3721 	if (d->ntouches_down == 2) {
3722 		litest_event(d, EV_ABS, ABS_MT_SLOT, 1);
3723 		send_abs_mt_xy(d, r, b);
3724 	}
3725 
3726 	litest_event(d, EV_SYN, SYN_REPORT, 0);
3727 
3728 	semi_mt->touches[slot].x = x;
3729 	semi_mt->touches[slot].y = y;
3730 }
3731 
3732 void
litest_semi_mt_touch_up(struct litest_device * d,struct litest_semi_mt * semi_mt,unsigned int slot)3733 litest_semi_mt_touch_up(struct litest_device *d,
3734 			struct litest_semi_mt *semi_mt,
3735 			unsigned int slot)
3736 {
3737 	/* note: ntouches_down is decreased before we get here */
3738 	if (d->ntouches_down >= 2 || slot > 1)
3739 		return;
3740 
3741 	litest_event(d, EV_ABS, ABS_MT_SLOT, d->ntouches_down);
3742 	litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, -1);
3743 
3744 	/* if we have one finger left, send x/y coords for that finger left.
3745 	   this is likely to happen with a real touchpad */
3746 	if (d->ntouches_down == 1) {
3747 		int other = (slot + 1) % 2;
3748 		send_abs_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
3749 		litest_event(d, EV_ABS, ABS_MT_SLOT, 0);
3750 		send_abs_mt_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y);
3751 	}
3752 
3753 	litest_event(d, EV_SYN, SYN_REPORT, 0);
3754 }
3755 
3756 enum litest_mode {
3757 	LITEST_MODE_ERROR,
3758 	LITEST_MODE_TEST,
3759 	LITEST_MODE_LIST,
3760 };
3761 
3762 static inline enum litest_mode
litest_parse_argv(int argc,char ** argv)3763 litest_parse_argv(int argc, char **argv)
3764 {
3765 	enum {
3766 		OPT_FILTER_TEST,
3767 		OPT_FILTER_DEVICE,
3768 		OPT_FILTER_GROUP,
3769 		OPT_FILTER_DEVICELESS,
3770 		OPT_JOBS,
3771 		OPT_LIST,
3772 		OPT_VERBOSE,
3773 	};
3774 	static const struct option opts[] = {
3775 		{ "filter-test", 1, 0, OPT_FILTER_TEST },
3776 		{ "filter-device", 1, 0, OPT_FILTER_DEVICE },
3777 		{ "filter-group", 1, 0, OPT_FILTER_GROUP },
3778 		{ "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS },
3779 		{ "jobs", 1, 0, OPT_JOBS },
3780 		{ "list", 0, 0, OPT_LIST },
3781 		{ "verbose", 0, 0, OPT_VERBOSE },
3782 		{ 0, 0, 0, 0}
3783 	};
3784 
3785 	enum {
3786 		JOBS_DEFAULT,
3787 		JOBS_SINGLE,
3788 		JOBS_CUSTOM
3789 	} want_jobs = JOBS_DEFAULT;
3790 
3791 	if (in_debugger)
3792 		want_jobs = JOBS_SINGLE;
3793 
3794 	while(1) {
3795 		int c;
3796 		int option_index = 0;
3797 
3798 		c = getopt_long(argc, argv, "j:", opts, &option_index);
3799 		if (c == -1)
3800 			break;
3801 		switch(c) {
3802 		case OPT_FILTER_TEST:
3803 			filter_test = optarg;
3804 			if (want_jobs == JOBS_DEFAULT)
3805 				want_jobs = JOBS_SINGLE;
3806 			break;
3807 		case OPT_FILTER_DEVICE:
3808 			filter_device = optarg;
3809 			if (want_jobs == JOBS_DEFAULT)
3810 				want_jobs = JOBS_SINGLE;
3811 			break;
3812 		case OPT_FILTER_GROUP:
3813 			filter_group = optarg;
3814 			if (want_jobs == JOBS_DEFAULT)
3815 				want_jobs = JOBS_SINGLE;
3816 			break;
3817 		case 'j':
3818 		case OPT_JOBS:
3819 			jobs = atoi(optarg);
3820 			want_jobs = JOBS_CUSTOM;
3821 			break;
3822 		case OPT_LIST:
3823 			return LITEST_MODE_LIST;
3824 		case OPT_VERBOSE:
3825 			verbose = true;
3826 			break;
3827 		case OPT_FILTER_DEVICELESS:
3828 			run_deviceless = true;
3829 			break;
3830 		default:
3831 			fprintf(stderr, "usage: %s [--list]\n", argv[0]);
3832 			return LITEST_MODE_ERROR;
3833 		}
3834 	}
3835 
3836 	if (want_jobs == JOBS_SINGLE)
3837 		jobs = 1;
3838 
3839 	return LITEST_MODE_TEST;
3840 }
3841 
3842 #ifndef LITEST_NO_MAIN
3843 static bool
is_debugger_attached(void)3844 is_debugger_attached(void)
3845 {
3846 	int status;
3847 	bool rc;
3848 	int pid = fork();
3849 
3850 	if (pid == -1)
3851 		return 0;
3852 
3853 	if (pid == 0) {
3854 		int ppid = getppid();
3855 		if (ptrace(PTRACE_ATTACH, ppid, NULL, 0) == 0) {
3856 			waitpid(ppid, NULL, 0);
3857 			ptrace(PTRACE_CONT, ppid, NULL, 0);
3858 			ptrace(PTRACE_DETACH, ppid, NULL, 0);
3859 			rc = false;
3860 		} else {
3861 			rc = true;
3862 		}
3863 		_exit(rc);
3864 	} else {
3865 		waitpid(pid, &status, 0);
3866 		rc = WEXITSTATUS(status);
3867 	}
3868 
3869 	return !!rc;
3870 }
3871 
3872 static void
litest_list_tests(struct list * tests)3873 litest_list_tests(struct list *tests)
3874 {
3875 	struct suite *s;
3876 	const char *last_test_name = NULL;
3877 
3878 	list_for_each(s, tests, node) {
3879 		struct test *t;
3880 		printf("%s:\n", s->name);
3881 		list_for_each(t, &s->tests, node) {
3882 			if (!last_test_name ||
3883 			    !streq(last_test_name, t->name))
3884 				printf("	%s:\n", t->name);
3885 
3886 			last_test_name = t->name;
3887 
3888 			printf("		%s\n", t->devname);
3889 		}
3890 	}
3891 }
3892 
3893 extern const struct test_device __start_test_section, __stop_test_section;
3894 
3895 static void
litest_init_test_devices(void)3896 litest_init_test_devices(void)
3897 {
3898 	const struct test_device *t;
3899 
3900 	list_init(&devices);
3901 
3902 	for (t = &__start_test_section; t < &__stop_test_section; t++)
3903 		list_append(&devices, &t->device->node);
3904 }
3905 
3906 extern const struct test_collection __start_test_collection_section,
3907 				    __stop_test_collection_section;
3908 
3909 static void
setup_tests(void)3910 setup_tests(void)
3911 {
3912 	const struct test_collection *c;
3913 
3914 	for (c = &__start_test_collection_section;
3915 	     c < &__stop_test_collection_section;
3916 	     c++) {
3917 		c->setup();
3918 	}
3919 }
3920 
3921 static int
check_device_access(void)3922 check_device_access(void)
3923 {
3924 	if (getuid() != 0) {
3925 		fprintf(stderr,
3926 			"%s must be run as root.\n",
3927 			program_invocation_short_name);
3928 		return 77;
3929 	}
3930 
3931 	if (access("/dev/uinput", F_OK) == -1 &&
3932 	    access("/dev/input/uinput", F_OK) == -1) {
3933 		fprintf(stderr,
3934 			"uinput device is missing, skipping tests.\n");
3935 		return 77;
3936 	}
3937 
3938 	return 0;
3939 }
3940 
3941 static int
disable_tty(void)3942 disable_tty(void)
3943 {
3944 	int tty_mode = -1;
3945 
3946 	/* If we're running 'normally' on the VT, disable the keyboard to
3947 	 * avoid messing up our host. But if we're inside gdb or running
3948 	 * without forking, leave it as-is.
3949 	 */
3950 	if (!run_deviceless &&
3951 	    jobs > 1 &&
3952 	    !in_debugger &&
3953 	    getenv("CK_FORK") == NULL &&
3954 	    isatty(STDIN_FILENO) &&
3955 	    ioctl(STDIN_FILENO, KDGKBMODE, &tty_mode) == 0) {
3956 #ifdef __linux__
3957 		ioctl(STDIN_FILENO, KDSKBMODE, K_OFF);
3958 #elif __FreeBSD__
3959 		ioctl(STDIN_FILENO, KDSKBMODE, K_RAW);
3960 
3961 		/* Put the tty into raw mode */
3962 		struct termios tios;
3963 		if (tcgetattr(STDIN_FILENO, &tios))
3964 				fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno));
3965 		cfmakeraw(&tios);
3966 		if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios))
3967 				fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno));
3968 #endif
3969 	}
3970 
3971 	return tty_mode;
3972 }
3973 
3974 int
main(int argc,char ** argv)3975 main(int argc, char **argv)
3976 {
3977 	const struct rlimit corelimit = { 0, 0 };
3978 	enum litest_mode mode;
3979 	int tty_mode = -1;
3980 	int failed_tests;
3981 	int rc;
3982 
3983 	in_debugger = is_debugger_attached();
3984 	if (in_debugger)
3985 		setenv("CK_FORK", "no", 0);
3986 
3987 	mode = litest_parse_argv(argc, argv);
3988 	if (mode == LITEST_MODE_ERROR)
3989 		return EXIT_FAILURE;
3990 
3991 	/* You don't get to skip the deviceless tests */
3992 	if (!run_deviceless) {
3993 		if (getenv("SKIP_LIBINPUT_TEST_SUITE_RUNNER"))
3994 			return 77;
3995 
3996 		if ((rc = check_device_access()) != 0)
3997 			return rc;
3998 	}
3999 
4000 	litest_init_test_devices();
4001 
4002 	list_init(&all_tests);
4003 
4004 	setenv("CK_DEFAULT_TIMEOUT", "30", 0);
4005 	setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1);
4006 
4007 	setup_tests();
4008 
4009 	if (mode == LITEST_MODE_LIST) {
4010 		litest_list_tests(&all_tests);
4011 		return EXIT_SUCCESS;
4012 	}
4013 
4014 	if (setrlimit(RLIMIT_CORE, &corelimit) != 0)
4015 		perror("WARNING: Core dumps not disabled. Reason");
4016 
4017 	tty_mode = disable_tty();
4018 
4019 	failed_tests = litest_run(argc, argv);
4020 
4021 	if (tty_mode != -1) {
4022 		ioctl(STDIN_FILENO, KDSKBMODE, tty_mode);
4023 #ifdef __FreeBSD__
4024 		/* Put the tty into "sane" mode */
4025 		struct termios tios;
4026 		if (tcgetattr(STDIN_FILENO, &tios))
4027 				fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno));
4028 		cfmakesane(&tios);
4029 		if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios))
4030 				fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno));
4031 #endif
4032 	}
4033 
4034 	return failed_tests;
4035 }
4036 #endif
4037