save checkpoint
This commit is contained in:
@@ -21,8 +21,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "System",
|
||||
TypeName = "String",
|
||||
MemberName = "Trim"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="String",
|
||||
Method ="Trim"
|
||||
};
|
||||
|
||||
// Act
|
||||
@@ -47,8 +48,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
adapter.RecordObservation(
|
||||
@@ -84,8 +86,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
// Record observation 10 days ago
|
||||
@@ -117,8 +120,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
adapter.RecordObservation(
|
||||
@@ -157,8 +161,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
adapter.RecordObservation(
|
||||
@@ -182,8 +187,7 @@ public class InMemorySignalsAdapterTests
|
||||
// Assert
|
||||
result.Contexts.Should().NotBeEmpty();
|
||||
result.Contexts[0].Environment.Should().Be("production");
|
||||
result.Contexts[0].Service.Should().Be("api-gateway");
|
||||
result.Contexts[0].TraceId.Should().Be("trace-001");
|
||||
result.Contexts[0].ContainerId.Should().Be("api-gateway");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -194,8 +198,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
adapter.RecordObservation(
|
||||
@@ -225,8 +230,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
adapter.RecordObservation(
|
||||
@@ -264,8 +270,9 @@ public class InMemorySignalsAdapterTests
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Namespace = "MyApp",
|
||||
TypeName = "Service",
|
||||
MemberName = "Process"
|
||||
Purl = "pkg:nuget/test@1.0.0",
|
||||
Type ="Service",
|
||||
Method ="Process"
|
||||
};
|
||||
|
||||
adapter.RecordObservation(
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Time.Testing;
|
||||
using StellaOps.Reachability.Core;
|
||||
using StellaOps.ReachGraph.Persistence;
|
||||
using StellaOps.ReachGraph.Schema;
|
||||
using StellaOps.ReachGraph.WebService.Services;
|
||||
using Xunit;
|
||||
@@ -23,9 +23,10 @@ public class ReachGraphStoreAdapterTests
|
||||
var adapter = CreateAdapter();
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Purl = "pkg:nuget/System@1.0.0",
|
||||
Namespace = "System",
|
||||
TypeName = "String",
|
||||
MemberName = "Trim"
|
||||
Type = "String",
|
||||
Method = "Trim"
|
||||
};
|
||||
|
||||
// Act
|
||||
@@ -48,9 +49,10 @@ public class ReachGraphStoreAdapterTests
|
||||
var adapter = CreateAdapter();
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Purl = "pkg:nuget/MyApp@1.0.0",
|
||||
Namespace = "MyApp",
|
||||
TypeName = "VulnerableClass",
|
||||
MemberName = "Execute"
|
||||
Type = "VulnerableClass",
|
||||
Method = "Execute"
|
||||
};
|
||||
|
||||
// Act
|
||||
@@ -59,7 +61,7 @@ public class ReachGraphStoreAdapterTests
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result.IsReachable.Should().BeTrue();
|
||||
result.DistanceFromEntrypoint.Should().BeGreaterThanOrEqualTo(0);
|
||||
result.ShortestPathLength.Should().BeGreaterThanOrEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -72,9 +74,10 @@ public class ReachGraphStoreAdapterTests
|
||||
var adapter = CreateAdapter();
|
||||
var symbol = new SymbolRef
|
||||
{
|
||||
Purl = "pkg:nuget/NonExistent@1.0.0",
|
||||
Namespace = "NonExistent",
|
||||
TypeName = "Class",
|
||||
MemberName = "Method"
|
||||
Type = "Class",
|
||||
Method = "Method"
|
||||
};
|
||||
|
||||
// Act
|
||||
@@ -151,7 +154,7 @@ public class ReachGraphStoreAdapterTests
|
||||
return new ReachGraphStoreAdapter(
|
||||
_storeService,
|
||||
_timeProvider,
|
||||
NullLogger<ReachGraphStoreAdapter>.Instance);
|
||||
"test-tenant");
|
||||
}
|
||||
|
||||
private static ReachGraphMinimal CreateTestGraph(string artifactDigest)
|
||||
@@ -160,53 +163,63 @@ public class ReachGraphStoreAdapterTests
|
||||
{
|
||||
Id = "entry-main",
|
||||
Ref = "MyApp.Program.Main",
|
||||
Kind = "method",
|
||||
Depth = 0
|
||||
Kind = ReachGraphNodeKind.Function,
|
||||
IsEntrypoint = true
|
||||
};
|
||||
|
||||
var vulnerableClass = new ReachGraphNode
|
||||
{
|
||||
Id = "vulnerable-class",
|
||||
Ref = "MyApp.VulnerableClass.Execute",
|
||||
Kind = "method",
|
||||
Depth = 1
|
||||
Kind = ReachGraphNodeKind.Function,
|
||||
IsSink = true
|
||||
};
|
||||
|
||||
var otherNode = new ReachGraphNode
|
||||
{
|
||||
Id = "other-node",
|
||||
Ref = "MyApp.OtherClass.DoWork",
|
||||
Kind = "method",
|
||||
Depth = 2
|
||||
Kind = ReachGraphNodeKind.Function
|
||||
};
|
||||
|
||||
var edges = ImmutableArray.Create(
|
||||
new ReachGraphEdge
|
||||
{
|
||||
Source = "entry-main",
|
||||
Target = "vulnerable-class"
|
||||
From = "entry-main",
|
||||
To = "vulnerable-class",
|
||||
Why = new EdgeExplanation
|
||||
{
|
||||
Type = EdgeExplanationType.DirectCall,
|
||||
Confidence = 1.0
|
||||
}
|
||||
},
|
||||
new ReachGraphEdge
|
||||
{
|
||||
Source = "entry-main",
|
||||
Target = "other-node"
|
||||
From = "entry-main",
|
||||
To = "other-node",
|
||||
Why = new EdgeExplanation
|
||||
{
|
||||
Type = EdgeExplanationType.DirectCall,
|
||||
Confidence = 1.0
|
||||
}
|
||||
});
|
||||
|
||||
return new ReachGraphMinimal
|
||||
{
|
||||
Artifact = new ReachGraphArtifact
|
||||
Artifact = new ReachGraphArtifact(
|
||||
"test-artifact",
|
||||
artifactDigest,
|
||||
ImmutableArray.Create("test")),
|
||||
Scope = new ReachGraphScope(
|
||||
ImmutableArray.Create("entry-main"),
|
||||
ImmutableArray<string>.Empty,
|
||||
null),
|
||||
Provenance = new ReachGraphProvenance
|
||||
{
|
||||
Name = "test-artifact",
|
||||
Digest = artifactDigest,
|
||||
Env = "test"
|
||||
Inputs = new ReachGraphInputs { Sbom = "sha256:sbom-test" },
|
||||
ComputedAt = DateTimeOffset.UtcNow,
|
||||
Analyzer = new ReachGraphAnalyzer("test-analyzer", "1.0.0", "sha256:toolchain")
|
||||
},
|
||||
Scope = new ReachGraphScope
|
||||
{
|
||||
Entrypoints = ImmutableArray.Create("entry-main"),
|
||||
Selectors = ImmutableArray<string>.Empty,
|
||||
Cves = null
|
||||
},
|
||||
Signature = null,
|
||||
Nodes = ImmutableArray.Create(entrypoint, vulnerableClass, otherNode),
|
||||
Edges = edges
|
||||
};
|
||||
@@ -220,16 +233,16 @@ internal sealed class InMemoryReachGraphStoreService : IReachGraphStoreService
|
||||
{
|
||||
private readonly Dictionary<string, ReachGraphMinimal> _graphs = new();
|
||||
|
||||
public Task<ReachGraphStoreResult> UpsertAsync(
|
||||
public Task<StoreResult> UpsertAsync(
|
||||
ReachGraphMinimal graph,
|
||||
string? tenantId,
|
||||
CancellationToken ct)
|
||||
string tenantId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var digest = graph.Artifact.Digest;
|
||||
var created = !_graphs.ContainsKey(digest);
|
||||
_graphs[digest] = graph;
|
||||
|
||||
return Task.FromResult(new ReachGraphStoreResult
|
||||
return Task.FromResult(new StoreResult
|
||||
{
|
||||
Digest = digest,
|
||||
ArtifactDigest = digest,
|
||||
@@ -242,28 +255,40 @@ internal sealed class InMemoryReachGraphStoreService : IReachGraphStoreService
|
||||
|
||||
public Task<ReachGraphMinimal?> GetByDigestAsync(
|
||||
string digest,
|
||||
string? tenantId,
|
||||
CancellationToken ct)
|
||||
string tenantId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
_graphs.TryGetValue(digest, out var graph);
|
||||
return Task.FromResult(graph);
|
||||
}
|
||||
|
||||
public Task<ReachGraphMinimal?> GetByArtifactAsync(
|
||||
public Task<IReadOnlyList<ReachGraphSummary>> ListByArtifactAsync(
|
||||
string artifactDigest,
|
||||
string? tenantId,
|
||||
CancellationToken ct)
|
||||
string tenantId,
|
||||
int limit = 50,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var graph = _graphs.Values.FirstOrDefault(g => g.Artifact.Digest == artifactDigest);
|
||||
return Task.FromResult(graph);
|
||||
var summaries = _graphs.Values
|
||||
.Where(g => g.Artifact.Digest == artifactDigest)
|
||||
.Select(g => new ReachGraphSummary
|
||||
{
|
||||
Digest = g.Artifact.Digest,
|
||||
ArtifactDigest = g.Artifact.Digest,
|
||||
NodeCount = g.Nodes.Length,
|
||||
EdgeCount = g.Edges.Length,
|
||||
BlobSizeBytes = 0,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
Scope = g.Scope
|
||||
})
|
||||
.Take(limit)
|
||||
.ToList();
|
||||
return Task.FromResult<IReadOnlyList<ReachGraphSummary>>(summaries);
|
||||
}
|
||||
|
||||
public Task<bool> ExistsAsync(string digest, string? tenantId, CancellationToken ct)
|
||||
{
|
||||
return Task.FromResult(_graphs.ContainsKey(digest));
|
||||
}
|
||||
|
||||
public Task<bool> DeleteAsync(string digest, string? tenantId, CancellationToken ct)
|
||||
public Task<bool> DeleteAsync(
|
||||
string digest,
|
||||
string tenantId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(_graphs.Remove(digest));
|
||||
}
|
||||
|
||||
@@ -22,5 +22,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\StellaOps.ReachGraph.WebService\StellaOps.ReachGraph.WebService.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.TestKit\StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user