Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: Add KUnit tests for some of the input core helper functions

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,
version and events 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/

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Tested-by: Enric Balletbo i Serra <eballetbo@redhat.com>
config: powerpc-allnoconfig (https://download.01.org/0day-ci/archive/20230330/202303301815.kRKFM3NH-lkp@intel.com/config)
Link: https://lore.kernel.org/r/20230330081831.2291351-1-javierm@redhat.com

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Javier Martinez Canillas and committed by
Dmitry Torokhov
fdefcbdd 57d94d15

+167
+10
drivers/input/Kconfig
··· 166 166 To compile this driver as a module, choose M here: the 167 167 module will be called evbug. 168 168 169 + config INPUT_KUNIT_TEST 170 + tristate "KUnit tests for Input" if !KUNIT_ALL_TESTS 171 + depends on INPUT && KUNIT=y 172 + default KUNIT_ALL_TESTS 173 + help 174 + Say Y here if you want to build the KUnit tests for the input 175 + subsystem. 176 + 177 + If in doubt, say "N". 178 + 169 179 config INPUT_APMPOWER 170 180 tristate "Input Power Event -> APM Bridge" if EXPERT 171 181 depends on INPUT && APM_EMULATION
+1
drivers/input/Makefile
··· 26 26 obj-$(CONFIG_INPUT_TABLET) += tablet/ 27 27 obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ 28 28 obj-$(CONFIG_INPUT_MISC) += misc/ 29 + obj-$(CONFIG_INPUT_KUNIT_TEST) += tests/ 29 30 30 31 obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o 31 32
+3
drivers/input/tests/.kunitconfig
··· 1 + CONFIG_KUNIT=y 2 + CONFIG_INPUT=y 3 + CONFIG_INPUT_KUNIT_TEST=y
+3
drivers/input/tests/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + obj-$(CONFIG_INPUT_KUNIT_TEST) += input_test.o
+150
drivers/input/tests/input_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * KUnit test for the input core. 4 + * 5 + * Copyright (c) 2023 Red Hat Inc 6 + */ 7 + 8 + #include <linux/delay.h> 9 + #include <linux/input.h> 10 + 11 + #include <kunit/test.h> 12 + 13 + #define POLL_INTERVAL 100 14 + 15 + static int input_test_init(struct kunit *test) 16 + { 17 + struct input_dev *input_dev; 18 + int ret; 19 + 20 + input_dev = input_allocate_device(); 21 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input_dev); 22 + 23 + input_dev->name = "Test input device"; 24 + input_dev->id.bustype = BUS_VIRTUAL; 25 + input_dev->id.vendor = 1; 26 + input_dev->id.product = 1; 27 + input_dev->id.version = 1; 28 + input_set_capability(input_dev, EV_KEY, BTN_LEFT); 29 + input_set_capability(input_dev, EV_KEY, BTN_RIGHT); 30 + 31 + ret = input_register_device(input_dev); 32 + if (ret) { 33 + input_free_device(input_dev); 34 + KUNIT_ASSERT_FAILURE(test, "Register device failed: %d", ret); 35 + } 36 + 37 + test->priv = input_dev; 38 + 39 + return 0; 40 + } 41 + 42 + static void input_test_exit(struct kunit *test) 43 + { 44 + struct input_dev *input_dev = test->priv; 45 + 46 + input_unregister_device(input_dev); 47 + input_free_device(input_dev); 48 + } 49 + 50 + static void input_test_poll(struct input_dev *input) { } 51 + 52 + static void input_test_polling(struct kunit *test) 53 + { 54 + struct input_dev *input_dev = test->priv; 55 + 56 + /* Must fail because a poll handler has not been set-up yet */ 57 + KUNIT_ASSERT_EQ(test, input_get_poll_interval(input_dev), -EINVAL); 58 + 59 + KUNIT_ASSERT_EQ(test, input_setup_polling(input_dev, input_test_poll), 0); 60 + 61 + input_set_poll_interval(input_dev, POLL_INTERVAL); 62 + 63 + /* Must succeed because poll handler was set-up and poll interval set */ 64 + KUNIT_ASSERT_EQ(test, input_get_poll_interval(input_dev), POLL_INTERVAL); 65 + } 66 + 67 + static void input_test_timestamp(struct kunit *test) 68 + { 69 + const ktime_t invalid_timestamp = ktime_set(0, 0); 70 + struct input_dev *input_dev = test->priv; 71 + ktime_t *timestamp, time; 72 + 73 + timestamp = input_get_timestamp(input_dev); 74 + time = timestamp[INPUT_CLK_MONO]; 75 + 76 + /* The returned timestamp must always be valid */ 77 + KUNIT_ASSERT_EQ(test, ktime_compare(time, invalid_timestamp), 1); 78 + 79 + time = ktime_get(); 80 + input_set_timestamp(input_dev, time); 81 + 82 + timestamp = input_get_timestamp(input_dev); 83 + /* The timestamp must be the same than set before */ 84 + KUNIT_ASSERT_EQ(test, ktime_compare(timestamp[INPUT_CLK_MONO], time), 0); 85 + } 86 + 87 + static void input_test_match_device_id(struct kunit *test) 88 + { 89 + struct input_dev *input_dev = test->priv; 90 + struct input_device_id id; 91 + 92 + /* 93 + * Must match when the input device bus, vendor, product, version 94 + * and events capable of handling are the same and fail to match 95 + * otherwise. 96 + */ 97 + id.flags = INPUT_DEVICE_ID_MATCH_BUS; 98 + id.bustype = BUS_VIRTUAL; 99 + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); 100 + 101 + id.bustype = BUS_I2C; 102 + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); 103 + 104 + id.flags = INPUT_DEVICE_ID_MATCH_VENDOR; 105 + id.vendor = 1; 106 + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); 107 + 108 + id.vendor = 2; 109 + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); 110 + 111 + id.flags = INPUT_DEVICE_ID_MATCH_PRODUCT; 112 + id.product = 1; 113 + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); 114 + 115 + id.product = 2; 116 + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); 117 + 118 + id.flags = INPUT_DEVICE_ID_MATCH_VERSION; 119 + id.version = 1; 120 + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); 121 + 122 + id.version = 2; 123 + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); 124 + 125 + id.flags = INPUT_DEVICE_ID_MATCH_EVBIT; 126 + __set_bit(EV_KEY, id.evbit); 127 + KUNIT_ASSERT_TRUE(test, input_match_device_id(input_dev, &id)); 128 + 129 + __set_bit(EV_ABS, id.evbit); 130 + KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id)); 131 + } 132 + 133 + static struct kunit_case input_tests[] = { 134 + KUNIT_CASE(input_test_polling), 135 + KUNIT_CASE(input_test_timestamp), 136 + KUNIT_CASE(input_test_match_device_id), 137 + { /* sentinel */ } 138 + }; 139 + 140 + static struct kunit_suite input_test_suite = { 141 + .name = "input_core", 142 + .init = input_test_init, 143 + .exit = input_test_exit, 144 + .test_cases = input_tests, 145 + }; 146 + 147 + kunit_test_suite(input_test_suite); 148 + 149 + MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>"); 150 + MODULE_LICENSE("GPL");