liquidctl/tests/test_smbus.py

159 lines
4.3 KiB
Python

import pytest
from pathlib import Path
from liquidctl.driver.smbus import LinuxI2c, LinuxI2cBus, SmbusDriver
class Canary(SmbusDriver):
"""Canary driver to reveal if SMBus probing is taking place."""
@classmethod
def probe(cls, smbus, **kwargs):
yield Canary(smbus, 'Canary', vendor_id=-1, product_id=-1, address=-1)
def connect(self, **kwargs):
# there is no justification for calling connect on this test driver
raise RuntimeError('forbidden')
def __repr__(self):
return repr(self._smbus)
def replace_smbus(replacement, monkeypatch):
import liquidctl.driver.smbus
# fragile hack: since messing with sys.meta_path (PEP 302) is tricky in a
# pytest context, get into liquidctl.driver.smbus module and replace the
# imported SMBus class after the fact
monkeypatch.setattr(liquidctl.driver.smbus, 'SMBus', replacement)
return replacement
@pytest.fixture
def emulated_smbus(monkeypatch):
"""Replace the SMBus implementation in liquidctl.driver.smbus."""
class SMBus:
def __init__(self, number):
pass
return replace_smbus(SMBus, monkeypatch)
def test__helper_fixture_replaces_real_smbus_implementation(emulated_smbus, tmpdir):
i2c_dev = Path(tmpdir.mkdir('i2c-9999')) # unlikely to be valid
bus = LinuxI2cBus(i2c_dev=i2c_dev)
bus.open()
assert type(bus._smbus) == emulated_smbus
def test_filter_by_usb_port_yields_no_devices(emulated_smbus):
discovered = Canary.find_supported_devices(usb_port='usb1')
assert discovered == []
def test_aborts_if_sysfs_is_missing_devices(emulated_smbus, tmpdir):
empty = tmpdir.mkdir('sys').mkdir('bus').mkdir('i2c')
virtual_bus = LinuxI2c(i2c_root=empty)
discovered = Canary.find_supported_devices(root_bus=virtual_bus)
assert discovered == []
def test_finds_a_device(emulated_smbus, tmpdir):
i2c_root = tmpdir.mkdir('sys').mkdir('bus').mkdir('i2c')
i2c_root.mkdir('devices').mkdir('i2c-42')
virtual_bus = LinuxI2c(i2c_root=i2c_root)
discovered = Canary.find_supported_devices(root_bus=virtual_bus)
assert len(discovered) == 1
assert discovered[0]._smbus.name == 'i2c-42'
def test_ignores_non_bus_sysfs_entries(emulated_smbus, tmpdir):
i2c_root = tmpdir.mkdir('sys').mkdir('bus').mkdir('i2c')
devices = i2c_root.mkdir('devices')
devices.mkdir('i2c-0')
devices.mkdir('0-0050') # SPD info chip on i2c-0
devices.mkdir('i2c-DELL0829:00') # i2c HID chip from Dell laptop
virtual_bus = LinuxI2c(i2c_root=i2c_root)
discovered = Canary.find_supported_devices(root_bus=virtual_bus)
assert len(discovered) == 1
assert discovered[0]._smbus.name == 'i2c-0'
def test_honors_a_bus_filter(emulated_smbus, tmpdir):
i2c_root = tmpdir.mkdir('sys').mkdir('bus').mkdir('i2c')
devices = i2c_root.mkdir('devices')
devices.mkdir('i2c-0')
devices.mkdir('i2c-1')
virtual_bus = LinuxI2c(i2c_root=i2c_root)
discovered = Canary.find_supported_devices(bus='i2c-1',
root_bus=virtual_bus)
assert len(discovered) == 1
assert discovered[0]._smbus.name == 'i2c-1'
@pytest.fixture
def emulated_device(tmpdir, emulated_smbus):
i2c_dev = Path(tmpdir.mkdir('i2c-0'))
bus = LinuxI2cBus(i2c_dev=i2c_dev)
dev = SmbusDriver(smbus=bus, description='Test', vendor_id=-1,
product_id=-1, address=-1)
return (bus, dev)
def test_connect_is_unsafe(emulated_device):
bus, dev = emulated_device
def mock_open():
nonlocal opened
opened = True
bus.open = mock_open
opened = False
dev.connect()
assert not opened
def test_connects(emulated_device):
bus, dev = emulated_device
def mock_open():
nonlocal opened
opened = True
bus.open = mock_open
opened = False
with dev.connect(unsafe='smbus') as cm:
assert cm == dev
assert opened
def test_loading_unnavailable_eeprom_returns_none(emulated_device):
bus, dev = emulated_device
assert bus.load_eeprom(0x51) is None
def test_loads_eeprom(emulated_device):
bus, dev = emulated_device
spd = bus._i2c_dev.joinpath('0-0051')
spd.mkdir()
spd.joinpath('eeprom').write_bytes(b'012345')
spd.joinpath('name').write_text('name\n')
assert bus.load_eeprom(0x51) == ('name', b'012345')