test: make gateway async tests xdist-safe (#1281)
* feat: improve context compaction handoff summaries Adapt PR #916 onto current main by replacing the old context summary marker with a clearer handoff wrapper, updating the summarization prompt for resume-oriented summaries, and preserving the current call_llm-based compression path. * fix: clearer error when docker backend is unavailable * fix: preserve docker discovery in backend preflight Follow up on salvaged PR #940 by reusing find_docker() during the new availability check so non-PATH Docker Desktop installs still work. Add a regression test covering the resolved executable path. * test: make gateway async tests xdist-safe Replace sync test usage of asyncio.get_event_loop().run_until_complete() with asyncio.run() so tests do not depend on an ambient current event loop. Also create the email disconnect poll task inside a running loop. This fixes xdist/CI failures where workers have no current loop in MainThread. --------- Co-authored-by: aydnOktay <xaydinoktay@gmail.com>
This commit is contained in:
parent
29312a23d9
commit
b91cac7b4b
1 changed files with 25 additions and 22 deletions
|
|
@ -407,7 +407,7 @@ class TestDispatchMessage(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
adapter._message_handler.assert_not_called()
|
adapter._message_handler.assert_not_called()
|
||||||
|
|
||||||
def test_subject_included_in_text(self):
|
def test_subject_included_in_text(self):
|
||||||
|
|
@ -441,7 +441,7 @@ class TestDispatchMessage(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
self.assertEqual(len(captured_events), 1)
|
self.assertEqual(len(captured_events), 1)
|
||||||
self.assertIn("[Subject: Help with Python]", captured_events[0].text)
|
self.assertIn("[Subject: Help with Python]", captured_events[0].text)
|
||||||
self.assertIn("How do I use lists?", captured_events[0].text)
|
self.assertIn("How do I use lists?", captured_events[0].text)
|
||||||
|
|
@ -469,7 +469,7 @@ class TestDispatchMessage(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
self.assertEqual(len(captured_events), 1)
|
self.assertEqual(len(captured_events), 1)
|
||||||
self.assertNotIn("[Subject:", captured_events[0].text)
|
self.assertNotIn("[Subject:", captured_events[0].text)
|
||||||
self.assertEqual(captured_events[0].text, "Thanks for the help!")
|
self.assertEqual(captured_events[0].text, "Thanks for the help!")
|
||||||
|
|
@ -497,7 +497,7 @@ class TestDispatchMessage(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
self.assertEqual(len(captured_events), 1)
|
self.assertEqual(len(captured_events), 1)
|
||||||
self.assertIn("(empty email)", captured_events[0].text)
|
self.assertIn("(empty email)", captured_events[0].text)
|
||||||
|
|
||||||
|
|
@ -525,7 +525,7 @@ class TestDispatchMessage(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
self.assertEqual(len(captured_events), 1)
|
self.assertEqual(len(captured_events), 1)
|
||||||
self.assertEqual(captured_events[0].message_type, MessageType.PHOTO)
|
self.assertEqual(captured_events[0].message_type, MessageType.PHOTO)
|
||||||
self.assertEqual(captured_events[0].media_urls, ["/tmp/img.jpg"])
|
self.assertEqual(captured_events[0].media_urls, ["/tmp/img.jpg"])
|
||||||
|
|
@ -553,7 +553,7 @@ class TestDispatchMessage(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
event = captured_events[0]
|
event = captured_events[0]
|
||||||
self.assertEqual(event.source.chat_id, "john@example.com")
|
self.assertEqual(event.source.chat_id, "john@example.com")
|
||||||
self.assertEqual(event.source.user_id, "john@example.com")
|
self.assertEqual(event.source.user_id, "john@example.com")
|
||||||
|
|
@ -598,7 +598,7 @@ class TestThreadContext(unittest.TestCase):
|
||||||
"date": "",
|
"date": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._dispatch_message(msg_data))
|
asyncio.run(adapter._dispatch_message(msg_data))
|
||||||
ctx = adapter._thread_context.get("user@test.com")
|
ctx = adapter._thread_context.get("user@test.com")
|
||||||
self.assertIsNotNone(ctx)
|
self.assertIsNotNone(ctx)
|
||||||
self.assertEqual(ctx["subject"], "Project question")
|
self.assertEqual(ctx["subject"], "Project question")
|
||||||
|
|
@ -680,7 +680,7 @@ class TestSendMethods(unittest.TestCase):
|
||||||
mock_server = MagicMock()
|
mock_server = MagicMock()
|
||||||
mock_smtp.return_value = mock_server
|
mock_smtp.return_value = mock_server
|
||||||
|
|
||||||
result = asyncio.get_event_loop().run_until_complete(
|
result = asyncio.run(
|
||||||
adapter.send("user@test.com", "Hello from Hermes!")
|
adapter.send("user@test.com", "Hello from Hermes!")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -698,7 +698,7 @@ class TestSendMethods(unittest.TestCase):
|
||||||
with patch("smtplib.SMTP") as mock_smtp:
|
with patch("smtplib.SMTP") as mock_smtp:
|
||||||
mock_smtp.side_effect = Exception("Connection refused")
|
mock_smtp.side_effect = Exception("Connection refused")
|
||||||
|
|
||||||
result = asyncio.get_event_loop().run_until_complete(
|
result = asyncio.run(
|
||||||
adapter.send("user@test.com", "Hello")
|
adapter.send("user@test.com", "Hello")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -713,7 +713,7 @@ class TestSendMethods(unittest.TestCase):
|
||||||
|
|
||||||
adapter.send = AsyncMock(return_value=SendResult(success=True))
|
adapter.send = AsyncMock(return_value=SendResult(success=True))
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(
|
asyncio.run(
|
||||||
adapter.send_image("user@test.com", "https://img.com/photo.jpg", "My photo")
|
adapter.send_image("user@test.com", "https://img.com/photo.jpg", "My photo")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -737,7 +737,7 @@ class TestSendMethods(unittest.TestCase):
|
||||||
mock_server = MagicMock()
|
mock_server = MagicMock()
|
||||||
mock_smtp.return_value = mock_server
|
mock_smtp.return_value = mock_server
|
||||||
|
|
||||||
result = asyncio.get_event_loop().run_until_complete(
|
result = asyncio.run(
|
||||||
adapter.send_document("user@test.com", tmp_path, "Here is the file")
|
adapter.send_document("user@test.com", tmp_path, "Here is the file")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -759,7 +759,7 @@ class TestSendMethods(unittest.TestCase):
|
||||||
import asyncio
|
import asyncio
|
||||||
adapter = self._make_adapter()
|
adapter = self._make_adapter()
|
||||||
# Should not raise
|
# Should not raise
|
||||||
asyncio.get_event_loop().run_until_complete(adapter.send_typing("user@test.com"))
|
asyncio.run(adapter.send_typing("user@test.com"))
|
||||||
|
|
||||||
def test_get_chat_info(self):
|
def test_get_chat_info(self):
|
||||||
"""get_chat_info should return email address as chat info."""
|
"""get_chat_info should return email address as chat info."""
|
||||||
|
|
@ -767,7 +767,7 @@ class TestSendMethods(unittest.TestCase):
|
||||||
adapter = self._make_adapter()
|
adapter = self._make_adapter()
|
||||||
adapter._thread_context["user@test.com"] = {"subject": "Test", "message_id": "<m@t>"}
|
adapter._thread_context["user@test.com"] = {"subject": "Test", "message_id": "<m@t>"}
|
||||||
|
|
||||||
info = asyncio.get_event_loop().run_until_complete(
|
info = asyncio.run(
|
||||||
adapter.get_chat_info("user@test.com")
|
adapter.get_chat_info("user@test.com")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -804,7 +804,7 @@ class TestConnectDisconnect(unittest.TestCase):
|
||||||
mock_server = MagicMock()
|
mock_server = MagicMock()
|
||||||
mock_smtp.return_value = mock_server
|
mock_smtp.return_value = mock_server
|
||||||
|
|
||||||
result = asyncio.get_event_loop().run_until_complete(adapter.connect())
|
result = asyncio.run(adapter.connect())
|
||||||
|
|
||||||
self.assertTrue(result)
|
self.assertTrue(result)
|
||||||
self.assertTrue(adapter._running)
|
self.assertTrue(adapter._running)
|
||||||
|
|
@ -821,7 +821,7 @@ class TestConnectDisconnect(unittest.TestCase):
|
||||||
adapter = self._make_adapter()
|
adapter = self._make_adapter()
|
||||||
|
|
||||||
with patch("imaplib.IMAP4_SSL", side_effect=Exception("IMAP down")):
|
with patch("imaplib.IMAP4_SSL", side_effect=Exception("IMAP down")):
|
||||||
result = asyncio.get_event_loop().run_until_complete(adapter.connect())
|
result = asyncio.run(adapter.connect())
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
self.assertFalse(adapter._running)
|
self.assertFalse(adapter._running)
|
||||||
|
|
||||||
|
|
@ -835,7 +835,7 @@ class TestConnectDisconnect(unittest.TestCase):
|
||||||
|
|
||||||
with patch("imaplib.IMAP4_SSL", return_value=mock_imap), \
|
with patch("imaplib.IMAP4_SSL", return_value=mock_imap), \
|
||||||
patch("smtplib.SMTP", side_effect=Exception("SMTP down")):
|
patch("smtplib.SMTP", side_effect=Exception("SMTP down")):
|
||||||
result = asyncio.get_event_loop().run_until_complete(adapter.connect())
|
result = asyncio.run(adapter.connect())
|
||||||
self.assertFalse(result)
|
self.assertFalse(result)
|
||||||
|
|
||||||
def test_disconnect_cancels_poll(self):
|
def test_disconnect_cancels_poll(self):
|
||||||
|
|
@ -843,9 +843,12 @@ class TestConnectDisconnect(unittest.TestCase):
|
||||||
import asyncio
|
import asyncio
|
||||||
adapter = self._make_adapter()
|
adapter = self._make_adapter()
|
||||||
adapter._running = True
|
adapter._running = True
|
||||||
adapter._poll_task = asyncio.ensure_future(asyncio.sleep(100))
|
|
||||||
|
|
||||||
asyncio.get_event_loop().run_until_complete(adapter.disconnect())
|
async def _exercise_disconnect():
|
||||||
|
adapter._poll_task = asyncio.create_task(asyncio.sleep(100))
|
||||||
|
await adapter.disconnect()
|
||||||
|
|
||||||
|
asyncio.run(_exercise_disconnect())
|
||||||
|
|
||||||
self.assertFalse(adapter._running)
|
self.assertFalse(adapter._running)
|
||||||
self.assertIsNone(adapter._poll_task)
|
self.assertIsNone(adapter._poll_task)
|
||||||
|
|
@ -967,7 +970,7 @@ class TestPollLoop(unittest.TestCase):
|
||||||
mock_imap.fetch.return_value = ("OK", [(b"1", raw_email.as_bytes())])
|
mock_imap.fetch.return_value = ("OK", [(b"1", raw_email.as_bytes())])
|
||||||
|
|
||||||
with patch("imaplib.IMAP4_SSL", return_value=mock_imap):
|
with patch("imaplib.IMAP4_SSL", return_value=mock_imap):
|
||||||
asyncio.get_event_loop().run_until_complete(adapter._check_inbox())
|
asyncio.run(adapter._check_inbox())
|
||||||
|
|
||||||
self.assertEqual(len(dispatched), 1)
|
self.assertEqual(len(dispatched), 1)
|
||||||
self.assertEqual(dispatched[0]["subject"], "Inbox Test")
|
self.assertEqual(dispatched[0]["subject"], "Inbox Test")
|
||||||
|
|
@ -991,7 +994,7 @@ class TestSendEmailStandalone(unittest.TestCase):
|
||||||
mock_server = MagicMock()
|
mock_server = MagicMock()
|
||||||
mock_smtp.return_value = mock_server
|
mock_smtp.return_value = mock_server
|
||||||
|
|
||||||
result = asyncio.get_event_loop().run_until_complete(
|
result = asyncio.run(
|
||||||
_send_email({"address": "hermes@test.com", "smtp_host": "smtp.test.com"}, "user@test.com", "Hello")
|
_send_email({"address": "hermes@test.com", "smtp_host": "smtp.test.com"}, "user@test.com", "Hello")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1009,7 +1012,7 @@ class TestSendEmailStandalone(unittest.TestCase):
|
||||||
from tools.send_message_tool import _send_email
|
from tools.send_message_tool import _send_email
|
||||||
|
|
||||||
with patch("smtplib.SMTP", side_effect=Exception("SMTP error")):
|
with patch("smtplib.SMTP", side_effect=Exception("SMTP error")):
|
||||||
result = asyncio.get_event_loop().run_until_complete(
|
result = asyncio.run(
|
||||||
_send_email({"address": "hermes@test.com", "smtp_host": "smtp.test.com"}, "user@test.com", "Hello")
|
_send_email({"address": "hermes@test.com", "smtp_host": "smtp.test.com"}, "user@test.com", "Hello")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1022,7 +1025,7 @@ class TestSendEmailStandalone(unittest.TestCase):
|
||||||
import asyncio
|
import asyncio
|
||||||
from tools.send_message_tool import _send_email
|
from tools.send_message_tool import _send_email
|
||||||
|
|
||||||
result = asyncio.get_event_loop().run_until_complete(
|
result = asyncio.run(
|
||||||
_send_email({}, "user@test.com", "Hello")
|
_send_email({}, "user@test.com", "Hello")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue