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