FiWiControl/tests/test_power_discovery.py

132 lines
4.1 KiB
Python

# Copyright (c) 2026 Umber
#
# Licensed under the Apache License, Version 2.0; see LICENSE.
from __future__ import annotations
import json
from types import SimpleNamespace
from unittest import mock
import pytest
from fiwicontrol.lab.discovery import (
MONSOON_USB_VID,
MONSOON_USB_PIDS,
_discover_monsoon_sysfs_usb,
acroname_module_info_from_spec,
discover_monsoon_serial_ports,
discovery_json,
parse_remote_discovery_payload,
)
@pytest.mark.parametrize(
"model_id, stem, downstream, entities",
[
(19, "USBHub3p", 8, 12),
(17, "USBHub2x4", 4, 6),
(24, "USBHub3c", 8, 8),
],
)
def test_acroname_module_info_from_spec_layout(model_id, stem, downstream, entities):
pytest.importorskip("brainstem")
import brainstem.discover as discover
spec = discover.Spec(discover.Spec.USB, 0xABCDEF01, 6, model_id)
info = acroname_module_info_from_spec(spec)
assert info.stem_class == stem
assert info.downstream_usb_ports == downstream
assert info.hub_port_entities == entities
assert info.transport == "USB"
assert info.serial_number == 0xABCDEF01
assert info.module_address == 6
assert stem in info.model_name or info.model_name.startswith("USB")
def test_discover_monsoon_sysfs_usb(tmp_path):
dev = tmp_path / "5-2"
dev.mkdir()
(dev / "idVendor").write_text("2ab9\n", encoding="utf-8")
(dev / "idProduct").write_text("0001\n", encoding="utf-8")
(dev / "busnum").write_text("5\n", encoding="utf-8")
(dev / "devnum").write_text("2\n", encoding="utf-8")
(dev / "serial").write_text("HVPM-TEST\n", encoding="utf-8")
rows = _discover_monsoon_sysfs_usb(
vid=MONSOON_USB_VID,
pids=MONSOON_USB_PIDS,
sysfs_usb_devices=tmp_path,
)
assert len(rows) == 1
assert rows[0].device == "/dev/bus/usb/5/2"
assert rows[0].vid == MONSOON_USB_VID
assert rows[0].pid == 0x0001
assert rows[0].serial_number == "HVPM-TEST"
def test_discover_monsoon_serial_ports_filters_vid_pid():
pytest.importorskip("serial")
fake = SimpleNamespace(
device="/dev/ttyUSB0",
serial_number="SN1",
vid=MONSOON_USB_VID,
pid=0x0001,
manufacturer="Monsoon",
description="HVPM",
hwid="USB VID:PID=2AB9:0001",
)
other = SimpleNamespace(
device="/dev/ttyS0",
serial_number=None,
vid=0x1234,
pid=0x5678,
manufacturer=None,
description="not monsoon",
hwid="",
)
with mock.patch("serial.tools.list_ports.comports", return_value=[other, fake]):
ports = discover_monsoon_serial_ports()
assert len(ports) == 1
assert ports[0].device == "/dev/ttyUSB0"
assert ports[0].serial_number == "SN1"
def test_discovery_json_is_parseable():
pytest.importorskip("brainstem")
pytest.importorskip("serial")
with mock.patch("fiwicontrol.lab.discovery.discover_acroname_modules", return_value=[]):
with mock.patch("fiwicontrol.lab.discovery.discover_monsoon_serial_ports", return_value=[]):
data = json.loads(discovery_json())
assert data["acroname"] == []
assert data["monsoon"] == []
assert "brainstem_version" in data
def test_parse_remote_discovery_payload_round_trip():
pytest.importorskip("brainstem")
import brainstem.discover as discover
spec = discover.Spec(discover.Spec.USB, 1, 6, 17)
info = acroname_module_info_from_spec(spec)
raw = {
"acroname": [
{
"transport": info.transport,
"serial_number": info.serial_number,
"module_address": info.module_address,
"model_id": info.model_id,
"model_name": info.model_name,
"model_description": info.model_description,
"stem_class": info.stem_class,
"downstream_usb_ports": info.downstream_usb_ports,
"hub_port_entities": info.hub_port_entities,
}
],
"monsoon": [],
}
ac, mo = parse_remote_discovery_payload(raw)
assert len(ac) == 1
assert ac[0].stem_class == "USBHub2x4"
assert ac[0].downstream_usb_ports == 4
assert mo == []