package diagnostics import ( "fmt" "strings" "testing" "unicode/utf8" "gitea.maximumdirect.net/eric/notarius/internal/core/source" "gitea.maximumdirect.net/eric/notarius/internal/framework/contracts" ) func TestCorrectionsGroupRulesBeforeContextAndHideKeys(t *testing.T) { var corrections Corrections corrections.Add("internal-kind", "Use a supported kind.", "Affected goblin at source unit 4.") corrections.Add("internal-kind", "Use a supported kind.", "Affected ogre at source units 8-9.") corrections.Add("internal-kind", "Use a supported kind.", "Affected goblin at source unit 4.") corrections.Add("name", "Provide a contextual name.", "Affected unnamed record at source unit 12.") guidance := corrections.Guidance("Correct every record") if strings.Contains(guidance, "internal-kind") { t.Fatalf("Guidance() exposed grouping key: %q", guidance) } if strings.Count(guidance, "Use a supported kind.") != 1 || strings.Count(guidance, "Affected goblin") != 1 { t.Fatalf("Guidance() did not de-duplicate rules and records: %q", guidance) } if strings.Index(guidance, "Use a supported kind.") > strings.Index(guidance, "Affected goblin") { t.Fatalf("Guidance() = %q, want rules before records", guidance) } } func TestSourceRangeUsesOnlyTranscriptPositions(t *testing.T) { refs := []source.SourceRef{ {SourceID: "opaque-source", StartUnitID: 8, EndUnitID: 10}, {SourceID: "opaque-source", StartUnitID: 12, EndUnitID: 12}, } got := SourceRange(refs) if strings.Contains(got, "opaque-source") || !strings.Contains(got, "8-10") || !strings.Contains(got, "first of 2") { t.Fatalf("SourceRange() = %q", got) } } func TestAggregateEnforcesByteBudgetAndReportsOmissions(t *testing.T) { issues := make([]string, MaxIssues) for index := range issues { issues[index] = fmt.Sprintf("issue-%d-%s", index, strings.Repeat("火", MaxDisplayedRunes)) } message := Aggregate("invalid D&D data", issues) if !utf8.ValidString(message) || len([]byte(message)) > MaxMessageBytes { t.Fatalf("Aggregate() returned invalid or oversized message: bytes=%d message=%q", len([]byte(message)), message) } displayed := strings.Count(message, "issue-") if displayed == 0 || displayed >= len(issues) { t.Fatalf("Aggregate() displayed %d issues, want byte-budget omission", displayed) } wantOmitted := fmt.Sprintf("%d additional issue(s) omitted", len(issues)-displayed) if !strings.Contains(message, wantOmitted) { t.Fatalf("Aggregate() = %q, want %q", message, wantOmitted) } } func TestDataQualityResultGroupsFindingsWithoutWarnings(t *testing.T) { result, err := DataQualityResult([]Finding{ {Scope: "records[0]", ReasonCode: "not_near_source", Message: "first"}, {Scope: "records[0]", ReasonCode: "not_near_source", Message: "first"}, {Scope: "records[1]", ReasonCode: "not_near_source", Message: "second"}, }) if err != nil { t.Fatal(err) } if !result.Approved || len(result.Diagnostics) != 1 { t.Fatalf("result = %#v", result) } diagnostic := result.Diagnostics[0] if diagnostic.Disposition != contracts.DiagnosticDispositionAdvisory || diagnostic.Category != contracts.DiagnosticCategoryDataQuality || diagnostic.OccurrenceCount != 3 || diagnostic.OmittedSampleCount != 1 || len(diagnostic.Samples) != 2 { t.Fatalf("diagnostic = %#v", diagnostic) } } func TestCollectGroupsNormalizationFindingsWithBoundedSamples(t *testing.T) { findings := make([]Finding, 5) for index := range findings { findings[index] = Finding{ Scope: fmt.Sprintf("records[%d]", index), ReasonCode: "record_normalized", Message: fmt.Sprintf("record %d normalized", index), } } groups, err := Collect(findings, contracts.DiagnosticDispositionObservation, contracts.DiagnosticCategoryNormalization) if err != nil { t.Fatal(err) } if len(groups) != 1 { t.Fatalf("groups = %#v, want one grouped observation", groups) } diagnostic := groups[0] if diagnostic.Disposition != contracts.DiagnosticDispositionObservation || diagnostic.Category != contracts.DiagnosticCategoryNormalization || diagnostic.OccurrenceCount != 5 || len(diagnostic.Samples) != contracts.MaxDiagnosticSamples || diagnostic.OmittedSampleCount != 2 { t.Fatalf("diagnostic = %#v", diagnostic) } } func TestNormalizationDiagnosticsCombinesQualityAndCleanupWithoutWarnings(t *testing.T) { groups, err := NormalizationDiagnostics([]Finding{ {Scope: "spell_casts[0]", ReasonCode: "spell_name_canonicalized", Message: "canonicalized spell name"}, {Scope: "spell_casts[1]", ReasonCode: "spell_name_unresolved", Message: "spell was not in the catalog"}, }, "spell_name_unresolved") if err != nil { t.Fatal(err) } if len(groups) != 2 || groups[0].Disposition != contracts.DiagnosticDispositionObservation || groups[1].Disposition != contracts.DiagnosticDispositionAdvisory { t.Fatalf("groups = %#v, want cleanup observation and quality advisory", groups) } for _, group := range groups { if group.Disposition == contracts.DiagnosticDispositionWarning { t.Fatalf("groups = %#v, want zero warning groups", groups) } } }