using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.Metrics; using StellaOps.Concelier.Models; using Xunit; using StellaOps.TestKit; namespace StellaOps.Concelier.Models.Tests; public sealed class OsvGhsaParityDiagnosticsTests { [Trait("Category", TestCategories.Unit)] [Fact] public void RecordReport_EmitsTotalAndIssues() { var issues = ImmutableArray.Create( new OsvGhsaParityIssue( GhsaId: "GHSA-AAA", IssueKind: "missing_osv", Detail: "", FieldMask: ImmutableArray.Create(ProvenanceFieldMasks.AffectedPackages)), new OsvGhsaParityIssue( GhsaId: "GHSA-BBB", IssueKind: "severity_mismatch", Detail: "", FieldMask: ImmutableArray.Empty)); var report = new OsvGhsaParityReport(2, issues); var measurements = new List<(string Instrument, long Value, IReadOnlyDictionary Tags)>(); using var listener = CreateListener(measurements); OsvGhsaParityDiagnostics.RecordReport(report, "QA"); listener.Dispose(); Assert.Equal(3, measurements.Count); var total = Assert.Single(measurements, m => m.Instrument == "concelier.osv_ghsa.total"); Assert.Equal(2, total.Value); Assert.Equal("qa", total.Tags["dataset"]); var missing = Assert.Single(measurements, m => m.Tags.TryGetValue("issueKind", out var kind) && string.Equals((string)kind!, "missing_osv", StringComparison.Ordinal)); Assert.Equal("affectedpackages[]", missing.Tags["fieldMask"]); var severity = Assert.Single(measurements, m => m.Tags.TryGetValue("issueKind", out var kind) && string.Equals((string)kind!, "severity_mismatch", StringComparison.Ordinal)); Assert.Equal("none", severity.Tags["fieldMask"]); } [Trait("Category", TestCategories.Unit)] [Fact] public void RecordReport_NoIssues_OnlyEmitsTotal() { var report = new OsvGhsaParityReport(0, ImmutableArray.Empty); var measurements = new List<(string Instrument, long Value, IReadOnlyDictionary Tags)>(); using var listener = CreateListener(measurements); OsvGhsaParityDiagnostics.RecordReport(report, ""); listener.Dispose(); Assert.Empty(measurements); } private static MeterListener CreateListener(List<(string Instrument, long Value, IReadOnlyDictionary Tags)> measurements) { var listener = new MeterListener { InstrumentPublished = (instrument, l) => { if (instrument.Meter.Name.StartsWith("StellaOps.Concelier.Models.OsvGhsaParity", StringComparison.Ordinal)) { l.EnableMeasurementEvents(instrument); } } }; listener.SetMeasurementEventCallback((instrument, measurement, tags, state) => { var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var tag in tags) { dict[tag.Key] = tag.Value; } measurements.Add((instrument.Name, measurement, dict)); }); listener.Start(); return listener; } }