- HID-чтение ChatMix (0x06 0x24) для Arctis 7 2019 — get_chatmix_level() - pactl-функции get_sink_volume() / set_sink_volume() - Поля game и chat в SinkConfig для имён PipeWire сингов каналов - CLI: lgcompanion volume get/set game|chat, lgcompanion chatmix - GUI: слайдеры громкости каналов на странице устройства - QSS-стили для QSlider в обеих темах (светлая/тёмная) - Диагностика ChatMix в lgcompanion diagnose - Сигнал chatmix_changed в EngineWorker для GUI - 8 новых тестов (ChatMix, volume pactl, config roundtrip)
117 lines
4.1 KiB
Python
117 lines
4.1 KiB
Python
"""Tests for HID discovery and battery polling."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from lgcompanion.config import DeviceProfile
|
|
from lgcompanion.hid_backend import (
|
|
_parse_hid_id,
|
|
find_hidraw_device,
|
|
get_battery_level,
|
|
get_chatmix_level,
|
|
)
|
|
|
|
|
|
def test_parse_hid_id_valid() -> None:
|
|
assert _parse_hid_id("0003:00001038:000012AD") == (0x1038, 0x12AD)
|
|
|
|
|
|
def test_parse_hid_id_invalid() -> None:
|
|
assert _parse_hid_id("bad") is None
|
|
assert _parse_hid_id("1:2") is None
|
|
|
|
|
|
def _make_uevent(vid: str, pid: str, name: str) -> str:
|
|
return f"HID_ID=0003:0000{vid}:0000{pid}\nHID_NAME={name}\n"
|
|
|
|
|
|
def test_find_hidraw_device_matches_profile(tmp_path: Path, monkeypatch) -> None:
|
|
# Build a fake sysfs tree under tmp_path
|
|
hidraw_root = tmp_path / "sys" / "class" / "hidraw"
|
|
hidraw_root.mkdir(parents=True)
|
|
node = hidraw_root / "hidraw0"
|
|
node.mkdir()
|
|
device_dir = node / "device"
|
|
device_dir.mkdir()
|
|
(device_dir / "uevent").write_text(_make_uevent("1038", "12AD", "SteelSeries Arctis 7"))
|
|
|
|
profile = DeviceProfile(
|
|
name="Arctis 7 2019",
|
|
vendor_id="0x1038",
|
|
product_id="0x12AD",
|
|
control_interface=0,
|
|
)
|
|
|
|
import lgcompanion.hid_backend as hid_mod
|
|
|
|
def fake_path(arg: str) -> Path:
|
|
if arg == "/sys/class/hidraw":
|
|
return hidraw_root
|
|
if arg == "/dev":
|
|
return tmp_path / "dev"
|
|
return Path(arg)
|
|
|
|
monkeypatch.setattr(hid_mod, "Path", fake_path)
|
|
|
|
found = find_hidraw_device([profile])
|
|
assert found is not None
|
|
assert found.profile.name == "Arctis 7 2019"
|
|
assert found.path == str(tmp_path / "dev" / "hidraw0")
|
|
|
|
|
|
def test_get_battery_level() -> None:
|
|
profile = DeviceProfile(name="Test", vendor_id="0x1038", product_id="0x12AD")
|
|
device = MagicMock(path="/dev/hidraw0", profile=profile)
|
|
with patch("lgcompanion.hid_backend.query_headset_raw") as mock_query:
|
|
mock_query.return_value = (True, b"\x06\x18\x50")
|
|
assert get_battery_level(device, 1.0) == 80
|
|
|
|
|
|
def test_get_battery_level_timeout() -> None:
|
|
profile = DeviceProfile(name="Test", vendor_id="0x1038", product_id="0x12AD")
|
|
device = MagicMock(path="/dev/hidraw0", profile=profile)
|
|
with patch("lgcompanion.hid_backend.query_headset_raw") as mock_query:
|
|
mock_query.return_value = (False, b"")
|
|
assert get_battery_level(device, 1.0) is None
|
|
|
|
|
|
def test_get_chatmix_level_center() -> None:
|
|
profile = DeviceProfile(name="Test", vendor_id="0x1038", product_id="0x12AD")
|
|
device = MagicMock(path="/dev/hidraw0", profile=profile)
|
|
with patch("lgcompanion.hid_backend.query_headset_raw") as mock_query:
|
|
mock_query.return_value = (True, b"\x06\x24\x00\x00")
|
|
result = get_chatmix_level(device, 1.0)
|
|
assert result == (100, 100)
|
|
|
|
|
|
def test_get_chatmix_level_game_max() -> None:
|
|
profile = DeviceProfile(name="Test", vendor_id="0x1038", product_id="0x12AD")
|
|
device = MagicMock(path="/dev/hidraw0", profile=profile)
|
|
with patch("lgcompanion.hid_backend.query_headset_raw") as mock_query:
|
|
mock_query.return_value = (True, b"\x06\x24\xFF\xBF")
|
|
result = get_chatmix_level(device, 1.0)
|
|
assert result is not None
|
|
assert result[0] == 100
|
|
assert result[1] == 0
|
|
|
|
|
|
def test_get_chatmix_level_chat_max() -> None:
|
|
profile = DeviceProfile(name="Test", vendor_id="0x1038", product_id="0x12AD")
|
|
device = MagicMock(path="/dev/hidraw0", profile=profile)
|
|
with patch("lgcompanion.hid_backend.query_headset_raw") as mock_query:
|
|
mock_query.return_value = (True, b"\x06\x24\xBF\xFF")
|
|
result = get_chatmix_level(device, 1.0)
|
|
assert result is not None
|
|
assert result[0] == 0
|
|
assert result[1] == 100
|
|
|
|
|
|
def test_get_chatmix_level_timeout() -> None:
|
|
profile = DeviceProfile(name="Test", vendor_id="0x1038", product_id="0x12AD")
|
|
device = MagicMock(path="/dev/hidraw0", profile=profile)
|
|
with patch("lgcompanion.hid_backend.query_headset_raw") as mock_query:
|
|
mock_query.return_value = (False, b"")
|
|
assert get_chatmix_level(device, 1.0) is None
|