| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- """The USB camera list the camera settings pick a device from.
- Only devices a USB camera can stream from are listed (streaming accepts
- /dev/video0 to /dev/video99), and the listing, which runs v4l2-ctl for each
- device, does not hold up the server while it runs.
- """
- import threading
- from pathlib import Path
- from unittest.mock import patch
- import pytest
- from httpx import AsyncClient
- from backend.app.services.external_camera import list_usb_cameras
- def _devices(tmp_path: Path, *names: str) -> Path:
- for name in names:
- (tmp_path / name).touch()
- return tmp_path
- def test_only_device_paths_streaming_accepts_are_listed(tmp_path):
- dev = _devices(tmp_path, "video0", "video12", "video100", "video05", "video-meta", "videoX")
- with patch("backend.app.services.external_camera.shutil.which", return_value=None):
- cameras = list_usb_cameras(dev_dir=dev)
- assert [camera["device"] for camera in cameras] == ["/dev/video0", "/dev/video12"]
- def test_paths_are_listed_as_dev_paths(tmp_path):
- """The entry names the device as the camera settings store it."""
- dev = _devices(tmp_path, "video2")
- with patch("backend.app.services.external_camera.shutil.which", return_value=None):
- cameras = list_usb_cameras(dev_dir=dev)
- assert cameras == [{"device": "/dev/video2", "name": "video2", "capabilities": []}]
- @pytest.mark.asyncio
- async def test_the_listing_runs_off_the_event_loop(async_client: AsyncClient):
- seen: list[threading.Thread] = []
- def listing():
- seen.append(threading.current_thread())
- return [{"device": "/dev/video0", "name": "Webcam", "capabilities": ["capture"]}]
- with patch("backend.app.services.external_camera.list_usb_cameras", side_effect=listing):
- response = await async_client.get("/api/v1/printers/usb-cameras")
- assert response.status_code == 200
- assert response.json()["cameras"][0]["device"] == "/dev/video0"
- assert seen and seen[0] is not threading.main_thread()
|