From c4a21a4e9e2e2f13ae7a7c180710728d4adab557 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 15:27:49 +1000 Subject: [PATCH 01/13] test: make the valgrind test an actual dependency of the test run With parallel builds the valgrind test run would run at the same time as the normal run, the test suite isn't designed for that. Signed-off-by: Peter Hutterer --- test/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile.am b/test/Makefile.am index 4562455b..fda0c5dc 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -206,7 +206,7 @@ VALGRIND_FLAGS=--leak-check=full \ --error-exitcode=3 \ --suppressions=$(srcdir)/valgrind.suppressions -valgrind: all +valgrind: check-am $(MAKE) check-TESTS TEST_SUITE_LOG="test-suite-valgrind.log" LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)" CK_FORK=no USING_VALGRIND=yes check: valgrind From bc76bd6f77b027e6f52933da6c875a6c1d1eb187 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 13:23:35 +1000 Subject: [PATCH 02/13] test: store created udev rules in a list for easier deletion Easier to clean up than knowing all the destination paths we'll install. Only affects global udev rules so far. Signed-off-by: Peter Hutterer --- test/litest.c | 79 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/test/litest.c b/test/litest.c index 9a274fa2..3875dd0c 100644 --- a/test/litest.c +++ b/test/litest.c @@ -68,8 +68,13 @@ const char *filter_test = NULL; const char *filter_device = NULL; const char *filter_group = NULL; -static inline void litest_remove_model_quirks(void); -static void litest_init_udev_rules(void); +struct created_file { + struct list link; + char *path; +}; + +static void litest_init_udev_rules(struct list *created_files_list); +static void litest_remove_udev_rules(struct list *created_files_list); /* defined for the litest selftest */ #ifndef LITEST_DISABLE_BACKTRACE_LOGGING @@ -866,6 +871,9 @@ litest_run(int argc, char **argv) struct suite *s, *snext; int failed; SRunner *sr = NULL; + struct list created_files_list; + + list_init(&created_files_list); if (list_empty(&all_tests)) { fprintf(stderr, @@ -889,7 +897,7 @@ litest_run(int argc, char **argv) if (getenv("LITEST_VERBOSE")) verbose = 1; - litest_init_udev_rules(); + litest_init_udev_rules(&created_files_list); srunner_run_all(sr, CK_ENV); failed = srunner_ntests_failed(sr); @@ -909,8 +917,7 @@ litest_run(int argc, char **argv) free(s); } - litest_remove_model_quirks(); - litest_reload_udev_rules(); + litest_remove_udev_rules(&created_files_list); return failed; } @@ -984,10 +991,16 @@ merge_events(const int *orig, const int *override) return events; } -static inline void +static inline struct created_file * litest_copy_file(const char *dest, const char *src, const char *header) { int in, out, length; + struct created_file *file; + + file = zalloc(sizeof(*file)); + litest_assert(file); + file->path = strdup(dest); + litest_assert(file->path); out = open(dest, O_CREAT|O_WRONLY, 0644); litest_assert_int_gt(out, -1); @@ -1003,10 +1016,12 @@ litest_copy_file(const char *dest, const char *src, const char *header) litest_assert_int_gt(sendfile(out, in, NULL, 40960), 0); close(out); close(in); + + return file; } static inline void -litest_install_model_quirks(void) +litest_install_model_quirks(struct list *created_files_list) { const char *warning = "#################################################################\n" @@ -1016,27 +1031,26 @@ litest_install_model_quirks(void) "# running, remove this file and update your hwdb: \n" "# sudo udevadm hwdb --update\n" "#################################################################\n\n"; - litest_copy_file(UDEV_MODEL_QUIRKS_RULE_FILE, - LIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE, - warning); - litest_copy_file(UDEV_MODEL_QUIRKS_HWDB_FILE, - LIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE, - warning); - litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE, - LIBINPUT_TEST_DEVICE_RULES_FILE, - warning); -} + struct created_file *file; -static inline void -litest_remove_model_quirks(void) -{ - unlink(UDEV_MODEL_QUIRKS_RULE_FILE); - unlink(UDEV_MODEL_QUIRKS_HWDB_FILE); - unlink(UDEV_TEST_DEVICE_RULE_FILE); + file = litest_copy_file(UDEV_MODEL_QUIRKS_RULE_FILE, + LIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE, + warning); + list_insert(created_files_list, &file->link); + + file = litest_copy_file(UDEV_MODEL_QUIRKS_HWDB_FILE, + LIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE, + warning); + list_insert(created_files_list, &file->link); + + file = litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE, + LIBINPUT_TEST_DEVICE_RULES_FILE, + warning); + list_insert(created_files_list, &file->link); } static void -litest_init_udev_rules(void) +litest_init_udev_rules(struct list *created_files) { int rc; @@ -1050,7 +1064,22 @@ litest_init_udev_rules(void) ck_abort_msg("Failed to create udev hwdb directory (%s)\n", strerror(errno)); - litest_install_model_quirks(); + litest_install_model_quirks(created_files); + litest_reload_udev_rules(); +} + +static void +litest_remove_udev_rules(struct list *created_files_list) +{ + struct created_file *f, *tmp; + + list_for_each_safe(f, tmp, created_files_list, link) { + list_remove(&f->link); + unlink(f->path); + free(f->path); + free(f); + } + litest_reload_udev_rules(); } From 35b28b1af3a7f6b58ec93286a2ab1de7c8ecb5aa Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 13:16:49 +1000 Subject: [PATCH 03/13] test: merge all tests into a single binary Call it a libinput-test-suite-runner, in subsequent patches we'll handle doing parallel tests ourselves instead of relying on automake features. Signed-off-by: Peter Hutterer --- doc/test-suite.dox | 14 +++--- test/Makefile.am | 102 +++++++++------------------------------- test/device.c | 2 +- test/gestures.c | 2 +- test/keyboard.c | 2 +- test/litest.c | 17 ++++++- test/litest.h | 20 ++++++-- test/log.c | 2 +- test/misc.c | 2 +- test/pad.c | 2 +- test/path.c | 2 +- test/pointer.c | 2 +- test/tablet.c | 2 +- test/touch.c | 2 +- test/touchpad-buttons.c | 2 +- test/touchpad-tap.c | 2 +- test/touchpad.c | 2 +- test/trackball.c | 2 +- test/trackpoint.c | 2 +- test/udev.c | 2 +- 20 files changed, 77 insertions(+), 108 deletions(-) diff --git a/doc/test-suite.dox b/doc/test-suite.dox index 30dd1579..104e2a91 100644 --- a/doc/test-suite.dox +++ b/doc/test-suite.dox @@ -4,8 +4,8 @@ The libinput test suite is based on [Check](http://check.sourceforge.net/doc/check_html/) and runs automatically during `make check`. Check itself is wrapped into a libinput-specific test -suite called *litest*. Tests are found in `$srcdir/test/`, the test binaries are -prefixed with `test-` and can be run individually. +suite called *litest*. Tests are found in `$srcdir/test/`, the main test +suite is `libinput-test-suite-runner`. @section test-config X.Org config to avoid interference @@ -30,7 +30,7 @@ litest's tests are grouped by test groups and devices. A test group is e.g. Each test function is (usually) run with one or more specific devices. The `--list` commandline argument shows the list of suites and tests. @code -$ ./test/test-device --list +$ ./test/libinput-test-suite-runner --list device:wheel: wheel only blackwidow @@ -56,7 +56,7 @@ The `--filter-test` argument enables selective running of tests through basic shell-style function name matching. For example: @code -$ ./test/test-touchpad --filter-test="*1fg_tap*" +$ ./test/libinput-test-suite-runner --filter-test="*1fg_tap*" @endcode The `--filter-device` argument enables selective running of tests through @@ -64,7 +64,7 @@ basic shell-style device name matching. The device names matched are the litest-specific shortnames, see the output of `--list`. For example: @code -$ ./test/test-touchpad --filter-device="synaptics*" +$ ./test/libinput-test-suite-runner --filter-device="synaptics*" @endcode The `--filter-group` argument enables selective running of test groups @@ -72,7 +72,7 @@ through basic shell-style test group matching. The test groups matched are litest-specific test groups, see the output of `--list`. For example: @code -$ ./test/test-touchpad --filter-group="touchpad:*hover*" +$ ./test/libinput-test-suite-runner --filter-group="touchpad:*hover*" @endcode The `--filter-device` and `--filter-group` arguments can be combined with @@ -85,7 +85,7 @@ output, see libinput_log_set_priority() for details. The `LITEST_VERBOSE` environment variable, if set, also enables verbose mode. @code -$ ./test/test-device --verbose +$ ./test/libinput-test-suite-runner --verbose $ LITEST_VERBOSE=1 make check @endcode diff --git a/test/Makefile.am b/test/Makefile.am index fda0c5dc..32e379af 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -77,24 +77,8 @@ liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS) endif -run_tests = \ - test-touchpad \ - test-touchpad-tap \ - test-touchpad-buttons \ - test-pad \ - test-tablet \ - test-device \ - test-gestures \ - test-pointer \ - test-touch \ - test-trackball \ - test-trackpoint \ - test-udev \ - test-path \ - test-log \ - test-misc \ - test-keyboard \ - test-litest-selftest +run_tests = libinput-test-suite-runner \ + test-litest-selftest build_tests = \ test-build-cxx \ @@ -108,70 +92,26 @@ TESTS = $(run_tests) symbols-leak-test .NOTPARALLEL: -test_udev_SOURCES = udev.c -test_udev_LDADD = $(TEST_LIBS) -test_udev_LDFLAGS = -no-install +libinput_test_suite_runner_SOURCES = udev.c \ + path.c \ + pointer.c \ + touch.c \ + log.c \ + tablet.c \ + pad.c \ + touchpad.c \ + touchpad-tap.c \ + touchpad-buttons.c \ + trackpoint.c \ + trackball.c \ + misc.c \ + keyboard.c \ + device.c \ + gestures.c -test_path_SOURCES = path.c -test_path_LDADD = $(TEST_LIBS) -test_path_LDFLAGS = -no-install - -test_pointer_SOURCES = pointer.c -test_pointer_LDADD = $(TEST_LIBS) -test_pointer_LDFLAGS = -no-install - -test_touch_SOURCES = touch.c -test_touch_LDADD = $(TEST_LIBS) -test_touch_LDFLAGS = -no-install - -test_log_SOURCES = log.c -test_log_LDADD = $(TEST_LIBS) -test_log_LDFLAGS = -no-install - -test_tablet_SOURCES = tablet.c -test_tablet_LDADD = $(TEST_LIBS) -test_tablet_LDFLAGS = -static - -test_pad_SOURCES = pad.c -test_pad_LDADD = $(TEST_LIBS) -test_pad_LDFLAGS = -static - -test_touchpad_SOURCES = touchpad.c -test_touchpad_LDADD = $(TEST_LIBS) -test_touchpad_LDFLAGS = -no-install - -test_touchpad_tap_SOURCES = touchpad-tap.c -test_touchpad_tap_LDADD = $(TEST_LIBS) -test_touchpad_tap_LDFLAGS = -no-install - -test_touchpad_buttons_SOURCES = touchpad-buttons.c -test_touchpad_buttons_LDADD = $(TEST_LIBS) -test_touchpad_buttons_LDFLAGS = -no-install - -test_trackpoint_SOURCES = trackpoint.c -test_trackpoint_LDADD = $(TEST_LIBS) -test_trackpoint_LDFLAGS = -no-install - -test_trackball_SOURCES = trackball.c -test_trackball_LDADD = $(TEST_LIBS) -test_trackball_LDFLAGS = -no-install - -test_misc_SOURCES = misc.c -test_misc_CFLAGS= $(AM_CFLAGS) -DLIBINPUT_LT_VERSION="\"$(LIBINPUT_LT_VERSION)\"" -test_misc_LDADD = $(TEST_LIBS) -test_misc_LDFLAGS = -no-install - -test_keyboard_SOURCES = keyboard.c -test_keyboard_LDADD = $(TEST_LIBS) -test_keyboard_LDFLAGS = -no-install - -test_device_SOURCES = device.c -test_device_LDADD = $(TEST_LIBS) -test_device_LDFLAGS = -no-install - -test_gestures_SOURCES = gestures.c -test_gestures_LDADD = $(TEST_LIBS) -test_gestures_LDFLAGS = -no-install +libinput_test_suite_runner_CFLAGS = $(AM_CFLAGS) -DLIBINPUT_LT_VERSION="\"$(LIBINPUT_LT_VERSION)\"" +libinput_test_suite_runner_LDADD = $(TEST_LIBS) +libinput_test_suite_runner_LDFLAGS = -no-install test_litest_selftest_SOURCES = litest-selftest.c litest.c litest-int.h litest.h test_litest_selftest_CFLAGS = -DLITEST_DISABLE_BACKTRACE_LOGGING -DLITEST_NO_MAIN $(liblitest_la_CFLAGS) diff --git a/test/device.c b/test/device.c index 809d8cf6..01f794f2 100644 --- a/test/device.c +++ b/test/device.c @@ -1347,7 +1347,7 @@ START_TEST(device_quirks_apple_magicmouse) END_TEST void -litest_setup_tests(void) +litest_setup_tests_device(void) { struct range abs_range = { 0, ABS_MISC }; struct range abs_mt_range = { ABS_MT_SLOT + 1, ABS_CNT }; diff --git a/test/gestures.c b/test/gestures.c index fa280a43..0b132c30 100644 --- a/test/gestures.c +++ b/test/gestures.c @@ -1215,7 +1215,7 @@ START_TEST(gestures_3fg_buttonarea_scroll_btntool) END_TEST void -litest_setup_tests(void) +litest_setup_tests_gestures(void) { /* N, NE, ... */ struct range cardinals = { 0, 8 }; diff --git a/test/keyboard.c b/test/keyboard.c index f3aa9df4..780506aa 100644 --- a/test/keyboard.c +++ b/test/keyboard.c @@ -379,7 +379,7 @@ START_TEST(keyboard_no_buttons) END_TEST void -litest_setup_tests(void) +litest_setup_tests_keyboard(void) { litest_add_no_device("keyboard:seat key count", keyboard_seat_key_count); litest_add_no_device("keyboard:key counting", keyboard_ignore_no_pressed_release); diff --git a/test/litest.c b/test/litest.c index 3875dd0c..2187901a 100644 --- a/test/litest.c +++ b/test/litest.c @@ -3143,7 +3143,22 @@ main(int argc, char **argv) if (mode == LITEST_MODE_ERROR) return EXIT_FAILURE; - litest_setup_tests(); + litest_setup_tests_udev(); + litest_setup_tests_path(); + litest_setup_tests_pointer(); + litest_setup_tests_touch(); + litest_setup_tests_log(); + litest_setup_tests_tablet(); + litest_setup_tests_pad(); + litest_setup_tests_touchpad(); + litest_setup_tests_touchpad_tap(); + litest_setup_tests_touchpad_buttons(); + litest_setup_tests_trackpoint(); + litest_setup_tests_trackball(); + litest_setup_tests_misc(); + litest_setup_tests_keyboard(); + litest_setup_tests_device(); + litest_setup_tests_gestures(); if (mode == LITEST_MODE_LIST) { litest_list_tests(&all_tests); diff --git a/test/litest.h b/test/litest.h index bf50e8cb..2ada8f66 100644 --- a/test/litest.h +++ b/test/litest.h @@ -35,6 +35,23 @@ #include #include +extern void litest_setup_tests_udev(void); +extern void litest_setup_tests_path(void); +extern void litest_setup_tests_pointer(void); +extern void litest_setup_tests_touch(void); +extern void litest_setup_tests_log(void); +extern void litest_setup_tests_tablet(void); +extern void litest_setup_tests_pad(void); +extern void litest_setup_tests_touchpad(void); +extern void litest_setup_tests_touchpad_tap(void); +extern void litest_setup_tests_touchpad_buttons(void); +extern void litest_setup_tests_trackpoint(void); +extern void litest_setup_tests_trackball(void); +extern void litest_setup_tests_misc(void); +extern void litest_setup_tests_keyboard(void); +extern void litest_setup_tests_device(void); +extern void litest_setup_tests_gestures(void); + void litest_fail_condition(const char *file, int line, @@ -334,9 +351,6 @@ _litest_add_ranged_no_device(const char *name, void *func, const struct range *range); -extern void -litest_setup_tests(void); - struct litest_device * litest_create_device(enum litest_device_type which); diff --git a/test/log.c b/test/log.c index 908af7e4..9dca1520 100644 --- a/test/log.c +++ b/test/log.c @@ -141,7 +141,7 @@ START_TEST(log_priority) END_TEST void -litest_setup_tests(void) +litest_setup_tests_log(void) { litest_add_no_device("log:defaults", log_default_priority); litest_add_no_device("log:logging", log_handler_invoked); diff --git a/test/misc.c b/test/misc.c index dec4ee4c..791ebc37 100644 --- a/test/misc.c +++ b/test/misc.c @@ -935,7 +935,7 @@ START_TEST(library_version) END_TEST void -litest_setup_tests(void) +litest_setup_tests_misc(void) { litest_add_no_device("events:conversion", event_conversion_device_notify); litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE); diff --git a/test/pad.c b/test/pad.c index 67caa71b..e2651e68 100644 --- a/test/pad.c +++ b/test/pad.c @@ -632,7 +632,7 @@ START_TEST(pad_mode_group_has_no_toggle) END_TEST void -litest_setup_tests(void) +litest_setup_tests_pad(void) { litest_add("pad:cap", pad_cap, LITEST_TABLET_PAD, LITEST_ANY); litest_add("pad:cap", pad_no_cap, LITEST_ANY, LITEST_TABLET_PAD); diff --git a/test/path.c b/test/path.c index 21b5fa08..221c1752 100644 --- a/test/path.c +++ b/test/path.c @@ -938,7 +938,7 @@ START_TEST(path_seat_recycle) END_TEST void -litest_setup_tests(void) +litest_setup_tests_path(void) { litest_add_no_device("path:create", path_create_NULL); litest_add_no_device("path:create", path_create_invalid); diff --git a/test/pointer.c b/test/pointer.c index f8651a7a..ac67ab9e 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -1723,7 +1723,7 @@ START_TEST(pointer_time_usec) END_TEST void -litest_setup_tests(void) +litest_setup_tests_pointer(void) { struct range axis_range = {ABS_X, ABS_Y + 1}; struct range compass = {0, 7}; /* cardinal directions */ diff --git a/test/tablet.c b/test/tablet.c index 04eb3078..b91d5cb1 100644 --- a/test/tablet.c +++ b/test/tablet.c @@ -3676,7 +3676,7 @@ START_TEST(relative_calibration) END_TEST void -litest_setup_tests(void) +litest_setup_tests_tablet(void) { litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add_no_device("tablet:tool", tool_capabilities); diff --git a/test/touch.c b/test/touch.c index cc1cfb27..ac2f29f4 100644 --- a/test/touch.c +++ b/test/touch.c @@ -720,7 +720,7 @@ START_TEST(touch_fuzz) END_TEST void -litest_setup_tests(void) +litest_setup_tests_touch(void) { struct range axes = { ABS_X, ABS_Y + 1}; diff --git a/test/touchpad-buttons.c b/test/touchpad-buttons.c index d72278b1..2beb637f 100644 --- a/test/touchpad-buttons.c +++ b/test/touchpad-buttons.c @@ -1805,7 +1805,7 @@ START_TEST(clickpad_middleemulation_click_disable_while_down) END_TEST void -litest_setup_tests(void) +litest_setup_tests_touchpad_buttons(void) { litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger_no_touch, LITEST_CLICKPAD, LITEST_ANY); diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index 8383aa93..d09189f4 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -1959,7 +1959,7 @@ START_TEST(touchpad_drag_lock_default_unavailable) END_TEST void -litest_setup_tests(void) +litest_setup_tests_touchpad_tap(void) { struct range multitap_range = {3, 8}; diff --git a/test/touchpad.c b/test/touchpad.c index 57e47123..fe685c1e 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -4136,7 +4136,7 @@ START_TEST(touchpad_jump_finger_motion) END_TEST void -litest_setup_tests(void) +litest_setup_tests_touchpad(void) { struct range axis_range = {ABS_X, ABS_Y + 1}; diff --git a/test/trackball.c b/test/trackball.c index d3238cfd..28639ad0 100644 --- a/test/trackball.c +++ b/test/trackball.c @@ -260,7 +260,7 @@ START_TEST(trackball_rotation_accel) END_TEST void -litest_setup_tests(void) +litest_setup_tests_trackball(void) { litest_add("trackball:rotation", trackball_rotation_config_defaults, LITEST_TRACKBALL, LITEST_ANY); litest_add("trackball:rotation", trackball_rotation_config_invalid_range, LITEST_TRACKBALL, LITEST_ANY); diff --git a/test/trackpoint.c b/test/trackpoint.c index 4098f6f0..a9d01c41 100644 --- a/test/trackpoint.c +++ b/test/trackpoint.c @@ -281,7 +281,7 @@ START_TEST(trackpoint_topsoftbuttons_left_handed_both) END_TEST void -litest_setup_tests(void) +litest_setup_tests_trackpoint(void) { litest_add("trackpoint:middlebutton", trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY); litest_add("trackpoint:middlebutton", trackpoint_middlebutton_noscroll, LITEST_POINTINGSTICK, LITEST_ANY); diff --git a/test/udev.c b/test/udev.c index 7c294c59..5a74436b 100644 --- a/test/udev.c +++ b/test/udev.c @@ -507,7 +507,7 @@ START_TEST(udev_seat_recycle) END_TEST void -litest_setup_tests(void) +litest_setup_tests_udev(void) { litest_add_no_device("udev:create", udev_create_NULL); litest_add_no_device("udev:create", udev_create_seat0); From a7f04c9a8498c6b0f1a3fd910dcd8f2d0d59733a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 8 Jul 2016 09:42:36 +1000 Subject: [PATCH 04/13] test: only init the device rules once The udev hwdb takes about 200ms and we still trigger it on each device. The udev rules don't actually change after compiling, so simply create them once and remove them after the test run. For multiple test binaries this needed to be synchronized (which is hard), hence the previous merge into a single binary for all tests. Signed-off-by: Peter Hutterer --- test/litest.c | 88 ++++++++++++++------------------------------------- test/litest.h | 2 -- 2 files changed, 23 insertions(+), 67 deletions(-) diff --git a/test/litest.c b/test/litest.c index 2187901a..7c185682 100644 --- a/test/litest.c +++ b/test/litest.c @@ -482,49 +482,6 @@ litest_reload_udev_rules(void) litest_system("udevadm hwdb --update"); } -static int -litest_udev_rule_filter(const struct dirent *entry) -{ - return strneq(entry->d_name, - UDEV_RULE_PREFIX, - strlen(UDEV_RULE_PREFIX)); -} - -static void -litest_drop_udev_rules(void) -{ - int n; - int rc; - struct dirent **entries; - char path[PATH_MAX]; - - n = scandir(UDEV_RULES_D, - &entries, - litest_udev_rule_filter, - alphasort); - if (n <= 0) - return; - - while (n--) { - rc = snprintf(path, sizeof(path), - "%s/%s", - UDEV_RULES_D, - entries[n]->d_name); - if (rc > 0 && - (size_t)rc == strlen(UDEV_RULES_D) + - strlen(entries[n]->d_name) + 1) - unlink(path); - else - fprintf(stderr, - "Failed to delete %s. Remaining tests are unreliable\n", - entries[n]->d_name); - free(entries[n]); - } - free(entries); - - litest_reload_udev_rules(); -} - static void litest_add_tcase_for_device(struct suite *suite, const char *funcname, @@ -554,13 +511,6 @@ litest_add_tcase_for_device(struct suite *suite, t->name = strdup(test_name); t->tc = tcase_create(test_name); list_insert(&suite->tests, &t->node); - /* we can't guarantee that we clean up properly if a test fails, the - udev rules used for a previous test may still be in place. Add an - unchecked fixture to always clean up all rules before/after a - test case completes */ - tcase_add_unchecked_fixture(t->tc, - litest_drop_udev_rules, - litest_drop_udev_rules); tcase_add_checked_fixture(t->tc, dev->setup, dev->teardown ? dev->teardown : litest_generic_device_teardown); if (range) @@ -847,6 +797,28 @@ litest_log_handler(struct libinput *libinput, litest_abort_msg("libinput bug triggered, aborting.\n"); } +static char * +litest_init_device_udev_rules(struct litest_test_device *dev); + +static void +litest_init_all_device_udev_rules(struct list *created_files) +{ + struct litest_test_device **dev = devices; + + while (*dev) { + char *udev_file; + + udev_file = litest_init_device_udev_rules(*dev); + if (udev_file) { + struct created_file *file = zalloc(sizeof(*file)); + litest_assert(file); + file->path = udev_file; + list_insert(created_files, &file->link); + } + dev++; + } +} + static int open_restricted(const char *path, int flags, void *userdata) { @@ -1065,6 +1037,7 @@ litest_init_udev_rules(struct list *created_files) strerror(errno)); litest_install_model_quirks(created_files); + litest_init_all_device_udev_rules(created_files); litest_reload_udev_rules(); } @@ -1108,8 +1081,6 @@ litest_init_device_udev_rules(struct litest_test_device *dev) litest_assert_int_ge(fputs(dev->udev_rule, f), 0); fclose(f); - litest_reload_udev_rules(); - return path; } @@ -1126,7 +1097,6 @@ litest_create(enum litest_device_type which, const struct input_id *id; struct input_absinfo *abs; int *events; - char *udev_file; dev = devices; while (*dev) { @@ -1141,17 +1111,13 @@ litest_create(enum litest_device_type which, d = zalloc(sizeof(*d)); litest_assert(d != NULL); - udev_file = litest_init_device_udev_rules(*dev); /* device has custom create method */ if ((*dev)->create) { (*dev)->create(d); if (abs_override || events_override) { - if (udev_file) - unlink(udev_file); litest_abort_msg("Custom create cannot be overridden"); } - d->udev_rule_file = udev_file; return d; } @@ -1165,7 +1131,6 @@ litest_create(enum litest_device_type which, abs, events); d->interface = (*dev)->interface; - d->udev_rule_file = udev_file; free(abs); free(events); @@ -1357,13 +1322,6 @@ litest_delete_device(struct litest_device *d) lfd = create_udev_lock_file(); - if (d->udev_rule_file) { - unlink(d->udev_rule_file); - free(d->udev_rule_file); - d->udev_rule_file = NULL; - litest_reload_udev_rules(); - } - libinput_device_unref(d->libinput_device); libinput_path_remove_device(d->libinput_device); if (d->owns_context) diff --git a/test/litest.h b/test/litest.h index 2ada8f66..4db6cf50 100644 --- a/test/litest.h +++ b/test/litest.h @@ -267,8 +267,6 @@ struct litest_device { bool skip_ev_syn; void *private; /* device-specific data */ - - char *udev_rule_file; }; struct axis_replacement { From f9f4bb026603738dda0367a3eb4cfb7289cf0211 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 20 Jul 2016 08:43:05 +1000 Subject: [PATCH 05/13] test: make sure we remove all udev rules when we SIGINT the test Signed-off-by: Peter Hutterer --- test/litest.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/litest.c b/test/litest.c index 7c185682..492aa3ac 100644 --- a/test/litest.c +++ b/test/litest.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,9 @@ struct created_file { char *path; }; +struct list created_files_list; /* list of all files to remove at the end of + the test run */ + static void litest_init_udev_rules(struct list *created_files_list); static void litest_remove_udev_rules(struct list *created_files_list); @@ -837,13 +841,40 @@ struct libinput_interface interface = { .close_restricted = close_restricted, }; +static void +litest_signal(int sig) +{ + struct created_file *f, *tmp; + + list_for_each_safe(f, tmp, &created_files_list, link) { + list_remove(&f->link); + unlink(f->path); + /* in the sighandler, we can't free */ + } + + exit(1); +} + +static inline void +litest_setup_sighandler(int sig) +{ + struct sigaction act, oact; + int rc; + + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, sig); + act.sa_flags = 0; + act.sa_handler = litest_signal; + rc = sigaction(sig, &act, &oact); + litest_assert_int_ne(rc, -1); +} + static inline int litest_run(int argc, char **argv) { struct suite *s, *snext; int failed; SRunner *sr = NULL; - struct list created_files_list; list_init(&created_files_list); @@ -871,6 +902,8 @@ litest_run(int argc, char **argv) litest_init_udev_rules(&created_files_list); + litest_setup_sighandler(SIGINT); + srunner_run_all(sr, CK_ENV); failed = srunner_ntests_failed(sr); srunner_free(sr); From 51fb42cb602ed08f14b49121e02dbf0c5c5e1877 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 20 Jul 2016 08:45:22 +1000 Subject: [PATCH 06/13] test: restore the hwdb/udev rules on SIGINT We can't call system() in the signal handler but we are allowed to fork. Do that, update the hwdb and immediately exit the child again. Signed-off-by: Peter Hutterer --- test/litest.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/litest.c b/test/litest.c index 492aa3ac..2adec941 100644 --- a/test/litest.c +++ b/test/litest.c @@ -852,6 +852,12 @@ litest_signal(int sig) /* in the sighandler, we can't free */ } + if (fork() == 0) { + /* child, we can run system() */ + litest_reload_udev_rules(); + exit(0); + } + exit(1); } From 68841bfd52904794f4f99aa7eb6af2206ab85025 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 13:30:20 +1000 Subject: [PATCH 07/13] Revert "test: create a lock file to avoid parallel udev reloads during device add" Not needed anymore, we only have one process creating the udev rules. This reverts commit 030ec053fbbc17f9bd0a3a8c6003318864986de7. --- configure.ac | 3 --- test/litest.c | 63 --------------------------------------------------- 2 files changed, 66 deletions(-) diff --git a/configure.ac b/configure.ac index 9e238b46..776b98f4 100644 --- a/configure.ac +++ b/configure.ac @@ -194,9 +194,6 @@ if test "x$build_tests" = "xyes"; then AC_DEFINE_UNQUOTED(HAVE_ADDR2LINE, 1, [addr2line found]) AC_DEFINE_UNQUOTED(ADDR2LINE, ["$ADDR2LINE"], [Path to addr2line]) fi - - AC_DEFINE(LITEST_UDEV_LOCKFILE, ["/tmp/litest-udev.lock"], - [Lock file used to restrict udev reloads during tests]) fi AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes]) diff --git a/test/litest.c b/test/litest.c index 2adec941..0d2d21b2 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1203,58 +1203,6 @@ litest_restore_log_handler(struct libinput *libinput) libinput_log_set_handler(libinput, litest_log_handler); } -static inline int -create_udev_lock_file(void) -{ - int lfd; - - /* Running the multiple tests in parallel usually trips over udev - * not being up-to-date. We change the udev rules for every device - * created, sometimes this means we end up getting the wrong udev - * device, or having wrong properties applied. - * - * litests use the path interface and there is a window between - * creating the device (which triggers udev reloads) and adding the - * device to the libinput context where another udev reload may - * upset things. - * - * To avoid this, create a lockfile on device add and device delete - * to make sure that we have exclusive access to udev while - * the udev rules are reloaded. - */ - do { - lfd = open(LITEST_UDEV_LOCKFILE, O_CREAT|O_EXCL, O_RDWR); - - if (lfd == -1) { - struct stat st; - time_t now = time(NULL); - - litest_assert_int_eq(errno, EEXIST); - msleep(10); - - /* If the lock file is older than 10s, it's a - leftover from some aborted test */ - if (stat(LITEST_UDEV_LOCKFILE, &st) != -1) { - if (st.st_mtime < now - 10) { - fprintf(stderr, - "Removing stale lock file %s.\n", - LITEST_UDEV_LOCKFILE); - unlink(LITEST_UDEV_LOCKFILE); - } - } - } - } while (lfd < 0); - - return lfd; -} - -static inline void -delete_udev_lock_file(int lfd) -{ - close(lfd); - unlink(LITEST_UDEV_LOCKFILE); -} - struct litest_device * litest_add_device_with_overrides(struct libinput *libinput, enum litest_device_type which, @@ -1268,8 +1216,6 @@ litest_add_device_with_overrides(struct libinput *libinput, int rc; const char *path; - int lfd = create_udev_lock_file(); - d = litest_create(which, name_override, id_override, @@ -1295,9 +1241,6 @@ litest_add_device_with_overrides(struct libinput *libinput, d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, ABS_Y); d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, ABS_Y); } - - delete_udev_lock_file(lfd); - return d; } @@ -1354,13 +1297,9 @@ litest_handle_events(struct litest_device *d) void litest_delete_device(struct litest_device *d) { - int lfd; - if (!d) return; - lfd = create_udev_lock_file(); - libinput_device_unref(d->libinput_device); libinput_path_remove_device(d->libinput_device); if (d->owns_context) @@ -1371,8 +1310,6 @@ litest_delete_device(struct litest_device *d) free(d->private); memset(d,0, sizeof(*d)); free(d); - - delete_udev_lock_file(lfd); } void From 1d5c1fedb45a50fcff7b05bba7da35c5735d9fd1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2016 14:38:34 +1000 Subject: [PATCH 08/13] test: drop the sysname comparison in the device add/remove test Running tests in parallel virtually guarantees a different device is added in between. What we're testing here is that the device comes back and the original ref doesn't send events, so a false test failure would still indicate a bug anyway. Signed-off-by: Peter Hutterer --- test/device.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/device.c b/test/device.c index 01f794f2..82ef03be 100644 --- a/test/device.c +++ b/test/device.c @@ -296,7 +296,7 @@ START_TEST(device_reenable_syspath_changed) { struct libinput *li; struct litest_device *litest_device; - struct libinput_device *device1, *device2; + struct libinput_device *device1; enum libinput_config_status status; struct libinput_event *event; @@ -315,12 +315,6 @@ START_TEST(device_reenable_syspath_changed) litest_drain_events(li); litest_device = litest_add_device(li, LITEST_MOUSE); - device2 = litest_device->libinput_device; - /* Note: if the sysname isn't the same, some other device got added - * or removed while this test was running. This is unlikely and - * would result in a false positive, so let's fail the test here */ - ck_assert_str_eq(libinput_device_get_sysname(device1), - libinput_device_get_sysname(device2)); status = libinput_device_config_send_events_set_mode(device1, LIBINPUT_CONFIG_SEND_EVENTS_ENABLED); From eb8e1d4a137c538488c405153146f9b9ace50e51 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 15:19:23 +1000 Subject: [PATCH 09/13] test: add a make-like job control to run tests in parallel Add a make-like -j/--jobs option to split the number of parallel test processes. Defaults to 8 if not specified, future patches will default this to 1 for special cases where filters are specified or gdb is detected. Each subprocess overwrites argv[0] to be easier identifiable in the ps output when we're trying to figure out which tests are still running. A -j1 is equivalent to the previous functionality, i.e. we don't fork. One quirk needed for check: any test case not part of a test runner will not be freed and thus triggers valgrind. We do test filtering by splitting up the tests across multiple forks (i.e. each process has several tests that are in the list but not added to the runner). Thus we need to mark those we expect check to free as used. Then on cleanup we traverse the test list, add all the unused one to a test runner and free that test runner (without actually running it). This cleans up both the filtered tests in each subprocess and the whole test list in the parent process which doesn't run a test itself. Signed-off-by: Peter Hutterer --- doc/test-suite.dox | 6 ++ test/litest.c | 140 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 119 insertions(+), 27 deletions(-) diff --git a/doc/test-suite.dox b/doc/test-suite.dox index 104e2a91..67d18053 100644 --- a/doc/test-suite.dox +++ b/doc/test-suite.dox @@ -7,6 +7,12 @@ during `make check`. Check itself is wrapped into a libinput-specific test suite called *litest*. Tests are found in `$srcdir/test/`, the main test suite is `libinput-test-suite-runner`. +The test suite has a make-like job control enabled by the `-j` or `--jobs` +flag and will fork off as many parallel processes as given by this flag. The +default if unspecified is 8. When debugging a specific test case failure it +is recommended to employ test filtures (see @ref test-filtering) and disable +parallel tests. + @section test-config X.Org config to avoid interference uinput devices created by the test suite are usually recognised by X as diff --git a/test/litest.c b/test/litest.c index 0d2d21b2..5a8498fc 100644 --- a/test/litest.c +++ b/test/litest.c @@ -63,6 +63,7 @@ #define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \ "/91-litest-test-device-REMOVEME.rules" +static int jobs = 8; static int in_debugger = -1; static int verbose = 0; const char *filter_test = NULL; @@ -325,6 +326,7 @@ struct suite { struct list tests; char *name; Suite *suite; + bool used; }; static struct litest_device *current_device; @@ -576,6 +578,7 @@ get_suite(const char *name) assert(s != NULL); s->name = strdup(name); s->suite = suite_create(s->name); + s->used = false; list_init(&s->tests); list_insert(&all_tests, &s->node); @@ -875,12 +878,107 @@ litest_setup_sighandler(int sig) litest_assert_int_ne(rc, -1); } +static void +litest_free_test_list(struct list *tests) +{ + struct suite *s, *snext; + SRunner *sr = NULL; + + /* quirk needed for check: test suites can only get freed by adding + * them to a test runner and freeing the runner. Without this, + * valgrind complains */ + list_for_each(s, tests, node) { + if (s->used) + continue; + + if (!sr) + sr = srunner_create(s->suite); + else + srunner_add_suite(sr, s->suite); + } + srunner_free(sr); + + list_for_each_safe(s, snext, tests, node) { + struct test *t, *tnext; + + list_for_each_safe(t, tnext, &s->tests, node) { + free(t->name); + list_remove(&t->node); + free(t); + } + + list_remove(&s->node); + free(s->name); + free(s); + } +} + +static int +litest_run_suite(char *argv0, struct list *tests, int which, int max) +{ + int failed = 0; + SRunner *sr = NULL; + struct suite *s; + int argvlen = strlen(argv0); + int count = -1; + + if (max > 1) + snprintf(argv0, argvlen, "libinput-test-%-50d", which); + + list_for_each(s, tests, node) { + ++count; + if (max != 1 && (count % max) != which) { + continue; + } + + if (!sr) + sr = srunner_create(s->suite); + else + srunner_add_suite(sr, s->suite); + + s->used = true; + } + + if (!sr) + return 0; + + srunner_run_all(sr, CK_ENV); + failed = srunner_ntests_failed(sr); + srunner_free(sr); + return failed; +} + +static int +litest_fork_subtests(char *argv0, struct list *tests, int max_forks) +{ + int failed = 0; + int status; + pid_t pid; + int f; + + for (f = 0; f < max_forks; f++) { + pid = fork(); + if (pid == 0) { + failed = litest_run_suite(argv0, tests, f, max_forks); + litest_free_test_list(&all_tests); + exit(failed); + /* child always exits here */ + } + } + + /* parent process only */ + while (wait(&status) != -1 && errno != ECHILD) { + if (WEXITSTATUS(status) != 0) + failed = 1; + } + + return failed; +} + static inline int litest_run(int argc, char **argv) { - struct suite *s, *snext; - int failed; - SRunner *sr = NULL; + int failed = 0; list_init(&created_files_list); @@ -896,13 +994,6 @@ litest_run(int argc, char **argv) setenv("CK_FORK", "no", 0); } - list_for_each(s, &all_tests, node) { - if (!sr) - sr = srunner_create(s->suite); - else - srunner_add_suite(sr, s->suite); - } - if (getenv("LITEST_VERBOSE")) verbose = 1; @@ -910,23 +1001,12 @@ litest_run(int argc, char **argv) litest_setup_sighandler(SIGINT); - srunner_run_all(sr, CK_ENV); - failed = srunner_ntests_failed(sr); - srunner_free(sr); + if (jobs == 1) + failed = litest_run_suite(argv[0], &all_tests, 1, 1); + else + failed = litest_fork_subtests(argv[0], &all_tests, jobs); - list_for_each_safe(s, snext, &all_tests, node) { - struct test *t, *tnext; - - list_for_each_safe(t, tnext, &s->tests, node) { - free(t->name); - list_remove(&t->node); - free(t); - } - - list_remove(&s->node); - free(s->name); - free(s); - } + litest_free_test_list(&all_tests); litest_remove_udev_rules(&created_files_list); @@ -3005,6 +3085,7 @@ litest_parse_argv(int argc, char **argv) OPT_FILTER_TEST, OPT_FILTER_DEVICE, OPT_FILTER_GROUP, + OPT_JOBS, OPT_LIST, OPT_VERBOSE, }; @@ -3012,6 +3093,7 @@ litest_parse_argv(int argc, char **argv) { "filter-test", 1, 0, OPT_FILTER_TEST }, { "filter-device", 1, 0, OPT_FILTER_DEVICE }, { "filter-group", 1, 0, OPT_FILTER_GROUP }, + { "jobs", 1, 0, OPT_JOBS }, { "list", 0, 0, OPT_LIST }, { "verbose", 0, 0, OPT_VERBOSE }, { 0, 0, 0, 0} @@ -3021,7 +3103,7 @@ litest_parse_argv(int argc, char **argv) int c; int option_index = 0; - c = getopt_long(argc, argv, "", opts, &option_index); + c = getopt_long(argc, argv, "j:", opts, &option_index); if (c == -1) break; switch(c) { @@ -3034,6 +3116,10 @@ litest_parse_argv(int argc, char **argv) case OPT_FILTER_GROUP: filter_group = optarg; break; + case 'j': + case OPT_JOBS: + jobs = atoi(optarg); + break; case OPT_LIST: return LITEST_MODE_LIST; case OPT_VERBOSE: From 152fe5fc5f5678d47d5554732a34a5bf0ac68dea Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 15:28:37 +1000 Subject: [PATCH 10/13] test: remove NOTPARALLEL We only have a single test runner now, so no need to restrict it. Signed-off-by: Peter Hutterer --- test/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index 32e379af..23a4bc81 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -90,8 +90,6 @@ noinst_PROGRAMS = $(build_tests) $(run_tests) noinst_SCRIPTS = symbols-leak-test TESTS = $(run_tests) symbols-leak-test -.NOTPARALLEL: - libinput_test_suite_runner_SOURCES = udev.c \ path.c \ pointer.c \ From 13a88a762c5d0b1c9328529aeda3718cf4597766 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 22 Jul 2016 16:31:25 +1000 Subject: [PATCH 11/13] test: split the tap tests into more tap groups We're grouping by test suites, so split up the suites a bit further. The tap tests all have timeouts and thus take forever, splitting them across multiple forks means we can finish the test suite quicker. Signed-off-by: Peter Hutterer --- test/touchpad-tap.c | 84 ++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index d09189f4..3dcca8fe 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -1963,49 +1963,49 @@ litest_setup_tests_touchpad_tap(void) { struct range multitap_range = {3, 8}; - litest_add("tap:1fg", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_doubletap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_tap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_move, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock_tap, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock_timeout, LITEST_TOUCHPAD, LITEST_ANY); - litest_add("tap:2fg", touchpad_2fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_n_drag_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); - litest_add("tap:2fg", touchpad_2fg_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_n_hold_first, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_n_hold_second, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_2fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_1fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); - litest_add("tap:2fg", touchpad_2fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD); + litest_add("tap-1fg:1fg", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("tap-1fg:1fg", touchpad_1fg_doubletap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_tap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_move, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &multitap_range); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); + litest_add("tap-1fg:1fg", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("tap-1fg:1fg", touchpad_1fg_tap_n_drag_draglock, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("tap-1fg:1fg", touchpad_1fg_tap_n_drag_draglock_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("tap-1fg:1fg", touchpad_1fg_tap_n_drag_draglock_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_n_drag_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-2fg:2fg", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_n_hold_first, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_n_hold_second, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-2fg:2fg", touchpad_1fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD); - litest_add("tap:2fg", touchpad_2fg_tap_click_apple, LITEST_APPLE_CLICKPAD, LITEST_ANY); - litest_add("tap:2fg", touchpad_no_2fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_no_2fg_tap_after_timeout, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:2fg", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:2fg", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap_btntool_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:3fg", touchpad_3fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("tap:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:4fg", touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:5fg", touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); - litest_add("tap:5fg", touchpad_5fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-2fg:2fg", touchpad_2fg_tap_click_apple, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add("tap-2fg:2fg", touchpad_no_2fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-2fg:2fg", touchpad_no_2fg_tap_after_timeout, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-2fg:2fg", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-2fg:2fg", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-3fg:3fg", touchpad_3fg_tap_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-3fg:3fg", touchpad_3fg_tap_btntool_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-3fg:3fg", touchpad_3fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-3fg:3fg", touchpad_3fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("tap-4fg:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-4fg:4fg", touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-5fg:5fg", touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add("tap-5fg:5fg", touchpad_5fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); /* Real buttons don't interfere with tapping, so don't run those for pads with buttons */ - litest_add("tap:1fg", touchpad_1fg_double_tap_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add_ranged("tap:1fg", touchpad_1fg_multitap_n_drag_tap_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); - litest_add("tap:1fg", touchpad_1fg_tap_n_drag_draglock_tap_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add("tap-1fg:1fg", touchpad_1fg_double_tap_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add("tap-1fg:1fg", touchpad_1fg_tap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_tap_click, LITEST_CLICKPAD, LITEST_ANY, &multitap_range); + litest_add("tap-1fg:1fg", touchpad_1fg_tap_n_drag_draglock_tap_click, LITEST_CLICKPAD, LITEST_ANY); litest_add("tap:config", touchpad_tap_default_disabled, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_ANY); litest_add("tap:config", touchpad_tap_default_enabled, LITEST_TOUCHPAD, LITEST_BUTTON); @@ -2013,8 +2013,8 @@ litest_setup_tests_touchpad_tap(void) litest_add("tap:config", touchpad_tap_is_available, LITEST_TOUCHPAD, LITEST_ANY); litest_add("tap:config", touchpad_tap_is_not_available, LITEST_ANY, LITEST_TOUCHPAD); - litest_add("tap:1fg", clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY); - litest_add("tap:2fg", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); + litest_add("tap-1fg:1fg", clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add("tap-2fg:2fg", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); litest_add("tap:draglock", touchpad_drag_lock_default_disabled, LITEST_TOUCHPAD, LITEST_ANY); litest_add("tap:draglock", touchpad_drag_lock_default_unavailable, LITEST_ANY, LITEST_TOUCHPAD); @@ -2025,5 +2025,5 @@ litest_setup_tests_touchpad_tap(void) litest_add("tap:drag", touchpad_drag_config_enabledisable, LITEST_TOUCHPAD, LITEST_ANY); litest_add("tap:drag", touchpad_drag_disabled, LITEST_TOUCHPAD, LITEST_ANY); litest_add("tap:drag", touchpad_drag_disabled_immediate, LITEST_TOUCHPAD, LITEST_ANY); - litest_add_ranged("tap:drag", touchpad_drag_disabled_multitap_no_drag, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); + litest_add_ranged("tap-multitap:drag", touchpad_drag_disabled_multitap_no_drag, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range); } From 681f967c8fb67d4af8de49a4298965ba61878384 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2016 14:03:33 +1000 Subject: [PATCH 12/13] test: if a filter is specified, don't parallelize jobs by default Likely testing a specific set of tests, possibly in gdb. So don't parallelize. Signed-off-by: Peter Hutterer --- test/litest.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/litest.c b/test/litest.c index 5a8498fc..902543d7 100644 --- a/test/litest.c +++ b/test/litest.c @@ -3099,6 +3099,12 @@ litest_parse_argv(int argc, char **argv) { 0, 0, 0, 0} }; + enum { + JOBS_DEFAULT, + JOBS_SINGLE, + JOBS_CUSTOM + } want_jobs = JOBS_DEFAULT; + while(1) { int c; int option_index = 0; @@ -3109,16 +3115,23 @@ litest_parse_argv(int argc, char **argv) switch(c) { case OPT_FILTER_TEST: filter_test = optarg; + if (want_jobs == JOBS_DEFAULT) + want_jobs = JOBS_SINGLE; break; case OPT_FILTER_DEVICE: filter_device = optarg; + if (want_jobs == JOBS_DEFAULT) + want_jobs = JOBS_SINGLE; break; case OPT_FILTER_GROUP: filter_group = optarg; + if (want_jobs == JOBS_DEFAULT) + want_jobs = JOBS_SINGLE; break; case 'j': case OPT_JOBS: jobs = atoi(optarg); + want_jobs = JOBS_CUSTOM; break; case OPT_LIST: return LITEST_MODE_LIST; @@ -3131,6 +3144,9 @@ litest_parse_argv(int argc, char **argv) } } + if (want_jobs == JOBS_SINGLE) + jobs = 1; + return LITEST_MODE_TEST; } From 6cde53fc1d8aae22f780eeee23199a41ab1521f3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 1 Aug 2016 14:09:02 +1000 Subject: [PATCH 13/13] test: if we're in a debugger, use single-fork mode only Don't fork by default if we're in gdb. Note that is_debugger_attached() is now inside #ifndef LITEST_NO_MAIN, gdb for the litest selftest will now require a manual CK_FORK=no. Signed-off-by: Peter Hutterer --- doc/test-suite.dox | 3 +- test/litest.c | 71 +++++++++++++++++++++++----------------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/doc/test-suite.dox b/doc/test-suite.dox index 67d18053..e6fbe629 100644 --- a/doc/test-suite.dox +++ b/doc/test-suite.dox @@ -11,7 +11,8 @@ The test suite has a make-like job control enabled by the `-j` or `--jobs` flag and will fork off as many parallel processes as given by this flag. The default if unspecified is 8. When debugging a specific test case failure it is recommended to employ test filtures (see @ref test-filtering) and disable -parallel tests. +parallel tests. The test suite automatically disables parallel make when run +in gdb. @section test-config X.Org config to avoid interference diff --git a/test/litest.c b/test/litest.c index 902543d7..c344f2fb 100644 --- a/test/litest.c +++ b/test/litest.c @@ -751,35 +751,6 @@ _litest_add_ranged_for_device(const char *name, litest_abort_msg("Invalid test device type"); } -static int -is_debugger_attached(void) -{ - int status; - int rc; - int pid = fork(); - - if (pid == -1) - return 0; - - if (pid == 0) { - int ppid = getppid(); - if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) { - waitpid(ppid, NULL, 0); - ptrace(PTRACE_CONT, NULL, NULL); - ptrace(PTRACE_DETACH, ppid, NULL, NULL); - rc = 0; - } else { - rc = 1; - } - _exit(rc); - } else { - waitpid(pid, &status, 0); - rc = WEXITSTATUS(status); - } - - return rc; -} - static void litest_log_handler(struct libinput *libinput, enum libinput_log_priority pri, @@ -988,12 +959,6 @@ litest_run(int argc, char **argv) return 1; } - if (in_debugger == -1) { - in_debugger = is_debugger_attached(); - if (in_debugger) - setenv("CK_FORK", "no", 0); - } - if (getenv("LITEST_VERBOSE")) verbose = 1; @@ -3105,6 +3070,9 @@ litest_parse_argv(int argc, char **argv) JOBS_CUSTOM } want_jobs = JOBS_DEFAULT; + if (in_debugger) + want_jobs = JOBS_SINGLE; + while(1) { int c; int option_index = 0; @@ -3151,6 +3119,35 @@ litest_parse_argv(int argc, char **argv) } #ifndef LITEST_NO_MAIN +static int +is_debugger_attached(void) +{ + int status; + int rc; + int pid = fork(); + + if (pid == -1) + return 0; + + if (pid == 0) { + int ppid = getppid(); + if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) { + waitpid(ppid, NULL, 0); + ptrace(PTRACE_CONT, NULL, NULL); + ptrace(PTRACE_DETACH, ppid, NULL, NULL); + rc = 0; + } else { + rc = 1; + } + _exit(rc); + } else { + waitpid(pid, &status, 0); + rc = WEXITSTATUS(status); + } + + return rc; +} + static void litest_list_tests(struct list *tests) { @@ -3175,6 +3172,10 @@ main(int argc, char **argv) setenv("CK_DEFAULT_TIMEOUT", "30", 0); setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1); + in_debugger = is_debugger_attached(); + if (in_debugger) + setenv("CK_FORK", "no", 0); + mode = litest_parse_argv(argc, argv); if (mode == LITEST_MODE_ERROR) return EXIT_FAILURE;