# Copyright (c) 2013-2021 Ben Croston
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import print_function
if hasattr(__builtins__, 'raw_input'):
input = raw_input
"""RPi.GPIO unit tests
This test suite assumes the following circuit is connected:
GND_PIN = 6
LED_PIN = 12 (with resistor to 0v)
SWITCH_PIN = 18 (with 0.1 uF capacitor around switch) to 0v
LOOP_IN = 16 connected with 1K resistor to LOOP_OUT
LOOP_OUT = 22
NC_PIN = 24 not connected to anything
"""
import os
import subprocess
import sys
import warnings
import time
from threading import Timer
import RPi.GPIO as GPIO
if sys.version[:3] == '2.6':
import unittest2 as unittest
else:
import unittest
GND_PIN = 6
LED_PIN = 12
LED_PIN_BCM = 18
SWITCH_PIN = 18
SWITCH_PIN_BCM = 24
LOOP_IN = 16
LOOP_IN_BCM = 23
LOOP_OUT = 22
NC_PIN = 24
non_interactive = False
for i,val in enumerate(sys.argv):
if val == '--non_interactive':
non_interactive = True
sys.argv.pop(i)
# Test starts with 'AAA' so that it is run first
class TestAAASetup(unittest.TestCase):
def runTest(self):
# Test mode not set (BOARD or BCM) exception
with self.assertRaises(RuntimeError) as e:
GPIO.setup(LED_PIN, GPIO.OUT)
self.assertEqual(str(e.exception), 'Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM)')
# Test trying to change mode after it has been set
GPIO.setmode(GPIO.BCM)
with self.assertRaises(ValueError) as e:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN_BCM, GPIO.IN)
GPIO.cleanup()
# Test setting an invalid mode
with self.assertRaises(ValueError):
GPIO.setmode(666)
# Test getmode()
self.assertEqual(GPIO.getmode(), None)
GPIO.setmode(GPIO.BCM)
self.assertEqual(GPIO.getmode(), GPIO.BCM)
GPIO.setup(LED_PIN_BCM, GPIO.IN)
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
self.assertEqual(GPIO.getmode(), GPIO.BOARD)
# Test not set as OUTPUT message
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(RuntimeError) as e:
GPIO.output(LED_PIN, GPIO.HIGH)
self.assertEqual(str(e.exception), 'The GPIO channel has not been set up as an OUTPUT')
# Test setup(..., pull_up_down=GPIO.HIGH) raises exception
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(ValueError):
GPIO.setup(LED_PIN, GPIO.IN, pull_up_down=GPIO.HIGH)
# Test not valid on a raspi exception
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(ValueError) as e:
GPIO.setup(GND_PIN, GPIO.OUT)
self.assertEqual(str(e.exception), 'The channel sent is invalid on a Raspberry Pi')
# Test 'already in use' warning
GPIO.setmode(GPIO.BOARD)
with open('/sys/class/gpio/export','wb') as f:
f.write(str(LED_PIN_BCM).encode())
time.sleep(0.2) # wait for udev to set permissions
with open('/sys/class/gpio/gpio%s/direction'%LED_PIN_BCM,'wb') as f:
f.write(b'out')
time.sleep(0.2)
with warnings.catch_warnings(record=True) as w:
GPIO.setup(LED_PIN, GPIO.OUT) # generate 'already in use' warning
self.assertEqual(w[0].category, RuntimeWarning)
with open('/sys/class/gpio/unexport','wb') as f:
f.write(str(LED_PIN_BCM).encode())
GPIO.cleanup()
# test initial value of high reads back as high
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.HIGH)
self.assertEqual(GPIO.input(LED_PIN), GPIO.HIGH)
GPIO.cleanup()
# test initial value of low reads back as low
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)
self.assertEqual(GPIO.input(LED_PIN), GPIO.LOW)
GPIO.cleanup()
# test pull up/down works
GPIO.setmode(GPIO.BOARD)
for i in range(1000):
GPIO.setup(NC_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
time.sleep(0.001)
self.assertEqual(GPIO.input(NC_PIN), GPIO.LOW)
GPIO.setup(NC_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
time.sleep(0.001)
self.assertEqual(GPIO.input(NC_PIN), GPIO.HIGH)
GPIO.cleanup()
# test setup of a list of channels
GPIO.setmode(GPIO.BOARD)
GPIO.setup( [LED_PIN, LOOP_OUT], GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT)
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(ValueError) as e:
GPIO.setup( [LED_PIN, GND_PIN], GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
self.assertEqual(str(e.exception), 'The channel sent is invalid on a Raspberry Pi')
GPIO.cleanup()
# test setup of a tuple of channels
GPIO.setmode(GPIO.BOARD)
GPIO.setup( (LED_PIN, LOOP_OUT), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT)
GPIO.cleanup()
# test warning when using pull up/down on i2c channels
GPIO.setmode(GPIO.BOARD)
if GPIO.RPI_INFO['P1_REVISION'] == 0: # compute module
pass # test not vailid
else: # revision 1, 2 or A+/B+
with warnings.catch_warnings(record=True) as w:
GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
self.assertEqual(w[0].category, RuntimeWarning)
with warnings.catch_warnings(record=True) as w:
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
self.assertEqual(w[0].category, RuntimeWarning)
GPIO.cleanup()
# test non integer channel
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(ValueError):
GPIO.setup('d', GPIO.OUT)
with self.assertRaises(ValueError):
GPIO.setup(('d',LED_PIN), GPIO.OUT)
# test setting pull_up_down on an output
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(ValueError):
GPIO.setup(LOOP_OUT, GPIO.OUT, pull_up_down=GPIO.PUD_DOWN)
# test setting initial on an input
GPIO.setmode(GPIO.BOARD)
with self.assertRaises(ValueError):
GPIO.setup(LOOP_IN, GPIO.IN, initial=GPIO.LOW)
class TestInputOutput(unittest.TestCase):
def setUp(self):
GPIO.setmode(GPIO.BOARD)
def test_outputread(self):
"""Test that an output() can be input()"""
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.output(LED_PIN, GPIO.HIGH)
self.assertEqual(GPIO.input(LED_PIN), GPIO.HIGH)
GPIO.output(LED_PIN, GPIO.LOW)
self.assertEqual(GPIO.input(LED_PIN), GPIO.LOW)
def test_loopback(self):
"""Test output loops back to another input"""
GPIO.setup(LOOP_IN, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
GPIO.setup(LOOP_OUT, GPIO.OUT, initial=GPIO.LOW)
self.assertEqual(GPIO.input(LOOP_IN), GPIO.LOW)
GPIO.output(LOOP_OUT, GPIO.HIGH)
self.assertEqual(GPIO.input(LOOP_IN), GPIO.HIGH)
def test_output_on_input(self):
"""Test output() can not be done on input"""
GPIO.setup(SWITCH_PIN, GPIO.IN)
with self.assertRaises(RuntimeError):
GPIO.output(SWITCH_PIN, GPIO.LOW)
def test_output_list(self):
"""Test output() using lists"""
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.output( [LOOP_OUT, LED_PIN], GPIO.HIGH)
self.assertEqual(GPIO.input(LOOP_OUT), GPIO.HIGH)
self.assertEqual(GPIO.input(LED_PIN), GPIO.HIGH)
GPIO.output( (LOOP_OUT, LED_PIN), GPIO.LOW)
self.assertEqual(GPIO.input(LOOP_OUT), GPIO.LOW)
self.assertEqual(GPIO.input(LED_PIN), GPIO.LOW)
GPIO.output( [LOOP_OUT, LED_PIN], [GPIO.HIGH, GPIO.LOW] )
self.assertEqual(GPIO.input(LOOP_OUT), GPIO.HIGH)
self.assertEqual(GPIO.input(LED_PIN), GPIO.LOW)
GPIO.output( (LOOP_OUT, LED_PIN), (GPIO.LOW, GPIO.HIGH) )
self.assertEqual(GPIO.input(LOOP_OUT), GPIO.LOW)
self.assertEqual(GPIO.input(LED_PIN), GPIO.HIGH)
with self.assertRaises(RuntimeError):
GPIO.output( [LOOP_OUT, LED_PIN], [0,0,0] )
with self.assertRaises(RuntimeError):
GPIO.output( [LOOP_OUT, LED_PIN], (0,) )
with self.assertRaises(RuntimeError):
GPIO.output(LOOP_OUT, (0,0))
with self.assertRaises(ValueError):
GPIO.output( [LOOP_OUT, 'x'], (0,0) )
with self.assertRaises(ValueError):
GPIO.output( [LOOP_OUT, LED_PIN], (0,'x') )
with self.assertRaises(ValueError):
GPIO.output( [LOOP_OUT, GND_PIN], (0,0) )
with self.assertRaises(RuntimeError):
GPIO.output( [LOOP_OUT, LOOP_IN], (0,0) )
def tearDown(self):
GPIO.cleanup()
class TestSoftPWMExists(unittest.TestCase):
def runTest(self):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT)
pwm = GPIO.PWM(LED_PIN, 50)
with self.assertRaises(RuntimeError):
pwm2 = GPIO.PWM(LED_PIN, 49)
GPIO.cleanup()
class TestSoftPWM(unittest.TestCase):
@unittest.skipIf(non_interactive, 'Non interactive mode')
def runTest(self):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT)
pwm = GPIO.PWM(LED_PIN, 50)
pwm.start(100)
print("\nPWM tests")
response = input('Is the LED on (y/n) ? ').upper()
self.assertEqual(response,'Y')
pwm.start(0)
response = input('Is the LED off (y/n) ? ').upper()
self.assertEqual(response,'Y')
print("LED Brighten/fade test...")
for i in range(0,3):
for x in range(0,101,5):
pwm.ChangeDutyCycle(x)
time.sleep(0.1)
for x in range(100,-1,-5):
pwm.ChangeDutyCycle(x)
time.sleep(0.1)
pwm.stop()
response = input('Did it work (y/n) ? ').upper()
self.assertEqual(response,'Y')
GPIO.cleanup()
class TestSetWarnings(unittest.TestCase):
def test_alreadyinuse(self):
"""Test 'already in use' warning"""
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
with open('/sys/class/gpio/export','wb') as f:
f.write(str(LED_PIN_BCM).encode())
time.sleep(0.2) # wait for udev to set permissions
with open('/sys/class/gpio/gpio%s/direction'%LED_PIN_BCM,'wb') as f:
f.write(b'out')
with warnings.catch_warnings(record=True) as w:
GPIO.setup(LED_PIN, GPIO.OUT) # generate 'already in use' warning
self.assertEqual(len(w),0) # should be no warnings
with open('/sys/class/gpio/unexport','wb') as f:
f.write(str(LED_PIN_BCM).encode())
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(True)
with open('/sys/class/gpio/export','wb') as f:
f.write(str(LED_PIN_BCM).encode())
time.sleep(0.2) # wait for udev to set permissions
with open('/sys/class/gpio/gpio%s/direction'%LED_PIN_BCM,'wb') as f:
f.write(b'out')
with warnings.catch_warnings(record=True) as w:
GPIO.setup(LED_PIN, GPIO.OUT) # generate 'already in use' warning
self.assertEqual(w[0].category, RuntimeWarning)
with open('/sys/class/gpio/unexport','wb') as f:
f.write(str(LED_PIN_BCM).encode())
GPIO.cleanup()
def test_cleanupwarning(self):
"""Test initial GPIO.cleanup() produces warning"""
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(SWITCH_PIN, GPIO.IN)
with warnings.catch_warnings(record=True) as w:
GPIO.cleanup()
self.assertEqual(len(w),0) # no warnings
GPIO.cleanup()
self.assertEqual(len(w),0) # no warnings
GPIO.setwarnings(True)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(SWITCH_PIN, GPIO.IN)
with warnings.catch_warnings(record=True) as w:
GPIO.cleanup()
self.assertEqual(len(w),0) # no warnings
GPIO.cleanup()
self.assertEqual(w[0].category, RuntimeWarning) # a warning
class TestVersions(unittest.TestCase):
def test_rpi_info(self):
print('RPi Board Information')
print('---------------------')
for key,val in list(GPIO.RPI_INFO.items()):
print('%s => %s'%(key,val))
response = input('\nIs this board info correct (y/n) ? ').upper()
self.assertEqual(response, 'Y')
def test_gpio_version(self):
response = input('\nRPi.GPIO version %s - is this correct (y/n) ? '%GPIO.VERSION).upper()
self.assertEqual(response, 'Y')
class TestGPIOFunction(unittest.TestCase):
def runTest(self):
GPIO.setmode(GPIO.BCM)
GPIO.setup(LED_PIN_BCM, GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN_BCM), GPIO.IN)
GPIO.setup(LED_PIN_BCM, GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN_BCM), GPIO.OUT)
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
GPIO.setup(LED_PIN, GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
def tearDown(self):
GPIO.cleanup()
class TestSwitchBounce(unittest.TestCase):
def __init__(self, *a, **k):
unittest.TestCase.__init__(self, *a, **k)
self.switchcount = 0
def cb(self,chan):
self.switchcount += 1
print('Button press',self.switchcount)
def setUp(self):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(SWITCH_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
@unittest.skipIf(non_interactive, 'Non interactive mode')
def test_switchbounce(self):
self.switchcount = 0
print("\nSwitch bounce test. Press switch at least 10 times and count...")
GPIO.add_event_detect(SWITCH_PIN, GPIO.FALLING, callback=self.cb, bouncetime=200)
while self.switchcount < 10:
time.sleep(1)
GPIO.remove_event_detect(SWITCH_PIN)
@unittest.skipIf(non_interactive, 'Non interactive mode')
def test_event_detected(self):
self.switchcount = 0
print("\nGPIO.event_detected() switch bounce test. Press switch at least 10 times and count...")
GPIO.add_event_detect(SWITCH_PIN, GPIO.FALLING, bouncetime=200)
while self.switchcount < 10:
if GPIO.event_detected(SWITCH_PIN):
self.switchcount += 1
print('Button press',self.switchcount)
GPIO.remove_event_detect(SWITCH_PIN)
def tearDown(self):
GPIO.cleanup()
class TestEdgeDetection(unittest.TestCase):
def setUp(self):
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LOOP_IN, GPIO.IN)
GPIO.setup(LOOP_OUT, GPIO.OUT)
# Running a shell command with os.sytem has caused problems
# with sending SIGCHLD to the polling thread, causing it
# to exit. Test for that.
def testShellCmdWithWaitForEdge(self):
self.finished = False
def shellcmd():
for i in range(50):
os.system('sleep 0')
subprocess.call('sleep 0', shell=True)
self.finished = True
def makehigh():
GPIO.output(LOOP_OUT, GPIO.HIGH)
GPIO.output(LOOP_OUT, GPIO.LOW)
t1 = Timer(0.1, shellcmd)
t2 = Timer(0.5, makehigh)
t1.start()
t2.start()
starttime = time.time()
channel = GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, timeout=1000)
endtime = time.time()
self.assertGreater(endtime - starttime, 0.5)
self.assertLess(endtime - starttime, 0.6)
self.assertEqual(channel, LOOP_IN)
# make sure tasks in this test have finished before continuing
while not self.finished:
time.sleep(0.1)
def testShellCmdWithEventCallback(self):
self.run_cb = False
def cb(channel):
self.run_cb = True
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING, callback=cb)
time.sleep(0.01)
for i in range(50):
os.system('sleep 0')
subprocess.call('sleep 0', shell=True)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
GPIO.remove_event_detect(LOOP_IN)
self.assertEqual(self.run_cb, True)
def testWaitForEdgeInLoop(self):
def makelow():
GPIO.output(LOOP_OUT, GPIO.LOW)
count = 0
timestart = time.time()
GPIO.output(LOOP_OUT, GPIO.HIGH)
while True:
t = Timer(0.1, makelow)
t.start()
starttime = time.time()
channel = GPIO.wait_for_edge(LOOP_IN, GPIO.FALLING, timeout=200)
endtime = time.time()
self.assertLess(endtime-starttime, 0.12)
self.assertEqual(channel, LOOP_IN)
GPIO.output(LOOP_OUT, GPIO.HIGH)
count += 1
if time.time() - timestart > 5 or count > 150:
break
def testWaitForEdgeWithCallback(self):
def cb():
raise Exception("Callback should not be called")
def makehigh():
GPIO.output(LOOP_OUT, GPIO.HIGH)
GPIO.output(LOOP_OUT, GPIO.LOW)
t = Timer(0.1, makehigh)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING)
t.start()
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING)
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_callback(LOOP_IN, callback=cb)
with self.assertRaises(RuntimeError): # conflicting edge exception
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING)
GPIO.remove_event_detect(LOOP_IN)
def testWaitForEventSwitchbounce(self):
self.finished = False
def bounce():
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.2)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.LOW)
self.finished = True
GPIO.output(LOOP_OUT, GPIO.LOW)
t1 = Timer(0.1, bounce)
t1.start()
starttime = time.time()
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, bouncetime=100)
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, bouncetime=100)
finishtime = time.time()
self.assertGreater(finishtime-starttime, 0.2)
while not self.finished:
time.sleep(0.1)
def testInvalidBouncetime(self):
with self.assertRaises(ValueError):
GPIO.add_event_detect(LOOP_IN, GPIO.RISING, bouncetime=-1)
with self.assertRaises(ValueError):
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, bouncetime=-1)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING, bouncetime=123)
with self.assertRaises(RuntimeError):
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, bouncetime=321)
GPIO.remove_event_detect(LOOP_IN)
def testAlreadyAdded(self):
GPIO.add_event_detect(LOOP_IN, GPIO.RISING)
with self.assertRaises(RuntimeError):
GPIO.add_event_detect(LOOP_IN, GPIO.RISING)
GPIO.remove_event_detect(LOOP_IN)
def testHighLowEvent(self):
with self.assertRaises(ValueError):
GPIO.add_event_detect(LOOP_IN, GPIO.LOW)
with self.assertRaises(ValueError):
GPIO.add_event_detect(LOOP_IN, GPIO.HIGH)
def testFallingEventDetected(self):
GPIO.output(LOOP_OUT, GPIO.HIGH)
GPIO.add_event_detect(LOOP_IN, GPIO.FALLING)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), False)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), True)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), False)
GPIO.remove_event_detect(LOOP_IN)
def testRisingEventDetected(self):
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), False)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), True)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), False)
GPIO.remove_event_detect(LOOP_IN)
def testBothEventDetected(self):
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_detect(LOOP_IN, GPIO.BOTH)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), False)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), True)
self.assertEqual(GPIO.event_detected(LOOP_IN), False)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.01)
self.assertEqual(GPIO.event_detected(LOOP_IN), True)
GPIO.remove_event_detect(LOOP_IN)
def testWaitForRising(self):
def makehigh():
GPIO.output(LOOP_OUT, GPIO.HIGH)
GPIO.output(LOOP_OUT, GPIO.LOW)
t = Timer(0.1, makehigh)
t.start()
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING)
def testWaitForFalling(self):
def makelow():
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.output(LOOP_OUT, GPIO.HIGH)
t = Timer(0.1, makelow)
t.start()
GPIO.wait_for_edge(LOOP_IN, GPIO.FALLING)
def testExceptionInCallback(self):
self.run_cb = False
def cb(channel):
with self.assertRaises(ZeroDivisionError):
self.run_cb = True
a = 1/0
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING, callback=cb)
time.sleep(0.01)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.01)
self.assertEqual(self.run_cb, True)
GPIO.remove_event_detect(LOOP_IN)
def testAddEventCallback(self):
def cb(channel):
self.callback_count += 1
# falling test
self.callback_count = 0
GPIO.output(LOOP_OUT, GPIO.HIGH)
GPIO.add_event_detect(LOOP_IN, GPIO.FALLING)
GPIO.add_event_callback(LOOP_IN, cb)
time.sleep(0.01)
for i in range(2048):
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.001)
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.001)
GPIO.remove_event_detect(LOOP_IN)
self.assertEqual(self.callback_count, 2048)
# rising test
self.callback_count = 0
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING, callback=cb)
time.sleep(0.01)
for i in range(2048):
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.001)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.001)
GPIO.remove_event_detect(LOOP_IN)
self.assertEqual(self.callback_count, 2048)
# both test
self.callback_count = 0
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.add_event_detect(LOOP_IN, GPIO.BOTH, callback=cb)
time.sleep(0.01)
for i in range(2048):
GPIO.output(LOOP_OUT, GPIO.HIGH)
time.sleep(0.001)
GPIO.output(LOOP_OUT, GPIO.LOW)
time.sleep(0.001)
GPIO.remove_event_detect(LOOP_IN)
self.assertEqual(self.callback_count, 4096)
def testEventOnOutput(self):
with self.assertRaises(RuntimeError):
GPIO.add_event_detect(LOOP_OUT, GPIO.FALLING)
def testAlternateWaitForEdge(self):
def makehigh():
GPIO.output(LOOP_OUT, GPIO.HIGH)
def makelow():
GPIO.output(LOOP_OUT, GPIO.LOW)
GPIO.output(LOOP_OUT, GPIO.LOW)
t = Timer(0.1, makehigh)
t2 = Timer(0.15, makelow)
t.start()
t2.start()
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING)
GPIO.wait_for_edge(LOOP_IN, GPIO.FALLING)
def testWaitForEdgeTimeout(self):
def makehigh():
GPIO.output(LOOP_OUT, GPIO.HIGH)
def makelow():
GPIO.output(LOOP_OUT, GPIO.LOW)
with self.assertRaises(TypeError):
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, timeout="beer")
with self.assertRaises(ValueError):
GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, timeout=-1234)
makelow()
chan = GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, timeout=200)
self.assertEqual(chan, None)
t = Timer(0.1, makehigh)
t.start()
chan = GPIO.wait_for_edge(LOOP_IN, GPIO.RISING, timeout=200)
self.assertEqual(chan, LOOP_IN)
def tearDown(self):
GPIO.cleanup()
class TestCleanup(unittest.TestCase):
def setUp(self):
GPIO.setmode(GPIO.BOARD)
def test_cleanall(self):
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
GPIO.cleanup()
GPIO.setmode(GPIO.BOARD)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
def test_cleanone(self):
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.setup(SWITCH_PIN, GPIO.IN)
GPIO.setup(LOOP_IN, GPIO.IN)
GPIO.add_event_detect(SWITCH_PIN, GPIO.FALLING)
GPIO.add_event_detect(LOOP_IN, GPIO.RISING)
time.sleep(0.2) # wait for udev to set permissions
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(SWITCH_PIN), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LOOP_IN), GPIO.IN)
self.assertTrue(os.path.exists('/sys/class/gpio/gpio%s'%SWITCH_PIN_BCM))
self.assertTrue(os.path.exists('/sys/class/gpio/gpio%s'%LOOP_IN_BCM))
GPIO.cleanup(SWITCH_PIN)
time.sleep(0.2) # wait for udev to set permissions
self.assertFalse(os.path.exists('/sys/class/gpio/gpio%s'%SWITCH_PIN_BCM))
self.assertTrue(os.path.exists('/sys/class/gpio/gpio%s'%LOOP_IN_BCM))
GPIO.cleanup(LOOP_IN)
time.sleep(0.2) # wait for udev to set permissions
self.assertFalse(os.path.exists('/sys/class/gpio/gpio%s'%SWITCH_PIN_BCM))
self.assertFalse(os.path.exists('/sys/class/gpio/gpio%s'%LOOP_IN_BCM))
GPIO.cleanup(LOOP_OUT)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
GPIO.cleanup(LED_PIN)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
def test_cleantuple(self):
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
GPIO.cleanup((LOOP_OUT,))
GPIO.setmode(GPIO.BOARD)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
GPIO.cleanup((LED_PIN,))
GPIO.setmode(GPIO.BOARD)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.cleanup((LOOP_OUT,LED_PIN))
GPIO.setmode(GPIO.BOARD)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
def test_cleanlist(self):
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
GPIO.cleanup([LOOP_OUT])
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT)
GPIO.cleanup([LED_PIN])
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
GPIO.setup(LOOP_OUT, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.cleanup([LOOP_OUT,LED_PIN])
self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN)
self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)
if __name__ == '__main__':
unittest.main()