From 5ebd7bd1f01bf73dc59e4964818479b2ca8d5085 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 9 Sep 2020 10:50:42 +1000 Subject: [PATCH] tools/replay: check the recorded udev properties against the local properties Where a device is replayed locally for testing, its udev properties should match the recorded properties. Otherwise the testing results will not be reliable. The exception here is the device group which we currently don't set for emulated devices and even if we did, it may intentionally differ anyway. Signed-off-by: Peter Hutterer --- tools/libinput-replay | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tools/libinput-replay b/tools/libinput-replay index 401dbbc3..556cf481 100755 --- a/tools/libinput-replay +++ b/tools/libinput-replay @@ -33,6 +33,7 @@ from pathlib import Path try: import libevdev import yaml + import pyudev except ModuleNotFoundError as e: print('Error: {}'.format(e), file=sys.stderr) print('One or more python modules are missing. Please install those ' @@ -60,6 +61,41 @@ def fetch(yaml, key): raise YamlException('Failed to get \'{}\' from recording.'.format(key)) +def check_udev_properties(yaml_data, uinput): + ''' + Compare the properties our new uinput device has with the ones from the + recording and ring the alarm bell if one of them is off. + ''' + yaml_udev_section = fetch(yaml_data, 'udev') + yaml_udev_props = fetch(yaml_udev_section, 'properties') + yaml_props = {k: v for (k, v) in [prop.split('=', maxsplit=1) for prop in yaml_udev_props]} + try: + # We don't assign this one to virtual devices + del yaml_props['LIBINPUT_DEVICE_GROUP'] + except KeyError: + pass + + # give udev some time to catch up + time.sleep(0.2) + context = pyudev.Context() + udev_device = pyudev.Devices.from_device_file(context, uinput.devnode) + for name, value in udev_device.properties.items(): + if name in yaml_props: + if yaml_props[name] != value: + error(f'Warning: udev property mismatch: recording has {name}={yaml_props[name]}, device has {name}={value}') + del yaml_props[name] + else: + # The list of properties we add to the recording, see libinput-record.c + prefixes = ("ID_INPUT", "LIBINPUT", "EVDEV_ABS", "MOUSE_DPI", "POINTINGSTICK_") + for prefix in prefixes: + if name.startswith(prefix): + error(f'Warning: unexpected property: {name}={value}') + + # the ones we found above were removed from the dict + for name, value in yaml_props.items(): + error(f'Warning: device is missing recorded udev property: {name}={value}') + + def create(device): evdev = fetch(device, 'evdev') @@ -95,6 +131,9 @@ def create(device): d.enable(libevdev.propbit(prop)) uinput = d.create_uinput_device() + + check_udev_properties(device, uinput) + return uinput