已合并
【API】Add custom validation cases for HealthCheckServer APIs #34493
【API】Add custom validation cases for HealthCheckServer APIs #34493
已合并
Jinfan Liu创建于 4月27日
1 个文件变更+95-0
@@ -0,0 +1,95 @@
1+"""
2+Add validation cases for torch.distributed.elastic.agent.server.health_check_server APIs.
3+ 
4+1. PyTorch community tests do not cover HealthCheckServer APIs, so this file is added.
5+2. This file validates :
6+torch.distributed.elastic.agent.server.health_check_server.HealthCheckServer
7+torch.distributed.elastic.agent.server.health_check_server.HealthCheckServer.start
8+torch.distributed.elastic.agent.server.health_check_server.HealthCheckServer.stop
9+torch.distributed.elastic.agent.server.health_check_server.create_healthcheck_server
10+(extendable)
11+"""
12+ 
13+import logging
14+from unittest.mock import MagicMock
15+ 
16+from torch.distributed.elastic.agent.server.health_check_server import (
17+ HealthCheckServer,
18+ create_healthcheck_server,
19+)
20+from torch_npu.testing.testcase import TestCase, run_tests
21+ 
22+LOGGER_NAME = "torch.distributed.elastic.agent.server.health_check_server"
23+ 
24+ 
25+class TestHealthCheckServer(TestCase):
26+ """Unit tests for HealthCheckServer and factory method create_healthcheck_server."""
27+ 
28+ def test_init(self):
29+ """Test HealthCheckServer initialization, verify attributes are assigned correctly
30+ and callback is not called prematurely.
31+ """
32+ alive_callback = MagicMock(return_value=123)
33+ server = HealthCheckServer(alive_callback, 0, 30)
34+ 
35+ self.assertIs(server._alive_callback, alive_callback)
36+ self.assertEqual(server._port, 0)
37+ self.assertEqual(server._timeout, 30)
38+ alive_callback.assert_not_called()
39+ 
40+ def test_create_healthcheck_server(self):
41+ """Test the factory function create_healthcheck_server, returns a valid HealthCheckServer instance."""
42+ alive_callback = MagicMock(return_value=123)
43+ server = create_healthcheck_server(alive_callback, 0, 45)
44+ 
45+ self.assertIsInstance(server, HealthCheckServer)
46+ self.assertIs(server._alive_callback, alive_callback)
47+ self.assertEqual(server._port, 0)
48+ self.assertEqual(server._timeout, 45)
49+ alive_callback.assert_not_called()
50+ 
51+ def test_start_logs_warning(self):
52+ """Test start() outputs expected WARNING log (current noop stub behavior)."""
53+ server = HealthCheckServer(lambda: 0, 0, 30)
54+ 
55+ with self.assertLogs(LOGGER_NAME, level=logging.WARNING) as captured:
56+ server.start()
57+ 
58+ self.assertEqual(len(captured.records), 1)
59+ self.assertEqual(
60+ captured.records[0].getMessage(),
61+ "No health check server started",
62+ )
63+ 
64+ def test_stop_logs_info(self):
65+ """Test stop() outputs expected INFO log (current noop stub behavior)."""
66+ server = HealthCheckServer(lambda: 0, 0, 30)
67+ 
68+ with self.assertLogs(LOGGER_NAME, level=logging.INFO) as captured:
69+ server.stop()
70+ 
71+ self.assertEqual(len(captured.records), 1)
72+ self.assertEqual(
73+ captured.records[0].getMessage(),
74+ "Stopping noop health check server.",
75+ )
76+ 
77+ def test_start_stop_lifecycle_safe(self):
78+ """Verify start -> stop full lifecycle runs safely without exceptions."""
79+ server = HealthCheckServer(lambda: True, 0, 5)
80+ server.start()
81+ server.stop()
82+ # Passes if no exception is thrown, no additional assertions needed
83+ 
84+ def test_stop_idempotent(self):
85+ """Verify stop() is idempotent: repeated calls do not throw exceptions."""
86+ server = HealthCheckServer(lambda: True, 0, 5)
87+ server.start()
88+ server.stop()
89+ server.stop()
90+ server.stop()
91+ # Passes if no exception is thrown, no additional assertions needed
92+ 
93+ 
94+if __name__ == "__main__":
95+ run_tests()