Merge pull request #220 from waveform80/test-real-pins

Add "real" pins tests
This commit is contained in:
Dave Jones
2016-02-21 23:21:23 +00:00
3 changed files with 148 additions and 3 deletions

View File

@@ -245,6 +245,7 @@ class NativePin(Pin):
def close(self):
self.when_changed = None
self.function = 'input'
self.pull = 'up' if self.number in (2, 3) else 'floating'
def _get_function(self):
return self.GPIO_FUNCTION_NAMES[(self._MEM[self._func_offset] >> self._func_shift) & 7]
@@ -253,7 +254,7 @@ class NativePin(Pin):
try:
value = self.GPIO_FUNCTIONS[value]
except KeyError:
raise PinInvalidFunction('invalid function "%s" for pin %r' % self)
raise PinInvalidFunction('invalid function "%s" for pin %r' % (value, self))
self._MEM[self._func_offset] = (
self._MEM[self._func_offset]
& ~(7 << self._func_shift)
@@ -282,7 +283,7 @@ class NativePin(Pin):
try:
value = self.GPIO_PULL_UPS[value]
except KeyError:
raise PinInvalidPull('invalid pull direction "%s" for pin %r' % self)
raise PinInvalidPull('invalid pull direction "%s" for pin %r' % (value, self))
self._MEM[self._MEM.GPPUD_OFFSET] = value
sleep(0.000000214)
self._MEM[self._pull_offset] = 1 << self._pull_shift

View File

@@ -13,6 +13,7 @@ from ..exc import (
PinInvalidFunction,
PinSetInput,
PinFixedPull,
PinInvalidPull,
)
@@ -144,7 +145,7 @@ class PiGPIOPin(Pin):
self.frequency = None
self.when_changed = None
self.function = 'input'
self.pull = 'floating'
self.pull = 'up' if self.number in (2, 3) else 'floating'
def _get_function(self):
return self.GPIO_FUNCTION_NAMES[self._connection.get_mode(self._number)]

143
tests/test_real_pins.py Normal file
View File

@@ -0,0 +1,143 @@
from __future__ import (
unicode_literals,
absolute_import,
print_function,
division,
)
str = type('')
import io
import subprocess
import pytest
from gpiozero import PinFixedPull, PinInvalidPull, PinInvalidFunction
# This module assumes you've wired the following GPIO pins together
TEST_PIN = 22
INPUT_PIN = 27
# Skip the entire module if we're not on a Pi
def is_a_pi():
with io.open('/proc/cpuinfo', 'r') as cpuinfo:
for line in cpuinfo:
if line.startswith('Hardware'):
hardware, colon, soc = line.strip().split(None, 2)
return soc in ('BCM2708', 'BCM2709', 'BCM2835', 'BCM2836')
else:
return False
pytestmark = pytest.mark.skipif(not is_a_pi(), reason='tests cannot run on non-Pi platforms')
del is_a_pi
# Try and import as many pin libraries as possible
PIN_CLASSES = []
try:
from gpiozero.pins.rpigpio import RPiGPIOPin
PIN_CLASSES.append(RPiGPIOPin)
except ImportError:
RPiGPIOPin = None
try:
from gpiozero.pins.rpio import RPIOPin
PIN_CLASSES.append(RPIOPin)
except ImportError:
RPIOPin = None
try:
from gpiozero.pins.pigpiod import PiGPIOPin
PIN_CLASSES.append(PiGPIOPin)
except ImportError:
PiGPIOPin = None
try:
from gpiozero.pins.native import NativePin
PIN_CLASSES.append(NativePin)
except ImportError:
NativePin = None
@pytest.fixture(scope='module', params=PIN_CLASSES)
def pin_class(request):
# pigpiod needs to be running for PiGPIOPin
if request.param.__name__ == 'PiGPIOPin':
subprocess.check_call(['sudo', 'pigpiod'])
# Unfortunately, pigpiod provides no option for running in the
# foreground, so we have to use the sledgehammer of killall to get shot
# of it
def kill_pigpiod():
subprocess.check_call(['sudo', 'killall', 'pigpiod'])
request.addfinalizer(kill_pigpiod)
return request.param
@pytest.fixture
def pins(request, pin_class):
# Why return both pins in a single fixture? If we defined one fixture for
# each pin then pytest will (correctly) test RPiGPIOPin(22) against
# NativePin(27) and so on. This isn't supported, so we don't test it
test_pin = pin_class(22)
input_pin = pin_class(27)
input_pin.function = 'input'
input_pin.pull = 'down'
def fin():
test_pin.close()
input_pin.close()
request.addfinalizer(fin)
return test_pin, input_pin
def test_pin_numbers(pins):
test_pin, input_pin = pins
assert test_pin.number == 22
assert input_pin.number == 27
def test_function_bad(pins):
test_pin, input_pin = pins
with pytest.raises(PinInvalidFunction):
test_pin.function = 'foo'
def test_output(pins):
test_pin, input_pin = pins
test_pin.function = 'output'
test_pin.state = 0
assert input_pin.state == 0
test_pin.state = 1
assert input_pin.state == 1
def test_output_with_state(pins):
test_pin, input_pin = pins
test_pin.output_with_state(0)
assert input_pin.state == 0
test_pin.output_with_state(1)
assert input_pin.state == 1
def test_pull(pins):
test_pin, input_pin = pins
test_pin.function = 'input'
test_pin.pull = 'up'
assert input_pin.state == 1
test_pin.pull = 'down'
test_pin, input_pin = pins
assert input_pin.state == 0
def test_pull_bad(pins):
test_pin, input_pin = pins
test_pin.function = 'input'
with pytest.raises(PinInvalidPull):
test_pin.pull = 'foo'
def test_pull_down_warning(pin_class):
pin = pin_class(2)
try:
with pytest.raises(PinFixedPull):
pin.pull = 'down'
finally:
pin.close()
def test_input_with_pull(pins):
test_pin, input_pin = pins
test_pin.input_with_pull('up')
assert input_pin.state == 1
test_pin.input_with_pull('down')
assert input_pin.state == 0