Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions router/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1291,10 +1291,11 @@ async def classify_request(
return "agent-advanced-core", latency, False, "advanced (exception)"


def _read_json_file_sync(file_path: str) -> dict:
"""Helper to read JSON files synchronously."""
with open(file_path, "r") as f:
return json.load(f)
async def _read_json_file_async(file_path: str) -> dict:
"""Helper to read JSON files asynchronously."""
async with aiofiles.open(file_path, "r", encoding="utf-8") as f:
content = await f.read()
return json.loads(content)



Expand All @@ -1307,7 +1308,7 @@ async def get_gemini_oauth_status() -> dict:
"detail": "No oauth_creds.json found",
"expiry_ms": 0,
}
data = await asyncio.to_thread(_read_json_file_sync, GEMINI_OAUTH_CREDS_PATH)
data = await _read_json_file_async(GEMINI_OAUTH_CREDS_PATH)
access_token = data.get("access_token")
expiry_ms = data.get("expiry_date", 0)
current_ms = int(time.time() * 1000)
Expand Down
14 changes: 10 additions & 4 deletions router/tests/test_get_gemini_oauth_status.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
import json
from unittest.mock import patch, mock_open
from unittest.mock import patch, AsyncMock

from router import main

Expand All @@ -13,8 +13,11 @@ async def test_get_gemini_oauth_status_missing_file():
@pytest.mark.asyncio
async def test_get_gemini_oauth_status_no_access_token():
mock_data = {"expiry_date": 1234567890000}
mock_file = AsyncMock()
mock_file.read.return_value = json.dumps(mock_data)
mock_file.__aenter__.return_value = mock_file
with patch("os.path.exists", return_value=True), \
patch("builtins.open", mock_open(read_data=json.dumps(mock_data))):
patch("aiofiles.open", return_value=mock_file):
result = await main.get_gemini_oauth_status()
assert result == {"status": "missing", "detail": "No access token in file", "expiry_ms": 0}

Expand All @@ -31,15 +34,18 @@ async def test_get_gemini_oauth_status_scenarios(delta, expected_status, expecte
current_time_ms = 1000000000000
expiry_ms = current_time_ms + delta
mock_data = {"access_token": "test_token", "expiry_date": expiry_ms}
mock_file = AsyncMock()
mock_file.read.return_value = json.dumps(mock_data)
mock_file.__aenter__.return_value = mock_file
with patch("os.path.exists", return_value=True), \
patch("builtins.open", mock_open(read_data=json.dumps(mock_data))), \
patch("aiofiles.open", return_value=mock_file), \
patch("time.time", return_value=current_time_ms / 1000.0):
result = await main.get_gemini_oauth_status()
assert result == {"status": expected_status, "detail": expected_detail, "expiry_ms": expiry_ms}

@pytest.mark.asyncio
async def test_get_gemini_oauth_status_exception():
with patch("os.path.exists", return_value=True), \
patch("builtins.open", side_effect=Exception("Test error")):
patch("aiofiles.open", side_effect=Exception("Test error")):
result = await main.get_gemini_oauth_status()
assert result == {"status": "error", "detail": "Test error", "expiry_ms": 0}
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import json
from unittest.mock import mock_open, patch
from unittest.mock import patch, AsyncMock
import pytest

from router import main


def test_read_json_file_sync_success():
@pytest.mark.asyncio
async def test_read_json_file_async_success():
mock_data = '{"key": "value"}'
with patch("builtins.open", mock_open(read_data=mock_data)):
result = main._read_json_file_sync("dummy_path.json")
mock_file = AsyncMock()
mock_file.read.return_value = mock_data
mock_file.__aenter__.return_value = mock_file
with patch("aiofiles.open", return_value=mock_file):
result = await main._read_json_file_async("dummy_path.json")
assert result == {"key": "value"}


@pytest.mark.parametrize(
"mock_kwargs, expected_exc, match_msg",
[
(
{"new": mock_open(read_data='{"key": "value"')},
{"return_value": AsyncMock(__aenter__=AsyncMock(return_value=AsyncMock(read=AsyncMock(return_value='{"key": "value"'))))},
json.JSONDecodeError,
r"Unterminated string starting at|Expecting",
),
Expand All @@ -32,7 +36,8 @@ def test_read_json_file_sync_success():
),
],
)
def test_read_json_file_sync_errors(mock_kwargs, expected_exc, match_msg):
with patch("builtins.open", **mock_kwargs):
@pytest.mark.asyncio
async def test_read_json_file_async_errors(mock_kwargs, expected_exc, match_msg):
with patch("aiofiles.open", **mock_kwargs):
with pytest.raises(expected_exc, match=match_msg):
main._read_json_file_sync("dummy_path.json")
await main._read_json_file_async("dummy_path.json")