first commit

This commit is contained in:
zj
2026-03-02 14:14:40 +08:00
commit c4f4fefa0a
20 changed files with 6037 additions and 0 deletions

3
tests/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
"""
ServerGuard 测试模块
"""

175
tests/test_modules.py Normal file
View File

@@ -0,0 +1,175 @@
"""
测试各个硬件检测模块
"""
import unittest
from unittest.mock import patch, MagicMock
import sys
import os
# 添加父目录到路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from modules import system_info, cpu, memory, storage, sensors, gpu, log_analyzer
class TestSystemInfo(unittest.TestCase):
"""测试系统信息模块"""
@patch('modules.system_info.execute_command')
def test_get_os_info(self, mock_exec):
mock_exec.return_value = (0, "test-hostname\n", "")
result = system_info.get_os_info()
self.assertIn("platform", result)
self.assertIn("machine", result)
def test_get_cpu_info(self):
result = system_info.get_cpu_info()
self.assertIn("model", result)
# 在大多数系统上应该能获取到一些信息
self.assertIsInstance(result["model"], str)
def test_get_memory_info(self):
result = system_info.get_memory_info()
self.assertIn("total_gb", result)
self.assertIsInstance(result["total_gb"], (int, float))
def test_get_system_info(self):
result = system_info.get_system_info()
self.assertIn("status", result)
self.assertIn("cpu", result)
self.assertIn("memory", result)
class TestCPU(unittest.TestCase):
"""测试 CPU 模块"""
def test_get_cpu_details(self):
result = cpu.get_cpu_details()
self.assertIn("model", result)
self.assertIn("cores", result)
self.assertIsInstance(result["cores"], int)
def test_get_cpu_temperature(self):
result = cpu.get_cpu_temperature()
self.assertIn("status", result)
self.assertIn("sensors", result)
def test_get_load_average(self):
result = cpu.get_load_average()
self.assertIn("1min", result)
self.assertIn("5min", result)
self.assertIn("15min", result)
def test_check_mce_errors(self):
result = cpu.check_mce_errors()
self.assertIn("count", result)
self.assertIn("status", result)
class TestMemory(unittest.TestCase):
"""测试内存模块"""
def test_get_memory_summary(self):
result = memory.get_memory_summary()
self.assertIn("total_bytes", result)
self.assertIn("total_gb", result)
self.assertIsInstance(result["total_gb"], (int, float))
def test_get_dimm_info(self):
result = memory.get_dimm_info()
self.assertIsInstance(result, list)
def test_check_ecc_status(self):
result = memory.check_ecc_status()
self.assertIn("supported", result)
self.assertIsInstance(result["supported"], bool)
def test_check_edac_errors(self):
result = memory.check_edac_errors()
self.assertIn("total_errors", result)
self.assertIsInstance(result["total_errors"], int)
class TestStorage(unittest.TestCase):
"""测试存储模块"""
def test_get_storage_devices(self):
result = storage.get_storage_devices()
self.assertIsInstance(result, list)
def test_check_raid_status(self):
result = storage.check_raid_status()
self.assertIn("arrays", result)
self.assertIsInstance(result["arrays"], list)
def test_get_io_statistics(self):
result = storage.get_io_statistics()
self.assertIsInstance(result, dict)
class TestSensors(unittest.TestCase):
"""测试传感器模块"""
def test_get_lm_sensors_data(self):
result = sensors.get_lm_sensors_data()
self.assertIn("available", result)
def test_get_thermal_zones(self):
result = sensors.get_thermal_zones()
self.assertIn("zones", result)
self.assertIsInstance(result["zones"], dict)
def test_get_power_supply_info(self):
result = sensors.get_power_supply_info()
self.assertIn("supplies", result)
self.assertIsInstance(result["supplies"], list)
class TestGPU(unittest.TestCase):
"""测试 GPU 模块"""
def test_check_generic_gpus(self):
result = gpu.check_generic_gpus()
self.assertIsInstance(result, list)
def test_check_gpu_dmesg_errors(self):
result = gpu.check_gpu_dmesg_errors()
self.assertIsInstance(result, list)
class TestLogAnalyzer(unittest.TestCase):
"""测试日志分析模块"""
def test_get_kernel_panic_logs(self):
result = log_analyzer.get_kernel_panic_logs()
self.assertIsInstance(result, list)
def test_get_hardware_error_logs(self):
result = log_analyzer.get_hardware_error_logs()
self.assertIn("mce_errors", result)
self.assertIn("ecc_errors", result)
self.assertIn("io_errors", result)
def test_summarize_errors(self):
test_data = {
"dmesg_analysis": {
"error_counts": {
"cpu_errors": 5,
"memory_errors": 3
}
},
"journal_analysis": {
"error_counts": {
"cpu_errors": 2,
"memory_errors": 1
}
}
}
result = log_analyzer.summarize_errors(test_data)
self.assertEqual(result["cpu_errors"], 7)
self.assertEqual(result["memory_errors"], 4)
if __name__ == '__main__':
unittest.main()

