Skip to content

Commit 642f9b2

Browse files
author
Benjamin Tissoires
committed
selftests/hid: sync the python tests to hid-tools 0.8
Instead of backporting one by one each commits, let's pull them in bulk and refer to the hid-tools project for a detailed history. The short summary is: - make use of dataclass when possible, to avoid tuples - wacom: remove unused uhdev parameter - various small fixes not worth mentioning Reviewed-by: Peter Hutterer <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent c85a8cb commit 642f9b2

File tree

9 files changed

+69
-43
lines changed

9 files changed

+69
-43
lines changed

tools/testing/selftests/hid/tests/base.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Copyright (c) 2017 Benjamin Tissoires <[email protected]>
66
# Copyright (c) 2017 Red Hat, Inc.
77

8+
import dataclasses
89
import libevdev
910
import os
1011
import pytest
@@ -145,6 +146,18 @@ def __init__(self, name, application, rdesc_str=None, rdesc=None, input_info=Non
145146
self.name = name
146147

147148

149+
@dataclasses.dataclass
150+
class HidBpf:
151+
object_name: str
152+
has_rdesc_fixup: bool
153+
154+
155+
@dataclasses.dataclass
156+
class KernelModule:
157+
driver_name: str
158+
module_name: str
159+
160+
148161
class BaseTestCase:
149162
class TestUhid(object):
150163
syn_event = libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT) # type: ignore
@@ -155,20 +168,20 @@ class TestUhid(object):
155168

156169
# List of kernel modules to load before starting the test
157170
# if any module is not available (not compiled), the test will skip.
158-
# Each element is a tuple '(kernel driver name, kernel module)',
159-
# for example ("playstation", "hid-playstation")
160-
kernel_modules: List[Tuple[str, str]] = []
171+
# Each element is a KernelModule object, for example
172+
# KernelModule("playstation", "hid-playstation")
173+
kernel_modules: List[KernelModule] = []
161174

162175
# List of in kernel HID-BPF object files to load
163176
# before starting the test
164177
# Any existing pre-loaded HID-BPF module will be removed
165178
# before the ones in this list will be manually loaded.
166-
# Each Element is a tuple '(hid_bpf_object, rdesc_fixup_present)',
167-
# for example '("xppen-ArtistPro16Gen2.bpf.o", True)'
168-
# If 'rdesc_fixup_present' is True, the test needs to wait
179+
# Each Element is a HidBpf object, for example
180+
# 'HidBpf("xppen-ArtistPro16Gen2.bpf.o", True)'
181+
# If 'has_rdesc_fixup' is True, the test needs to wait
169182
# for one unbind and rebind before it can be sure the kernel is
170183
# ready
171-
hid_bpfs: List[Tuple[str, bool]] = []
184+
hid_bpfs: List[HidBpf] = []
172185

173186
def assertInputEventsIn(self, expected_events, effective_events):
174187
effective_events = effective_events.copy()
@@ -232,25 +245,26 @@ def _load_kernel_module(self, kernel_driver, kernel_module):
232245

233246
@pytest.fixture()
234247
def load_kernel_module(self):
235-
for kernel_driver, kernel_module in self.kernel_modules:
236-
self._load_kernel_module(kernel_driver, kernel_module)
248+
for k in self.kernel_modules:
249+
self._load_kernel_module(k.driver_name, k.module_name)
237250
yield
238251

239252
def load_hid_bpfs(self):
253+
# this function will only work when run in the kernel tree
240254
script_dir = Path(os.path.dirname(os.path.realpath(__file__)))
241255
root_dir = (script_dir / "../../../../..").resolve()
242256
bpf_dir = root_dir / "drivers/hid/bpf/progs"
243257

258+
if not bpf_dir.exists():
259+
pytest.skip("looks like we are not in the kernel tree, skipping")
260+
244261
udev_hid_bpf = shutil.which("udev-hid-bpf")
245262
if not udev_hid_bpf:
246263
pytest.skip("udev-hid-bpf not found in $PATH, skipping")
247264

248-
wait = False
249-
for _, rdesc_fixup in self.hid_bpfs:
250-
if rdesc_fixup:
251-
wait = True
265+
wait = any(b.has_rdesc_fixup for b in self.hid_bpfs)
252266

253-
for hid_bpf, _ in self.hid_bpfs:
267+
for hid_bpf in self.hid_bpfs:
254268
# We need to start `udev-hid-bpf` in the background
255269
# and dispatch uhid events in case the kernel needs
256270
# to fetch features on the device
@@ -260,13 +274,13 @@ def load_hid_bpfs(self):
260274
"--verbose",
261275
"add",
262276
str(self.uhdev.sys_path),
263-
str(bpf_dir / hid_bpf),
277+
str(bpf_dir / hid_bpf.object_name),
264278
],
265279
)
266280
while process.poll() is None:
267281
self.uhdev.dispatch(1)
268282

269-
if process.poll() != 0:
283+
if process.returncode != 0:
270284
pytest.fail(
271285
f"Couldn't insert hid-bpf program '{hid_bpf}', marking the test as failed"
272286
)

