from pathlib import Path from scripts.dedicated_host import CommandResult, HostPaths, check_profile def make_paths(tmp_path: Path) -> HostPaths: compatible = ( tmp_path / "proc" / "device-tree" / "soc" / "pinctrl@300b000" / "compatible" ) compatible.parent.mkdir(parents=True) compatible.write_bytes(b"allwinner,sun50i-h616-pinctrl\0") dev_mem = tmp_path / "dev" / "mem" dev_mem.parent.mkdir(parents=True) dev_mem.touch() i2c = tmp_path / "dev" / "i2c-1" i2c.touch() cpu3 = tmp_path / "sys" / "devices" / "system" / "cpu" / "cpu3" cpu3.mkdir(parents=True) native = tmp_path / "source" / "app" / "display" / "native" / "libh618_hub75.so" native.parent.mkdir(parents=True) native.touch() return HostPaths(compatible, dev_mem, i2c, cpu3, native) def healthy_runner(args): if tuple(args[:2]) == ("systemctl", "is-active") and args[2] != "NetworkManager.service": return CommandResult(3, "inactive\n") responses = { ("uname", "-m"): CommandResult(0, "aarch64\n"), ("ip", "route", "show", "default"): CommandResult( 0, "default via 192.168.198.1 dev wlan0\n" ), ("systemctl", "is-active", "NetworkManager.service"): CommandResult( 0, "active\n" ), } return responses[tuple(args)] def test_check_profile_accepts_walnutpi_contract(tmp_path): checks = check_profile(make_paths(tmp_path), runner=healthy_runner) assert all(check.ok for check in checks), [ (check.name, check.detail) for check in checks if not check.ok ] def test_bluetooth_is_not_a_display_startup_blocker(tmp_path): def runner(args): assert not any('bluetooth' in part for part in args) return healthy_runner(args) assert all(check.ok for check in check_profile(make_paths(tmp_path), runner=runner)) def test_service_preflight_does_not_require_default_route(tmp_path): def runner(args): assert tuple(args) != ("ip", "route", "show", "default") return healthy_runner(args) checks = check_profile(make_paths(tmp_path), service_only=True, runner=runner) assert all(check.ok for check in checks) assert all(check.name != "default network route" for check in checks) def test_manual_profile_still_requires_default_route(tmp_path): def runner(args): if tuple(args) == ("ip", "route", "show", "default"): return CommandResult(0, "") return healthy_runner(args) checks = check_profile(make_paths(tmp_path), runner=runner) assert any( check.name == "default network route" and not check.ok for check in checks ) def test_check_profile_rejects_wrong_pinctrl(tmp_path): paths = make_paths(tmp_path) paths.pinctrl_compatible.write_bytes(b"vendor,other-pinctrl\0") checks = check_profile(paths, runner=healthy_runner) assert any(check.name == "H618 PI pinctrl" and not check.ok for check in checks) def test_check_profile_reports_missing_reserved_i2c_bus(tmp_path): paths = make_paths(tmp_path) paths.i2c_device.unlink() checks = check_profile(paths, service_only=True, runner=healthy_runner) assert any(check.name == "/dev/i2c-1 present" and not check.ok for check in checks) def test_check_profile_rejects_running_vendor_gpio_service(tmp_path): def runner(args): if tuple(args) == ("systemctl", "is-active", "gpioc-server.service"): return CommandResult(0, "active\n") return healthy_runner(args) checks = check_profile(make_paths(tmp_path), runner=runner) assert any( check.name == "gpioc-server.service inactive" and not check.ok for check in checks ) def test_check_profile_requires_compiled_native_library(tmp_path): paths = make_paths(tmp_path) paths.native_library.unlink() checks = check_profile(paths, runner=healthy_runner) assert any( check.name == "native HUB75 library" and not check.ok for check in checks ) def test_detect_uses_walnutpi_device_tree_and_source_root(tmp_path): source = tmp_path / "payload" paths = HostPaths.detect(tmp_path, source) assert paths.pinctrl_compatible == ( tmp_path / "proc" / "device-tree" / "soc" / "pinctrl@300b000" / "compatible" ) assert paths.native_library == source / "app/display/native/libh618_hub75.so"