diff --git a/test/Makefile.am b/test/Makefile.am index 0d54dab6..ce1973fe 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -32,6 +32,7 @@ liblitest_la_SOURCES = \ litest-device-keyboard.c \ litest-device-keyboard-all-codes.c \ litest-device-keyboard-razer-blackwidow.c \ + litest-device-lid-switch.c \ litest-device-logitech-trackball.c \ litest-device-nexus4-touch-screen.c \ litest-device-magic-trackpad.c \ @@ -117,7 +118,8 @@ libinput_test_suite_runner_SOURCES = test-udev.c \ test-misc.c \ test-keyboard.c \ test-device.c \ - test-gestures.c + test-gestures.c \ + test-lid.c libinput_test_suite_runner_CFLAGS = $(AM_CFLAGS) -DLIBINPUT_LT_VERSION="\"$(LIBINPUT_LT_VERSION)\"" libinput_test_suite_runner_LDADD = $(TEST_LIBS) diff --git a/test/litest-device-lid-switch.c b/test/litest-device-lid-switch.c new file mode 100644 index 00000000..823a5c9d --- /dev/null +++ b/test/litest-device-lid-switch.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2017 James Ye + * + * 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 "litest.h" +#include "litest-int.h" + +static void +litest_lid_switch_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_LID_SWITCH); + litest_set_current_device(d); +} + +static struct input_id input_id = { + .bustype = 0x19, + .vendor = 0x0, + .product = 0x5, +}; + +static int events[] = { + EV_SW, SW_LID, + -1, -1, +}; + +static const char udev_rule[] = +"ACTION==\"remove\", GOTO=\"switch_end\"\n" +"KERNEL!=\"event*\", GOTO=\"switch_end\"\n" +"\n" +"ATTRS{name}==\"litest Lid Switch*\",\\\n" +" ENV{ID_INPUT_SWITCH}=\"1\"\n" +"\n" +"LABEL=\"switch_end\""; + +struct litest_test_device litest_lid_switch_device = { + .type = LITEST_LID_SWITCH, + .features = LITEST_SWITCH, + .shortname = "lid switch", + .setup = litest_lid_switch_setup, + .interface = NULL, + + .name = "Lid Switch", + .id = &input_id, + .events = events, + .absinfo = NULL, + + .udev_rule = udev_rule, +}; diff --git a/test/litest.c b/test/litest.c index 5b1e7b54..7a5ec57e 100644 --- a/test/litest.c +++ b/test/litest.c @@ -408,6 +408,7 @@ extern struct litest_test_device litest_acer_hawaii_keyboard_device; extern struct litest_test_device litest_acer_hawaii_touchpad_device; extern struct litest_test_device litest_synaptics_rmi4_device; extern struct litest_test_device litest_mouse_wheel_tilt_device; +extern struct litest_test_device litest_lid_switch_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -470,6 +471,7 @@ struct litest_test_device* devices[] = { &litest_acer_hawaii_touchpad_device, &litest_synaptics_rmi4_device, &litest_mouse_wheel_tilt_device, + &litest_lid_switch_device, NULL, }; @@ -1907,6 +1909,14 @@ litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press) litest_button_click(d, key, is_press); } +void +litest_lid_action(struct litest_device *dev, + enum libinput_switch_state state) +{ + litest_event(dev, EV_SW, SW_LID, state); + litest_event(dev, EV_SYN, SYN_REPORT, 0); +} + static int litest_scale_axis(const struct litest_device *d, unsigned int axis, @@ -2819,6 +2829,25 @@ litest_is_pad_strip_event(struct libinput_event *event, return p; } +struct libinput_event_switch * +litest_is_switch_event(struct libinput_event *event, + enum libinput_switch sw, + enum libinput_switch_state state) +{ + struct libinput_event_switch *swev; + enum libinput_event_type type = LIBINPUT_EVENT_SWITCH_TOGGLE; + + litest_assert_notnull(event); + litest_assert_event_type(event, type); + swev = libinput_event_get_switch_event(event); + + litest_assert_int_eq(libinput_event_switch_get_switch(swev), sw); + litest_assert_int_eq(libinput_event_switch_get_switch_state(swev), + state); + + return swev; +} + void litest_assert_pad_button_event(struct libinput *li, unsigned int button, @@ -3323,6 +3352,7 @@ main(int argc, char **argv) litest_setup_tests_keyboard(); litest_setup_tests_device(); litest_setup_tests_gestures(); + litest_setup_tests_lid(); if (mode == LITEST_MODE_LIST) { litest_list_tests(&all_tests); diff --git a/test/litest.h b/test/litest.h index e6d35a90..00756046 100644 --- a/test/litest.h +++ b/test/litest.h @@ -49,6 +49,7 @@ 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); +extern void litest_setup_tests_lid(void); void litest_fail_condition(const char *file, @@ -228,6 +229,7 @@ enum litest_device_type { LITEST_ACER_HAWAII_TOUCHPAD, LITEST_SYNAPTICS_RMI4, LITEST_MOUSE_WHEEL_TILT, + LITEST_LID_SWITCH, }; enum litest_device_feature { @@ -259,6 +261,7 @@ enum litest_device_feature { LITEST_STRIP = 1 << 23, LITEST_TRACKBALL = 1 << 24, LITEST_LEDS = 1 << 25, + LITEST_SWITCH = 1 << 26, }; struct litest_device { @@ -526,6 +529,9 @@ litest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press); +void litest_lid_action(struct litest_device *d, + enum libinput_switch_state state); + void litest_wait_for_event(struct libinput *li); @@ -589,6 +595,11 @@ litest_is_pad_strip_event(struct libinput_event *event, unsigned int number, enum libinput_tablet_pad_strip_axis_source source); +struct libinput_event_switch * +litest_is_switch_event(struct libinput_event *event, + enum libinput_switch sw, + enum libinput_switch_state state); + void litest_assert_button_event(struct libinput *li, unsigned int button, diff --git a/test/test-device.c b/test/test-device.c index 3fa35d8b..8f06f7e4 100644 --- a/test/test-device.c +++ b/test/test-device.c @@ -1493,6 +1493,7 @@ START_TEST(device_capability_at_least_one) LIBINPUT_DEVICE_CAP_TABLET_TOOL, LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_GESTURE, + LIBINPUT_DEVICE_CAP_SWITCH, }; enum libinput_device_capability *cap; int ncaps = 0; @@ -1512,7 +1513,7 @@ START_TEST(device_capability_check_invalid) struct libinput_device *device = dev->libinput_device; ck_assert(!libinput_device_has_capability(device, -1)); - ck_assert(!libinput_device_has_capability(device, 6)); + ck_assert(!libinput_device_has_capability(device, 7)); ck_assert(!libinput_device_has_capability(device, 0xffff)); } diff --git a/test/test-lid.c b/test/test-lid.c new file mode 100644 index 00000000..e1a9088c --- /dev/null +++ b/test/test-lid.c @@ -0,0 +1,265 @@ +/* + * Copyright © 2017 James Ye + * + * 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 + +#include +#include + +#include "libinput-util.h" +#include "litest.h" + +START_TEST(lid_switch) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li = sw->libinput; + struct libinput_event *event; + + litest_drain_events(li); + + /* lid closed */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + /* lid opened */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(lid_switch_double) +{ + struct litest_device *sw = litest_current_device(); + struct libinput *li = sw->libinput; + struct libinput_event *event; + + litest_drain_events(li); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + /* This will be filtered by the kernel, so this test is a bit + * useless */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + litest_assert_empty_queue(li); +} +END_TEST + +static inline struct litest_device * +lid_init_paired_touchpad(struct libinput *li) +{ + enum litest_device_type which = LITEST_SYNAPTICS_I2C; + + return litest_add_device(li, which); +} + +START_TEST(lid_disable_touchpad) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + /* lid is down - no events */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_empty_queue(li); + + /* lid is up - motion events */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_during_touch) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5, 1); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 5, 1); + litest_touch_up(touchpad, 0); + litest_assert_empty_queue(li); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_edge_scroll) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_enable_edge_scroll(touchpad); + + litest_drain_events(li); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); + + litest_touch_down(touchpad, 0, 99, 20); + libinput_dispatch(li); + litest_timeout_edgescroll(); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_touch_move_to(touchpad, 0, 99, 20, 99, 80, 60, 10); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_touch_move_to(touchpad, 0, 99, 80, 99, 20, 60, 10); + litest_touch_up(touchpad, 0); + libinput_dispatch(li); + litest_assert_empty_queue(li); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_edge_scroll_interrupt) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + struct libinput_event *event; + + touchpad = lid_init_paired_touchpad(li); + litest_enable_edge_scroll(touchpad); + + litest_drain_events(li); + + litest_touch_down(touchpad, 0, 99, 20); + libinput_dispatch(li); + litest_timeout_edgescroll(); + litest_touch_move_to(touchpad, 0, 99, 20, 99, 30, 10, 10); + libinput_dispatch(li); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + libinput_dispatch(li); + + event = libinput_get_event(li); + litest_is_axis_event(event, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + libinput_event_destroy(event); + + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + + litest_delete_device(touchpad); +} +END_TEST + +START_TEST(lid_disable_touchpad_already_open) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + + touchpad = lid_init_paired_touchpad(li); + litest_disable_tap(touchpad->libinput_device); + litest_drain_events(li); + + /* default: lid is up - motion events */ + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + /* open lid - motion events */ + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + + litest_touch_down(touchpad, 0, 50, 50); + litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); + litest_touch_up(touchpad, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_delete_device(touchpad); +} +END_TEST + +void +litest_setup_tests_lid(void) +{ + litest_add("lid:switch", lid_switch, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:switch", lid_switch_double, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY); +} diff --git a/test/test-misc.c b/test/test-misc.c index ed5471db..9517042d 100644 --- a/test/test-misc.c +++ b/test/test-misc.c @@ -135,6 +135,7 @@ START_TEST(event_conversion_device_notify) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } @@ -192,6 +193,7 @@ START_TEST(event_conversion_pointer) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -243,6 +245,7 @@ START_TEST(event_conversion_pointer_abs) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -287,6 +290,7 @@ START_TEST(event_conversion_key) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -338,6 +342,7 @@ START_TEST(event_conversion_touch) ck_assert(libinput_event_get_gesture_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -387,6 +392,7 @@ START_TEST(event_conversion_gesture) ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -434,6 +440,7 @@ START_TEST(event_conversion_tablet) ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -477,6 +484,7 @@ START_TEST(event_conversion_tablet_pad) ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); + ck_assert(libinput_event_get_switch_event(event) == NULL); litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -486,6 +494,47 @@ START_TEST(event_conversion_tablet_pad) } END_TEST +START_TEST(event_conversion_switch) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + int sw = 0; + + litest_lid_action(dev, LIBINPUT_SWITCH_STATE_ON); + litest_lid_action(dev, LIBINPUT_SWITCH_STATE_OFF); + libinput_dispatch(li); + + while ((event = libinput_get_event(li))) { + enum libinput_event_type type; + type = libinput_event_get_type(event); + + if (type == LIBINPUT_EVENT_SWITCH_TOGGLE) { + struct libinput_event_switch *s; + struct libinput_event *base; + s = libinput_event_get_switch_event(event); + base = libinput_event_switch_get_base_event(s); + ck_assert(event == base); + + sw++; + + litest_disable_log_handler(li); + ck_assert(libinput_event_get_device_notify_event(event) == NULL); + ck_assert(libinput_event_get_keyboard_event(event) == NULL); + ck_assert(libinput_event_get_pointer_event(event) == NULL); + ck_assert(libinput_event_get_touch_event(event) == NULL); + ck_assert(libinput_event_get_gesture_event(event) == NULL); + ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); + ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); + litest_restore_log_handler(li); + } + libinput_event_destroy(event); + } + + ck_assert_int_gt(sw, 0); +} +END_TEST + START_TEST(bitfield_helpers) { /* This value has a bit set on all of the word boundaries we want to @@ -1118,6 +1167,7 @@ litest_setup_tests_misc(void) litest_add_for_device("events:conversion", event_conversion_gesture, LITEST_BCM5974); litest_add_for_device("events:conversion", event_conversion_tablet, LITEST_WACOM_CINTIQ); litest_add_for_device("events:conversion", event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD); + litest_add_for_device("events:conversion", event_conversion_switch, LITEST_LID_SWITCH); litest_add_no_device("misc:bitfield_helpers", bitfield_helpers); litest_add_no_device("context:refcount", context_ref_counting);