Skip to content

Commit 8362711

Browse files
author
matdev83
committed
Manual Merge PR #632
1 parent ea5cf5e commit 8362711

File tree

4 files changed

+92
-2
lines changed

4 files changed

+92
-2
lines changed

data/test_suite_state.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"test_count": 5068,
2+
"test_count": 5072,
33
"last_updated": "1762168167.0802596"
44
}

src/connectors/qwen_oauth.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,5 +1346,20 @@ def __del__(self) -> None:
13461346
with contextlib.suppress(Exception):
13471347
self._stop_file_watching()
13481348

1349+
process = self._cli_refresh_process
1350+
if process is not None:
1351+
try:
1352+
if process.poll() is None:
1353+
process.terminate()
1354+
process.wait(timeout=5)
1355+
except subprocess.TimeoutExpired:
1356+
process.kill()
1357+
process.wait(timeout=5)
1358+
except Exception:
1359+
# interpreter shutdown
1360+
pass
1361+
finally:
1362+
self._cli_refresh_process = None
1363+
13491364

13501365
backend_registry.register_backend("qwen-oauth", QwenOAuthConnector)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""Unit tests for Qwen OAuth connector cleanup behavior."""
2+
3+
from __future__ import annotations
4+
5+
import subprocess
6+
from unittest.mock import AsyncMock, Mock, patch
7+
8+
import httpx
9+
import pytest
10+
from src.connectors.qwen_oauth import QwenOAuthConnector
11+
from src.core.config.app_config import AppConfig
12+
13+
14+
@pytest.fixture
15+
def connector() -> QwenOAuthConnector:
16+
"""Create a QwenOAuthConnector instance for testing cleanup logic."""
17+
18+
mock_client = AsyncMock(spec=httpx.AsyncClient)
19+
return QwenOAuthConnector(mock_client, config=AppConfig())
20+
21+
22+
def test_cleanup_stops_file_watching_and_terminates_process(
23+
connector: QwenOAuthConnector,
24+
) -> None:
25+
"""Connector cleanup should stop file watching and terminate CLI refresh process."""
26+
27+
mock_process = Mock()
28+
mock_process.poll.return_value = None
29+
connector._cli_refresh_process = mock_process
30+
31+
with patch.object(connector, "_stop_file_watching") as mock_stop:
32+
connector.__del__()
33+
mock_stop.assert_called_once()
34+
35+
mock_process.terminate.assert_called_once()
36+
assert mock_process.wait.call_count >= 1
37+
assert connector._cli_refresh_process is None
38+
39+
40+
def test_cleanup_kills_hung_cli_refresh_process(
41+
connector: QwenOAuthConnector,
42+
) -> None:
43+
"""Connector cleanup should kill CLI process if terminate does not finish it."""
44+
45+
mock_process = Mock()
46+
mock_process.poll.return_value = None
47+
mock_process.wait.side_effect = [
48+
subprocess.TimeoutExpired(cmd="qwen", timeout=5),
49+
None,
50+
]
51+
connector._cli_refresh_process = mock_process
52+
53+
connector.__del__()
54+
55+
mock_process.terminate.assert_called_once()
56+
mock_process.kill.assert_called_once()
57+
assert mock_process.wait.call_count == 2
58+
assert connector._cli_refresh_process is None
59+
60+
61+
def test_cleanup_ignores_errors_during_shutdown(
62+
connector: QwenOAuthConnector,
63+
) -> None:
64+
"""Exceptions while stopping watchers or processes should be suppressed."""
65+
66+
connector._cli_refresh_process = Mock()
67+
connector._cli_refresh_process.poll.side_effect = RuntimeError("boom")
68+
69+
with patch.object(
70+
connector, "_stop_file_watching", side_effect=Exception("watch error")
71+
):
72+
connector.__del__()
73+
74+
# Process attribute should be cleared even when errors occur
75+
assert connector._cli_refresh_process is None

tests/unit/core/services/test_tool_call_reactor_middleware.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from unittest.mock import AsyncMock
21
import json
2+
from unittest.mock import AsyncMock
33

44
import pytest
55
from src.core.domain.chat import ChatMessage, FunctionCall, ToolCall

0 commit comments

Comments
 (0)