blob: 4e70978cbd9520c06aa0d454e6b6106b6a7c953b [file] [log] [blame]
Akrone33db5c2025-06-12 15:31:10 +02001package tools
2
3import (
4 "context"
5 "testing"
6
7 "github.com/mark3labs/mcp-go/mcp"
8 "github.com/stretchr/testify/assert"
9)
10
11// mockTool implements the Tool interface for testing
12type mockTool struct {
13 name string
14 description string
15 schema map[string]interface{}
16}
17
18func (t *mockTool) Name() string {
19 return t.name
20}
21
22func (t *mockTool) Description() string {
23 return t.description
24}
25
26func (t *mockTool) InputSchema() map[string]interface{} {
27 return t.schema
28}
29
30func (t *mockTool) Execute(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
31 return mcp.NewToolResultText("mock result"), nil
32}
33
34func TestNewRegistry(t *testing.T) {
35 registry := NewRegistry()
36 assert.NotNil(t, registry)
37 assert.Equal(t, 0, registry.Count())
38}
39
40func TestRegister(t *testing.T) {
41 registry := NewRegistry()
42
43 // Test registering a valid tool
44 tool := &mockTool{
45 name: "test-tool",
46 description: "A test tool",
47 schema: map[string]interface{}{
48 "type": "object",
49 },
50 }
51
52 err := registry.Register(tool)
53 assert.NoError(t, err)
54 assert.Equal(t, 1, registry.Count())
55
56 // Test registering nil tool
57 err = registry.Register(nil)
58 assert.Error(t, err)
59 assert.Contains(t, err.Error(), "cannot register nil tool")
60
61 // Test registering tool with empty name
62 emptyNameTool := &mockTool{
63 name: "",
64 description: "A tool with no name",
65 }
66 err = registry.Register(emptyNameTool)
67 assert.Error(t, err)
68 assert.Contains(t, err.Error(), "tool name cannot be empty")
69
70 // Test registering duplicate tool
71 err = registry.Register(tool)
72 assert.Error(t, err)
73 assert.Contains(t, err.Error(), "already registered")
74}
75
76func TestUnregister(t *testing.T) {
77 registry := NewRegistry()
78
79 tool := &mockTool{
80 name: "test-tool",
81 description: "A test tool",
82 }
83
84 // Register the tool first
85 err := registry.Register(tool)
86 assert.NoError(t, err)
87
88 // Test unregistering existing tool
89 err = registry.Unregister("test-tool")
90 assert.NoError(t, err)
91 assert.Equal(t, 0, registry.Count())
92
93 // Test unregistering non-existent tool
94 err = registry.Unregister("non-existent")
95 assert.Error(t, err)
96 assert.Contains(t, err.Error(), "not found")
97}
98
99func TestGet(t *testing.T) {
100 registry := NewRegistry()
101
102 tool := &mockTool{
103 name: "test-tool",
104 description: "A test tool",
105 }
106
107 // Register the tool first
108 err := registry.Register(tool)
109 assert.NoError(t, err)
110
111 // Test getting existing tool
112 gotTool, exists := registry.Get("test-tool")
113 assert.True(t, exists)
114 assert.Equal(t, tool, gotTool)
115
116 // Test getting non-existent tool
117 _, exists = registry.Get("non-existent")
118 assert.False(t, exists)
119}
120
121func TestList(t *testing.T) {
122 registry := NewRegistry()
123
124 tool1 := &mockTool{
125 name: "tool-1",
126 description: "First tool",
127 }
128 tool2 := &mockTool{
129 name: "tool-2",
130 description: "Second tool",
131 }
132
133 // Register both tools
134 err := registry.Register(tool1)
135 assert.NoError(t, err)
136 err = registry.Register(tool2)
137 assert.NoError(t, err)
138
139 // Test listing tools
140 tools := registry.List()
141 assert.Len(t, tools, 2)
142
143 // Verify tool names and descriptions
144 names := make(map[string]string)
145 for _, tool := range tools {
146 names[tool.Name] = tool.Description
147 }
148
149 assert.Equal(t, "First tool", names["tool-1"])
150 assert.Equal(t, "Second tool", names["tool-2"])
151}
152
153func TestNames(t *testing.T) {
154 registry := NewRegistry()
155
156 tool1 := &mockTool{
157 name: "tool-1",
158 description: "First tool",
159 }
160 tool2 := &mockTool{
161 name: "tool-2",
162 description: "Second tool",
163 }
164
165 // Register both tools
166 err := registry.Register(tool1)
167 assert.NoError(t, err)
168 err = registry.Register(tool2)
169 assert.NoError(t, err)
170
171 // Test getting tool names
172 names := registry.Names()
173 assert.Len(t, names, 2)
174 assert.Contains(t, names, "tool-1")
175 assert.Contains(t, names, "tool-2")
176}
177
178func TestExecute(t *testing.T) {
179 registry := NewRegistry()
180
181 tool := &mockTool{
182 name: "test-tool",
183 description: "A test tool",
184 }
185
186 // Register the tool first
187 err := registry.Register(tool)
188 assert.NoError(t, err)
189
190 // Test executing existing tool
191 request := mcp.CallToolRequest{}
192
193 result, err := registry.Execute(context.Background(), "test-tool", request)
194 assert.NoError(t, err)
195 assert.NotNil(t, result)
196
197 // Test executing non-existent tool
198 _, err = registry.Execute(context.Background(), "non-existent", request)
199 assert.Error(t, err)
200 assert.Contains(t, err.Error(), "not found")
201}
202
203func TestClear(t *testing.T) {
204 registry := NewRegistry()
205
206 tool1 := &mockTool{
207 name: "tool-1",
208 description: "First tool",
209 }
210 tool2 := &mockTool{
211 name: "tool-2",
212 description: "Second tool",
213 }
214
215 // Register both tools
216 err := registry.Register(tool1)
217 assert.NoError(t, err)
218 err = registry.Register(tool2)
219 assert.NoError(t, err)
220
221 // Test clearing registry
222 registry.Clear()
223 assert.Equal(t, 0, registry.Count())
224
225 // Verify tools are gone
226 _, exists := registry.Get("tool-1")
227 assert.False(t, exists)
228 _, exists = registry.Get("tool-2")
229 assert.False(t, exists)
230}