AM_CONDITIONAL([HAVE_DOXYGEN], [test "x$have_doxygen" = "xyes"])
AC_ARG_ENABLE(tests,
- AS_HELP_STRING([--enable-tests], [Build the tests (default=yes)]),
+ AS_HELP_STRING([--enable-tests], [Build the tests (default=auto)]),
[build_tests="$enableval"],
- [build_tests="yes"])
+ [build_tests="auto"])
+
+PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4], [HAVE_LIBEVDEV="yes"], [HAVE_LIBEVDEV="no"])
+PKG_CHECK_MODULES(CHECK, [check >= 0.9.9], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
+
+if test "x$build_tests" = "xauto"; then
+ if test "x$HAVE_CHECK" = "xyes" -a "x$HAVE_LIBEVDEV" = "xyes"; then
+ build_tests="yes"
+ fi
+fi
+if test "x$build_tests" = "xyes" -a "x$HAVE_CHECK" = "xno"; then
+ AC_MSG_ERROR([Cannot build tests, check is missing])
+fi
+if test "x$build_tests" = "xyes" -a "x$HAVE_LIBEVDEV" = "xno"; then
+ AC_MSG_ERROR([Cannot build tests, libevdev is missing])
+fi
AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"])
if BUILD_TESTS
-AM_CPPFLAGS = -I$(top_srcdir)/src
+AM_CPPFLAGS = -I$(top_srcdir)/src $(CHECK_CFLAGS) $(LIBEVDEV_CFLAGS)
+
+TEST_LIBS = liblitest.la $(CHECK_LIBS) $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) $(top_builddir)/src/libinput.la -lm
+noinst_LTLIBRARIES = liblitest.la
+liblitest_la_SOURCES = \
+ $(top_srcdir)/src/libinput-util.h \
+ $(top_srcdir)/src/libinput-util.c \
+ litest.h \
+ litest-int.h \
+ litest-bcm5974.c \
+ litest-keyboard.c \
+ litest-synaptics.c \
+ litest-trackpoint.c \
+ litest.c
run_tests =
build_tests = test-build-linker test-build-pedantic-c99 test-build-std-gnuc90
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+#include "libinput-util.h"
+
+static void litest_bcm5974_setup(void)
+{
+ struct litest_device *d = litest_create_device(LITEST_BCM5974);
+ litest_set_current_device(d);
+}
+
+static void
+litest_bcm5974_touch_down(struct litest_device *d,
+ unsigned int slot,
+ int x, int y)
+{
+ static int tracking_id;
+ struct input_event *ev;
+ struct input_event down[] = {
+ { .type = EV_ABS, .code = ABS_X, .value = x },
+ { .type = EV_ABS, .code = ABS_Y, .value = y },
+ { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 },
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
+ { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = ++tracking_id },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ };
+
+ down[0].value = litest_scale(d, ABS_X, x);
+ down[1].value = litest_scale(d, ABS_Y, y);
+ down[5].value = litest_scale(d, ABS_X, x);
+ down[6].value = litest_scale(d, ABS_Y, y);
+
+ ARRAY_FOR_EACH(down, ev)
+ litest_event(d, ev->type, ev->code, ev->value);
+}
+
+void
+litest_bcm5974_move(struct litest_device *d, unsigned int slot, int x, int y)
+{
+ struct input_event *ev;
+ struct input_event move[] = {
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
+ { .type = EV_ABS, .code = ABS_X, .value = x },
+ { .type = EV_ABS, .code = ABS_Y, .value = y },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
+ { .type = EV_KEY, .code = BTN_TOOL_FINGER, .value = 1 },
+ { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ };
+
+ move[1].value = litest_scale(d, ABS_X, x);
+ move[2].value = litest_scale(d, ABS_Y, y);
+ move[3].value = litest_scale(d, ABS_X, x);
+ move[4].value = litest_scale(d, ABS_Y, y);
+
+ ARRAY_FOR_EACH(move, ev)
+ litest_event(d, ev->type, ev->code, ev->value);
+}
+
+static struct litest_device_interface interface = {
+ .touch_down = litest_bcm5974_touch_down,
+ .touch_move = litest_bcm5974_move,
+};
+
+void
+litest_create_bcm5974(struct litest_device *d)
+{
+ struct libevdev *dev;
+ struct input_absinfo abs[] = {
+ { ABS_X, 1472, 5472, 75 },
+ { ABS_Y, 1408, 4448, 129 },
+ { ABS_PRESSURE, 0, 255, 0 },
+ { ABS_TOOL_WIDTH, 0, 15, 0 },
+ { ABS_MT_SLOT, 0, 1, 0 },
+ { ABS_MT_POSITION_X, 1472, 5472, 75 },
+ { ABS_MT_POSITION_Y, 1408, 4448, 129 },
+ { ABS_MT_TRACKING_ID, 0, 65535, 0 },
+ { ABS_MT_PRESSURE, 0, 255, 0 }
+ };
+ struct input_absinfo *a;
+ int rc;
+
+ d->interface = &interface;
+
+ dev = libevdev_new();
+ ck_assert(dev != NULL);
+
+ libevdev_set_name(dev, "bcm5974");
+ libevdev_set_id_bustype(dev, 0x3);
+ libevdev_set_id_vendor(dev, 0x5ac);
+ libevdev_set_id_product(dev, 0x249);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_FINGER, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_QUINTTAP, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOUCH, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_DOUBLETAP, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_TRIPLETAP, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_QUADTAP, NULL);
+
+ ARRAY_FOR_EACH(abs, a)
+ libevdev_enable_event_code(dev, EV_ABS, a->value, a);
+
+ rc = libevdev_uinput_create_from_device(dev,
+ LIBEVDEV_UINPUT_OPEN_MANAGED,
+ &d->uinput);
+ ck_assert_int_eq(rc, 0);
+ libevdev_free(dev);
+}
+
+struct litest_test_device litest_bcm5974_device = {
+ .type = LITEST_BCM5974,
+ .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
+ .shortname = "bcm5974",
+ .setup = litest_bcm5974_setup,
+ .teardown = litest_generic_device_teardown,
+ .create = litest_create_bcm5974,
+};
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef LITEST_INT_H
+#define LITEST_INT_H
+#include "litest.h"
+
+struct litest_test_device {
+ enum litest_device_type type;
+ enum litest_device_feature features;
+ const char *shortname;
+ void (*setup)(void); /* test fixture, used by check */
+ void (*teardown)(void); /* test fixture, used by check */
+
+ void (*create)(struct litest_device *d);
+};
+
+struct litest_device_interface {
+ void (*touch_down)(struct litest_device *d, unsigned int slot, int x, int y);
+ void (*touch_move)(struct litest_device *d, unsigned int slot, int x, int y);
+
+ int min[2];
+ int max[2];
+};
+
+void litest_set_current_device(struct litest_device *device);
+int litest_scale(const struct litest_device *d, unsigned int axis, int val);
+void litest_generic_device_teardown(void);
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+#include "libinput-util.h"
+
+static void litest_keyboard_setup(void)
+{
+ struct litest_device *d = litest_create_device(LITEST_KEYBOARD);
+ litest_set_current_device(d);
+}
+
+static struct litest_device_interface interface = {
+};
+
+static void
+litest_create_keyboard(struct litest_device *d)
+{
+ struct libevdev *dev;
+ int rc;
+ const int keys[] = {
+ KEY_MENU,
+ KEY_CALC,
+ KEY_SETUP,
+ KEY_SLEEP,
+ KEY_WAKEUP,
+ KEY_SCREENLOCK,
+ KEY_DIRECTION,
+ KEY_CYCLEWINDOWS,
+ KEY_MAIL,
+ KEY_BOOKMARKS,
+ KEY_COMPUTER,
+ KEY_BACK,
+ KEY_FORWARD,
+ KEY_NEXTSONG,
+ KEY_PLAYPAUSE,
+ KEY_PREVIOUSSONG,
+ KEY_STOPCD,
+ KEY_HOMEPAGE,
+ KEY_REFRESH,
+ KEY_F14,
+ KEY_F15,
+ KEY_SEARCH,
+ KEY_MEDIA,
+ KEY_FN,
+ };
+ int k;
+ const int *key;
+ int delay = 500, period = 30;
+
+ d->interface = &interface;
+
+ dev = libevdev_new();
+ ck_assert(dev != NULL);
+
+ libevdev_set_name(dev, "AT Translated Set 2 keyboard");
+ libevdev_set_id_bustype(dev, 0x11);
+ libevdev_set_id_vendor(dev, 0x1);
+ libevdev_set_id_product(dev, 0x1);
+ for (k = KEY_ESC; k <= KEY_STOP; k++) {
+ if (k == KEY_SCALE)
+ continue;
+ libevdev_enable_event_code(dev, EV_KEY, k, NULL);
+ }
+
+ ARRAY_FOR_EACH(keys, key)
+ libevdev_enable_event_code(dev, EV_KEY, *key, NULL);
+
+ libevdev_enable_event_code(dev, EV_LED, LED_NUML, NULL);
+ libevdev_enable_event_code(dev, EV_LED, LED_CAPSL, NULL);
+ libevdev_enable_event_code(dev, EV_LED, LED_SCROLLL, NULL);
+ libevdev_enable_event_code(dev, EV_MSC, MSC_SCAN, NULL);
+ libevdev_enable_event_code(dev, EV_REP, REP_PERIOD, &period);
+ libevdev_enable_event_code(dev, EV_REP, REP_DELAY, &delay);
+
+ rc = libevdev_uinput_create_from_device(dev,
+ LIBEVDEV_UINPUT_OPEN_MANAGED,
+ &d->uinput);
+ ck_assert_int_eq(rc, 0);
+ libevdev_free(dev);
+}
+
+struct litest_test_device litest_keyboard_device = {
+ .type = LITEST_KEYBOARD,
+ .features = LITEST_KEYBOARD,
+ .shortname = "default keyboard",
+ .setup = litest_keyboard_setup,
+ .teardown = litest_generic_device_teardown,
+ .create = litest_create_keyboard,
+};
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+#include "libinput-util.h"
+
+void litest_synaptics_clickpad_setup(void)
+{
+ struct litest_device *d = litest_create_device(LITEST_SYNAPTICS_CLICKPAD);
+ litest_set_current_device(d);
+}
+
+void
+litest_synaptics_clickpad_touch_down(struct litest_device *d,
+ unsigned int slot,
+ int x, int y)
+{
+ static int tracking_id;
+ struct input_event *ev;
+ struct input_event down[] = {
+ { .type = EV_ABS, .code = ABS_X, .value = x },
+ { .type = EV_ABS, .code = ABS_Y, .value = y },
+ { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 },
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
+ { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = ++tracking_id },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ };
+
+ down[0].value = litest_scale(d, ABS_X, x);
+ down[1].value = litest_scale(d, ABS_Y, y);
+ down[5].value = litest_scale(d, ABS_X, x);
+ down[6].value = litest_scale(d, ABS_Y, y);
+
+ ARRAY_FOR_EACH(down, ev)
+ litest_event(d, ev->type, ev->code, ev->value);
+}
+
+void
+litest_synaptics_clickpad_move(struct litest_device *d,
+ unsigned int slot,
+ int x, int y)
+{
+ struct input_event *ev;
+ struct input_event move[] = {
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
+ { .type = EV_ABS, .code = ABS_X, .value = x },
+ { .type = EV_ABS, .code = ABS_Y, .value = y },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
+ { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
+ { .type = EV_KEY, .code = BTN_TOOL_FINGER, .value = 1 },
+ { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ };
+
+ move[1].value = litest_scale(d, ABS_X, x);
+ move[2].value = litest_scale(d, ABS_Y, y);
+ move[3].value = litest_scale(d, ABS_X, x);
+ move[4].value = litest_scale(d, ABS_Y, y);
+
+ ARRAY_FOR_EACH(move, ev)
+ litest_event(d, ev->type, ev->code, ev->value);
+}
+
+static struct litest_device_interface interface = {
+ .touch_down = litest_synaptics_clickpad_touch_down,
+ .touch_move = litest_synaptics_clickpad_move,
+};
+
+void
+litest_create_synaptics_clickpad(struct litest_device *d)
+{
+ struct libevdev *dev;
+ struct input_absinfo abs[] = {
+ { ABS_X, 1472, 5472, 75 },
+ { ABS_Y, 1408, 4448, 129 },
+ { ABS_PRESSURE, 0, 255, 0 },
+ { ABS_TOOL_WIDTH, 0, 15, 0 },
+ { ABS_MT_SLOT, 0, 1, 0 },
+ { ABS_MT_POSITION_X, 1472, 5472, 75 },
+ { ABS_MT_POSITION_Y, 1408, 4448, 129 },
+ { ABS_MT_TRACKING_ID, 0, 65535, 0 },
+ { ABS_MT_PRESSURE, 0, 255, 0 }
+ };
+ struct input_absinfo *a;
+ int rc;
+
+ d->interface = &interface;
+
+ dev = libevdev_new();
+ ck_assert(dev != NULL);
+
+ libevdev_set_name(dev, "SynPS/2 Synaptics TouchPad");
+ libevdev_set_id_bustype(dev, 0x11);
+ libevdev_set_id_vendor(dev, 0x2);
+ libevdev_set_id_product(dev, 0x11);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_FINGER, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_QUINTTAP, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOUCH, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_DOUBLETAP, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_TRIPLETAP, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_QUADTAP, NULL);
+
+ ARRAY_FOR_EACH(abs, a)
+ libevdev_enable_event_code(dev, EV_ABS, a->value, a);
+
+ rc = libevdev_uinput_create_from_device(dev,
+ LIBEVDEV_UINPUT_OPEN_MANAGED,
+ &d->uinput);
+ ck_assert_int_eq(rc, 0);
+ libevdev_free(dev);
+}
+
+struct litest_test_device litest_synaptics_clickpad_device = {
+ .type = LITEST_SYNAPTICS_CLICKPAD,
+ .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
+ .shortname = "synaptics",
+ .setup = litest_synaptics_clickpad_setup,
+ .teardown = litest_generic_device_teardown,
+ .create = litest_create_synaptics_clickpad,
+};
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+#include "libinput-util.h"
+
+static void litest_trackpoint_setup(void)
+{
+ struct litest_device *d = litest_create_device(LITEST_TRACKPOINT);
+ litest_set_current_device(d);
+}
+
+static struct litest_device_interface interface = {
+};
+
+static void
+litest_create_trackpoint(struct litest_device *d)
+{
+ struct libevdev *dev;
+ int rc;
+
+ d->interface = &interface;
+ dev = libevdev_new();
+ ck_assert(dev != NULL);
+
+ libevdev_set_name(dev, "TPPS/2 IBM TrackPoint");
+ libevdev_set_id_bustype(dev, 0x11);
+ libevdev_set_id_vendor(dev, 0x2);
+ libevdev_set_id_product(dev, 0xa);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_RIGHT, NULL);
+ libevdev_enable_event_code(dev, EV_KEY, BTN_MIDDLE, NULL);
+ libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
+ libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
+
+ rc = libevdev_uinput_create_from_device(dev,
+ LIBEVDEV_UINPUT_OPEN_MANAGED,
+ &d->uinput);
+ ck_assert_int_eq(rc, 0);
+ libevdev_free(dev);
+}
+
+struct litest_test_device litest_trackpoint_device = {
+ .type = LITEST_TRACKPOINT,
+ .features = LITEST_POINTER | LITEST_BUTTON,
+ .shortname = "trackpoint",
+ .setup = litest_trackpoint_setup,
+ .teardown = litest_generic_device_teardown,
+ .create = litest_create_trackpoint,
+};
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <check.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <sys/ptrace.h>
+#include <sys/timerfd.h>
+#include <sys/wait.h>
+
+#include "litest.h"
+#include "litest-int.h"
+#include "libinput-util.h"
+
+static int in_debugger = -1;
+
+struct test {
+ struct list node;
+ char *name;
+ TCase *tc;
+ enum litest_device_type devices;
+};
+
+struct suite {
+ struct list node;
+ struct list tests;
+ char *name;
+ Suite *suite;
+};
+
+static struct litest_device *current_device;
+
+struct litest_device *litest_current_device(void) {
+ return current_device;
+}
+
+void litest_set_current_device(struct litest_device *device) {
+ current_device = device;
+}
+
+void litest_generic_device_teardown(void)
+{
+ litest_delete_device(current_device);
+ current_device = NULL;
+}
+
+extern struct litest_test_device litest_keyboard_device;
+extern struct litest_test_device litest_synaptics_clickpad_device;
+extern struct litest_test_device litest_trackpoint_device;
+extern struct litest_test_device litest_bcm5974_device;
+
+struct litest_test_device* devices[] = {
+ &litest_synaptics_clickpad_device,
+ &litest_keyboard_device,
+ &litest_trackpoint_device,
+ &litest_bcm5974_device,
+ NULL,
+};
+
+
+static struct list all_tests;
+
+static void
+litest_add_tcase_for_device(struct suite *suite,
+ void *func,
+ const struct litest_test_device *dev)
+{
+ struct test *t;
+ const char *test_name = dev->shortname;
+
+ list_for_each(t, &suite->tests, node) {
+ if (strcmp(t->name, test_name) != 0)
+ continue;
+
+ tcase_add_test(t->tc, func);
+ return;
+ }
+
+ t = zalloc(sizeof(*t));
+ t->name = strdup(test_name);
+ t->tc = tcase_create(test_name);
+ list_insert(&suite->tests, &t->node);
+ tcase_add_checked_fixture(t->tc, dev->setup, dev->teardown);
+ tcase_add_test(t->tc, func);
+ suite_add_tcase(suite->suite, t->tc);
+}
+
+static void
+litest_add_tcase_no_device(struct suite *suite, void *func)
+{
+ struct test *t;
+ const char *test_name = "no device";
+
+ list_for_each(t, &suite->tests, node) {
+ if (strcmp(t->name, test_name) != 0)
+ continue;
+
+ tcase_add_test(t->tc, func);
+ return;
+ }
+
+ t = zalloc(sizeof(*t));
+ t->name = strdup(test_name);
+ t->tc = tcase_create(test_name);
+ list_insert(&suite->tests, &t->node);
+ tcase_add_test(t->tc, func);
+ suite_add_tcase(suite->suite, t->tc);
+}
+
+static void
+litest_add_tcase(struct suite *suite, void *func,
+ enum litest_device_feature required,
+ enum litest_device_feature excluded)
+{
+ struct litest_test_device **dev = devices;
+
+ if (required == LITEST_DISABLE_DEVICE &&
+ excluded == LITEST_DISABLE_DEVICE) {
+ litest_add_tcase_no_device(suite, func);
+ } else if (required != LITEST_ANY || excluded != LITEST_ANY) {
+ while (*dev) {
+ if (((*dev)->features & required) == required &&
+ ((*dev)->features & excluded) == 0)
+ litest_add_tcase_for_device(suite, func, *dev);
+ dev++;
+ }
+ } else {
+ while (*dev) {
+ litest_add_tcase_for_device(suite, func, *dev);
+ dev++;
+ }
+ }
+}
+
+void
+litest_add_no_device(const char *name, void *func)
+{
+ litest_add(name, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE);
+}
+
+void
+litest_add(const char *name,
+ void *func,
+ enum litest_device_feature required,
+ enum litest_device_feature excluded)
+{
+ struct suite *s;
+
+ if (all_tests.next == NULL && all_tests.prev == NULL)
+ list_init(&all_tests);
+
+ list_for_each(s, &all_tests, node) {
+ if (strcmp(s->name, name) == 0) {
+ litest_add_tcase(s, func, required, excluded);
+ return;
+ }
+ }
+
+ s = zalloc(sizeof(*s));
+ s->name = strdup(name);
+ s->suite = suite_create(s->name);
+
+ list_init(&s->tests);
+ list_insert(&all_tests, &s->node);
+ litest_add_tcase(s, func, required, excluded);
+}
+
+int is_debugger_attached()
+{
+ 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)
+{
+ struct suite *s;
+
+ list_for_each(s, tests, node) {
+ struct test *t;
+ printf("%s:\n", s->name);
+ list_for_each(t, &s->tests, node) {
+ printf(" %s\n", t->name);
+ }
+ }
+}
+
+static const struct option opts[] = {
+ { "list", 0, 0, 'l' },
+ { 0, 0, 0, 0}
+};
+
+int
+litest_run(int argc, char **argv) {
+ struct suite *s, *snext;
+ int failed;
+ SRunner *sr = NULL;
+
+ if (in_debugger == -1) {
+ in_debugger = is_debugger_attached();
+ if (in_debugger)
+ 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);
+ }
+
+ while(1) {
+ int c;
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "", opts, &option_index);
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'l':
+ litest_list_tests(&all_tests);
+ return 0;
+ }
+ }
+
+ srunner_run_all(sr, CK_NORMAL);
+ failed = srunner_ntests_failed(sr);
+ srunner_free(sr);
+
+ 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);
+ }
+
+ return failed;
+}
+
+static int
+open_restricted(const char *path, int flags, void *userdata)
+{
+ return open(path, flags);
+}
+
+static void
+close_restricted(int fd, void *userdata)
+{
+ close(fd);
+}
+
+const struct libinput_interface interface = {
+ .open_restricted = open_restricted,
+ .close_restricted = close_restricted,
+};
+
+struct litest_device *
+litest_create_device(enum litest_device_type which)
+{
+ struct litest_device *d = zalloc(sizeof(*d));
+ int fd;
+ int rc;
+ const char *path;
+ struct litest_test_device **dev;
+
+ ck_assert(d != NULL);
+
+ dev = devices;
+ while (*dev) {
+ if ((*dev)->type == which) {
+ (*dev)->create(d);
+ break;
+ }
+ dev++;
+ }
+
+ if (!dev) {
+ ck_abort_msg("Invalid device type %d\n", which);
+ return NULL;
+ }
+
+ path = libevdev_uinput_get_devnode(d->uinput);
+ ck_assert(path != NULL);
+ fd = open(path, O_RDWR|O_NONBLOCK);
+ ck_assert_int_ne(fd, -1);
+
+ rc = libevdev_new_from_fd(fd, &d->evdev);
+ ck_assert_int_eq(rc, 0);
+
+ d->libinput = libinput_create_from_path(&interface, NULL, path);
+ ck_assert(d->libinput != NULL);
+
+ d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, ABS_X);
+ d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, ABS_X);
+ 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);
+ return d;
+}
+
+int
+litest_handle_events(struct litest_device *d)
+{
+ struct pollfd fd;
+
+ fd.fd = libinput_get_fd(d->libinput);
+ fd.events = POLLIN;
+
+ while (poll(&fd, 1, 1))
+ libinput_dispatch(d->libinput);
+
+ return 0;
+}
+
+void
+litest_delete_device(struct litest_device *d)
+{
+ if (!d)
+ return;
+
+ libinput_destroy(d->libinput);
+ libevdev_free(d->evdev);
+ libevdev_uinput_destroy(d->uinput);
+ memset(d,0, sizeof(*d));
+ free(d);
+}
+
+void
+litest_event(struct litest_device *d, unsigned int type,
+ unsigned int code, int value)
+{
+ libevdev_uinput_write_event(d->uinput, type, code, value);
+}
+
+void
+litest_touch_down(struct litest_device *d, unsigned int slot, int x, int y)
+{
+ d->interface->touch_down(d, slot, x, y);
+}
+
+void
+litest_touch_up(struct litest_device *d, unsigned int slot)
+{
+ struct input_event *ev;
+ struct input_event up[] = {
+ { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
+ { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ };
+
+ ARRAY_FOR_EACH(up, ev)
+ litest_event(d, ev->type, ev->code, ev->value);
+}
+
+void
+litest_touch_move(struct litest_device *d, unsigned int slot, int x, int y)
+{
+ d->interface->touch_move(d, slot, x, y);
+}
+
+void
+litest_touch_move_to(struct litest_device *d,
+ unsigned int slot,
+ int x_from, int y_from,
+ int x_to, int y_to,
+ int steps)
+{
+ for (int i = 0; i < steps - 1; i++)
+ litest_touch_move(d, slot,
+ x_from + (x_to - x_from)/steps * i,
+ y_from + (y_to - y_from)/steps * i);
+ litest_touch_move(d, slot, x_to, y_to);
+}
+
+void
+litest_click(struct litest_device *d, unsigned int button, bool is_press)
+{
+
+ struct input_event *ev;
+ struct input_event click[] = {
+ { .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 },
+ { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+ };
+
+ ARRAY_FOR_EACH(click, ev)
+ litest_event(d, ev->type, ev->code, ev->value);
+}
+
+int litest_scale(const struct litest_device *d, unsigned int axis, int val)
+{
+ int min, max;
+ ck_assert_int_ge(val, 0);
+ ck_assert_int_le(val, 100);
+ ck_assert_int_le(axis, ABS_Y);
+
+ min = d->interface->min[axis];
+ max = d->interface->max[axis];
+ return (max - min) * val/100.0 + min;
+}
--- /dev/null
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef LITEST_H
+#define LITEST_H
+
+#include <stdbool.h>
+#include <check.h>
+#include <libevdev/libevdev.h>
+#include <libevdev/libevdev-uinput.h>
+#include <libinput.h>
+
+enum litest_device_type {
+ LITEST_NO_DEVICE = -1,
+ LITEST_SYNAPTICS_CLICKPAD,
+ LITEST_BCM5974,
+ LITEST_KEYBOARD,
+ LITEST_TRACKPOINT,
+};
+
+enum litest_device_feature {
+ LITEST_DISABLE_DEVICE = -1,
+ LITEST_ANY = 0,
+ LITEST_TOUCHPAD = 1 << 0,
+ LITEST_CLICKPAD = 1 << 1,
+ LITEST_BUTTON = 1 << 2,
+ LITEST_KEYS = 1 << 3,
+ LITEST_POINTER = 1 << 4,
+};
+
+struct litest_device {
+ struct libevdev *evdev;
+ struct libevdev_uinput *uinput;
+ struct libinput *libinput;
+ struct litest_device_interface *interface;
+};
+
+void litest_add(const char *name, void *func,
+ enum litest_device_feature required_feature,
+ enum litest_device_feature excluded_feature);
+void litest_add_no_device(const char *name, void *func);
+
+int litest_run(int argc, char **argv);
+struct litest_device * litest_create_device(enum litest_device_type which);
+struct litest_device *litest_current_device(void);
+void litest_delete_device(struct litest_device *d);
+int litest_handle_events(struct litest_device *d);
+
+void litest_event(struct litest_device *t,
+ unsigned int type,
+ unsigned int code,
+ int value);
+void litest_touch_up(struct litest_device *d, unsigned int slot);
+void litest_touch_move(struct litest_device *d,
+ unsigned int slot,
+ int x,
+ int y);
+void litest_touch_down(struct litest_device *d,
+ unsigned int slot,
+ int x,
+ int y);
+void litest_touch_move_to(struct litest_device *d,
+ unsigned int slot,
+ int x_from, int y_from,
+ int x_to, int y_to,
+ int steps);
+void litest_button_click(struct litest_device *d,
+ unsigned int button,
+ bool is_press);
+
+#endif /* LITEST_H */