doctor enhancements, setup, enhancements, ui functionality and design consolidation and , test projects fixes , product advisory attestation/rekor and delta verfications enhancements

This commit is contained in:
master
2026-01-19 09:02:59 +02:00
parent 8c4bf54aed
commit 17419ba7c4
809 changed files with 170738 additions and 12244 deletions

View File

@@ -0,0 +1,504 @@
// -----------------------------------------------------------------------------
// ScoreGateCommandTests.cs
// Sprint: SPRINT_20260118_030_LIB_verdict_rekor_gate_api
// Task: TASK-030-008 - CLI Gate Command
// Description: Unit tests for score-based gate CLI commands
// -----------------------------------------------------------------------------
using System.CommandLine;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Cli.Commands;
using StellaOps.Cli.Configuration;
using StellaOps.TestKit;
using Xunit;
namespace StellaOps.Cli.Tests.Commands;
/// <summary>
/// Unit tests for score-based gate CLI commands.
/// </summary>
[Trait("Category", TestCategories.Unit)]
public class ScoreGateCommandTests
{
private readonly IServiceProvider _services;
private readonly StellaOpsCliOptions _options;
private readonly Option<bool> _verboseOption;
public ScoreGateCommandTests()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
_services = serviceCollection.BuildServiceProvider();
_options = new StellaOpsCliOptions
{
PolicyGateway = new StellaOpsCliPolicyGatewayOptions
{
BaseUrl = "http://localhost:5080"
}
};
_verboseOption = new Option<bool>("--verbose", "-v") { Description = "Enable verbose output" };
}
#region Score Command Structure Tests
[Fact]
public void BuildScoreCommand_CreatesScoreCommandTree()
{
// Act
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
// Assert
Assert.Equal("score", command.Name);
Assert.Contains("Score-based", command.Description);
Assert.Contains("EWS", command.Description);
}
[Fact]
public void BuildScoreCommand_HasEvaluateSubcommand()
{
// Act
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.FirstOrDefault(c => c.Name == "evaluate");
// Assert
Assert.NotNull(evaluateCommand);
Assert.Contains("single finding", evaluateCommand.Description, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void BuildScoreCommand_HasBatchSubcommand()
{
// Act
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.FirstOrDefault(c => c.Name == "batch");
// Assert
Assert.NotNull(batchCommand);
Assert.Contains("multiple findings", batchCommand.Description, StringComparison.OrdinalIgnoreCase);
}
#endregion
#region Evaluate Command Tests
[Fact]
public void EvaluateCommand_HasFindingIdOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var findingIdOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--finding-id") || o.Aliases.Contains("-f"));
// Assert
Assert.NotNull(findingIdOption);
Assert.Equal(1, findingIdOption.Arity.MinimumNumberOfValues); // Required
}
[Fact]
public void EvaluateCommand_HasCvssOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var cvssOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--cvss"));
// Assert
Assert.NotNull(cvssOption);
Assert.Contains("0-10", cvssOption.Description);
}
[Fact]
public void EvaluateCommand_HasEpssOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var epssOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--epss"));
// Assert
Assert.NotNull(epssOption);
Assert.Contains("0-1", epssOption.Description);
}
[Fact]
public void EvaluateCommand_HasReachabilityOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var reachabilityOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--reachability") || o.Aliases.Contains("-r"));
// Assert
Assert.NotNull(reachabilityOption);
Assert.Contains("none", reachabilityOption.Description);
Assert.Contains("package", reachabilityOption.Description);
Assert.Contains("function", reachabilityOption.Description);
Assert.Contains("caller", reachabilityOption.Description);
}
[Fact]
public void EvaluateCommand_HasExploitMaturityOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var exploitOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--exploit-maturity") || o.Aliases.Contains("-e"));
// Assert
Assert.NotNull(exploitOption);
Assert.Contains("poc", exploitOption.Description);
Assert.Contains("functional", exploitOption.Description);
Assert.Contains("high", exploitOption.Description);
}
[Fact]
public void EvaluateCommand_HasPatchProofOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var patchProofOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--patch-proof"));
// Assert
Assert.NotNull(patchProofOption);
Assert.Contains("0-1", patchProofOption.Description);
}
[Fact]
public void EvaluateCommand_HasVexStatusOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var vexStatusOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--vex-status"));
// Assert
Assert.NotNull(vexStatusOption);
Assert.Contains("affected", vexStatusOption.Description);
Assert.Contains("not_affected", vexStatusOption.Description);
Assert.Contains("fixed", vexStatusOption.Description);
}
[Fact]
public void EvaluateCommand_HasPolicyProfileOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var policyOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--policy") || o.Aliases.Contains("-p"));
// Assert
Assert.NotNull(policyOption);
Assert.Contains("advisory", policyOption.Description);
}
[Fact]
public void EvaluateCommand_HasAnchorOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var anchorOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--anchor"));
// Assert
Assert.NotNull(anchorOption);
Assert.Contains("Rekor", anchorOption.Description);
}
[Fact]
public void EvaluateCommand_HasOutputOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var outputOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--output") || o.Aliases.Contains("-o"));
// Assert
Assert.NotNull(outputOption);
Assert.Contains("table", outputOption.Description, StringComparison.OrdinalIgnoreCase);
Assert.Contains("json", outputOption.Description, StringComparison.OrdinalIgnoreCase);
Assert.Contains("ci", outputOption.Description, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void EvaluateCommand_HasBreakdownOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var evaluateCommand = command.Subcommands.First(c => c.Name == "evaluate");
// Act
var breakdownOption = evaluateCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--breakdown"));
// Assert
Assert.NotNull(breakdownOption);
Assert.Contains("breakdown", breakdownOption.Description, StringComparison.OrdinalIgnoreCase);
}
#endregion
#region Batch Command Tests
[Fact]
public void BatchCommand_HasInputOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.First(c => c.Name == "batch");
// Act
var inputOption = batchCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--input") || o.Aliases.Contains("-i"));
// Assert
Assert.NotNull(inputOption);
Assert.Contains("JSON", inputOption.Description);
}
[Fact]
public void BatchCommand_HasSarifOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.First(c => c.Name == "batch");
// Act
var sarifOption = batchCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--sarif"));
// Assert
Assert.NotNull(sarifOption);
Assert.Contains("SARIF", sarifOption.Description);
}
[Fact]
public void BatchCommand_HasFailFastOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.First(c => c.Name == "batch");
// Act
var failFastOption = batchCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--fail-fast"));
// Assert
Assert.NotNull(failFastOption);
Assert.Contains("Stop", failFastOption.Description);
}
[Fact]
public void BatchCommand_HasParallelismOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.First(c => c.Name == "batch");
// Act
var parallelismOption = batchCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--parallelism"));
// Assert
Assert.NotNull(parallelismOption);
Assert.Contains("parallelism", parallelismOption.Description, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void BatchCommand_HasIncludeVerdictsOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.First(c => c.Name == "batch");
// Act
var includeVerdictsOption = batchCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--include-verdicts"));
// Assert
Assert.NotNull(includeVerdictsOption);
Assert.Contains("verdict", includeVerdictsOption.Description, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void BatchCommand_HasOutputOption()
{
// Arrange
var command = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
var batchCommand = command.Subcommands.First(c => c.Name == "batch");
// Act
var outputOption = batchCommand.Options.FirstOrDefault(o =>
o.Aliases.Contains("--output") || o.Aliases.Contains("-o"));
// Assert
Assert.NotNull(outputOption);
Assert.Contains("table", outputOption.Description, StringComparison.OrdinalIgnoreCase);
Assert.Contains("json", outputOption.Description, StringComparison.OrdinalIgnoreCase);
Assert.Contains("ci", outputOption.Description, StringComparison.OrdinalIgnoreCase);
}
#endregion
#region Integration with Gate Command Tests
[Fact]
public void ScoreCommand_ShouldBeAddableToGateCommand()
{
// Arrange
var gateCommand = new Command("gate", "CI/CD release gate operations");
var scoreCommand = ScoreGateCommandGroup.BuildScoreCommand(
_services, _options, _verboseOption, CancellationToken.None);
// Act
gateCommand.Add(scoreCommand);
// Assert
Assert.Contains(gateCommand.Subcommands, c => c.Name == "score");
}
[Fact]
public void GateCommand_IncludesScoreSubcommand()
{
// Act
var gateCommand = GateCommandGroup.BuildGateCommand(
_services, _options, _verboseOption, CancellationToken.None);
// Assert
Assert.Contains(gateCommand.Subcommands, c => c.Name == "score");
}
[Fact]
public void GateScoreEvaluate_FullCommandPath()
{
// Arrange
var gateCommand = GateCommandGroup.BuildGateCommand(
_services, _options, _verboseOption, CancellationToken.None);
// Act
var scoreCommand = gateCommand.Subcommands.First(c => c.Name == "score");
var evaluateCommand = scoreCommand.Subcommands.First(c => c.Name == "evaluate");
// Assert
Assert.NotNull(evaluateCommand);
Assert.Equal("evaluate", evaluateCommand.Name);
}
[Fact]
public void GateScoreBatch_FullCommandPath()
{
// Arrange
var gateCommand = GateCommandGroup.BuildGateCommand(
_services, _options, _verboseOption, CancellationToken.None);
// Act
var scoreCommand = gateCommand.Subcommands.First(c => c.Name == "score");
var batchCommand = scoreCommand.Subcommands.First(c => c.Name == "batch");
// Assert
Assert.NotNull(batchCommand);
Assert.Equal("batch", batchCommand.Name);
}
#endregion
#region Exit Codes Tests
[Fact]
public void ScoreGateExitCodes_PassIsZero()
{
Assert.Equal(0, ScoreGateExitCodes.Pass);
}
[Fact]
public void ScoreGateExitCodes_WarnIsOne()
{
Assert.Equal(1, ScoreGateExitCodes.Warn);
}
[Fact]
public void ScoreGateExitCodes_BlockIsTwo()
{
Assert.Equal(2, ScoreGateExitCodes.Block);
}
[Fact]
public void ScoreGateExitCodes_InputErrorIsTen()
{
Assert.Equal(10, ScoreGateExitCodes.InputError);
}
[Fact]
public void ScoreGateExitCodes_NetworkErrorIsEleven()
{
Assert.Equal(11, ScoreGateExitCodes.NetworkError);
}
[Fact]
public void ScoreGateExitCodes_PolicyErrorIsTwelve()
{
Assert.Equal(12, ScoreGateExitCodes.PolicyError);
}
[Fact]
public void ScoreGateExitCodes_UnknownErrorIsNinetyNine()
{
Assert.Equal(99, ScoreGateExitCodes.UnknownError);
}
#endregion
}