from __future__ import annotations from pathlib import Path import pytest from scripts.measure_gpio_status import MeasurementError, percentile_95, validate_samples def sample(frames: int, *, misses: int = 0, fault: int = 0, performance: bool = True): return { "screen": { "driver_status": { "actual_refresh_rate_hz": 97.4, "panel_scan_rate_hz": 97.4, "scans_per_frame": 1, "completed_frames": frames, "completed_scans": frames, "deadline_misses": misses, "oe_pulse_faults": fault, "oe_forced_blanks": 0, "driver_error": None, "oe_timing_error": None, "safeoff_error": None, "cpu_affinity": 3, "cpu_affinity_active": True, "realtime_priority": 50, "realtime_priority_active": True, "memory_locked": True, } }, "system": { "performance_mode": { "requested": performance, "effective": performance, "current_governors": {"policy0": "performance" if performance else "schedutil"}, "restore_governors": {"policy0": "schedutil"}, } }, } def test_gpio_measurement_accepts_equal_progress_and_fixed_rgb_frame(): result = validate_samples( [sample(100), sample(198), sample(295)], performance="on", frame_before="same", frame_after="same", ) assert result["completed_frames_delta"] == 195 assert result["deadline_miss_rate"] == 0 assert percentile_95([1, 2, 3, 100]) == 100 def test_gpio_measurement_rejects_fault_growth_and_changed_frame(): with pytest.raises(MeasurementError, match="oe_pulse_faults"): validate_samples( [sample(100), sample(198, fault=1)], performance="on", frame_before="same", frame_after="same", ) with pytest.raises(MeasurementError, match="RGB frame changed"): validate_samples( [sample(100), sample(198)], performance="on", frame_before="before", frame_after="after", ) def test_gpio_measurement_requires_governor_restore_when_off(): off = [sample(100, performance=False), sample(198, performance=False)] validate_samples(off, performance="off", frame_before="same", frame_after="same") off[-1]["system"]["performance_mode"]["current_governors"] = {"policy0": "powersave"} with pytest.raises(MeasurementError, match="not restored"): validate_samples(off, performance="off", frame_before="same", frame_after="same") def test_preview_performance_unit_is_isolated_and_preserves_realtime_contract(): source_root = Path(__file__).resolve().parents[1] unit = (source_root / "systemd/matrix-screen-controller-preview-perf.service").read_text( encoding="utf-8" ) assert "Conflicts=matrix-screen-controller.service" in unit assert "MATRIX_DATA_DIR=/var/tmp/matrix-screen-controller-preview-perf-20260824" in unit assert "MATRIX_RUNTIME_DIR=/run/matrix-screen-controller-preview-perf-20260824" in unit assert "/var/lib/matrix-screen-controller" not in unit assert "CPUAffinity=0 1 2" in unit assert "LimitRTPRIO=50" in unit assert "LimitMEMLOCK=infinity" in unit assert unit.count("hub75_safeoff") == 2 assert "app.system.performance restore" in unit