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