// SPDX-License-Identifier: MIT
/*
 * Copyright © 2013 Red Hat, Inc.
 */

#include "config.h"
#include <linux/input.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>

#include "test-common.h"

static int evbits[] = {
	EV_SYN, EV_KEY, EV_REL, EV_ABS, EV_MSC,
	EV_SW, EV_LED, EV_SND, EV_FF,
	/* Intentionally skipping these, they're different
	 * EV_PWR, EV_FF_STATUS, EV_REP, */
	-1,
};

START_TEST(test_has_ev_bit)
{
	int *evbit = evbits;

	while(*evbit != -1) {
		struct uinput_device* uidev;
		struct libevdev *dev;
		int i;

		if (*evbit == EV_ABS) {
			struct input_absinfo abs = { ABS_X, 0, 2, 0, 0, 0};
			test_create_abs_device(&uidev, &dev,
					       1, &abs,
					       -1);
		} else
			test_create_device(&uidev, &dev,
					   *evbit, 0,
					   -1);

		ck_assert_msg(libevdev_has_event_type(dev, EV_SYN), "for event type %d\n", *evbit);
		ck_assert_msg(libevdev_has_event_type(dev, *evbit), "for event type %d\n", *evbit);

		for (i = 0; i <= EV_MAX; i++) {
			if (i == EV_SYN || i == *evbit)
				continue;

			ck_assert_msg(!libevdev_has_event_type(dev, i), "for event type %d\n", i);
		}

		libevdev_free(dev);
		uinput_device_free(uidev);

		evbit++;
	}
}
END_TEST

START_TEST(test_ev_bit_limits)
{
	int *evbit = evbits;

	while(*evbit != -1) {
		struct uinput_device* uidev;
		struct libevdev *dev;

		if (*evbit == EV_ABS) {
			struct input_absinfo abs = { ABS_X, 0, 2, 0, 0, 0};
			test_create_abs_device(&uidev, &dev,
					       1, &abs,
					       -1);
		} else
			test_create_device(&uidev, &dev,
					   *evbit, 0,
					   -1);

		ck_assert_int_eq(libevdev_has_event_type(dev, EV_MAX + 1), 0);
		ck_assert_int_eq(libevdev_has_event_type(dev, INT_MAX), 0);
		ck_assert_int_eq(libevdev_has_event_type(dev, UINT_MAX), 0);

		libevdev_free(dev);
		uinput_device_free(uidev);

		evbit++;
	}
}
END_TEST

START_TEST(test_event_codes)
{
	int *evbit = evbits;

	while(*evbit != -1) {
		struct uinput_device* uidev;
		struct libevdev *dev;
		int code, max;
		if (*evbit == EV_SYN) {
			evbit++;
			continue;
		}

#ifdef __FreeBSD__
		/* Force feedback events are not supported by FreeBSD */
		if (*evbit == EV_FF) {
			evbit++;
			continue;
		}
#endif

		max = libevdev_event_type_get_max(*evbit);

		for (code = 1; code < max; code += 10) {
			if (*evbit == EV_ABS) {
				struct input_absinfo abs = { code, 0, 2, 0, 0, 0};
				test_create_abs_device(&uidev, &dev,
						       1, &abs,
						       -1);
			} else {
				test_create_device(&uidev, &dev,
						   *evbit, code,
						   -1);
			}

			ck_assert_msg(libevdev_has_event_type(dev, *evbit), "for event type %d\n", *evbit);
			ck_assert_msg(libevdev_has_event_code(dev, *evbit, code), "for type %d code %d", *evbit, code);
			ck_assert_msg(libevdev_has_event_code(dev, EV_SYN, SYN_REPORT), "for EV_SYN");
			/* always false */
			ck_assert_msg(!libevdev_has_event_code(dev, EV_PWR, 0), "for EV_PWR");

			libevdev_free(dev);
			uinput_device_free(uidev);
		}

		evbit++;
	}
}
END_TEST

START_TEST(test_event_code_limits)
{
	int *evbit = evbits;

	while(*evbit != -1) {
		struct uinput_device* uidev;
		struct libevdev *dev;
		int max;

		if (*evbit == EV_SYN) {
			evbit++;
			continue;
		}

		max = libevdev_event_type_get_max(*evbit);
		ck_assert(max != -1);

		if (*evbit == EV_ABS) {
			struct input_absinfo abs = { ABS_X, 0, 2, 0, 0, 0};
			test_create_abs_device(&uidev, &dev,
					       1, &abs,
					       -1);
		} else
			test_create_device(&uidev, &dev,
					   *evbit, 1,
					   -1);

		ck_assert_msg(!libevdev_has_event_code(dev, *evbit, max), "for type %d code %d", *evbit, max);
		ck_assert_msg(!libevdev_has_event_code(dev, *evbit, INT_MAX), "for type %d code %d", *evbit, INT_MAX);
		ck_assert_msg(!libevdev_has_event_code(dev, *evbit, UINT_MAX), "for type %d code %d", *evbit, UINT_MAX);

		libevdev_free(dev);
		uinput_device_free(uidev);

		evbit++;
	}
}
END_TEST

