"""Tests for utils.resource — Hardware detection and resource monitoring.""" import os from unittest.mock import patch, mock_open import pytest from utils.resource import ( get_hardware_tier, get_memory_info, get_cpu_temperature, get_disk_usage, get_process_resources, detect_hardware, HardwareInfo, TIER_GENERIC, TIER_PI_ZERO, TIER_OPI_ZERO3, ) class TestResource: def test_detect_hardware_tier(self): """get_hardware_tier() returns a valid tier string.""" tier = get_hardware_tier() assert tier in (TIER_GENERIC, TIER_PI_ZERO, TIER_OPI_ZERO3) def test_detect_hardware_info(self): """detect_hardware() returns a HardwareInfo dataclass.""" info = detect_hardware() assert isinstance(info, HardwareInfo) assert info.tier in (TIER_GENERIC, TIER_PI_ZERO, TIER_OPI_ZERO3) assert info.cpu_cores >= 1 assert isinstance(info.architecture, str) assert len(info.architecture) > 0 def test_get_memory_info(self): """get_memory_info() returns a dict with MemTotal and MemAvailable.""" info = get_memory_info() assert isinstance(info, dict) # On Linux, /proc/meminfo should be available if os.path.exists("/proc/meminfo"): assert "MemTotal" in info assert info["MemTotal"] > 0 def test_get_cpu_temperature(self): """get_cpu_temperature() returns a float or None (no crash).""" temp = get_cpu_temperature() # May be None if no thermal zone is available (CI/container) if temp is not None: assert isinstance(temp, float) # Sanity check: between -20 and 120 Celsius assert -20 <= temp <= 120 def test_get_disk_usage(self): """get_disk_usage() returns (total_gb, free_gb, used_pct) for /.""" total_gb, free_gb, used_pct = get_disk_usage("/") assert isinstance(total_gb, float) assert isinstance(free_gb, float) assert isinstance(used_pct, float) assert total_gb > 0 assert free_gb >= 0 assert 0 <= used_pct <= 100 def test_get_process_resources(self): """get_process_resources() returns stats for the current PID.""" pid = os.getpid() result = get_process_resources(pid) # Should succeed for our own PID on Linux if result is not None: assert result.pid == pid assert result.rss_mb >= 0 assert result.vms_mb >= 0 assert result.threads >= 1 assert isinstance(result.name, str) assert isinstance(result.state, str) def test_get_process_resources_invalid_pid(self): """get_process_resources() returns None for a non-existent PID.""" result = get_process_resources(999999999) assert result is None