@@ -19,23 +19,41 @@ import (
19
19
// FakeMatcher implements both Matcher and Embedder interfaces for testing
20
20
type FakeMatcher struct {
21
21
// Configured responses for testing
22
- matchResponse bool
23
- matchScore float64
24
- matchError error
25
- embeddings []float32
26
- embeddingsError error
22
+ matchResponse bool
23
+ matchScore float64
24
+ matchCount int
25
+ totalCount int
26
+ matchError error
27
+ embeddings []float32
28
+ embeddingsError error
29
+ capabilitiesToMatch map [string ]any
27
30
}
28
31
29
32
func NewFakeMatcher () * FakeMatcher {
30
33
return & FakeMatcher {
31
- matchResponse : true ,
32
- matchScore : 0.9 ,
33
- embeddings : []float32 {0.1 , 0.2 , 0.3 },
34
+ matchResponse : true ,
35
+ matchScore : 0.9 ,
36
+ embeddings : []float32 {0.1 , 0.2 , 0.3 },
37
+ capabilitiesToMatch : make (map [string ]any ),
34
38
}
35
39
}
36
40
41
+ // In the same file, update the FakeMatcher MatchTexts method:
37
42
func (f * FakeMatcher ) MatchTexts (_ context.Context , _ , _ string , _ float64 ) (bool , float64 , error ) {
38
- return f .matchResponse , f .matchScore , f .matchError
43
+ if f .matchError != nil {
44
+ return false , 0 , f .matchError
45
+ }
46
+
47
+ // For specific capability testing (like the 88.24% case)
48
+ if f .matchCount >= 0 && f .totalCount > 0 {
49
+ f .matchCount ++
50
+ // Only match the first 88.24% of capabilities
51
+ match := f .matchCount <= int (float64 (f .totalCount )* 0.8824 )
52
+ return match , f .matchScore , nil
53
+ }
54
+
55
+ // Default behavior for other test cases
56
+ return f .matchResponse , f .matchScore , nil
39
57
}
40
58
41
59
func (f * FakeMatcher ) GenerateEmbeddingVector (_ context.Context , _ string ) (* mat.VecDense , error ) {
@@ -162,22 +180,25 @@ func TestPddlDomainGenerator_GenerateDomain(t *testing.T) {
162
180
}
163
181
164
182
func TestPddlDomainGenerator_ValidateServiceCapabilities (t * testing.T ) {
165
- useCase := GroundingUseCase {
166
- Capabilities : []string {
167
- "Verify refund eligibility" ,
168
- "Process payment refund" ,
169
- },
170
- }
171
-
172
183
tests := []struct {
173
- name string
174
- matchResult bool
175
- tasks []* SubTask
176
- wantErr bool
184
+ name string
185
+ useCase GroundingUseCase
186
+ matchResult bool
187
+ matchScore float64
188
+ tasks []* SubTask
189
+ expectedErr bool
190
+ expectedErrMsg string
177
191
}{
178
192
{
179
- name : "matching capabilities" ,
193
+ name : "all capabilities matched" ,
194
+ useCase : GroundingUseCase {
195
+ Capabilities : []string {
196
+ "Verify refund eligibility" ,
197
+ "Process payment refund" ,
198
+ },
199
+ },
180
200
matchResult : true ,
201
+ matchScore : 0.9 ,
181
202
tasks : []* SubTask {
182
203
{
183
204
ID : "task1" ,
@@ -187,38 +208,137 @@ func TestPddlDomainGenerator_ValidateServiceCapabilities(t *testing.T) {
187
208
},
188
209
},
189
210
},
190
- wantErr : false ,
211
+ expectedErr : false ,
191
212
},
192
213
{
193
- name : "missing capability" ,
194
- matchResult : false ,
214
+ name : "exactly 95% capabilities matched" ,
215
+ useCase : GroundingUseCase {
216
+ Capabilities : []string {
217
+ "Verify refund eligibility" ,
218
+ "Process payment refund" ,
219
+ "Send confirmation email" ,
220
+ "Update order status" ,
221
+ "Notify customer service" ,
222
+ "Update inventory" ,
223
+ "Calculate tax refund" ,
224
+ "Process loyalty points" ,
225
+ "Record transaction" ,
226
+ "Generate receipt" ,
227
+ "Archive refund record" ,
228
+ "Update customer history" ,
229
+ "Check fraud indicators" ,
230
+ "Validate shipping status" ,
231
+ "Update payment gateway" ,
232
+ "Check compliance rules" ,
233
+ "Record audit trail" ,
234
+ "Update financial records" ,
235
+ "Process chargeback" ,
236
+ "Update metrics" ,
237
+ },
238
+ },
239
+ matchResult : true ,
240
+ matchScore : 0.8 ,
195
241
tasks : []* SubTask {
196
242
{
197
243
ID : "task1" ,
198
244
Service : "refund-service" ,
199
245
Capabilities : []string {
200
- "A service that only processes payments " ,
246
+ "Comprehensive refund processing service with validation " ,
201
247
},
202
248
},
203
249
},
204
- wantErr : true ,
250
+ expectedErr : false ,
251
+ },
252
+ {
253
+ name : "88.24% capabilities matched (below threshold)" ,
254
+ useCase : GroundingUseCase {
255
+ Capabilities : []string {
256
+ "Cap1" , "Cap2" , "Cap3" , "Cap4" , "Cap5" ,
257
+ "Cap6" , "Cap7" , "Cap8" , "Cap9" , "Cap10" ,
258
+ "Cap11" , "Cap12" , "Cap13" , "Cap14" , "Cap15" ,
259
+ "Cap16" , "Cap17" ,
260
+ },
261
+ },
262
+ matchResult : true , // Match first 16 capabilities
263
+ matchScore : 0.8 ,
264
+ tasks : []* SubTask {
265
+ {
266
+ ID : "task1" ,
267
+ Service : "test-service" ,
268
+ Capabilities : []string {
269
+ "Generic service capability" ,
270
+ },
271
+ },
272
+ },
273
+ expectedErr : true ,
274
+ expectedErrMsg : "insufficient capability coverage: 88.24%" ,
275
+ },
276
+ {
277
+ name : "no capabilities matched" ,
278
+ useCase : GroundingUseCase {
279
+ Capabilities : []string {
280
+ "Verify refund eligibility" ,
281
+ "Process payment refund" ,
282
+ },
283
+ },
284
+ matchResult : false ,
285
+ matchScore : 0.7 ,
286
+ tasks : []* SubTask {
287
+ {
288
+ ID : "task1" ,
289
+ Service : "unrelated-service" ,
290
+ Capabilities : []string {
291
+ "A completely different service capability" ,
292
+ },
293
+ },
294
+ },
295
+ expectedErr : true ,
296
+ expectedErrMsg : "insufficient capability coverage: 0.00%" ,
205
297
},
206
298
}
207
299
208
300
for _ , tt := range tests {
209
301
t .Run (tt .name , func (t * testing.T ) {
302
+ // Setup test logger to capture logs
303
+ var logBuf strings.Builder
304
+ testLogger := zerolog .New (& logBuf )
305
+
306
+ // Configure fake matcher for specific test case
210
307
matcher := NewFakeMatcher ()
211
308
matcher .matchResponse = tt .matchResult
309
+ matcher .matchScore = tt .matchScore
212
310
213
- generator := NewPddlGenerator ("test-action" , & ExecutionPlan {Tasks : tt .tasks }, matcher , zerolog .Nop ())
311
+ // For the 88.24% test case, set up specific matches
312
+ if tt .name == "88.24% capabilities matched (below threshold)" {
313
+ // Add these two lines here:
314
+ matcher .matchCount = 0
315
+ matcher .totalCount = len (tt .useCase .Capabilities )
316
+ }
317
+
318
+ // Create generator with test configuration
319
+ generator := NewPddlGenerator ("test-action" , & ExecutionPlan {Tasks : tt .tasks }, matcher , testLogger )
320
+
321
+ // Execute validation
322
+ err := generator .validateServiceCapabilities (context .Background (), tt .useCase )
214
323
215
- err := generator . validateServiceCapabilities ( context . Background (), useCase )
216
- if tt .wantErr {
324
+ // Verify error cases
325
+ if tt .expectedErr {
217
326
assert .Error (t , err )
218
- assert .Contains (t , err .Error (), "no service found with required capability" )
327
+ if tt .expectedErrMsg != "" {
328
+ assert .Contains (t , err .Error (), tt .expectedErrMsg )
329
+ }
219
330
} else {
220
331
assert .NoError (t , err )
221
332
}
333
+
334
+ // Verify logging
335
+ logOutput := logBuf .String ()
336
+ assert .Contains (t , logOutput , "Matching capabilities" )
337
+ assert .Contains (t , logOutput , "Capability matching summary" )
338
+
339
+ if ! tt .expectedErr {
340
+ assert .Contains (t , logOutput , `"matchPercentage":1` ) // 100% for full match cases
341
+ }
222
342
})
223
343
}
224
344
}
0 commit comments