up
Some checks failed
api-governance / spectral-lint (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Some checks failed
api-governance / spectral-lint (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using StellaOps.Scanner.Worker.Determinism;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.Worker.Tests.Determinism;
|
||||
|
||||
public class DeterministicTimeProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public void GetUtcNow_ReturnsFixedInstant()
|
||||
{
|
||||
var fixedInstant = new DateTimeOffset(2024, 01, 01, 12, 0, 0, TimeSpan.Zero);
|
||||
var provider = new DeterministicTimeProvider(fixedInstant);
|
||||
|
||||
Assert.Equal(fixedInstant, provider.GetUtcNow());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeterministicRandomProvider_ReturnsStableSequence_WhenSeeded()
|
||||
{
|
||||
var provider = new DeterministicRandomProvider(1234);
|
||||
var rng1 = provider.Create();
|
||||
var rng2 = provider.Create();
|
||||
|
||||
var seq1 = new[] { rng1.Next(), rng1.Next(), rng1.Next() };
|
||||
var seq2 = new[] { rng2.Next(), rng2.Next(), rng2.Next() };
|
||||
|
||||
Assert.Equal(seq1, seq2);
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public class EntropyStageExecutorTests
|
||||
|
||||
var fileEntries = new List<ScanFileEntry>
|
||||
{
|
||||
new ScanFileEntry(tmp, sizeBytes: bytes.LongLength, kind: "blob", metadata: new Dictionary<string, string>())
|
||||
new ScanFileEntry(tmp, SizeBytes: bytes.LongLength, Kind: "blob", Metadata: new Dictionary<string, string>())
|
||||
};
|
||||
|
||||
var lease = new StubLease("job-1", "scan-1", imageDigest: "sha256:test", layerDigest: "sha256:layer");
|
||||
@@ -55,13 +55,25 @@ public class EntropyStageExecutorTests
|
||||
{
|
||||
JobId = jobId;
|
||||
ScanId = scanId;
|
||||
ImageDigest = imageDigest;
|
||||
LayerDigest = layerDigest;
|
||||
Metadata = new Dictionary<string, string>
|
||||
{
|
||||
["image.digest"] = imageDigest,
|
||||
["layerDigest"] = layerDigest
|
||||
};
|
||||
}
|
||||
|
||||
public string JobId { get; }
|
||||
public string ScanId { get; }
|
||||
public string? ImageDigest { get; }
|
||||
public string? LayerDigest { get; }
|
||||
public int Attempt => 1;
|
||||
public DateTimeOffset EnqueuedAtUtc => DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset LeasedAtUtc => DateTimeOffset.UtcNow;
|
||||
public TimeSpan LeaseDuration => TimeSpan.FromMinutes(5);
|
||||
public IReadOnlyDictionary<string, string> Metadata { get; }
|
||||
|
||||
public ValueTask RenewAsync(CancellationToken cancellationToken) => ValueTask.CompletedTask;
|
||||
public ValueTask CompleteAsync(CancellationToken cancellationToken) => ValueTask.CompletedTask;
|
||||
public ValueTask AbandonAsync(string reason, CancellationToken cancellationToken) => ValueTask.CompletedTask;
|
||||
public ValueTask PoisonAsync(string reason, CancellationToken cancellationToken) => ValueTask.CompletedTask;
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scanner.Analyzers.Lang;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Ruby;
|
||||
using StellaOps.Scanner.Core.Contracts;
|
||||
using StellaOps.Scanner.Core.Entropy;
|
||||
using StellaOps.Scanner.EntryTrace;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.FS;
|
||||
@@ -120,6 +121,62 @@ public sealed class SurfaceManifestStageExecutorTests
|
||||
Assert.Contains(payloadMetrics, m => Equals("layer.fragments", m["surface.kind"]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteAsync_IncludesEntropyPayloads_WhenPresent()
|
||||
{
|
||||
var metrics = new ScannerWorkerMetrics();
|
||||
var publisher = new TestSurfaceManifestPublisher("tenant-a");
|
||||
var cache = new RecordingSurfaceCache();
|
||||
var environment = new TestSurfaceEnvironment("tenant-a");
|
||||
var hash = CreateCryptoHash();
|
||||
|
||||
var executor = new SurfaceManifestStageExecutor(
|
||||
publisher,
|
||||
cache,
|
||||
environment,
|
||||
metrics,
|
||||
NullLogger<SurfaceManifestStageExecutor>.Instance,
|
||||
hash,
|
||||
new NullRubyPackageInventoryStore());
|
||||
|
||||
var context = CreateContext();
|
||||
|
||||
var entropyReport = new EntropyReport(
|
||||
ImageDigest: "sha256:image",
|
||||
LayerDigest: "sha256:layer",
|
||||
Files: new[]
|
||||
{
|
||||
new EntropyFileReport(
|
||||
Path: "/bin/app",
|
||||
Size: 1024 * 32,
|
||||
OpaqueBytes: 1024 * 8,
|
||||
OpaqueRatio: 0.25,
|
||||
Flags: Array.Empty<string>(),
|
||||
Windows: Array.Empty<EntropyFileWindow>())
|
||||
},
|
||||
ImageOpaqueRatio: 0.2);
|
||||
|
||||
var entropySummary = new EntropyLayerSummary(
|
||||
LayerDigest: "sha256:layer",
|
||||
OpaqueBytes: 1024 * 8,
|
||||
TotalBytes: 1024 * 32,
|
||||
OpaqueRatio: 0.25,
|
||||
Indicators: Array.Empty<string>());
|
||||
|
||||
context.Analysis.Set(ScanAnalysisKeys.EntropyReport, entropyReport);
|
||||
context.Analysis.Set(ScanAnalysisKeys.EntropyLayerSummary, entropySummary);
|
||||
|
||||
await executor.ExecuteAsync(context, CancellationToken.None);
|
||||
|
||||
Assert.Equal(1, publisher.PublishCalls);
|
||||
Assert.NotNull(publisher.LastRequest);
|
||||
Assert.Contains(publisher.LastRequest!.Payloads, p => p.Kind == "entropy.report");
|
||||
Assert.Contains(publisher.LastRequest!.Payloads, p => p.Kind == "entropy.layer-summary");
|
||||
|
||||
// Two payloads + manifest persisted to cache.
|
||||
Assert.Equal(3, cache.Entries.Count);
|
||||
}
|
||||
|
||||
private static ScanJobContext CreateContext()
|
||||
{
|
||||
var lease = new FakeJobLease();
|
||||
|
||||
Reference in New Issue
Block a user