START_TEST(test_ev_rep)
{
	struct libevdev *dev;
	struct uinput_device* uidev;
	int rc;
	int rep, delay;
	const int KERNEL_DEFAULT_REP = 250;
	const int KERNEL_DEFAULT_DELAY = 33;

	/* EV_REP is special, it's always fully set if set at all,
	   can't test this through uinput though */
	uidev = uinput_device_new(TEST_DEVICE_NAME);
	ck_assert(uidev != NULL);
	rc = uinput_device_set_bit(uidev, EV_REP);
	ck_assert_int_eq(rc, 0);

	rc = uinput_device_create(uidev);
	ck_assert_int_eq(rc, 0);

	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
	ck_assert_int_eq(rc, 0);

	ck_assert_int_eq(libevdev_has_event_type(dev, EV_REP), 1);
	ck_assert_int_eq(libevdev_has_event_code(dev, EV_REP, REP_DELAY), 1);
	ck_assert_int_eq(libevdev_has_event_code(dev, EV_REP, REP_PERIOD), 1);

	ck_assert_int_eq(libevdev_get_repeat(dev, &rep, &delay), 0);
	/* default values as set by the kernel,
	   see drivers/input/input.c:input_register_device() */
	ck_assert_int_eq(rep, KERNEL_DEFAULT_REP);
	ck_assert_int_eq(delay, KERNEL_DEFAULT_DELAY);

	libevdev_free(dev);
	uinput_device_free(uidev);
}
END_TEST

