feat(gateway)!: drop HTTP listener, run outbound agent only
- delete GatewayHTTPServer/GatewayHandler, create_server, /healthz and /v1/channel; event_channel module removed - load_config now requires CREATOR_PLATFORM_URL + CREATOR_GATEWAY_KEY - run() wires Gateway into OutboundAgent; SIGINT/SIGTERM stop the agent - deploy env example, install script, systemd unit docs and deployment docs updated to the outbound model; NATIVE_GATEWAY_ENDPOINT dead dev config removed
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
"""Server entry tests: outbound-only config and run() wiring."""
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from importlib import import_module
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
gateway_module = import_module(f"{__package__}.server.http")
|
||||
|
||||
load_config = gateway_module.load_config
|
||||
|
||||
|
||||
class OutboundConfigTests(unittest.TestCase):
|
||||
def test_platform_url_and_key_are_required(self) -> None:
|
||||
config = load_config({
|
||||
"CREATOR_PLATFORM_URL": "http://platform.example:8080",
|
||||
"CREATOR_GATEWAY_KEY": "0123456789abcdef",
|
||||
"BROWSER_PATH": "/bin/true",
|
||||
})
|
||||
self.assertEqual(config["platform_url"], "http://platform.example:8080")
|
||||
self.assertEqual(config["access_key"], "0123456789abcdef")
|
||||
self.assertNotIn("listen", config)
|
||||
self.assertNotIn("token", config)
|
||||
|
||||
def test_platform_url_must_be_http(self) -> None:
|
||||
with self.assertRaises(ValueError):
|
||||
load_config({
|
||||
"CREATOR_PLATFORM_URL": "ftp://platform.example",
|
||||
"CREATOR_GATEWAY_KEY": "0123456789abcdef",
|
||||
"BROWSER_PATH": "/bin/true",
|
||||
})
|
||||
|
||||
def test_platform_url_must_not_embed_agent_path(self) -> None:
|
||||
with self.assertRaises(ValueError):
|
||||
load_config({
|
||||
"CREATOR_PLATFORM_URL": "http://platform.example:8080/v1/agent",
|
||||
"CREATOR_GATEWAY_KEY": "0123456789abcdef",
|
||||
"BROWSER_PATH": "/bin/true",
|
||||
})
|
||||
|
||||
def test_access_key_minimum_length(self) -> None:
|
||||
with self.assertRaises(ValueError):
|
||||
load_config({
|
||||
"CREATOR_PLATFORM_URL": "http://platform.example:8080",
|
||||
"CREATOR_GATEWAY_KEY": "short",
|
||||
"BROWSER_PATH": "/bin/true",
|
||||
})
|
||||
|
||||
def test_trailing_slash_platform_url_is_normalized(self) -> None:
|
||||
config = load_config({
|
||||
"CREATOR_PLATFORM_URL": "http://platform.example:8080/",
|
||||
"CREATOR_GATEWAY_KEY": "0123456789abcdef",
|
||||
"BROWSER_PATH": "/bin/true",
|
||||
})
|
||||
self.assertEqual(config["platform_url"], "http://platform.example:8080")
|
||||
|
||||
|
||||
class RunWiringTests(unittest.TestCase):
|
||||
def test_run_builds_agent_from_config_and_stops_on_signal(self) -> None:
|
||||
config = load_config({
|
||||
"CREATOR_PLATFORM_URL": "http://platform.example:8080",
|
||||
"CREATOR_GATEWAY_KEY": "0123456789abcdef",
|
||||
"BROWSER_PATH": "/bin/true",
|
||||
})
|
||||
agent_instances = []
|
||||
|
||||
class FakeAgent:
|
||||
def __init__(self, gateway, agent_config) -> None:
|
||||
self.gateway = gateway
|
||||
self.config = agent_config
|
||||
self.ran = False
|
||||
self.stopped = False
|
||||
agent_instances.append(self)
|
||||
|
||||
def run(self) -> None:
|
||||
self.ran = True
|
||||
|
||||
def stop(self) -> None:
|
||||
self.stopped = True
|
||||
|
||||
registered = {}
|
||||
|
||||
def record_signal(signum, handler):
|
||||
registered[signum] = handler
|
||||
|
||||
with patch.object(gateway_module, "OutboundAgent", FakeAgent), \
|
||||
patch.object(gateway_module, "NativeRuntimeManager", Mock()), \
|
||||
patch.object(gateway_module.signal, "signal", record_signal):
|
||||
exit_code = gateway_module.run(config)
|
||||
self.assertEqual(exit_code, 0)
|
||||
self.assertEqual(len(agent_instances), 1)
|
||||
self.assertEqual(agent_instances[0].config.platform_url, config["platform_url"])
|
||||
self.assertEqual(agent_instances[0].config.access_key, config["access_key"])
|
||||
self.assertTrue(agent_instances[0].ran)
|
||||
# SIGINT/SIGTERM 都注册了停止回调,触发后 agent 收到 stop
|
||||
self.assertIn(gateway_module.signal.SIGINT, registered)
|
||||
self.assertIn(gateway_module.signal.SIGTERM, registered)
|
||||
registered[gateway_module.signal.SIGTERM](15, None)
|
||||
registered[gateway_module.signal.SIGINT](2, None)
|
||||
self.assertTrue(agent_instances[0].stopped)
|
||||
# Gateway 的业务方法必须仍挂在 agent 上(agent.gateway)
|
||||
self.assertIsNotNone(agent_instances[0].gateway.subscriptions)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user