blob: 88c7e6de9aeb3ae78532cba4ec9dd8489181b35b [file] [log] [blame]
Akronbd154ea2025-06-12 17:01:58 +02001package tools
2
3import (
4 "context"
5 "testing"
6
7 "github.com/korap/korap-mcp/service"
8 "github.com/mark3labs/mcp-go/mcp"
9 "github.com/stretchr/testify/assert"
10)
11
12func TestMetadataTool_Name(t *testing.T) {
13 client := &service.Client{}
14 tool := NewMetadataTool(client)
15
16 assert.Equal(t, "korap_metadata", tool.Name())
17}
18
19func TestMetadataTool_Description(t *testing.T) {
20 client := &service.Client{}
21 tool := NewMetadataTool(client)
22
23 expected := "Retrieve metadata and statistics for KorAP corpora"
24 assert.Equal(t, expected, tool.Description())
25}
26
27func TestMetadataTool_InputSchema(t *testing.T) {
28 client := &service.Client{}
29 tool := NewMetadataTool(client)
30
31 schema := tool.InputSchema()
32
33 // Verify it's an object type
34 assert.Equal(t, "object", schema["type"])
35
36 // Verify properties exist
37 properties, ok := schema["properties"].(map[string]interface{})
38 assert.True(t, ok)
39 assert.Contains(t, properties, "action")
40 assert.Contains(t, properties, "corpus")
41
42 // Verify action property details
43 action, ok := properties["action"].(map[string]interface{})
44 assert.True(t, ok)
45 assert.Equal(t, "string", action["type"])
46
47 enum, ok := action["enum"].([]string)
48 assert.True(t, ok)
49 assert.Contains(t, enum, "list")
50 assert.Contains(t, enum, "statistics")
51 assert.Equal(t, "list", action["default"])
52
53 // Verify required fields
54 required, ok := schema["required"].([]string)
55 assert.True(t, ok)
56 assert.Contains(t, required, "action")
57}
58
59func TestNewMetadataTool(t *testing.T) {
60 client := &service.Client{}
61 tool := NewMetadataTool(client)
62
63 assert.NotNil(t, tool)
64 assert.Equal(t, client, tool.client)
65}
66
67func TestMetadataTool_Execute_MissingAction(t *testing.T) {
68 client := &service.Client{}
69 tool := NewMetadataTool(client)
70
71 // Create request without action parameter
72 request := mcp.CallToolRequest{
73 Params: mcp.CallToolParams{
74 Arguments: map[string]interface{}{},
75 },
76 }
77
78 _, err := tool.Execute(context.Background(), request)
79 assert.Error(t, err)
80 assert.Contains(t, err.Error(), "action parameter is required")
81}
82
83func TestMetadataTool_Execute_NilClient(t *testing.T) {
84 tool := NewMetadataTool(nil)
85
86 request := mcp.CallToolRequest{
87 Params: mcp.CallToolParams{
88 Arguments: map[string]interface{}{
89 "action": "list",
90 },
91 },
92 }
93
94 _, err := tool.Execute(context.Background(), request)
95 assert.Error(t, err)
96 assert.Contains(t, err.Error(), "KorAP client not configured")
97}
98
99func TestMetadataTool_Execute_UnknownAction(t *testing.T) {
100 client := &service.Client{}
101 tool := NewMetadataTool(client)
102
103 request := mcp.CallToolRequest{
104 Params: mcp.CallToolParams{
105 Arguments: map[string]interface{}{
106 "action": "unknown",
107 },
108 },
109 }
110
111 _, err := tool.Execute(context.Background(), request)
112 assert.Error(t, err)
113 // The unknown action error should come before authentication
114 assert.Contains(t, err.Error(), "unknown action: unknown")
115}
116
117func TestMetadataTool_Execute_StatisticsWithoutCorpus(t *testing.T) {
118 tool := NewMetadataTool(nil)
119
120 request := mcp.CallToolRequest{
121 Params: mcp.CallToolParams{
122 Arguments: map[string]interface{}{
123 "action": "statistics",
124 },
125 },
126 }
127
128 _, err := tool.Execute(context.Background(), request)
129 assert.Error(t, err)
130 // Should fail at client check since corpus is now optional
131 assert.Contains(t, err.Error(), "KorAP client not configured")
132}
133
134func TestMetadataTool_Execute_ParameterExtraction(t *testing.T) {
135 // This test verifies that parameters are extracted correctly
136 // It should fail with authentication error since we don't have a mock server
137 // but we can verify the parameters were parsed correctly by checking the log messages
138
139 client := &service.Client{}
140 tool := NewMetadataTool(client)
141
142 tests := []struct {
143 name string
144 arguments map[string]interface{}
145 expectErr bool
146 }{
147 {
148 name: "list_action",
149 arguments: map[string]interface{}{
150 "action": "list",
151 },
152 expectErr: true, // Will fail at authentication
153 },
154 {
155 name: "statistics_action",
156 arguments: map[string]interface{}{
157 "action": "statistics",
158 "corpus": "test-corpus",
159 },
160 expectErr: true, // Will fail at authentication
161 },
162 {
163 name: "statistics_with_empty_corpus",
164 arguments: map[string]interface{}{
165 "action": "statistics",
166 "corpus": "",
167 },
168 expectErr: true, // Will fail at authentication (corpus is optional)
169 },
170 }
171
172 for _, tt := range tests {
173 t.Run(tt.name, func(t *testing.T) {
174 request := mcp.CallToolRequest{
175 Params: mcp.CallToolParams{
176 Arguments: tt.arguments,
177 },
178 }
179
180 _, err := tool.Execute(context.Background(), request)
181 if tt.expectErr {
182 assert.Error(t, err)
183 }
184 })
185 }
186}
187
188func TestMetadataTool_formatCorpusList(t *testing.T) {
189 client := &service.Client{}
190 tool := NewMetadataTool(client)
191
192 // Test empty response
193 emptyResponse := &service.CorpusListResponse{
194 Corpora: []service.CorpusInfo{},
195 }
196
197 result := tool.formatCorpusList(emptyResponse)
198 assert.Contains(t, result, "KorAP Available Corpora")
199 assert.Contains(t, result, "No corpora available")
200
201 // Test response with corpora
202 responseWithCorpora := &service.CorpusListResponse{
203 Corpora: []service.CorpusInfo{
204 {
205 ID: "corpus1",
206 Name: "Test Corpus 1",
207 Description: "A test corpus",
208 Documents: 100,
209 Tokens: 50000,
210 Sentences: 2500,
211 Paragraphs: 500,
212 },
213 {
214 ID: "corpus2",
215 Name: "Test Corpus 2",
216 Documents: 200,
217 Tokens: 75000,
218 },
219 },
220 }
221
222 result = tool.formatCorpusList(responseWithCorpora)
223 assert.Contains(t, result, "KorAP Available Corpora")
224 assert.Contains(t, result, "Total Corpora: 2")
225 assert.Contains(t, result, "1. Test Corpus 1")
226 assert.Contains(t, result, "ID: corpus1")
227 assert.Contains(t, result, "Description: A test corpus")
228 assert.Contains(t, result, "Documents: 100")
229 assert.Contains(t, result, "Tokens: 50000")
230 assert.Contains(t, result, "Sentences: 2500")
231 assert.Contains(t, result, "Paragraphs: 500")
232 assert.Contains(t, result, "2. Test Corpus 2")
233 assert.Contains(t, result, "ID: corpus2")
234 assert.Contains(t, result, "Documents: 200")
235 assert.Contains(t, result, "Tokens: 75000")
236}
237
238func TestMetadataTool_formatCorpusStatistics(t *testing.T) {
239 client := &service.Client{}
240 tool := NewMetadataTool(client)
241
242 // Test minimal statistics
243 minimalStats := &service.StatisticsResponse{
244 Documents: 100,
245 Tokens: 50000,
246 }
247
248 result := tool.formatCorpusStatistics("test-corpus", minimalStats)
249 assert.Contains(t, result, "KorAP Corpus Statistics")
250 assert.Contains(t, result, "Corpus Query: test-corpus")
251 assert.Contains(t, result, "Documents: 100")
252 assert.Contains(t, result, "Tokens: 50000")
253
254 // Test complete statistics with additional fields
255 completeStats := &service.StatisticsResponse{
256 Documents: 200,
257 Tokens: 100000,
258 Sentences: 5000,
259 Paragraphs: 1000,
260 Fields: map[string]interface{}{
261 "genre": "literature",
262 "language": "German",
263 "year": 2023,
264 },
265 }
266
267 result = tool.formatCorpusStatistics("complete-corpus", completeStats)
268 assert.Contains(t, result, "KorAP Corpus Statistics")
269 assert.Contains(t, result, "Corpus Query: complete-corpus")
270 assert.Contains(t, result, "Documents: 200")
271 assert.Contains(t, result, "Tokens: 100000")
272 assert.Contains(t, result, "Sentences: 5000")
273 assert.Contains(t, result, "Paragraphs: 1000")
274 assert.Contains(t, result, "Additional Fields:")
275 assert.Contains(t, result, "genre: literature")
276 assert.Contains(t, result, "language: German")
277 assert.Contains(t, result, "year: 2023")
278
279 // Test empty corpus query (all available data)
280 result = tool.formatCorpusStatistics("", minimalStats)
281 assert.Contains(t, result, "KorAP Corpus Statistics")
282 assert.Contains(t, result, "Corpus Query: (all available data)")
283 assert.Contains(t, result, "Documents: 100")
284 assert.Contains(t, result, "Tokens: 50000")
285}