main
py 89 lines 2.99 KB
Raw
1 from __future__ import annotations
2
3 import httpx
4 import pytest
5 from pydantic import ValidationError
6
7 from app.portfolio_orchestration import (
8 PortfolioResearchOrchestrator,
9 PortfolioServiceUnavailableError,
10 )
11 from app.settings import Settings
12
13
14 def _orchestrator(settings: Settings, client: httpx.AsyncClient) -> PortfolioResearchOrchestrator:
15 return PortfolioResearchOrchestrator(
16 object(),
17 settings,
18 client=client,
19 structured_provider=object(),
20 )
21
22
23 @pytest.mark.asyncio
24 async def test_only_nifty_reference_refresh_uses_dedicated_timeout() -> None:
25 requests: list[httpx.Request] = []
26
27 def handler(request: httpx.Request) -> httpx.Response:
28 requests.append(request)
29 if request.method == "GET":
30 return httpx.Response(200, json={"instruments": [], "totalElements": 0})
31 return httpx.Response(200, json={"activeUniverse": 498})
32
33 settings = Settings(
34 _env_file=None,
35 research_request_timeout_seconds=10.0,
36 research_connect_timeout_seconds=3.0,
37 market_data_nifty_refresh_timeout_seconds=30.0,
38 )
39 client = httpx.AsyncClient(
40 transport=httpx.MockTransport(handler),
41 timeout=httpx.Timeout(10.0, connect=3.0),
42 )
43 try:
44 assert await _orchestrator(settings, client).india_nifty500_universe() == []
45 result = await _orchestrator(settings, client).refresh_india_nifty500_reference()
46 finally:
47 await client.aclose()
48
49 assert result == {"activeUniverse": 498}
50 assert requests[0].extensions["timeout"] == {
51 "connect": 3.0,
52 "read": 10.0,
53 "write": 10.0,
54 "pool": 10.0,
55 }
56 assert requests[1].extensions["timeout"] == {
57 "connect": 3.0,
58 "read": 30.0,
59 "write": 30.0,
60 "pool": 30.0,
61 }
62
63
64 @pytest.mark.asyncio
65 async def test_nifty_reference_refresh_timeout_remains_service_unavailable() -> None:
66 def handler(request: httpx.Request) -> httpx.Response:
67 raise httpx.ReadTimeout("fixture refresh timeout", request=request)
68
69 settings = Settings(_env_file=None, market_data_nifty_refresh_timeout_seconds=30.0)
70 client = httpx.AsyncClient(transport=httpx.MockTransport(handler))
71 try:
72 with pytest.raises(PortfolioServiceUnavailableError) as captured:
73 await _orchestrator(settings, client).refresh_india_nifty500_reference()
74 finally:
75 await client.aclose()
76
77 assert isinstance(captured.value.__cause__, httpx.ReadTimeout)
78
79
80 def test_nifty_reference_refresh_timeout_setting_uses_aip_environment(monkeypatch) -> None:
81 monkeypatch.setenv("AIP_MARKET_DATA_NIFTY_REFRESH_TIMEOUT_SECONDS", "45")
82
83 assert Settings(_env_file=None).market_data_nifty_refresh_timeout_seconds == 45.0
84
85
86 @pytest.mark.parametrize("value", [9.99, 120.01])
87 def test_nifty_reference_refresh_timeout_setting_is_bounded(value: float) -> None:
88 with pytest.raises(ValidationError, match="must be between 10 and 120"):
89 Settings(_env_file=None, market_data_nifty_refresh_timeout_seconds=value)