mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 23:27:01 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
The CUPS-fallback note blamed a missing pyusb when the probe was really skipped because CUPS owned the printer. It now names the real reason. run.sh installs python-pyusb for the system python3 that sudo runs. A paper misfeed blocks the usb:// backend while CUPS keeps saying "processing", and cancel leaves that backend hung so the queue never recovers. The report now flags a job whose page counter is frozen for 15 s, and a backend of a cancelled job, with a y/N offer to SIGKILL it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AaBRWtXXWCs3K3yPHSruUC
134 lines
5.2 KiB
Python
134 lines
5.2 KiB
Python
"""Tests for brother_printer._cups_fallback - the CUPS fallback query."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from python_pkg.brother_printer._cups_fallback import query_usb_via_cups
|
|
from python_pkg.brother_printer.data_classes import USBPortStatus
|
|
|
|
MOD = "python_pkg.brother_printer._cups_fallback"
|
|
|
|
|
|
# ── query_usb_via_cups ───────────────────────────────────────────────
|
|
|
|
|
|
class TestQueryUsbViaCups:
|
|
"""Tests for query_usb_via_cups."""
|
|
|
|
@patch(f"{MOD}.find_cups_printer_name", return_value="")
|
|
@patch(f"{MOD}._ensure_cups_running", return_value=True)
|
|
def test_no_printer(self, e: MagicMock, f: MagicMock) -> None:
|
|
result = query_usb_via_cups()
|
|
assert result.error != ""
|
|
|
|
def test_no_port_status_idle(self) -> None:
|
|
with (
|
|
patch(f"{MOD}._ensure_cups_running", return_value=True),
|
|
patch(f"{MOD}.find_cups_printer_name", return_value="Brother"),
|
|
patch(f"{MOD}._get_pyusb_device_info", return_value={}),
|
|
patch(
|
|
f"{MOD}.printer_info_from_cups",
|
|
return_value={"product": "HL-1110", "serial": "ABC"},
|
|
),
|
|
patch(
|
|
f"{MOD}._get_cups_ipp_status",
|
|
return_value={
|
|
"printer-state": "idle",
|
|
"printer-state-reasons": "none",
|
|
"printer-state-message": "Ready",
|
|
},
|
|
),
|
|
patch(f"{MOD}._get_cups_economode", return_value="ON"),
|
|
patch(f"{MOD}._query_usb_port_status_raw", return_value=None),
|
|
):
|
|
result = query_usb_via_cups()
|
|
assert result.online == "TRUE"
|
|
assert result.product == "HL-1110"
|
|
assert result.economode == "ON"
|
|
|
|
def test_no_port_status_stopped(self) -> None:
|
|
with (
|
|
patch(f"{MOD}._ensure_cups_running", return_value=True),
|
|
patch(f"{MOD}.find_cups_printer_name", return_value="Brother"),
|
|
patch(f"{MOD}._get_pyusb_device_info", return_value={}),
|
|
patch(
|
|
f"{MOD}.printer_info_from_cups",
|
|
return_value={"product": "", "serial": ""},
|
|
),
|
|
patch(
|
|
f"{MOD}._get_cups_ipp_status",
|
|
return_value={
|
|
"printer-state": "stopped",
|
|
"printer-state-reasons": "none",
|
|
},
|
|
),
|
|
patch(f"{MOD}._get_cups_economode", return_value=""),
|
|
patch(f"{MOD}._query_usb_port_status_raw", return_value=None),
|
|
):
|
|
result = query_usb_via_cups()
|
|
assert result.online == "FALSE"
|
|
assert result.product == "Brother Laser Printer"
|
|
|
|
def test_port_status_hw_error(self) -> None:
|
|
with (
|
|
patch(f"{MOD}._ensure_cups_running", return_value=True),
|
|
patch(f"{MOD}.find_cups_printer_name", return_value="Brother"),
|
|
patch(f"{MOD}._get_pyusb_device_info", return_value={}),
|
|
patch(
|
|
f"{MOD}.printer_info_from_cups",
|
|
return_value={"product": "", "serial": ""},
|
|
),
|
|
patch(
|
|
f"{MOD}._get_cups_ipp_status",
|
|
return_value={
|
|
"printer-state": "stopped",
|
|
"printer-state-reasons": "none",
|
|
},
|
|
),
|
|
patch(f"{MOD}._get_cups_economode", return_value=""),
|
|
patch(
|
|
f"{MOD}._query_usb_port_status_raw",
|
|
return_value=USBPortStatus(
|
|
error=True,
|
|
paper_empty=True,
|
|
online=False,
|
|
raw_byte=0x20,
|
|
),
|
|
),
|
|
):
|
|
result = query_usb_via_cups()
|
|
assert result.status_code == "41000"
|
|
assert result.online == "FALSE"
|
|
|
|
|
|
class TestQueryUsbViaCupsStuckJob:
|
|
"""A busy queue whose job goes nowhere must not read as "printing"."""
|
|
|
|
def _query(self, *, stuck: bool) -> tuple[object, MagicMock]:
|
|
with (
|
|
patch(f"{MOD}._ensure_cups_running", return_value=True),
|
|
patch(f"{MOD}.find_cups_printer_name", return_value="Brother"),
|
|
patch(f"{MOD}._get_pyusb_device_info", return_value={}),
|
|
patch(f"{MOD}.printer_info_from_cups", return_value={}),
|
|
patch(
|
|
f"{MOD}._get_cups_ipp_status",
|
|
return_value={"printer-state": "processing"},
|
|
),
|
|
patch(f"{MOD}._get_cups_economode", return_value=""),
|
|
patch(f"{MOD}._query_usb_port_status_raw", return_value=None),
|
|
patch(f"{MOD}.flag_stuck_job", return_value=stuck) as flag,
|
|
):
|
|
return query_usb_via_cups(), flag
|
|
|
|
def test_stuck_job_short_circuits(self) -> None:
|
|
result, flag = self._query(stuck=True)
|
|
flag.assert_called_once()
|
|
assert result.status_code == "" # left for flag_stuck_job to set
|
|
|
|
def test_progressing_job_reads_as_printing(self) -> None:
|
|
result, flag = self._query(stuck=False)
|
|
flag.assert_called_once()
|
|
assert result.status_code == "10023"
|
|
assert "CUPS has a job" in result.cups.probe_note
|