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