tests: use hidpp module in several test modules

This commit is contained in:
Peter F. Patel-Schneider 2024-03-20 12:10:35 -04:00
parent ebc76bca24
commit 10e3f844dd
2 changed files with 71 additions and 108 deletions

View File

@ -1,7 +1,7 @@
from dataclasses import dataclass from dataclasses import dataclass
from dataclasses import field from dataclasses import field
from struct import pack
from typing import Any from typing import Any
from typing import Optional
import pytest import pytest
@ -10,13 +10,7 @@ from lib.logitech_receiver import hidpp20
from lib.logitech_receiver import hidpp20_constants from lib.logitech_receiver import hidpp20_constants
from lib.logitech_receiver import special_keys from lib.logitech_receiver import special_keys
from . import hidpp
@dataclass
class Response:
response: Optional[str]
request_id: int
params: Any
no_reply: bool = False
@dataclass @dataclass
@ -29,10 +23,11 @@ class Device:
def request(self, id, *params, no_reply=False): def request(self, id, *params, no_reply=False):
if params is None: if params is None:
params = [] params = []
params = b"".join(pack("B", p) if isinstance(p, int) else p for p in params)
print("REQUEST ", self.name, hex(id), params) print("REQUEST ", self.name, hex(id), params)
for r in self.responses: for r in self.responses:
if id == r.request_id and params == r.params: if id == r.id and params == bytes.fromhex(r.params):
print("RESPONSE", self.name, hex(r.request_id), r.params, r.response) print("RESPONSE", self.name, hex(r.id), r.params, r.response)
return bytes.fromhex(r.response) if r.response is not None else None return bytes.fromhex(r.response) if r.response is not None else None
def feature_request(self, feature, function=0x00, *params, no_reply=False): def feature_request(self, feature, function=0x00, *params, no_reply=False):
@ -43,21 +38,9 @@ class Device:
device_offline = Device("REGISTERS", False) device_offline = Device("REGISTERS", False)
device_registers = Device("OFFLINE", True, 1.0) device_registers = Device("OFFLINE", True, 1.0)
device_nofeatures = Device("NOFEATURES", True, 4.5) device_nofeatures = Device("NOFEATURES", True, 4.5)
device_zerofeatures = Device("ZEROFEATURES", True, 4.5, [Response("0000", 0x0000, (b"\x00\x01",))]) device_zerofeatures = Device("ZEROFEATURES", True, 4.5, [hidpp.Response("0000", 0x0000, "0001")])
device_broken = Device("BROKEN", True, 4.5, [Response("0500", 0x0000, (b"\x00\x01",)), Response(None, 0x0100, ())]) device_broken = Device("BROKEN", True, 4.5, [hidpp.Response("0500", 0x0000, "0001"), hidpp.Response(None, 0x0100)])
responses_standard = [ device_standard = Device("STANDARD", True, 4.5, hidpp.r_keyboard_2)
Response("0100", 0x0000, (b"\x00\x01",)),
Response("05000300", 0x0000, (b"\x1b\x04",)),
Response("0500", 0x0100, ()),
Response("01000000", 0x0110, (0x02,)),
Response("1B040003", 0x0110, (0x05,)),
Response("00110012AB010203CD00", 0x0510, (0,)),
Response("01110022AB010203CD00", 0x0510, (1,)),
Response("03110032AB010204CD00", 0x0510, (3,)),
Response("00010111AB010203CD00", 0x0510, (2,)),
Response("00030333AB010203CD00", 0x0510, (4,)),
]
device_standard = Device("STANDARD", True, 4.5, responses_standard)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -68,7 +51,7 @@ device_standard = Device("STANDARD", True, 4.5, responses_standard)
(device_nofeatures, False, 0), (device_nofeatures, False, 0),
(device_zerofeatures, False, 0), (device_zerofeatures, False, 0),
(device_broken, False, 0), (device_broken, False, 0),
(device_standard, True, 6), (device_standard, True, 9),
], ],
) )
def test_FeaturesArray_check(device, expected_result, expected_count): def test_FeaturesArray_check(device, expected_result, expected_count):
@ -88,7 +71,7 @@ def test_FeaturesArray_check(device, expected_result, expected_count):
"device, expected0, expected1, expected2, expected5, expected5v", "device, expected0, expected1, expected2, expected5, expected5v",
[ [
(device_zerofeatures, None, None, None, None, None), (device_zerofeatures, None, None, None, None, None),
(device_standard, 0x0000, 0x0001, 0x0100, hidpp20_constants.FEATURE.REPROG_CONTROLS_V4, 3), (device_standard, 0x0000, 0x0001, 0x1000, hidpp20_constants.FEATURE.REPROG_CONTROLS_V4, 3),
], ],
) )
def test_FeaturesArray_get_feature(device, expected0, expected1, expected2, expected5, expected5v): def test_FeaturesArray_get_feature(device, expected0, expected1, expected2, expected5, expected5v):
@ -119,10 +102,13 @@ def test_FeaturesArray_get_feature(device, expected0, expected1, expected2, expe
[ [
(hidpp20_constants.FEATURE.ROOT, 0), (hidpp20_constants.FEATURE.ROOT, 0),
(hidpp20_constants.FEATURE.FEATURE_SET, 1), (hidpp20_constants.FEATURE.FEATURE_SET, 1),
(common.NamedInt(256, "unknown:0100"), 2), (hidpp20_constants.FEATURE.BATTERY_STATUS, 2),
(None, 3), (hidpp20_constants.FEATURE.DEVICE_FW_VERSION, 3),
(None, 4), (common.NamedInt(256, "unknown:0100"), 4),
(hidpp20_constants.FEATURE.REPROG_CONTROLS_V4, 5), (hidpp20_constants.FEATURE.REPROG_CONTROLS_V4, 5),
(None, 6),
(None, 7),
(None, 8),
], ],
), ),
], ],
@ -273,25 +259,25 @@ def test_KeysArrayV4_index(key, index):
responses_key = [ responses_key = [
Response("0A00", 0x0100, ()), hidpp.Response("0A00", 0x0100),
Response("01000000", 0x0000, (b"\x00\x01",)), hidpp.Response("01000000", 0x0000, "0001"),
Response("09000300", 0x0000, (b"\x1b\x04",)), hidpp.Response("09000300", 0x0000, "1b04"),
Response("00500038010001010400000000000000", 0x0910, (0,)), hidpp.Response("00500038010001010400000000000000", 0x0910, "00"),
Response("00510039010001010400000000000000", 0x0910, (1,)), hidpp.Response("00510039010001010400000000000000", 0x0910, "01"),
Response("0052003A310003070500000000000000", 0x0910, (2,)), hidpp.Response("0052003A310003070500000000000000", 0x0910, "02"),
Response("0053003C310002030500000000000000", 0x0910, (3,)), hidpp.Response("0053003C310002030500000000000000", 0x0910, "03"),
Response("0056003E310002030500000000000000", 0x0910, (4,)), hidpp.Response("0056003E310002030500000000000000", 0x0910, "04"),
Response("00C300A9310003070500000000000000", 0x0910, (5,)), hidpp.Response("00C300A9310003070500000000000000", 0x0910, "05"),
Response("00C4009D310003070500000000000000", 0x0910, (6,)), hidpp.Response("00C4009D310003070500000000000000", 0x0910, "06"),
Response("00D700B4A00004000300000000000000", 0x0910, (7,)), hidpp.Response("00D700B4A00004000300000000000000", 0x0910, "07"),
Response("00500000000000000000000000000000", 0x0920, (0, 0x50)), hidpp.Response("00500000000000000000000000000000", 0x0920, "0050"),
Response("00510000000000000000000000000000", 0x0920, (0, 0x51)), hidpp.Response("00510000000000000000000000000000", 0x0920, "0051"),
Response("00520000500000000000000000000000", 0x0920, (0, 0x52)), hidpp.Response("00520000500000000000000000000000", 0x0920, "0052"),
Response("00530000000000000000000000000000", 0x0920, (0, 0x53)), hidpp.Response("00530000000000000000000000000000", 0x0920, "0053"),
Response("00560000000000000000000000000000", 0x0920, (0, 0x56)), hidpp.Response("00560000000000000000000000000000", 0x0920, "0056"),
Response("00C30000000000000000000000000000", 0x0920, (0, 0xC3)), hidpp.Response("00C30000000000000000000000000000", 0x0920, "00C3"),
Response("00C40000500000000000000000000000", 0x0920, (0, 0xC4)), hidpp.Response("00C40000500000000000000000000000", 0x0920, "00C4"),
Response("00D70000510000000000000000000000", 0x0920, (0, 0xD7)), hidpp.Response("00D70000510000000000000000000000", 0x0920, "00D7"),
] ]
device_key = Device("KEY", True, 4.5, responses=responses_key) device_key = Device("KEY", True, 4.5, responses=responses_key)

