5235e3c2731ffb3332b0993122b59afe41804748
[platform/upstream/libinput.git] / test / litest.c
1 /*
2  * Copyright © 2013 Red Hat, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #if HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <check.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <getopt.h>
31 #include <poll.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <linux/input.h>
38 #include <sys/ptrace.h>
39 #include <sys/timerfd.h>
40 #include <sys/wait.h>
41
42 #include "litest.h"
43 #include "litest-int.h"
44 #include "libinput-util.h"
45
46 static int in_debugger = -1;
47
48 struct test {
49         struct list node;
50         char *name;
51         TCase *tc;
52         enum litest_device_type devices;
53 };
54
55 struct suite {
56         struct list node;
57         struct list tests;
58         char *name;
59         Suite *suite;
60 };
61
62 static struct litest_device *current_device;
63
64 struct litest_device *litest_current_device(void) {
65         return current_device;
66 }
67
68 void litest_set_current_device(struct litest_device *device) {
69         current_device = device;
70 }
71
72 void litest_generic_device_teardown(void)
73 {
74         litest_delete_device(current_device);
75         current_device = NULL;
76 }
77
78 extern struct litest_test_device litest_keyboard_device;
79 extern struct litest_test_device litest_synaptics_clickpad_device;
80 extern struct litest_test_device litest_trackpoint_device;
81 extern struct litest_test_device litest_bcm5974_device;
82 extern struct litest_test_device litest_mouse_device;
83 extern struct litest_test_device litest_wacom_touch_device;
84
85 struct litest_test_device* devices[] = {
86         &litest_synaptics_clickpad_device,
87         &litest_keyboard_device,
88         &litest_trackpoint_device,
89         &litest_bcm5974_device,
90         &litest_mouse_device,
91         &litest_wacom_touch_device,
92         NULL,
93 };
94
95
96 static struct list all_tests;
97
98 static void
99 litest_add_tcase_for_device(struct suite *suite,
100                             void *func,
101                             const struct litest_test_device *dev)
102 {
103         struct test *t;
104         const char *test_name = dev->shortname;
105
106         list_for_each(t, &suite->tests, node) {
107                 if (strcmp(t->name, test_name) != 0)
108                         continue;
109
110                 tcase_add_test(t->tc, func);
111                 return;
112         }
113
114         t = zalloc(sizeof(*t));
115         t->name = strdup(test_name);
116         t->tc = tcase_create(test_name);
117         list_insert(&suite->tests, &t->node);
118         tcase_add_checked_fixture(t->tc, dev->setup, dev->teardown);
119         tcase_add_test(t->tc, func);
120         suite_add_tcase(suite->suite, t->tc);
121 }
122
123 static void
124 litest_add_tcase_no_device(struct suite *suite, void *func)
125 {
126         struct test *t;
127         const char *test_name = "no device";
128
129         list_for_each(t, &suite->tests, node) {
130                 if (strcmp(t->name, test_name) != 0)
131                         continue;
132
133                 tcase_add_test(t->tc, func);
134                 return;
135         }
136
137         t = zalloc(sizeof(*t));
138         t->name = strdup(test_name);
139         t->tc = tcase_create(test_name);
140         list_insert(&suite->tests, &t->node);
141         tcase_add_test(t->tc, func);
142         suite_add_tcase(suite->suite, t->tc);
143 }
144
145 static void
146 litest_add_tcase(struct suite *suite, void *func,
147                  enum litest_device_feature required,
148                  enum litest_device_feature excluded)
149 {
150         struct litest_test_device **dev = devices;
151
152         if (required == LITEST_DISABLE_DEVICE &&
153             excluded == LITEST_DISABLE_DEVICE) {
154                 litest_add_tcase_no_device(suite, func);
155         } else if (required != LITEST_ANY || excluded != LITEST_ANY) {
156                 while (*dev) {
157                         if (((*dev)->features & required) == required &&
158                             ((*dev)->features & excluded) == 0)
159                                 litest_add_tcase_for_device(suite, func, *dev);
160                         dev++;
161                 }
162         } else {
163                 while (*dev) {
164                         litest_add_tcase_for_device(suite, func, *dev);
165                         dev++;
166                 }
167         }
168 }
169
170 void
171 litest_add_no_device(const char *name, void *func)
172 {
173         litest_add(name, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
174 }
175
176 void
177 litest_add(const char *name,
178            void *func,
179            enum litest_device_feature required,
180            enum litest_device_feature excluded)
181 {
182         struct suite *s;
183
184         if (all_tests.next == NULL && all_tests.prev == NULL)
185                 list_init(&all_tests);
186
187         list_for_each(s, &all_tests, node) {
188                 if (strcmp(s->name, name) == 0) {
189                         litest_add_tcase(s, func, required, excluded);
190                         return;
191                 }
192         }
193
194         s = zalloc(sizeof(*s));
195         s->name = strdup(name);
196         s->suite = suite_create(s->name);
197
198         list_init(&s->tests);
199         list_insert(&all_tests, &s->node);
200         litest_add_tcase(s, func, required, excluded);
201 }
202
203 int is_debugger_attached()
204 {
205         int status;
206         int rc;
207         int pid = fork();
208
209         if (pid == -1)
210                 return 0;
211
212         if (pid == 0) {
213                 int ppid = getppid();
214                 if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) {
215                         waitpid(ppid, NULL, 0);
216                         ptrace(PTRACE_CONT, NULL, NULL);
217                         ptrace(PTRACE_DETACH, ppid, NULL, NULL);
218                         rc = 0;
219                 } else {
220                         rc = 1;
221                 }
222                 _exit(rc);
223         } else {
224                 waitpid(pid, &status, 0);
225                 rc = WEXITSTATUS(status);
226         }
227
228         return rc;
229 }
230
231
232 static void
233 litest_list_tests(struct list *tests)
234 {
235         struct suite *s;
236
237         list_for_each(s, tests, node) {
238                 struct test *t;
239                 printf("%s:\n", s->name);
240                 list_for_each(t, &s->tests, node) {
241                         printf("        %s\n", t->name);
242                 }
243         }
244 }
245
246 static const struct option opts[] = {
247         { "list", 0, 0, 'l' },
248         { 0, 0, 0, 0}
249 };
250
251 int
252 litest_run(int argc, char **argv) {
253         struct suite *s, *snext;
254         int failed;
255         SRunner *sr = NULL;
256
257         if (in_debugger == -1) {
258                 in_debugger = is_debugger_attached();
259                 if (in_debugger)
260                         setenv("CK_FORK", "no", 0);
261         }
262
263         list_for_each(s, &all_tests, node) {
264                 if (!sr)
265                         sr = srunner_create(s->suite);
266                 else
267                         srunner_add_suite(sr, s->suite);
268         }
269
270         while(1) {
271                 int c;
272                 int option_index = 0;
273
274                 c = getopt_long(argc, argv, "", opts, &option_index);
275                 if (c == -1)
276                         break;
277                 switch(c) {
278                         case 'l':
279                                 litest_list_tests(&all_tests);
280                                 return 0;
281                         default:
282                                 fprintf(stderr, "usage: %s [--list]\n", argv[0]);
283                                 return 1;
284
285                 }
286         }
287
288         srunner_run_all(sr, CK_NORMAL);
289         failed = srunner_ntests_failed(sr);
290         srunner_free(sr);
291
292         list_for_each_safe(s, snext, &all_tests, node) {
293                 struct test *t, *tnext;
294
295                 list_for_each_safe(t, tnext, &s->tests, node) {
296                         free(t->name);
297                         list_remove(&t->node);
298                         free(t);
299                 }
300
301                 list_remove(&s->node);
302                 free(s->name);
303                 free(s);
304         }
305
306         return failed;
307 }
308
309 static int
310 open_restricted(const char *path, int flags, void *userdata)
311 {
312         return open(path, flags);
313 }
314
315 static void
316 close_restricted(int fd, void *userdata)
317 {
318         close(fd);
319 }
320
321 static void
322 get_current_screen_dimensions(struct libinput_device *device,
323                               int *width,
324                               int *height,
325                               void *user_data)
326 {
327         *width = 1024;
328         *height = 768;
329 }
330
331 const struct libinput_interface interface = {
332         .open_restricted = open_restricted,
333         .close_restricted = close_restricted,
334         .get_current_screen_dimensions = get_current_screen_dimensions,
335 };
336
337 struct litest_device *
338 litest_create_device(enum litest_device_type which)
339 {
340         struct litest_device *d = zalloc(sizeof(*d));
341         int fd;
342         int rc;
343         const char *path;
344         struct litest_test_device **dev;
345
346         ck_assert(d != NULL);
347
348         dev = devices;
349         while (*dev) {
350                 if ((*dev)->type == which) {
351                         (*dev)->create(d);
352                         break;
353                 }
354                 dev++;
355         }
356
357         if (!dev) {
358                 ck_abort_msg("Invalid device type %d\n", which);
359                 return NULL;
360         }
361
362         path = libevdev_uinput_get_devnode(d->uinput);
363         ck_assert(path != NULL);
364         fd = open(path, O_RDWR|O_NONBLOCK);
365         ck_assert_int_ne(fd, -1);
366
367         rc = libevdev_new_from_fd(fd, &d->evdev);
368         ck_assert_int_eq(rc, 0);
369
370         d->libinput = libinput_create_from_path(&interface, NULL, path);
371         ck_assert(d->libinput != NULL);
372
373         d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, ABS_X);
374         d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, ABS_X);
375         d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, ABS_Y);
376         d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, ABS_Y);
377         return d;
378 }
379
380 int
381 litest_handle_events(struct litest_device *d)
382 {
383         struct pollfd fd;
384
385         fd.fd = libinput_get_fd(d->libinput);
386         fd.events = POLLIN;
387
388         while (poll(&fd, 1, 1))
389                 libinput_dispatch(d->libinput);
390
391         return 0;
392 }
393
394 void
395 litest_delete_device(struct litest_device *d)
396 {
397         if (!d)
398                 return;
399
400         libinput_destroy(d->libinput);
401         libevdev_free(d->evdev);
402         libevdev_uinput_destroy(d->uinput);
403         memset(d,0, sizeof(*d));
404         free(d);
405 }
406
407 void
408 litest_event(struct litest_device *d, unsigned int type,
409              unsigned int code, int value)
410 {
411         libevdev_uinput_write_event(d->uinput, type, code, value);
412 }
413
414 void
415 litest_touch_down(struct litest_device *d, unsigned int slot, int x, int y)
416 {
417         d->interface->touch_down(d, slot, x, y);
418 }
419
420 void
421 litest_touch_up(struct litest_device *d, unsigned int slot)
422 {
423         struct input_event *ev;
424         struct input_event up[] = {
425                 { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
426                 { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
427                 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
428         };
429
430         ARRAY_FOR_EACH(up, ev)
431                 litest_event(d, ev->type, ev->code, ev->value);
432 }
433
434 void
435 litest_touch_move(struct litest_device *d, unsigned int slot, int x, int y)
436 {
437         d->interface->touch_move(d, slot, x, y);
438 }
439
440 void
441 litest_touch_move_to(struct litest_device *d,
442                      unsigned int slot,
443                      int x_from, int y_from,
444                      int x_to, int y_to,
445                      int steps)
446 {
447         for (int i = 0; i < steps - 1; i++)
448                 litest_touch_move(d, slot,
449                                   x_from + (x_to - x_from)/steps * i,
450                                   y_from + (y_to - y_from)/steps * i);
451         litest_touch_move(d, slot, x_to, y_to);
452 }
453
454 void
455 litest_click(struct litest_device *d, unsigned int button, bool is_press)
456 {
457
458         struct input_event *ev;
459         struct input_event click[] = {
460                 { .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
461                 { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
462         };
463
464         ARRAY_FOR_EACH(click, ev)
465                 litest_event(d, ev->type, ev->code, ev->value);
466 }
467
468 int litest_scale(const struct litest_device *d, unsigned int axis, int val)
469 {
470         int min, max;
471         ck_assert_int_ge(val, 0);
472         ck_assert_int_le(val, 100);
473         ck_assert_int_le(axis, ABS_Y);
474
475         min = d->interface->min[axis];
476         max = d->interface->max[axis];
477         return (max - min) * val/100.0 + min;
478 }
479
480 void
481 litest_drain_events(struct libinput *li)
482 {
483         struct libinput_event *event;
484
485         libinput_dispatch(li);
486         while ((event = libinput_get_event(li))) {
487                 libinput_event_destroy(event);
488                 libinput_dispatch(li);
489         }
490 }