Files
python-gpiozero/tests/test_spi.py
Dave Jones d2a7c1434a Fix SPI tests when spidev is installed
Doh! SPI tests fail when the spidev package is installed (which it
normally isn't in my virtualenv) because hardware SPI always takes
precedence and the mock SPI stuff only replaces software SPI.
2017-06-21 14:40:52 +01:00

198 lines
8.1 KiB
Python

from __future__ import (
unicode_literals,
absolute_import,
print_function,
division,
)
nstr = str
str = type('')
import sys
import pytest
from array import array
from mock import patch
from collections import namedtuple
from gpiozero.pins.native import NativeFactory
from gpiozero.pins.local import (
LocalPiHardwareSPI,
LocalPiSoftwareSPI,
LocalPiHardwareSPIShared,
LocalPiSoftwareSPIShared,
)
from gpiozero.pins.mock import MockSPIDevice
from gpiozero import *
def teardown_function(function):
Device._pin_factory.reset()
def test_spi_hardware_params():
with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
io_open.return_value.__enter__.return_value = ['Revision: a21042']
with patch('gpiozero.devices.Device._pin_factory', NativeFactory()), \
patch('gpiozero.pins.local.SpiDev'):
with Device._pin_factory.spi() as device:
assert isinstance(device, LocalPiHardwareSPI)
with Device._pin_factory.spi(port=0, device=0) as device:
assert isinstance(device, LocalPiHardwareSPI)
with Device._pin_factory.spi(port=0, device=1) as device:
assert isinstance(device, LocalPiHardwareSPI)
with Device._pin_factory.spi(clock_pin=11) as device:
assert isinstance(device, LocalPiHardwareSPI)
with Device._pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=8) as device:
assert isinstance(device, LocalPiHardwareSPI)
with Device._pin_factory.spi(clock_pin=11, mosi_pin=10, select_pin=7) as device:
assert isinstance(device, LocalPiHardwareSPI)
with Device._pin_factory.spi(shared=True) as device:
assert isinstance(device, LocalPiHardwareSPIShared)
with pytest.raises(ValueError):
Device._pin_factory.spi(port=1)
with pytest.raises(ValueError):
Device._pin_factory.spi(device=2)
with pytest.raises(ValueError):
Device._pin_factory.spi(port=0, clock_pin=12)
with pytest.raises(ValueError):
Device._pin_factory.spi(foo='bar')
def test_spi_software_params():
with patch('os.open'), patch('mmap.mmap') as mmap_mmap, patch('io.open') as io_open:
mmap_mmap.return_value = array(nstr('B'), (0,) * 4096)
io_open.return_value.__enter__.return_value = ['Revision: a21042']
with patch('gpiozero.devices.Device._pin_factory', NativeFactory()), \
patch('gpiozero.pins.local.SpiDev'):
with Device._pin_factory.spi(select_pin=6) as device:
assert isinstance(device, LocalPiSoftwareSPI)
with Device._pin_factory.spi(clock_pin=11, mosi_pin=9, miso_pin=10) as device:
assert isinstance(device, LocalPiSoftwareSPI)
with Device._pin_factory.spi(select_pin=6, shared=True) as device:
assert isinstance(device, LocalPiSoftwareSPIShared)
with patch('gpiozero.devices.Device._pin_factory', NativeFactory()), \
patch('gpiozero.pins.local.SpiDev', None):
# Clear out the old factory's pins cache (this is only necessary
# because we're being very naughty switching out pin factories)
Device._pin_factory.pins.clear()
# Ensure software fallback works when SpiDev isn't present
with Device._pin_factory.spi() as device:
assert isinstance(device, LocalPiSoftwareSPI)
def test_spi_hardware_conflict():
with patch('gpiozero.pins.local.SpiDev') as spidev:
with LED(11) as led:
with pytest.raises(GPIOPinInUse):
Device._pin_factory.spi(port=0, device=0)
with patch('gpiozero.pins.local.SpiDev') as spidev:
with Device._pin_factory.spi(port=0, device=0) as spi:
with pytest.raises(GPIOPinInUse):
LED(11)
def test_spi_hardware_read():
with patch('gpiozero.pins.local.SpiDev') as spidev:
spidev.return_value.xfer2.side_effect = lambda data: list(range(10))[:len(data)]
with Device._pin_factory.spi() as device:
assert device.read(3) == [0, 1, 2]
assert device.read(6) == list(range(6))
def test_spi_hardware_write():
with patch('gpiozero.pins.local.SpiDev') as spidev:
spidev.return_value.xfer2.side_effect = lambda data: list(range(10))[:len(data)]
with Device._pin_factory.spi() as device:
assert device.write([0, 1, 2]) == 3
assert spidev.return_value.xfer2.called_with([0, 1, 2])
assert device.write(list(range(6))) == 6
assert spidev.return_value.xfer2.called_with(list(range(6)))
def test_spi_hardware_modes():
with patch('gpiozero.pins.local.SpiDev') as spidev:
spidev.return_value.mode = 0
spidev.return_value.lsbfirst = False
spidev.return_value.cshigh = True
spidev.return_value.bits_per_word = 8
with Device._pin_factory.spi() as device:
assert device.clock_mode == 0
assert not device.clock_polarity
assert not device.clock_phase
device.clock_polarity = False
assert device.clock_mode == 0
device.clock_polarity = True
assert device.clock_mode == 2
device.clock_phase = True
assert device.clock_mode == 3
assert not device.lsb_first
assert device.select_high
assert device.bits_per_word == 8
device.select_high = False
device.lsb_first = True
device.bits_per_word = 12
assert not spidev.return_value.cshigh
assert spidev.return_value.lsbfirst
assert spidev.return_value.bits_per_word == 12
def test_spi_software_read():
class SPISlave(MockSPIDevice):
def on_start(self):
super(SPISlave, self).on_start()
for i in range(10):
self.tx_word(i)
with patch('gpiozero.pins.local.SpiDev', None), \
SPISlave(11, 10, 9, 8) as slave, \
Device._pin_factory.spi() as master:
assert master.read(3) == [0, 1, 2]
assert master.read(6) == [0, 1, 2, 3, 4, 5]
slave.clock_phase = True
master.clock_phase = True
assert master.read(3) == [0, 1, 2]
assert master.read(6) == [0, 1, 2, 3, 4, 5]
def test_spi_software_write():
with patch('gpiozero.pins.local.SpiDev', None), \
MockSPIDevice(11, 10, 9, 8) as test_device, \
Device._pin_factory.spi() as master:
master.write([0])
assert test_device.rx_word() == 0
master.write([2, 0])
assert test_device.rx_word() == 512
master.write([0, 1, 1])
assert test_device.rx_word() == 257
def test_spi_software_clock_mode():
with patch('gpiozero.pins.local.SpiDev', None), \
Device._pin_factory.spi() as master:
assert master.clock_mode == 0
assert not master.clock_polarity
assert not master.clock_phase
master.clock_polarity = False
assert master.clock_mode == 0
master.clock_polarity = True
assert master.clock_mode == 2
master.clock_phase = True
assert master.clock_mode == 3
master.clock_mode = 0
assert not master.clock_polarity
assert not master.clock_phase
with pytest.raises(ValueError):
master.clock_mode = 5
def test_spi_software_attr():
with patch('gpiozero.pins.local.SpiDev', None), \
Device._pin_factory.spi() as master:
assert not master.lsb_first
assert not master.select_high
assert master.bits_per_word == 8
master.bits_per_word = 12
assert master.bits_per_word == 12
master.lsb_first = True
assert master.lsb_first
master.select_high = True
assert master.select_high
with pytest.raises(ValueError):
master.bits_per_word = 0
# XXX Test two simultaneous SPI devices sharing clock, MOSI, and MISO, with
# separate select pins (including threaded tests which attempt simultaneous
# reading/writing)