using Xunit; using Moq; using System.Text.Json; using System.Threading.Tasks; using System.Linq; namespace Svrnty.MCP.Core.Tests; /// /// Unit tests for ToolRegistry following TDD approach. /// Tests dynamic tool registration and retrieval. /// public class ToolRegistryTests { [Fact] public void ToolRegistry_ShouldInitializeEmpty() { // Arrange & Act var registry = new ToolRegistry(); // Assert Assert.NotNull(registry); Assert.Empty(registry.GetAllTools()); } [Fact] public void ToolRegistry_ShouldAddTool() { // Arrange var registry = new ToolRegistry(); var mockTool = CreateMockTool("test_tool", "A test tool"); // Act registry.AddTool(mockTool.Object); // Assert Assert.Single(registry.GetAllTools()); } [Fact] public void ToolRegistry_ShouldGetToolByName() { // Arrange var registry = new ToolRegistry(); var mockTool = CreateMockTool("search_codex", "Search CODEX documents"); registry.AddTool(mockTool.Object); // Act var retrieved = registry.GetTool("search_codex"); // Assert Assert.NotNull(retrieved); Assert.Equal("search_codex", retrieved.Name); } [Fact] public void ToolRegistry_GetTool_WithInvalidName_ReturnsNull() { // Arrange var registry = new ToolRegistry(); var mockTool = CreateMockTool("existing_tool", "Exists"); registry.AddTool(mockTool.Object); // Act var result = registry.GetTool("nonexistent_tool"); // Assert Assert.Null(result); } [Fact] public void ToolRegistry_ShouldAddMultipleTools() { // Arrange var registry = new ToolRegistry(); var tool1 = CreateMockTool("tool1", "First tool"); var tool2 = CreateMockTool("tool2", "Second tool"); var tool3 = CreateMockTool("tool3", "Third tool"); // Act registry.AddTool(tool1.Object); registry.AddTool(tool2.Object); registry.AddTool(tool3.Object); // Assert var allTools = registry.GetAllTools(); Assert.Equal(3, allTools.Count()); } [Fact] public void ToolRegistry_ShouldPreventDuplicateToolNames() { // Arrange var registry = new ToolRegistry(); var tool1 = CreateMockTool("duplicate", "First"); var tool2 = CreateMockTool("duplicate", "Second"); registry.AddTool(tool1.Object); // Act & Assert var exception = Assert.Throws(() => registry.AddTool(tool2.Object) ); Assert.Contains("already registered", exception.Message); Assert.Single(registry.GetAllTools()); } [Fact] public void ToolRegistry_ShouldRemoveTool() { // Arrange var registry = new ToolRegistry(); var mockTool = CreateMockTool("temp_tool", "Temporary"); registry.AddTool(mockTool.Object); // Act var removed = registry.RemoveTool("temp_tool"); // Assert Assert.True(removed); Assert.Empty(registry.GetAllTools()); Assert.Null(registry.GetTool("temp_tool")); } [Fact] public void ToolRegistry_RemoveTool_WithInvalidName_ReturnsFalse() { // Arrange var registry = new ToolRegistry(); // Act var removed = registry.RemoveTool("nonexistent"); // Assert Assert.False(removed); } [Fact] public void ToolRegistry_ShouldListAllToolNames() { // Arrange var registry = new ToolRegistry(); registry.AddTool(CreateMockTool("tool_a", "A").Object); registry.AddTool(CreateMockTool("tool_b", "B").Object); registry.AddTool(CreateMockTool("tool_c", "C").Object); // Act var names = registry.GetToolNames(); // Assert Assert.Equal(3, names.Count()); Assert.Contains("tool_a", names); Assert.Contains("tool_b", names); Assert.Contains("tool_c", names); } [Fact] public void ToolRegistry_ShouldHaveTool() { // Arrange var registry = new ToolRegistry(); registry.AddTool(CreateMockTool("exists", "Tool").Object); // Act & Assert Assert.True(registry.HasTool("exists")); Assert.False(registry.HasTool("not_exists")); } [Fact] public void ToolRegistry_ShouldClearAllTools() { // Arrange var registry = new ToolRegistry(); registry.AddTool(CreateMockTool("tool1", "1").Object); registry.AddTool(CreateMockTool("tool2", "2").Object); // Act registry.Clear(); // Assert Assert.Empty(registry.GetAllTools()); Assert.Empty(registry.GetToolNames()); } [Fact] public void ToolRegistry_GetAllTools_ShouldReturnReadOnlyCollection() { // Arrange var registry = new ToolRegistry(); registry.AddTool(CreateMockTool("tool", "Tool").Object); // Act var tools = registry.GetAllTools(); // Assert Assert.NotNull(tools); // Ensure modifying returned collection doesn't affect registry Assert.IsAssignableFrom>(tools); } // Helper method to create mock tools private Mock CreateMockTool(string name, string description) { var mockTool = new Mock(); mockTool.Setup(t => t.Name).Returns(name); mockTool.Setup(t => t.Description).Returns(description); mockTool.Setup(t => t.Schema).Returns(JsonDocument.Parse("""{"type": "object"}""")); mockTool.Setup(t => t.ExecuteAsync(It.IsAny())) .ReturnsAsync(JsonDocument.Parse("""{"status": "ok"}""")); return mockTool; } }