tests fixes and some product advisories tunes ups
This commit is contained in:
356
src/Cli/__Tests/StellaOps.Cli.Tests/WitnessCoreCommandTests.cs
Normal file
356
src/Cli/__Tests/StellaOps.Cli.Tests/WitnessCoreCommandTests.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// WitnessCoreCommandTests.cs
|
||||
// Sprint: SPRINT_0128_001_BinaryIndex_binary_micro_witness
|
||||
// Task: TASK-003 — Integration tests for binary micro-witness CLI commands
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Parsing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit;
|
||||
using StellaOps.Cli.Commands.Witness;
|
||||
using StellaOps.TestKit;
|
||||
|
||||
namespace StellaOps.Cli.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for binary micro-witness CLI commands (generate, verify, bundle).
|
||||
/// Tests the WitnessCoreCommandGroup which handles patch verification workflows.
|
||||
/// </summary>
|
||||
public sealed class WitnessCoreCommandTests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly Option<bool> _verboseOption;
|
||||
private readonly CancellationToken _ct;
|
||||
|
||||
public WitnessCoreCommandTests()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddLogging(builder => builder.AddConsole());
|
||||
_services = serviceCollection.BuildServiceProvider();
|
||||
_verboseOption = new Option<bool>("--verbose");
|
||||
_ct = CancellationToken.None;
|
||||
}
|
||||
|
||||
#region Command Structure Tests
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreCommand_ShouldHaveExpectedSubcommands()
|
||||
{
|
||||
// Act
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(command);
|
||||
Assert.Equal("witness", command.Name);
|
||||
|
||||
var subcommandNames = command.Children.OfType<Command>().Select(c => c.Name).ToList();
|
||||
Assert.Contains("generate", subcommandNames);
|
||||
Assert.Contains("verify", subcommandNames);
|
||||
Assert.Contains("bundle", subcommandNames);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreCommand_HasCorrectDescription()
|
||||
{
|
||||
// Act
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
|
||||
// Assert
|
||||
Assert.Contains("micro-witness", command.Description);
|
||||
Assert.Contains("patch verification", command.Description);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Generate Command Tests
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_HasExpectedOptionCount()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Assert - generate has: cve, sbom, output, sign, rekor, format, verbose
|
||||
Assert.True(generateCommand.Options.Count() >= 6,
|
||||
$"Expected at least 6 options, found: {string.Join(", ", generateCommand.Options.Select(o => o.Name))}");
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_RequiresBinaryArgument()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Act - parse without binary argument
|
||||
var result = generateCommand.Parse("--cve CVE-2024-1234");
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_ParsesWithoutCveOption()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Act - parse without --cve (cve validated at runtime by handler)
|
||||
var result = generateCommand.Parse("test.elf");
|
||||
|
||||
// Assert - parse succeeds, runtime will validate cve is provided
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_ParsesValidArguments()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Act
|
||||
var result = generateCommand.Parse("test.elf --cve CVE-2024-0567 --sbom sbom.json --sign --rekor");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_ParsesWithEnvelopeFormat()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Act
|
||||
var result = generateCommand.Parse("test.elf --cve CVE-2024-0567 --format envelope");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_ParsesWithOutputOption()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Act
|
||||
var result = generateCommand.Parse("test.elf --cve CVE-2024-0567 --output witness.json");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Verify Command Tests
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreVerify_HasExpectedOptionCount()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var verifyCommand = command.Children.OfType<Command>().First(c => c.Name == "verify");
|
||||
|
||||
// Assert - verify has: offline, sbom, format, verbose
|
||||
Assert.True(verifyCommand.Options.Count() >= 3,
|
||||
$"Expected at least 3 options, found: {string.Join(", ", verifyCommand.Options.Select(o => o.Name))}");
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreVerify_RequiresWitnessArgument()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var verifyCommand = command.Children.OfType<Command>().First(c => c.Name == "verify");
|
||||
|
||||
// Act - parse without witness argument
|
||||
var result = verifyCommand.Parse("--offline");
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreVerify_ParsesValidArguments()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var verifyCommand = command.Children.OfType<Command>().First(c => c.Name == "verify");
|
||||
|
||||
// Act
|
||||
var result = verifyCommand.Parse("witness.json --offline --sbom sbom.json");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreVerify_ParsesWithOfflineFlag()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var verifyCommand = command.Children.OfType<Command>().First(c => c.Name == "verify");
|
||||
|
||||
// Act
|
||||
var result = verifyCommand.Parse("witness.json --offline");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreVerify_ParsesWithJsonFormat()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var verifyCommand = command.Children.OfType<Command>().First(c => c.Name == "verify");
|
||||
|
||||
// Act
|
||||
var result = verifyCommand.Parse("witness.json --format json");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bundle Command Tests
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreBundle_HasExpectedOptionCount()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var bundleCommand = command.Children.OfType<Command>().First(c => c.Name == "bundle");
|
||||
|
||||
// Assert - bundle has: output, include-binary, include-sbom, verbose
|
||||
Assert.True(bundleCommand.Options.Count() >= 3,
|
||||
$"Expected at least 3 options, found: {string.Join(", ", bundleCommand.Options.Select(o => o.Name))}");
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreBundle_RequiresWitnessArgument()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var bundleCommand = command.Children.OfType<Command>().First(c => c.Name == "bundle");
|
||||
|
||||
// Act - parse without witness argument
|
||||
var result = bundleCommand.Parse("--output ./bundle");
|
||||
|
||||
// Assert
|
||||
Assert.NotEmpty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreBundle_ParsesWithoutOptionalOutput()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var bundleCommand = command.Children.OfType<Command>().First(c => c.Name == "bundle");
|
||||
|
||||
// Act - parse without --output (output validated at runtime by handler)
|
||||
var result = bundleCommand.Parse("witness.json");
|
||||
|
||||
// Assert - parse succeeds, runtime will validate output is provided
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreBundle_ParsesValidArguments()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var bundleCommand = command.Children.OfType<Command>().First(c => c.Name == "bundle");
|
||||
|
||||
// Act
|
||||
var result = bundleCommand.Parse("witness.json --output ./bundle --include-binary --include-sbom");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreBundle_ParsesWithIncludeBinaryFlag()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var bundleCommand = command.Children.OfType<Command>().First(c => c.Name == "bundle");
|
||||
|
||||
// Act
|
||||
var result = bundleCommand.Parse("witness.json --output ./bundle --include-binary");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result.Errors);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Help Text Tests
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreGenerate_DescriptionMentionsGenerate()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var generateCommand = command.Children.OfType<Command>().First(c => c.Name == "generate");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(generateCommand.Description);
|
||||
Assert.Contains("micro-witness", generateCommand.Description.ToLowerInvariant());
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreVerify_DescriptionMentionsVerify()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var verifyCommand = command.Children.OfType<Command>().First(c => c.Name == "verify");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(verifyCommand.Description);
|
||||
Assert.Contains("verify", verifyCommand.Description.ToLowerInvariant());
|
||||
}
|
||||
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void WitnessCoreBundle_DescriptionMentionsAirGapped()
|
||||
{
|
||||
// Arrange
|
||||
var command = WitnessCoreCommandGroup.BuildWitnessCommand(_services, _verboseOption, _ct);
|
||||
var bundleCommand = command.Children.OfType<Command>().First(c => c.Name == "bundle");
|
||||
|
||||
// Assert
|
||||
Assert.Contains("air-gapped", bundleCommand.Description.ToLowerInvariant());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user