115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
|
|
"""Tests for _resolve_user_id_from_request in unity_transport.py."""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
import types
|
||
|
|
from unittest.mock import AsyncMock
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from core.config import config
|
||
|
|
from services.api_key_service import ApiKeyService, ValidationResult
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.fixture(autouse=True)
|
||
|
|
def _reset_api_key_singleton():
|
||
|
|
ApiKeyService._instance = None
|
||
|
|
yield
|
||
|
|
ApiKeyService._instance = None
|
||
|
|
|
||
|
|
|
||
|
|
class TestResolveUserIdFromRequest:
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_returns_none_when_not_remote_hosted(self, monkeypatch):
|
||
|
|
monkeypatch.setattr(config, "http_remote_hosted", False)
|
||
|
|
|
||
|
|
from transport.unity_transport import _resolve_user_id_from_request
|
||
|
|
|
||
|
|
result = await _resolve_user_id_from_request()
|
||
|
|
assert result is None
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_returns_none_when_service_not_initialized(self, monkeypatch):
|
||
|
|
monkeypatch.setattr(config, "http_remote_hosted", True)
|
||
|
|
# ApiKeyService._instance is None (from fixture)
|
||
|
|
|
||
|
|
from transport.unity_transport import _resolve_user_id_from_request
|
||
|
|
|
||
|
|
result = await _resolve_user_id_from_request()
|
||
|
|
assert result is None
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_returns_user_id_for_valid_key(self, monkeypatch):
|
||
|
|
monkeypatch.setattr(config, "http_remote_hosted", True)
|
||
|
|
|
||
|
|
svc = ApiKeyService(validation_url="https://auth.example.com/validate")
|
||
|
|
svc.validate = AsyncMock(
|
||
|
|
return_value=ValidationResult(valid=True, user_id="user-123")
|
||
|
|
)
|
||
|
|
|
||
|
|
# Stub the fastmcp dependency that provides HTTP headers
|
||
|
|
deps_mod = types.ModuleType("fastmcp.server.dependencies")
|
||
|
|
deps_mod.get_http_headers = lambda include_all=False: {
|
||
|
|
"x-api-key": "sk-valid"}
|
||
|
|
monkeypatch.setitem(
|
||
|
|
sys.modules, "fastmcp.server.dependencies", deps_mod)
|
||
|
|
|
||
|
|
from transport.unity_transport import _resolve_user_id_from_request
|
||
|
|
|
||
|
|
result = await _resolve_user_id_from_request()
|
||
|
|
assert result == "user-123"
|
||
|
|
svc.validate.assert_called_once_with("sk-valid")
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_returns_none_for_invalid_key(self, monkeypatch):
|
||
|
|
monkeypatch.setattr(config, "http_remote_hosted", True)
|
||
|
|
|
||
|
|
svc = ApiKeyService(validation_url="https://auth.example.com/validate")
|
||
|
|
svc.validate = AsyncMock(
|
||
|
|
return_value=ValidationResult(valid=False, error="bad key")
|
||
|
|
)
|
||
|
|
|
||
|
|
deps_mod = types.ModuleType("fastmcp.server.dependencies")
|
||
|
|
deps_mod.get_http_headers = lambda include_all=False: {
|
||
|
|
"x-api-key": "sk-bad"}
|
||
|
|
monkeypatch.setitem(
|
||
|
|
sys.modules, "fastmcp.server.dependencies", deps_mod)
|
||
|
|
|
||
|
|
from transport.unity_transport import _resolve_user_id_from_request
|
||
|
|
|
||
|
|
result = await _resolve_user_id_from_request()
|
||
|
|
assert result is None
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_returns_none_on_exception(self, monkeypatch):
|
||
|
|
monkeypatch.setattr(config, "http_remote_hosted", True)
|
||
|
|
|
||
|
|
svc = ApiKeyService(validation_url="https://auth.example.com/validate")
|
||
|
|
svc.validate = AsyncMock(side_effect=RuntimeError("boom"))
|
||
|
|
|
||
|
|
deps_mod = types.ModuleType("fastmcp.server.dependencies")
|
||
|
|
deps_mod.get_http_headers = lambda include_all=False: {
|
||
|
|
"x-api-key": "sk-err"}
|
||
|
|
monkeypatch.setitem(
|
||
|
|
sys.modules, "fastmcp.server.dependencies", deps_mod)
|
||
|
|
|
||
|
|
from transport.unity_transport import _resolve_user_id_from_request
|
||
|
|
|
||
|
|
result = await _resolve_user_id_from_request()
|
||
|
|
assert result is None
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_returns_none_when_no_api_key_header(self, monkeypatch):
|
||
|
|
monkeypatch.setattr(config, "http_remote_hosted", True)
|
||
|
|
|
||
|
|
ApiKeyService(validation_url="https://auth.example.com/validate")
|
||
|
|
|
||
|
|
deps_mod = types.ModuleType("fastmcp.server.dependencies")
|
||
|
|
deps_mod.get_http_headers = lambda include_all=False: {} # No x-api-key
|
||
|
|
monkeypatch.setitem(
|
||
|
|
sys.modules, "fastmcp.server.dependencies", deps_mod)
|
||
|
|
|
||
|
|
from transport.unity_transport import _resolve_user_id_from_request
|
||
|
|
|
||
|
|
result = await _resolve_user_id_from_request()
|
||
|
|
assert result is None
|