blob: e5d60cda3172c0fb2cd0f0199743e2156e397c08 [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)
Akron81f709c2025-06-12 17:30:55 +0200113 // The validation error should come before authentication
114 assert.Contains(t, err.Error(), "invalid metadata request")
115 assert.Contains(t, err.Error(), "invalid action")
Akronbd154ea2025-06-12 17:01:58 +0200116}
117
118func TestMetadataTool_Execute_StatisticsWithoutCorpus(t *testing.T) {
119 tool := NewMetadataTool(nil)
120
121 request := mcp.CallToolRequest{
122 Params: mcp.CallToolParams{
123 Arguments: map[string]interface{}{
124 "action": "statistics",
125 },
126 },
127 }
128
129 _, err := tool.Execute(context.Background(), request)
130 assert.Error(t, err)
131 // Should fail at client check since corpus is now optional
132 assert.Contains(t, err.Error(), "KorAP client not configured")
133}
134
135func TestMetadataTool_Execute_ParameterExtraction(t *testing.T) {
136 // This test verifies that parameters are extracted correctly
137 // It should fail with authentication error since we don't have a mock server
138 // but we can verify the parameters were parsed correctly by checking the log messages
139
140 client := &service.Client{}
141 tool := NewMetadataTool(client)
142
143 tests := []struct {
144 name string
145 arguments map[string]interface{}
146 expectErr bool
147 }{
148 {
149 name: "list_action",
150 arguments: map[string]interface{}{
151 "action": "list",
152 },
153 expectErr: true, // Will fail at authentication
154 },
155 {
156 name: "statistics_action",
157 arguments: map[string]interface{}{
158 "action": "statistics",
159 "corpus": "test-corpus",
160 },
161 expectErr: true, // Will fail at authentication
162 },
163 {
164 name: "statistics_with_empty_corpus",
165 arguments: map[string]interface{}{
166 "action": "statistics",
167 "corpus": "",
168 },
169 expectErr: true, // Will fail at authentication (corpus is optional)
170 },
171 }
172
173 for _, tt := range tests {
174 t.Run(tt.name, func(t *testing.T) {
175 request := mcp.CallToolRequest{
176 Params: mcp.CallToolParams{
177 Arguments: tt.arguments,
178 },
179 }
180
181 _, err := tool.Execute(context.Background(), request)
182 if tt.expectErr {
183 assert.Error(t, err)
184 }
185 })
186 }
187}
188
189func TestMetadataTool_formatCorpusList(t *testing.T) {
190 client := &service.Client{}
191 tool := NewMetadataTool(client)
192
193 // Test empty response
194 emptyResponse := &service.CorpusListResponse{
195 Corpora: []service.CorpusInfo{},
196 }
197
198 result := tool.formatCorpusList(emptyResponse)
199 assert.Contains(t, result, "KorAP Available Corpora")
200 assert.Contains(t, result, "No corpora available")
201
202 // Test response with corpora
203 responseWithCorpora := &service.CorpusListResponse{
204 Corpora: []service.CorpusInfo{
205 {
206 ID: "corpus1",
207 Name: "Test Corpus 1",
208 Description: "A test corpus",
209 Documents: 100,
210 Tokens: 50000,
211 Sentences: 2500,
212 Paragraphs: 500,
213 },
214 {
215 ID: "corpus2",
216 Name: "Test Corpus 2",
217 Documents: 200,
218 Tokens: 75000,
219 },
220 },
221 }
222
223 result = tool.formatCorpusList(responseWithCorpora)
224 assert.Contains(t, result, "KorAP Available Corpora")
225 assert.Contains(t, result, "Total Corpora: 2")
226 assert.Contains(t, result, "1. Test Corpus 1")
227 assert.Contains(t, result, "ID: corpus1")
228 assert.Contains(t, result, "Description: A test corpus")
229 assert.Contains(t, result, "Documents: 100")
230 assert.Contains(t, result, "Tokens: 50000")
231 assert.Contains(t, result, "Sentences: 2500")
232 assert.Contains(t, result, "Paragraphs: 500")
233 assert.Contains(t, result, "2. Test Corpus 2")
234 assert.Contains(t, result, "ID: corpus2")
235 assert.Contains(t, result, "Documents: 200")
236 assert.Contains(t, result, "Tokens: 75000")
237}
238
239func TestMetadataTool_formatCorpusStatistics(t *testing.T) {
240 client := &service.Client{}
241 tool := NewMetadataTool(client)
242
243 // Test minimal statistics
244 minimalStats := &service.StatisticsResponse{
245 Documents: 100,
246 Tokens: 50000,
247 }
248
249 result := tool.formatCorpusStatistics("test-corpus", minimalStats)
250 assert.Contains(t, result, "KorAP Corpus Statistics")
251 assert.Contains(t, result, "Corpus Query: test-corpus")
252 assert.Contains(t, result, "Documents: 100")
253 assert.Contains(t, result, "Tokens: 50000")
254
255 // Test complete statistics with additional fields
256 completeStats := &service.StatisticsResponse{
257 Documents: 200,
258 Tokens: 100000,
259 Sentences: 5000,
260 Paragraphs: 1000,
261 Fields: map[string]interface{}{
262 "genre": "literature",
263 "language": "German",
264 "year": 2023,
265 },
266 }
267
268 result = tool.formatCorpusStatistics("complete-corpus", completeStats)
269 assert.Contains(t, result, "KorAP Corpus Statistics")
270 assert.Contains(t, result, "Corpus Query: complete-corpus")
271 assert.Contains(t, result, "Documents: 200")
272 assert.Contains(t, result, "Tokens: 100000")
273 assert.Contains(t, result, "Sentences: 5000")
274 assert.Contains(t, result, "Paragraphs: 1000")
275 assert.Contains(t, result, "Additional Fields:")
276 assert.Contains(t, result, "genre: literature")
277 assert.Contains(t, result, "language: German")
278 assert.Contains(t, result, "year: 2023")
279
280 // Test empty corpus query (all available data)
281 result = tool.formatCorpusStatistics("", minimalStats)
282 assert.Contains(t, result, "KorAP Corpus Statistics")
283 assert.Contains(t, result, "Corpus Query: (all available data)")
284 assert.Contains(t, result, "Documents: 100")
285 assert.Contains(t, result, "Tokens: 50000")
286}