using System.Collections.Immutable; using MongoDB.Bson; using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Ru.Nkcki.Internal; using StellaOps.Concelier.Storage.Mongo.Documents; using Xunit; using System.Reflection; namespace StellaOps.Concelier.Connector.Ru.Nkcki.Tests; public sealed class RuNkckiMapperTests { [Fact] public void Map_ConstructsCanonicalAdvisory() { var softwareEntries = ImmutableArray.Create( new RuNkckiSoftwareEntry( "SampleVendor SampleSCADA", "SampleVendor SampleSCADA <= 4.2", ImmutableArray.Create("<= 4.2"))); var dto = new RuNkckiVulnerabilityDto( FstecId: "BDU:2025-00001", MitreId: "CVE-2025-0001", DatePublished: new DateTimeOffset(2025, 9, 1, 0, 0, 0, TimeSpan.Zero), DateUpdated: new DateTimeOffset(2025, 9, 2, 0, 0, 0, TimeSpan.Zero), CvssRating: "КРИТИЧЕСКИЙ", PatchAvailable: true, Description: "Test NKCKI vulnerability", Cwe: new RuNkckiCweDto(79, "Cross-site scripting"), ProductCategories: ImmutableArray.Create("ICS", "Automation"), Mitigation: "Apply update", VulnerableSoftwareText: null, VulnerableSoftwareHasCpe: false, VulnerableSoftwareEntries: softwareEntries, CvssScore: 8.8, CvssVector: "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", CvssScoreV4: 6.4, CvssVectorV4: "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H", Impact: "ACE", MethodOfExploitation: "Special request", UserInteraction: false, Urls: ImmutableArray.Create("https://example.com/advisory", "https://cert.gov.ru/materialy/uyazvimosti/2025-00001"), Tags: ImmutableArray.Create("ics")); var document = new DocumentRecord( Guid.NewGuid(), RuNkckiConnectorPlugin.SourceName, "https://cert.gov.ru/materialy/uyazvimosti/2025-00001", DateTimeOffset.UtcNow, "abc", DocumentStatuses.PendingMap, "application/json", null, null, null, dto.DateUpdated, ObjectId.GenerateNewId()); Assert.Equal("КРИТИЧЕСКИЙ", dto.CvssRating); var normalizeSeverity = typeof(RuNkckiMapper).GetMethod("NormalizeSeverity", BindingFlags.NonPublic | BindingFlags.Static)!; var ratingSeverity = (string?)normalizeSeverity.Invoke(null, new object?[] { dto.CvssRating }); Assert.Equal("critical", ratingSeverity); var advisory = RuNkckiMapper.Map(dto, document, dto.DateUpdated!.Value); Assert.Contains("BDU:2025-00001", advisory.Aliases); Assert.Contains("CVE-2025-0001", advisory.Aliases); Assert.Equal("critical", advisory.Severity); Assert.True(advisory.ExploitKnown); Assert.Single(advisory.AffectedPackages); var package = advisory.AffectedPackages[0]; Assert.Equal(AffectedPackageTypes.IcsVendor, package.Type); Assert.Single(package.NormalizedVersions); Assert.Equal(2, advisory.CvssMetrics.Length); Assert.Contains(advisory.CvssMetrics, metric => metric.Version == "4.0"); Assert.Equal("critical", advisory.Severity); Assert.Contains(advisory.References, reference => reference.Url.Contains("example.com", StringComparison.OrdinalIgnoreCase)); } }