Files
git.stella-ops.org/src/__Tests/Graph/StellaOps.Graph.Indexer.Tests/SbomIngestServiceCollectionExtensionsTests.cs

131 lines
4.4 KiB
C#

using System;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using StellaOps.Graph.Indexer.Ingestion.Sbom;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Graph.Indexer.Tests;
public sealed class SbomIngestServiceCollectionExtensionsTests : IDisposable
{
private static readonly string FixturesRoot =
Path.Combine(AppContext.BaseDirectory, "Fixtures", "v1");
private readonly string _tempDirectory;
public SbomIngestServiceCollectionExtensionsTests()
{
_tempDirectory = Path.Combine(Path.GetTempPath(), $"graph-indexer-{Guid.NewGuid():N}");
Directory.CreateDirectory(_tempDirectory);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task AddSbomIngestPipeline_exports_snapshots_to_configured_directory()
{
var services = new ServiceCollection();
services.AddSingleton<IGraphDocumentWriter, CaptureWriter>();
services.AddSbomIngestPipeline(options => options.SnapshotRootDirectory = _tempDirectory);
using var provider = services.BuildServiceProvider();
var processor = provider.GetRequiredService<SbomIngestProcessor>();
var snapshot = LoadSnapshot();
await processor.ProcessAsync(snapshot, CancellationToken.None);
AssertSnapshotOutputs(_tempDirectory);
var writer = provider.GetRequiredService<IGraphDocumentWriter>() as CaptureWriter;
writer!.LastBatch.Should().NotBeNull();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task AddSbomIngestPipeline_uses_environment_variable_when_not_configured()
{
var previous = Environment.GetEnvironmentVariable("STELLAOPS_GRAPH_SNAPSHOT_DIR");
try
{
Environment.SetEnvironmentVariable("STELLAOPS_GRAPH_SNAPSHOT_DIR", _tempDirectory);
var services = new ServiceCollection();
services.AddSingleton<IGraphDocumentWriter, CaptureWriter>();
services.AddSbomIngestPipeline();
using var provider = services.BuildServiceProvider();
using StellaOps.TestKit;
var processor = provider.GetRequiredService<SbomIngestProcessor>();
var snapshot = LoadSnapshot();
await processor.ProcessAsync(snapshot, CancellationToken.None);
AssertSnapshotOutputs(_tempDirectory);
}
finally
{
Environment.SetEnvironmentVariable("STELLAOPS_GRAPH_SNAPSHOT_DIR", previous);
}
}
private static SbomSnapshot LoadSnapshot()
{
var path = Path.Combine(FixturesRoot, "sbom-snapshot.json");
var json = File.ReadAllText(path);
return JsonSerializer.Deserialize<SbomSnapshot>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
})!;
}
private static void AssertSnapshotOutputs(string root)
{
var manifestPath = Path.Combine(root, "manifest.json");
var adjacencyPath = Path.Combine(root, "adjacency.json");
var nodesPath = Path.Combine(root, "nodes.jsonl");
var edgesPath = Path.Combine(root, "edges.jsonl");
File.Exists(manifestPath).Should().BeTrue("manifest should be exported");
File.Exists(adjacencyPath).Should().BeTrue("adjacency manifest should be exported");
File.Exists(nodesPath).Should().BeTrue("node stream should be exported");
File.Exists(edgesPath).Should().BeTrue("edge stream should be exported");
new FileInfo(manifestPath).Length.Should().BeGreaterThan(0);
new FileInfo(adjacencyPath).Length.Should().BeGreaterThan(0);
new FileInfo(nodesPath).Length.Should().BeGreaterThan(0);
new FileInfo(edgesPath).Length.Should().BeGreaterThan(0);
}
public void Dispose()
{
try
{
if (Directory.Exists(_tempDirectory))
{
Directory.Delete(_tempDirectory, recursive: true);
}
}
catch
{
// Ignore cleanup failures in CI environments.
}
}
private sealed class CaptureWriter : IGraphDocumentWriter
{
public GraphBuildBatch? LastBatch { get; private set; }
public Task WriteAsync(GraphBuildBatch batch, CancellationToken cancellationToken)
{
LastBatch = batch;
return Task.CompletedTask;
}
}
}