test_spoolbuddy_system_stats.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. """Tests for SpoolBuddy daemon system_stats collector."""
  2. import pytest
  3. pytest.importorskip("spoolbuddy", reason="spoolbuddy package not available in Docker")
  4. from unittest.mock import patch
  5. from spoolbuddy.daemon.system_stats import (
  6. _cpu_count,
  7. _cpu_temp,
  8. _disk_info,
  9. _load_avg,
  10. _memory_info,
  11. _os_info,
  12. _system_uptime,
  13. collect,
  14. )
  15. class TestCpuTemp:
  16. def test_reads_thermal_zone(self):
  17. with patch("spoolbuddy.daemon.system_stats._read_file", return_value="52100"):
  18. assert _cpu_temp() == 52.1
  19. def test_returns_none_on_missing_file(self):
  20. with patch("spoolbuddy.daemon.system_stats._read_file", return_value=None):
  21. assert _cpu_temp() is None
  22. def test_returns_none_on_bad_value(self):
  23. with patch("spoolbuddy.daemon.system_stats._read_file", return_value="not_a_number"):
  24. assert _cpu_temp() is None
  25. class TestMemoryInfo:
  26. SAMPLE_MEMINFO = (
  27. "MemTotal: 1024000 kB\n"
  28. "MemFree: 200000 kB\n"
  29. "MemAvailable: 512000 kB\n"
  30. "Buffers: 50000 kB\n"
  31. )
  32. def test_parses_meminfo(self):
  33. with patch("spoolbuddy.daemon.system_stats._read_file", return_value=self.SAMPLE_MEMINFO):
  34. result = _memory_info()
  35. assert result is not None
  36. assert result["total_mb"] == 1000
  37. assert result["available_mb"] == 500
  38. assert result["used_mb"] == 500
  39. assert result["percent"] == 50.0
  40. def test_returns_none_on_missing(self):
  41. with patch("spoolbuddy.daemon.system_stats._read_file", return_value=None):
  42. assert _memory_info() is None
  43. class TestDiskInfo:
  44. def test_returns_disk_stats(self):
  45. result = _disk_info()
  46. # Should always work on Linux
  47. assert result is not None
  48. assert "total_gb" in result
  49. assert "used_gb" in result
  50. assert "free_gb" in result
  51. assert "percent" in result
  52. assert 0 <= result["percent"] <= 100
  53. class TestLoadAvg:
  54. def test_returns_three_values(self):
  55. result = _load_avg()
  56. assert result is not None
  57. assert len(result) == 3
  58. for val in result:
  59. assert isinstance(val, float)
  60. class TestCpuCount:
  61. def test_returns_positive_int(self):
  62. result = _cpu_count()
  63. assert result is not None
  64. assert result > 0
  65. class TestOsInfo:
  66. def test_returns_required_keys(self):
  67. result = _os_info()
  68. assert "os" in result
  69. assert "kernel" in result
  70. assert "arch" in result
  71. assert "python" in result
  72. def test_parses_pretty_name(self):
  73. fake_release = 'PRETTY_NAME="Raspbian GNU/Linux 12 (bookworm)"\nID=raspbian\n'
  74. with patch("spoolbuddy.daemon.system_stats._read_file", return_value=fake_release):
  75. result = _os_info()
  76. assert result["os"] == "Raspbian GNU/Linux 12 (bookworm)"
  77. class TestSystemUptime:
  78. def test_parses_uptime(self):
  79. with patch("spoolbuddy.daemon.system_stats._read_file", return_value="86400.55 172000.10"):
  80. assert _system_uptime() == 86400
  81. def test_returns_none_on_missing(self):
  82. with patch("spoolbuddy.daemon.system_stats._read_file", return_value=None):
  83. assert _system_uptime() is None
  84. class TestCollect:
  85. def test_returns_dict_with_expected_keys(self):
  86. result = collect()
  87. assert isinstance(result, dict)
  88. assert "os" in result
  89. # These may or may not be present depending on platform, but os is always present
  90. def test_all_values_are_json_serializable(self):
  91. import json
  92. result = collect()
  93. # Should not raise
  94. json.dumps(result)