Skip to content

Commit fdefcbd

Browse files
martinezjavierdtor
authored andcommitted
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>
1 parent 57d94d1 commit fdefcbd

5 files changed

Lines changed: 167 additions & 0 deletions

File tree

drivers/input/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ config INPUT_EVBUG
166166
To compile this driver as a module, choose M here: the
167167
module will be called evbug.
168168

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+
169179
config INPUT_APMPOWER
170180
tristate "Input Power Event -> APM Bridge" if EXPERT
171181
depends on INPUT && APM_EMULATION

drivers/input/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
2626
obj-$(CONFIG_INPUT_TABLET) += tablet/
2727
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
2828
obj-$(CONFIG_INPUT_MISC) += misc/
29+
obj-$(CONFIG_INPUT_KUNIT_TEST) += tests/
2930

3031
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
3132

drivers/input/tests/.kunitconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_KUNIT=y
2+
CONFIG_INPUT=y
3+
CONFIG_INPUT_KUNIT_TEST=y

drivers/input/tests/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
obj-$(CONFIG_INPUT_KUNIT_TEST) += input_test.o

drivers/input/tests/input_test.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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");

0 commit comments

Comments
 (0)