View File

@ -1,7 +1,5 @@
from dataclasses import dataclass from dataclasses import dataclass
from functools import partial from functools import partial
from struct import pack
from typing import Optional
from unittest import mock from unittest import mock
import pytest import pytest
@ -10,6 +8,8 @@ from logitech_receiver import common
from logitech_receiver import exceptions from logitech_receiver import exceptions
from logitech_receiver import receiver from logitech_receiver import receiver
from . import hidpp
@pytest.mark.parametrize( @pytest.mark.parametrize(
"index, expected_kind", "index, expected_kind",
@ -39,29 +39,6 @@ class DeviceInfo:
product_id: int = 0xC52B product_id: int = 0xC52B
@dataclass
class Response:
response: Optional[str]
handle: int
devnumber: int
id: int
params: str = ""
no_reply: bool = False
def request(responses, handle, devnumber, id, *params, no_reply=False, return_error=False, long_message=False, protocol=1.0):
params = b"".join(pack("B", p) if isinstance(p, int) else p for p in params)
print("REQUEST ", hex(handle), hex(devnumber), hex(id), params.hex())
for r in responses:
if handle == r.handle and devnumber == r.devnumber and r.id == id and bytes.fromhex(r.params) == params:
print("RESPONSE", hex(r.handle), hex(r.devnumber), hex(r.id), r.params, r.response)
return bytes.fromhex(r.response) if r.response is not None else None
def open_path(path: Optional[str]) -> Optional[int]:
return int(path, 16) if path is not None else None
@pytest.fixture @pytest.fixture
def mock_request(): def mock_request():
with mock.patch("logitech_receiver.base.request", return_value=None) as mock_request: with mock.patch("logitech_receiver.base.request", return_value=None) as mock_request:
@ -76,38 +53,38 @@ def mock_base():
responses_unifying = [ responses_unifying = [
Response("000000", 0x11, 0xFF, 0x8003, "FF"), hidpp.Response("000000", 0x8003, "FF"),
Response("000300", 0x11, 0xFF, 0x8102), hidpp.Response("000300", 0x8102),
Response("0316CC9CB40506220000000000000000", 0x11, 0xFF, 0x83B5, "03"), hidpp.Response("0316CC9CB40506220000000000000000", 0x83B5, "03"),
Response("20200840820402020700000000000000", 0x11, 0xFF, 0x83B5, "20"), hidpp.Response("20200840820402020700000000000000", 0x83B5, "20"),
Response("21211420110400010D1A000000000000", 0x11, 0xFF, 0x83B5, "21"), hidpp.Response("21211420110400010D1A000000000000", 0x83B5, "21"),
Response("22220840660402010700000000020000", 0x11, 0xFF, 0x83B5, "22"), hidpp.Response("22220840660402010700000000020000", 0x83B5, "22"),
Response("30198E3EB80600000001000000000000", 0x11, 0xFF, 0x83B5, "30"), hidpp.Response("30198E3EB80600000001000000000000", 0x83B5, "30"),
Response("31811119511A40000002000000000000", 0x11, 0xFF, 0x83B5, "31"), hidpp.Response("31811119511A40000002000000000000", 0x83B5, "31"),
Response("32112C46EA1E40000003000000000000", 0x11, 0xFF, 0x83B5, "32"), hidpp.Response("32112C46EA1E40000003000000000000", 0x83B5, "32"),
Response("400B4D58204D61737465722033000000", 0x11, 0xFF, 0x83B5, "40"), hidpp.Response("400B4D58204D61737465722033000000", 0x83B5, "40"),
Response("41044B35323020202020202020202020", 0x11, 0xFF, 0x83B5, "41"), hidpp.Response("41044B35323020202020202020202020", 0x83B5, "41"),
Response("42054372616674000000000000000000", 0x11, 0xFF, 0x83B5, "42"), hidpp.Response("42054372616674000000000000000000", 0x83B5, "42"),
Response("012411", 0x11, 0xFF, 0x81F1, "01"), hidpp.Response("012411", 0x81F1, "01"),
Response("020036", 0x11, 0xFF, 0x81F1, "02"), hidpp.Response("020036", 0x81F1, "02"),
Response("03AAAC", 0x11, 0xFF, 0x81F1, "03"), hidpp.Response("03AAAC", 0x81F1, "03"),
Response("040209", 0x11, 0xFF, 0x81F1, "04"), hidpp.Response("040209", 0x81F1, "04"),
] ]
responses_c534 = [ responses_c534 = [
Response("000000", 0x12, 0xFF, 0x8003, "FF"), hidpp.Response("000000", 0x8003, "FF", handle=0x12),
Response("000209", 0x12, 0xFF, 0x8102), hidpp.Response("000209", 0x8102, handle=0x12),
Response("0316CC9CB40502220000000000000000", 0x12, 0xFF, 0x83B5, "03"), hidpp.Response("0316CC9CB40502220000000000000000", 0x83B5, "03", handle=0x12),
Response("00000445AB", 0x12, 0xFF, 0x83B5, "04"), hidpp.Response("00000445AB", 0x83B5, "04", handle=0x12),
] ]
responses_unusual = [ responses_unusual = [
Response("000000", 0x13, 0xFF, 0x8003, "FF"), hidpp.Response("000000", 0x8003, "FF", handle=0x13),
Response("000300", 0x13, 0xFF, 0x8102), hidpp.Response("000300", 0x8102, handle=0x13),
Response("00000445AB", 0x13, 0xFF, 0x83B5, "04"), hidpp.Response("00000445AB", 0x83B5, "04", handle=0x13),
Response("0326CC9CB40508220000000000000000", 0x13, 0xFF, 0x83B5, "03"), hidpp.Response("0326CC9CB40508220000000000000000", 0x83B5, "03", handle=0x13),
] ]
responses_lacking = [ responses_lacking = [
Response("000000", 0x14, 0xFF, 0x8003, "FF"), hidpp.Response("000000", 0x8003, "FF", handle=0x14),
Response("000300", 0x14, 0xFF, 0x8102), hidpp.Response("000300", 0x8102, handle=0x14),
] ]
mouse_info = { mouse_info = {
@ -133,8 +110,8 @@ c534_info = {"kind": common.NamedInt(0, "unknown"), "polling": "", "power_switch
], ],
) )
def test_ReceiverFactory_create_receiver(device_info, responses, handle, serial, max_devices, mock_base): def test_ReceiverFactory_create_receiver(device_info, responses, handle, serial, max_devices, mock_base):
mock_base[0].side_effect = open_path mock_base[0].side_effect = hidpp.open_path
mock_base[1].side_effect = partial(request, responses) mock_base[1].side_effect = partial(hidpp.request, responses)
r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x) r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x)
@ -155,8 +132,8 @@ def test_ReceiverFactory_create_receiver(device_info, responses, handle, serial,
], ],
) )
def test_ReceiverFactory_props(device_info, responses, firmware, codename, remaining_pairings, pairing_info, count, mock_base): def test_ReceiverFactory_props(device_info, responses, firmware, codename, remaining_pairings, pairing_info, count, mock_base):
mock_base[0].side_effect = open_path mock_base[0].side_effect = hidpp.open_path
mock_base[1].side_effect = partial(request, responses) mock_base[1].side_effect = partial(hidpp.request, responses)
r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x) r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x)
@ -176,8 +153,8 @@ def test_ReceiverFactory_props(device_info, responses, firmware, codename, remai
], ],
) )
def test_ReceiverFactory_string(device_info, responses, status_str, strng, mock_base): def test_ReceiverFactory_string(device_info, responses, status_str, strng, mock_base):
mock_base[0].side_effect = open_path mock_base[0].side_effect = hidpp.open_path
mock_base[1].side_effect = partial(request, responses) mock_base[1].side_effect = partial(hidpp.request, responses)
r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x) r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x)
@ -193,8 +170,8 @@ def test_ReceiverFactory_string(device_info, responses, status_str, strng, mock_
], ],
) )
def test_ReceiverFactory_nodevice(device_info, responses, mock_base): def test_ReceiverFactory_nodevice(device_info, responses, mock_base):
mock_base[0].side_effect = open_path mock_base[0].side_effect = hidpp.open_path
mock_base[1].side_effect = partial(request, responses) mock_base[1].side_effect = partial(hidpp.request, responses)
r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x) r = receiver.ReceiverFactory.create_receiver(device_info, lambda x: x)