Refactor code structure for improved readability and maintainability; optimize performance in key functions.
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
using System.Collections.Immutable;
|
||||
using StellaOps.Scanner.VulnSurfaces.Models;
|
||||
using StellaOps.Scanner.VulnSurfaces.Services;
|
||||
using StellaOps.Scanner.VulnSurfaces.Storage;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.VulnSurfaces.Tests;
|
||||
|
||||
public sealed class VulnSurfaceServiceTests
|
||||
{
|
||||
[Fact(DisplayName = "GetAffectedSymbolsAsync returns sinks when surface exists")]
|
||||
public async Task GetAffectedSymbolsAsync_ReturnsSurfaceSinks()
|
||||
{
|
||||
var surfaceGuid = Guid.NewGuid();
|
||||
var surface = new VulnSurface
|
||||
{
|
||||
SurfaceGuid = surfaceGuid,
|
||||
SurfaceId = 1,
|
||||
CveId = "CVE-2024-1234",
|
||||
PackageId = "pkg:npm/lodash@4.17.21",
|
||||
Ecosystem = "npm",
|
||||
VulnVersion = "4.17.21",
|
||||
FixedVersion = "4.17.22",
|
||||
Status = VulnSurfaceStatus.Computed,
|
||||
Confidence = 0.85,
|
||||
ComputedAt = DateTimeOffset.UtcNow
|
||||
};
|
||||
|
||||
var sinks = new[]
|
||||
{
|
||||
new VulnSurfaceSink
|
||||
{
|
||||
SurfaceId = 1,
|
||||
SinkId = 10,
|
||||
MethodKey = "lodash.template",
|
||||
DeclaringType = "Lodash",
|
||||
MethodName = "template",
|
||||
ChangeType = MethodChangeType.Modified
|
||||
}
|
||||
};
|
||||
|
||||
var repository = new FakeRepository(surface, sinks);
|
||||
var service = new VulnSurfaceService(repository, new NullPackageSymbolProvider());
|
||||
|
||||
var result = await service.GetAffectedSymbolsAsync("CVE-2024-1234", "pkg:npm/lodash@4.17.21");
|
||||
|
||||
Assert.Equal("surface", result.Source);
|
||||
Assert.Equal(0.85, result.Confidence);
|
||||
Assert.Single(result.Symbols);
|
||||
Assert.Equal(surfaceGuid, repository.LastSurfaceId);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "GetAffectedSymbolsAsync falls back to package symbol provider")]
|
||||
public async Task GetAffectedSymbolsAsync_FallsBackToPackageSymbols()
|
||||
{
|
||||
var repository = new FakeRepository(null, Array.Empty<VulnSurfaceSink>());
|
||||
var provider = new FakePackageSymbolProvider(ImmutableArray.Create(
|
||||
new AffectedSymbol { SymbolId = "public.symbol", Confidence = 0.4 }));
|
||||
|
||||
var service = new VulnSurfaceService(repository, provider);
|
||||
var result = await service.GetAffectedSymbolsAsync("CVE-2024-9999", "pkg:npm/example@1.0.0");
|
||||
|
||||
Assert.Equal("package-symbols", result.Source);
|
||||
Assert.Single(result.Symbols);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "GetAffectedSymbolsAsync returns heuristic when no data")]
|
||||
public async Task GetAffectedSymbolsAsync_ReturnsHeuristicWhenEmpty()
|
||||
{
|
||||
var repository = new FakeRepository(null, Array.Empty<VulnSurfaceSink>());
|
||||
var provider = new FakePackageSymbolProvider(ImmutableArray<AffectedSymbol>.Empty);
|
||||
var service = new VulnSurfaceService(repository, provider);
|
||||
|
||||
var result = await service.GetAffectedSymbolsAsync("CVE-2024-9999", "pkg:npm/example@1.0.0");
|
||||
|
||||
Assert.Equal("heuristic", result.Source);
|
||||
Assert.Empty(result.Symbols);
|
||||
}
|
||||
|
||||
private sealed class FakeRepository : IVulnSurfaceRepository
|
||||
{
|
||||
private readonly VulnSurface? _surface;
|
||||
private readonly IReadOnlyList<VulnSurfaceSink> _sinks;
|
||||
|
||||
public FakeRepository(VulnSurface? surface, IReadOnlyList<VulnSurfaceSink> sinks)
|
||||
{
|
||||
_surface = surface;
|
||||
_sinks = sinks;
|
||||
}
|
||||
|
||||
public Guid? LastSurfaceId { get; private set; }
|
||||
|
||||
public Task<Guid> CreateSurfaceAsync(Guid tenantId, string cveId, string ecosystem, string packageName, string vulnVersion,
|
||||
string? fixedVersion, string fingerprintMethod, int totalMethodsVuln, int totalMethodsFixed, int changedMethodCount,
|
||||
int? computationDurationMs, string? attestationDigest, CancellationToken cancellationToken = default)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task<Guid> AddSinkAsync(Guid surfaceId, string methodKey, string methodName, string declaringType, string changeType,
|
||||
string? vulnHash, string? fixedHash, CancellationToken cancellationToken = default)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task<Guid> AddTriggerAsync(Guid surfaceId, string triggerMethodKey, string sinkMethodKey, int depth, double confidence,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task<VulnSurface?> GetByCveAndPackageAsync(Guid tenantId, string cveId, string ecosystem, string packageName,
|
||||
string vulnVersion, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(_surface);
|
||||
|
||||
public Task<IReadOnlyList<VulnSurfaceSink>> GetSinksAsync(Guid surfaceId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LastSurfaceId = surfaceId;
|
||||
return Task.FromResult(_sinks);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<VulnSurfaceTrigger>> GetTriggersAsync(Guid surfaceId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<VulnSurfaceTrigger>>(Array.Empty<VulnSurfaceTrigger>());
|
||||
|
||||
public Task<IReadOnlyList<VulnSurface>> GetSurfacesByCveAsync(Guid tenantId, string cveId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<VulnSurface>>(Array.Empty<VulnSurface>());
|
||||
|
||||
public Task<bool> DeleteSurfaceAsync(Guid surfaceId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(false);
|
||||
}
|
||||
|
||||
private sealed class FakePackageSymbolProvider : IPackageSymbolProvider
|
||||
{
|
||||
private readonly ImmutableArray<AffectedSymbol> _symbols;
|
||||
|
||||
public FakePackageSymbolProvider(ImmutableArray<AffectedSymbol> symbols)
|
||||
{
|
||||
_symbols = symbols;
|
||||
}
|
||||
|
||||
public Task<ImmutableArray<AffectedSymbol>> GetPublicSymbolsAsync(string purl, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(_symbols);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user