START_TEST(test_ev_rep_values)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	int delay = 0xab, period = 0xbc;

	/* EV_REP is special, it's always fully set if set at all, can't set
	   it through uinput though. */
	test_create_device(&uidev, &dev, -1);

	ck_assert_int_eq(libevdev_get_repeat(dev, NULL, NULL), -1);
	ck_assert_int_eq(libevdev_get_repeat(dev, &delay, NULL), -1);
	ck_assert_int_eq(libevdev_get_repeat(dev, NULL, &period), -1);
	ck_assert_int_eq(libevdev_get_repeat(dev, &delay, &period), -1);

	ck_assert_int_eq(delay, 0xab);
	ck_assert_int_eq(period, 0xbc);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_input_props)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	int rc, i;
	struct input_absinfo abs = { .value = 0, .minimum = 0, .maximum = 2};

	uidev = uinput_device_new(TEST_DEVICE_NAME);
	rc = uinput_device_set_abs_bit(uidev, ABS_X, &abs);
	ck_assert_int_eq(rc, 0);
	uinput_device_set_prop(uidev, INPUT_PROP_DIRECT);
	uinput_device_set_prop(uidev, INPUT_PROP_BUTTONPAD);
	rc = uinput_device_create(uidev);
	ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));

	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));

	for (i = 0; i < INPUT_PROP_CNT; i++) {
		if (i == INPUT_PROP_DIRECT || i == INPUT_PROP_BUTTONPAD)
			ck_assert_int_eq(libevdev_has_property(dev, i), 1);
		else
			ck_assert_int_eq(libevdev_has_property(dev, i), 0);
	}

	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_MAX + 1), 0);
	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_MAX), 0);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_set_input_props)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	int rc, fd;
	struct input_absinfo abs = { .value = 0, .minimum = 0, .maximum = 2};

	dev = libevdev_new();
	ck_assert_int_eq(libevdev_enable_property(dev, INPUT_PROP_MAX + 1), -1);
	ck_assert_int_eq(libevdev_enable_property(dev, INPUT_PROP_DIRECT), 0);
	ck_assert_int_eq(libevdev_enable_property(dev, INPUT_PROP_BUTTONPAD), 0);
	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_DIRECT), 1);
	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_BUTTONPAD), 1);

	uidev = uinput_device_new(TEST_DEVICE_NAME);
	rc = uinput_device_set_abs_bit(uidev, ABS_X, &abs);
	ck_assert_int_eq(rc, 0);
	uinput_device_set_prop(uidev, INPUT_PROP_BUTTONPAD);
	rc = uinput_device_create(uidev);
	ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));

	fd = uinput_device_get_fd(uidev);
	rc = libevdev_set_fd(dev, fd);
	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));

	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_DIRECT), 0);
	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_BUTTONPAD), 1);

	/* Test disabling the properties too */
	ck_assert_int_eq(libevdev_disable_property(dev, INPUT_PROP_MAX + 1), -1);
	ck_assert_int_eq(libevdev_disable_property(dev, INPUT_PROP_DIRECT), 0);
	ck_assert_int_eq(libevdev_disable_property(dev, INPUT_PROP_BUTTONPAD), 0);
	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_DIRECT), 0);
	ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_BUTTONPAD), 0);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_slot_init_value)
{
	struct uinput_device *uidev;
	struct libevdev *dev;
	int rc;
	const int nabs = 6;
	int i;
	int fd;
	struct input_absinfo abs[] = {
		{ .value = ABS_X, .minimum = 0, .maximum = 1000 },
		{ .value = ABS_Y, .minimum = 0, .maximum = 1000 },
		{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 1000 },
		{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 1000 },
		{ .value = ABS_MT_TRACKING_ID, .minimum = -1, .maximum = 2 },
		{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = 1 }
	};

	uidev = uinput_device_new(TEST_DEVICE_NAME);

	for (i = 0; i < nabs; i++) {
		rc = uinput_device_set_abs_bit(uidev, abs[i].value, &abs[i]);
		ck_assert_int_eq(rc, 0);
	}

	rc = uinput_device_create(uidev);
	ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));

	fd = uinput_device_get_fd(uidev);
	rc = fcntl(fd, F_SETFL, O_NONBLOCK);
	ck_assert_msg(rc == 0, "fcntl failed: %s", strerror(errno));

	uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 0);
	uinput_device_event(uidev, EV_ABS, ABS_X, 100);
	uinput_device_event(uidev, EV_ABS, ABS_Y, 500);
	uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100);
	uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 500);
	uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 1);
	uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1);
	uinput_device_event(uidev, EV_ABS, ABS_X, 1);
	uinput_device_event(uidev, EV_ABS, ABS_Y, 5);
	uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 1);
	uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 5);
	uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 2);
	uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);

	rc = libevdev_new_from_fd(fd, &dev);
	ck_assert_int_eq(rc, 0);

	ck_assert_int_eq(libevdev_get_current_slot(dev), 1);
	ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 100);
	ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_Y), 500);
	ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 1);
	ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_Y), 5);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_no_slots)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs[] = {
		{ .value = ABS_X, .minimum = 0, .maximum = 2 },
		{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 }
	};

	test_create_abs_device(&uidev, &dev, 4, abs,
			       -1);

	ck_assert_int_eq(libevdev_get_num_slots(dev), -1);
	ck_assert_int_eq(libevdev_get_current_slot(dev), -1);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_slot_number)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	const int nslots = 4;
	struct input_absinfo abs[] = {
		{ .value = ABS_X, .minimum = 0, .maximum = 2 },
		{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = nslots - 1 }
	};

	test_create_abs_device(&uidev, &dev, 5, abs,
			       -1);

	ck_assert_int_eq(libevdev_get_num_slots(dev), nslots);
	ck_assert_int_eq(libevdev_get_current_slot(dev), 0);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_invalid_mt_device)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	const int nslots = 4;
	int value;
	struct input_absinfo abs[] = {
		{ .value = ABS_X, .minimum = 0, .maximum = 2 },
		{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_SLOT - 1, .minimum = 0, .maximum = 2 },
		{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = nslots - 1 }
	};

	test_create_abs_device(&uidev, &dev, 6, abs,
			       -1);

	ck_assert_int_eq(libevdev_get_num_slots(dev), -1);
	ck_assert_int_eq(libevdev_get_current_slot(dev), -1);
	ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_X, 0), -1);
	ck_assert_int_eq(libevdev_fetch_slot_value(dev, 0, ABS_MT_POSITION_X, &value), 0);

	ck_assert(libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT - 1));
	ck_assert(libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT));

	ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, 1), 0);
	ck_assert(libevdev_get_event_value(dev, EV_ABS, ABS_MT_SLOT) == 1);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_name)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_id ids = {1, 2, 3, 4};
	const char *str;
	int rc;

	dev = libevdev_new();

	str = libevdev_get_name(dev);
	ck_assert(str != NULL);
	ck_assert_int_eq(strlen(str), 0);

	rc = uinput_device_new_with_events(&uidev, TEST_DEVICE_NAME, &ids,
					   EV_REL, REL_X,
					   -1);
	ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));
	rc = libevdev_set_fd(dev, uinput_device_get_fd(uidev));
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;

	str = libevdev_get_name(dev);
	ck_assert_int_eq(strcmp(str, TEST_DEVICE_NAME), 0);

	str = libevdev_get_phys(dev);
	ck_assert(str == NULL);

	str = libevdev_get_uniq(dev);
	ck_assert(str == NULL);

	ck_assert_int_eq(libevdev_get_id_bustype(dev), ids.bustype);
	ck_assert_int_eq(libevdev_get_id_vendor(dev), ids.vendor);
	ck_assert_int_eq(libevdev_get_id_product(dev), ids.product);
	ck_assert_int_eq(libevdev_get_id_version(dev), ids.version);
	ck_assert_int_eq(libevdev_get_driver_version(dev), EV_VERSION);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_set_name)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_id ids = {1, 2, 3, 4};
	const char *str;
	int rc;

	dev = libevdev_new();

	libevdev_set_name(dev, "the name");
	libevdev_set_phys(dev, "the phys");
	libevdev_set_uniq(dev, "the uniq");

	str = libevdev_get_name(dev);
	ck_assert(str != NULL);
	ck_assert_int_eq(strcmp(str, "the name"), 0);

	str = libevdev_get_phys(dev);
	ck_assert(str != NULL);
	ck_assert_int_eq(strcmp(str, "the phys"), 0);

	str = libevdev_get_uniq(dev);
	ck_assert(str != NULL);
	ck_assert_int_eq(strcmp(str, "the uniq"), 0);

	rc = uinput_device_new_with_events(&uidev, TEST_DEVICE_NAME, &ids,
					   EV_REL, REL_X,
					   -1);
	ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));
	rc = libevdev_set_fd(dev, uinput_device_get_fd(uidev));
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;

	str = libevdev_get_name(dev);
	ck_assert_int_eq(strcmp(str, TEST_DEVICE_NAME), 0);

	str = libevdev_get_phys(dev);
	ck_assert(str == NULL);

	str = libevdev_get_uniq(dev);
	ck_assert(str == NULL);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_set_ids)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_id ids = {1, 2, 3, 4};
	int rc;

	dev = libevdev_new();

	libevdev_set_id_product(dev, 10);
	libevdev_set_id_vendor(dev, 20);
	libevdev_set_id_bustype(dev, 30);
	libevdev_set_id_version(dev, 40);

	ck_assert_int_eq(libevdev_get_id_product(dev), 10);
	ck_assert_int_eq(libevdev_get_id_vendor(dev), 20);
	ck_assert_int_eq(libevdev_get_id_bustype(dev), 30);
	ck_assert_int_eq(libevdev_get_id_version(dev), 40);

	rc = uinput_device_new_with_events(&uidev, TEST_DEVICE_NAME, &ids,
					   EV_REL, REL_X,
					   -1);
	ck_assert_msg(rc == 0, "Failed to create uinput device: %s", strerror(-rc));
	rc = libevdev_set_fd(dev, uinput_device_get_fd(uidev));
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;

	ck_assert_int_eq(libevdev_get_id_bustype(dev), ids.bustype);
	ck_assert_int_eq(libevdev_get_id_vendor(dev), ids.vendor);
	ck_assert_int_eq(libevdev_get_id_product(dev), ids.product);
	ck_assert_int_eq(libevdev_get_id_version(dev), ids.version);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_get_abs_info)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs;
	const struct input_absinfo *a;
	int rc;

	uidev = uinput_device_new(TEST_DEVICE_NAME);
	ck_assert(uidev != NULL);

	abs.minimum = 0;
	abs.maximum = 1000;
	abs.fuzz = 1;
	abs.flat = 2;
	abs.resolution = 3;
	abs.value = 0;

	uinput_device_set_abs_bit(uidev, ABS_X, &abs);
	uinput_device_set_abs_bit(uidev, ABS_MT_POSITION_X, &abs);

	abs.minimum = -500;
	abs.maximum = 500;
	abs.fuzz = 10;
	abs.flat = 20;
	abs.resolution = 30;
	abs.value = 0;

	uinput_device_set_abs_bit(uidev, ABS_Y, &abs);
	uinput_device_set_abs_bit(uidev, ABS_MT_POSITION_Y, &abs);

	rc = uinput_device_create(uidev);
	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));

	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_MAX + 1), 0);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_MAX + 1), 0);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_MAX + 1), 0);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_MAX + 1), 0);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_MAX + 1), 0);
	ck_assert(!libevdev_get_abs_info(dev, ABS_MAX + 1));

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_X), 0);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_X), 1000);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_X), 1);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_X), 2);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_X), 3);
	a = libevdev_get_abs_info(dev, ABS_X);
	ck_assert(a != NULL);
	ck_assert_int_eq(a->minimum, 0);
	ck_assert_int_eq(a->maximum, 1000);
	ck_assert_int_eq(a->fuzz, 1);
	ck_assert_int_eq(a->flat, 2);
	ck_assert_int_eq(a->resolution, 3);

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_MT_POSITION_X), 0);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_MT_POSITION_X), 1000);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_MT_POSITION_X), 1);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_MT_POSITION_X), 2);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_MT_POSITION_X), 3);
	a = libevdev_get_abs_info(dev, ABS_MT_POSITION_X);
	ck_assert(a != NULL);
	ck_assert_int_eq(a->minimum, 0);
	ck_assert_int_eq(a->maximum, 1000);
	ck_assert_int_eq(a->fuzz, 1);
	ck_assert_int_eq(a->flat, 2);
	ck_assert_int_eq(a->resolution, 3);

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_Y), -500);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_Y), 500);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_Y), 10);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_Y), 20);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_Y), 30);
	a = libevdev_get_abs_info(dev, ABS_Y);
	ck_assert(a != NULL);
	ck_assert_int_eq(a->minimum, -500);
	ck_assert_int_eq(a->maximum, 500);
	ck_assert_int_eq(a->fuzz, 10);
	ck_assert_int_eq(a->flat, 20);
	ck_assert_int_eq(a->resolution, 30);

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_MT_POSITION_Y), -500);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_MT_POSITION_Y), 500);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_MT_POSITION_Y), 10);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_MT_POSITION_Y), 20);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_MT_POSITION_Y), 30);
	a = libevdev_get_abs_info(dev, ABS_MT_POSITION_Y);
	ck_assert(a != NULL);
	ck_assert_int_eq(a->minimum, -500);
	ck_assert_int_eq(a->maximum, 500);
	ck_assert_int_eq(a->fuzz, 10);
	ck_assert_int_eq(a->flat, 20);
	ck_assert_int_eq(a->resolution, 30);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_set_abs)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs[2];
	struct input_absinfo a;

	memset(abs, 0, sizeof(abs));
	abs[0].value = ABS_X;
	abs[0].maximum = 1000;

	abs[1].value = ABS_Y;
	abs[1].maximum = 1000;

	test_create_abs_device(&uidev, &dev,
			       2, abs,
			       EV_SYN,
			       -1);

	libevdev_set_abs_minimum(dev, ABS_X, 1);
	libevdev_set_abs_minimum(dev, ABS_Y, 5);
	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_X),  1);
	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_Y),  5);

	libevdev_set_abs_maximum(dev, ABS_X, 3000);
	libevdev_set_abs_maximum(dev, ABS_Y, 5000);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_X),  3000);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_Y),  5000);

	libevdev_set_abs_fuzz(dev, ABS_X, 3);
	libevdev_set_abs_fuzz(dev, ABS_Y, 5);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_X),  3);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_Y),  5);

	libevdev_set_abs_flat(dev, ABS_X, 8);
	libevdev_set_abs_flat(dev, ABS_Y, 15);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_X),  8);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_Y),  15);

	libevdev_set_abs_resolution(dev, ABS_X, 80);
	libevdev_set_abs_resolution(dev, ABS_Y, 150);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_X),  80);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_Y),  150);

	a.value = 0;
	a.minimum = 10;
	a.maximum = 100;
	a.fuzz = 13;
	a.flat = 1;
	a.resolution = 16;

	libevdev_set_abs_info(dev, ABS_X, &a);
	ck_assert_int_eq(memcmp(&a, libevdev_get_abs_info(dev, ABS_X), sizeof(a)), 0);

	libevdev_set_abs_minimum(dev, ABS_Z, 10);
	ck_assert_int_eq(libevdev_has_event_code(dev, EV_ABS, ABS_Z),  0);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_enable_bit)
{
	struct uinput_device* uidev;
	struct libevdev *dev, *dev2;
	struct input_absinfo abs = { .value = ABS_X, .minimum = 0, .maximum = 2 };
	int rc;

	test_create_abs_device(&uidev, &dev, 1, &abs,
			       -1);

	ck_assert(!libevdev_has_event_code(dev, EV_ABS, ABS_Y));
	ck_assert(!libevdev_has_event_type(dev, EV_REL));
	ck_assert(!libevdev_has_event_code(dev, EV_REL, REL_X));

	abs.minimum = 0;
	abs.maximum = 100;
	abs.fuzz = 1;
	abs.flat = 2;
	abs.resolution = 3;

	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_ABS, ABS_Y, &abs), 0);
	ck_assert(libevdev_has_event_code(dev, EV_ABS, ABS_Y));

	ck_assert_int_eq(libevdev_enable_event_type(dev, EV_REL), 0);
	ck_assert(libevdev_has_event_type(dev, EV_REL));
	ck_assert(!libevdev_has_event_code(dev, EV_REL, REL_X));

	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_REL, REL_X, NULL), 0);
	ck_assert(libevdev_has_event_code(dev, EV_REL, REL_X));

	/* make sure kernel device is unchanged */
	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev2);
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));
	ck_assert(libevdev_has_event_code(dev2, EV_ABS, ABS_X));
	ck_assert(!libevdev_has_event_code(dev2, EV_ABS, ABS_Y));
	ck_assert(!libevdev_has_event_type(dev2, EV_REL));
	ck_assert(!libevdev_has_event_code(dev2, EV_REL, REL_X));
	libevdev_free(dev2);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_enable_bit_invalid)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs = { .value = ABS_X, .minimum = 0, .maximum = 1 };

	test_create_abs_device(&uidev, &dev, 1, &abs,
			       -1);

	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_ABS, ABS_MAX + 1, &abs), -1);
	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_MAX + 1, ABS_MAX + 1, &abs), -1);
	ck_assert_int_eq(libevdev_enable_event_type(dev, EV_MAX + 1), -1);
	/* there's a gap between EV_SW and EV_LED */
	ck_assert_int_eq(libevdev_enable_event_type(dev, EV_LED - 1), -1);
	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_LED - 1, 0, NULL), -1);

	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_ABS, ABS_Y, NULL), -1);
	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_REP, REP_DELAY, NULL), -1);
	ck_assert_int_eq(libevdev_enable_event_code(dev, EV_REL, REL_X, &abs), -1);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_disable_bit)
{
	struct uinput_device* uidev;
	struct libevdev *dev, *dev2;
	int rc;
	struct input_absinfo abs[2] = {
		{ .value = ABS_X, .minimum = 0, .maximum = 1 },
		{ .value = ABS_Y, .minimum = 0, .maximum = 1 },
	};

	test_create_abs_device(&uidev, &dev,
			       2, abs,
			       EV_REL, REL_X,
			       EV_REL, REL_Y,
			       -1);

	ck_assert(libevdev_has_event_code(dev, EV_ABS, ABS_X));
	ck_assert(libevdev_has_event_code(dev, EV_ABS, ABS_Y));
	ck_assert(libevdev_has_event_type(dev, EV_REL));
	ck_assert(libevdev_has_event_code(dev, EV_REL, REL_X));
	ck_assert(libevdev_has_event_code(dev, EV_REL, REL_Y));

	ck_assert_int_eq(libevdev_disable_event_code(dev, EV_ABS, ABS_Y), 0);
	ck_assert(!libevdev_has_event_code(dev, EV_ABS, ABS_Y));

	ck_assert_int_eq(libevdev_disable_event_code(dev, EV_REL, REL_X), 0);
	ck_assert(!libevdev_has_event_code(dev, EV_REL, REL_X));
	ck_assert(libevdev_has_event_code(dev, EV_REL, REL_Y));
	ck_assert(libevdev_has_event_type(dev, EV_REL));

	ck_assert_int_eq(libevdev_disable_event_type(dev, EV_REL), 0);
	ck_assert(!libevdev_has_event_type(dev, EV_REL));
	ck_assert(!libevdev_has_event_code(dev, EV_REL, REL_X));
	ck_assert(!libevdev_has_event_code(dev, EV_REL, REL_Y));

	/* make sure kernel device is unchanged */
	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev2);
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));
	ck_assert(libevdev_has_event_code(dev2, EV_ABS, ABS_X));
	ck_assert(libevdev_has_event_code(dev2, EV_ABS, ABS_Y));
	ck_assert(libevdev_has_event_type(dev2, EV_REL));
	ck_assert(libevdev_has_event_code(dev2, EV_REL, REL_X));
	ck_assert(libevdev_has_event_code(dev2, EV_REL, REL_Y));
	libevdev_free(dev2);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_disable_bit_invalid)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs = { .value = ABS_X, .minimum = 0, .maximum = 1 };

	test_create_abs_device(&uidev, &dev, 1, &abs, -1);

	/* there's a gap between EV_SW and EV_LED */
	ck_assert_int_eq(libevdev_disable_event_type(dev, EV_LED - 1), -1);
	ck_assert_int_eq(libevdev_disable_event_code(dev, EV_LED - 1, 0), -1);
	ck_assert_int_eq(libevdev_disable_event_code(dev, EV_ABS, ABS_MAX + 1), -1);
	ck_assert_int_eq(libevdev_disable_event_code(dev, EV_MAX + 1, ABS_MAX + 1), -1);
	ck_assert_int_eq(libevdev_disable_event_type(dev, EV_MAX + 1), -1);
	ck_assert_int_eq(libevdev_disable_event_type(dev, EV_SYN), -1);
	ck_assert_int_eq(libevdev_disable_event_code(dev, EV_SYN, SYN_REPORT), -1);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_device_kernel_change_axis)
{
	struct uinput_device* uidev;
	struct libevdev *dev, *dev2;
	struct input_absinfo abs;
	int rc;

	uidev = uinput_device_new(TEST_DEVICE_NAME);
	ck_assert(uidev != NULL);

	abs.minimum = 0;
	abs.maximum = 1000;
	abs.fuzz = 1;
	abs.flat = 2;
	abs.resolution = 3;
	abs.value = 0;

	uinput_device_set_abs_bit(uidev, ABS_X, &abs);

	rc = uinput_device_create(uidev);
	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));

	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_X), 0);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_X), 1000);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_X), 1);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_X), 2);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_X), 3);

	abs.minimum = 500;
	abs.maximum = 5000;
	abs.fuzz = 10;
	abs.flat = 20;
	abs.resolution = 30;
	rc = libevdev_kernel_set_abs_info(dev, ABS_X, &abs);
	ck_assert_int_eq(rc, 0);

	ck_assert_int_eq(libevdev_get_abs_minimum(dev, ABS_X), 500);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev, ABS_X), 5000);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev, ABS_X), 10);
	ck_assert_int_eq(libevdev_get_abs_flat(dev, ABS_X), 20);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev, ABS_X), 30);

	/* make sure kernel device is changed */
	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev2);
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));
	ck_assert_int_eq(libevdev_get_abs_minimum(dev2, ABS_X), 500);
	ck_assert_int_eq(libevdev_get_abs_maximum(dev2, ABS_X), 5000);
	ck_assert_int_eq(libevdev_get_abs_fuzz(dev2, ABS_X), 10);
	ck_assert_int_eq(libevdev_get_abs_flat(dev2, ABS_X), 20);
	ck_assert_int_eq(libevdev_get_abs_resolution(dev2, ABS_X), 30);
	libevdev_free(dev2);

	libevdev_free(dev);
	uinput_device_free(uidev);
}
END_TEST

