Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/trcc/adapters/diagnostics/debug_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def build_debug_report(
sensors, sensors_err = _collect_sensors(platform)
powercap = _collect_powercap()
settings_text, settings_err = _read_settings_file(
settings_path or platform.paths().config_dir() / "config.json",
settings_path or platform.paths().config_dir() / "trcc.json",
)
health = run_health_checks(platform)
log_path = platform.paths().log_file()
Expand Down
22 changes: 12 additions & 10 deletions src/trcc/adapters/diagnostics/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,25 +301,27 @@ def check_qt_importable() -> HealthCheckResult:


def check_udev_rules_linux() -> HealthCheckResult:
"""Linux-only: look for installed udev rules under /etc/udev/rules.d/."""
"""Linux-only: look for the canonical rule in standard install paths."""
log.info("check_udev_rules_linux: called")
if sys.platform != "linux":
return HealthCheckResult(
name="udev-rules", severity="OK",
message="Not applicable on this OS",
)
candidate_paths = [
Path("/etc/udev/rules.d/99-trcc.rules"),
Path("/etc/udev/rules.d/90-trcc.rules"),
Path("/lib/udev/rules.d/99-trcc.rules"),
]
found = [p for p in candidate_paths if p.is_file()]
udev_rule_paths = (
Path("/etc/udev/rules.d/99-trcc-lcd.rules"),
Path("/run/udev/rules.d/99-trcc-lcd.rules"),
Path("/usr/local/lib/udev/rules.d/99-trcc-lcd.rules"),
Path("/usr/lib/udev/rules.d/99-trcc-lcd.rules"),
Path("/lib/udev/rules.d/99-trcc-lcd.rules"),
)
found = [p for p in udev_rule_paths if p.is_file()]
if not found:
return HealthCheckResult(
name="udev-rules", severity="WARN",
message="No TRCC udev rules found under /etc/udev/rules.d/",
fix_hint="Run `trcc system setup` (or install via the distro "
"package) to lay down /etc/udev/rules.d/99-trcc.rules",
message="No TRCC udev rules found",
fix_hint="Run `trcc system setup` or reinstall the distro package "
"to install 99-trcc-lcd.rules",
)
return HealthCheckResult(
name="udev-rules", severity="OK",
Expand Down
56 changes: 56 additions & 0 deletions tests/test_diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
check_gpu_sensors,
check_log_writable,
check_python_version,
check_udev_rules_linux,
package_install_hint,
run_health_checks,
)
Expand Down Expand Up @@ -260,6 +261,44 @@ def test_log_writable_check_passes_on_tmp_dir(
assert result.severity == "OK"


@pytest.mark.parametrize(
"installed_rule",
(
Path("/etc/udev/rules.d/99-trcc-lcd.rules"),
Path("/run/udev/rules.d/99-trcc-lcd.rules"),
Path("/usr/local/lib/udev/rules.d/99-trcc-lcd.rules"),
Path("/usr/lib/udev/rules.d/99-trcc-lcd.rules"),
Path("/lib/udev/rules.d/99-trcc-lcd.rules"),
),
)
def test_udev_check_accepts_canonical_rule_in_standard_location(
installed_rule: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(
health_mod.Path,
"is_file",
lambda path: path == installed_rule,
)

result = check_udev_rules_linux()

assert result.severity == "OK"
assert str(installed_rule) in result.message


def test_udev_check_warns_with_current_rule_name(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(health_mod.Path, "is_file", lambda path: False)

result = check_udev_rules_linux()

assert result.severity == "WARN"
assert "99-trcc-lcd.rules" in result.fix_hint
assert "99-trcc.rules" not in result.fix_hint


def test_run_health_checks_returns_full_report(fake_platform) -> None:
report = run_health_checks(fake_platform)
names = {c.name for c in report.checks}
Expand Down Expand Up @@ -388,6 +427,23 @@ def test_debug_report_writes_to_disk(fake_platform, tmp_path: Path) -> None:
assert "Paths" in body


def test_debug_report_reads_canonical_settings_file(fake_platform) -> None:
config_dir = fake_platform.paths().config_dir()
config_dir.mkdir(parents=True, exist_ok=True)
(config_dir / "config.json").write_text(
'{"source": "obsolete"}', encoding="utf-8",
)
(config_dir / "trcc.json").write_text(
'{"source": "canonical"}', encoding="utf-8",
)

report = build_debug_report(fake_platform)

assert report.settings_error == ""
assert '"source": "canonical"' in report.settings_json
assert "obsolete" not in report.settings_json


def test_debug_report_captures_live_handshake(tmp_path: Path) -> None:
"""A connected LCD device's exact PM / SUB / fbl / resolution / raw bytes
are captured live — the byte the report previously couldn't produce because
Expand Down