tools/testing/selftests/hid/tests/base_device.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# You should have received a copy of the GNU General Public License
1919
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2020

21+
import dataclasses
2122
import fcntl
2223
import functools
2324
import libevdev
@@ -104,6 +105,12 @@ def type(self) -> str:
104105
return self._type.str_value
105106

106107

108+
@dataclasses.dataclass
109+
class HidReadiness:
110+
is_ready: bool = False
111+
count: int = 0
112+
113+
107114
class HIDIsReady(object):
108115
"""
109116
Companion class that binds to a kernel mechanism
@@ -115,18 +122,18 @@ class HIDIsReady(object):
115122
def __init__(self: "HIDIsReady", uhid: UHIDDevice) -> None:
116123
self.uhid = uhid
117124

118-
def is_ready(self: "HIDIsReady") -> bool:
125+
def is_ready(self: "HIDIsReady") -> HidReadiness:
119126
"""
120127
Overwrite in subclasses: should return True or False whether
121128
the attached uhid device is ready or not.
122129
"""
123-
return False
130+
return HidReadiness()
124131

125132

126133
class UdevHIDIsReady(HIDIsReady):
127134
_pyudev_context: ClassVar[Optional[pyudev.Context]] = None
128135
_pyudev_monitor: ClassVar[Optional[pyudev.Monitor]] = None
129-
_uhid_devices: ClassVar[Dict[int, Tuple[bool, int]]] = {}
136+
_uhid_devices: ClassVar[Dict[int, HidReadiness]] = {}
130137

131138
def __init__(self: "UdevHIDIsReady", uhid: UHIDDevice) -> None:
132139
super().__init__(uhid)
@@ -157,18 +164,19 @@ def _cls_udev_event_callback(cls: Type["UdevHIDIsReady"]) -> None:
157164

158165
id = int(event.sys_path.strip().split(".")[-1], 16)
159166

160-
device_ready, count = cls._uhid_devices.get(id, (False, 0))
167+
readiness = cls._uhid_devices.setdefault(id, HidReadiness())
161168

162169
ready = event.action == "bind"
163-
if not device_ready and ready:
164-
count += 1
165-
cls._uhid_devices[id] = (ready, count)
170+
if not readiness.is_ready and ready:
171+
readiness.count += 1
172+
173+
readiness.is_ready = ready
166174

167-
def is_ready(self: "UdevHIDIsReady") -> Tuple[bool, int]:
175+
def is_ready(self: "UdevHIDIsReady") -> HidReadiness:
168176
try:
169177
return self._uhid_devices[self.uhid.hid_id]
170178
except KeyError:
171-
return (False, 0)
179+
return HidReadiness()
172180

173181

174182
class EvdevMatch(object):
@@ -322,11 +330,11 @@ def led_classes(self: "BaseDevice") -> List[LED]:
322330

323331
@property
324332
def kernel_is_ready(self: "BaseDevice") -> bool:
325-
return self._kernel_is_ready.is_ready()[0] and self.started
333+
return self._kernel_is_ready.is_ready().is_ready and self.started
326334

327335
@property
328336
def kernel_ready_count(self: "BaseDevice") -> int:
329-
return self._kernel_is_ready.is_ready()[1]
337+
return self._kernel_is_ready.is_ready().count
330338

331339
@property
332340
def input_nodes(self: "BaseDevice") -> List[EvdevDevice]:

tools/testing/selftests/hid/tests/test_apple_keyboard.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88

99
from .test_keyboard import ArrayKeyboard, TestArrayKeyboard
1010
from hidtools.util import BusType
11+
from . import base
1112

1213
import libevdev
1314
import logging
1415

1516
logger = logging.getLogger("hidtools.test.apple-keyboard")
1617

17-
KERNEL_MODULE = ("apple", "hid-apple")
18+
KERNEL_MODULE = base.KernelModule("apple", "hid-apple")
1819

1920

2021
class KbdData(object):

tools/testing/selftests/hid/tests/test_gamepad.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from .base_gamepad import BaseGamepad, JoystickGamepad, AxisMapping
1414
from hidtools.util import BusType
15+
from .base import HidBpf
1516

1617
import logging
1718

@@ -654,7 +655,7 @@ def create_device(self):
654655

655656

656657
class TestRaptorMach2Joystick(BaseTest.TestGamepad):
657-
hid_bpfs = [("FR-TEC__Raptor-Mach-2.bpf.o", True)]
658+
hid_bpfs = [HidBpf("FR-TEC__Raptor-Mach-2.bpf.o", True)]
658659

659660
def create_device(self):
660661
return RaptorMach2Joystick(

tools/testing/selftests/hid/tests/test_ite_keyboard.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111

1212
import libevdev
1313
import logging
14+
from . import base
1415

1516
logger = logging.getLogger("hidtools.test.ite-keyboard")
1617

17-
KERNEL_MODULE = ("itetech", "hid_ite")
18+
KERNEL_MODULE = base.KernelModule("itetech", "hid_ite")
1819

1920

2021
class KbdData(object):

tools/testing/selftests/hid/tests/test_multitouch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
logger = logging.getLogger("hidtools.test.multitouch")
1919

20-
KERNEL_MODULE = ("hid-multitouch", "hid_multitouch")
20+
KERNEL_MODULE = base.KernelModule("hid-multitouch", "hid_multitouch")
2121

2222

2323
def BIT(x):

tools/testing/selftests/hid/tests/test_sony.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#
88

99
from .base import application_matches
10+
from .base import KernelModule
1011
from .test_gamepad import BaseTest
1112
from hidtools.device.sony_gamepad import (
1213
PS3Controller,
@@ -24,9 +25,9 @@
2425

2526
logger = logging.getLogger("hidtools.test.sony")
2627

27-
PS3_MODULE = ("sony", "hid_sony")
28-
PS4_MODULE = ("playstation", "hid_playstation")
29-
PS5_MODULE = ("playstation", "hid_playstation")
28+
PS3_MODULE = KernelModule("sony", "hid_sony")
29+
PS4_MODULE = KernelModule("playstation", "hid_playstation")
30+
PS5_MODULE = KernelModule("playstation", "hid_playstation")
3031

3132

3233
class SonyBaseTest:

tools/testing/selftests/hid/tests/test_tablet.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import copy
1111
from enum import Enum
1212
from hidtools.util import BusType
13+
from .base import HidBpf
1314
import libevdev
1415
import logging
1516
import pytest
@@ -1472,7 +1473,7 @@ def create_device(self):
14721473

14731474

14741475
class TestXPPen_ArtistPro16Gen2_28bd_095b(BaseTest.TestTablet):
1475-
hid_bpfs = [("XPPen__ArtistPro16Gen2.bpf.o", True)]
1476+
hid_bpfs = [HidBpf("XPPen__ArtistPro16Gen2.bpf.o", True)]
14761477

14771478
def create_device(self):
14781479
dev = XPPen_ArtistPro16Gen2_28bd_095b(
@@ -1484,7 +1485,7 @@ def create_device(self):
14841485

14851486

14861487
class TestXPPen_Artist24_28bd_093a(BaseTest.TestTablet):
1487-
hid_bpfs = [("XPPen__Artist24.bpf.o", True)]
1488+
hid_bpfs = [HidBpf("XPPen__Artist24.bpf.o", True)]
14881489

14891490
def create_device(self):
14901491
return XPPen_Artist24_28bd_093a(
@@ -1495,7 +1496,7 @@ def create_device(self):
14951496

14961497

14971498
class TestHuion_Kamvas_Pro_19_256c_006b(BaseTest.TestTablet):
1498-
hid_bpfs = [("Huion__Kamvas-Pro-19.bpf.o", True)]
1499+
hid_bpfs = [HidBpf("Huion__Kamvas-Pro-19.bpf.o", True)]
14991500

15001501
def create_device(self):
15011502
return Huion_Kamvas_Pro_19_256c_006b(

tools/testing/selftests/hid/tests/test_wacom_generic.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
logger = logging.getLogger("hidtools.test.wacom")
4242

43-
KERNEL_MODULE = ("wacom", "wacom")
43+
KERNEL_MODULE = base.KernelModule("wacom", "wacom")
4444

4545

4646
class ProximityState(Enum):
@@ -894,7 +894,7 @@ def make_contacts(self, n, t=0):
894894
"""
895895
return [self.make_contact(id, t) for id in range(0, n)]
896896

