| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- /*
- * Copyright © 2013 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- #include <config.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <libinput-util.h>
- #include <libinput.h>
- #include <libudev.h>
- #include <unistd.h>
- #include "litest.h"
- static int
- open_restricted(const char *path, int flags, void *data)
- {
- int fd;
- fd = open(path, flags);
- return fd < 0 ? -errno : fd;
- }
- static void
- close_restricted(int fd, void *data)
- {
- close(fd);
- }
- static const struct libinput_interface simple_interface = {
- .open_restricted = open_restricted,
- .close_restricted = close_restricted,
- };
- START_TEST(udev_create_NULL)
- {
- _unref_(udev) *udev = udev_new();
- _unref_(libinput) *li = libinput_udev_create_context(NULL, NULL, NULL);
- litest_assert(li == NULL);
- li = libinput_udev_create_context(&simple_interface, NULL, NULL);
- litest_assert(li == NULL);
- li = libinput_udev_create_context(NULL, NULL, udev);
- litest_assert(li == NULL);
- li = libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, NULL), -1);
- }
- END_TEST
- START_TEST(udev_create_seat0)
- {
- struct libinput_event *event;
- int fd;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- fd = libinput_get_fd(li);
- litest_assert_int_ge(fd, 0);
- /* expect at least one event */
- litest_dispatch(li);
- event = libinput_get_event(li);
- litest_assert_notnull(event);
- libinput_event_destroy(event);
- }
- END_TEST
- START_TEST(udev_create_empty_seat)
- {
- struct libinput_event *event;
- int fd;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- /* expect a libinput reference, but no events */
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seatdoesntexist"), 0);
- fd = libinput_get_fd(li);
- litest_assert_int_ge(fd, 0);
- litest_dispatch(li);
- event = libinput_get_event(li);
- litest_assert(event == NULL);
- libinput_event_destroy(event);
- }
- END_TEST
- START_TEST(udev_create_seat_too_long)
- {
- char seatname[258];
- memset(seatname, 'a', sizeof(seatname) - 1);
- seatname[sizeof(seatname) - 1] = '\0';
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_set_log_handler_bug(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, seatname), -1);
- litest_assert_empty_queue(li);
- }
- END_TEST
- START_TEST(udev_set_user_data)
- {
- int data1, data2;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, &data1, udev);
- litest_assert_notnull(li);
- litest_assert(libinput_get_user_data(li) == &data1);
- libinput_set_user_data(li, &data2);
- litest_assert(libinput_get_user_data(li) == &data2);
- }
- END_TEST
- START_TEST(udev_added_seat_default)
- {
- struct libinput_event *event;
- struct libinput_device *device;
- struct libinput_seat *seat;
- const char *seat_name;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_dispatch(li);
- /* Drop any events from other devices */
- litest_drain_events(li);
- /* Now create our own device, it should be in the "default"
- * logical seat. This test may fail if there is a local rule changing
- * that, but it'll be fine for the 99% case. */
- _unused_ _destroy_(litest_device) *dev =
- litest_create(LITEST_MOUSE, NULL, NULL, NULL, NULL);
- litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED);
- event = libinput_get_event(li);
- device = libinput_event_get_device(event);
- seat = libinput_device_get_seat(device);
- litest_assert_notnull(seat);
- seat_name = libinput_seat_get_logical_name(seat);
- litest_assert_str_eq(seat_name, "default");
- libinput_event_destroy(event);
- }
- END_TEST
- START_TEST(udev_change_seat)
- {
- const char *seat2_name = "new seat";
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_dispatch(li);
- /* Drop any events from other devices */
- litest_drain_events(li);
- const char *devname = "udev-change-seat device";
- /* Now create our own device, it should be in the "default"
- * logical seat. This test may fail if there is a local rule changing
- * that, but it'll be fine for the 99% case. */
- _unused_ _destroy_(litest_device) *dev =
- litest_create(LITEST_MOUSE, devname, NULL, NULL, NULL);
- _unref_(libinput_device) *device = NULL;
- _autofree_ char *seat1_name = NULL;
- while (true) {
- litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED);
- _destroy_(libinput_event) *event = libinput_get_event(li);
- struct libinput_device *d = libinput_event_get_device(event);
- const char *name = libinput_device_get_name(d);
- if (strendswith(name, devname)) {
- device = libinput_device_ref(d);
- struct libinput_seat *seat = libinput_device_get_seat(device);
- seat1_name = safe_strdup(libinput_seat_get_logical_name(seat));
- break;
- }
- }
- litest_drain_events(li);
- /* Changing the logical seat name will remove and re-add the device */
- int rc = libinput_device_set_seat_logical_name(device, seat2_name);
- litest_assert_int_eq(rc, 0);
- while (true) {
- litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_REMOVED);
- _destroy_(libinput_event) *event = libinput_get_event(li);
- litest_assert_event_type(event, LIBINPUT_EVENT_DEVICE_REMOVED);
- if (libinput_event_get_device(event) == device)
- break;
- }
- _unref_(libinput_seat) *seat2 = NULL;
- while (true) {
- litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED);
- _destroy_(libinput_event) *event = libinput_get_event(li);
- litest_assert_event_type(event, LIBINPUT_EVENT_DEVICE_ADDED);
- struct libinput_device *d = libinput_event_get_device(event);
- const char *name = libinput_device_get_name(d);
- if (strendswith(name, devname)) {
- seat2 = libinput_device_get_seat(d);
- libinput_seat_ref(seat2);
- break;
- }
- }
- litest_assert_str_ne(libinput_seat_get_logical_name(seat2), seat1_name);
- litest_assert_str_eq(libinput_seat_get_logical_name(seat2), seat2_name);
- }
- END_TEST
- START_TEST(udev_double_suspend)
- {
- struct libinput_event *event;
- int fd;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- fd = libinput_get_fd(li);
- litest_assert_int_ge(fd, 0);
- /* expect at least one event */
- litest_assert_int_ge(litest_dispatch(li), 0);
- event = libinput_get_event(li);
- litest_assert_notnull(event);
- libinput_suspend(li);
- libinput_suspend(li);
- libinput_resume(li);
- libinput_event_destroy(event);
- }
- END_TEST
- START_TEST(udev_double_resume)
- {
- struct libinput_event *event;
- int fd;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- fd = libinput_get_fd(li);
- litest_assert_int_ge(fd, 0);
- /* expect at least one event */
- litest_assert_int_ge(litest_dispatch(li), 0);
- event = libinput_get_event(li);
- litest_assert_notnull(event);
- libinput_suspend(li);
- libinput_resume(li);
- libinput_resume(li);
- libinput_event_destroy(event);
- }
- END_TEST
- static void
- process_events_count_devices(struct libinput *li, int *device_count)
- {
- struct libinput_event *event;
- while ((event = libinput_get_event(li))) {
- switch (libinput_event_get_type(event)) {
- case LIBINPUT_EVENT_DEVICE_ADDED:
- (*device_count)++;
- break;
- case LIBINPUT_EVENT_DEVICE_REMOVED:
- (*device_count)--;
- break;
- default:
- break;
- }
- libinput_event_destroy(event);
- }
- }
- START_TEST(udev_suspend_resume)
- {
- int fd;
- int num_devices = 0;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- fd = libinput_get_fd(li);
- litest_assert_int_ge(fd, 0);
- /* Check that at least one device was discovered after creation. */
- litest_assert_int_ge(litest_dispatch(li), 0);
- process_events_count_devices(li, &num_devices);
- litest_assert_int_gt(num_devices, 0);
- /* Check that after a suspend, no devices are left. */
- libinput_suspend(li);
- litest_assert_int_ge(litest_dispatch(li), 0);
- process_events_count_devices(li, &num_devices);
- litest_assert_int_eq(num_devices, 0);
- /* Check that after a resume, at least one device is discovered. */
- libinput_resume(li);
- litest_assert_int_ge(litest_dispatch(li), 0);
- process_events_count_devices(li, &num_devices);
- litest_assert_int_gt(num_devices, 0);
- }
- END_TEST
- START_TEST(udev_resume_before_seat)
- {
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- int rc = libinput_resume(li);
- litest_assert_int_eq(rc, 0);
- }
- END_TEST
- START_TEST(udev_suspend_resume_before_seat)
- {
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- libinput_suspend(li);
- int rc = libinput_resume(li);
- litest_assert_int_eq(rc, 0);
- }
- END_TEST
- START_TEST(udev_device_sysname)
- {
- struct libinput_event *ev;
- struct libinput_device *device;
- const char *sysname;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_dispatch(li);
- while ((ev = libinput_get_event(li))) {
- if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED) {
- libinput_event_destroy(ev);
- continue;
- }
- device = libinput_event_get_device(ev);
- sysname = libinput_device_get_sysname(device);
- litest_assert_notnull(sysname);
- litest_assert_int_gt(strlen(sysname), 1U);
- litest_assert(strchr(sysname, '/') == NULL);
- litest_assert(strstartswith(sysname, "event"));
- libinput_event_destroy(ev);
- }
- }
- END_TEST
- START_TEST(udev_seat_recycle)
- {
- struct libinput_event *ev;
- struct libinput_device *device;
- struct libinput_seat *saved_seat = NULL;
- struct libinput_seat *seat;
- int data = 0;
- int found = 0;
- void *user_data;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_dispatch(li);
- while ((ev = libinput_get_event(li))) {
- switch (libinput_event_get_type(ev)) {
- case LIBINPUT_EVENT_DEVICE_ADDED:
- if (saved_seat)
- break;
- device = libinput_event_get_device(ev);
- litest_assert_notnull(device);
- saved_seat = libinput_device_get_seat(device);
- libinput_seat_set_user_data(saved_seat, &data);
- libinput_seat_ref(saved_seat);
- break;
- default:
- break;
- }
- libinput_event_destroy(ev);
- }
- litest_assert_notnull(saved_seat);
- libinput_suspend(li);
- litest_drain_events(li);
- libinput_resume(li);
- litest_dispatch(li);
- while ((ev = libinput_get_event(li))) {
- switch (libinput_event_get_type(ev)) {
- case LIBINPUT_EVENT_DEVICE_ADDED:
- device = libinput_event_get_device(ev);
- litest_assert_notnull(device);
- seat = libinput_device_get_seat(device);
- user_data = libinput_seat_get_user_data(seat);
- if (user_data == &data) {
- found = 1;
- litest_assert(seat == saved_seat);
- }
- break;
- default:
- break;
- }
- libinput_event_destroy(ev);
- }
- litest_assert(found == 1);
- }
- END_TEST
- START_TEST(udev_path_add_device)
- {
- struct libinput_device *device;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_set_log_handler_bug(li);
- device = libinput_path_add_device(li, "/dev/input/event0");
- litest_assert(device == NULL);
- litest_restore_log_handler(li);
- }
- END_TEST
- START_TEST(udev_path_remove_device)
- {
- struct libinput_device *device;
- struct libinput_event *event;
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_dispatch(li);
- litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED);
- event = libinput_get_event(li);
- device = libinput_event_get_device(event);
- litest_assert_notnull(device);
- /* no effect bug a bug log msg */
- litest_set_log_handler_bug(li);
- libinput_path_remove_device(device);
- litest_restore_log_handler(li);
- libinput_event_destroy(event);
- }
- END_TEST
- START_TEST(udev_ignore_device)
- {
- struct libinput_device *device;
- struct libinput_event *event;
- const char *devname;
- _destroy_(litest_device) *dev =
- litest_create(LITEST_IGNORED_MOUSE, NULL, NULL, NULL, NULL);
- devname = libevdev_get_name(dev->evdev);
- _unref_(udev) *udev = udev_new();
- litest_assert_notnull(udev);
- _unref_(libinput) *li =
- libinput_udev_create_context(&simple_interface, NULL, udev);
- litest_assert_notnull(li);
- litest_restore_log_handler(li);
- litest_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0);
- litest_dispatch(li);
- event = libinput_get_event(li);
- litest_assert_notnull(event);
- while (event) {
- if (libinput_event_get_type(event) == LIBINPUT_EVENT_DEVICE_ADDED) {
- const char *name;
- device = libinput_event_get_device(event);
- name = libinput_device_get_name(device);
- litest_assert_str_ne(devname, name);
- }
- libinput_event_destroy(event);
- litest_dispatch(li);
- event = libinput_get_event(li);
- }
- }
- END_TEST
- TEST_COLLECTION(udev)
- {
- /* clang-format off */
- litest_add_no_device(udev_create_NULL);
- litest_add_no_device(udev_create_seat0);
- litest_add_no_device(udev_create_empty_seat);
- litest_add_no_device(udev_create_seat_too_long);
- litest_add_no_device(udev_set_user_data);
- litest_add_no_device(udev_added_seat_default);
- litest_add_no_device(udev_change_seat);
- litest_add_for_device(udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_for_device(udev_double_resume, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_for_device(udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_for_device(udev_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_for_device(udev_suspend_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_for_device(udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_for_device(udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_no_device(udev_path_add_device);
- litest_add_for_device(udev_path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220);
- litest_add_no_device(udev_ignore_device);
- /* clang-format on */
- }
|