blob: 1311a4697ed705c94d84cdf8557f9ee9235b9299 [file] [log] [blame]
Akronb7e1f352025-05-16 15:45:23 +02001package ast
2
3import (
Akron8b3942b2025-05-23 13:36:37 +02004 "encoding/json"
Akronb7e1f352025-05-16 15:45:23 +02005 "testing"
6
7 "github.com/stretchr/testify/assert"
8)
9
10func TestNodeTypes(t *testing.T) {
11 tests := []struct {
12 name string
13 node Node
14 expected NodeType
15 }{
16 {
17 name: "Token node returns correct type",
18 node: &Token{Wrap: &Term{}},
19 expected: TokenNode,
20 },
21 {
22 name: "TermGroup node returns correct type",
23 node: &TermGroup{
24 Operands: []Node{&Term{}},
25 Relation: AndRelation,
26 },
27 expected: TermGroupNode,
28 },
29 {
30 name: "Term node returns correct type",
31 node: &Term{
32 Foundry: "opennlp",
33 Key: "DET",
34 Layer: "p",
35 Match: MatchEqual,
36 },
37 expected: TermNode,
38 },
39 }
40
41 for _, tt := range tests {
42 t.Run(tt.name, func(t *testing.T) {
43 assert.Equal(t, tt.expected, tt.node.Type())
44 })
45 }
46}
47
48func TestTermGroupConstruction(t *testing.T) {
49 term1 := &Term{
50 Foundry: "opennlp",
51 Key: "DET",
52 Layer: "p",
53 Match: MatchEqual,
54 }
55
56 term2 := &Term{
57 Foundry: "opennlp",
58 Key: "AdjType",
59 Layer: "m",
60 Match: MatchEqual,
61 Value: "Pdt",
62 }
63
64 group := &TermGroup{
65 Operands: []Node{term1, term2},
66 Relation: AndRelation,
67 }
68
69 assert.Len(t, group.Operands, 2)
70 assert.Equal(t, AndRelation, group.Relation)
71 assert.Equal(t, TermGroupNode, group.Type())
72
73 // Test operands are correctly set
74 assert.Equal(t, term1, group.Operands[0])
75 assert.Equal(t, term2, group.Operands[1])
76}
77
78func TestTokenConstruction(t *testing.T) {
79 term := &Term{
80 Foundry: "opennlp",
81 Key: "DET",
82 Layer: "p",
83 Match: MatchEqual,
84 }
85
86 token := &Token{Wrap: term}
87
88 assert.Equal(t, TokenNode, token.Type())
89 assert.Equal(t, term, token.Wrap)
90}
91
92func TestTermConstruction(t *testing.T) {
93 tests := []struct {
94 name string
95 term *Term
96 foundry string
97 key string
98 layer string
99 match MatchType
100 hasValue bool
101 value string
102 }{
103 {
104 name: "Term without value",
105 term: &Term{
106 Foundry: "opennlp",
107 Key: "DET",
108 Layer: "p",
109 Match: MatchEqual,
110 },
111 foundry: "opennlp",
112 key: "DET",
113 layer: "p",
114 match: MatchEqual,
115 hasValue: false,
116 },
117 {
118 name: "Term with value",
119 term: &Term{
120 Foundry: "opennlp",
121 Key: "AdjType",
122 Layer: "m",
123 Match: MatchEqual,
124 Value: "Pdt",
125 },
126 foundry: "opennlp",
127 key: "AdjType",
128 layer: "m",
129 match: MatchEqual,
130 hasValue: true,
131 value: "Pdt",
132 },
133 {
134 name: "Term with not equal match",
135 term: &Term{
136 Foundry: "opennlp",
137 Key: "DET",
138 Layer: "p",
139 Match: MatchNotEqual,
140 },
141 foundry: "opennlp",
142 key: "DET",
143 layer: "p",
144 match: MatchNotEqual,
145 hasValue: false,
146 },
147 }
148
149 for _, tt := range tests {
150 t.Run(tt.name, func(t *testing.T) {
151 assert.Equal(t, TermNode, tt.term.Type())
152 assert.Equal(t, tt.foundry, tt.term.Foundry)
153 assert.Equal(t, tt.key, tt.term.Key)
154 assert.Equal(t, tt.layer, tt.term.Layer)
155 assert.Equal(t, tt.match, tt.term.Match)
156 if tt.hasValue {
157 assert.Equal(t, tt.value, tt.term.Value)
158 } else {
159 assert.Empty(t, tt.term.Value)
160 }
161 })
162 }
163}
164
165func TestPatternAndReplacement(t *testing.T) {
166 // Create a simple pattern
167 patternTerm := &Term{
168 Foundry: "opennlp",
169 Key: "DET",
170 Layer: "p",
171 Match: MatchEqual,
172 }
173 pattern := Pattern{Root: patternTerm}
174
175 // Create a simple replacement
176 replacementTerm := &Term{
177 Foundry: "opennlp",
178 Key: "COMBINED_DET",
179 Layer: "p",
180 Match: MatchEqual,
181 }
182 replacement := Replacement{Root: replacementTerm}
183
184 // Test pattern
185 assert.NotNil(t, pattern.Root)
186 assert.Equal(t, patternTerm, pattern.Root)
187
188 // Test replacement
189 assert.NotNil(t, replacement.Root)
190 assert.Equal(t, replacementTerm, replacement.Root)
191}
Akron8b3942b2025-05-23 13:36:37 +0200192
193func TestCatchallNode(t *testing.T) {
194 tests := []struct {
195 name string
196 nodeType string
197 content string
198 wrap Node
199 operands []Node
200 expectType NodeType
201 }{
202 {
203 name: "CatchallNode with custom type",
204 nodeType: "customType",
205 content: `{"key": "value"}`,
206 expectType: NodeType("customType"),
207 },
208 {
209 name: "CatchallNode with wrapped term",
210 nodeType: "wrapper",
211 content: `{"key": "value"}`,
212 wrap: &Term{
213 Foundry: "test",
214 Key: "TEST",
215 Layer: "x",
216 Match: MatchEqual,
217 },
218 expectType: NodeType("wrapper"),
219 },
220 {
221 name: "CatchallNode with operands",
222 nodeType: "custom_group",
223 content: `{"key": "value"}`,
224 operands: []Node{
225 &Term{Foundry: "test1", Key: "TEST1", Layer: "x", Match: MatchEqual},
226 &Term{Foundry: "test2", Key: "TEST2", Layer: "y", Match: MatchEqual},
227 },
228 expectType: NodeType("custom_group"),
229 },
230 }
231
232 for _, tt := range tests {
233 t.Run(tt.name, func(t *testing.T) {
234 rawContent := json.RawMessage(tt.content)
235 node := &CatchallNode{
236 NodeType: tt.nodeType,
237 RawContent: rawContent,
238 Wrap: tt.wrap,
239 Operands: tt.operands,
240 }
241
242 assert.Equal(t, tt.expectType, node.Type())
243 if tt.wrap != nil {
244 assert.Equal(t, tt.wrap, node.Wrap)
245 }
246 if tt.operands != nil {
247 assert.Equal(t, tt.operands, node.Operands)
248 }
249 assert.Equal(t, rawContent, node.RawContent)
250 })
251 }
252}
253
254func TestComplexNestedStructures(t *testing.T) {
255 // Create a complex nested structure
256 innerGroup1 := &TermGroup{
257 Operands: []Node{
258 &Term{Foundry: "f1", Key: "k1", Layer: "l1", Match: MatchEqual},
259 &Term{Foundry: "f2", Key: "k2", Layer: "l2", Match: MatchNotEqual},
260 },
261 Relation: AndRelation,
262 }
263
264 innerGroup2 := &TermGroup{
265 Operands: []Node{
266 &Term{Foundry: "f3", Key: "k3", Layer: "l3", Match: MatchEqual},
267 &Term{Foundry: "f4", Key: "k4", Layer: "l4", Match: MatchEqual, Value: "test"},
268 },
269 Relation: OrRelation,
270 }
271
272 topGroup := &TermGroup{
273 Operands: []Node{
274 innerGroup1,
275 innerGroup2,
276 &Token{Wrap: &Term{Foundry: "f5", Key: "k5", Layer: "l5", Match: MatchEqual}},
277 },
278 Relation: AndRelation,
279 }
280
281 assert.Equal(t, TermGroupNode, topGroup.Type())
282 assert.Len(t, topGroup.Operands, 3)
283 assert.Equal(t, AndRelation, topGroup.Relation)
284
285 // Test inner groups
286 group1 := topGroup.Operands[0].(*TermGroup)
287 assert.Len(t, group1.Operands, 2)
288 assert.Equal(t, AndRelation, group1.Relation)
289
290 group2 := topGroup.Operands[1].(*TermGroup)
291 assert.Len(t, group2.Operands, 2)
292 assert.Equal(t, OrRelation, group2.Relation)
293
294 // Test token wrapping
295 token := topGroup.Operands[2].(*Token)
296 assert.NotNil(t, token.Wrap)
297 assert.Equal(t, TermNode, token.Wrap.Type())
298}
299
300func TestEdgeCases(t *testing.T) {
301 tests := []struct {
302 name string
303 test func(t *testing.T)
304 }{
305 {
306 name: "Empty TermGroup",
307 test: func(t *testing.T) {
308 group := &TermGroup{
309 Operands: []Node{},
310 Relation: AndRelation,
311 }
312 assert.Empty(t, group.Operands)
313 assert.Equal(t, AndRelation, group.Relation)
314 },
315 },
316 {
317 name: "Token with nil wrap",
318 test: func(t *testing.T) {
319 token := &Token{Wrap: nil}
320 assert.Equal(t, TokenNode, token.Type())
321 assert.Nil(t, token.Wrap)
322 },
323 },
324 {
325 name: "Term with empty strings",
326 test: func(t *testing.T) {
327 term := &Term{
328 Foundry: "",
329 Key: "",
330 Layer: "",
331 Match: MatchEqual,
332 Value: "",
333 }
334 assert.Equal(t, TermNode, term.Type())
335 assert.Empty(t, term.Foundry)
336 assert.Empty(t, term.Key)
337 assert.Empty(t, term.Layer)
338 assert.Empty(t, term.Value)
339 },
340 },
341 {
342 name: "Complex Pattern and Replacement",
343 test: func(t *testing.T) {
344 // Create a complex pattern
345 patternGroup := &TermGroup{
346 Operands: []Node{
347 &Term{Foundry: "f1", Key: "k1", Layer: "l1", Match: MatchEqual},
348 &Token{Wrap: &Term{Foundry: "f2", Key: "k2", Layer: "l2", Match: MatchNotEqual}},
349 },
350 Relation: OrRelation,
351 }
352 pattern := Pattern{Root: patternGroup}
353
354 // Create a complex replacement
355 replacementGroup := &TermGroup{
356 Operands: []Node{
357 &Term{Foundry: "f3", Key: "k3", Layer: "l3", Match: MatchEqual},
358 &Term{Foundry: "f4", Key: "k4", Layer: "l4", Match: MatchEqual},
359 },
360 Relation: AndRelation,
361 }
362 replacement := Replacement{Root: replacementGroup}
363
364 assert.Equal(t, TermGroupNode, pattern.Root.Type())
365 assert.Equal(t, TermGroupNode, replacement.Root.Type())
366 },
367 },
368 }
369
370 for _, tt := range tests {
371 t.Run(tt.name, tt.test)
372 }
373}