Hi Javier, Many thanks for the patch and to work on this. On Wed, Mar 29, 2023 at 11:23 AM Javier Martinez Canillas <javierm@xxxxxxxxxx> wrote: > > The input subsystem doesn't currently have any unit tests, let's add a > CONFIG_INPUT_KUNIT_TEST option that builds a test suite to be executed > with the KUnit test infrastructure. > > For now, only three tests were added for some of the input core helper > functions that are trivial to test: > > * input_test_polling: set/get poll interval and set-up a poll handler. > > * input_test_timestamp: set/get input event timestamps. > > * input_test_match_device_id: match a device by bus, vendor, product > and events that is capable of handling. > > But having the minimal KUnit support allows to add more tests and suites > as follow-up changes. The tests can be run with the following command: > > $ ./tools/testing/kunit/kunit.py run \ > --kunitconfig=drivers/input/tests/.kunitconfig > > Signed-off-by: Javier Martinez Canillas <javierm@xxxxxxxxxx> I'll let other more experienced people comment on the kunit tests. In my opinion it's a starting point and after applying your patch and giving a try I can confirm that it works as expected, so just wanted to give my. Tested-by: Enric Balletbo i Serra <eballetbo@xxxxxxxxxx> Thanks, Enric > --- > > drivers/input/Kconfig | 12 +++ > drivers/input/Makefile | 1 + > drivers/input/tests/Makefile | 3 + > drivers/input/tests/input_test.c | 144 +++++++++++++++++++++++++++++++ > 4 files changed, 160 insertions(+) > create mode 100644 drivers/input/tests/Makefile > create mode 100644 drivers/input/tests/input_test.c > > diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig > index e2752f7364bc..e094e5bbaa0c 100644 > --- a/drivers/input/Kconfig > +++ b/drivers/input/Kconfig > @@ -166,6 +166,18 @@ config INPUT_EVBUG > To compile this driver as a module, choose M here: the > module will be called evbug. > > +config INPUT_KUNIT_TEST > + tristate "KUnit tests for Input" if !KUNIT_ALL_TESTS > + depends on INPUT && KUNIT=y > + default KUNIT_ALL_TESTS > + help > + Say Y here if you want to build the KUnit tests for the input > + subsystem. For more information about KUnit and unit tests in > + general, please refer to the KUnit documentation in > + Documentation/dev-tools/kunit/. > + > + If in doubt, say "N". > + > config INPUT_APMPOWER > tristate "Input Power Event -> APM Bridge" if EXPERT > depends on INPUT && APM_EMULATION > diff --git a/drivers/input/Makefile b/drivers/input/Makefile > index 2266c7d010ef..c78753274921 100644 > --- a/drivers/input/Makefile > +++ b/drivers/input/Makefile > @@ -26,6 +26,7 @@ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ > obj-$(CONFIG_INPUT_TABLET) += tablet/ > obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ > obj-$(CONFIG_INPUT_MISC) += misc/ > +obj-$(CONFIG_INPUT_KUNIT_TEST) += tests/ > > obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o > > diff --git a/drivers/input/tests/Makefile b/drivers/input/tests/Makefile > new file mode 100644 > index 000000000000..90cf954181bc > --- /dev/null > +++ b/drivers/input/tests/Makefile > @@ -0,0 +1,3 @@ > +# SPDX-License-Identifier: GPL-2.0 > + > +obj-$(CONFIG_INPUT_KUNIT_TEST) += input_test.o > diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c > new file mode 100644 > index 000000000000..25bbf51b5c87 > --- /dev/null > +++ b/drivers/input/tests/input_test.c > @@ -0,0 +1,144 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * KUnit test for the input core. > + * > + * Copyright (c) 2023 Red Hat Inc > + */ > + > +#include <linux/delay.h> > +#include <linux/input.h> > + > +#include <kunit/test.h> > + > +#define POLL_INTERVAL 100 > + > +static int input_test_init(struct kunit *test) > +{ > + struct input_dev *input_dev; > + int ret; > + > + input_dev = input_allocate_device(); > + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input_dev); > + > + input_dev->name = "Test input device"; > + input_dev->id.bustype = BUS_VIRTUAL; > + input_dev->id.vendor = 1; > + input_dev->id.product = 1; > + input_dev->id.version = 1; > + input_set_capability(input_dev, EV_KEY, BTN_LEFT); > + input_set_capability(input_dev, EV_KEY, BTN_RIGHT); > + > + ret = input_register_device(input_dev); > + KUNIT_ASSERT_EQ(test, ret, 0); > + > + test->priv = input_dev; > + > + return 0; > +} > + > +static void input_test_exit(struct kunit *test) > +{ > + struct input_dev *input_dev = test->priv; > + > + input_unregister_device(input_dev); > +} > + > +static void input_test_poll(struct input_dev *input) { } > + > +static void input_test_polling(struct kunit *test) > +{ > + struct input_dev *input_dev = test->priv; > + int ret; > + > + ret = input_get_poll_interval(input_dev); > + KUNIT_ASSERT_EQ(test, ret, -EINVAL); > + > + ret = input_setup_polling(input_dev, input_test_poll); > + KUNIT_ASSERT_EQ(test, ret, 0); > + > + input_set_poll_interval(input_dev, POLL_INTERVAL); > + > + ret = input_get_poll_interval(input_dev); > + KUNIT_ASSERT_EQ(test, ret, POLL_INTERVAL); > +} > + > +static void input_test_timestamp(struct kunit *test) > +{ > + const ktime_t invalid_timestamp = ktime_set(0, 0); > + struct input_dev *input_dev = test->priv; > + ktime_t *timestamp, time; > + int ret; > + > + timestamp = input_get_timestamp(input_dev); > + time = timestamp[INPUT_CLK_MONO]; > + > + ret = ktime_compare(time, invalid_timestamp); > + KUNIT_ASSERT_EQ(test, ret, 1); > + > + time = ktime_get(); > + input_set_timestamp(input_dev, time); > + > + timestamp = input_get_timestamp(input_dev); > + KUNIT_ASSERT_EQ(test, ktime_compare(timestamp[INPUT_CLK_MONO], > + time), 0); > +} > + > +static void input_test_match_device_id(struct kunit *test) > +{ > + struct input_dev *input_dev = test->priv; > + struct input_device_id id; > + > + id.flags = INPUT_DEVICE_ID_MATCH_BUS; > + id.bustype = BUS_VIRTUAL; > + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); > + > + id.bustype = BUS_I2C; > + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); > + > + id.flags = INPUT_DEVICE_ID_MATCH_VENDOR; > + id.vendor = 1; > + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); > + > + id.vendor = 2; > + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); > + > + id.flags = INPUT_DEVICE_ID_MATCH_PRODUCT; > + id.product = 1; > + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); > + > + id.product = 2; > + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); > + > + id.flags = INPUT_DEVICE_ID_MATCH_VERSION; > + id.version = 1; > + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); > + > + id.version = 2; > + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); > + > + id.flags = INPUT_DEVICE_ID_MATCH_EVBIT; > + __set_bit(EV_KEY, id.evbit); > + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); > + > + __set_bit(EV_ABS, id.evbit); > + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); > +} > + > +static struct kunit_case input_tests[] = { > + KUNIT_CASE(input_test_polling), > + KUNIT_CASE(input_test_timestamp), > + KUNIT_CASE(input_test_match_device_id), > + { /* sentinel */ } > +}; > + > +static struct kunit_suite input_test_suite = { > + .name = "input_core", > + .init = input_test_init, > + .exit = input_test_exit, > + .test_cases = input_tests, > +}; > + > +kunit_test_suite(input_test_suite); > + > +MODULE_AUTHOR("Javier Martinez Canillas <javierm@xxxxxxxxxx>"); > +MODULE_LICENSE("GPL"); > > base-commit: 3a93e40326c8f470e71d20b4c42d36767450f38f > -- > 2.40.0 >