consolidation of some of the modules, localization fixes, product advisories work, qa work

This commit is contained in:
master
2026-03-05 03:54:22 +02:00
parent 7bafcc3eef
commit 8e1cb9448d
3878 changed files with 72600 additions and 46861 deletions

View File

@@ -8,7 +8,6 @@
using System.CommandLine;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -38,6 +37,32 @@ public class Sprint3500_0004_0001_CommandTests
_cancellationToken = CancellationToken.None;
}
private static IServiceProvider CreateScoreExplainProvider(HttpResponseMessage response)
{
var handlerMock = new Mock<HttpMessageHandler>();
handlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(response);
var httpClient = new HttpClient(handlerMock.Object);
var httpClientFactory = new Mock<IHttpClientFactory>();
httpClientFactory
.Setup(factory => factory.CreateClient("Platform"))
.Returns(httpClient);
httpClientFactory
.Setup(factory => factory.CreateClient("PlatformApi"))
.Returns(httpClient);
var services = new ServiceCollection();
services.AddSingleton(httpClientFactory.Object);
services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
return services.BuildServiceProvider();
}
#region ScoreReplayCommandGroup Tests
[Fact]
@@ -138,55 +163,51 @@ public class Sprint3500_0004_0001_CommandTests
}
[Fact]
public async Task ScoreExplain_OutputsDeterministicJson_WhenApiUnavailable()
public async Task ScoreExplain_ReturnsNetworkError_WhenBackendUnavailable()
{
// Arrange
var handlerMock = new Mock<HttpMessageHandler>();
handlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.InternalServerError));
var httpClient = new HttpClient(handlerMock.Object);
var httpClientFactory = new Mock<IHttpClientFactory>();
httpClientFactory
.Setup(factory => factory.CreateClient("Scanner"))
.Returns(httpClient);
var services = new ServiceCollection();
services.AddSingleton(httpClientFactory.Object);
services.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
var provider = services.BuildServiceProvider();
var provider = CreateScoreExplainProvider(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
{
Content = new StringContent("{\"code\":\"backend_unavailable\",\"message\":\"offline\"}")
});
var command = ScoreReplayCommandGroup.BuildScoreCommand(provider, _verboseOption, _cancellationToken);
var root = new RootCommand { command };
var writer = new StringWriter();
var originalOut = Console.Out;
int exitCode;
try
var exitCode = await root.Parse("score explain sha256:abc --format json").InvokeAsync();
Assert.Equal(ScoreExitCodes.NetworkError, exitCode);
}
[Fact]
public async Task ScoreExplain_ReturnsNotFound_WhenDigestMissing()
{
var provider = CreateScoreExplainProvider(new HttpResponseMessage(HttpStatusCode.NotFound)
{
Console.SetOut(writer);
exitCode = await root.Parse("score explain sha256:abc --format json").InvokeAsync();
}
finally
Content = new StringContent("{\"code\":\"not_found\",\"message\":\"missing\"}")
});
var command = ScoreReplayCommandGroup.BuildScoreCommand(provider, _verboseOption, _cancellationToken);
var root = new RootCommand { command };
var exitCode = await root.Parse("score explain sha256:abc --format json").InvokeAsync();
Assert.Equal(ScoreExitCodes.NotFound, exitCode);
}
[Fact]
public async Task ScoreExplain_ReturnsParseError_WhenPayloadMalformed()
{
var provider = CreateScoreExplainProvider(new HttpResponseMessage(HttpStatusCode.OK)
{
Console.SetOut(originalOut);
}
Content = new StringContent("{\"item\":")
});
// Assert
Assert.Equal(0, exitCode);
var command = ScoreReplayCommandGroup.BuildScoreCommand(provider, _verboseOption, _cancellationToken);
var root = new RootCommand { command };
var output = writer.ToString();
using var doc = JsonDocument.Parse(output);
var rootElement = doc.RootElement;
var exitCode = await root.Parse("score explain sha256:abc --format json").InvokeAsync();
Assert.Equal("sha256:abc", rootElement.GetProperty("digest").GetString());
Assert.Equal(7.5, rootElement.GetProperty("finalScore").GetDouble());
Assert.Equal(8.1, rootElement.GetProperty("scoreBreakdown").GetProperty("cvssScore").GetDouble());
Assert.Equal(ScoreExitCodes.ParseError, exitCode);
}
#endregion