1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
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')
|