blob: 0387cc6a555498f44130e02d7220e223e9df7c42 [file] [log] [blame]
Akron49ceeb42025-05-23 17:46:01 +02001package main
2
3import (
4 "bytes"
5 "encoding/json"
6 "io"
7 "net/http"
8 "net/http/httptest"
9 "os"
10 "path/filepath"
11 "testing"
12
13 "github.com/KorAP/KoralPipe-TermMapper2/pkg/mapper"
14 "github.com/gofiber/fiber/v2"
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
17)
18
19func TestTransformEndpoint(t *testing.T) {
20 // Create a temporary config file
21 tmpDir := t.TempDir()
22 configFile := filepath.Join(tmpDir, "test-config.yaml")
23
24 configContent := `- id: test-mapper
25 foundryA: opennlp
26 layerA: p
27 foundryB: upos
28 layerB: p
29 mappings:
30 - "[PIDAT] <> [opennlp/p=PIDAT & opennlp/p=AdjType:Pdt]"
31 - "[DET] <> [opennlp/p=DET]"`
32
33 err := os.WriteFile(configFile, []byte(configContent), 0644)
34 require.NoError(t, err)
35
36 // Create mapper
37 m, err := mapper.NewMapper(configFile)
38 require.NoError(t, err)
39
40 // Create fiber app
41 app := fiber.New()
42 setupRoutes(app, m)
43
44 tests := []struct {
45 name string
46 mapID string
47 direction string
48 foundryA string
49 foundryB string
50 layerA string
51 layerB string
52 input string
53 expectedCode int
54 expectedBody string
55 expectedError string
56 }{
57 {
58 name: "Simple A to B mapping",
59 mapID: "test-mapper",
60 direction: "atob",
61 input: `{
62 "@type": "koral:token",
63 "wrap": {
64 "@type": "koral:term",
65 "foundry": "opennlp",
66 "key": "PIDAT",
67 "layer": "p",
68 "match": "match:eq"
69 }
70 }`,
71 expectedCode: http.StatusOK,
72 expectedBody: `{
73 "@type": "koral:token",
74 "wrap": {
75 "@type": "koral:termGroup",
76 "operands": [
77 {
78 "@type": "koral:term",
79 "foundry": "opennlp",
80 "key": "PIDAT",
81 "layer": "p",
82 "match": "match:eq"
83 },
84 {
85 "@type": "koral:term",
86 "foundry": "opennlp",
87 "key": "AdjType",
88 "layer": "p",
89 "match": "match:eq",
90 "value": "Pdt"
91 }
92 ],
93 "relation": "relation:and"
94 }
95 }`,
96 },
97 {
98 name: "B to A mapping",
99 mapID: "test-mapper",
100 direction: "btoa",
101 input: `{
102 "@type": "koral:token",
103 "wrap": {
104 "@type": "koral:termGroup",
105 "operands": [
106 {
107 "@type": "koral:term",
108 "foundry": "opennlp",
109 "key": "PIDAT",
110 "layer": "p",
111 "match": "match:eq"
112 },
113 {
114 "@type": "koral:term",
115 "foundry": "opennlp",
116 "key": "AdjType",
117 "layer": "p",
118 "match": "match:eq",
119 "value": "Pdt"
120 }
121 ],
122 "relation": "relation:and"
123 }
124 }`,
125 expectedCode: http.StatusOK,
126 expectedBody: `{
127 "@type": "koral:token",
128 "wrap": {
129 "@type": "koral:term",
130 "foundry": "opennlp",
131 "key": "PIDAT",
132 "layer": "p",
133 "match": "match:eq"
134 }
135 }`,
136 },
137 {
138 name: "Mapping with foundry override",
139 mapID: "test-mapper",
140 direction: "atob",
141 foundryB: "custom",
142 input: `{
143 "@type": "koral:token",
144 "wrap": {
145 "@type": "koral:term",
146 "foundry": "opennlp",
147 "key": "PIDAT",
148 "layer": "p",
149 "match": "match:eq"
150 }
151 }`,
152 expectedCode: http.StatusOK,
153 expectedBody: `{
154 "@type": "koral:token",
155 "wrap": {
156 "@type": "koral:termGroup",
157 "operands": [
158 {
159 "@type": "koral:term",
160 "foundry": "custom",
161 "key": "PIDAT",
162 "layer": "p",
163 "match": "match:eq"
164 },
165 {
166 "@type": "koral:term",
167 "foundry": "custom",
168 "key": "AdjType",
169 "layer": "p",
170 "match": "match:eq",
171 "value": "Pdt"
172 }
173 ],
174 "relation": "relation:and"
175 }
176 }`,
177 },
178 {
179 name: "Invalid mapping ID",
180 mapID: "nonexistent",
181 direction: "atob",
182 input: `{"@type": "koral:token"}`,
183 expectedCode: http.StatusInternalServerError,
184 expectedError: "mapping list with ID nonexistent not found",
185 },
186 {
187 name: "Invalid direction",
188 mapID: "test-mapper",
189 direction: "invalid",
190 input: `{"@type": "koral:token"}`,
191 expectedCode: http.StatusBadRequest,
192 expectedError: "invalid direction, must be 'atob' or 'btoa'",
193 },
194 {
195 name: "Invalid JSON",
196 mapID: "test-mapper",
197 direction: "atob",
198 input: `invalid json`,
199 expectedCode: http.StatusBadRequest,
200 expectedError: "invalid JSON in request body",
201 },
202 }
203
204 for _, tt := range tests {
205 t.Run(tt.name, func(t *testing.T) {
206 // Build URL with query parameters
207 url := "/" + tt.mapID + "/query"
208 if tt.direction != "" {
209 url += "?dir=" + tt.direction
210 }
211 if tt.foundryA != "" {
212 url += "&foundryA=" + tt.foundryA
213 }
214 if tt.foundryB != "" {
215 url += "&foundryB=" + tt.foundryB
216 }
217 if tt.layerA != "" {
218 url += "&layerA=" + tt.layerA
219 }
220 if tt.layerB != "" {
221 url += "&layerB=" + tt.layerB
222 }
223
224 // Make request
225 req := httptest.NewRequest(http.MethodPost, url, bytes.NewBufferString(tt.input))
226 req.Header.Set("Content-Type", "application/json")
227 resp, err := app.Test(req)
228 require.NoError(t, err)
229 defer resp.Body.Close()
230
231 // Check status code
232 assert.Equal(t, tt.expectedCode, resp.StatusCode)
233
234 // Read response body
235 body, err := io.ReadAll(resp.Body)
236 require.NoError(t, err)
237
238 if tt.expectedError != "" {
239 // Check error message
240 var errResp fiber.Map
241 err = json.Unmarshal(body, &errResp)
242 require.NoError(t, err)
243 assert.Equal(t, tt.expectedError, errResp["error"])
244 } else {
245 // Compare JSON responses
246 var expected, actual interface{}
247 err = json.Unmarshal([]byte(tt.expectedBody), &expected)
248 require.NoError(t, err)
249 err = json.Unmarshal(body, &actual)
250 require.NoError(t, err)
251 assert.Equal(t, expected, actual)
252 }
253 })
254 }
255}
256
257func TestHealthEndpoint(t *testing.T) {
258 // Create a temporary config file for the mapper
259 tmpDir := t.TempDir()
260 configFile := filepath.Join(tmpDir, "test-config.yaml")
261 configContent := `- id: test-mapper
262 mappings:
263 - "[A] <> [B]"`
264
265 err := os.WriteFile(configFile, []byte(configContent), 0644)
266 require.NoError(t, err)
267
268 // Create mapper with config
269 m, err := mapper.NewMapper(configFile)
270 require.NoError(t, err)
271
272 // Create fiber app
273 app := fiber.New()
274 setupRoutes(app, m)
275
276 // Test health endpoint
277 req := httptest.NewRequest(http.MethodGet, "/health", nil)
278 resp, err := app.Test(req)
279 require.NoError(t, err)
280 defer resp.Body.Close()
281
282 assert.Equal(t, http.StatusOK, resp.StatusCode)
283 body, err := io.ReadAll(resp.Body)
284 require.NoError(t, err)
285 assert.Equal(t, "OK", string(body))
286}