START_TEST(test_device_kernel_change_axis_invalid)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs;
	int rc;

	uidev = uinput_device_new(TEST_DEVICE_NAME);
	ck_assert(uidev != NULL);

	abs.minimum = 0;
	abs.maximum = 1000;
	abs.fuzz = 1;
	abs.flat = 2;
	abs.resolution = 3; /* FIXME: value is unused, we can't test resolution */
	abs.value = 0;

	uinput_device_set_abs_bit(uidev, ABS_X, &abs);

	rc = uinput_device_create(uidev);
	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));

	rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
	ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;

	rc = libevdev_kernel_set_abs_info(dev, ABS_MAX + 1, &abs);
	ck_assert_int_eq(rc, -EINVAL);

	libevdev_free(dev);
	uinput_device_free(uidev);
}
END_TEST

START_TEST(test_device_kernel_set_abs_invalid_fd)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	struct input_absinfo abs[2];
	struct input_absinfo a;
	int rc;

	libevdev_set_log_function(test_logfunc_ignore_error, NULL);

	memset(abs, 0, sizeof(abs));
	abs[0].value = ABS_X;
	abs[0].maximum = 1000;

	abs[1].value = ABS_Y;
	abs[1].maximum = 1000;

	dev = libevdev_new();
	rc = libevdev_kernel_set_abs_info(dev, ABS_X, &a);
	ck_assert_int_eq(rc, -EBADF);
	libevdev_free(dev);

	test_create_abs_device(&uidev, &dev,
			       2, abs,
			       EV_SYN,
			       -1);

	libevdev_change_fd(dev, -2);
	rc = libevdev_kernel_set_abs_info(dev, ABS_X, &a);
	ck_assert_int_eq(rc, -EBADF);

	libevdev_set_log_function(test_logfunc_abort_on_error, NULL);

	uinput_device_free(uidev);
	libevdev_free(dev);
}
END_TEST

