test_server.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import json
  2. import threading
  3. import unittest
  4. from http.server import ThreadingHTTPServer
  5. from pathlib import Path
  6. from urllib import request as urlrequest
  7. from unittest.mock import patch
  8. from config import AppConfig
  9. class StartSsoProxyTests(unittest.TestCase):
  10. def _post_json(self, url, payload):
  11. data = json.dumps(payload).encode("utf-8")
  12. req = urlrequest.Request(url, data=data, method="POST", headers={"Content-Type": "application/json"})
  13. try:
  14. with urlrequest.urlopen(req, timeout=5) as resp:
  15. return resp.status, json.loads(resp.read().decode("utf-8"))
  16. except urlrequest.HTTPError as exc:
  17. return exc.code, json.loads(exc.read().decode("utf-8"))
  18. def test_start_sso_does_not_inherit_global_proxy_by_default(self):
  19. import server
  20. cfg = AppConfig(
  21. proxy_url="http://global.proxy:8080",
  22. sso_mail_domain="aef.claudeai.life",
  23. cpa_url="http://cpa.example",
  24. cpa_management_key="token",
  25. )
  26. httpd = ThreadingHTTPServer(("127.0.0.1", 0), server.Handler)
  27. thread = threading.Thread(target=httpd.serve_forever, daemon=True)
  28. with patch("server.AppConfig.load", return_value=cfg), patch.object(server.JOB, "start_sso", return_value="") as start_sso:
  29. thread.start()
  30. self.addCleanup(thread.join, 2)
  31. self.addCleanup(httpd.server_close)
  32. self.addCleanup(httpd.shutdown)
  33. status, body = self._post_json(
  34. f"http://127.0.0.1:{httpd.server_address[1]}/api/start-sso",
  35. {"account_count": 1, "cpa_url": "http://cpa.example", "cpa_management_key": "token"},
  36. )
  37. self.assertEqual(status, 200)
  38. self.assertTrue(body["ok"])
  39. self.assertEqual(start_sso.call_args.kwargs["proxy_url"], "")
  40. class DeprecatedFullAutomationTests(unittest.TestCase):
  41. def _post_json(self, url, payload=None):
  42. data = json.dumps(payload or {}).encode("utf-8")
  43. req = urlrequest.Request(url, data=data, method="POST", headers={"Content-Type": "application/json"})
  44. try:
  45. with urlrequest.urlopen(req, timeout=5) as resp:
  46. return resp.status, json.loads(resp.read().decode("utf-8"))
  47. except urlrequest.HTTPError as exc:
  48. return exc.code, json.loads(exc.read().decode("utf-8"))
  49. def _serve(self):
  50. import server
  51. httpd = ThreadingHTTPServer(("127.0.0.1", 0), server.Handler)
  52. thread = threading.Thread(target=httpd.serve_forever, daemon=True)
  53. thread.start()
  54. self.addCleanup(thread.join, 2)
  55. self.addCleanup(httpd.server_close)
  56. self.addCleanup(httpd.shutdown)
  57. return httpd
  58. def test_start_endpoint_is_disabled_for_full_automation(self):
  59. import server
  60. httpd = self._serve()
  61. status, body = self._post_json(f"http://127.0.0.1:{httpd.server_address[1]}/api/start")
  62. self.assertEqual(status, 410)
  63. self.assertIn("已停用", body["error"])
  64. self.assertFalse(hasattr(server.JOB, "start"))
  65. def test_tasks_api_rejects_full_mode_without_creating_task(self):
  66. import server
  67. httpd = self._serve()
  68. with patch("server.create_task") as create_task:
  69. status, body = self._post_json(
  70. f"http://127.0.0.1:{httpd.server_address[1]}/api/tasks",
  71. {"mode": "full"},
  72. )
  73. self.assertEqual(status, 410)
  74. self.assertIn("full", body["error"])
  75. create_task.assert_not_called()
  76. def test_status_does_not_expose_pool_maintainer(self):
  77. import server
  78. self.assertNotIn("pool_maintainer", server.JOB.status())
  79. def test_server_no_longer_starts_pool_maintainer(self):
  80. server_py = Path(__file__).resolve().parent.joinpath("server.py").read_text(encoding="utf-8")
  81. self.assertNotIn("start_pool_maintainer", server_py)
  82. if __name__ == "__main__":
  83. unittest.main()