package pipeline import ( "context" "testing" "gitea.maximumdirect.net/eric/notarius/internal/framework/contracts" ) func TestTerminalDiagnosticGroupsDiscardSupersededAttemptDiagnostics(t *testing.T) { terminal, err := runProducerAttempts(context.Background(), producerAttemptConfig{Retries: 1, Policy: DefaultValidationPolicy()}, func(_ context.Context, request producerAttemptRequest) (producerAttemptOutput, error) { if request.Number == 1 { return producerAttemptOutput{Value: "first", Diagnostics: []contracts.ProducerDiagnostic{producerDiagnostic("discarded", "discarded")}, Candidate: attemptCandidate(t, "first")}, nil } return producerAttemptOutput{Value: "second", Diagnostics: []contracts.ProducerDiagnostic{producerDiagnostic("terminal", "terminal")}}, nil }, func(_ context.Context, output producerAttemptOutput) (validationReport, error) { if output.Value == "first" { return validationReport{records: []validationRecord{{validatorName: "validator", outcome: validationRejected, reasonCode: "invalid", correctionGuidance: "Correct it."}}}, nil } return validationReport{}, nil }) if err != nil { t.Fatalf("runProducerAttempts() error = %v", err) } groups, err := terminalDiagnosticGroups(terminal, contracts.DiagnosticOrigin{Stage: contracts.DiagnosticOriginStageMerge, StepID: "step", LaneID: "lane", ModuleKey: "module"}, nil) if err != nil { t.Fatalf("terminalDiagnosticGroups() error = %v", err) } if len(groups) != 1 || groups[0].Samples[0].Scope != "terminal" { t.Fatalf("groups = %#v, want only terminal attempt diagnostics", groups) } } func TestTerminalDiagnosticGroupsPreserveValidatorOrigin(t *testing.T) { terminal := producerAttemptTerminal{Validation: validationReport{records: []validationRecord{{ validatorName: "dnd/spells/source-relatedness", outcome: validationApproved, diagnostics: []contracts.ProducerDiagnostic{producerDiagnostic("spells[0]", "not found")}, }}}} groups, err := terminalDiagnosticGroups(terminal, contracts.DiagnosticOrigin{Stage: contracts.DiagnosticOriginStageExtract, StepID: "extract", LaneID: "spells", ModuleKey: "dnd/spells"}, nil) if err != nil { t.Fatalf("terminalDiagnosticGroups() error = %v", err) } if len(groups) != 1 || groups[0].Origin.ValidatorKey != "dnd/spells/source-relatedness" { t.Fatalf("groups = %#v, want validator origin", groups) } } func TestAppendDiagnosticGroupsRetainsOnlyStructuredDiagnostics(t *testing.T) { output := RunOutput{} appendDiagnosticGroups(&output, []contracts.DiagnosticGroup{{ Disposition: contracts.DiagnosticDispositionAdvisory, Category: contracts.DiagnosticCategoryDataQuality, ReasonCode: "source_unrelated", Origin: contracts.DiagnosticOrigin{Stage: contracts.DiagnosticOriginStageExtract, StepID: "extract", LaneID: "spells", ModuleKey: "dnd/spells"}, OccurrenceCount: 2, Samples: []contracts.DiagnosticSample{{Scope: "spells[0]", Message: "not found"}, {Scope: "spells[1]", Message: "also not found"}}, }}) if err := finalizeDiagnostics(&output); err != nil { t.Fatalf("finalizeDiagnostics() error = %v", err) } if len(output.Diagnostics.Groups) != 1 || output.Diagnostics.Groups[0].OccurrenceCount != 2 { t.Fatalf("diagnostics = %#v, want grouped collection", output.Diagnostics) } } func producerDiagnostic(scope string, message string) contracts.ProducerDiagnostic { return contracts.ProducerDiagnostic{ Disposition: contracts.DiagnosticDispositionAdvisory, Category: contracts.DiagnosticCategoryDataQuality, ReasonCode: "source_unrelated", OccurrenceCount: 1, Samples: []contracts.DiagnosticSample{{Scope: scope, Message: message}}, } }