Skip to content

Commit ec6d377

Browse files
committed
Add missing content formatter error test case
1 parent 04d278d commit ec6d377

File tree

1 file changed

+67
-15
lines changed

1 file changed

+67
-15
lines changed

tests/unittests/plugins/test_bigquery_agent_analytics_plugin.py

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -298,21 +298,23 @@ async def test_event_allowlist(
298298
mock_write_client.append_rows.assert_called_once()
299299
mock_write_client.append_rows.reset_mock()
300300

301-
# Re-init plugin logic since close() shuts it down, but for this test we want to test denial
302-
# However, close() cleans up clients. We should probably create a new plugin or just check that the task was not created.
303-
# But on_user_message_callback will try to log.
304-
# To keep it simple, let's just use a fresh plugin for the second part or assume close() resets state enough to re-run _ensure_init if needed,
305-
# but _ensure_init is called inside _perform_write.
306-
# Actually, close() sets _is_shutting_down to True, so further logs are ignored.
307-
# So we need a new plugin instance or reset _is_shutting_down.
308-
plugin._is_shutting_down = False
301+
# REFACTOR: Use a fresh plugin instance for the denied case
302+
plugin_denied = (
303+
bigquery_agent_analytics_plugin.BigQueryAgentAnalyticsPlugin(
304+
PROJECT_ID, DATASET_ID, TABLE_ID, config
305+
)
306+
)
307+
await plugin_denied._ensure_init()
308+
# Inject the same mock_write_client
309+
plugin_denied._write_client = mock_write_client
310+
plugin_denied._arrow_schema = plugin._arrow_schema
309311

310312
user_message = types.Content(parts=[types.Part(text="What is up?")])
311-
await plugin.on_user_message_callback(
313+
await plugin_denied.on_user_message_callback(
312314
invocation_context=invocation_context, user_message=user_message
313315
)
314316
# Since it's denied, no task is created. close() would wait if there was one.
315-
await plugin.close()
317+
await plugin_denied.close()
316318
mock_write_client.append_rows.assert_not_called()
317319

318320
@pytest.mark.asyncio
@@ -340,11 +342,21 @@ async def test_event_denylist(
340342
await plugin.close()
341343
mock_write_client.append_rows.assert_not_called()
342344

343-
# Reset for next call
344-
plugin._is_shutting_down = False
345+
# REFACTOR: Use a fresh plugin instance for the allowed case
346+
plugin_allowed = (
347+
bigquery_agent_analytics_plugin.BigQueryAgentAnalyticsPlugin(
348+
PROJECT_ID, DATASET_ID, TABLE_ID, config
349+
)
350+
)
351+
await plugin_allowed._ensure_init()
352+
# Inject the same mock_write_client
353+
plugin_allowed._write_client = mock_write_client
354+
plugin_allowed._arrow_schema = plugin._arrow_schema
345355

346-
await plugin.before_run_callback(invocation_context=invocation_context)
347-
await plugin.close()
356+
await plugin_allowed.before_run_callback(
357+
invocation_context=invocation_context
358+
)
359+
await plugin_allowed.close()
348360
mock_write_client.append_rows.assert_called_once()
349361

350362
@pytest.mark.asyncio
@@ -399,6 +411,44 @@ def mutate_payload(data):
399411
assert content["model"] == "GEMINI-PRO"
400412
assert content["prompt"][0]["role"] == "user"
401413

414+
@pytest.mark.asyncio
415+
async def test_content_formatter_error_fallback(
416+
self,
417+
mock_write_client,
418+
invocation_context,
419+
mock_auth_default,
420+
mock_bq_client,
421+
mock_to_arrow_schema,
422+
dummy_arrow_schema,
423+
mock_asyncio_to_thread,
424+
):
425+
"""Tests that if content_formatter fails, the original payload is used."""
426+
427+
def error_formatter(data):
428+
raise ValueError("Formatter failed")
429+
430+
config = BigQueryLoggerConfig(content_formatter=error_formatter)
431+
plugin = bigquery_agent_analytics_plugin.BigQueryAgentAnalyticsPlugin(
432+
PROJECT_ID, DATASET_ID, TABLE_ID, config
433+
)
434+
await plugin._ensure_init()
435+
mock_write_client.append_rows.reset_mock()
436+
437+
user_message = types.Content(parts=[types.Part(text="Original message")])
438+
439+
# This triggers the log. Internal logic catches exception and proceeds.
440+
await plugin.on_user_message_callback(
441+
invocation_context=invocation_context, user_message=user_message
442+
)
443+
await plugin.close()
444+
445+
mock_write_client.append_rows.assert_called_once()
446+
log_entry = _get_captured_event_dict(mock_write_client, dummy_arrow_schema)
447+
448+
# Verify that despite the error, we still got the original data
449+
content = json.loads(log_entry["content"])
450+
assert content["text"] == "Original message"
451+
402452
@pytest.mark.asyncio
403453
async def test_max_content_length_smart_truncation(
404454
self,
@@ -725,7 +775,9 @@ async def test_before_tool_callback_logs_correctly(
725775
type(mock_tool).name = mock.PropertyMock(return_value="MyTool")
726776
type(mock_tool).description = mock.PropertyMock(return_value="Description")
727777
await bq_plugin_inst.before_tool_callback(
728-
tool=mock_tool, tool_args={"param": "value"}, tool_context=tool_context
778+
tool=mock_tool,
779+
tool_args={"param": "value"},
780+
tool_context=tool_context,
729781
)
730782
await bq_plugin_inst.close()
731783
log_entry = _get_captured_event_dict(mock_write_client, dummy_arrow_schema)

0 commit comments

Comments
 (0)