tests fixes and some product advisories tunes ups
This commit is contained in:
@@ -28,12 +28,17 @@ public sealed class BundleExportService : IBundleExportService
|
||||
private readonly ILogger<BundleExportService> _logger;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
private static readonly JsonSerializerOptions JsonWriteOptions = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
private static readonly JsonSerializerOptions JsonReadOptions = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BundleExportService"/> class.
|
||||
/// </summary>
|
||||
@@ -347,7 +352,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
};
|
||||
|
||||
await using var stream = new MemoryStream();
|
||||
await JsonSerializer.SerializeAsync(stream, sbom, JsonOptions, cancellationToken);
|
||||
await JsonSerializer.SerializeAsync(stream, sbom, JsonWriteOptions, cancellationToken);
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
@@ -384,7 +389,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
};
|
||||
|
||||
// Wrap in DSSE envelope format
|
||||
var payload = JsonSerializer.SerializeToUtf8Bytes(predicate, JsonOptions);
|
||||
var payload = JsonSerializer.SerializeToUtf8Bytes(predicate, JsonWriteOptions);
|
||||
var envelope = new
|
||||
{
|
||||
payloadType = "application/vnd.stella-ops.delta-sig+json",
|
||||
@@ -393,7 +398,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
};
|
||||
|
||||
await using var stream = new MemoryStream();
|
||||
await JsonSerializer.SerializeAsync(stream, envelope, JsonOptions, cancellationToken);
|
||||
await JsonSerializer.SerializeAsync(stream, envelope, JsonWriteOptions, cancellationToken);
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
@@ -534,7 +539,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(manifestPath);
|
||||
var manifest = JsonSerializer.Deserialize<PairManifest>(json);
|
||||
var manifest = JsonSerializer.Deserialize<PairManifest>(json, JsonReadOptions);
|
||||
if (manifest is not null)
|
||||
{
|
||||
return new CorpusBinaryPair
|
||||
@@ -736,7 +741,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
|
||||
var kpiPath = Path.Combine(kpisDir, "kpis.json");
|
||||
await using var stream = File.Create(kpiPath);
|
||||
await JsonSerializer.SerializeAsync(stream, kpiExport, JsonOptions, ct);
|
||||
await JsonSerializer.SerializeAsync(stream, kpiExport, JsonWriteOptions, ct);
|
||||
}
|
||||
|
||||
private async Task<BundleManifestInfo> CreateManifestAsync(
|
||||
@@ -777,7 +782,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
};
|
||||
|
||||
var manifestPath = Path.Combine(stagingDir, "manifest.json");
|
||||
var bytes = JsonSerializer.SerializeToUtf8Bytes(manifest, JsonOptions);
|
||||
var bytes = JsonSerializer.SerializeToUtf8Bytes(manifest, JsonWriteOptions);
|
||||
await File.WriteAllBytesAsync(manifestPath, bytes, ct);
|
||||
|
||||
var digest = ComputeHash(bytes);
|
||||
@@ -804,7 +809,7 @@ public sealed class BundleExportService : IBundleExportService
|
||||
message = "Signing integration pending"
|
||||
};
|
||||
|
||||
return File.WriteAllTextAsync(signaturePath, JsonSerializer.Serialize(placeholder, JsonOptions), ct);
|
||||
return File.WriteAllTextAsync(signaturePath, JsonSerializer.Serialize(placeholder, JsonWriteOptions), ct);
|
||||
}
|
||||
|
||||
private static async Task CreateTarballAsync(string sourceDir, string outputPath, CancellationToken ct)
|
||||
|
||||
@@ -172,8 +172,13 @@ public sealed class BundleImportService : IBundleImportService
|
||||
|
||||
if (!digestResult.Passed)
|
||||
{
|
||||
return BundleImportResult.Failed(
|
||||
$"Digest verification failed: {digestResult.Mismatches.Length} mismatches");
|
||||
return new BundleImportResult
|
||||
{
|
||||
Success = false,
|
||||
OverallStatus = VerificationStatus.Failed,
|
||||
DigestResult = digestResult,
|
||||
Error = $"Digest verification failed: {digestResult.Mismatches.Length} mismatches"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +303,11 @@ public sealed class SbomStabilityValidator : ISbomStabilityValidator
|
||||
Duration = stopwatch.Elapsed
|
||||
};
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_logger.LogWarning("SBOM stability validation was cancelled");
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "SBOM stability validation failed");
|
||||
|
||||
@@ -51,7 +51,8 @@ public class DdebConnectorIntegrationTests : IAsyncLifetime
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact(Skip = "Integration test requires network access to Ubuntu ddebs repository")]
|
||||
[Fact]
|
||||
[Trait("Category", "NetworkIntegration")]
|
||||
public async Task DdebConnector_CanFetchPackagesIndex()
|
||||
{
|
||||
// Skip if integration tests are disabled or if running in CI without network
|
||||
|
||||
@@ -284,9 +284,10 @@ public sealed class BundleImportServiceTests : IDisposable
|
||||
using var cts = new CancellationTokenSource();
|
||||
await cts.CancelAsync();
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<OperationCanceledException>(
|
||||
// Act & Assert - TaskCanceledException inherits from OperationCanceledException
|
||||
var ex = await Assert.ThrowsAnyAsync<OperationCanceledException>(
|
||||
() => _sut.ImportAsync(request, cancellationToken: cts.Token));
|
||||
Assert.True(ex is OperationCanceledException);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -343,7 +344,7 @@ public sealed class BundleImportServiceTests : IDisposable
|
||||
File.Exists(reportPath).Should().BeTrue();
|
||||
var content = await File.ReadAllTextAsync(reportPath);
|
||||
content.Should().Contain("# Bundle Verification Report");
|
||||
content.Should().Contain("PASSED");
|
||||
content.Should().Contain("Passed"); // Report uses "✅ Passed" format
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -404,7 +405,7 @@ public sealed class BundleImportServiceTests : IDisposable
|
||||
|
||||
// Assert
|
||||
var content = await File.ReadAllTextAsync(reportPath);
|
||||
content.Should().Contain("FAILED");
|
||||
content.Should().Contain("Failed"); // Report uses "❌ Failed" format
|
||||
content.Should().Contain("Test error message");
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Time.Testing;
|
||||
using StellaOps.BinaryIndex.GroundTruth.Abstractions;
|
||||
using StellaOps.BinaryIndex.GroundTruth.Reproducible.Models;
|
||||
using StellaOps.BinaryIndex.GroundTruth.Reproducible.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.BinaryIndex.GroundTruth.Reproducible.Tests.Integration;
|
||||
@@ -354,7 +356,7 @@ public sealed class KpiRegressionIntegrationTests : IDisposable
|
||||
|
||||
// Assert
|
||||
result.OverallStatus.Should().Be(GateStatus.Fail);
|
||||
result.FailedGates.Should().HaveCountGreaterOrEqualTo(3);
|
||||
result.FailedGates.Should().HaveCountGreaterThanOrEqualTo(3);
|
||||
result.FailedGates.Should().Contain(g => g.Contains("Precision"));
|
||||
result.FailedGates.Should().Contain(g => g.Contains("Recall"));
|
||||
result.FailedGates.Should().Contain(g => g.Contains("False Negative"));
|
||||
|
||||
@@ -373,7 +373,7 @@ public class KpiRegressionServiceTests : IDisposable
|
||||
|
||||
// Assert
|
||||
result.Passed.Should().BeFalse();
|
||||
result.Gates.Count(g => !g.Passed).Should().BeGreaterOrEqualTo(2);
|
||||
result.Gates.Count(g => !g.Passed).Should().BeGreaterThanOrEqualTo(2);
|
||||
result.Summary.Should().Contain("2");
|
||||
}
|
||||
|
||||
@@ -540,8 +540,9 @@ public class KpiRegressionServiceTests : IDisposable
|
||||
// Act
|
||||
var report = _service.GenerateJsonReport(checkResult);
|
||||
|
||||
// Assert
|
||||
var action = () => JsonSerializer.Deserialize<RegressionCheckResult>(report);
|
||||
// Assert - use Web defaults (camelCase) to match the serialization options
|
||||
var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
|
||||
var action = () => JsonSerializer.Deserialize<RegressionCheckResult>(report, jsonOptions);
|
||||
action.Should().NotThrow();
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ public sealed class SbomStabilityValidatorTests
|
||||
// Assert
|
||||
result.Duration.Should().BeGreaterThan(TimeSpan.Zero);
|
||||
result.Runs.Should().AllSatisfy(r =>
|
||||
r.Duration.Should().BeGreaterOrEqualTo(TimeSpan.Zero));
|
||||
r.Duration.Should().BeGreaterThanOrEqualTo(TimeSpan.Zero));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<OutputType>Exe</OutputType>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<UseXunitV3>true</UseXunitV3>
|
||||
<RootNamespace>StellaOps.BinaryIndex.GroundTruth.Reproducible.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Exclude tests that depend on incomplete library implementations -->
|
||||
<ItemGroup>
|
||||
<Compile Remove="Integration\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="NSubstitute" />
|
||||
<PackageReference Include="xunit.v3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -49,7 +49,8 @@ public class SecDbConnectorIntegrationTests : IAsyncLifetime
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact(Skip = "Integration test requires network access to Alpine GitLab")]
|
||||
[Fact]
|
||||
[Trait("Category", "NetworkIntegration")]
|
||||
public async Task SecDbConnector_CanTestConnectivity()
|
||||
{
|
||||
Skip.If(_skipTests, "Integration tests skipped");
|
||||
@@ -104,7 +105,8 @@ public class SecDbConnectorIntegrationTests : IAsyncLifetime
|
||||
connector.SupportedDistros.Should().Contain("alpine");
|
||||
}
|
||||
|
||||
[Fact(Skip = "Integration test requires network access to Alpine GitLab")]
|
||||
[Fact]
|
||||
[Trait("Category", "NetworkIntegration")]
|
||||
public async Task SecDbConnector_FetchAndGetVulnerabilities_ReturnsData()
|
||||
{
|
||||
Skip.If(_skipTests, "Integration tests skipped");
|
||||
|
||||
Reference in New Issue
Block a user