@@ -511,3 +511,110 @@ def test_validate_tool_spec_with_ref_property():
511511 assert props ["ref_field" ] == {"$ref" : "#/$defs/SomeType" }
512512 assert "type" not in props ["ref_field" ]
513513 assert "description" not in props ["ref_field" ]
514+ def test_tool_registry_replace_existing_tool ():
515+ """Test replacing an existing tool."""
516+ old_tool = MagicMock ()
517+ old_tool .tool_name = "my_tool"
518+ old_tool .is_dynamic = False
519+ old_tool .supports_hot_reload = False
520+
521+ new_tool = MagicMock ()
522+ new_tool .tool_name = "my_tool"
523+ new_tool .is_dynamic = False
524+
525+ registry = ToolRegistry ()
526+ registry .register_tool (old_tool )
527+ registry .replace ("my_tool" , new_tool )
528+
529+ assert registry .registry ["my_tool" ] == new_tool
530+
531+
532+ def test_tool_registry_replace_nonexistent_tool ():
533+ """Test replacing a tool that doesn't exist raises ValueError."""
534+ new_tool = MagicMock ()
535+ new_tool .tool_name = "my_tool"
536+
537+ registry = ToolRegistry ()
538+
539+ with pytest .raises (ValueError , match = "Cannot replace tool 'my_tool' - tool does not exist" ):
540+ registry .replace ("my_tool" , new_tool )
541+
542+
543+ def test_tool_registry_replace_with_different_name ():
544+ """Test replacing with different name raises ValueError."""
545+ old_tool = MagicMock ()
546+ old_tool .tool_name = "old_tool"
547+ old_tool .is_dynamic = False
548+ old_tool .supports_hot_reload = False
549+
550+ new_tool = MagicMock ()
551+ new_tool .tool_name = "new_tool"
552+
553+ registry = ToolRegistry ()
554+ registry .register_tool (old_tool )
555+
556+ with pytest .raises (ValueError , match = "Tool names must match" ):
557+ registry .replace ("old_tool" , new_tool )
558+
559+
560+ def test_tool_registry_replace_dynamic_tool ():
561+ """Test replacing a dynamic tool updates both registries."""
562+ old_tool = MagicMock ()
563+ old_tool .tool_name = "dynamic_tool"
564+ old_tool .is_dynamic = True
565+ old_tool .supports_hot_reload = True
566+
567+ new_tool = MagicMock ()
568+ new_tool .tool_name = "dynamic_tool"
569+ new_tool .is_dynamic = True
570+
571+ registry = ToolRegistry ()
572+ registry .register_tool (old_tool )
573+ registry .replace ("dynamic_tool" , new_tool )
574+
575+ assert registry .registry ["dynamic_tool" ] == new_tool
576+ assert registry .dynamic_tools ["dynamic_tool" ] == new_tool
577+
578+
579+ def test_tool_registry_replace_dynamic_with_non_dynamic ():
580+ """Test replacing a dynamic tool with non-dynamic tool removes from dynamic_tools."""
581+ old_tool = MagicMock ()
582+ old_tool .tool_name = "my_tool"
583+ old_tool .is_dynamic = True
584+ old_tool .supports_hot_reload = True
585+
586+ new_tool = MagicMock ()
587+ new_tool .tool_name = "my_tool"
588+ new_tool .is_dynamic = False
589+
590+ registry = ToolRegistry ()
591+ registry .register_tool (old_tool )
592+
593+ assert "my_tool" in registry .dynamic_tools
594+
595+ registry .replace ("my_tool" , new_tool )
596+
597+ assert registry .registry ["my_tool" ] == new_tool
598+ assert "my_tool" not in registry .dynamic_tools
599+
600+
601+ def test_tool_registry_replace_non_dynamic_with_dynamic ():
602+ """Test replacing a non-dynamic tool with dynamic tool adds to dynamic_tools."""
603+ old_tool = MagicMock ()
604+ old_tool .tool_name = "my_tool"
605+ old_tool .is_dynamic = False
606+ old_tool .supports_hot_reload = False
607+
608+ new_tool = MagicMock ()
609+ new_tool .tool_name = "my_tool"
610+ new_tool .is_dynamic = True
611+
612+ registry = ToolRegistry ()
613+ registry .register_tool (old_tool )
614+
615+ assert "my_tool" not in registry .dynamic_tools
616+
617+ registry .replace ("my_tool" , new_tool )
618+
619+ assert registry .registry ["my_tool" ] == new_tool
620+ assert registry .dynamic_tools ["my_tool" ] == new_tool
0 commit comments