Files
lms-nav2-camera-test/tests/test_devices.py
T

68 lines
3.5 KiB
Python

import importlib.util
from pathlib import Path
import stat
import struct
from types import SimpleNamespace
import unittest
from unittest.mock import patch
path = Path(__file__).parents[1] / 'src/camera_test_pkg/camera_test_pkg/devices.py'
spec = importlib.util.spec_from_file_location('camera_devices', path)
devices = importlib.util.module_from_spec(spec)
spec.loader.exec_module(devices)
def capability(caps, device_caps=0):
data = bytearray(104)
struct.pack_into('II', data, 84, caps, device_caps)
return data
class DeviceTests(unittest.TestCase):
def test_capture_only_not_metadata_or_codec(self):
for caps in [0x04000001, 0x04001000, 0x01000001]:
self.assertTrue(devices.capture_capabilities(capability(caps)))
for caps in [0x04800000, 0x04008001, 0x04004001, 0x04000002, 1]:
self.assertFalse(devices.capture_capabilities(capability(caps)))
self.assertFalse(devices.capture_capabilities(capability(0x84000001, 0x04800000)))
def test_discovery_filters_nodes_and_sorts_numbers(self):
def query(fd, request, data, mutate):
self.assertEqual(request, 0x80685600)
data[:] = capability(0x04800000 if fd == 1 else 0x04000001)
with patch.object(devices.glob, 'glob', return_value=['/dev/video10', '/dev/video1', '/dev/video0', '/dev/videobad']), \
patch.object(devices.os, 'lstat', return_value=SimpleNamespace(st_mode=stat.S_IFCHR)), \
patch.object(devices.os, 'open', side_effect=lambda path, flags: int(path[10:])), \
patch.object(devices.os, 'close') as close, patch.object(devices.fcntl, 'ioctl', side_effect=query):
self.assertEqual(devices.discover_devices(), ['/dev/video0', '/dev/video10'])
self.assertEqual(close.call_count, 3)
def test_no_devices_and_invalid_roots_fail_without_scanning(self):
with patch.object(devices.glob, 'glob', return_value=[]):
with self.assertRaisesRegex(RuntimeError, 'No usable'):
devices.discover_devices()
with self.assertRaises(ValueError):
devices.discover_devices('/etc')
def test_launch_creates_independent_topic_and_raw_streams(self):
import ast
source = ast.parse((path.parents[1] / 'launch/camera.launch.py').read_text())
nodes = [node for node in source.body if not isinstance(node, (ast.Import, ast.ImportFrom))]
class Configuration:
def __init__(self, name): self.name = name
def perform(self, context): return context[self.name]
scope = {'LaunchConfiguration': Configuration, 'ParameterValue': lambda value, value_type: value,
'Node': lambda **kwargs: kwargs, 'discover_devices': lambda: ['/dev/video0', '/dev/video2']}
exec(compile(ast.Module(body=nodes, type_ignores=[]), 'camera-launch', 'exec'), scope)
result = scope['camera_nodes']({'video_device': '/dev'})
self.assertEqual([node['name'] for node in result], ['camera_test_video0', 'camera_test_video2'])
self.assertEqual(result[1]['parameters'][0]['jpeg_topic'], '/camera_test/cameras/video2/image_jpeg')
self.assertEqual(result[1]['parameters'][0]['raw_topic'], '/camera_test/cameras/video2/image_raw')
single = scope['camera_nodes']({'video_device': '/dev/video0'})
self.assertEqual(single[0]['name'], 'camera_test')
self.assertEqual(single[0]['parameters'][0]['jpeg_topic'].name, 'jpeg_topic')
if __name__ == '__main__':
unittest.main()