Skip to content

Commit 310024b

Browse files
committed
added some more tests for code coverage
1 parent 5d671b0 commit 310024b

File tree

1 file changed

+90
-0
lines changed
  • aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/test-opentelemetry-instrumentation-langchain-v2

1 file changed

+90
-0
lines changed

aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/test-opentelemetry-instrumentation-langchain-v2/test_callback_handler.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,53 @@ def test_on_tool_start_end(self, mock_context_api):
274274

275275
self.mock_span.set_attribute.assert_any_call("gen_ai.tool.output", output)
276276

277+
@patch("amazon.opentelemetry.distro.opentelemetry.instrumentation.langchain_v2.callback_handler.context_api")
278+
def test_on_agent_action_and_finish(self, mock_context_api):
279+
"""Test the on_agent_action and on_agent_finish methods."""
280+
mock_context_api.get_value.return_value = False
281+
282+
# Create a mock AgentAction
283+
mock_action = Mock()
284+
mock_action.tool = "calculator"
285+
mock_action.tool_input = "2 + 2"
286+
287+
# Create a mock AgentFinish
288+
mock_finish = Mock()
289+
mock_finish.return_values = {"output": "The answer is 4"}
290+
291+
# Set up the handler with a mocked span
292+
self.handler.span_mapping[self.run_id] = SpanHolder(self.mock_span, [], time.time(), "gpt-4")
293+
294+
# Test on_agent_action
295+
self.handler.on_agent_action(action=mock_action, run_id=self.run_id, parent_run_id=self.parent_run_id)
296+
297+
# Verify the expected attributes were set
298+
self.mock_span.set_attribute.assert_any_call("gen_ai.agent.tool.input", "2 + 2")
299+
self.mock_span.set_attribute.assert_any_call("gen_ai.agent.tool.name", "calculator")
300+
self.mock_span.set_attribute.assert_any_call(SpanAttributes.GEN_AI_OPERATION_NAME, "invoke_agent")
301+
302+
# Test on_agent_finish
303+
self.handler.on_agent_finish(finish=mock_finish, run_id=self.run_id, parent_run_id=self.parent_run_id)
304+
305+
# Verify the output attribute was set
306+
self.mock_span.set_attribute.assert_any_call("gen_ai.agent.tool.output", "The answer is 4")
307+
308+
@patch("amazon.opentelemetry.distro.opentelemetry.instrumentation.langchain_v2.callback_handler.context_api")
309+
def test_on_agent_error(self, mock_context_api):
310+
"""Test the on_agent_error method."""
311+
mock_context_api.get_value.return_value = False
312+
313+
# Create a test error
314+
test_error = ValueError("Something went wrong")
315+
316+
# Patch the _handle_error method
317+
with patch.object(self.handler, "_handle_error") as mock_handle_error:
318+
# Call on_agent_error
319+
self.handler.on_agent_error(error=test_error, run_id=self.run_id, parent_run_id=self.parent_run_id)
320+
321+
# Verify _handle_error was called with the right parameters
322+
mock_handle_error.assert_called_once_with(test_error, self.run_id, self.parent_run_id)
323+
277324

278325
class TestLangChainInstrumentor(unittest.TestCase):
279326
"""Test the LangChainInstrumentor class."""
@@ -360,6 +407,49 @@ def test_init_wrapper_handler_already_exists(self):
360407
instance.add_handler.assert_not_called()
361408

362409

410+
class TestSanitizeMetadataValue(unittest.TestCase):
411+
"""Tests for the _sanitize_metadata_value function."""
412+
413+
def test_sanitize_none(self):
414+
"""Test that None values remain None."""
415+
self.assertIsNone(_sanitize_metadata_value(None))
416+
417+
def test_sanitize_primitive_types(self):
418+
"""Test that primitive types (bool, str, bytes, int, float) remain unchanged."""
419+
self.assertEqual(_sanitize_metadata_value(True), True)
420+
self.assertEqual(_sanitize_metadata_value(False), False)
421+
self.assertEqual(_sanitize_metadata_value("test_string"), "test_string")
422+
self.assertEqual(_sanitize_metadata_value(b"test_bytes"), b"test_bytes")
423+
self.assertEqual(_sanitize_metadata_value(123), 123)
424+
self.assertEqual(_sanitize_metadata_value(123.45), 123.45)
425+
426+
def test_sanitize_lists_and_tuples(self):
427+
"""Test that lists and tuples are properly sanitized."""
428+
self.assertEqual(_sanitize_metadata_value([1, 2, 3]), ["1", "2", "3"])
429+
430+
self.assertEqual(_sanitize_metadata_value([1, "test", True, None]), ["1", "test", "True", "None"])
431+
432+
self.assertEqual(_sanitize_metadata_value((1, 2, 3)), ["1", "2", "3"])
433+
434+
self.assertEqual(_sanitize_metadata_value([1, [2, 3], 4]), ["1", "['2', '3']", "4"])
435+
436+
def test_sanitize_complex_objects(self):
437+
"""Test that complex objects are converted to strings."""
438+
self.assertEqual(_sanitize_metadata_value({"key": "value"}), "{'key': 'value'}")
439+
440+
class TestObject:
441+
def __str__(self):
442+
return "TestObject"
443+
444+
self.assertEqual(_sanitize_metadata_value(TestObject()), "TestObject")
445+
446+
self.assertTrue(_sanitize_metadata_value({1, 2, 3}).startswith("{"))
447+
self.assertTrue(_sanitize_metadata_value({1, 2, 3}).endswith("}"))
448+
449+
complex_struct = {"key1": [1, 2, 3], "key2": {"nested": "value"}, "key3": TestObject()}
450+
self.assertTrue(isinstance(_sanitize_metadata_value(complex_struct), str))
451+
452+
363453
if __name__ == "__main__":
364454
import time
365455

0 commit comments

Comments
 (0)