897-
def assert_contact(self, uhdev, evdev, contact_ids, t=0):
897+
def assert_contact(self, evdev, contact_ids, t=0):
898898
"""
899899
Assert properties of a contact generated by make_contact.
900900
"""
@@ -916,12 +916,12 @@ def assert_contact(self, uhdev, evdev, contact_ids, t=0):
916916
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_X] == x
917917
assert evdev.slots[slot_num][libevdev.EV_ABS.ABS_MT_POSITION_Y] == y
918918

919-
def assert_contacts(self, uhdev, evdev, data, t=0):
919+
def assert_contacts(self, evdev, data, t=0):
920920
"""
921921
Assert properties of a list of contacts generated by make_contacts.
922922
"""
923923
for contact_ids in data:
924-
self.assert_contact(uhdev, evdev, contact_ids, t)
924+
self.assert_contact(evdev, contact_ids, t)
925925

926926
def test_contact_id_0(self):
927927
"""
@@ -998,7 +998,6 @@ def test_confidence_multitouch(self):
998998
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
999999

10001000
self.assert_contacts(
1001-
uhdev,
10021001
evdev,
10031002
[
10041003
self.ContactIds(contact_id=0, tracking_id=-1, slot_num=None),
@@ -1032,7 +1031,7 @@ def confidence_change_assert_playback(self, uhdev, evdev, timeline):
10321031
self.debug_reports(r, uhdev, events)
10331032

10341033
ids = [x[0] for x in state]
1035-
self.assert_contacts(uhdev, evdev, ids, t)
1034+
self.assert_contacts(evdev, ids, t)
10361035

10371036
t += 1
10381037

0 commit comments

Comments
 (0)