mirror of
https://github.com/rookiestar28/ComfyUI-OpenClaw.git
synced 2026-08-14 00:48:07 +00:00
119 lines
4.0 KiB
Python
119 lines
4.0 KiB
Python
"""
|
|
Unit tests for R85 Bridge Handshake (N/N-1 Policy).
|
|
"""
|
|
|
|
import unittest
|
|
|
|
from services.bridge_handshake import verify_handshake
|
|
from services.sidecar.bridge_contract import BRIDGE_PROTOCOL_VERSION
|
|
|
|
|
|
class TestBridgeHandshake(unittest.TestCase):
|
|
|
|
def test_exact_match(self):
|
|
"""Current version (N) should pass."""
|
|
ok, msg, meta = verify_handshake(BRIDGE_PROTOCOL_VERSION)
|
|
self.assertTrue(ok)
|
|
# Handle cases where server_version might match client_version
|
|
self.assertEqual(meta["server_version"], BRIDGE_PROTOCOL_VERSION)
|
|
|
|
def test_n_minus_one(self):
|
|
"""Previous version (N-1) should pass."""
|
|
if BRIDGE_PROTOCOL_VERSION > 1:
|
|
prev_ver = BRIDGE_PROTOCOL_VERSION - 1
|
|
ok, msg, meta = verify_handshake(prev_ver)
|
|
self.assertTrue(ok)
|
|
self.assertEqual(meta["client_version"], prev_ver)
|
|
else:
|
|
# If version is 1, N-1 is 0 which might be rejected if min_supported is 1
|
|
# verify_handshake implementation uses max(1, server-1)
|
|
# So if server=1, min=1. Client 0 should fail.
|
|
pass
|
|
|
|
def test_too_old(self):
|
|
"""Version < N-1 should fail."""
|
|
# Force a drift scenario
|
|
server_ver = BRIDGE_PROTOCOL_VERSION
|
|
min_ver = max(1, server_ver - 1)
|
|
|
|
if min_ver > 1:
|
|
too_old = min_ver - 1
|
|
ok, msg, meta = verify_handshake(too_old)
|
|
self.assertFalse(ok)
|
|
self.assertIn("too old", msg)
|
|
|
|
def test_too_new(self):
|
|
"""Version > N should fail."""
|
|
future_ver = BRIDGE_PROTOCOL_VERSION + 1
|
|
ok, msg, meta = verify_handshake(future_ver)
|
|
self.assertFalse(ok)
|
|
self.assertIn("newer than server", msg)
|
|
|
|
|
|
import asyncio
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
|
|
class TestBridgeClient(unittest.TestCase):
|
|
def setUp(self):
|
|
self.client = MagicMock()
|
|
# We'll mock the internal machinery of BridgeClient for isolation
|
|
# But importing it is better to test the actual logic
|
|
pass
|
|
|
|
@patch("aiohttp.ClientSession.post")
|
|
def test_client_handshake_success(self, mock_post):
|
|
"""Test client handles specific 200 OK handshake."""
|
|
# Need to import BridgeClient locally to avoid import errors if deps missing
|
|
try:
|
|
from services.sidecar.bridge_client import BridgeClient
|
|
except ImportError:
|
|
self.skipTest("aiohttp or internal modules missing")
|
|
|
|
# Mock Response
|
|
mock_resp = AsyncMock()
|
|
mock_resp.status = 200
|
|
mock_resp.json.return_value = {"ok": True, "message": "Compatible"}
|
|
mock_post.return_value.__aenter__.return_value = mock_resp
|
|
|
|
client = BridgeClient("http://test", "token", "worker1")
|
|
client.session = MagicMock()
|
|
client.session.post.return_value.__aenter__.return_value = mock_resp
|
|
|
|
# Run async test
|
|
loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(loop)
|
|
try:
|
|
result = loop.run_until_complete(client.perform_handshake())
|
|
self.assertTrue(result)
|
|
finally:
|
|
loop.close()
|
|
|
|
@patch("aiohttp.ClientSession.post")
|
|
def test_client_handshake_fail(self, mock_post):
|
|
"""Test client raises error on 409 Conflict."""
|
|
try:
|
|
from services.sidecar.bridge_client import BridgeClient
|
|
except ImportError:
|
|
self.skipTest("aiohttp or internal modules missing")
|
|
|
|
mock_resp = AsyncMock()
|
|
mock_resp.status = 409
|
|
mock_resp.json.return_value = {"ok": False, "message": "Version mismatch"}
|
|
|
|
client = BridgeClient("http://test", "token", "worker1")
|
|
client.session = MagicMock()
|
|
client.session.post.return_value.__aenter__.return_value = mock_resp
|
|
|
|
loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(loop)
|
|
try:
|
|
with self.assertRaises(RuntimeError):
|
|
loop.run_until_complete(client.perform_handshake())
|
|
finally:
|
|
loop.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|