sprints work.
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace StellaOps.BinaryIndex.GroundTruth.SecDb.Tests.Fixtures;
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to deterministic test fixtures for offline testing.
|
||||
/// </summary>
|
||||
public static class FixtureProvider
|
||||
{
|
||||
private static readonly string FixturesPath;
|
||||
|
||||
static FixtureProvider()
|
||||
{
|
||||
var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
||||
FixturesPath = Path.Combine(assemblyDir, "Fixtures");
|
||||
|
||||
// Also try the source directory for development
|
||||
if (!Directory.Exists(FixturesPath))
|
||||
{
|
||||
var sourceDir = FindSourceFixturesDirectory();
|
||||
if (sourceDir is not null)
|
||||
{
|
||||
FixturesPath = sourceDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get sample SecDB YAML content for main repository.
|
||||
/// </summary>
|
||||
public static string GetSampleSecDbMain()
|
||||
{
|
||||
var path = Path.Combine(FixturesPath, "main.yaml");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
// Return inline fixture if file doesn't exist
|
||||
return SampleSecDbMainContent;
|
||||
}
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get sample SecDB YAML content for community repository.
|
||||
/// </summary>
|
||||
public static string GetSampleSecDbCommunity()
|
||||
{
|
||||
var path = Path.Combine(FixturesPath, "community.yaml");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return SampleSecDbCommunityContent;
|
||||
}
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a fixture file as a stream.
|
||||
/// </summary>
|
||||
public static Stream GetFixtureStream(string name)
|
||||
{
|
||||
var path = Path.Combine(FixturesPath, name);
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new FileNotFoundException($"Fixture not found: {path}");
|
||||
}
|
||||
return File.OpenRead(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a fixture exists.
|
||||
/// </summary>
|
||||
public static bool FixtureExists(string name)
|
||||
{
|
||||
var path = Path.Combine(FixturesPath, name);
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
private static string? FindSourceFixturesDirectory()
|
||||
{
|
||||
var dir = Directory.GetCurrentDirectory();
|
||||
while (dir is not null)
|
||||
{
|
||||
var candidate = Path.Combine(dir, "src", "BinaryIndex", "__Tests",
|
||||
"StellaOps.BinaryIndex.GroundTruth.SecDb.Tests", "Fixtures");
|
||||
if (Directory.Exists(candidate))
|
||||
{
|
||||
return candidate;
|
||||
}
|
||||
dir = Directory.GetParent(dir)?.FullName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inline sample SecDB main.yaml content for deterministic testing.
|
||||
/// Based on Alpine SecDB format.
|
||||
/// </summary>
|
||||
private const string SampleSecDbMainContent = """
|
||||
distroversion: v3.19
|
||||
reponame: main
|
||||
urlprefix: https://dl-cdn.alpinelinux.org/alpine/v3.19/main
|
||||
packages:
|
||||
- pkg: curl
|
||||
secfixes:
|
||||
8.5.0-r0:
|
||||
- CVE-2023-46218 Improper validation of HTTP headers
|
||||
- CVE-2023-46219 Double free in async URL resolver
|
||||
8.4.0-r0:
|
||||
- CVE-2023-38545 SOCKS5 heap buffer overflow
|
||||
8.1.2-r0:
|
||||
- CVE-2023-27535 FTP injection vulnerability
|
||||
- pkg: openssl
|
||||
secfixes:
|
||||
3.1.4-r3:
|
||||
- CVE-2024-0727 PKCS12 decoding crash
|
||||
3.1.4-r0:
|
||||
- CVE-2023-5678 Denial of service
|
||||
3.1.2-r0:
|
||||
- CVE-2023-3817 Excessive time checking DH parameters
|
||||
- pkg: linux-lts
|
||||
secfixes:
|
||||
6.1.67-r0:
|
||||
- CVE-2023-6817 Use-after-free in netfilter
|
||||
- CVE-2023-6606 Out-of-bounds read in SMB
|
||||
6.1.64-r0:
|
||||
- CVE-2023-5717 User-mode root exploit via perf
|
||||
""";
|
||||
|
||||
/// <summary>
|
||||
/// Inline sample SecDB community.yaml content.
|
||||
/// </summary>
|
||||
private const string SampleSecDbCommunityContent = """
|
||||
distroversion: v3.19
|
||||
reponame: community
|
||||
urlprefix: https://dl-cdn.alpinelinux.org/alpine/v3.19/community
|
||||
packages:
|
||||
- pkg: go
|
||||
secfixes:
|
||||
1.21.5-r0:
|
||||
- CVE-2023-45283 Path traversal on Windows
|
||||
- CVE-2023-45284 Runtime panic in crypto/tls
|
||||
1.21.4-r0:
|
||||
- CVE-2023-44487 HTTP/2 rapid reset attack
|
||||
- pkg: nodejs
|
||||
secfixes:
|
||||
20.10.0-r0:
|
||||
- CVE-2023-46809 Permissions policy bypass
|
||||
20.9.0-r0:
|
||||
- CVE-2023-38552 Integrity bypass via TLS/HTTPS
|
||||
- pkg: chromium
|
||||
secfixes:
|
||||
120.0.6099.71-r0:
|
||||
- CVE-2023-6702 Type confusion in V8
|
||||
119.0.6045.199-r0:
|
||||
- CVE-2023-6345 Integer overflow in Skia
|
||||
- pkg: unfixed-example
|
||||
secfixes:
|
||||
"0":
|
||||
- CVE-2023-99999 Example unfixed vulnerability
|
||||
""";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test fixture constants for SecDB tests.
|
||||
/// </summary>
|
||||
public static class FixtureConstants
|
||||
{
|
||||
// Sample package info
|
||||
public const string SamplePackageCurl = "curl";
|
||||
public const string SamplePackageOpenssl = "openssl";
|
||||
public const string SamplePackageGo = "go";
|
||||
public const string SamplePackageNodejs = "nodejs";
|
||||
|
||||
// Sample branches
|
||||
public const string SampleBranchV319 = "v3.19";
|
||||
public const string SampleBranchEdge = "edge";
|
||||
|
||||
// Sample repositories
|
||||
public const string SampleRepoMain = "main";
|
||||
public const string SampleRepoCommunity = "community";
|
||||
|
||||
// Expected CVE counts
|
||||
public const int ExpectedCurlCveCount = 4;
|
||||
public const int ExpectedOpensslCveCount = 3;
|
||||
|
||||
// Sample CVEs
|
||||
public const string SampleCveCurl = "CVE-2023-46218";
|
||||
public const string SampleCveOpenssl = "CVE-2024-0727";
|
||||
public const string SampleCveUnfixed = "CVE-2023-99999";
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.BinaryIndex.GroundTruth.SecDb.Configuration;
|
||||
using StellaOps.BinaryIndex.GroundTruth.SecDb.Tests.Fixtures;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.BinaryIndex.GroundTruth.SecDb.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for SecDb connector.
|
||||
/// These tests require network access to gitlab.alpinelinux.org.
|
||||
/// Skip in CI by setting SKIP_INTEGRATION_TESTS=true.
|
||||
/// </summary>
|
||||
[Trait("Category", "Integration")]
|
||||
public class SecDbConnectorIntegrationTests : IAsyncLifetime
|
||||
{
|
||||
private ServiceProvider? _services;
|
||||
private readonly bool _skipTests;
|
||||
|
||||
public SecDbConnectorIntegrationTests()
|
||||
{
|
||||
_skipTests = Environment.GetEnvironmentVariable("SKIP_INTEGRATION_TESTS")?.ToLowerInvariant() == "true"
|
||||
|| Environment.GetEnvironmentVariable("CI")?.ToLowerInvariant() == "true";
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
if (_skipTests)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Debug));
|
||||
services.AddSecDbConnector(opts =>
|
||||
{
|
||||
opts.Branches = ["v3.19"];
|
||||
opts.Repositories = ["main"];
|
||||
opts.TimeoutSeconds = 120;
|
||||
opts.FetchAports = false; // Don't fetch aports for integration tests
|
||||
});
|
||||
|
||||
_services = services.BuildServiceProvider();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
_services?.Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SecDbConnector_CanTestConnectivity()
|
||||
{
|
||||
Skip.If(_skipTests, "Integration tests skipped");
|
||||
|
||||
// Arrange
|
||||
var connector = _services!.GetRequiredService<SecDbConnector>();
|
||||
|
||||
// Act
|
||||
var result = await connector.TestConnectivityAsync();
|
||||
|
||||
// Assert
|
||||
result.IsConnected.Should().BeTrue("Should be able to connect to Alpine GitLab");
|
||||
result.Latency.Should().BeLessThan(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SecDbConnector_CanGetMetadata()
|
||||
{
|
||||
Skip.If(_skipTests, "Integration tests skipped");
|
||||
|
||||
// Arrange
|
||||
var connector = _services!.GetRequiredService<SecDbConnector>();
|
||||
|
||||
// Act
|
||||
var metadata = await connector.GetMetadataAsync();
|
||||
|
||||
// Assert
|
||||
metadata.SourceId.Should().Be("secdb-alpine");
|
||||
metadata.DisplayName.Should().Contain("Alpine");
|
||||
metadata.BaseUrl.Should().Contain("gitlab.alpinelinux.org");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SecDbConnector_HasCorrectProperties()
|
||||
{
|
||||
Skip.If(_skipTests, "Integration tests skipped");
|
||||
|
||||
// Arrange
|
||||
var connector = _services!.GetRequiredService<SecDbConnector>();
|
||||
|
||||
// Assert
|
||||
connector.SourceId.Should().Be("secdb-alpine");
|
||||
connector.DisplayName.Should().Contain("SecDB");
|
||||
connector.SupportedDistros.Should().Contain("alpine");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SecDbConnector_FetchAndGetVulnerabilities_ReturnsData()
|
||||
{
|
||||
Skip.If(_skipTests, "Integration tests skipped");
|
||||
|
||||
// Arrange
|
||||
var connector = _services!.GetRequiredService<SecDbConnector>();
|
||||
|
||||
// First fetch the data
|
||||
await connector.FetchAsync(_services!, CancellationToken.None);
|
||||
|
||||
// Act - get vulnerabilities for a well-known package
|
||||
var vulnerabilities = await connector.GetVulnerabilitiesForPackageAsync("curl");
|
||||
|
||||
// Assert
|
||||
vulnerabilities.Should().NotBeEmpty("curl should have known vulnerabilities");
|
||||
vulnerabilities.Should().OnlyContain(v => v.CveId.StartsWith("CVE-"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides Skip functionality for xUnit when condition is true.
|
||||
/// </summary>
|
||||
public static class Skip
|
||||
{
|
||||
public static void If(bool condition, string reason)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
throw new SkipException(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exception to skip a test.
|
||||
/// </summary>
|
||||
public class SkipException : Exception
|
||||
{
|
||||
public SkipException(string reason) : base(reason) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test meter factory for diagnostics.
|
||||
/// </summary>
|
||||
internal sealed class TestMeterFactory : System.Diagnostics.Metrics.IMeterFactory
|
||||
{
|
||||
public System.Diagnostics.Metrics.Meter Create(System.Diagnostics.Metrics.MeterOptions options)
|
||||
=> new(options.Name, options.Version);
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
using FluentAssertions;
|
||||
using StellaOps.BinaryIndex.GroundTruth.SecDb.Internal;
|
||||
using StellaOps.BinaryIndex.GroundTruth.SecDb.Tests.Fixtures;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.BinaryIndex.GroundTruth.SecDb.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for SecDbParser using deterministic fixtures.
|
||||
/// </summary>
|
||||
public class SecDbParserTests
|
||||
{
|
||||
private readonly SecDbParser _parser = new();
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleMainYaml_ParsesDistroVersion()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
result.DistroVersion.Should().Be(FixtureConstants.SampleBranchV319);
|
||||
result.RepoName.Should().Be(FixtureConstants.SampleRepoMain);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleMainYaml_ExtractsPackages()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
result.Packages.Should().HaveCountGreaterThanOrEqualTo(3);
|
||||
result.Packages.Should().Contain(p => p.Name == FixtureConstants.SamplePackageCurl);
|
||||
result.Packages.Should().Contain(p => p.Name == FixtureConstants.SamplePackageOpenssl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleMainYaml_ExtractsCurlVulnerabilities()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
var curl = result.Packages.First(p => p.Name == FixtureConstants.SamplePackageCurl);
|
||||
curl.Vulnerabilities.Should().HaveCount(FixtureConstants.ExpectedCurlCveCount);
|
||||
curl.Vulnerabilities.Should().Contain(v => v.CveId == FixtureConstants.SampleCveCurl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleMainYaml_ExtractsFixedVersions()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
var curl = result.Packages.First(p => p.Name == FixtureConstants.SamplePackageCurl);
|
||||
var cve = curl.Vulnerabilities.First(v => v.CveId == FixtureConstants.SampleCveCurl);
|
||||
cve.FixedInVersion.Should().Be("8.5.0-r0");
|
||||
cve.IsUnfixed.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleCommunityYaml_ParsesCommunityPackages()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbCommunity();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoCommunity);
|
||||
|
||||
// Assert
|
||||
result.Packages.Should().Contain(p => p.Name == FixtureConstants.SamplePackageGo);
|
||||
result.Packages.Should().Contain(p => p.Name == FixtureConstants.SamplePackageNodejs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleCommunityYaml_DetectsUnfixedVulnerabilities()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbCommunity();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoCommunity);
|
||||
|
||||
// Assert
|
||||
var unfixedPkg = result.Packages.First(p => p.Name == "unfixed-example");
|
||||
var unfixedCve = unfixedPkg.Vulnerabilities.First(v => v.CveId == FixtureConstants.SampleCveUnfixed);
|
||||
unfixedCve.FixedInVersion.Should().Be("0");
|
||||
unfixedCve.IsUnfixed.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SampleMainYaml_CalculatesTotalVulnerabilityCount()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
result.VulnerabilityCount.Should().BeGreaterThan(0);
|
||||
result.VulnerabilityCount.Should().Be(result.Packages.Sum(p => p.Vulnerabilities.Count));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_CveWithDescription_ExtractsDescription()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
var curl = result.Packages.First(p => p.Name == FixtureConstants.SamplePackageCurl);
|
||||
var cve = curl.Vulnerabilities.First(v => v.CveId == FixtureConstants.SampleCveCurl);
|
||||
cve.Description.Should().Contain("HTTP headers");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_EmptyContent_ThrowsFormatException()
|
||||
{
|
||||
// Act
|
||||
var act = () => _parser.Parse("", FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
act.Should().Throw<FormatException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidYaml_ThrowsFormatException()
|
||||
{
|
||||
// Arrange
|
||||
var content = "this is not valid yaml: [incomplete";
|
||||
|
||||
// Act
|
||||
var act = () => _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
act.Should().Throw<FormatException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_EmptyPackagesArray_ReturnsEmptyPackageList()
|
||||
{
|
||||
// Arrange
|
||||
var content = """
|
||||
distroversion: v3.19
|
||||
reponame: main
|
||||
packages: []
|
||||
""";
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
result.Packages.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_PackageWithNoSecfixes_ReturnsEmptyVulnerabilities()
|
||||
{
|
||||
// Arrange
|
||||
var content = """
|
||||
distroversion: v3.19
|
||||
reponame: main
|
||||
packages:
|
||||
- pkg: no-vulns-pkg
|
||||
""";
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
result.Packages.Should().HaveCount(1);
|
||||
result.Packages[0].Vulnerabilities.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_NonCveEntry_SkipsNonCveIdentifiers()
|
||||
{
|
||||
// Arrange - Alpine secdb sometimes has XSA-xxx or other identifiers
|
||||
var content = """
|
||||
distroversion: v3.19
|
||||
reponame: main
|
||||
packages:
|
||||
- pkg: xen
|
||||
secfixes:
|
||||
4.18.0-r1:
|
||||
- XSA-445 Not a CVE
|
||||
- CVE-2023-12345 Actual CVE
|
||||
""";
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
var xen = result.Packages.First();
|
||||
xen.Vulnerabilities.Should().HaveCount(1);
|
||||
xen.Vulnerabilities[0].CveId.Should().Be("CVE-2023-12345");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_CveIdNormalization_ConvertsToUppercase()
|
||||
{
|
||||
// Arrange
|
||||
var content = """
|
||||
distroversion: v3.19
|
||||
reponame: main
|
||||
packages:
|
||||
- pkg: test
|
||||
secfixes:
|
||||
1.0-r0:
|
||||
- cve-2023-12345 lowercase
|
||||
""";
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
var pkg = result.Packages.First();
|
||||
pkg.Vulnerabilities[0].CveId.Should().Be("CVE-2023-12345");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_MultipleCvesInSameVersion_ParsesAll()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
var linuxLts = result.Packages.First(p => p.Name == "linux-lts");
|
||||
var version6167 = linuxLts.Vulnerabilities.Where(v => v.FixedInVersion == "6.1.67-r0").ToList();
|
||||
version6167.Should().HaveCount(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SetsBranchAndRepository()
|
||||
{
|
||||
// Arrange
|
||||
var content = FixtureProvider.GetSampleSecDbMain();
|
||||
|
||||
// Act
|
||||
var result = _parser.Parse(content, FixtureConstants.SampleBranchV319, FixtureConstants.SampleRepoMain);
|
||||
|
||||
// Assert
|
||||
result.Branch.Should().Be(FixtureConstants.SampleBranchV319);
|
||||
result.Repository.Should().Be(FixtureConstants.SampleRepoMain);
|
||||
|
||||
foreach (var pkg in result.Packages)
|
||||
{
|
||||
pkg.Branch.Should().Be(FixtureConstants.SampleBranchV319);
|
||||
pkg.Repository.Should().Be(FixtureConstants.SampleRepoMain);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.BinaryIndex.GroundTruth.SecDb\StellaOps.BinaryIndex.GroundTruth.SecDb.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Fixtures\**\*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user