Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
246 lines
8.9 KiB
C#
246 lines
8.9 KiB
C#
using System;
|
|
using System.Collections.Immutable;
|
|
using System.Text.Json;
|
|
|
|
namespace StellaOps.Scheduler.Models.Tests;
|
|
|
|
public sealed class SamplePayloadTests
|
|
{
|
|
private static readonly string SamplesRoot = LocateSamplesRoot();
|
|
|
|
[Fact]
|
|
public void ScheduleSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("schedule.json");
|
|
var schedule = CanonicalJsonSerializer.Deserialize<Schedule>(json);
|
|
|
|
Assert.Equal("sch_20251018a", schedule.Id);
|
|
Assert.Equal("tenant-alpha", schedule.TenantId);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(schedule);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void RunSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("run.json");
|
|
var run = CanonicalJsonSerializer.Deserialize<Run>(json);
|
|
|
|
Assert.Equal(RunState.Running, run.State);
|
|
Assert.Equal(42, run.Stats.Deltas);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(run);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void ImpactSetSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("impact-set.json");
|
|
var impact = CanonicalJsonSerializer.Deserialize<ImpactSet>(json);
|
|
|
|
Assert.True(impact.UsageOnly);
|
|
Assert.Single(impact.Images);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(impact);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void AuditSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("audit.json");
|
|
var audit = CanonicalJsonSerializer.Deserialize<AuditRecord>(json);
|
|
|
|
Assert.Equal("scheduler", audit.Category);
|
|
Assert.Equal("pause", audit.Action);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(audit);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void GraphBuildJobSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("graph-build-job.json");
|
|
var job = CanonicalJsonSerializer.Deserialize<GraphBuildJob>(json);
|
|
|
|
Assert.Equal(GraphJobStatus.Running, job.Status);
|
|
Assert.Equal(GraphBuildJobTrigger.SbomVersion, job.Trigger);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(job);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void GraphOverlayJobSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("graph-overlay-job.json");
|
|
var job = CanonicalJsonSerializer.Deserialize<GraphOverlayJob>(json);
|
|
|
|
Assert.Equal(GraphJobStatus.Queued, job.Status);
|
|
Assert.Equal(GraphOverlayJobTrigger.Policy, job.Trigger);
|
|
Assert.Equal(GraphOverlayKind.Policy, job.OverlayKind);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(job);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void PolicyRunRequestSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("policy-run-request.json");
|
|
var request = CanonicalJsonSerializer.Deserialize<PolicyRunRequest>(json);
|
|
|
|
Assert.Equal("default", request.TenantId);
|
|
Assert.Equal(PolicyRunMode.Incremental, request.Mode);
|
|
Assert.Equal("run:P-7:2025-10-26:auto", request.RunId);
|
|
Assert.True(request.Inputs.CaptureExplain);
|
|
Assert.Equal(2, request.Inputs.SbomSet.Length);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(request);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void PolicyRunStatusSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("policy-run-status.json");
|
|
var status = CanonicalJsonSerializer.Deserialize<PolicyRunStatus>(json);
|
|
|
|
Assert.Equal(PolicyRunExecutionStatus.Succeeded, status.Status);
|
|
Assert.Equal(1742, status.Stats.Components);
|
|
Assert.Equal("scheduler", status.Metadata["orchestrator"]);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(status);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void PolicyDiffSummarySample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("policy-diff-summary.json");
|
|
var summary = CanonicalJsonSerializer.Deserialize<PolicyDiffSummary>(json);
|
|
|
|
Assert.Equal(12, summary.Added);
|
|
Assert.Contains(summary.BySeverity.Keys, key => string.Equals(key, "critical", StringComparison.OrdinalIgnoreCase));
|
|
Assert.Equal(2, summary.RuleHits.Length);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(summary);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
|
|
[Fact]
|
|
public void PolicyExplainTraceSample_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var json = ReadSample("policy-explain-trace.json");
|
|
var trace = CanonicalJsonSerializer.Deserialize<PolicyExplainTrace>(json);
|
|
|
|
Assert.Equal("finding:sbom:S-42/pkg:npm/lodash@4.17.21", trace.FindingId);
|
|
Assert.Equal(PolicyVerdictStatus.Blocked, trace.Verdict.Status);
|
|
Assert.Equal(2, trace.RuleChain.Length);
|
|
Assert.Equal(2, trace.Evidence.Length);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(trace);
|
|
AssertJsonEquivalent(json, canonical);
|
|
}
|
|
[Fact]
|
|
public void PolicyRunJob_RoundtripsThroughCanonicalSerializer()
|
|
{
|
|
var metadata = ImmutableSortedDictionary.CreateBuilder<string, string>(StringComparer.Ordinal);
|
|
metadata["source"] = "cli";
|
|
metadata["trigger"] = "manual";
|
|
|
|
var job = new PolicyRunJob(
|
|
SchemaVersion: SchedulerSchemaVersions.PolicyRunJob,
|
|
Id: "job_20251026T140500Z",
|
|
TenantId: "tenant-alpha",
|
|
PolicyId: "P-7",
|
|
PolicyVersion: 4,
|
|
Mode: PolicyRunMode.Incremental,
|
|
Priority: PolicyRunPriority.High,
|
|
PriorityRank: -1,
|
|
RunId: "run:P-7:2025-10-26:auto",
|
|
RequestedBy: "user:cli",
|
|
CorrelationId: "req-20251026T140500Z",
|
|
Metadata: metadata.ToImmutable(),
|
|
Inputs: new PolicyRunInputs(
|
|
sbomSet: new[] { "sbom:S-42", "sbom:S-318" },
|
|
advisoryCursor: DateTimeOffset.Parse("2025-10-26T13:59:00Z"),
|
|
captureExplain: true),
|
|
QueuedAt: DateTimeOffset.Parse("2025-10-26T14:05:00Z"),
|
|
Status: PolicyRunJobStatus.Pending,
|
|
AttemptCount: 1,
|
|
LastAttemptAt: DateTimeOffset.Parse("2025-10-26T14:05:30Z"),
|
|
LastError: "transient network error",
|
|
CreatedAt: DateTimeOffset.Parse("2025-10-26T14:04:50Z"),
|
|
UpdatedAt: DateTimeOffset.Parse("2025-10-26T14:05:10Z"),
|
|
AvailableAt: DateTimeOffset.Parse("2025-10-26T14:05:20Z"),
|
|
SubmittedAt: null,
|
|
CompletedAt: null,
|
|
LeaseOwner: "worker-01",
|
|
LeaseExpiresAt: DateTimeOffset.Parse("2025-10-26T14:06:30Z"),
|
|
CancellationRequested: false,
|
|
CancellationRequestedAt: null,
|
|
CancellationReason: null,
|
|
CancelledAt: null);
|
|
|
|
var canonical = CanonicalJsonSerializer.Serialize(job);
|
|
var roundtrip = CanonicalJsonSerializer.Deserialize<PolicyRunJob>(canonical);
|
|
|
|
Assert.Equal(job.TenantId, roundtrip.TenantId);
|
|
Assert.Equal(job.PolicyId, roundtrip.PolicyId);
|
|
Assert.Equal(job.Priority, roundtrip.Priority);
|
|
Assert.Equal(job.Status, roundtrip.Status);
|
|
Assert.Equal(job.RunId, roundtrip.RunId);
|
|
Assert.Equal("cli", roundtrip.Metadata!["source"]);
|
|
}
|
|
|
|
|
|
private static string ReadSample(string fileName)
|
|
{
|
|
var path = Path.Combine(SamplesRoot, fileName);
|
|
return File.ReadAllText(path);
|
|
}
|
|
|
|
private static string LocateSamplesRoot()
|
|
{
|
|
var current = AppContext.BaseDirectory;
|
|
while (!string.IsNullOrEmpty(current))
|
|
{
|
|
var candidate = Path.Combine(current, "samples", "api", "scheduler");
|
|
if (Directory.Exists(candidate))
|
|
{
|
|
return candidate;
|
|
}
|
|
|
|
var parent = Path.GetDirectoryName(current.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
|
|
if (string.Equals(parent, current, StringComparison.Ordinal))
|
|
{
|
|
break;
|
|
}
|
|
|
|
current = parent;
|
|
}
|
|
|
|
throw new DirectoryNotFoundException("Unable to locate samples/api/scheduler in repository tree.");
|
|
}
|
|
|
|
private static void AssertJsonEquivalent(string expected, string actual)
|
|
{
|
|
var normalizedExpected = NormalizeJson(expected);
|
|
var normalizedActual = NormalizeJson(actual);
|
|
Assert.Equal(normalizedExpected, normalizedActual);
|
|
}
|
|
|
|
private static string NormalizeJson(string json)
|
|
{
|
|
using var document = JsonDocument.Parse(json);
|
|
return JsonSerializer.Serialize(document.RootElement, new JsonSerializerOptions
|
|
{
|
|
WriteIndented = false
|
|
});
|
|
}
|
|
}
|