169 lines
5.0 KiB
C#
169 lines
5.0 KiB
C#
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 ValueTask InitializeAsync()
|
|
{
|
|
if (_skipTests)
|
|
return ValueTask.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 ValueTask.CompletedTask;
|
|
}
|
|
|
|
public ValueTask DisposeAsync()
|
|
{
|
|
_services?.Dispose();
|
|
return ValueTask.CompletedTask;
|
|
}
|
|
|
|
[Fact]
|
|
[Trait("Category", "NetworkIntegration")]
|
|
public async Task SecDbConnector_CanTestConnectivity()
|
|
{
|
|
Skip.If(_skipTests, "Integration tests skipped");
|
|
|
|
// Arrange
|
|
var connector = _services!.GetRequiredService<SecDbConnector>();
|
|
|
|
// Act
|
|
try
|
|
{
|
|
var result = await connector.TestConnectivityAsync();
|
|
|
|
// Assert - only if network is available
|
|
result.IsConnected.Should().BeTrue("Should be able to connect to Alpine GitLab");
|
|
result.Latency.Should().BeLessThan(TimeSpan.FromSeconds(30));
|
|
}
|
|
catch (HttpRequestException)
|
|
{
|
|
// Network unavailable - skip test
|
|
Skip.If(true, "Network unavailable");
|
|
}
|
|
}
|
|
|
|
[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]
|
|
[Trait("Category", "NetworkIntegration")]
|
|
public async Task SecDbConnector_FetchAndGetVulnerabilities_ReturnsData()
|
|
{
|
|
Skip.If(_skipTests, "Integration tests skipped");
|
|
|
|
// Arrange
|
|
var connector = _services!.GetRequiredService<SecDbConnector>();
|
|
|
|
try
|
|
{
|
|
// 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-"));
|
|
}
|
|
catch (HttpRequestException)
|
|
{
|
|
// Network unavailable - skip test
|
|
Skip.If(true, "Network unavailable");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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() { }
|
|
}
|