1/* 2 * Copyright © 2013 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <config.h> 25 26#include <check.h> 27#include <errno.h> 28#include <fcntl.h> 29#include <libinput.h> 30#include <libinput-util.h> 31#include <libudev.h> 32#include <unistd.h> 33 34#include "litest.h" 35 36static int open_restricted(const char *path, int flags, void *data) 37{ 38 int fd; 39 fd = open(path, flags); 40 return fd < 0 ? -errno : fd; 41} 42static void close_restricted(int fd, void *data) 43{ 44 close(fd); 45} 46 47static const struct libinput_interface simple_interface = { 48 .open_restricted = open_restricted, 49 .close_restricted = close_restricted, 50}; 51 52START_TEST(udev_create_NULL) 53{ 54 struct libinput *li; 55 struct udev *udev; 56 57 udev = udev_new(); 58 59 li = libinput_udev_create_context(NULL, NULL, NULL); 60 ck_assert(li == NULL); 61 62 li = libinput_udev_create_context(&simple_interface, NULL, NULL); 63 ck_assert(li == NULL); 64 65 li = libinput_udev_create_context(NULL, NULL, udev); 66 ck_assert(li == NULL); 67 68 li = libinput_udev_create_context(&simple_interface, NULL, udev); 69 ck_assert_notnull(li); 70 ck_assert_int_eq(libinput_udev_assign_seat(li, NULL), -1); 71 72 libinput_unref(li); 73 udev_unref(udev); 74} 75END_TEST 76 77START_TEST(udev_create_seat0) 78{ 79 struct libinput *li; 80 struct libinput_event *event; 81 struct udev *udev; 82 int fd; 83 84 udev = udev_new(); 85 ck_assert_notnull(udev); 86 87 li = libinput_udev_create_context(&simple_interface, NULL, udev); 88 ck_assert_notnull(li); 89 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 90 91 fd = libinput_get_fd(li); 92 ck_assert_int_ge(fd, 0); 93 94 /* expect at least one event */ 95 libinput_dispatch(li); 96 event = libinput_get_event(li); 97 ck_assert_notnull(event); 98 99 libinput_event_destroy(event); 100 libinput_unref(li); 101 udev_unref(udev); 102} 103END_TEST 104 105START_TEST(udev_create_empty_seat) 106{ 107 struct libinput *li; 108 struct libinput_event *event; 109 struct udev *udev; 110 int fd; 111 112 udev = udev_new(); 113 ck_assert_notnull(udev); 114 115 /* expect a libinput reference, but no events */ 116 li = libinput_udev_create_context(&simple_interface, NULL, udev); 117 ck_assert_notnull(li); 118 ck_assert_int_eq(libinput_udev_assign_seat(li, "seatdoesntexist"), 0); 119 120 fd = libinput_get_fd(li); 121 ck_assert_int_ge(fd, 0); 122 123 libinput_dispatch(li); 124 event = libinput_get_event(li); 125 ck_assert(event == NULL); 126 127 libinput_event_destroy(event); 128 libinput_unref(li); 129 udev_unref(udev); 130} 131END_TEST 132 133START_TEST(udev_create_seat_too_long) 134{ 135 struct libinput *li; 136 struct udev *udev; 137 char seatname[258]; 138 139 memset(seatname, 'a', sizeof(seatname) - 1); 140 seatname[sizeof(seatname) - 1] = '\0'; 141 142 udev = udev_new(); 143 ck_assert_notnull(udev); 144 145 li = libinput_udev_create_context(&simple_interface, NULL, udev); 146 ck_assert_notnull(li); 147 litest_set_log_handler_bug(li); 148 149 ck_assert_int_eq(libinput_udev_assign_seat(li, seatname), -1); 150 151 litest_assert_empty_queue(li); 152 153 libinput_unref(li); 154 udev_unref(udev); 155} 156END_TEST 157 158START_TEST(udev_set_user_data) 159{ 160 struct libinput *li; 161 struct udev *udev; 162 int data1, data2; 163 164 udev = udev_new(); 165 ck_assert_notnull(udev); 166 167 li = libinput_udev_create_context(&simple_interface, &data1, udev); 168 ck_assert_notnull(li); 169 ck_assert(libinput_get_user_data(li) == &data1); 170 libinput_set_user_data(li, &data2); 171 ck_assert(libinput_get_user_data(li) == &data2); 172 173 libinput_unref(li); 174 udev_unref(udev); 175} 176END_TEST 177 178START_TEST(udev_added_seat_default) 179{ 180 struct libinput *li; 181 struct libinput_event *event; 182 struct udev *udev; 183 struct libinput_device *device; 184 struct libinput_seat *seat; 185 const char *seat_name; 186 struct litest_device *dev; 187 188 udev = udev_new(); 189 ck_assert_notnull(udev); 190 191 li = libinput_udev_create_context(&simple_interface, NULL, udev); 192 ck_assert_notnull(li); 193 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 194 libinput_dispatch(li); 195 196 /* Drop any events from other devices */ 197 litest_drain_events(li); 198 199 /* Now create our own device, it should be in the "default" 200 * logical seat. This test may fail if there is a local rule changing 201 * that, but it'll be fine for the 99% case. */ 202 dev = litest_create(LITEST_MOUSE, NULL, NULL, NULL, NULL); 203 litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED, -1); 204 event = libinput_get_event(li); 205 device = libinput_event_get_device(event); 206 seat = libinput_device_get_seat(device); 207 ck_assert_notnull(seat); 208 209 seat_name = libinput_seat_get_logical_name(seat); 210 ck_assert_str_eq(seat_name, "default"); 211 libinput_event_destroy(event); 212 213 libinput_unref(li); 214 udev_unref(udev); 215 216 litest_delete_device(dev); 217} 218END_TEST 219 220START_TEST(udev_change_seat) 221{ 222 struct libinput *li; 223 struct udev *udev; 224 struct libinput_event *event; 225 struct libinput_device *device; 226 struct libinput_seat *seat1, *seat2; 227 const char *seat1_name; 228 const char *seat2_name = "new seat"; 229 int rc; 230 struct litest_device *dev; 231 232 udev = udev_new(); 233 ck_assert_notnull(udev); 234 235 li = libinput_udev_create_context(&simple_interface, NULL, udev); 236 ck_assert_notnull(li); 237 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 238 libinput_dispatch(li); 239 240 /* Drop any events from other devices */ 241 litest_drain_events(li); 242 243 /* Now create our own device, it should be in the "default" 244 * logical seat. This test may fail if there is a local rule changing 245 * that, but it'll be fine for the 99% case. */ 246 dev = litest_create(LITEST_MOUSE, NULL, NULL, NULL, NULL); 247 litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED, -1); 248 event = libinput_get_event(li); 249 device = libinput_event_get_device(event); 250 libinput_device_ref(device); 251 252 seat1 = libinput_device_get_seat(device); 253 libinput_seat_ref(seat1); 254 255 seat1_name = libinput_seat_get_logical_name(seat1); 256 libinput_event_destroy(event); 257 258 litest_drain_events(li); 259 260 /* Changing the logical seat name will remove and re-add the device */ 261 rc = libinput_device_set_seat_logical_name(device, 262 seat2_name); 263 ck_assert_int_eq(rc, 0); 264 265 libinput_dispatch(li); 266 267 event = libinput_get_event(li); 268 ck_assert_int_eq(libinput_event_get_type(event), 269 LIBINPUT_EVENT_DEVICE_REMOVED); 270 271 ck_assert(libinput_event_get_device(event) == device); 272 libinput_event_destroy(event); 273 274 event = libinput_get_event(li); 275 ck_assert_int_eq(libinput_event_get_type(event), 276 LIBINPUT_EVENT_DEVICE_ADDED); 277 ck_assert(libinput_event_get_device(event) != device); 278 libinput_device_unref(device); 279 280 device = libinput_event_get_device(event); 281 seat2 = libinput_device_get_seat(device); 282 283 ck_assert_str_ne(libinput_seat_get_logical_name(seat2), 284 seat1_name); 285 ck_assert_str_eq(libinput_seat_get_logical_name(seat2), 286 seat2_name); 287 libinput_event_destroy(event); 288 289 libinput_seat_unref(seat1); 290 291 libinput_unref(li); 292 udev_unref(udev); 293 294 litest_delete_device(dev); 295} 296END_TEST 297 298START_TEST(udev_double_suspend) 299{ 300 struct libinput *li; 301 struct libinput_event *event; 302 struct udev *udev; 303 int fd; 304 305 udev = udev_new(); 306 ck_assert_notnull(udev); 307 308 li = libinput_udev_create_context(&simple_interface, NULL, udev); 309 ck_assert_notnull(li); 310 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 311 312 fd = libinput_get_fd(li); 313 ck_assert_int_ge(fd, 0); 314 315 /* expect at least one event */ 316 ck_assert_int_ge(libinput_dispatch(li), 0); 317 event = libinput_get_event(li); 318 ck_assert_notnull(event); 319 320 libinput_suspend(li); 321 libinput_suspend(li); 322 libinput_resume(li); 323 324 libinput_event_destroy(event); 325 libinput_unref(li); 326 udev_unref(udev); 327} 328END_TEST 329 330START_TEST(udev_double_resume) 331{ 332 struct libinput *li; 333 struct libinput_event *event; 334 struct udev *udev; 335 int fd; 336 337 udev = udev_new(); 338 ck_assert_notnull(udev); 339 340 li = libinput_udev_create_context(&simple_interface, NULL, udev); 341 ck_assert_notnull(li); 342 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 343 344 fd = libinput_get_fd(li); 345 ck_assert_int_ge(fd, 0); 346 347 /* expect at least one event */ 348 ck_assert_int_ge(libinput_dispatch(li), 0); 349 event = libinput_get_event(li); 350 ck_assert_notnull(event); 351 352 libinput_suspend(li); 353 libinput_resume(li); 354 libinput_resume(li); 355 356 libinput_event_destroy(event); 357 libinput_unref(li); 358 udev_unref(udev); 359} 360END_TEST 361 362static void 363process_events_count_devices(struct libinput *li, int *device_count) 364{ 365 struct libinput_event *event; 366 367 while ((event = libinput_get_event(li))) { 368 switch (libinput_event_get_type(event)) { 369 case LIBINPUT_EVENT_DEVICE_ADDED: 370 (*device_count)++; 371 break; 372 case LIBINPUT_EVENT_DEVICE_REMOVED: 373 (*device_count)--; 374 break; 375 default: 376 break; 377 } 378 libinput_event_destroy(event); 379 } 380} 381 382START_TEST(udev_suspend_resume) 383{ 384 struct libinput *li; 385 struct udev *udev; 386 int fd; 387 int num_devices = 0; 388 389 udev = udev_new(); 390 ck_assert_notnull(udev); 391 392 li = libinput_udev_create_context(&simple_interface, NULL, udev); 393 ck_assert_notnull(li); 394 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 395 396 fd = libinput_get_fd(li); 397 ck_assert_int_ge(fd, 0); 398 399 /* Check that at least one device was discovered after creation. */ 400 ck_assert_int_ge(libinput_dispatch(li), 0); 401 process_events_count_devices(li, &num_devices); 402 ck_assert_int_gt(num_devices, 0); 403 404 /* Check that after a suspend, no devices are left. */ 405 libinput_suspend(li); 406 ck_assert_int_ge(libinput_dispatch(li), 0); 407 process_events_count_devices(li, &num_devices); 408 ck_assert_int_eq(num_devices, 0); 409 410 /* Check that after a resume, at least one device is discovered. */ 411 libinput_resume(li); 412 ck_assert_int_ge(libinput_dispatch(li), 0); 413 process_events_count_devices(li, &num_devices); 414 ck_assert_int_gt(num_devices, 0); 415 416 libinput_unref(li); 417 udev_unref(udev); 418} 419END_TEST 420 421START_TEST(udev_resume_before_seat) 422{ 423 struct libinput *li; 424 struct udev *udev; 425 int rc; 426 427 udev = udev_new(); 428 ck_assert_notnull(udev); 429 430 li = libinput_udev_create_context(&simple_interface, NULL, udev); 431 ck_assert_notnull(li); 432 433 rc = libinput_resume(li); 434 ck_assert_int_eq(rc, 0); 435 436 libinput_unref(li); 437 udev_unref(udev); 438} 439END_TEST 440 441START_TEST(udev_suspend_resume_before_seat) 442{ 443 struct libinput *li; 444 struct udev *udev; 445 int rc; 446 447 udev = udev_new(); 448 ck_assert_notnull(udev); 449 450 li = libinput_udev_create_context(&simple_interface, NULL, udev); 451 ck_assert_notnull(li); 452 453 libinput_suspend(li); 454 rc = libinput_resume(li); 455 ck_assert_int_eq(rc, 0); 456 457 libinput_unref(li); 458 udev_unref(udev); 459} 460END_TEST 461 462START_TEST(udev_device_sysname) 463{ 464 struct libinput *li; 465 struct libinput_event *ev; 466 struct libinput_device *device; 467 const char *sysname; 468 struct udev *udev; 469 470 udev = udev_new(); 471 ck_assert_notnull(udev); 472 473 li = libinput_udev_create_context(&simple_interface, NULL, udev); 474 ck_assert_notnull(li); 475 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 476 477 libinput_dispatch(li); 478 479 while ((ev = libinput_get_event(li))) { 480 if (libinput_event_get_type(ev) != 481 LIBINPUT_EVENT_DEVICE_ADDED) { 482 libinput_event_destroy(ev); 483 continue; 484 } 485 486 device = libinput_event_get_device(ev); 487 sysname = libinput_device_get_sysname(device); 488 ck_assert_notnull(sysname); 489 ck_assert_int_gt(strlen(sysname), 1); 490 ck_assert(strchr(sysname, '/') == NULL); 491 ck_assert(strneq(sysname, "event", 5)); 492 libinput_event_destroy(ev); 493 } 494 495 libinput_unref(li); 496 udev_unref(udev); 497} 498END_TEST 499 500START_TEST(udev_seat_recycle) 501{ 502 struct udev *udev; 503 struct libinput *li; 504 struct libinput_event *ev; 505 struct libinput_device *device; 506 struct libinput_seat *saved_seat = NULL; 507 struct libinput_seat *seat; 508 int data = 0; 509 int found = 0; 510 void *user_data; 511 512 udev = udev_new(); 513 ck_assert_notnull(udev); 514 515 li = libinput_udev_create_context(&simple_interface, NULL, udev); 516 ck_assert_notnull(li); 517 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 518 519 libinput_dispatch(li); 520 while ((ev = libinput_get_event(li))) { 521 switch (libinput_event_get_type(ev)) { 522 case LIBINPUT_EVENT_DEVICE_ADDED: 523 if (saved_seat) 524 break; 525 526 device = libinput_event_get_device(ev); 527 ck_assert_notnull(device); 528 saved_seat = libinput_device_get_seat(device); 529 libinput_seat_set_user_data(saved_seat, &data); 530 libinput_seat_ref(saved_seat); 531 break; 532 default: 533 break; 534 } 535 536 libinput_event_destroy(ev); 537 } 538 539 ck_assert_notnull(saved_seat); 540 541 libinput_suspend(li); 542 543 litest_drain_events(li); 544 545 libinput_resume(li); 546 547 libinput_dispatch(li); 548 while ((ev = libinput_get_event(li))) { 549 switch (libinput_event_get_type(ev)) { 550 case LIBINPUT_EVENT_DEVICE_ADDED: 551 device = libinput_event_get_device(ev); 552 ck_assert_notnull(device); 553 554 seat = libinput_device_get_seat(device); 555 user_data = libinput_seat_get_user_data(seat); 556 if (user_data == &data) { 557 found = 1; 558 ck_assert(seat == saved_seat); 559 } 560 break; 561 default: 562 break; 563 } 564 565 libinput_event_destroy(ev); 566 } 567 568 ck_assert(found == 1); 569 570 libinput_unref(li); 571 udev_unref(udev); 572} 573END_TEST 574 575START_TEST(udev_path_add_device) 576{ 577 struct udev *udev; 578 struct libinput *li; 579 struct libinput_device *device; 580 581 udev = udev_new(); 582 ck_assert_notnull(udev); 583 584 li = libinput_udev_create_context(&simple_interface, NULL, udev); 585 ck_assert_notnull(li); 586 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 587 588 litest_set_log_handler_bug(li); 589 device = libinput_path_add_device(li, "/dev/input/event0"); 590 ck_assert(device == NULL); 591 litest_restore_log_handler(li); 592 593 libinput_unref(li); 594 udev_unref(udev); 595} 596END_TEST 597 598START_TEST(udev_path_remove_device) 599{ 600 struct udev *udev; 601 struct libinput *li; 602 struct libinput_device *device; 603 struct libinput_event *event; 604 605 udev = udev_new(); 606 ck_assert_notnull(udev); 607 608 li = libinput_udev_create_context(&simple_interface, NULL, udev); 609 ck_assert_notnull(li); 610 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 611 libinput_dispatch(li); 612 613 litest_wait_for_event_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED, -1); 614 event = libinput_get_event(li); 615 device = libinput_event_get_device(event); 616 ck_assert_notnull(device); 617 618 /* no effect bug a bug log msg */ 619 litest_set_log_handler_bug(li); 620 libinput_path_remove_device(device); 621 litest_restore_log_handler(li); 622 623 libinput_event_destroy(event); 624 libinput_unref(li); 625 udev_unref(udev); 626} 627END_TEST 628 629START_TEST(udev_ignore_device) 630{ 631 struct udev *udev; 632 struct libinput *li; 633 struct libinput_device *device; 634 struct libinput_event *event; 635 struct litest_device *dev; 636 const char *devname; 637 638 dev = litest_create(LITEST_IGNORED_MOUSE, NULL, NULL, NULL, NULL); 639 devname = libevdev_get_name(dev->evdev); 640 641 udev = udev_new(); 642 ck_assert_notnull(udev); 643 644 li = libinput_udev_create_context(&simple_interface, NULL, udev); 645 ck_assert_notnull(li); 646 litest_restore_log_handler(li); 647 648 ck_assert_int_eq(libinput_udev_assign_seat(li, "seat0"), 0); 649 libinput_dispatch(li); 650 651 event = libinput_get_event(li); 652 ck_assert_notnull(event); 653 while (event) { 654 if (libinput_event_get_type(event) == 655 LIBINPUT_EVENT_DEVICE_ADDED) { 656 const char *name; 657 658 device = libinput_event_get_device(event); 659 name = libinput_device_get_name(device); 660 ck_assert_str_ne(devname, name); 661 } 662 libinput_event_destroy(event); 663 libinput_dispatch(li); 664 event = libinput_get_event(li); 665 } 666 667 libinput_unref(li); 668 udev_unref(udev); 669 670 litest_delete_device(dev); 671} 672END_TEST 673 674TEST_COLLECTION(udev) 675{ 676 litest_add_no_device(udev_create_NULL); 677 litest_add_no_device(udev_create_seat0); 678 litest_add_no_device(udev_create_empty_seat); 679 litest_add_no_device(udev_create_seat_too_long); 680 litest_add_no_device(udev_set_user_data); 681 682 litest_add_no_device(udev_added_seat_default); 683 litest_add_no_device(udev_change_seat); 684 685 litest_add_for_device(udev_double_suspend, LITEST_SYNAPTICS_CLICKPAD_X220); 686 litest_add_for_device(udev_double_resume, LITEST_SYNAPTICS_CLICKPAD_X220); 687 litest_add_for_device(udev_suspend_resume, LITEST_SYNAPTICS_CLICKPAD_X220); 688 litest_add_for_device(udev_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220); 689 litest_add_for_device(udev_suspend_resume_before_seat, LITEST_SYNAPTICS_CLICKPAD_X220); 690 litest_add_for_device(udev_device_sysname, LITEST_SYNAPTICS_CLICKPAD_X220); 691 litest_add_for_device(udev_seat_recycle, LITEST_SYNAPTICS_CLICKPAD_X220); 692 693 litest_add_no_device(udev_path_add_device); 694 litest_add_for_device(udev_path_remove_device, LITEST_SYNAPTICS_CLICKPAD_X220); 695 696 litest_add_no_device(udev_ignore_device); 697} 698