START_TEST(test_led_valid)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	int rc;

	test_create_device(&uidev, &dev,
			   EV_LED, LED_NUML,
			   EV_LED, LED_CAPSL,
			   EV_LED, LED_COMPOSE,
			   -1);

	rc = libevdev_kernel_set_led_value(dev, LED_NUML, LIBEVDEV_LED_ON);
	ck_assert_int_eq(rc, 0);
	rc = libevdev_kernel_set_led_value(dev, LED_NUML, LIBEVDEV_LED_OFF);
	ck_assert_int_eq(rc, 0);

	rc = libevdev_kernel_set_led_values(dev,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_CAPSL, LIBEVDEV_LED_ON,
					    LED_COMPOSE, LIBEVDEV_LED_OFF,
					    -1);
	ck_assert_int_eq(rc, 0);
	ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_NUML));
	ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
	ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));

	rc = libevdev_kernel_set_led_values(dev,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_CAPSL, LIBEVDEV_LED_OFF,
					    LED_COMPOSE, LIBEVDEV_LED_ON,
					    -1);
	ck_assert_int_eq(rc, 0);
	ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_NUML));
	ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
	ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));

	/* make sure we ignore unset leds */
	rc = libevdev_kernel_set_led_values(dev,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_CAPSL, LIBEVDEV_LED_OFF,
					    LED_SCROLLL, LIBEVDEV_LED_OFF,
					    LED_COMPOSE, LIBEVDEV_LED_ON,
					    -1);
	ck_assert_int_eq(rc, 0);
	ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_NUML));
	ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
	ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));

	libevdev_free(dev);
	uinput_device_free(uidev);
}
END_TEST

