testsAndMisc/python_pkg/brother_printer/tests/test_page_delivery.py
Krzysztof kuhy Rudnicki 2c01a0267e
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
Clear the last three brother_printer test modules over the cap
test_consumables_part2.py 273 -> 133 (renamed test_counter_scales.py),
test_consumables.py 272 -> 123, test_check_brother_printer.py 275 -> 112.
python_pkg/brother_printer is now entirely under the 250-line cap, from
fifteen violations at the start.

The consumables split lands exactly on the MOD/MOD_PD boundary an earlier
commit introduced, so the two-constant workaround dissolves instead of
being carried forward - each file has one module under test again.

Pass count is 402, unchanged across all eight commits of this pass.

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

153 lines
5.4 KiB
Python

"""Tests for brother_printer._page_delivery - dropped-page detection.
Split from test_consumables_part2.py under the 250-line cap. These are exactly
the tests whose functions moved to _page_delivery, so the file needs only that
module's patch target rather than the two constants the combined file carried.
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
from python_pkg.brother_printer._page_delivery import (
_snapshot_counters,
check_page_delivery,
)
MOD = "python_pkg.brother_printer._page_delivery"
class TestCheckPageDelivery:
"""Spotting pages the printer silently dropped.
CUPS calls a job successful once the data leaves the machine, so this
comparison against the printer's own counter is the only signal that a page
never actually came out.
"""
@patch(f"{MOD}._snapshot_counters")
@patch(f"{MOD}._get_cups_total_pages", return_value=1841)
@patch(f"{MOD}._load_consumable_state")
def test_detects_dropped_pages(
self,
mock_load: MagicMock,
mock_cups: MagicMock,
mock_snap: MagicMock,
) -> None:
"""Replay of the real failure: CUPS sent 63, printer printed none."""
mock_load.return_value = {
"last_printer_count": 2087,
"last_cups_total": 1778,
}
check = check_page_delivery(2087, queue_idle=True)
assert check.cups_pages == 63
assert check.printer_pages == 0
assert check.dropped == 63
assert check.suspected is True
@patch(f"{MOD}._snapshot_counters")
@patch(f"{MOD}._get_cups_total_pages", return_value=1841)
@patch(f"{MOD}._load_consumable_state")
def test_healthy_job_does_not_warn(
self,
mock_load: MagicMock,
mock_cups: MagicMock,
mock_snap: MagicMock,
) -> None:
mock_load.return_value = {
"last_printer_count": 2024,
"last_cups_total": 1778,
}
check = check_page_delivery(2087, queue_idle=True)
assert check.dropped == 0
assert check.suspected is False
@patch(f"{MOD}._snapshot_counters")
@patch(f"{MOD}._get_cups_total_pages", return_value=1780)
@patch(f"{MOD}._load_consumable_state")
def test_small_gap_is_not_a_warning(
self,
mock_load: MagicMock,
mock_cups: MagicMock,
mock_snap: MagicMock,
) -> None:
"""A page or two of drift is timing, not a fault."""
mock_load.return_value = {
"last_printer_count": 2087,
"last_cups_total": 1778,
}
check = check_page_delivery(2087, queue_idle=True)
assert check.dropped == 2
assert check.suspected is False
def test_skipped_while_printing(self) -> None:
"""Mid-job the counters legitimately disagree, so never compare."""
assert check_page_delivery(2087, queue_idle=False).suspected is False
def test_skipped_without_printer_count(self) -> None:
assert check_page_delivery(0, queue_idle=True).suspected is False
@patch(f"{MOD}._snapshot_counters")
@patch(f"{MOD}._get_cups_total_pages", return_value=1841)
@patch(f"{MOD}._load_consumable_state")
def test_first_run_only_establishes_baseline(
self,
mock_load: MagicMock,
mock_cups: MagicMock,
mock_snap: MagicMock,
) -> None:
mock_load.return_value = {"last_printer_count": 0, "last_cups_total": 0}
check = check_page_delivery(2087, queue_idle=True)
assert check.suspected is False
mock_snap.assert_called_once()
@patch(f"{MOD}._snapshot_counters")
@patch(f"{MOD}._get_cups_total_pages", return_value=10)
@patch(f"{MOD}._load_consumable_state")
def test_log_rotation_draws_no_conclusion(
self,
mock_load: MagicMock,
mock_cups: MagicMock,
mock_snap: MagicMock,
) -> None:
"""A rotated page log makes the delta negative; do not cry wolf."""
mock_load.return_value = {
"last_printer_count": 2087,
"last_cups_total": 1778,
}
check = check_page_delivery(2087, queue_idle=True)
assert check.suspected is False
@patch(f"{MOD}._snapshot_counters")
@patch(f"{MOD}._get_cups_total_pages", return_value=1841)
@patch(f"{MOD}._load_consumable_state")
def test_printer_counter_reset_draws_no_conclusion(
self,
mock_load: MagicMock,
mock_cups: MagicMock,
mock_snap: MagicMock,
) -> None:
mock_load.return_value = {
"last_printer_count": 5000,
"last_cups_total": 1778,
}
check = check_page_delivery(2087, queue_idle=True)
assert check.suspected is False
class TestSnapshotCounters:
@patch(f"{MOD}._save_consumable_state")
def test_writes_new_snapshot(self, mock_save: MagicMock) -> None:
state = {"last_printer_count": 2000, "last_cups_total": 1700}
_snapshot_counters(state, 2087, 1778)
saved = mock_save.call_args[0][0]
assert saved["last_printer_count"] == 2087
assert saved["last_cups_total"] == 1778
@patch(f"{MOD}._save_consumable_state")
def test_unchanged_counters_skip_the_write(self, mock_save: MagicMock) -> None:
"""Do not rewrite the file on every run when nothing moved."""
state = {"last_printer_count": 2087, "last_cups_total": 1778}
_snapshot_counters(state, 2087, 1778)
mock_save.assert_not_called()