94
tests/test_utils.py Normal file
View File

@@ -0,0 +1,94 @@
"""
测试 utils 模块
"""
import unittest
import sys
import os
# 添加父目录到路径
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils import (
parse_key_value_output, parse_table_output, extract_with_regex,
safe_int, safe_float, format_bytes, sanitize_filename,
merge_dicts, check_command_exists
)
class TestParseFunctions(unittest.TestCase):
"""测试解析函数"""
def test_parse_key_value_output(self):
text = """
Key1: Value1
Key2: Value2
# Comment line
Key3: Value with: colon
"""
result = parse_key_value_output(text)
self.assertEqual(result["Key1"], "Value1")
self.assertEqual(result["Key2"], "Value2")
self.assertEqual(result["Key3"], "Value with: colon")
def test_parse_table_output(self):
text = """
NAME SIZE TYPE MODEL
sda 1T disk Samsung SSD
sdb 2T disk WD HDD
"""
result = parse_table_output(text, headers=["NAME", "SIZE", "TYPE", "MODEL"])
self.assertEqual(len(result), 2)
self.assertEqual(result[0]["NAME"], "sda")
self.assertEqual(result[1]["TYPE"], "disk")
def test_extract_with_regex(self):
text = "Temperature: 45.5 degrees"
result = extract_with_regex(text, r'Temperature:\s*([\d.]+)')
self.assertEqual(result, "45.5")
def test_safe_int(self):
self.assertEqual(safe_int("123"), 123)
self.assertEqual(safe_int("123.5"), 123)
self.assertEqual(safe_int("1,234"), 1234)
self.assertEqual(safe_int("32 GB"), 32)
self.assertEqual(safe_int("invalid"), 0)
self.assertEqual(safe_int("invalid", -1), -1)
def test_safe_float(self):
self.assertEqual(safe_float("123.5"), 123.5)
self.assertEqual(safe_float("2.5GHz"), 2.5)
self.assertEqual(safe_float("invalid"), 0.0)
def test_format_bytes(self):
self.assertEqual(format_bytes(0), "0 B")
self.assertEqual(format_bytes(1024), "1.00 KB")
self.assertEqual(format_bytes(1024**2), "1.00 MB")
self.assertEqual(format_bytes(1024**3), "1.00 GB")
def test_sanitize_filename(self):
self.assertEqual(sanitize_filename("file<name>.txt"), "file_name_.txt")
self.assertEqual(sanitize_filename("path/to/file"), "path/to/file")
def test_merge_dicts(self):
base = {"a": 1, "b": {"c": 2}}
update = {"b": {"d": 3}, "e": 4}
result = merge_dicts(base, update)
self.assertEqual(result["a"], 1)
self.assertEqual(result["b"]["c"], 2)
self.assertEqual(result["b"]["d"], 3)
self.assertEqual(result["e"], 4)
class TestCommandFunctions(unittest.TestCase):
"""测试命令相关函数"""
def test_check_command_exists(self):
# ls 应该存在
self.assertTrue(check_command_exists("ls"))
# 不存在的命令
self.assertFalse(check_command_exists("nonexistent_command_12345"))
if __name__ == '__main__':
unittest.main()