mirror of
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
synced 2026-10-24 00:48:53 +03:00
Since their inclusion in Python 3.6, f-strings have become the preferred way to format strings with variable values as they are generally more readable as the value substitution is in place and doesn't have to be parsed from the list or arguments to `.format()`. Where it does not impact readability (when the line is <120 characters), swap usage of `.format()` to an f-string. For lines that are not converted, inform the linter to ignore attempts to upgrade those instances to f-strings [0] [0]: https://docs.astral.sh/ruff/rules/f-string/ Signed-off-by: Vincent Fazio <vfazio@xes-inc.com> Link: https://lore.kernel.org/r/20241114145116.2123714-23-vfazio@xes-inc.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
236 lines
7.1 KiB
Python
236 lines
7.1 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# SPDX-FileCopyrightText: 2022 Bartosz Golaszewski <brgl@bgdev.pl>
|
|
|
|
import errno
|
|
import os
|
|
from unittest import TestCase
|
|
|
|
import gpiod
|
|
|
|
from . import gpiosim
|
|
from .helpers import LinkGuard
|
|
|
|
|
|
class ChipConstructor(TestCase):
|
|
def test_open_existing_chip(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
with gpiod.Chip(sim.dev_path):
|
|
pass
|
|
|
|
def test_open_existing_chip_with_keyword(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
with gpiod.Chip(path=sim.dev_path):
|
|
pass
|
|
|
|
def test_open_chip_by_link(self) -> None:
|
|
link = f"/tmp/gpiod-py-test-link.{os.getpid()}"
|
|
sim = gpiosim.Chip()
|
|
|
|
with LinkGuard(sim.dev_path, link):
|
|
with gpiod.Chip(link):
|
|
pass
|
|
|
|
def test_open_nonexistent_chip(self) -> None:
|
|
with self.assertRaises(OSError) as ex:
|
|
gpiod.Chip("/dev/nonexistent")
|
|
|
|
self.assertEqual(ex.exception.errno, errno.ENOENT)
|
|
|
|
def test_open_not_a_character_device(self) -> None:
|
|
with self.assertRaises(OSError) as ex:
|
|
gpiod.Chip("/tmp")
|
|
|
|
self.assertEqual(ex.exception.errno, errno.ENOTTY)
|
|
|
|
def test_open_not_a_gpio_device(self) -> None:
|
|
with self.assertRaises(OSError) as ex:
|
|
gpiod.Chip("/dev/null")
|
|
|
|
self.assertEqual(ex.exception.errno, errno.ENODEV)
|
|
|
|
def test_missing_path(self) -> None:
|
|
with self.assertRaises(TypeError):
|
|
gpiod.Chip() # type: ignore[call-arg]
|
|
|
|
def test_invalid_type_for_path(self) -> None:
|
|
with self.assertRaises(TypeError):
|
|
gpiod.Chip(4) # type: ignore[arg-type]
|
|
|
|
|
|
class ChipBooleanConversion(TestCase):
|
|
def test_chip_bool(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
chip = gpiod.Chip(sim.dev_path)
|
|
self.assertTrue(chip)
|
|
chip.close()
|
|
self.assertFalse(chip)
|
|
|
|
|
|
class ChipProperties(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip()
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
self.sim = None # type: ignore[assignment]
|
|
|
|
def test_get_chip_path(self) -> None:
|
|
self.assertEqual(self.sim.dev_path, self.chip.path)
|
|
|
|
def test_get_fd(self) -> None:
|
|
self.assertGreaterEqual(self.chip.fd, 0)
|
|
|
|
def test_properties_are_immutable(self) -> None:
|
|
with self.assertRaises(AttributeError):
|
|
self.chip.path = "foobar" # type: ignore[misc]
|
|
|
|
with self.assertRaises(AttributeError):
|
|
self.chip.fd = 4 # type: ignore[misc]
|
|
|
|
|
|
class ChipDevPathFromLink(TestCase):
|
|
def test_dev_path_open_by_link(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
link = f"/tmp/gpiod-py-test-link.{os.getpid()}"
|
|
|
|
with LinkGuard(sim.dev_path, link):
|
|
with gpiod.Chip(link) as chip:
|
|
self.assertEqual(chip.path, link)
|
|
|
|
|
|
class ChipMapLine(TestCase):
|
|
def test_lookup_by_name_good(self) -> None:
|
|
sim = gpiosim.Chip(
|
|
num_lines=8, line_names={1: "foo", 2: "bar", 4: "baz", 5: "xyz"}
|
|
)
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
self.assertEqual(chip.line_offset_from_id("baz"), 4)
|
|
|
|
def test_lookup_by_name_good_keyword_argument(self) -> None:
|
|
sim = gpiosim.Chip(
|
|
num_lines=8, line_names={1: "foo", 2: "bar", 4: "baz", 5: "xyz"}
|
|
)
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
self.assertEqual(chip.line_offset_from_id(id="baz"), 4)
|
|
|
|
def test_lookup_bad_name(self) -> None:
|
|
sim = gpiosim.Chip(
|
|
num_lines=8, line_names={1: "foo", 2: "bar", 4: "baz", 5: "xyz"}
|
|
)
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
with self.assertRaises(FileNotFoundError):
|
|
chip.line_offset_from_id("nonexistent")
|
|
|
|
def test_lookup_bad_offset(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
with self.assertRaises(ValueError):
|
|
chip.line_offset_from_id(4)
|
|
|
|
def test_lookup_bad_offset_as_string(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
with self.assertRaises(ValueError):
|
|
chip.line_offset_from_id("4")
|
|
|
|
def test_duplicate_names(self) -> None:
|
|
sim = gpiosim.Chip(
|
|
num_lines=8, line_names={1: "foo", 2: "bar", 4: "baz", 5: "bar"}
|
|
)
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
self.assertEqual(chip.line_offset_from_id("bar"), 2)
|
|
|
|
def test_integer_offsets(self) -> None:
|
|
sim = gpiosim.Chip(num_lines=8, line_names={1: "foo", 2: "bar", 6: "baz"})
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
self.assertEqual(chip.line_offset_from_id(4), 4)
|
|
self.assertEqual(chip.line_offset_from_id(1), 1)
|
|
|
|
def test_offsets_as_string(self) -> None:
|
|
sim = gpiosim.Chip(num_lines=8, line_names={1: "foo", 2: "bar", 7: "6"})
|
|
|
|
with gpiod.Chip(sim.dev_path) as chip:
|
|
self.assertEqual(chip.line_offset_from_id("2"), 2)
|
|
self.assertEqual(chip.line_offset_from_id("6"), 7)
|
|
|
|
|
|
class ClosedChipCannotBeUsed(TestCase):
|
|
def test_close_chip_and_try_to_use_it(self) -> None:
|
|
sim = gpiosim.Chip(label="foobar")
|
|
|
|
chip = gpiod.Chip(sim.dev_path)
|
|
chip.close()
|
|
|
|
with self.assertRaises(gpiod.ChipClosedError):
|
|
_ = chip.path
|
|
|
|
def test_close_chip_and_try_controlled_execution(self) -> None:
|
|
sim = gpiosim.Chip()
|
|
|
|
chip = gpiod.Chip(sim.dev_path)
|
|
chip.close()
|
|
|
|
with self.assertRaises(gpiod.ChipClosedError):
|
|
with chip:
|
|
_ = chip.fd
|
|
|
|
def test_close_chip_twice(self) -> None:
|
|
sim = gpiosim.Chip(label="foobar")
|
|
chip = gpiod.Chip(sim.dev_path)
|
|
chip.close()
|
|
|
|
with self.assertRaises(gpiod.ChipClosedError):
|
|
chip.close()
|
|
|
|
|
|
class StringRepresentation(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=4, label="foobar")
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.chip.close()
|
|
self.sim = None # type: ignore[assignment]
|
|
|
|
def test_repr(self) -> None:
|
|
self.assertEqual(repr(self.chip), f'gpiod.Chip("{self.sim.dev_path}")')
|
|
|
|
cmp = eval(repr(self.chip))
|
|
self.assertEqual(self.chip.path, cmp.path)
|
|
|
|
def test_str(self) -> None:
|
|
info = self.chip.get_info()
|
|
self.assertEqual(
|
|
str(self.chip),
|
|
'<Chip path="{}" fd={} info=<ChipInfo name="{}" label="foobar" num_lines=4>>'.format( # noqa: UP032
|
|
self.sim.dev_path, self.chip.fd, info.name
|
|
),
|
|
)
|
|
|
|
|
|
class StringRepresentationClosed(TestCase):
|
|
def setUp(self) -> None:
|
|
self.sim = gpiosim.Chip(num_lines=4, label="foobar")
|
|
self.chip = gpiod.Chip(self.sim.dev_path)
|
|
|
|
def tearDown(self) -> None:
|
|
self.sim = None # type: ignore[assignment]
|
|
|
|
def test_repr_closed(self) -> None:
|
|
self.chip.close()
|
|
self.assertEqual(repr(self.chip), "<Chip CLOSED>")
|
|
|
|
def test_str_closed(self) -> None:
|
|
self.chip.close()
|
|
self.assertEqual(str(self.chip), "<Chip CLOSED>")
|