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