testsAndMisc/python_pkg/brother_printer/tests/test_cups_service.py
Krzysztof kuhy Rudnicki 607ba98c85 Split the brother_printer cups_service test modules under the cap
test_cups_service.py 390 -> 172 (usblp port status to _port),
part2 261 -> 115 (status mapping and discovery out), part3 260 -> 105
(the four healthy-port cases out). part3 was one 235-line class, so it
split by method rather than by class.

The four part-numbered files are renamed for what they cover; three of
them now name _cups_fallback, matching where the code moved earlier.

The first run after the part2 split reported 400, not 402: the moved
classes needed subprocess and get_status_info that my hand-written
import block had dropped. Fixed, and the count is 402 again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 17:19:55 +02:00

173 lines
6.2 KiB
Python

"""Tests for brother_printer.cups_service - pyusb info and service control."""
from __future__ import annotations
import subprocess
from unittest.mock import MagicMock, patch
from python_pkg.brother_printer.cups_service import (
_ensure_cups_running,
_get_pyusb_device_info,
is_cups_scheduler_running,
start_cups,
)
MOD = "python_pkg.brother_printer.cups_service"
class TestGetPyusbDeviceInfo:
def test_found(self) -> None:
import sys as _sys
mock_usb = MagicMock()
mock_dev = MagicMock()
mock_dev.product = "HL-1110"
mock_dev.serial_number = "SN123"
mock_usb.core.find.return_value = mock_dev
with patch.dict(_sys.modules, {"usb": mock_usb, "usb.core": mock_usb.core}):
result = _get_pyusb_device_info()
assert result["product"] == "HL-1110"
assert result["serial"] == "SN123"
def test_import_error(self) -> None:
import sys as _sys
mock_usb = MagicMock()
mock_usb.core.find.side_effect = ImportError("no usb")
with patch.dict(_sys.modules, {"usb": mock_usb, "usb.core": mock_usb.core}):
result = _get_pyusb_device_info()
assert result == {}
def test_not_found(self) -> None:
import sys as _sys
mock_usb = MagicMock()
mock_usb.core.find.return_value = None
with patch.dict(_sys.modules, {"usb": mock_usb, "usb.core": mock_usb.core}):
result = _get_pyusb_device_info()
assert result == {}
def test_none_product_serial(self) -> None:
import sys as _sys
mock_usb = MagicMock()
mock_dev = MagicMock()
mock_dev.product = None
mock_dev.serial_number = None
mock_usb.core.find.return_value = mock_dev
with patch.dict(_sys.modules, {"usb": mock_usb, "usb.core": mock_usb.core}):
result = _get_pyusb_device_info()
assert result["product"] == ""
assert result["serial"] == ""
def test_oserror(self) -> None:
import sys as _sys
mock_usb = MagicMock()
mock_usb.core.find.side_effect = OSError("usb fail")
with patch.dict(_sys.modules, {"usb": mock_usb, "usb.core": mock_usb.core}):
result = _get_pyusb_device_info()
assert result == {}
def test_value_error(self) -> None:
import sys as _sys
mock_usb = MagicMock()
mock_usb.core.find.side_effect = ValueError("bad")
with patch.dict(_sys.modules, {"usb": mock_usb, "usb.core": mock_usb.core}):
result = _get_pyusb_device_info()
assert result == {}
class TestIsCupsSchedulerRunning:
@patch(f"{MOD}.shutil.which", return_value=None)
def test_no_lpstat(self, m: MagicMock) -> None:
assert is_cups_scheduler_running() is False
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/lpstat")
def test_running(self, w: MagicMock, mock_run: MagicMock) -> None:
mock_run.return_value = MagicMock(stdout="scheduler is running")
assert is_cups_scheduler_running() is True
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/lpstat")
def test_not_running(self, w: MagicMock, mock_run: MagicMock) -> None:
mock_run.return_value = MagicMock(stdout="scheduler is not running")
assert is_cups_scheduler_running() is False
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/lpstat")
def test_timeout(self, w: MagicMock, mock_run: MagicMock) -> None:
mock_run.side_effect = subprocess.TimeoutExpired("lpstat", 3)
assert is_cups_scheduler_running() is False
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/lpstat")
def test_oserror(self, w: MagicMock, mock_run: MagicMock) -> None:
mock_run.side_effect = OSError("fail")
assert is_cups_scheduler_running() is False
class TestStartCups:
@patch(f"{MOD}.shutil.which", return_value=None)
def test_no_systemctl(self, m: MagicMock) -> None:
assert start_cups() is False
@patch(f"{MOD}.time.sleep")
@patch(f"{MOD}.is_cups_scheduler_running")
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/systemctl")
def test_success(
self,
w: MagicMock,
mock_run: MagicMock,
mock_is_running: MagicMock,
s: MagicMock,
) -> None:
mock_run.return_value = MagicMock()
mock_is_running.return_value = True
assert start_cups() is True
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/systemctl")
def test_timeout(self, w: MagicMock, mock_run: MagicMock) -> None:
mock_run.side_effect = subprocess.TimeoutExpired("systemctl", 15)
assert start_cups() is False
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/systemctl")
def test_called_process_error(self, w: MagicMock, mock_run: MagicMock) -> None:
mock_run.side_effect = subprocess.CalledProcessError(1, "systemctl")
assert start_cups() is False
@patch(f"{MOD}.time.sleep")
@patch(f"{MOD}.is_cups_scheduler_running", return_value=False)
@patch(f"{MOD}.subprocess.run")
@patch(f"{MOD}.shutil.which", return_value="/usr/bin/systemctl")
def test_never_starts(
self,
w: MagicMock,
mock_run: MagicMock,
is_running: MagicMock,
s: MagicMock,
) -> None:
mock_run.return_value = MagicMock()
assert start_cups() is False
class TestEnsureCupsRunning:
@patch(f"{MOD}.is_cups_scheduler_running", return_value=True)
def test_already_running(self, m: MagicMock) -> None:
assert _ensure_cups_running() is True
@patch(f"{MOD}.start_cups", return_value=True)
@patch(f"{MOD}.is_cups_scheduler_running", return_value=False)
def test_needs_start(self, is_running: MagicMock, st: MagicMock) -> None:
assert _ensure_cups_running() is True
@patch(f"{MOD}.start_cups", return_value=False)
@patch(f"{MOD}.is_cups_scheduler_running", return_value=False)
def test_start_fails(self, is_running: MagicMock, st: MagicMock) -> None:
assert _ensure_cups_running() is False