@@ -3,6 +3,9 @@ package cli
33import (
44 "strings"
55 "testing"
6+
7+ "github.com/dotcommander/cclint/internal/cue"
8+ "github.com/dotcommander/cclint/internal/discovery"
69)
710
811func TestValidateAgentSpecific (t * testing.T ) {
@@ -248,3 +251,135 @@ func TestKnownAgentFields(t *testing.T) {
248251 }
249252 }
250253}
254+
255+ func TestAgentLinterPostProcessBatch (t * testing.T ) {
256+ linter := NewAgentLinter ()
257+
258+ tests := []struct {
259+ name string
260+ files []discovery.File
261+ noCycleCheck bool
262+ wantCycleErrors int
263+ wantTotalErrors int
264+ wantFailedFiles int
265+ wantSuccessFiles int
266+ }{
267+ {
268+ name : "no cycles detected" ,
269+ files : []discovery.File {
270+ {
271+ RelPath : "agents/agent-a.md" ,
272+ Type : discovery .FileTypeAgent ,
273+ Contents : "Skill: skill-a" ,
274+ },
275+ {
276+ RelPath : "skills/skill-a/SKILL.md" ,
277+ Type : discovery .FileTypeSkill ,
278+ Contents : "Skill content" ,
279+ },
280+ },
281+ noCycleCheck : false ,
282+ wantCycleErrors : 0 ,
283+ wantTotalErrors : 0 ,
284+ wantFailedFiles : 0 ,
285+ wantSuccessFiles : 2 ,
286+ },
287+ {
288+ name : "cycle detected" ,
289+ files : []discovery.File {
290+ {
291+ RelPath : "agents/agent-a.md" ,
292+ Type : discovery .FileTypeAgent ,
293+ Contents : "Task(agent-b)" ,
294+ },
295+ {
296+ RelPath : "agents/agent-b.md" ,
297+ Type : discovery .FileTypeAgent ,
298+ Contents : "Task(agent-a)" ,
299+ },
300+ },
301+ noCycleCheck : false ,
302+ wantCycleErrors : 2 , // One error per agent in cycle
303+ wantTotalErrors : 2 ,
304+ wantFailedFiles : 2 ,
305+ wantSuccessFiles : 0 ,
306+ },
307+ {
308+ name : "cycle check disabled" ,
309+ files : []discovery.File {
310+ {
311+ RelPath : "agents/agent-a.md" ,
312+ Type : discovery .FileTypeAgent ,
313+ Contents : "Task(agent-b)" ,
314+ },
315+ {
316+ RelPath : "agents/agent-b.md" ,
317+ Type : discovery .FileTypeAgent ,
318+ Contents : "Task(agent-a)" ,
319+ },
320+ },
321+ noCycleCheck : true ,
322+ wantCycleErrors : 0 , // Cycle check disabled
323+ wantTotalErrors : 0 ,
324+ wantFailedFiles : 0 ,
325+ wantSuccessFiles : 2 ,
326+ },
327+ }
328+
329+ for _ , tt := range tests {
330+ t .Run (tt .name , func (t * testing.T ) {
331+ crossValidator := NewCrossFileValidator (tt .files )
332+ ctx := & LinterContext {
333+ CrossValidator : crossValidator ,
334+ NoCycleCheck : tt .noCycleCheck ,
335+ }
336+
337+ // Create initial summary with all files successful
338+ summary := & LintSummary {
339+ TotalFiles : len (tt .files ),
340+ SuccessfulFiles : len (tt .files ),
341+ FailedFiles : 0 ,
342+ TotalErrors : 0 ,
343+ Results : make ([]LintResult , len (tt .files )),
344+ }
345+
346+ for i , file := range tt .files {
347+ summary .Results [i ] = LintResult {
348+ File : file .RelPath ,
349+ Type : "agent" ,
350+ Success : true ,
351+ Errors : []cue.ValidationError {},
352+ }
353+ }
354+
355+ // Run post-processing
356+ linter .PostProcessBatch (ctx , summary )
357+
358+ // Count cycle errors
359+ cycleErrors := 0
360+ for _ , result := range summary .Results {
361+ for _ , err := range result .Errors {
362+ if strings .Contains (err .Message , "Circular dependency" ) {
363+ cycleErrors ++
364+ }
365+ }
366+ }
367+
368+ if cycleErrors != tt .wantCycleErrors {
369+ t .Errorf ("PostProcessBatch() cycle errors = %d, want %d" , cycleErrors , tt .wantCycleErrors )
370+ }
371+
372+ if summary .TotalErrors != tt .wantTotalErrors {
373+ t .Errorf ("PostProcessBatch() TotalErrors = %d, want %d" , summary .TotalErrors , tt .wantTotalErrors )
374+ }
375+
376+ if summary .FailedFiles != tt .wantFailedFiles {
377+ t .Errorf ("PostProcessBatch() FailedFiles = %d, want %d" , summary .FailedFiles , tt .wantFailedFiles )
378+ }
379+
380+ if summary .SuccessfulFiles != tt .wantSuccessFiles {
381+ t .Errorf ("PostProcessBatch() SuccessfulFiles = %d, want %d" , summary .SuccessfulFiles , tt .wantSuccessFiles )
382+ }
383+ })
384+ }
385+ }
0 commit comments