blob: c8ee85b23bf53190b899ceec1b6e6b569107c8d0 [file] [log] [blame]
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
import errno
import gpiod
import gpiomockup
import os
import select
import time
import threading
import unittest
from packaging import version
mockup = None
default_consumer = 'gpiod-py-test'
class MockupTestCase(unittest.TestCase):
chip_sizes = None
flags = 0
def setUp(self):
mockup.probe(self.chip_sizes, flags=self.flags)
def tearDown(self):
mockup.remove()
class EventThread(threading.Thread):
def __init__(self, chip_idx, line_offset, period_ms):
threading.Thread.__init__(self)
self.chip_idx = chip_idx
self.line_offset = line_offset
self.period_ms = period_ms
self.lock = threading.Lock()
self.cond = threading.Condition(self.lock)
self.should_stop = False
def run(self):
i = 0;
while True:
with self.lock:
if self.should_stop:
break;
if not self.cond.wait(float(self.period_ms) / 1000):
mockup.chip_set_pull(self.chip_idx,
self.line_offset, i % 2)
i += 1
def stop(self):
with self.lock:
self.should_stop = True
self.cond.notify_all()
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.stop()
self.join()
def check_kernel(major, minor, release):
current = os.uname().release.split('-')[0]
required = '{}.{}.{}'.format(major, minor, release)
if version.parse(current) < version.parse(required):
raise NotImplementedError(
'linux kernel version must be at least {} - got {}'.format(required, current))
#
# Chip test cases
#
class IsGpioDevice(MockupTestCase):
chip_sizes = ( 8, )
def test_is_gpiochip_device_good(self):
self.assertTrue(gpiod.is_gpiochip_device(mockup.chip_path(0)))
def test_is_gpiochip_device_bad(self):
self.assertFalse(gpiod.is_gpiochip_device('/dev/null'))
def test_is_gpiochip_device_nonexistent(self):
self.assertFalse(gpiod.is_gpiochip_device('/dev/nonexistent_device'))
class ChipOpen(MockupTestCase):
chip_sizes = ( 8, 8, 8 )
def test_open_good(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
self.assertEqual(chip.name(), mockup.chip_name(1))
def test_nonexistent_chip(self):
with self.assertRaises(FileNotFoundError):
chip = gpiod.Chip('nonexistent-chip')
def test_open_chip_no_arguments(self):
with self.assertRaises(TypeError):
chip = gpiod.Chip()
class ChipClose(MockupTestCase):
chip_sizes = ( 8, )
def test_use_chip_after_close(self):
chip = gpiod.Chip(mockup.chip_path(0))
self.assertEqual(chip.name(), mockup.chip_name(0))
chip.close()
with self.assertRaises(ValueError):
chip.name()
class ChipInfo(MockupTestCase):
chip_sizes = ( 16, )
def test_chip_get_info(self):
chip = gpiod.Chip(mockup.chip_path(0))
self.assertEqual(chip.name(), mockup.chip_name(0))
self.assertEqual(chip.label(), 'gpio-mockup-A')
self.assertEqual(chip.num_lines(), 16)
class ChipGetLines(MockupTestCase):
chip_sizes = ( 8, 8, 4 )
flags = gpiomockup.Mockup.FLAG_NAMED_LINES
def test_get_single_line_by_offset(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
line = chip.get_line(4)
self.assertEqual(line.name(), 'gpio-mockup-B-4')
def test_find_single_line_by_name(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
offset = chip.find_line('gpio-mockup-B-4')
self.assertIsNotNone(offset)
self.assertEqual(offset, 4)
def test_get_single_line_invalid_offset(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
with self.assertRaises(OSError) as err_ctx:
line = chip.get_line(11)
self.assertEqual(err_ctx.exception.errno, errno.EINVAL)
def test_find_single_line_nonexistent(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
offset = chip.find_line('nonexistent-line')
self.assertIsNone(offset)
def test_get_multiple_lines_by_offsets_in_tuple(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
lines = chip.get_lines(( 1, 3, 6, 7 )).to_list()
self.assertEqual(len(lines), 4)
self.assertEqual(lines[0].name(), 'gpio-mockup-B-1')
self.assertEqual(lines[1].name(), 'gpio-mockup-B-3')
self.assertEqual(lines[2].name(), 'gpio-mockup-B-6')
self.assertEqual(lines[3].name(), 'gpio-mockup-B-7')
def test_get_multiple_lines_by_offsets_in_list(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
lines = chip.get_lines([ 1, 3, 6, 7 ]).to_list()
self.assertEqual(len(lines), 4)
self.assertEqual(lines[0].name(), 'gpio-mockup-B-1')
self.assertEqual(lines[1].name(), 'gpio-mockup-B-3')
self.assertEqual(lines[2].name(), 'gpio-mockup-B-6')
self.assertEqual(lines[3].name(), 'gpio-mockup-B-7')
def test_get_multiple_lines_invalid_offset(self):
with gpiod.Chip(mockup.chip_path(1)) as chip:
with self.assertRaises(OSError) as err_ctx:
line = chip.get_lines(( 1, 3, 11, 7 ))
self.assertEqual(err_ctx.exception.errno, errno.EINVAL)
def test_get_all_lines(self):
with gpiod.Chip(mockup.chip_path(2)) as chip:
lines = chip.get_all_lines().to_list()
self.assertEqual(len(lines), 4)
self.assertEqual(lines[0].name(), 'gpio-mockup-C-0')
self.assertEqual(lines[1].name(), 'gpio-mockup-C-1')
self.assertEqual(lines[2].name(), 'gpio-mockup-C-2')
self.assertEqual(lines[3].name(), 'gpio-mockup-C-3')
#
# Line test cases
#
class LineInfo(MockupTestCase):
chip_sizes = ( 8, )
flags = gpiomockup.Mockup.FLAG_NAMED_LINES
def test_unexported_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT)
self.assertFalse(line.is_active_low())
self.assertEqual(line.consumer(), None)
self.assertFalse(line.is_used())
self.assertFalse(line.is_requested())
def test_exported_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertTrue(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
def test_exported_line_with_flags(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
flags = (gpiod.LINE_REQ_FLAG_ACTIVE_LOW |
gpiod.LINE_REQ_FLAG_OPEN_DRAIN)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=flags)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertTrue(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
self.assertEqual(line.drive(), gpiod.Line.DRIVE_OPEN_DRAIN)
self.assertEqual(line.bias(), gpiod.Line.BIAS_UNKNOWN)
def test_exported_open_drain_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
flags = gpiod.LINE_REQ_FLAG_OPEN_DRAIN
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=flags)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertFalse(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
self.assertEqual(line.drive(), gpiod.Line.DRIVE_OPEN_DRAIN)
self.assertEqual(line.bias(), gpiod.Line.BIAS_UNKNOWN)
def test_exported_open_source_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
flags = gpiod.LINE_REQ_FLAG_OPEN_SOURCE
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=flags)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertFalse(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
self.assertEqual(line.drive(), gpiod.Line.DRIVE_OPEN_SOURCE)
self.assertEqual(line.bias(), gpiod.Line.BIAS_UNKNOWN)
def test_exported_bias_disable_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
flags = gpiod.LINE_REQ_FLAG_BIAS_DISABLED
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=flags)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertFalse(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
self.assertEqual(line.drive(), gpiod.Line.DRIVE_PUSH_PULL)
self.assertEqual(line.bias(), gpiod.Line.BIAS_DISABLED)
def test_exported_bias_pull_down_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
flags = gpiod.LINE_REQ_FLAG_BIAS_PULL_DOWN
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=flags)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertFalse(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
self.assertEqual(line.drive(), gpiod.Line.DRIVE_PUSH_PULL)
self.assertEqual(line.bias(), gpiod.Line.BIAS_PULL_DOWN)
def test_exported_bias_pull_up_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
flags = gpiod.LINE_REQ_FLAG_BIAS_PULL_UP
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=flags)
self.assertEqual(line.offset(), 4)
self.assertEqual(line.name(), 'gpio-mockup-A-4')
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertFalse(line.is_active_low())
self.assertEqual(line.consumer(), default_consumer)
self.assertTrue(line.is_used())
self.assertTrue(line.is_requested())
self.assertEqual(line.drive(), gpiod.Line.DRIVE_PUSH_PULL)
self.assertEqual(line.bias(), gpiod.Line.BIAS_PULL_UP)
def test_update_line_info(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.update()
class LineValues(MockupTestCase):
chip_sizes = ( 8, )
def test_get_value_single_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
self.assertEqual(line.get_value(), 0)
mockup.chip_set_pull(0, 3, 1)
self.assertEqual(line.get_value(), 1)
def test_set_value_single_line(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT)
line.set_value(1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
line.set_value(0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
def test_set_value_with_default_value_argument(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
default_val=1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
def test_get_value_multiple_lines(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 3, 4, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
self.assertEqual(lines.get_values(), [ 0, 0, 0, 0 ])
mockup.chip_set_pull(0, 0, 1)
mockup.chip_set_pull(0, 4, 1)
mockup.chip_set_pull(0, 6, 1)
self.assertEqual(lines.get_values(), [ 1, 0, 1, 1 ])
def test_set_value_multiple_lines(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 3, 4, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT)
lines.set_values(( 1, 0, 1, 1 ))
self.assertEqual(mockup.chip_get_value(0, 0), 1)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 1)
lines.set_values(( 0, 0, 1, 0 ))
self.assertEqual(mockup.chip_get_value(0, 0), 0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 0)
def test_set_multiple_values_with_default_vals_argument(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 3, 4, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
default_vals=( 1, 0, 1, 1 ))
self.assertEqual(mockup.chip_get_value(0, 0), 1)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 1)
def test_get_value_active_low(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN,
flags=gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
self.assertEqual(line.get_value(), 1)
mockup.chip_set_pull(0, 3, 1)
self.assertEqual(line.get_value(), 0)
def test_set_value_active_low(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
flags=gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
line.set_value(1)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
line.set_value(0)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
class LineConfig(MockupTestCase):
chip_sizes = ( 8, )
def test_set_config_direction(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT)
line.set_config(gpiod.LINE_REQ_DIR_IN, 0, 0)
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT)
line.set_config(gpiod.LINE_REQ_DIR_OUT,0,0)
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
def test_set_config_flags(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT)
line.set_config(gpiod.LINE_REQ_DIR_OUT,
gpiod.LINE_REQ_FLAG_ACTIVE_LOW, 0)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
line.set_config(gpiod.LINE_REQ_DIR_OUT, 0, 0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
def test_set_config_output_value(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
line.set_config(gpiod.LINE_REQ_DIR_OUT,0,1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
line.set_config(gpiod.LINE_REQ_DIR_OUT,0,0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
def test_set_config_output_no_value(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
default_val=1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
line.set_config(gpiod.LINE_REQ_DIR_OUT,0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
def test_set_config_bulk_output_no_values(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 3, 4, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
default_vals=(1,1,1,1))
self.assertEqual(mockup.chip_get_value(0, 0), 1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 1)
lines.set_config(gpiod.LINE_REQ_DIR_OUT,0)
self.assertEqual(mockup.chip_get_value(0, 0), 0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 0)
self.assertEqual(mockup.chip_get_value(0, 6), 0)
class LineFlags(MockupTestCase):
chip_sizes = ( 8, )
def test_set_flags(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
default_val=1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
line.set_flags(gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
line.set_flags(0)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
def test_set_flags_bulk(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 3, 4, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT,
default_vals=(1,1,1,1))
self.assertEqual(mockup.chip_get_value(0, 0), 1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 1)
lines.set_flags(gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
self.assertEqual(mockup.chip_get_value(0, 0), 0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 0)
self.assertEqual(mockup.chip_get_value(0, 6), 0)
lines.set_flags(0)
self.assertEqual(mockup.chip_get_value(0, 0), 1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 1)
class LineDirection(MockupTestCase):
chip_sizes = ( 8, )
def test_set_direction(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT)
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
line.set_direction_input()
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT)
line.set_direction_output(0)
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
line.set_direction_output(1)
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
line.set_direction_output()
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
def test_set_direction_bulk(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 3, 4, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_OUT)
self.assertEqual(lines.to_list()[0].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[1].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[2].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[3].direction(),
gpiod.Line.DIRECTION_OUTPUT)
lines.set_direction_input()
self.assertEqual(lines.to_list()[0].direction(),
gpiod.Line.DIRECTION_INPUT)
self.assertEqual(lines.to_list()[1].direction(),
gpiod.Line.DIRECTION_INPUT)
self.assertEqual(lines.to_list()[2].direction(),
gpiod.Line.DIRECTION_INPUT)
self.assertEqual(lines.to_list()[3].direction(),
gpiod.Line.DIRECTION_INPUT)
lines.set_direction_output((0,0,1,0))
self.assertEqual(lines.to_list()[0].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[1].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[2].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[3].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(mockup.chip_get_value(0, 0), 0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 0)
lines.set_direction_output((1,1,1,0))
self.assertEqual(lines.to_list()[0].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[1].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[2].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[3].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(mockup.chip_get_value(0, 0), 1)
self.assertEqual(mockup.chip_get_value(0, 3), 1)
self.assertEqual(mockup.chip_get_value(0, 4), 1)
self.assertEqual(mockup.chip_get_value(0, 6), 0)
lines.set_direction_output()
self.assertEqual(lines.to_list()[0].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[1].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[2].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(lines.to_list()[3].direction(),
gpiod.Line.DIRECTION_OUTPUT)
self.assertEqual(mockup.chip_get_value(0, 0), 0)
self.assertEqual(mockup.chip_get_value(0, 3), 0)
self.assertEqual(mockup.chip_get_value(0, 4), 0)
self.assertEqual(mockup.chip_get_value(0, 6), 0)
class LineRequestBehavior(MockupTestCase):
chip_sizes = ( 8, )
def test_line_export_release(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
self.assertTrue(line.is_requested())
self.assertEqual(line.get_value(), 0)
line.release()
self.assertFalse(line.is_requested())
def test_line_request_twice_two_calls(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
with self.assertRaises(OSError) as err_ctx:
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
self.assertEqual(err_ctx.exception.errno, errno.EBUSY)
def test_line_request_twice_in_bulk(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 2, 3, 6, 6 ))
with self.assertRaises(OSError) as err_ctx:
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
self.assertEqual(err_ctx.exception.errno, errno.EBUSY)
def test_use_value_unrequested(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
with self.assertRaises(OSError) as err_ctx:
line.get_value()
self.assertEqual(err_ctx.exception.errno, errno.EPERM)
def test_request_with_no_kwds(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(2)
line.request(default_consumer)
self.assertTrue(line.is_requested())
self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT)
line.release()
self.assertFalse(line.is_requested())
#
# Iterator test cases
#
class LineIterator(MockupTestCase):
chip_sizes = ( 4, )
def test_iterate_over_lines(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
count = 0
for line in gpiod.LineIter(chip):
self.assertEqual(line.offset(), count)
count += 1
self.assertEqual(count, chip.num_lines())
class LineBulkIter(MockupTestCase):
chip_sizes = ( 4, )
def test_line_bulk_iterator(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_all_lines()
count = 0
for line in lines:
self.assertEqual(line.offset(), count)
count += 1
self.assertEqual(count, chip.num_lines())
#
# Event test cases
#
class EventSingleLine(MockupTestCase):
chip_sizes = ( 8, )
def test_single_line_rising_edge_event(self):
with EventThread(0, 4, 200):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_RISING_EDGE)
self.assertTrue(line.event_wait(sec=1))
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(event.source.offset(), 4)
def test_single_line_falling_edge_event(self):
with EventThread(0, 4, 200):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_FALLING_EDGE)
self.assertTrue(line.event_wait(sec=1))
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.FALLING_EDGE)
self.assertEqual(event.source.offset(), 4)
def test_single_line_both_edges_events(self):
with EventThread(0, 4, 200):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES)
self.assertTrue(line.event_wait(sec=1))
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(event.source.offset(), 4)
self.assertTrue(line.event_wait(sec=1))
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.FALLING_EDGE)
self.assertEqual(event.source.offset(), 4)
def test_single_line_both_edges_events_active_low(self):
with EventThread(0, 4, 200):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES,
flags=gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
self.assertTrue(line.event_wait(sec=1))
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.FALLING_EDGE)
self.assertEqual(event.source.offset(), 4)
self.assertTrue(line.event_wait(sec=1))
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(event.source.offset(), 4)
def test_single_line_read_multiple_events(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(4)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES)
mockup.chip_set_pull(0, 4, 1)
time.sleep(0.01)
mockup.chip_set_pull(0, 4, 0)
time.sleep(0.01)
mockup.chip_set_pull(0, 4, 1)
time.sleep(0.01)
self.assertTrue(line.event_wait(sec=1))
events = line.event_read_multiple()
self.assertEqual(len(events), 3)
self.assertEqual(events[0].type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(events[1].type, gpiod.LineEvent.FALLING_EDGE)
self.assertEqual(events[2].type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(events[0].source.offset(), 4)
self.assertEqual(events[1].source.offset(), 4)
self.assertEqual(events[2].source.offset(), 4)
class EventBulk(MockupTestCase):
chip_sizes = ( 8, )
def test_watch_multiple_lines_for_events(self):
with EventThread(0, 2, 200):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 1, 2, 3, 4 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES)
event_lines = lines.event_wait(sec=1)
self.assertEqual(len(event_lines), 1)
line = event_lines[0]
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(event.source.offset(), 2)
event_lines = lines.event_wait(sec=1)
self.assertEqual(len(event_lines), 1)
line = event_lines[0]
event = line.event_read()
self.assertEqual(event.type, gpiod.LineEvent.FALLING_EDGE)
self.assertEqual(event.source.offset(), 2)
class EventValues(MockupTestCase):
chip_sizes = ( 8, )
def test_request_for_events_get_value(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES)
self.assertEqual(line.get_value(), 0)
mockup.chip_set_pull(0, 3, 1)
self.assertEqual(line.get_value(), 1)
def test_request_for_events_get_value_active_low(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES,
flags=gpiod.LINE_REQ_FLAG_ACTIVE_LOW)
self.assertEqual(line.get_value(), 1)
mockup.chip_set_pull(0, 3, 1)
self.assertEqual(line.get_value(), 0)
class EventFileDescriptor(MockupTestCase):
chip_sizes = ( 8, )
def test_event_get_fd(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES)
fd = line.event_get_fd();
self.assertGreaterEqual(fd, 0)
def test_event_get_fd_not_requested(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
with self.assertRaises(OSError) as err_ctx:
fd = line.event_get_fd();
self.assertEqual(err_ctx.exception.errno, errno.EPERM)
def test_event_get_fd_requested_for_values(self):
with gpiod.Chip(mockup.chip_path(0)) as chip:
line = chip.get_line(3)
line.request(consumer=default_consumer,
type=gpiod.LINE_REQ_DIR_IN)
with self.assertRaises(OSError) as err_ctx:
fd = line.event_get_fd();
self.assertEqual(err_ctx.exception.errno, errno.EPERM)
def test_event_fd_polling(self):
with EventThread(0, 2, 200):
with gpiod.Chip(mockup.chip_path(0)) as chip:
lines = chip.get_lines(( 0, 1, 2, 3, 4, 5, 6 ))
lines.request(consumer=default_consumer,
type=gpiod.LINE_REQ_EV_BOTH_EDGES)
inputs = []
for line in lines:
inputs.append(line.event_get_fd())
readable, writable, exceptional = select.select(inputs, [],
inputs, 1.0)
self.assertEqual(len(readable), 1)
event = lines.to_list()[2].event_read()
self.assertEqual(event.type, gpiod.LineEvent.RISING_EDGE)
self.assertEqual(event.source.offset(), 2)
#
# Main
#
if __name__ == '__main__':
check_kernel(5, 10, 0)
mockup = gpiomockup.Mockup()
unittest.main()