mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 10:51:36 -04:00
209 lines
6.9 KiB
Python
209 lines
6.9 KiB
Python
"""
|
|
Unit tests for controller.lib.status module.
|
|
|
|
The status module now returns formats compatible with the main WROLPi API
|
|
so the React app can seamlessly use either source.
|
|
"""
|
|
|
|
from unittest import mock
|
|
|
|
from controller.lib.status import (
|
|
get_cpu_status,
|
|
get_drive_status,
|
|
get_load_status,
|
|
get_memory_status,
|
|
get_network_status,
|
|
get_power_status,
|
|
get_primary_drive_status,
|
|
)
|
|
|
|
|
|
class TestGetCpuStatus:
|
|
"""Tests for get_cpu_status function."""
|
|
|
|
def test_returns_dict(self):
|
|
"""Should return a dictionary."""
|
|
result = get_cpu_status()
|
|
assert isinstance(result, dict)
|
|
|
|
def test_has_required_keys(self):
|
|
"""Should have all required keys (main API format)."""
|
|
result = get_cpu_status()
|
|
assert "percent" in result
|
|
assert "cores" in result
|
|
assert "cur_frequency" in result
|
|
assert "max_frequency" in result
|
|
assert "min_frequency" in result
|
|
assert "temperature" in result
|
|
assert "high_temperature" in result
|
|
assert "critical_temperature" in result
|
|
|
|
def test_percent_is_numeric(self):
|
|
"""CPU percent should be a number."""
|
|
result = get_cpu_status()
|
|
assert isinstance(result["percent"], (int, float))
|
|
assert 0 <= result["percent"] <= 100
|
|
|
|
def test_cores_is_positive(self):
|
|
"""Core count should be a positive integer."""
|
|
result = get_cpu_status()
|
|
assert isinstance(result["cores"], int)
|
|
assert result["cores"] > 0
|
|
|
|
|
|
class TestGetMemoryStatus:
|
|
"""Tests for get_memory_status function."""
|
|
|
|
def test_returns_dict(self):
|
|
"""Should return a dictionary."""
|
|
result = get_memory_status()
|
|
assert isinstance(result, dict)
|
|
|
|
def test_has_required_keys(self):
|
|
"""Should have all required keys (main API format)."""
|
|
result = get_memory_status()
|
|
assert "total" in result
|
|
assert "used" in result
|
|
assert "free" in result
|
|
assert "cached" in result
|
|
|
|
def test_total_is_positive(self):
|
|
"""Memory total should be positive."""
|
|
result = get_memory_status()
|
|
assert result["total"] > 0
|
|
|
|
def test_bytes_are_non_negative(self):
|
|
"""Memory bytes should be non-negative."""
|
|
result = get_memory_status()
|
|
assert result["used"] >= 0
|
|
assert result["free"] >= 0
|
|
assert result["cached"] >= 0
|
|
|
|
|
|
class TestGetLoadStatus:
|
|
"""Tests for get_load_status function."""
|
|
|
|
def test_returns_dict(self):
|
|
"""Should return a dictionary."""
|
|
result = get_load_status()
|
|
assert isinstance(result, dict)
|
|
|
|
def test_has_required_keys(self):
|
|
"""Should have all required keys (main API format)."""
|
|
result = get_load_status()
|
|
assert "minute_1" in result
|
|
assert "minute_5" in result
|
|
assert "minute_15" in result
|
|
|
|
def test_values_are_strings(self):
|
|
"""Load values should be string representations of numbers (main API format)."""
|
|
result = get_load_status()
|
|
# Values are strings in the main API format
|
|
assert isinstance(result["minute_1"], str)
|
|
assert isinstance(result["minute_5"], str)
|
|
assert isinstance(result["minute_15"], str)
|
|
# But they should be parseable as floats
|
|
assert float(result["minute_1"]) >= 0
|
|
assert float(result["minute_5"]) >= 0
|
|
assert float(result["minute_15"]) >= 0
|
|
|
|
|
|
class TestGetDriveStatus:
|
|
"""Tests for get_drive_status function."""
|
|
|
|
def test_returns_list(self):
|
|
"""Should return a list."""
|
|
result = get_drive_status()
|
|
assert isinstance(result, list)
|
|
|
|
def test_returns_drives_or_empty(self):
|
|
"""Should return drives list (may be empty in Docker containers)."""
|
|
result = get_drive_status()
|
|
# The result should be a valid list
|
|
# May be empty in Docker containers where root fs is not visible
|
|
assert isinstance(result, list)
|
|
|
|
def test_drive_has_required_keys(self):
|
|
"""Each drive should have all required keys (main API format)."""
|
|
result = get_drive_status()
|
|
if result: # Only test if we have drives
|
|
drive = result[0]
|
|
assert "mount" in drive
|
|
assert "percent" in drive
|
|
assert "size" in drive
|
|
assert "used" in drive
|
|
|
|
|
|
class TestGetPrimaryDriveStatus:
|
|
"""Tests for get_primary_drive_status function."""
|
|
|
|
def test_returns_none_when_not_mounted(self):
|
|
"""Should return None when /media/wrolpi is not mounted."""
|
|
# In most test environments, /media/wrolpi won't be mounted
|
|
result = get_primary_drive_status()
|
|
# This could be None or a dict depending on the environment
|
|
assert result is None or isinstance(result, dict)
|
|
|
|
def test_returns_dict_when_mounted(self):
|
|
"""Should return drive info when /media/wrolpi is mounted."""
|
|
# Mock the get_drive_status to return a drive at /media/wrolpi
|
|
mock_drives = [
|
|
{
|
|
"mount": "/media/wrolpi",
|
|
"percent": 50,
|
|
"size": 1000000000,
|
|
"used": 500000000,
|
|
}
|
|
]
|
|
with mock.patch(
|
|
"controller.lib.status.get_drive_status", return_value=mock_drives
|
|
):
|
|
result = get_primary_drive_status()
|
|
assert result is not None
|
|
assert result["mount"] == "/media/wrolpi"
|
|
|
|
|
|
class TestGetNetworkStatus:
|
|
"""Tests for get_network_status function."""
|
|
|
|
def test_returns_dict(self):
|
|
"""Should return a dict (main API format: dict of interface name -> stats)."""
|
|
result = get_network_status()
|
|
assert isinstance(result, dict)
|
|
|
|
def test_excludes_loopback(self):
|
|
"""Should not include the loopback interface."""
|
|
result = get_network_status()
|
|
assert "lo" not in result
|
|
|
|
def test_interface_has_required_keys(self):
|
|
"""Each interface should have required keys (main API format)."""
|
|
result = get_network_status()
|
|
if result: # Only test if we have interfaces
|
|
iface = list(result.values())[0]
|
|
assert "name" in iface
|
|
assert "bytes_sent" in iface
|
|
assert "bytes_recv" in iface
|
|
assert "speed" in iface
|
|
assert "now" in iface
|
|
|
|
|
|
class TestGetPowerStatus:
|
|
"""Tests for get_power_status function."""
|
|
|
|
def test_returns_dict(self):
|
|
"""Should return a dictionary."""
|
|
result = get_power_status()
|
|
assert isinstance(result, dict)
|
|
|
|
def test_has_required_keys(self):
|
|
"""Should have all required keys (main API format)."""
|
|
result = get_power_status()
|
|
assert "under_voltage" in result
|
|
assert "over_current" in result
|
|
|
|
def test_values_are_bool(self):
|
|
"""All values should be boolean."""
|
|
result = get_power_status()
|
|
assert isinstance(result["under_voltage"], bool)
|
|
assert isinstance(result["over_current"], bool)
|