Skip to content

Commit 486c21a

Browse files
Improving tests and handling one failure mode in memory
1 parent 9c19c02 commit 486c21a

3 files changed

Lines changed: 96 additions & 1 deletion

File tree

src/google/adk/integrations/firestore/firestore_memory_service.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,14 @@ async def search_memory(
169169
self._search_by_keyword(app_name, user_id, keyword)
170170
for keyword in keywords
171171
]
172-
results = await asyncio.gather(*tasks)
172+
results = await asyncio.gather(*tasks, return_exceptions=True)
173173

174174
seen = set()
175175
memories = []
176176
for result_list in results:
177+
if isinstance(result_list, Exception):
178+
logger.warning(f"Memory keyword search partial failure: {result_list}")
179+
continue
177180
for entry in result_list:
178181
content_text = ""
179182
if entry.content and entry.content.parts:

tests/unittests/integrations/firestore/test_firestore_memory_service.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,41 @@ async def test_search_memory_only_stop_words(mock_firestore_client):
201201
mock_firestore_client.collection.assert_not_called()
202202

203203

204+
@pytest.mark.asyncio
205+
async def test_search_memory_partial_failures(mock_firestore_client, caplog):
206+
service = FirestoreMemoryService(client=mock_firestore_client)
207+
app_name = "test_app"
208+
user_id = "test_user"
209+
query = "fox quick"
210+
211+
coll_ref = mock_firestore_client.collection.return_value.where.return_value.where.return_value.where.return_value
212+
213+
doc_snapshot = mock.MagicMock()
214+
doc_snapshot.to_dict.return_value = {
215+
"content": {"parts": [{"text": "quick response"}]},
216+
"author": "user",
217+
"timestamp": 1234567890.0
218+
}
219+
220+
call_count = 0
221+
async def mock_get():
222+
nonlocal call_count
223+
call_count += 1
224+
if call_count == 1:
225+
raise ValueError("Mock generic network failure standalone")
226+
return [doc_snapshot]
227+
228+
coll_ref.get = mock.AsyncMock(side_effect=mock_get)
229+
230+
response = await service.search_memory(
231+
app_name=app_name, user_id=user_id, query=query
232+
)
233+
234+
assert len(response.memories) == 1
235+
assert response.memories[0].author == "user"
236+
assert "Memory keyword search partial failure" in caplog.text
237+
238+
204239
def test_init_default_client():
205240
with mock.patch("google.cloud.firestore.AsyncClient") as mock_client_class:
206241
mock_instance = mock.MagicMock()

tests/unittests/integrations/firestore/test_firestore_session_service.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,63 @@ def collection_side_effect(name):
427427
)
428428

429429

430+
@pytest.mark.asyncio
431+
async def test_list_sessions_filters_other_apps(mock_firestore_client):
432+
service = FirestoreSessionService(client=mock_firestore_client)
433+
app_name = "test_app"
434+
435+
session_doc = mock.MagicMock()
436+
session_doc.to_dict.return_value = {
437+
"id": "session1",
438+
"appName": app_name,
439+
"userId": "user1",
440+
"state": {"session_key": "session_val"},
441+
}
442+
443+
mock_firestore_client.collection_group.return_value.where.return_value.get = (
444+
mock.AsyncMock(return_value=[session_doc])
445+
)
446+
447+
app_state_coll = mock.MagicMock()
448+
user_state_coll = mock.MagicMock()
449+
450+
def collection_side_effect(name):
451+
if name == service.app_state_collection:
452+
return app_state_coll
453+
elif name == service.user_state_collection:
454+
return user_state_coll
455+
return mock.MagicMock()
456+
457+
mock_firestore_client.collection.side_effect = collection_side_effect
458+
459+
app_doc = mock.MagicMock()
460+
app_doc.exists = True
461+
app_doc.to_dict.return_value = {"app_key": "app_val"}
462+
app_doc_ref = mock.MagicMock()
463+
app_state_coll.document.return_value = app_doc_ref
464+
app_doc_ref.get = mock.AsyncMock(return_value=app_doc)
465+
466+
user_doc = mock.MagicMock()
467+
user_doc.id = "user1"
468+
user_doc.to_dict.return_value = {"user_key": "user_val"}
469+
user_app_doc = mock.MagicMock()
470+
user_state_coll.document.return_value = user_app_doc
471+
users_coll = mock.MagicMock()
472+
user_app_doc.collection.return_value = users_coll
473+
users_coll.get = mock.AsyncMock(return_value=[user_doc])
474+
475+
response = await service.list_sessions(app_name=app_name)
476+
477+
assert len(response.sessions) == 1
478+
assert response.sessions[0].id == "session1"
479+
assert response.sessions[0].app_name == app_name
480+
481+
mock_firestore_client.collection_group.assert_called_once_with("sessions")
482+
mock_firestore_client.collection_group.return_value.where.assert_called_once_with(
483+
"appName", "==", app_name
484+
)
485+
486+
430487
@pytest.mark.asyncio
431488
async def test_create_session_already_exists(mock_firestore_client):
432489
service = FirestoreSessionService(client=mock_firestore_client)

0 commit comments

Comments
 (0)