START_TEST(test_led_invalid)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	int rc;

	test_create_device(&uidev, &dev,
			   EV_LED, LED_NUML,
			   EV_LED, LED_CAPSL,
			   EV_LED, LED_COMPOSE,
			   -1);

	rc = libevdev_kernel_set_led_value(dev, LED_MAX + 1, LIBEVDEV_LED_ON);
	ck_assert_int_eq(rc, -EINVAL);

	rc = libevdev_kernel_set_led_value(dev, LED_NUML, LIBEVDEV_LED_OFF + 1);
	ck_assert_int_eq(rc, -EINVAL);

	rc = libevdev_kernel_set_led_value(dev, LED_SCROLLL, LIBEVDEV_LED_ON);
	ck_assert_int_eq(rc, 0);

	rc = libevdev_kernel_set_led_values(dev,
					    LED_NUML, LIBEVDEV_LED_OFF + 1,
					    -1);
	ck_assert_int_eq(rc, -EINVAL);

	rc = libevdev_kernel_set_led_values(dev,
					    LED_MAX + 1, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF + 1,
					    -1);
	ck_assert_int_eq(rc, -EINVAL);

	rc = libevdev_kernel_set_led_values(dev,
					    LED_SCROLLL, LIBEVDEV_LED_OFF,
					    -1);
	ck_assert_int_eq(rc, 0);

	libevdev_free(dev);
	uinput_device_free(uidev);
}
END_TEST

START_TEST(test_led_same)
{
	struct uinput_device* uidev;
	struct libevdev *dev;
	int rc;

	test_create_device(&uidev, &dev,
			   EV_LED, LED_NUML,
			   EV_LED, LED_CAPSL,
			   EV_LED, LED_COMPOSE,
			   -1);

	rc = libevdev_kernel_set_led_values(dev,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    LED_NUML, LIBEVDEV_LED_OFF,
					    LED_NUML, LIBEVDEV_LED_ON,
					    /* more than LED_CNT */
					    -1);
	ck_assert_int_eq(rc, 0);
	ck_assert_int_eq(1, libevdev_get_event_value(dev, EV_LED, LED_NUML));
	ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_CAPSL));
	ck_assert_int_eq(0, libevdev_get_event_value(dev, EV_LED, LED_COMPOSE));

	libevdev_free(dev);
	uinput_device_free(uidev);
}
END_TEST

TEST_SUITE_ROOT_PRIVILEGES(has_events)
{
	Suite *s = suite_create("libevdev_has_event tests");

	add_test(s, test_ev_bit_limits);
	add_test(s, test_has_ev_bit);

	add_test(s, test_event_codes);
	add_test(s, test_event_code_limits);

	add_test(s, test_ev_rep);
	add_test(s, test_ev_rep_values);

	add_test(s, test_input_props);
	add_test(s, test_set_input_props);

	add_test(s, test_no_slots);
	add_test(s, test_slot_number);
	add_test(s, test_slot_init_value);
	add_test(s, test_invalid_mt_device);

	add_test(s, test_device_name);
	add_test(s, test_device_set_name);
	add_test(s, test_device_set_ids);
	add_test(s, test_device_get_abs_info);

	add_test(s, test_device_set_abs);
	add_test(s, test_device_enable_bit);
	add_test(s, test_device_enable_bit_invalid);
	add_test(s, test_device_disable_bit);
	add_test(s, test_device_disable_bit_invalid);
	add_test(s, test_device_kernel_change_axis);
	add_test(s, test_device_kernel_change_axis_invalid);
	add_test(s, test_device_kernel_set_abs_invalid_fd);

	add_test(s, test_led_valid);
	add_test(s, test_led_invalid);
	add_test(s, test_led_same);

	return s;
}
