1 /*
2 * Copyright © 2013 Red Hat, Inc.
3 * Copyright © 2013 Marcin Slusarz <marcin.slusarz@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "config.h"
26
27 #include <check.h>
28 #include <dirent.h>
29 #include <errno.h>
30 #include <libgen.h>
31 #include <fcntl.h>
32 #include <fnmatch.h>
33 #include <getopt.h>
34 #include <poll.h>
35 #include <signal.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdarg.h>
40 #include <time.h>
41 #include <unistd.h>
42 #include "linux/input.h"
43 #include <sys/ptrace.h>
44 #include <sys/resource.h>
45 #include <sys/timerfd.h>
46 #include <sys/wait.h>
47 #include <sys/stat.h>
48 #include <sys/types.h>
49 #include <sys/sysinfo.h>
50 #include <libudev.h>
51 #if HAVE_LIBSYSTEMD
52 #include <systemd/sd-bus.h>
53 #endif
54 #ifdef __FreeBSD__
55 #include <termios.h>
56 #endif
57
58 #include <valgrind/valgrind.h>
59
60 #include "litest.h"
61 #include "litest-int.h"
62 #include "libinput-util.h"
63 #include "quirks.h"
64 #include "builddir.h"
65
66 #include <linux/kd.h>
67
68 #define evbit(t, c) ((t) << 16U | (c & 0xffff))
69
70 #define UDEV_RULES_D "/run/udev/rules.d"
71 #define UDEV_FUZZ_OVERRIDE_RULE_FILE UDEV_RULES_D \
72 "/91-litest-fuzz-override-REMOVEME-XXXXXX.rules"
73 #define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \
74 "/91-litest-test-device-REMOVEME-XXXXXXX.rules"
75 #define UDEV_DEVICE_GROUPS_FILE UDEV_RULES_D \
76 "/80-libinput-device-groups-litest-XXXXXX.rules"
77
78 static int jobs;
79 static bool in_debugger = false;
80 static bool verbose = false;
81 static bool run_deviceless = false;
82 static bool use_system_rules_quirks = false;
83 static const char *filter_test = NULL;
84 static const char *filter_device = NULL;
85 static const char *filter_group = NULL;
86 static const char *xml_prefix = NULL;
87 static struct quirks_context *quirks_context;
88
89 struct created_file {
90 struct list link;
91 char *path;
92 };
93
94 static struct list created_files_list; /* list of all files to remove at the end
95 of the test run */
96
97 static void litest_init_udev_rules(struct list *created_files_list);
98 static void litest_remove_udev_rules(struct list *created_files_list);
99
100 enum quirks_setup_mode {
101 QUIRKS_SETUP_USE_SRCDIR,
102 QUIRKS_SETUP_ONLY_DEVICE,
103 QUIRKS_SETUP_FULL,
104 };
105 static void litest_setup_quirks(struct list *created_files_list,
106 enum quirks_setup_mode mode);
107
108 /* defined for the litest selftest */
109 #ifndef LITEST_DISABLE_BACKTRACE_LOGGING
110 #define litest_log(...) fprintf(stderr, __VA_ARGS__)
111 #define litest_vlog(format_, args_) vfprintf(stderr, format_, args_)
112 #else
113 #define litest_log(...) { /* __VA_ARGS__ */ }
114 #define litest_vlog(...) { /* __VA_ARGS__ */ }
115 #endif
116
117 static void
litest_backtrace(void)118 litest_backtrace(void)
119 {
120 #if HAVE_GSTACK
121 pid_t parent, child;
122 int pipefd[2];
123
124 if (RUNNING_ON_VALGRIND) {
125 litest_log(" Using valgrind, omitting backtrace\n");
126 return;
127 }
128
129 if (pipe(pipefd) == -1)
130 return;
131
132 parent = getpid();
133 child = fork();
134
135 if (child == 0) {
136 char pid[8];
137
138 close(pipefd[0]);
139 dup2(pipefd[1], STDOUT_FILENO);
140
141 sprintf(pid, "%d", parent);
142
143 execlp("gstack", "gstack", pid, NULL);
144 exit(errno);
145 }
146
147 /* parent */
148 char buf[1024];
149 int status, nread;
150
151 close(pipefd[1]);
152 waitpid(child, &status, 0);
153
154 status = WEXITSTATUS(status);
155 if (status != 0) {
156 litest_log("ERROR: gstack failed, no backtrace available: %s\n",
157 strerror(status));
158 } else {
159 litest_log("\nBacktrace:\n");
160 while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) {
161 buf[nread] = '\0';
162 litest_log("%s", buf);
163 }
164 litest_log("\n");
165 }
166 close(pipefd[0]);
167 #endif
168 }
169
170 LIBINPUT_ATTRIBUTE_PRINTF(5, 6)
171 __attribute__((noreturn))
172 void
litest_fail_condition(const char *file, int line, const char *func, const char *condition, const char *message, ...)173 litest_fail_condition(const char *file,
174 int line,
175 const char *func,
176 const char *condition,
177 const char *message,
178 ...)
179 {
180 litest_log("FAILED: %s\n", condition);
181
182 if (message) {
183 va_list args;
184 va_start(args, message);
185 litest_vlog(message, args);
186 va_end(args);
187 }
188
189 litest_log("in %s() (%s:%d)\n", func, file, line);
190 litest_backtrace();
191 abort();
192 }
193
194 __attribute__((noreturn))
195 void
litest_fail_comparison_int(const char *file, int line, const char *func, const char *operator, int a, int b, const char *astr, const char *bstr)196 litest_fail_comparison_int(const char *file,
197 int line,
198 const char *func,
199 const char *operator,
200 int a,
201 int b,
202 const char *astr,
203 const char *bstr)
204 {
205 litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
206 litest_log("Resolved to: %d %s %d\n", a, operator, b);
207 litest_log("in %s() (%s:%d)\n", func, file, line);
208 litest_backtrace();
209 abort();
210 }
211
212 __attribute__((noreturn))
213 void
litest_fail_comparison_double(const char *file, int line, const char *func, const char *operator, double a, double b, const char *astr, const char *bstr)214 litest_fail_comparison_double(const char *file,
215 int line,
216 const char *func,
217 const char *operator,
218 double a,
219 double b,
220 const char *astr,
221 const char *bstr)
222 {
223 litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr);
224 litest_log("Resolved to: %.3f %s %.3f\n", a, operator, b);
225 litest_log("in %s() (%s:%d)\n", func, file, line);
226 litest_backtrace();
227 abort();
228 }
229
230 __attribute__((noreturn))
231 void
litest_fail_comparison_ptr(const char *file, int line, const char *func, const char *comparison)232 litest_fail_comparison_ptr(const char *file,
233 int line,
234 const char *func,
235 const char *comparison)
236 {
237 litest_log("FAILED COMPARISON: %s\n", comparison);
238 litest_log("in %s() (%s:%d)\n", func, file, line);
239 litest_backtrace();
240 abort();
241 }
242
243 struct test {
244 struct list node;
245 char *name;
246 char *devname;
247 const void *func;
248 void *setup;
249 void *teardown;
250
251 struct range range;
252 bool deviceless;
253 };
254
255 struct suite {
256 struct list node;
257 struct list tests;
258 char *name;
259 };
260
261 static struct litest_device *current_device;
262
litest_current_device(void)263 struct litest_device *litest_current_device(void)
264 {
265 return current_device;
266 }
267
268 static void
grab_device(struct litest_device *device, bool mode)269 grab_device(struct litest_device *device, bool mode)
270 {
271 struct libinput *li = libinput_device_get_context(device->libinput_device);
272 struct litest_context *ctx = libinput_get_user_data(li);
273 struct udev_device *udev_device;
274 const char *devnode;
275 struct path *p;
276
277 udev_device = libinput_device_get_udev_device(device->libinput_device);
278 litest_assert_ptr_notnull(udev_device);
279
280 devnode = udev_device_get_devnode(udev_device);
281
282 /* Note: in some tests we create multiple devices for the same path.
283 * This will only grab the first device in the list but we're using
284 * list_insert() so the first device is the latest that was
285 * initialized, so we should be good.
286 */
287 list_for_each(p, &ctx->paths, link) {
288 if (streq(p->path, devnode)) {
289 int rc = ioctl(p->fd, EVIOCGRAB, (void*)mode ? 1 : 0);
290 ck_assert_int_gt(rc, -1);
291 udev_device_unref(udev_device);
292 return;
293 }
294 }
295 litest_abort_msg("Failed to find device %s to %sgrab\n",
296 devnode, mode ? "" : "un");
297 }
298
299 void
litest_grab_device(struct litest_device *device)300 litest_grab_device(struct litest_device *device)
301 {
302 grab_device(device, true);
303 }
304
305 void
litest_ungrab_device(struct litest_device *device)306 litest_ungrab_device(struct litest_device *device)
307 {
308 grab_device(device, false);
309 }
310
litest_set_current_device(struct litest_device *device)311 void litest_set_current_device(struct litest_device *device)
312 {
313 current_device = device;
314 }
315
litest_generic_device_teardown(void)316 void litest_generic_device_teardown(void)
317 {
318 litest_delete_device(current_device);
319 current_device = NULL;
320 }
321
322 static struct list devices;
323
324 static struct list all_tests;
325
326 static inline void
litest_system(const char *command)327 litest_system(const char *command)
328 {
329 int ret;
330
331 ret = system(command);
332
333 if (ret == -1) {
334 litest_abort_msg("Failed to execute: %s", command);
335 } else if (WIFEXITED(ret)) {
336 if (WEXITSTATUS(ret))
337 litest_abort_msg("'%s' failed with %d",
338 command,
339 WEXITSTATUS(ret));
340 } else if (WIFSIGNALED(ret)) {
341 litest_abort_msg("'%s' terminated with signal %d",
342 command,
343 WTERMSIG(ret));
344 }
345 }
346
347 static void
litest_reload_udev_rules(void)348 litest_reload_udev_rules(void)
349 {
350 litest_system("udevadm control --reload-rules");
351 }
352
353 static void
litest_add_tcase_for_device(struct suite *suite, const char *funcname, const void *func, const struct litest_test_device *dev, const struct range *range)354 litest_add_tcase_for_device(struct suite *suite,
355 const char *funcname,
356 const void *func,
357 const struct litest_test_device *dev,
358 const struct range *range)
359 {
360 struct test *t;
361
362 t = zalloc(sizeof(*t));
363 t->name = safe_strdup(funcname);
364 t->devname = safe_strdup(dev->shortname);
365 t->func = func;
366 t->setup = dev->setup;
367 t->teardown = dev->teardown ?
368 dev->teardown : litest_generic_device_teardown;
369 if (range)
370 t->range = *range;
371
372 list_insert(&suite->tests, &t->node);
373 }
374
375 static void
litest_add_tcase_no_device(struct suite *suite, const void *func, const char *funcname, const struct range *range)376 litest_add_tcase_no_device(struct suite *suite,
377 const void *func,
378 const char *funcname,
379 const struct range *range)
380 {
381 struct test *t;
382 const char *test_name = funcname;
383
384 if (filter_device &&
385 strstr(test_name, filter_device) == NULL &&
386 fnmatch(filter_device, test_name, 0) != 0)
387 return;
388
389 t = zalloc(sizeof(*t));
390 t->name = safe_strdup(test_name);
391 t->devname = safe_strdup("no device");
392 t->func = func;
393 if (range)
394 t->range = *range;
395 t->setup = NULL;
396 t->teardown = NULL;
397
398 list_insert(&suite->tests, &t->node);
399 }
400
401 static void
litest_add_tcase_deviceless(struct suite *suite, const void *func, const char *funcname, const struct range *range)402 litest_add_tcase_deviceless(struct suite *suite,
403 const void *func,
404 const char *funcname,
405 const struct range *range)
406 {
407 struct test *t;
408 const char *test_name = funcname;
409
410 if (filter_device &&
411 strstr(test_name, filter_device) == NULL &&
412 fnmatch(filter_device, test_name, 0) != 0)
413 return;
414
415 t = zalloc(sizeof(*t));
416 t->deviceless = true;
417 t->name = safe_strdup(test_name);
418 t->devname = safe_strdup("deviceless");
419 t->func = func;
420 if (range)
421 t->range = *range;
422 t->setup = NULL;
423 t->teardown = NULL;
424
425 list_insert(&suite->tests, &t->node);
426 }
427
428 static struct suite *
get_suite(const char *name)429 get_suite(const char *name)
430 {
431 struct suite *s;
432
433 list_for_each(s, &all_tests, node) {
434 if (streq(s->name, name))
435 return s;
436 }
437
438 s = zalloc(sizeof(*s));
439 s->name = safe_strdup(name);
440
441 list_init(&s->tests);
442 list_insert(&all_tests, &s->node);
443
444 return s;
445 }
446
447 static void
create_suite_name(const char *filename, char suitename[64])448 create_suite_name(const char *filename, char suitename[64])
449 {
450 char *trunk = trunkname(filename);
451 char *p = trunk;
452
453 /* strip the test- prefix */
454 if (strstartswith(trunk, "test-"))
455 p += 5;
456
457 snprintf(suitename, 64, "%s", p);
458 free(trunk);
459 }
460
461 static void
litest_add_tcase(const char *filename, const char *funcname, const void *func, int64_t required, int64_t excluded, const struct range *range)462 litest_add_tcase(const char *filename,
463 const char *funcname,
464 const void *func,
465 int64_t required,
466 int64_t excluded,
467 const struct range *range)
468 {
469 char suite_name[65];
470 struct suite *suite;
471 bool added = false;
472
473 litest_assert(required >= LITEST_DEVICELESS);
474 litest_assert(excluded >= LITEST_DEVICELESS);
475
476 if (filter_test &&
477 strstr(funcname, filter_test) == NULL &&
478 fnmatch(filter_test, funcname, 0) != 0)
479 return;
480
481 create_suite_name(filename, suite_name);
482
483 if (filter_group && fnmatch(filter_group, suite_name, 0) != 0)
484 return;
485
486 suite = get_suite(suite_name);
487
488 if (required == LITEST_DEVICELESS &&
489 excluded == LITEST_DEVICELESS) {
490 litest_add_tcase_deviceless(suite, func, funcname, range);
491 added = true;
492 } else if (required == LITEST_DISABLE_DEVICE &&
493 excluded == LITEST_DISABLE_DEVICE) {
494 litest_add_tcase_no_device(suite, func, funcname, range);
495 added = true;
496 } else if (required != LITEST_ANY || excluded != LITEST_ANY) {
497 struct litest_test_device *dev;
498
499 list_for_each(dev, &devices, node) {
500 if (dev->features & LITEST_IGNORED)
501 continue;
502
503 if (filter_device &&
504 strstr(dev->shortname, filter_device) == NULL &&
505 fnmatch(filter_device, dev->shortname, 0) != 0)
506 continue;
507 if ((dev->features & required) != required ||
508 (dev->features & excluded) != 0)
509 continue;
510
511 litest_add_tcase_for_device(suite,
512 funcname,
513 func,
514 dev,
515 range);
516 added = true;
517 }
518 } else {
519 struct litest_test_device *dev;
520
521 list_for_each(dev, &devices, node) {
522 if (dev->features & LITEST_IGNORED)
523 continue;
524
525 if (filter_device &&
526 strstr(dev->shortname, filter_device) == NULL &&
527 fnmatch(filter_device, dev->shortname, 0) != 0)
528 continue;
529
530 litest_add_tcase_for_device(suite,
531 funcname,
532 func,
533 dev,
534 range);
535 added = true;
536 }
537 }
538
539 if (!added &&
540 filter_test == NULL &&
541 filter_device == NULL &&
542 filter_group == NULL) {
543 fprintf(stderr, "Test '%s' does not match any devices. Aborting.\n", funcname);
544 abort();
545 }
546 }
547
548 void
_litest_add_no_device(const char *name, const char *funcname, const void *func)549 _litest_add_no_device(const char *name, const char *funcname, const void *func)
550 {
551 _litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
552 }
553
554 void
_litest_add_ranged_no_device(const char *name, const char *funcname, const void *func, const struct range *range)555 _litest_add_ranged_no_device(const char *name,
556 const char *funcname,
557 const void *func,
558 const struct range *range)
559 {
560 _litest_add_ranged(name,
561 funcname,
562 func,
563 LITEST_DISABLE_DEVICE,
564 LITEST_DISABLE_DEVICE,
565 range);
566 }
567
568 void
_litest_add_deviceless(const char *name, const char *funcname, const void *func)569 _litest_add_deviceless(const char *name,
570 const char *funcname,
571 const void *func)
572 {
573 _litest_add_ranged(name,
574 funcname,
575 func,
576 LITEST_DEVICELESS,
577 LITEST_DEVICELESS,
578 NULL);
579 }
580
581 void
_litest_add(const char *name, const char *funcname, const void *func, int64_t required, int64_t excluded)582 _litest_add(const char *name,
583 const char *funcname,
584 const void *func,
585 int64_t required,
586 int64_t excluded)
587 {
588 _litest_add_ranged(name,
589 funcname,
590 func,
591 required,
592 excluded,
593 NULL);
594 }
595
596 void
_litest_add_ranged(const char *name, const char *funcname, const void *func, int64_t required, int64_t excluded, const struct range *range)597 _litest_add_ranged(const char *name,
598 const char *funcname,
599 const void *func,
600 int64_t required,
601 int64_t excluded,
602 const struct range *range)
603 {
604 litest_add_tcase(name, funcname, func, required, excluded, range);
605 }
606
607 void
_litest_add_for_device(const char *name, const char *funcname, const void *func, enum litest_device_type type)608 _litest_add_for_device(const char *name,
609 const char *funcname,
610 const void *func,
611 enum litest_device_type type)
612 {
613 _litest_add_ranged_for_device(name, funcname, func, type, NULL);
614 }
615
616 void
_litest_add_ranged_for_device(const char *filename, const char *funcname, const void *func, enum litest_device_type type, const struct range *range)617 _litest_add_ranged_for_device(const char *filename,
618 const char *funcname,
619 const void *func,
620 enum litest_device_type type,
621 const struct range *range)
622 {
623 struct suite *s;
624 struct litest_test_device *dev;
625 bool device_filtered = false;
626 char suite_name[64];
627
628 litest_assert(type < LITEST_NO_DEVICE);
629
630 if (filter_test &&
631 strstr(funcname, filter_test) == NULL &&
632 fnmatch(filter_test, funcname, 0) != 0)
633 return;
634
635 create_suite_name(filename, suite_name);
636 if (filter_group && fnmatch(filter_group, suite_name, 0) != 0)
637 return;
638
639 s = get_suite(suite_name);
640 list_for_each(dev, &devices, node) {
641 if (filter_device &&
642 strstr(dev->shortname, filter_device) == NULL &&
643 fnmatch(filter_device, dev->shortname, 0) != 0) {
644 device_filtered = true;
645 continue;
646 }
647
648 if (dev->type == type) {
649 litest_add_tcase_for_device(s,
650 funcname,
651 func,
652 dev,
653 range);
654 return;
655 }
656 }
657
658 /* only abort if no filter was set, that's a bug */
659 if (!device_filtered)
660 litest_abort_msg("Invalid test device type\n");
661 }
662
663 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
664 static void
litest_log_handler(struct libinput *libinput, enum libinput_log_priority pri, const char *format, va_list args)665 litest_log_handler(struct libinput *libinput,
666 enum libinput_log_priority pri,
667 const char *format,
668 va_list args)
669 {
670 static int is_tty = -1;
671 const char *priority = NULL;
672 const char *color;
673
674 if (is_tty == -1)
675 is_tty = isatty(STDERR_FILENO);
676
677 switch(pri) {
678 case LIBINPUT_LOG_PRIORITY_INFO:
679 priority = "info ";
680 color = ANSI_HIGHLIGHT;
681 break;
682 case LIBINPUT_LOG_PRIORITY_ERROR:
683 priority = "error";
684 color = ANSI_BRIGHT_RED;
685 break;
686 case LIBINPUT_LOG_PRIORITY_DEBUG:
687 priority = "debug";
688 color = ANSI_NORMAL;
689 break;
690 default:
691 abort();
692 }
693
694 if (!is_tty)
695 color = "";
696 else if (strstr(format, "tap:"))
697 color = ANSI_BLUE;
698 else if (strstr(format, "thumb state:"))
699 color = ANSI_YELLOW;
700 else if (strstr(format, "button state:"))
701 color = ANSI_MAGENTA;
702 else if (strstr(format, "touch-size:") ||
703 strstr(format, "pressure:"))
704 color = ANSI_GREEN;
705 else if (strstr(format, "palm:") ||
706 strstr(format, "thumb:"))
707 color = ANSI_CYAN;
708 else if (strstr(format, "edge-scroll:"))
709 color = ANSI_BRIGHT_GREEN;
710
711 fprintf(stderr, "%slitest %s ", color, priority);
712 vfprintf(stderr, format, args);
713 if (is_tty)
714 fprintf(stderr, ANSI_NORMAL);
715
716 if (strstr(format, "client bug: ") ||
717 strstr(format, "libinput bug: ")) {
718 /* valgrind is too slow and some of our offsets are too
719 * short, don't abort if during a valgrind run we get a
720 * negative offset */
721 if ((RUNNING_ON_VALGRIND && in_debugger) ||
722 !strstr(format, "scheduled expiry is in the past")) {
723 /* noop */
724 } else if (!strstr(format, "event processing lagging behind")) {
725 /* noop */
726 } else {
727 litest_abort_msg("libinput bug triggered, aborting.\n");
728 }
729 }
730
731 if (strstr(format, "Touch jump detected and discarded")) {
732 litest_abort_msg("libinput touch jump triggered, aborting.\n");
733 }
734 }
735
736 static void
litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f)737 litest_init_device_udev_rules(struct litest_test_device *dev, FILE *f)
738 {
739 const struct key_value_str *kv;
740 static int count;
741 bool need_keyboard_builtin = false;
742
743 if (dev->udev_properties[0].key == NULL)
744 return;
745
746 count++;
747
748 fprintf(f, "# %s\n", dev->shortname);
749 fprintf(f, "ACTION==\"remove\", GOTO=\"rule%d_end\"\n", count);
750 fprintf(f, "KERNEL!=\"event*\", GOTO=\"rule%d_end\"\n", count);
751
752 fprintf(f, "ATTRS{name}==\"litest %s*\"", dev->name);
753
754 kv = dev->udev_properties;
755 while (kv->key) {
756 fprintf(f, ", \\\n\tENV{%s}=\"%s\"", kv->key, kv->value);
757 if (strneq(kv->key, "EVDEV_ABS_", 10))
758 need_keyboard_builtin = true;
759 kv++;
760 }
761 fprintf(f, "\n");
762
763 /* Special case: the udev keyboard builtin is only run for hwdb
764 * matches but we don't set any up in litest. So instead scan the
765 * device's udev properties for any EVDEV_ABS properties and where
766 * they exist, force a (re-)run of the keyboard builtin to set up
767 * the evdev device correctly.
768 * This needs to be done as separate rule apparently, otherwise the
769 * ENV variables aren't set yet by the time the builtin runs.
770 */
771 if (need_keyboard_builtin) {
772 fprintf(f, ""
773 "ATTRS{name}==\"litest %s*\","
774 " IMPORT{builtin}=\"keyboard\"\n",
775 dev->name);
776 }
777
778 fprintf(f, "LABEL=\"rule%d_end\"\n\n", count);;
779 }
780
781 static void
litest_init_all_device_udev_rules(struct list *created_files)782 litest_init_all_device_udev_rules(struct list *created_files)
783 {
784 struct created_file *file = zalloc(sizeof(*file));
785 struct litest_test_device *dev;
786 char *path = NULL;
787 FILE *f;
788 int rc;
789 int fd;
790
791 rc = xasprintf(&path,
792 "%s/99-litest-XXXXXX.rules",
793 UDEV_RULES_D);
794 litest_assert_int_gt(rc, 0);
795
796 fd = mkstemps(path, 6);
797 litest_assert_int_ne(fd, -1);
798 f = fdopen(fd, "w");
799 litest_assert_notnull(f);
800
801 list_for_each(dev, &devices, node)
802 litest_init_device_udev_rules(dev, f);
803
804 fclose(f);
805
806 file->path = path;
807 list_insert(created_files, &file->link);
808 }
809
810 static int
open_restricted(const char *path, int flags, void *userdata)811 open_restricted(const char *path, int flags, void *userdata)
812 {
813 const char prefix[] = "/dev/input/event";
814 struct litest_context *ctx = userdata;
815 struct path *p;
816 int fd;
817
818 litest_assert_ptr_notnull(ctx);
819
820 fd = open(path, flags);
821 if (fd < 0)
822 return -errno;
823
824 if (strneq(path, prefix, strlen(prefix))) {
825 p = zalloc(sizeof *p);
826 p->path = safe_strdup(path);
827 p->fd = fd;
828 /* We specifically insert here so that the most-recently
829 * opened path is the first one in the list. This helps when
830 * we have multiple test devices with the same device path,
831 * the fd of the most recent device is the first one to get
832 * grabbed
833 */
834 list_insert(&ctx->paths, &p->link);
835 }
836
837 return fd;
838 }
839
840 static void
close_restricted(int fd, void *userdata)841 close_restricted(int fd, void *userdata)
842 {
843 struct litest_context *ctx = userdata;
844 struct path *p;
845
846 list_for_each_safe(p, &ctx->paths, link) {
847 if (p->fd != fd)
848 continue;
849 list_remove(&p->link);
850 free(p->path);
851 free(p);
852 }
853
854 close(fd);
855 }
856
857 static struct libinput_interface interface = {
858 .open_restricted = open_restricted,
859 .close_restricted = close_restricted,
860 };
861
862 static void
litest_signal(int sig)863 litest_signal(int sig)
864 {
865 struct created_file *f;
866
867 list_for_each_safe(f, &created_files_list, link) {
868 list_remove(&f->link);
869 unlink(f->path);
870 rmdir(f->path);
871 /* in the sighandler, we can't free */
872 }
873
874 if (fork() == 0) {
875 /* child, we can run system() */
876 litest_reload_udev_rules();
877 exit(0);
878 }
879
880 exit(1);
881 }
882
883 static inline void
litest_setup_sighandler(int sig)884 litest_setup_sighandler(int sig)
885 {
886 struct sigaction act, oact;
887 int rc;
888
889 sigemptyset(&act.sa_mask);
890 sigaddset(&act.sa_mask, sig);
891 act.sa_flags = 0;
892 act.sa_handler = litest_signal;
893 rc = sigaction(sig, &act, &oact);
894 litest_assert_int_ne(rc, -1);
895 }
896
897 static void
litest_free_test_list(struct list *tests)898 litest_free_test_list(struct list *tests)
899 {
900 struct suite *s;
901
902 list_for_each_safe(s, tests, node) {
903 struct test *t;
904
905 list_for_each_safe(t, &s->tests, node) {
906 free(t->name);
907 free(t->devname);
908 list_remove(&t->node);
909 free(t);
910 }
911
912 list_remove(&s->node);
913 free(s->name);
914 free(s);
915 }
916 }
917
918 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
919 static inline void
quirk_log_handler(struct libinput *unused, enum libinput_log_priority priority, const char *format, va_list args)920 quirk_log_handler(struct libinput *unused,
921 enum libinput_log_priority priority,
922 const char *format,
923 va_list args)
924 {
925 if (priority < LIBINPUT_LOG_PRIORITY_ERROR)
926 return;
927
928 vfprintf(stderr, format, args);
929 }
930
931 static void
litest_export_xml(SRunner *sr, const char *xml_prefix)932 litest_export_xml(SRunner *sr, const char *xml_prefix)
933 {
934 TestResult **results;
935 int nresults, nfailed;
936 char *filename;
937 int fd;
938
939 /* This is the minimum-effort implementation here because its only
940 * real purpose is to make test logs look pretty in the gitlab CI.
941 *
942 * Which means:
943 * - there's no filename validation, if you supply a filename that
944 * mkstemps doesn't like, things go boom.
945 * - every fork writes out a separate junit.xml file. gitlab is better
946 * at collecting lots of files than I am at writing code to collect
947 * this across forks to write out only one file.
948 * - most of the content is pretty useless because libcheck only gives
949 * us minimal information. the libcheck XML file has more info like
950 * the duration of each test but it's more complicated to extract
951 * and we don't need it for now.
952 */
953 filename = safe_strdup(xml_prefix);
954 fd = mkstemps(filename, 4);
955
956 results = srunner_results(sr);
957 nresults = srunner_ntests_run(sr);
958 nfailed = srunner_ntests_failed(sr);
959
960 dprintf(fd, "<?xml version=\"1.0\"?>\n");
961 dprintf(fd, "<testsuites id=\"%s\" tests=\"%d\" failures=\"%d\">\n",
962 filename,
963 nresults,
964 nfailed);
965 dprintf(fd, " <testsuite>\n");
966 for (int i = 0; i < nresults; i++) {
967 TestResult *r = results[i];
968
969 dprintf(fd, " <testcase id=\"%s\" name=\"%s\" %s>\n",
970 tr_tcname(r),
971 tr_tcname(r),
972 tr_rtype(r) == CK_PASS ? "/" : "");
973 if (tr_rtype(r) != CK_PASS) {
974 dprintf(fd, " <failure message=\"%s:%d\">\n",
975 tr_lfile(r),
976 tr_lno(r));
977 dprintf(fd, " %s:%d\n", tr_lfile(r), tr_lno(r));
978 dprintf(fd, " %s\n", tr_tcname(r));
979 dprintf(fd, "\n");
980 dprintf(fd, " %s\n", tr_msg(r));
981 dprintf(fd, " </failure>\n");
982 dprintf(fd, " </testcase>\n");
983 }
984 }
985 dprintf(fd, " </testsuite>\n");
986 dprintf(fd, "</testsuites>\n");
987
988 free(results);
989 close(fd);
990 free(filename);
991 }
992
993 static int
litest_run_suite(struct list *tests, int which, int max, int error_fd)994 litest_run_suite(struct list *tests, int which, int max, int error_fd)
995 {
996 int failed = 0;
997 SRunner *sr = NULL;
998 struct suite *s;
999 struct test *t;
1000 int count = -1;
1001 struct name {
1002 struct list node;
1003 char *name;
1004 };
1005 struct name *n;
1006 struct list testnames;
1007 const char *data_path;
1008
1009 data_path = getenv("LIBINPUT_QUIRKS_DIR");
1010 if (!data_path)
1011 data_path = LIBINPUT_QUIRKS_DIR;
1012
1013 quirks_context = quirks_init_subsystem(data_path,
1014 NULL,
1015 quirk_log_handler,
1016 NULL,
1017 QLOG_LIBINPUT_LOGGING);
1018
1019 /* Check just takes the suite/test name pointers but doesn't strdup
1020 * them - we have to keep them around */
1021 list_init(&testnames);
1022
1023 /* For each test, create one test suite with one test case, then
1024 add it to the test runner. The only benefit suites give us in
1025 check is that we can filter them, but our test runner has a
1026 --filter-group anyway. */
1027 list_for_each(s, tests, node) {
1028 list_for_each(t, &s->tests, node) {
1029 Suite *suite;
1030 TCase *tc;
1031 char *sname, *tname;
1032
1033 /* We run deviceless tests as part of the normal
1034 * test suite runner, just in case. Filtering
1035 * all the other ones out just for the case where
1036 * we can't run the full runner.
1037 */
1038 if (run_deviceless && !t->deviceless)
1039 continue;
1040
1041 count = (count + 1) % max;
1042 if (max != 1 && (count % max) != which)
1043 continue;
1044
1045 xasprintf(&sname,
1046 "%s:%s:%s",
1047 s->name,
1048 t->name,
1049 t->devname);
1050 litest_assert_ptr_notnull(sname);
1051 n = zalloc(sizeof(*n));
1052 n->name = sname;
1053 list_insert(&testnames, &n->node);
1054
1055 xasprintf(&tname,
1056 "%s:%s",
1057 t->name,
1058 t->devname);
1059 litest_assert_ptr_notnull(tname);
1060 n = zalloc(sizeof(*n));
1061 n->name = tname;
1062 list_insert(&testnames, &n->node);
1063
1064 tc = tcase_create(tname);
1065 tcase_add_checked_fixture(tc,
1066 t->setup,
1067 t->teardown);
1068 if (t->range.upper != t->range.lower)
1069 tcase_add_loop_test(tc,
1070 t->func,
1071 t->range.lower,
1072 t->range.upper);
1073 else
1074 tcase_add_test(tc, t->func);
1075
1076 suite = suite_create(sname);
1077 suite_add_tcase(suite, tc);
1078
1079 if (!sr)
1080 sr = srunner_create(suite);
1081 else
1082 srunner_add_suite(sr, suite);
1083 }
1084 }
1085
1086 if (!sr)
1087 goto out;
1088
1089 srunner_run_all(sr, CK_ENV);
1090 if (xml_prefix)
1091 litest_export_xml(sr, xml_prefix);
1092
1093
1094 failed = srunner_ntests_failed(sr);
1095 if (failed) {
1096 TestResult **trs;
1097
1098 trs = srunner_failures(sr);
1099 for (int i = 0; i < failed; i++) {
1100 char tname[256];
1101 char *c = tname;
1102
1103 /* tr_tcname is in the form "suite:testcase", let's
1104 * convert this to "suite(testcase)" to make
1105 * double-click selection in the terminal a bit
1106 * easier. */
1107 snprintf(tname, sizeof(tname), "%s)", tr_tcname(trs[i]));
1108 if ((c = index(c, ':')))
1109 *c = '(';
1110
1111 dprintf(error_fd,
1112 ":: Failure: %s:%d: %s\n",
1113 tr_lfile(trs[i]),
1114 tr_lno(trs[i]),
1115 tname);
1116 }
1117 free(trs);
1118 }
1119 srunner_free(sr);
1120 out:
1121 list_for_each_safe(n, &testnames, node) {
1122 free(n->name);
1123 free(n);
1124 }
1125
1126 quirks_context_unref(quirks_context);
1127
1128 return failed;
1129 }
1130
1131 static int
litest_fork_subtests(struct list *tests, int max_forks)1132 litest_fork_subtests(struct list *tests, int max_forks)
1133 {
1134 int failed = 0;
1135 int status;
1136 pid_t pid;
1137 int f;
1138 int pipes[max_forks];
1139
1140 for (f = 0; f < max_forks; f++) {
1141 int rc;
1142 int pipefd[2];
1143
1144 rc = pipe2(pipefd, O_NONBLOCK);
1145 assert(rc != -1);
1146
1147 pid = fork();
1148 if (pid == 0) {
1149 close(pipefd[0]);
1150 failed = litest_run_suite(tests,
1151 f,
1152 max_forks,
1153 pipefd[1]);
1154
1155 litest_free_test_list(&all_tests);
1156 exit(failed);
1157 /* child always exits here */
1158 } else {
1159 pipes[f] = pipefd[0];
1160 close(pipefd[1]);
1161 }
1162 }
1163
1164 /* parent process only */
1165 while (wait(&status) != -1 && errno != ECHILD) {
1166 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
1167 failed = 1;
1168 }
1169
1170 for (f = 0; f < max_forks; f++) {
1171 char buf[1024] = {0};
1172 int rc;
1173
1174 while ((rc = read(pipes[f], buf, sizeof(buf) - 1)) > 0) {
1175 buf[rc] = '\0';
1176 fprintf(stderr, "%s", buf);
1177 }
1178
1179 close(pipes[f]);
1180 }
1181
1182 return failed;
1183 }
1184
1185 static inline int
inhibit(void)1186 inhibit(void)
1187 {
1188 int lock_fd = -1;
1189 #if HAVE_LIBSYSTEMD
1190 sd_bus_error error = SD_BUS_ERROR_NULL;
1191 sd_bus_message *m = NULL;
1192 sd_bus *bus = NULL;
1193 int rc;
1194
1195 if (run_deviceless)
1196 return -1;
1197
1198 rc = sd_bus_open_system(&bus);
1199 if (rc != 0) {
1200 fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
1201 goto out;
1202 }
1203
1204 rc = sd_bus_call_method(bus,
1205 "org.freedesktop.login1",
1206 "/org/freedesktop/login1",
1207 "org.freedesktop.login1.Manager",
1208 "Inhibit",
1209 &error,
1210 &m,
1211 "ssss",
1212 "sleep:shutdown:handle-lid-switch:handle-power-key:handle-suspend-key:handle-hibernate-key",
1213 "libinput test-suite runner",
1214 "testing in progress",
1215 "block");
1216 if (rc < 0) {
1217 fprintf(stderr, "Warning: inhibit failed: %s\n", error.message);
1218 goto out;
1219 }
1220
1221 rc = sd_bus_message_read(m, "h", &lock_fd);
1222 if (rc < 0) {
1223 fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc));
1224 goto out;
1225 }
1226
1227 lock_fd = dup(lock_fd);
1228 out:
1229 sd_bus_error_free(&error);
1230 sd_bus_message_unref(m);
1231 sd_bus_close(bus);
1232 sd_bus_unref(bus);
1233 #endif
1234 return lock_fd;
1235 }
1236
1237 static inline int
litest_run(int argc, char **argv)1238 litest_run(int argc, char **argv)
1239 {
1240 int failed = 0;
1241 int inhibit_lock_fd;
1242
1243 list_init(&created_files_list);
1244
1245 if (list_empty(&all_tests)) {
1246 fprintf(stderr,
1247 "Error: filters are too strict, no tests to run.\n");
1248 return 1;
1249 }
1250
1251 if (getenv("LITEST_VERBOSE"))
1252 verbose = true;
1253
1254 if (run_deviceless) {
1255 litest_setup_quirks(&created_files_list,
1256 QUIRKS_SETUP_USE_SRCDIR);
1257 } else {
1258 enum quirks_setup_mode mode;
1259 litest_init_udev_rules(&created_files_list);
1260
1261
1262 mode = use_system_rules_quirks ?
1263 QUIRKS_SETUP_ONLY_DEVICE :
1264 QUIRKS_SETUP_FULL;
1265 litest_setup_quirks(&created_files_list, mode);
1266 }
1267
1268 litest_setup_sighandler(SIGINT);
1269
1270 inhibit_lock_fd = inhibit();
1271
1272 if (jobs == 1)
1273 failed = litest_run_suite(&all_tests, 1, 1, STDERR_FILENO);
1274 else
1275 failed = litest_fork_subtests(&all_tests, jobs);
1276
1277 close(inhibit_lock_fd);
1278
1279 litest_free_test_list(&all_tests);
1280
1281 litest_remove_udev_rules(&created_files_list);
1282
1283 return failed;
1284 }
1285
1286 static struct input_absinfo *
merge_absinfo(const struct input_absinfo *orig, const struct input_absinfo *override)1287 merge_absinfo(const struct input_absinfo *orig,
1288 const struct input_absinfo *override)
1289 {
1290 struct input_absinfo *abs;
1291 unsigned int nelem, i;
1292 size_t sz = ABS_MAX + 1;
1293
1294 if (!orig)
1295 return NULL;
1296
1297 abs = zalloc(sz * sizeof(*abs));
1298 litest_assert_ptr_notnull(abs);
1299
1300 nelem = 0;
1301 while (orig[nelem].value != -1) {
1302 abs[nelem] = orig[nelem];
1303 nelem++;
1304 litest_assert_int_lt(nelem, sz);
1305 }
1306
1307 /* just append, if the same axis is present twice, libevdev will
1308 only use the last value anyway */
1309 i = 0;
1310 while (override && override[i].value != -1) {
1311 abs[nelem++] = override[i++];
1312 litest_assert_int_lt(nelem, sz);
1313 }
1314
1315 litest_assert_int_lt(nelem, sz);
1316 abs[nelem].value = -1;
1317
1318 return abs;
1319 }
1320
1321 static int*
merge_events(const int *orig, const int *override)1322 merge_events(const int *orig, const int *override)
1323 {
1324 int *events;
1325 unsigned int nelem, i;
1326 size_t sz = KEY_MAX * 3;
1327
1328 if (!orig)
1329 return NULL;
1330
1331 events = zalloc(sz * sizeof(int));
1332 litest_assert_ptr_notnull(events);
1333
1334 nelem = 0;
1335 while (orig[nelem] != -1) {
1336 events[nelem] = orig[nelem];
1337 nelem++;
1338 litest_assert_int_lt(nelem, sz);
1339 }
1340
1341 /* just append, if the same axis is present twice, libevdev will
1342 * ignore the double definition anyway */
1343 i = 0;
1344 while (override && override[i] != -1) {
1345 events[nelem++] = override[i++];
1346 litest_assert_int_le(nelem, sz);
1347 }
1348
1349 litest_assert_int_lt(nelem, sz);
1350 events[nelem] = -1;
1351
1352 return events;
1353 }
1354
1355 static inline struct created_file *
litest_copy_file(const char *dest, const char *src, const char *header, bool is_file)1356 litest_copy_file(const char *dest, const char *src, const char *header, bool is_file)
1357 {
1358 int in, out, length;
1359 struct created_file *file;
1360
1361 file = zalloc(sizeof(*file));
1362 file->path = safe_strdup(dest);
1363
1364 if (strstr(dest, "XXXXXX")) {
1365 int suffixlen;
1366
1367 suffixlen = file->path +
1368 strlen(file->path) -
1369 rindex(file->path, '.');
1370 out = mkstemps(file->path, suffixlen);
1371 } else {
1372 out = open(file->path, O_CREAT|O_WRONLY, 0644);
1373 }
1374 if (out == -1)
1375 litest_abort_msg("Failed to write to file %s (%s)\n",
1376 file->path,
1377 strerror(errno));
1378 litest_assert_int_ne(chmod(file->path, 0644), -1);
1379
1380 if (header) {
1381 length = strlen(header);
1382 litest_assert_int_eq(write(out, header, length), length);
1383 }
1384
1385 if (is_file) {
1386 in = open(src, O_RDONLY);
1387 if (in == -1)
1388 litest_abort_msg("Failed to open file %s (%s)\n",
1389 src,
1390 strerror(errno));
1391 /* lazy, just check for error and empty file copy */
1392 litest_assert_int_gt(litest_send_file(out, in), 0);
1393 close(in);
1394 } else {
1395 size_t written = write(out, src, strlen(src));
1396 litest_assert_int_eq(written, strlen(src));
1397
1398 }
1399 close(out);
1400
1401 return file;
1402 }
1403
1404 static inline void
litest_install_model_quirks(struct list *created_files_list)1405 litest_install_model_quirks(struct list *created_files_list)
1406 {
1407 const char *warning =
1408 "#################################################################\n"
1409 "# WARNING: REMOVE THIS FILE\n"
1410 "# This is a run-time file for the libinput test suite and\n"
1411 "# should be removed on exit. If the test-suite is not currently \n"
1412 "# running, remove this file\n"
1413 "#################################################################\n\n";
1414 struct created_file *file;
1415 const char *test_device_udev_rule = "KERNELS==\"*input*\", "
1416 "ATTRS{name}==\"litest *\", "
1417 "ENV{LIBINPUT_TEST_DEVICE}=\"1\"";
1418
1419 file = litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE,
1420 test_device_udev_rule,
1421 warning,
1422 false);
1423 list_insert(created_files_list, &file->link);
1424
1425 /* Only install the litest device rule when we're running as system
1426 * test suite, we expect the others to be in place already */
1427 if (use_system_rules_quirks)
1428 return;
1429
1430 file = litest_copy_file(UDEV_DEVICE_GROUPS_FILE,
1431 LIBINPUT_DEVICE_GROUPS_RULES_FILE,
1432 warning,
1433 true);
1434 list_insert(created_files_list, &file->link);
1435
1436 file = litest_copy_file(UDEV_FUZZ_OVERRIDE_RULE_FILE,
1437 LIBINPUT_FUZZ_OVERRIDE_UDEV_RULES_FILE,
1438 warning,
1439 true);
1440 list_insert(created_files_list, &file->link);
1441 }
1442
1443 static char *
litest_init_device_quirk_file(const char *data_dir, struct litest_test_device *dev)1444 litest_init_device_quirk_file(const char *data_dir,
1445 struct litest_test_device *dev)
1446 {
1447 int fd;
1448 FILE *f;
1449 char path[PATH_MAX];
1450 static int count;
1451
1452 if (!dev->quirk_file)
1453 return NULL;
1454
1455 snprintf(path, sizeof(path),
1456 "%s/99-%03d-%s.quirks",
1457 data_dir,
1458 ++count,
1459 dev->shortname);
1460 fd = open(path, O_CREAT|O_WRONLY, 0644);
1461 litest_assert_int_ne(fd, -1);
1462 f = fdopen(fd, "w");
1463 litest_assert_notnull(f);
1464 litest_assert_int_ge(fputs(dev->quirk_file, f), 0);
1465 fclose(f);
1466
1467 return safe_strdup(path);
1468 }
1469
is_quirks_file(const struct dirent *dir)1470 static int is_quirks_file(const struct dirent *dir) {
1471 return strendswith(dir->d_name, ".quirks");
1472 }
1473
1474 /**
1475 * Install the quirks from the quirks/ source directory.
1476 */
1477 static void
litest_install_source_quirks(struct list *created_files_list, const char *dirname)1478 litest_install_source_quirks(struct list *created_files_list,
1479 const char *dirname)
1480 {
1481 struct dirent **namelist;
1482 int ndev;
1483
1484 ndev = scandir(LIBINPUT_QUIRKS_SRCDIR,
1485 &namelist,
1486 is_quirks_file,
1487 versionsort);
1488 litest_assert_int_ge(ndev, 0);
1489
1490 for (int idx = 0; idx < ndev; idx++) {
1491 struct created_file *file;
1492 char *filename;
1493 char dest[PATH_MAX];
1494 char src[PATH_MAX];
1495
1496 filename = namelist[idx]->d_name;
1497 snprintf(src, sizeof(src), "%s/%s",
1498 LIBINPUT_QUIRKS_SRCDIR, filename);
1499 snprintf(dest, sizeof(dest), "%s/%s", dirname, filename);
1500 file = litest_copy_file(dest, src, NULL, true);
1501 list_append(created_files_list, &file->link);
1502 free(namelist[idx]);
1503 }
1504 free(namelist);
1505 }
1506
1507 /**
1508 * Install the quirks from the various litest test devices
1509 */
1510 static void
litest_install_device_quirks(struct list *created_files_list, const char *dirname)1511 litest_install_device_quirks(struct list *created_files_list,
1512 const char *dirname)
1513 {
1514 struct litest_test_device *dev;
1515
1516 list_for_each(dev, &devices, node) {
1517 char *path;
1518
1519 path = litest_init_device_quirk_file(dirname, dev);
1520 if (path) {
1521 struct created_file *file = zalloc(sizeof(*file));
1522 file->path = path;
1523 list_insert(created_files_list, &file->link);
1524 }
1525 }
1526 }
1527
1528 static void
litest_setup_quirks(struct list *created_files_list, enum quirks_setup_mode mode)1529 litest_setup_quirks(struct list *created_files_list,
1530 enum quirks_setup_mode mode)
1531 {
1532 struct created_file *file = NULL;
1533 const char *dirname;
1534 char tmpdir[] = "/run/litest-XXXXXX";
1535
1536 switch (mode) {
1537 case QUIRKS_SETUP_USE_SRCDIR:
1538 dirname = LIBINPUT_QUIRKS_SRCDIR;
1539 break;
1540 case QUIRKS_SETUP_ONLY_DEVICE:
1541 dirname = LIBINPUT_QUIRKS_DIR;
1542 litest_install_device_quirks(created_files_list, dirname);
1543 break;
1544 case QUIRKS_SETUP_FULL:
1545 litest_assert_notnull(mkdtemp(tmpdir));
1546 litest_assert_int_ne(chmod(tmpdir, 0755), -1);
1547 file = zalloc(sizeof *file);
1548 file->path = safe_strdup(tmpdir);
1549 dirname = tmpdir;
1550
1551 litest_install_source_quirks(created_files_list, dirname);
1552 litest_install_device_quirks(created_files_list, dirname);
1553 list_append(created_files_list, &file->link);
1554 break;
1555 }
1556
1557 setenv("LIBINPUT_QUIRKS_DIR", dirname, 1);
1558 }
1559
1560 static inline void
mkdir_p(const char *dir)1561 mkdir_p(const char *dir)
1562 {
1563 char *path, *parent;
1564 int rc;
1565
1566 if (streq(dir, "/"))
1567 return;
1568
1569 path = safe_strdup(dir);
1570 parent = dirname(path);
1571
1572 mkdir_p(parent);
1573 rc = mkdir(dir, 0755);
1574
1575 if (rc == -1 && errno != EEXIST) {
1576 litest_abort_msg("Failed to create directory %s (%s)\n",
1577 dir,
1578 strerror(errno));
1579 }
1580
1581 free(path);
1582 }
1583
1584 static inline void
litest_init_udev_rules(struct list *created_files)1585 litest_init_udev_rules(struct list *created_files)
1586 {
1587 mkdir_p(UDEV_RULES_D);
1588
1589 litest_install_model_quirks(created_files);
1590 litest_init_all_device_udev_rules(created_files);
1591 litest_reload_udev_rules();
1592 }
1593
1594 static inline void
litest_remove_udev_rules(struct list *created_files_list)1595 litest_remove_udev_rules(struct list *created_files_list)
1596 {
1597 struct created_file *f;
1598 bool reload_udev;
1599
1600 reload_udev = !list_empty(created_files_list);
1601
1602 list_for_each_safe(f, created_files_list, link) {
1603 list_remove(&f->link);
1604 unlink(f->path);
1605 rmdir(f->path);
1606 free(f->path);
1607 free(f);
1608 }
1609
1610 if (reload_udev)
1611 litest_reload_udev_rules();
1612 }
1613
1614 /**
1615 * Creates a uinput device but does not add it to a libinput context
1616 */
1617 struct litest_device *
litest_create(enum litest_device_type which, const char *name_override, struct input_id *id_override, const struct input_absinfo *abs_override, const int *events_override)1618 litest_create(enum litest_device_type which,
1619 const char *name_override,
1620 struct input_id *id_override,
1621 const struct input_absinfo *abs_override,
1622 const int *events_override)
1623 {
1624 struct litest_device *d = NULL;
1625 struct litest_test_device *dev;
1626 const char *name;
1627 const struct input_id *id;
1628 struct input_absinfo *abs;
1629 int *events, *e;
1630 const char *path;
1631 int fd, rc;
1632 bool found = false;
1633 bool create_device = true;
1634
1635 list_for_each(dev, &devices, node) {
1636 if (dev->type == which) {
1637 found = true;
1638 break;
1639 }
1640 }
1641
1642 if (!found)
1643 ck_abort_msg("Invalid device type %d\n", which);
1644
1645 d = zalloc(sizeof(*d));
1646 d->which = which;
1647
1648 /* device has custom create method */
1649 if (dev->create) {
1650 create_device = dev->create(d);
1651 if (abs_override || events_override) {
1652 litest_abort_msg("Custom create cannot be overridden");
1653 }
1654 }
1655
1656 abs = merge_absinfo(dev->absinfo, abs_override);
1657 events = merge_events(dev->events, events_override);
1658 name = name_override ? name_override : dev->name;
1659 id = id_override ? id_override : dev->id;
1660
1661 if (create_device) {
1662 d->uinput = litest_create_uinput_device_from_description(name,
1663 id,
1664 abs,
1665 events);
1666 d->interface = dev->interface;
1667
1668 for (e = events; *e != -1; e += 2) {
1669 unsigned int type = *e,
1670 code = *(e + 1);
1671
1672 if (type == INPUT_PROP_MAX &&
1673 code == INPUT_PROP_SEMI_MT) {
1674 d->semi_mt.is_semi_mt = true;
1675 break;
1676 }
1677 }
1678 }
1679
1680 free(abs);
1681 free(events);
1682
1683 path = libevdev_uinput_get_devnode(d->uinput);
1684 litest_assert_ptr_notnull(path);
1685 fd = open(path, O_RDWR|O_NONBLOCK);
1686 litest_assert_int_ne(fd, -1);
1687
1688 rc = libevdev_new_from_fd(fd, &d->evdev);
1689 litest_assert_int_eq(rc, 0);
1690
1691 return d;
1692
1693 }
1694
1695 struct libinput *
litest_create_context(void)1696 litest_create_context(void)
1697 {
1698 struct libinput *libinput;
1699 struct litest_context *ctx;
1700
1701 ctx = zalloc(sizeof *ctx);
1702 list_init(&ctx->paths);
1703
1704 libinput = libinput_path_create_context(&interface, ctx);
1705 litest_assert_notnull(libinput);
1706
1707 libinput_log_set_handler(libinput, litest_log_handler);
1708 if (verbose)
1709 libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1710
1711 return libinput;
1712 }
1713
1714 void
litest_destroy_context(struct libinput *li)1715 litest_destroy_context(struct libinput *li)
1716 {
1717 struct path *p;
1718 struct litest_context *ctx;
1719
1720
1721 ctx = libinput_get_user_data(li);
1722 litest_assert_ptr_notnull(ctx);
1723 libinput_unref(li);
1724
1725 list_for_each_safe(p, &ctx->paths, link) {
1726 litest_abort_msg("Device paths should be removed by now");
1727 }
1728 free(ctx);
1729 }
1730
1731 void
litest_disable_log_handler(struct libinput *libinput)1732 litest_disable_log_handler(struct libinput *libinput)
1733 {
1734 libinput_log_set_handler(libinput, NULL);
1735 }
1736
1737 void
litest_restore_log_handler(struct libinput *libinput)1738 litest_restore_log_handler(struct libinput *libinput)
1739 {
1740 libinput_log_set_handler(libinput, litest_log_handler);
1741 if (verbose)
1742 libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
1743 }
1744
1745 LIBINPUT_ATTRIBUTE_PRINTF(3, 0)
1746 static void
litest_bug_log_handler(struct libinput *libinput, enum libinput_log_priority pri, const char *format, va_list args)1747 litest_bug_log_handler(struct libinput *libinput,
1748 enum libinput_log_priority pri,
1749 const char *format,
1750 va_list args)
1751 {
1752 if (strstr(format, "client bug: ") ||
1753 strstr(format, "libinput bug: ") ||
1754 strstr(format, "kernel bug: "))
1755 return;
1756
1757 litest_abort_msg("Expected bug statement in log msg, aborting.\n");
1758 }
1759
1760 void
litest_set_log_handler_bug(struct libinput *libinput)1761 litest_set_log_handler_bug(struct libinput *libinput)
1762 {
1763 libinput_log_set_handler(libinput, litest_bug_log_handler);
1764 }
1765
1766 struct litest_device *
litest_add_device_with_overrides(struct libinput *libinput, enum litest_device_type which, const char *name_override, struct input_id *id_override, const struct input_absinfo *abs_override, const int *events_override)1767 litest_add_device_with_overrides(struct libinput *libinput,
1768 enum litest_device_type which,
1769 const char *name_override,
1770 struct input_id *id_override,
1771 const struct input_absinfo *abs_override,
1772 const int *events_override)
1773 {
1774 struct udev_device *ud;
1775 struct litest_device *d;
1776 const char *path;
1777
1778 d = litest_create(which,
1779 name_override,
1780 id_override,
1781 abs_override,
1782 events_override);
1783
1784 path = libevdev_uinput_get_devnode(d->uinput);
1785 litest_assert_ptr_notnull(path);
1786
1787 d->libinput = libinput;
1788 d->libinput_device = libinput_path_add_device(d->libinput, path);
1789 litest_assert_ptr_notnull(d->libinput_device);
1790 ud = libinput_device_get_udev_device(d->libinput_device);
1791 d->quirks = quirks_fetch_for_device(quirks_context, ud);
1792 udev_device_unref(ud);
1793
1794 libinput_device_ref(d->libinput_device);
1795
1796 if (d->interface) {
1797 unsigned int code;
1798
1799 code = ABS_X;
1800 if (!libevdev_has_event_code(d->evdev, EV_ABS, code))
1801 code = ABS_MT_POSITION_X;
1802 if (libevdev_has_event_code(d->evdev, EV_ABS, code)) {
1803 d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, code);
1804 d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, code);
1805 }
1806
1807 code = ABS_Y;
1808 if (!libevdev_has_event_code(d->evdev, EV_ABS, code))
1809 code = ABS_MT_POSITION_Y;
1810 if (libevdev_has_event_code(d->evdev, EV_ABS, code)) {
1811 d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, code);
1812 d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, code);
1813 }
1814 d->interface->tool_type = BTN_TOOL_PEN;
1815 }
1816 return d;
1817 }
1818
1819 struct litest_device *
litest_add_device(struct libinput *libinput, enum litest_device_type which)1820 litest_add_device(struct libinput *libinput,
1821 enum litest_device_type which)
1822 {
1823 return litest_add_device_with_overrides(libinput,
1824 which,
1825 NULL,
1826 NULL,
1827 NULL,
1828 NULL);
1829 }
1830
1831 struct litest_device *
litest_create_device_with_overrides(enum litest_device_type which, const char *name_override, struct input_id *id_override, const struct input_absinfo *abs_override, const int *events_override)1832 litest_create_device_with_overrides(enum litest_device_type which,
1833 const char *name_override,
1834 struct input_id *id_override,
1835 const struct input_absinfo *abs_override,
1836 const int *events_override)
1837 {
1838 struct litest_device *dev =
1839 litest_add_device_with_overrides(litest_create_context(),
1840 which,
1841 name_override,
1842 id_override,
1843 abs_override,
1844 events_override);
1845 dev->owns_context = true;
1846 return dev;
1847 }
1848
1849 struct litest_device *
litest_create_device(enum litest_device_type which)1850 litest_create_device(enum litest_device_type which)
1851 {
1852 return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL);
1853 }
1854
1855 static struct udev_monitor *
udev_setup_monitor(void)1856 udev_setup_monitor(void)
1857 {
1858 struct udev *udev;
1859 struct udev_monitor *udev_monitor;
1860 int rc;
1861
1862 udev = udev_new();
1863 litest_assert_notnull(udev);
1864 udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1865 litest_assert_notnull(udev_monitor);
1866 udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
1867 NULL);
1868
1869
1870 /* remove O_NONBLOCK */
1871 rc = fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0);
1872 litest_assert_int_ne(rc, -1);
1873 litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor),
1874 0);
1875 udev_unref(udev);
1876
1877 return udev_monitor;
1878 }
1879
1880 static struct udev_device *
udev_wait_for_device_event(struct udev_monitor *udev_monitor, const char *udev_event, const char *syspath)1881 udev_wait_for_device_event(struct udev_monitor *udev_monitor,
1882 const char *udev_event,
1883 const char *syspath)
1884 {
1885 struct udev_device *udev_device = NULL;
1886
1887 /* blocking, we don't want to continue until udev is ready */
1888 while (1) {
1889 const char *udev_syspath = NULL;
1890 const char *udev_action;
1891
1892 udev_device = udev_monitor_receive_device(udev_monitor);
1893 litest_assert_notnull(udev_device);
1894 udev_action = udev_device_get_action(udev_device);
1895 if (!udev_action || !streq(udev_action, udev_event)) {
1896 udev_device_unref(udev_device);
1897 continue;
1898 }
1899
1900 udev_syspath = udev_device_get_syspath(udev_device);
1901 if (udev_syspath && strstartswith(udev_syspath, syspath))
1902 break;
1903
1904 udev_device_unref(udev_device);
1905 }
1906
1907 return udev_device;
1908 }
1909
1910 void
litest_delete_device(struct litest_device *d)1911 litest_delete_device(struct litest_device *d)
1912 {
1913
1914 struct udev_monitor *udev_monitor;
1915 struct udev_device *udev_device;
1916 char path[PATH_MAX];
1917
1918 if (!d)
1919 return;
1920
1921 udev_monitor = udev_setup_monitor();
1922 snprintf(path, sizeof(path),
1923 "%s/event",
1924 libevdev_uinput_get_syspath(d->uinput));
1925
1926 litest_assert_int_eq(d->skip_ev_syn, 0);
1927
1928 quirks_unref(d->quirks);
1929
1930 if (d->libinput_device) {
1931 libinput_path_remove_device(d->libinput_device);
1932 libinput_device_unref(d->libinput_device);
1933 }
1934 if (d->owns_context) {
1935 libinput_dispatch(d->libinput);
1936 litest_destroy_context(d->libinput);
1937 }
1938 close(libevdev_get_fd(d->evdev));
1939 libevdev_free(d->evdev);
1940 libevdev_uinput_destroy(d->uinput);
1941 free(d->private);
1942 memset(d,0, sizeof(*d));
1943 free(d);
1944
1945 udev_device = udev_wait_for_device_event(udev_monitor,
1946 "remove",
1947 path);
1948 udev_device_unref(udev_device);
1949 udev_monitor_unref(udev_monitor);
1950 }
1951
1952 void
litest_event(struct litest_device *d, unsigned int type, unsigned int code, int value)1953 litest_event(struct litest_device *d, unsigned int type,
1954 unsigned int code, int value)
1955 {
1956 int ret;
1957
1958 if (!libevdev_has_event_code(d->evdev, type, code))
1959 return;
1960
1961 if (d->skip_ev_syn && type == EV_SYN && code == SYN_REPORT)
1962 return;
1963
1964 ret = libevdev_uinput_write_event(d->uinput, type, code, value);
1965 litest_assert_int_eq(ret, 0);
1966 }
1967
1968 static bool
axis_replacement_value(struct litest_device *d, struct axis_replacement *axes, int32_t evcode, int32_t *value)1969 axis_replacement_value(struct litest_device *d,
1970 struct axis_replacement *axes,
1971 int32_t evcode,
1972 int32_t *value)
1973 {
1974 struct axis_replacement *axis = axes;
1975
1976 if (!axes)
1977 return false;
1978
1979 while (axis->evcode != -1) {
1980 if (axis->evcode == evcode) {
1981 switch (evcode) {
1982 case ABS_MT_SLOT:
1983 case ABS_MT_TRACKING_ID:
1984 case ABS_MT_TOOL_TYPE:
1985 *value = axis->value;
1986 break;
1987 default:
1988 *value = litest_scale(d, evcode, axis->value);
1989 break;
1990 }
1991 return true;
1992 }
1993 axis++;
1994 }
1995
1996 return false;
1997 }
1998
1999 int
litest_auto_assign_value(struct litest_device *d, const struct input_event *ev, int slot, double x, double y, struct axis_replacement *axes, bool touching)2000 litest_auto_assign_value(struct litest_device *d,
2001 const struct input_event *ev,
2002 int slot, double x, double y,
2003 struct axis_replacement *axes,
2004 bool touching)
2005 {
2006 static int tracking_id;
2007 int value = ev->value;
2008
2009 if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2010 return value;
2011
2012 switch (ev->code) {
2013 case ABS_X:
2014 case ABS_MT_POSITION_X:
2015 value = litest_scale(d, ABS_X, x);
2016 break;
2017 case ABS_Y:
2018 case ABS_MT_POSITION_Y:
2019 value = litest_scale(d, ABS_Y, y);
2020 break;
2021 case ABS_MT_TRACKING_ID:
2022 value = ++tracking_id;
2023 break;
2024 case ABS_MT_SLOT:
2025 value = slot;
2026 break;
2027 case ABS_MT_DISTANCE:
2028 value = touching ? 0 : 1;
2029 break;
2030 case ABS_MT_TOOL_TYPE:
2031 if (!axis_replacement_value(d, axes, ev->code, &value))
2032 value = MT_TOOL_FINGER;
2033 break;
2034 default:
2035 if (!axis_replacement_value(d, axes, ev->code, &value) &&
2036 d->interface->get_axis_default) {
2037 int error = d->interface->get_axis_default(d,
2038 ev->code,
2039 &value);
2040 if (error) {
2041 litest_abort_msg("Failed to get default axis value for %s (%d)\n",
2042 libevdev_event_code_get_name(EV_ABS, ev->code),
2043 ev->code);
2044 }
2045 }
2046 break;
2047 }
2048
2049 return value;
2050 }
2051
2052 static void
send_btntool(struct litest_device *d, bool hover)2053 send_btntool(struct litest_device *d, bool hover)
2054 {
2055 litest_event(d, EV_KEY, BTN_TOUCH, d->ntouches_down != 0 && !hover);
2056 litest_event(d, EV_KEY, BTN_TOOL_FINGER, d->ntouches_down == 1);
2057 litest_event(d, EV_KEY, BTN_TOOL_DOUBLETAP, d->ntouches_down == 2);
2058 litest_event(d, EV_KEY, BTN_TOOL_TRIPLETAP, d->ntouches_down == 3);
2059 litest_event(d, EV_KEY, BTN_TOOL_QUADTAP, d->ntouches_down == 4);
2060 litest_event(d, EV_KEY, BTN_TOOL_QUINTTAP, d->ntouches_down == 5);
2061 }
2062
2063 static void
slot_start(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching, bool filter_abs_xy)2064 slot_start(struct litest_device *d,
2065 unsigned int slot,
2066 double x,
2067 double y,
2068 struct axis_replacement *axes,
2069 bool touching,
2070 bool filter_abs_xy)
2071 {
2072 struct input_event *ev;
2073
2074 litest_assert_int_ge(d->ntouches_down, 0);
2075 d->ntouches_down++;
2076
2077 send_btntool(d, !touching);
2078
2079 /* If the test device overrides touch_down and says it didn't
2080 * handle the event, let's continue normally */
2081 if (d->interface->touch_down &&
2082 d->interface->touch_down(d, slot, x, y))
2083 return;
2084
2085 for (ev = d->interface->touch_down_events;
2086 ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2087 ev++) {
2088 int value = litest_auto_assign_value(d,
2089 ev,
2090 slot,
2091 x,
2092 y,
2093 axes,
2094 touching);
2095 if (value == LITEST_AUTO_ASSIGN)
2096 continue;
2097
2098 if (filter_abs_xy && ev->type == EV_ABS &&
2099 (ev->code == ABS_X || ev->code == ABS_Y))
2100 continue;
2101
2102 litest_event(d, ev->type, ev->code, value);
2103 }
2104 }
2105
2106 static void
slot_move(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching, bool filter_abs_xy)2107 slot_move(struct litest_device *d,
2108 unsigned int slot,
2109 double x,
2110 double y,
2111 struct axis_replacement *axes,
2112 bool touching,
2113 bool filter_abs_xy)
2114 {
2115 struct input_event *ev;
2116
2117 if (d->interface->touch_move &&
2118 d->interface->touch_move(d, slot, x, y))
2119 return;
2120
2121 for (ev = d->interface->touch_move_events;
2122 ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2123 ev++) {
2124 int value = litest_auto_assign_value(d,
2125 ev,
2126 slot,
2127 x,
2128 y,
2129 axes,
2130 touching);
2131 if (value == LITEST_AUTO_ASSIGN)
2132 continue;
2133
2134 if (filter_abs_xy && ev->type == EV_ABS &&
2135 (ev->code == ABS_X || ev->code == ABS_Y))
2136 continue;
2137
2138 litest_event(d, ev->type, ev->code, value);
2139 }
2140 }
2141
2142 static void
touch_up(struct litest_device *d, unsigned int slot)2143 touch_up(struct litest_device *d, unsigned int slot)
2144 {
2145 struct input_event *ev;
2146 struct input_event up[] = {
2147 { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
2148 { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
2149 { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
2150 { .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 0 },
2151 { .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 0 },
2152 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
2153 { .type = -1, .code = -1 }
2154 };
2155
2156 litest_assert_int_gt(d->ntouches_down, 0);
2157 d->ntouches_down--;
2158
2159 send_btntool(d, false);
2160
2161 if (d->interface->touch_up &&
2162 d->interface->touch_up(d, slot)) {
2163 return;
2164 } else if (d->interface->touch_up_events) {
2165 ev = d->interface->touch_up_events;
2166 } else
2167 ev = up;
2168
2169 for ( /* */;
2170 ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1;
2171 ev++) {
2172 int value = litest_auto_assign_value(d,
2173 ev,
2174 slot,
2175 0,
2176 0,
2177 NULL,
2178 false);
2179 litest_event(d, ev->type, ev->code, value);
2180 }
2181 }
2182
2183 static void
litest_slot_start(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching)2184 litest_slot_start(struct litest_device *d,
2185 unsigned int slot,
2186 double x,
2187 double y,
2188 struct axis_replacement *axes,
2189 bool touching)
2190 {
2191 double t, l, r = 0, b = 0; /* top, left, right, bottom */
2192 bool filter_abs_xy = false;
2193
2194 if (!d->semi_mt.is_semi_mt) {
2195 slot_start(d, slot, x, y, axes, touching, filter_abs_xy);
2196 return;
2197 }
2198
2199 if (d->ntouches_down >= 2 || slot > 1)
2200 return;
2201
2202 slot = d->ntouches_down;
2203
2204 if (d->ntouches_down == 0) {
2205 l = x;
2206 t = y;
2207 } else {
2208 int other = (slot + 1) % 2;
2209 l = min(x, d->semi_mt.touches[other].x);
2210 t = min(y, d->semi_mt.touches[other].y);
2211 r = max(x, d->semi_mt.touches[other].x);
2212 b = max(y, d->semi_mt.touches[other].y);
2213 }
2214
2215 litest_push_event_frame(d);
2216 if (d->ntouches_down == 0)
2217 slot_start(d, 0, l, t, axes, touching, filter_abs_xy);
2218 else
2219 slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
2220
2221 if (slot == 1) {
2222 filter_abs_xy = true;
2223 slot_start(d, 1, r, b, axes, touching, filter_abs_xy);
2224 }
2225
2226 litest_pop_event_frame(d);
2227
2228 d->semi_mt.touches[slot].x = x;
2229 d->semi_mt.touches[slot].y = y;
2230 }
2231
2232 void
litest_touch_sequence(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, int steps)2233 litest_touch_sequence(struct litest_device *d,
2234 unsigned int slot,
2235 double x_from,
2236 double y_from,
2237 double x_to,
2238 double y_to,
2239 int steps)
2240 {
2241 litest_touch_down(d, slot, x_from, y_from);
2242 litest_touch_move_to(d, slot,
2243 x_from, y_from,
2244 x_to, y_to,
2245 steps);
2246 litest_touch_up(d, slot);
2247 }
2248
2249 void
litest_touch_down(struct litest_device *d, unsigned int slot, double x, double y)2250 litest_touch_down(struct litest_device *d,
2251 unsigned int slot,
2252 double x,
2253 double y)
2254 {
2255 litest_slot_start(d, slot, x, y, NULL, true);
2256 }
2257
2258 void
litest_touch_down_extended(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes)2259 litest_touch_down_extended(struct litest_device *d,
2260 unsigned int slot,
2261 double x,
2262 double y,
2263 struct axis_replacement *axes)
2264 {
2265 litest_slot_start(d, slot, x, y, axes, true);
2266 }
2267
2268 static void
litest_slot_move(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes, bool touching)2269 litest_slot_move(struct litest_device *d,
2270 unsigned int slot,
2271 double x,
2272 double y,
2273 struct axis_replacement *axes,
2274 bool touching)
2275 {
2276 double t, l, r = 0, b = 0; /* top, left, right, bottom */
2277 bool filter_abs_xy = false;
2278
2279 if (!d->semi_mt.is_semi_mt) {
2280 slot_move(d, slot, x, y, axes, touching, filter_abs_xy);
2281 return;
2282 }
2283
2284 if (d->ntouches_down > 2 || slot > 1)
2285 return;
2286
2287 if (d->ntouches_down == 1) {
2288 l = x;
2289 t = y;
2290 } else {
2291 int other = (slot + 1) % 2;
2292 l = min(x, d->semi_mt.touches[other].x);
2293 t = min(y, d->semi_mt.touches[other].y);
2294 r = max(x, d->semi_mt.touches[other].x);
2295 b = max(y, d->semi_mt.touches[other].y);
2296 }
2297
2298 litest_push_event_frame(d);
2299 slot_move(d, 0, l, t, axes, touching, filter_abs_xy);
2300
2301 if (d->ntouches_down == 2) {
2302 filter_abs_xy = true;
2303 slot_move(d, 1, r, b, axes, touching, filter_abs_xy);
2304 }
2305
2306 litest_pop_event_frame(d);
2307
2308 d->semi_mt.touches[slot].x = x;
2309 d->semi_mt.touches[slot].y = y;
2310 }
2311
2312 void
litest_touch_up(struct litest_device *d, unsigned int slot)2313 litest_touch_up(struct litest_device *d, unsigned int slot)
2314 {
2315 if (!d->semi_mt.is_semi_mt) {
2316 touch_up(d, slot);
2317 return;
2318 }
2319
2320 if (d->ntouches_down > 2 || slot > 1)
2321 return;
2322
2323 litest_push_event_frame(d);
2324 touch_up(d, d->ntouches_down - 1);
2325
2326 /* if we have one finger left, send x/y coords for that finger left.
2327 this is likely to happen with a real touchpad */
2328 if (d->ntouches_down == 1) {
2329 bool touching = true;
2330 bool filter_abs_xy = false;
2331
2332 int other = (slot + 1) % 2;
2333 slot_move(d,
2334 0,
2335 d->semi_mt.touches[other].x,
2336 d->semi_mt.touches[other].y,
2337 NULL,
2338 touching,
2339 filter_abs_xy);
2340 }
2341
2342 litest_pop_event_frame(d);
2343 }
2344
2345 void
litest_touch_move(struct litest_device *d, unsigned int slot, double x, double y)2346 litest_touch_move(struct litest_device *d,
2347 unsigned int slot,
2348 double x,
2349 double y)
2350 {
2351 litest_slot_move(d, slot, x, y, NULL, true);
2352 }
2353
2354 void
litest_touch_move_extended(struct litest_device *d, unsigned int slot, double x, double y, struct axis_replacement *axes)2355 litest_touch_move_extended(struct litest_device *d,
2356 unsigned int slot,
2357 double x,
2358 double y,
2359 struct axis_replacement *axes)
2360 {
2361 litest_slot_move(d, slot, x, y, axes, true);
2362 }
2363
2364 void
litest_touch_move_to(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, int steps)2365 litest_touch_move_to(struct litest_device *d,
2366 unsigned int slot,
2367 double x_from, double y_from,
2368 double x_to, double y_to,
2369 int steps)
2370 {
2371 litest_touch_move_to_extended(d, slot,
2372 x_from, y_from,
2373 x_to, y_to,
2374 NULL,
2375 steps);
2376 }
2377
2378 void
litest_touch_move_to_extended(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, struct axis_replacement *axes, int steps)2379 litest_touch_move_to_extended(struct litest_device *d,
2380 unsigned int slot,
2381 double x_from, double y_from,
2382 double x_to, double y_to,
2383 struct axis_replacement *axes,
2384 int steps)
2385 {
2386 int sleep_ms = 10;
2387
2388 for (int i = 1; i < steps; i++) {
2389 litest_touch_move_extended(d, slot,
2390 x_from + (x_to - x_from)/steps * i,
2391 y_from + (y_to - y_from)/steps * i,
2392 axes);
2393 libinput_dispatch(d->libinput);
2394 msleep(sleep_ms);
2395 libinput_dispatch(d->libinput);
2396 }
2397 litest_touch_move_extended(d, slot, x_to, y_to, axes);
2398 }
2399
2400 static int
auto_assign_tablet_value(struct litest_device *d, const struct input_event *ev, int x, int y, struct axis_replacement *axes)2401 auto_assign_tablet_value(struct litest_device *d,
2402 const struct input_event *ev,
2403 int x, int y,
2404 struct axis_replacement *axes)
2405 {
2406 static int tracking_id;
2407 int value = ev->value;
2408
2409 if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS)
2410 return value;
2411
2412 switch (ev->code) {
2413 case ABS_MT_TRACKING_ID:
2414 value = ++tracking_id;
2415 break;
2416 case ABS_X:
2417 case ABS_MT_POSITION_X:
2418 value = litest_scale(d, ABS_X, x);
2419 break;
2420 case ABS_Y:
2421 case ABS_MT_POSITION_Y:
2422 value = litest_scale(d, ABS_Y, y);
2423 break;
2424 default:
2425 if (!axis_replacement_value(d, axes, ev->code, &value) &&
2426 d->interface->get_axis_default) {
2427 int error = d->interface->get_axis_default(d, ev->code, &value);
2428 if (error) {
2429 litest_abort_msg("Failed to get default axis value for %s (%d)\n",
2430 libevdev_event_code_get_name(EV_ABS, ev->code),
2431 ev->code);
2432 }
2433 }
2434 break;
2435 }
2436
2437 return value;
2438 }
2439
2440 static int
tablet_ignore_event(const struct input_event *ev, int value)2441 tablet_ignore_event(const struct input_event *ev, int value)
2442 {
2443 return value == -1 && (ev->code == ABS_PRESSURE || ev->code == ABS_DISTANCE);
2444 }
2445
2446 void
litest_tablet_set_tool_type(struct litest_device *d, unsigned int code)2447 litest_tablet_set_tool_type(struct litest_device *d, unsigned int code)
2448 {
2449 switch (code) {
2450 case BTN_TOOL_PEN:
2451 case BTN_TOOL_RUBBER:
2452 case BTN_TOOL_BRUSH:
2453 case BTN_TOOL_PENCIL:
2454 case BTN_TOOL_AIRBRUSH:
2455 case BTN_TOOL_MOUSE:
2456 case BTN_TOOL_LENS:
2457 break;
2458 default:
2459 abort();
2460 }
2461
2462 d->interface->tool_type = code;
2463 }
2464
2465 static void
litest_tool_event(struct litest_device *d, int value)2466 litest_tool_event(struct litest_device *d, int value)
2467 {
2468 unsigned int tool = d->interface->tool_type;
2469
2470 litest_event(d, EV_KEY, tool, value);
2471 }
2472
2473 void
litest_tablet_proximity_in(struct litest_device *d, double x, double y, struct axis_replacement *axes)2474 litest_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
2503 void
litest_tablet_proximity_out(struct litest_device *d)2504 litest_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
2532 void
litest_tablet_motion(struct litest_device *d, double x, double y, struct axis_replacement *axes)2533 litest_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
2554 void
litest_tablet_tip_down(struct litest_device *d, double x, double y, struct axis_replacement *axes)2555 litest_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
2569 void
litest_tablet_tip_up(struct litest_device *d, double x, double y, struct axis_replacement *axes)2570 litest_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
2584 void
litest_touch_move_two_touches(struct litest_device *d, double x0, double y0, double x1, double y1, double dx, double dy, int steps)2585 litest_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
2610 void
litest_touch_move_three_touches(struct litest_device *d, double x0, double y0, double x1, double y1, double x2, double y2, double dx, double dy, int steps)2611 litest_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
2636 void
litest_hover_start(struct litest_device *d, unsigned int slot, double x, double y)2637 litest_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
2651 void
litest_hover_end(struct litest_device *d, unsigned int slot)2652 litest_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
2683 void
litest_hover_move(struct litest_device *d, unsigned int slot, double x, double y)2684 litest_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
2696 void
litest_hover_move_to(struct litest_device *d, unsigned int slot, double x_from, double y_from, double x_to, double y_to, int steps)2697 litest_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
2716 void
litest_hover_move_two_touches(struct litest_device *d, double x0, double y0, double x1, double y1, double dx, double dy, int steps)2717 litest_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
2742 void
litest_button_click(struct litest_device *d, unsigned int button, bool is_press)2743 litest_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
2756 void
litest_button_click_debounced(struct litest_device *d, struct libinput *li, unsigned int button, bool is_press)2757 litest_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
2769 void
litest_button_scroll(struct litest_device *dev, unsigned int button, double dx, double dy)2770 litest_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
2791 void
litest_button_scroll_locked(struct litest_device *dev, unsigned int button, double dx, double dy)2792 litest_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
2812 void
litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press)2813 litest_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
2824 void
litest_switch_action(struct litest_device *dev, enum libinput_switch sw, enum libinput_switch_state state)2825 litest_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
2846 static int
litest_scale_axis(const struct litest_device *d, unsigned int axis, double val)2847 litest_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
2866 static inline int
litest_scale_range(int min, int max, double val)2867 litest_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
2875 int
litest_scale(const struct litest_device *d, unsigned int axis, double val)2876 litest_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
2896 static inline int
auto_assign_pad_value(struct litest_device *dev, struct input_event *ev, double value)2897 auto_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
2927 void
litest_pad_ring_start(struct litest_device *d, double value)2928 litest_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
2940 void
litest_pad_ring_change(struct litest_device *d, double value)2941 litest_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
2953 void
litest_pad_ring_end(struct litest_device *d)2954 litest_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
2965 void
litest_pad_strip_start(struct litest_device *d, double value)2966 litest_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
2978 void
litest_pad_strip_change(struct litest_device *d, double value)2979 litest_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
2991 void
litest_pad_strip_end(struct litest_device *d)2992 litest_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
3003 void
litest_wait_for_event(struct libinput *li)3004 litest_wait_for_event(struct libinput *li)
3005 {
3006 return litest_wait_for_event_of_type(li, -1);
3007 }
3008
3009 void
litest_wait_for_event_of_type(struct libinput *li, ...)3010 litest_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
3056 void
litest_drain_events(struct libinput *li)3057 litest_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
3069 void
litest_drain_events_of_type(struct libinput *li, ...)3070 litest_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
3110 static const char *
litest_event_type_str(enum libinput_event_type type)3111 litest_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
3218 static const char *
litest_event_get_type_str(struct libinput_event *event)3219 litest_event_get_type_str(struct libinput_event *event)
3220 {
3221 return litest_event_type_str(libinput_event_get_type(event));
3222 }
3223
3224 static void
litest_print_event(struct libinput_event *event)3225 litest_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
3322 static void
_litest_assert_event_type_is_one_of(struct libinput_event *event, ...)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
3366 void
litest_assert_event_type(struct libinput_event *event, enum libinput_event_type want)3367 litest_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
3373 void
litest_assert_empty_queue(struct libinput *li)3374 litest_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
3392 static struct libevdev_uinput *
litest_create_uinput(const char *name, const struct input_id *id, const struct input_absinfo *abs_info, const int *events)3393 litest_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
3496 struct libevdev_uinput *
litest_create_uinput_device_from_description(const char *name, const struct input_id *id, const struct input_absinfo *abs_info, const int *events)3497 litest_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
3526 static struct libevdev_uinput *
litest_create_uinput_abs_device_v(const char *name, struct input_id *id, const struct input_absinfo *abs, va_list args)3527 litest_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
3550 struct libevdev_uinput *
litest_create_uinput_abs_device(const char *name, struct input_id *id, const struct input_absinfo *abs, ...)3551 litest_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
3566 struct libevdev_uinput *
litest_create_uinput_device(const char *name, struct input_id *id, ...)3567 litest_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
3579 struct libinput_event_pointer*
litest_is_button_event(struct libinput_event *event, unsigned int button, enum libinput_button_state state)3580 litest_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
3598 struct libinput_event_pointer *
litest_is_axis_event(struct libinput_event *event, enum libinput_event_type axis_type, enum libinput_pointer_axis axis, enum libinput_pointer_axis_source source)3599 litest_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
3624 bool
litest_is_high_res_axis_event(struct libinput_event *event)3625 litest_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
3636 struct libinput_event_pointer *
litest_is_motion_event(struct libinput_event *event)3637 litest_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
3659 void
litest_assert_key_event(struct libinput *li, unsigned int key, enum libinput_key_state state)3660 litest_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
3673 void
litest_assert_button_event(struct libinput *li, unsigned int button, enum libinput_button_state state)3674 litest_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
3687 struct libinput_event_touch *
litest_is_touch_event(struct libinput_event *event, enum libinput_event_type type)3688 litest_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
3715 struct libinput_event_keyboard *
litest_is_keyboard_event(struct libinput_event *event, unsigned int key, enum libinput_key_state state)3716 litest_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
3735 struct libinput_event_gesture *
litest_is_gesture_event(struct libinput_event *event, enum libinput_event_type type, int nfingers)3736 litest_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
3754 void
litest_assert_gesture_event(struct libinput *li, enum libinput_event_type type, int nfingers)3755 litest_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
3768 struct libinput_event_tablet_tool *
litest_is_tablet_event(struct libinput_event *event, enum libinput_event_type type)3769 litest_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
3783 void
litest_assert_tablet_button_event(struct libinput *li, unsigned int button, enum libinput_button_state state)3784 litest_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
3805 struct libinput_event_tablet_tool *
litest_is_proximity_event(struct libinput_event *event, enum libinput_tablet_tool_proximity_state state)3806 litest_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
3820 double
litest_event_pointer_get_value(struct libinput_event_pointer *ptrev, enum libinput_pointer_axis axis)3821 litest_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
3843 enum libinput_pointer_axis_source
litest_event_pointer_get_axis_source(struct libinput_event_pointer *ptrev)3844 litest_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
litest_assert_tablet_proximity_event(struct libinput *li, enum libinput_tablet_tool_proximity_state state)3867 void 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
litest_assert_tablet_tip_event(struct libinput *li, enum libinput_tablet_tool_tip_state state)3878 void 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
3896 struct libinput_event_tablet_pad *
litest_is_pad_button_event(struct libinput_event *event, unsigned int button, enum libinput_button_state state)3897 litest_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
3918 struct libinput_event_tablet_pad *
litest_is_pad_ring_event(struct libinput_event *event, unsigned int number, enum libinput_tablet_pad_ring_axis_source source)3919 litest_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
3938 struct libinput_event_tablet_pad *
litest_is_pad_strip_event(struct libinput_event *event, unsigned int number, enum libinput_tablet_pad_strip_axis_source source)3939 litest_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
3958 struct libinput_event_tablet_pad *
litest_is_pad_key_event(struct libinput_event *event, unsigned int key, enum libinput_key_state state)3959 litest_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
3979 struct libinput_event_switch *
litest_is_switch_event(struct libinput_event *event, enum libinput_switch sw, enum libinput_switch_state state)3980 litest_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
3998 void
litest_assert_switch_event(struct libinput *li, enum libinput_switch sw, enum libinput_switch_state state)3999 litest_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
4013 void
litest_assert_pad_button_event(struct libinput *li, unsigned int button, enum libinput_button_state state)4014 litest_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
4027 void
litest_assert_pad_key_event(struct libinput *li, unsigned int key, enum libinput_key_state state)4028 litest_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
4041 void
litest_assert_scroll(struct libinput *li, enum libinput_event_type axis_type, enum libinput_pointer_axis axis, int minimum_movement)4042 litest_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
4107 void
litest_assert_axis_end_sequence(struct libinput *li, enum libinput_event_type axis_type, enum libinput_pointer_axis axis, enum libinput_pointer_axis_source source)4108 litest_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
4148 void
litest_assert_only_typed_events(struct libinput *li, enum libinput_event_type type)4149 litest_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
4168 void
litest_assert_only_axis_events(struct libinput *li, enum libinput_event_type axis_type)4169 litest_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
4192 void
litest_assert_no_typed_events(struct libinput *li, enum libinput_event_type type)4193 litest_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
4212 void
litest_assert_touch_sequence(struct libinput *li)4213 litest_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
4250 void
litest_assert_touch_motion_frame(struct libinput *li)4251 litest_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
4277 void
litest_assert_touch_down_frame(struct libinput *li)4278 litest_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
4291 void
litest_assert_touch_up_frame(struct libinput *li)4292 litest_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
4305 void
litest_assert_touch_cancel(struct libinput *li)4306 litest_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
4319 void
litest_timeout_tap(void)4320 litest_timeout_tap(void)
4321 {
4322 msleep(300);
4323 }
4324
4325 void
litest_timeout_tapndrag(void)4326 litest_timeout_tapndrag(void)
4327 {
4328 msleep(520);
4329 }
4330
4331 void
litest_timeout_debounce(void)4332 litest_timeout_debounce(void)
4333 {
4334 msleep(30);
4335 }
4336
4337 void
litest_timeout_softbuttons(void)4338 litest_timeout_softbuttons(void)
4339 {
4340 msleep(300);
4341 }
4342
4343 void
litest_timeout_buttonscroll(void)4344 litest_timeout_buttonscroll(void)
4345 {
4346 msleep(300);
4347 }
4348
4349 void
litest_timeout_finger_switch(void)4350 litest_timeout_finger_switch(void)
4351 {
4352 msleep(120);
4353 }
4354
4355 void
litest_timeout_wheel_scroll(void)4356 litest_timeout_wheel_scroll(void)
4357 {
4358 msleep(600);
4359 }
4360
4361 void
litest_timeout_edgescroll(void)4362 litest_timeout_edgescroll(void)
4363 {
4364 msleep(300);
4365 }
4366
4367 void
litest_timeout_middlebutton(void)4368 litest_timeout_middlebutton(void)
4369 {
4370 msleep(70);
4371 }
4372
4373 void
litest_timeout_dwt_short(void)4374 litest_timeout_dwt_short(void)
4375 {
4376 msleep(220);
4377 }
4378
4379 void
litest_timeout_dwt_long(void)4380 litest_timeout_dwt_long(void)
4381 {
4382 msleep(520);
4383 }
4384
4385 void
litest_timeout_gesture(void)4386 litest_timeout_gesture(void)
4387 {
4388 msleep(120);
4389 }
4390
4391 void
litest_timeout_gesture_scroll(void)4392 litest_timeout_gesture_scroll(void)
4393 {
4394 msleep(180);
4395 }
4396
4397 void
litest_timeout_gesture_hold(void)4398 litest_timeout_gesture_hold(void)
4399 {
4400 msleep(300);
4401 }
4402
4403 void
litest_timeout_gesture_quick_hold(void)4404 litest_timeout_gesture_quick_hold(void)
4405 {
4406 msleep(60);
4407 }
4408
4409 void
litest_timeout_trackpoint(void)4410 litest_timeout_trackpoint(void)
4411 {
4412 msleep(320);
4413 }
4414
4415 void
litest_timeout_tablet_proxout(void)4416 litest_timeout_tablet_proxout(void)
4417 {
4418 msleep(170);
4419 }
4420
4421 void
litest_timeout_touch_arbitration(void)4422 litest_timeout_touch_arbitration(void)
4423 {
4424 msleep(100);
4425 }
4426
4427 void
litest_timeout_hysteresis(void)4428 litest_timeout_hysteresis(void)
4429 {
4430 msleep(90);
4431 }
4432
4433 void
litest_push_event_frame(struct litest_device *dev)4434 litest_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
4440 void
litest_pop_event_frame(struct litest_device *dev)4441 litest_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
4449 void
litest_filter_event(struct litest_device *dev, unsigned int type, unsigned int code)4450 litest_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
4457 void
litest_unfilter_event(struct litest_device *dev, unsigned int type, unsigned int code)4458 litest_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
4469 static void
send_abs_xy(struct litest_device *d, double x, double y)4470 send_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
4486 static void
send_abs_mt_xy(struct litest_device *d, double x, double y)4487 send_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
4504 void
litest_semi_mt_touch_down(struct litest_device *d, struct litest_semi_mt *semi_mt, unsigned int slot, double x, double y)4505 litest_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
4548 void
litest_semi_mt_touch_move(struct litest_device *d, struct litest_semi_mt *semi_mt, unsigned int slot, double x, double y)4549 litest_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
4586 void
litest_semi_mt_touch_up(struct litest_device *d, struct litest_semi_mt *semi_mt, unsigned int slot)4587 litest_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
4610 enum litest_mode {
4611 LITEST_MODE_ERROR,
4612 LITEST_MODE_TEST,
4613 LITEST_MODE_LIST,
4614 };
4615
4616 static inline enum litest_mode
litest_parse_argv(int argc, char **argv)4617 litest_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
4742 static bool
is_debugger_attached(void)4743 is_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
4771 static void
litest_list_tests(struct list *tests)4772 litest_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
4792 extern const struct test_device __start_test_section, __stop_test_section;
4793
4794 static void
litest_init_test_devices(void)4795 litest_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
4805 extern const struct test_collection __start_test_collection_section,
4806 __stop_test_collection_section;
4807
4808 static void
setup_tests(void)4809 setup_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
4820 static int
check_device_access(void)4821 check_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
4840 static int
disable_tty(void)4841 disable_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
4873 int
main(int argc, char **argv)4874 main(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