mirror of
https://github.com/shenmintao/aic8800d80.git
synced 2026-11-10 16:49:17 +00:00
Take the aic.rules portion of #129: restrict 1111:1111 switching to 88M80 USB devices, target the event's bus/device address, and eject only whole disks on add. Add selection fixtures and document the product restriction. Keep installer paths and existing firmware handling unchanged. Co-authored-by: rtk94 <richardtknepp@gmail.com>
70 lines
3.1 KiB
Python
70 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Check device/event selection using fixtures; does not switch real devices.
|
|
|
|
This models the basic equality/glob predicates used by aic.rules. Run
|
|
udevadm verify separately to validate syntax with the real udev parser.
|
|
"""
|
|
|
|
from fnmatch import fnmatchcase
|
|
from pathlib import Path
|
|
import re
|
|
import unittest
|
|
|
|
|
|
RULES = (Path(__file__).resolve().parents[2] / "aic.rules").read_text().splitlines()
|
|
|
|
|
|
def matching_rules(device):
|
|
result = []
|
|
for rule in RULES:
|
|
if not rule.strip() or rule.lstrip().startswith("#"):
|
|
continue
|
|
predicates = re.findall(r'([A-Z]+(?:\{[^}]+\})?)=="([^"]*)"', rule)
|
|
if predicates and all(fnmatchcase(device.get(key, ""), value) for key, value in predicates):
|
|
result.append(rule)
|
|
return result
|
|
|
|
|
|
class UdevTests(unittest.TestCase):
|
|
def pandora(self, **changes):
|
|
device = {"ACTION": "add", "SUBSYSTEM": "usb", "ENV{DEVTYPE}": "usb_device",
|
|
"ATTR{idVendor}": "1111", "ATTR{idProduct}": "1111", "ATTR{product}": "88M80"}
|
|
device.update(changes)
|
|
return device
|
|
|
|
def test_88m80_uses_event_bus_and_device_numbers(self):
|
|
for product in ("88M80", "88M80 USB WiFi"):
|
|
with self.subTest(product=product):
|
|
matches = matching_rules(self.pandora(**{"ATTR{product}": product}))
|
|
self.assertEqual(len(matches), 1)
|
|
# Both possible usb_modeswitch executable locations target this event's device.
|
|
self.assertEqual(matches[0].count("-b $attr{busnum} -g $attr{devnum}"), 2)
|
|
|
|
def test_generic_1111_flash_disk_is_not_switched(self):
|
|
for product in ("FLASH UDISK 2.30", "USB DISK", ""):
|
|
with self.subTest(product=product):
|
|
self.assertEqual(matching_rules(self.pandora(**{"ATTR{product}": product})), [])
|
|
|
|
def test_wrong_ids_interfaces_and_non_add_events_are_not_switched(self):
|
|
for changes in ({"ACTION": "change"}, {"ACTION": "remove"},
|
|
{"ENV{DEVTYPE}": "usb_interface"}, {"ATTR{idVendor}": "2222"},
|
|
{"ATTR{idProduct}": "8d80"}):
|
|
with self.subTest(changes=changes):
|
|
self.assertEqual(matching_rules(self.pandora(**changes)), [])
|
|
|
|
def test_eject_only_on_add_of_a_whole_supported_disk(self):
|
|
for product in ("5721", "5722", "5723", "5724", "5725", "5726", "5727", "572a", "572c", "572f"):
|
|
disk = {"ACTION": "add", "SUBSYSTEM": "block", "ENV{DEVTYPE}": "disk", "KERNEL": "sdb",
|
|
"ATTRS{idVendor}": "a69c", "ATTRS{idProduct}": product}
|
|
with self.subTest(product=product):
|
|
matches = matching_rules(disk)
|
|
self.assertEqual(len(matches), 1)
|
|
self.assertIn('/usr/bin/eject /dev/%k', matches[0])
|
|
for changes in ({"ACTION": "change"}, {"ACTION": "remove"},
|
|
{"ENV{DEVTYPE}": "partition", "KERNEL": "sdb1"}):
|
|
self.assertEqual(matching_rules(dict(disk, **changes)), [])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|