Files
AareDAQ/tests/unit/gui/test_camera_thread.py
T
2026-05-22 18:05:46 +02:00

106 lines
3.4 KiB
Python

import pytest
import json
import numpy as np
import cv2
import zmq
from unittest.mock import MagicMock, patch
from PySide6.QtGui import QPixmap
from aare.gui.threads.camera_thread import SampleCameraThread
from aare.common.models import DAQStatusModel
@pytest.fixture
def mock_zmq():
with patch('zmq.Context') as mock_ctx_class:
mock_ctx = mock_ctx_class.return_value
mock_socket = mock_ctx.socket.return_value
yield mock_socket
@pytest.fixture
def camera_thread(mock_zmq, qtbot):
thread = SampleCameraThread("tcp://127.0.0.1:5555")
return thread
def test_init(camera_thread):
assert camera_thread.running is True
assert camera_thread._SampleCameraThread__camera_available is False
def test_update_daq_status(camera_thread):
s = MagicMock()
s.geom.beam_location_pxl.x = 100
s.geom.beam_location_pxl.y = 200
camera_thread.update_daq_status(s)
assert camera_thread._SampleCameraThread__beam_x == 100
assert camera_thread._SampleCameraThread__beam_y == 200
def test_enable_focus_measurement(camera_thread):
camera_thread.enable_focus_measurement(True)
assert camera_thread._SampleCameraThread__measure_focus is True
camera_thread.enable_focus_measurement(False)
assert camera_thread._SampleCameraThread__measure_focus is False
def test_run_success(camera_thread, mock_zmq, qtbot):
# Create a small valid JPEG
img = np.zeros((10, 10, 3), dtype=np.uint8)
_, jpeg_bytes = cv2.imencode('.jpg', img)
header = json.dumps({"encoding": "jpeg"}).encode("utf-8")
def side_effect():
camera_thread.running = False
return [header, jpeg_bytes.tobytes()]
mock_zmq.recv_multipart.side_effect = side_effect
# Increase timeout to 5000ms
with qtbot.waitSignal(camera_thread.camera_image, timeout=5000):
camera_thread.run()
assert camera_thread._SampleCameraThread__camera_available is True
def test_run_bayer_success(camera_thread, mock_zmq, qtbot):
# Create a small bayer image
h, w = 10, 10
raw = np.zeros((h, w), dtype=np.uint8)
header = json.dumps({"shape": [h, w]}).encode("utf-8")
def side_effect():
camera_thread.running = False
return [header, raw.tobytes()]
mock_zmq.recv_multipart.side_effect = side_effect
# Increase timeout to 5000ms
with qtbot.waitSignal(camera_thread.camera_image, timeout=5000):
camera_thread.run()
assert camera_thread._SampleCameraThread__camera_available is True
def test_run_zmq_timeout(camera_thread, mock_zmq, qtbot):
def side_effect():
camera_thread.running = False
raise zmq.Again()
mock_zmq.recv_multipart.side_effect = side_effect
# We want to check if it emits nan or 0 for FPS on timeout
# But it only emits every 0.5s.
camera_thread._SampleCameraThread__fps_emit_period_s = 0.0
# Increase timeout to 5000ms
with qtbot.waitSignal(camera_thread.fps_measure, timeout=5000):
try:
camera_thread.run()
except StopIteration:
pass
def test_stop(camera_thread, mock_zmq):
# Mocking wait and quit to avoid actual thread blocking in test
camera_thread.quit = MagicMock()
camera_thread.wait = MagicMock()
camera_thread.stop()
assert camera_thread.running is False
mock_zmq.close.assert_called_once()
camera_thread.quit.assert_called_once()
camera_thread.wait.assert_called_once()