blob: 326625f24246c75f47aecca6317808e637f83d55 [file] [log] [blame]
Akrone562ad62025-06-25 11:15:56 +02001package parser
2
3import (
4 "testing"
5
6 "github.com/KorAP/KoralPipe-TermMapper/ast"
7 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/require"
9)
10
11func TestTitleAttributeParser_ParseTitleAttribute(t *testing.T) {
12 parser := NewTitleAttributeParser()
13
14 tests := []struct {
15 name string
16 input string
17 expected *TitleAttribute
18 wantErr bool
19 }{
20 {
21 name: "Parse simple title with key only",
22 input: "corenlp/p:ART",
23 expected: &TitleAttribute{
24 Foundry: "corenlp",
25 Layer: "p",
26 Key: "ART",
27 Value: "",
28 },
29 wantErr: false,
30 },
31 {
32 name: "Parse title with key and value",
Akron7de5b612025-06-26 16:15:03 +020033 input: "marmot/m:case:nom",
Akrone562ad62025-06-25 11:15:56 +020034 expected: &TitleAttribute{
35 Foundry: "marmot",
36 Layer: "m",
37 Key: "case",
38 Value: "nom",
39 },
40 wantErr: false,
41 },
42 {
43 name: "Parse title with colon separator for value",
44 input: "marmot/m:gender:masc",
45 expected: &TitleAttribute{
46 Foundry: "marmot",
47 Layer: "m",
48 Key: "gender",
49 Value: "masc",
50 },
51 wantErr: false,
52 },
53 {
54 name: "Parse title with equals separator for value",
Akron7de5b612025-06-26 16:15:03 +020055 input: "marmot/m:degree:pos",
Akrone562ad62025-06-25 11:15:56 +020056 expected: &TitleAttribute{
57 Foundry: "marmot",
58 Layer: "m",
59 Key: "degree",
60 Value: "pos",
61 },
62 wantErr: false,
63 },
64 {
65 name: "Parse title with lemma layer",
66 input: "tt/l:die",
67 expected: &TitleAttribute{
68 Foundry: "tt",
69 Layer: "l",
70 Key: "die",
71 Value: "",
72 },
73 wantErr: false,
74 },
75 {
76 name: "Parse title with special characters in value",
77 input: "tt/l:@card@",
78 expected: &TitleAttribute{
79 Foundry: "tt",
80 Layer: "l",
81 Key: "@card@",
82 Value: "",
83 },
84 wantErr: false,
85 },
86 {
87 name: "Empty title should fail",
88 input: "",
89 wantErr: true,
90 },
91 {
92 name: "Missing foundry separator should fail",
93 input: "corenlp_p:ART",
94 wantErr: true,
95 },
96 {
97 name: "Missing layer separator should fail",
98 input: "corenlp/p_ART",
99 wantErr: true,
100 },
101 {
102 name: "Only foundry should fail",
103 input: "corenlp",
104 wantErr: true,
105 },
106 {
107 name: "Only foundry and layer should fail",
108 input: "corenlp/p",
109 wantErr: true,
110 },
111 }
112
113 for _, tt := range tests {
114 t.Run(tt.name, func(t *testing.T) {
115 result, err := parser.ParseTitleAttribute(tt.input)
116
117 if tt.wantErr {
118 assert.Error(t, err)
119 assert.Nil(t, result)
120 } else {
121 require.NoError(t, err)
122 require.NotNil(t, result)
123 assert.Equal(t, tt.expected.Foundry, result.Foundry)
124 assert.Equal(t, tt.expected.Layer, result.Layer)
125 assert.Equal(t, tt.expected.Key, result.Key)
126 assert.Equal(t, tt.expected.Value, result.Value)
127 }
128 })
129 }
130}
131
132func TestTitleAttributeParser_ParseTitleAttributesToTerms(t *testing.T) {
133 parser := NewTitleAttributeParser()
134
135 tests := []struct {
136 name string
137 input []string
138 expected []ast.Node
139 wantErr bool
140 }{
141 {
142 name: "Parse multiple title attributes",
Akron7de5b612025-06-26 16:15:03 +0200143 input: []string{"corenlp/p:ART", "marmot/m:case:nom", "tt/l:die"},
Akrone562ad62025-06-25 11:15:56 +0200144 expected: []ast.Node{
145 &ast.Term{
146 Foundry: "corenlp",
147 Layer: "p",
148 Key: "ART",
149 Value: "",
150 Match: ast.MatchEqual,
151 },
152 &ast.Term{
153 Foundry: "marmot",
154 Layer: "m",
155 Key: "case",
156 Value: "nom",
157 Match: ast.MatchEqual,
158 },
159 &ast.Term{
160 Foundry: "tt",
161 Layer: "l",
162 Key: "die",
163 Value: "",
164 Match: ast.MatchEqual,
165 },
166 },
167 wantErr: false,
168 },
169 {
170 name: "Empty input should return empty slice",
171 input: []string{},
172 expected: []ast.Node{},
173 wantErr: false,
174 },
175 {
176 name: "Invalid title should cause error",
177 input: []string{"corenlp/p:ART", "invalid_title", "tt/l:die"},
178 wantErr: true,
179 },
180 }
181
182 for _, tt := range tests {
183 t.Run(tt.name, func(t *testing.T) {
184 result, err := parser.ParseTitleAttributesToTerms(tt.input)
185
186 if tt.wantErr {
187 assert.Error(t, err)
188 } else {
189 require.NoError(t, err)
190 require.Len(t, result, len(tt.expected))
191
192 for i, expectedTerm := range tt.expected {
193 expectedTermNode := expectedTerm.(*ast.Term)
194 actualTermNode := result[i].(*ast.Term)
195
196 assert.Equal(t, expectedTermNode.Foundry, actualTermNode.Foundry)
197 assert.Equal(t, expectedTermNode.Layer, actualTermNode.Layer)
198 assert.Equal(t, expectedTermNode.Key, actualTermNode.Key)
199 assert.Equal(t, expectedTermNode.Value, actualTermNode.Value)
200 assert.Equal(t, expectedTermNode.Match, actualTermNode.Match)
201 }
202 }
203 })
204 }
205}
206
207func TestTitleAttribute_ToAST(t *testing.T) {
208 tests := []struct {
209 name string
210 attr *TitleAttribute
211 expected *ast.Term
212 }{
213 {
214 name: "Convert title attribute to AST term",
215 attr: &TitleAttribute{
216 Foundry: "corenlp",
217 Layer: "p",
218 Key: "ART",
219 Value: "",
220 },
221 expected: &ast.Term{
222 Foundry: "corenlp",
223 Layer: "p",
224 Key: "ART",
225 Value: "",
226 Match: ast.MatchEqual,
227 },
228 },
229 {
230 name: "Convert title attribute with value to AST term",
231 attr: &TitleAttribute{
232 Foundry: "marmot",
233 Layer: "m",
234 Key: "case",
235 Value: "nom",
236 },
237 expected: &ast.Term{
238 Foundry: "marmot",
239 Layer: "m",
240 Key: "case",
241 Value: "nom",
242 Match: ast.MatchEqual,
243 },
244 },
245 }
246
247 for _, tt := range tests {
248 t.Run(tt.name, func(t *testing.T) {
249 result := tt.attr.ToAST()
250
251 termResult := result.(*ast.Term)
252 assert.Equal(t, tt.expected.Foundry, termResult.Foundry)
253 assert.Equal(t, tt.expected.Layer, termResult.Layer)
254 assert.Equal(t, tt.expected.Key, termResult.Key)
255 assert.Equal(t, tt.expected.Value, termResult.Value)
256 assert.Equal(t, tt.expected.Match, termResult.Match)
257 })
258 }
259}
260
261func TestTitleAttribute_String(t *testing.T) {
262 tests := []struct {
263 name string
264 attr *TitleAttribute
265 expected string
266 }{
267 {
268 name: "String representation without value",
269 attr: &TitleAttribute{
270 Foundry: "corenlp",
271 Layer: "p",
272 Key: "ART",
273 Value: "",
274 },
275 expected: "corenlp/p:ART",
276 },
277 {
278 name: "String representation with value",
279 attr: &TitleAttribute{
280 Foundry: "marmot",
281 Layer: "m",
282 Key: "case",
283 Value: "nom",
284 },
285 expected: "marmot/m:case=nom",
286 },
287 }
288
289 for _, tt := range tests {
290 t.Run(tt.name, func(t *testing.T) {
291 result := tt.attr.String()
292 assert.Equal(t, tt.expected, result)
293 })
294 }
295}
296
297func TestTitleAttributeParser_RealWorldExample(t *testing.T) {
298 parser := NewTitleAttributeParser()
299
300 // Example titles from the response test file
301 titles := []string{
302 "corenlp/p:ART",
303 "marmot/m:case=nom",
304 "marmot/m:gender=masc",
305 "marmot/m:number=sg",
306 "marmot/p:ART",
307 "opennlp/p:ART",
308 "tt/l:die",
309 "tt/p:ART",
310 }
311
312 // Parse each title attribute
313 for _, title := range titles {
314 attr, err := parser.ParseTitleAttribute(title)
315 require.NoError(t, err)
316 require.NotNil(t, attr)
317
318 // Verify the string representation matches
319 assert.Equal(t, title, attr.String())
320
321 // Verify conversion to AST works
322 astNode := attr.ToAST()
323 require.NotNil(t, astNode)
324
325 term := astNode.(*ast.Term)
326 assert.NotEmpty(t, term.Foundry)
327 assert.NotEmpty(t, term.Layer)
328 assert.NotEmpty(t, term.Key)
329 assert.Equal(t, ast.MatchEqual, term.Match)
330 }
331}