119 lines
4.0 KiB
C#
119 lines
4.0 KiB
C#
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Options;
|
|
using StellaOps.Scanner.CallGraph;
|
|
using StellaOps.Scanner.CallGraph.Caching;
|
|
using StellaOps.Scanner.Contracts;
|
|
using Xunit;
|
|
|
|
using StellaOps.TestKit;
|
|
namespace StellaOps.Scanner.CallGraph.Tests;
|
|
|
|
/// <summary>
|
|
/// Integration tests for Valkey/Redis call graph caching.
|
|
/// These tests require a Redis-compatible server to be running.
|
|
/// Set STELLA_VALKEY_TESTS=1 to enable when Valkey is available.
|
|
/// </summary>
|
|
public class ValkeyCallGraphCacheServiceTests : IAsyncLifetime
|
|
{
|
|
private ValkeyCallGraphCacheService? _cache;
|
|
|
|
private static readonly bool ValkeyTestsEnabled =
|
|
Environment.GetEnvironmentVariable("STELLA_VALKEY_TESTS") == "1";
|
|
|
|
public async ValueTask InitializeAsync()
|
|
{
|
|
if (!ValkeyTestsEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var options = Options.Create(new CallGraphCacheConfig
|
|
{
|
|
Enabled = true,
|
|
ConnectionString = Environment.GetEnvironmentVariable("STELLA_VALKEY_CONNECTION") ?? "localhost:6379",
|
|
KeyPrefix = $"test:callgraph:{Guid.NewGuid():N}:",
|
|
TtlSeconds = 60,
|
|
EnableGzip = true,
|
|
CircuitBreaker = new CircuitBreakerConfig { FailureThreshold = 3, TimeoutSeconds = 30, HalfOpenTimeout = 10 }
|
|
});
|
|
|
|
try
|
|
{
|
|
_cache = new ValkeyCallGraphCacheService(
|
|
options,
|
|
NullLogger<ValkeyCallGraphCacheService>.Instance);
|
|
}
|
|
catch
|
|
{
|
|
_cache = null;
|
|
}
|
|
|
|
await ValueTask.CompletedTask;
|
|
}
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
if (_cache is not null)
|
|
{
|
|
await _cache.DisposeAsync();
|
|
}
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Integration)]
|
|
[Fact]
|
|
public async Task SetThenGet_CallGraph_RoundTrips()
|
|
{
|
|
if (!ValkeyTestsEnabled || _cache is null)
|
|
{
|
|
Assert.True(true, "Valkey integration tests disabled. Set STELLA_VALKEY_TESTS=1 to enable.");
|
|
return;
|
|
}
|
|
|
|
var nodeId = CallGraphNodeIds.Compute("dotnet:test:entry");
|
|
var snapshot = new CallGraphSnapshot(
|
|
ScanId: "scan-cache-1",
|
|
GraphDigest: "sha256:cg",
|
|
Language: "dotnet",
|
|
ExtractedAt: DateTimeOffset.UtcNow,
|
|
Nodes: [new CallGraphNode(nodeId, "Entry", "file.cs", 1, "app", Visibility.Public, true, EntrypointType.HttpHandler, false, null)],
|
|
Edges: [],
|
|
EntrypointIds: [nodeId],
|
|
SinkIds: []);
|
|
|
|
await _cache.SetCallGraphAsync(snapshot, cancellationToken: TestContext.Current.CancellationToken);
|
|
var loaded = await _cache.TryGetCallGraphAsync("scan-cache-1", "dotnet", cancellationToken: TestContext.Current.CancellationToken);
|
|
|
|
Assert.NotNull(loaded);
|
|
Assert.Equal(snapshot.ScanId, loaded!.ScanId);
|
|
Assert.Equal(snapshot.Language, loaded.Language);
|
|
Assert.Equal(snapshot.GraphDigest, loaded.GraphDigest);
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Integration)]
|
|
[Fact]
|
|
public async Task SetThenGet_ReachabilityResult_RoundTrips()
|
|
{
|
|
if (!ValkeyTestsEnabled || _cache is null)
|
|
{
|
|
Assert.True(true, "Valkey integration tests disabled. Set STELLA_VALKEY_TESTS=1 to enable.");
|
|
return;
|
|
}
|
|
|
|
var result = new ReachabilityAnalysisResult(
|
|
ScanId: "scan-cache-2",
|
|
GraphDigest: "sha256:cg",
|
|
Language: "dotnet",
|
|
ComputedAt: DateTimeOffset.UtcNow,
|
|
ReachableNodeIds: [],
|
|
ReachableSinkIds: [],
|
|
Paths: [],
|
|
ResultDigest: "sha256:r");
|
|
|
|
await _cache.SetReachabilityResultAsync(result, cancellationToken: TestContext.Current.CancellationToken);
|
|
var loaded = await _cache.TryGetReachabilityResultAsync("scan-cache-2", "dotnet", cancellationToken: TestContext.Current.CancellationToken);
|
|
|
|
Assert.NotNull(loaded);
|
|
Assert.Equal(result.ResultDigest, loaded!.ResultDigest);
|
|
}
|
|
}
|