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