up
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
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
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
global using System.Collections.Immutable;
|
||||
global using StellaOps.Scheduler.ImpactIndex;
|
||||
global using StellaOps.Scheduler.Models;
|
||||
global using StellaOps.Scheduler.Worker;
|
||||
global using Xunit;
|
||||
global using System.Collections.Immutable;
|
||||
global using StellaOps.Scheduler.ImpactIndex;
|
||||
global using StellaOps.Scheduler.Models;
|
||||
global using StellaOps.Scheduler.Worker;
|
||||
global using Xunit;
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Scheduler.Queue;
|
||||
using StellaOps.Scheduler.Storage.Postgres.Repositories.Projections;
|
||||
using StellaOps.Scheduler.Storage.Postgres.Repositories;
|
||||
@@ -212,23 +211,23 @@ public sealed class PlannerBackgroundServiceTests
|
||||
|
||||
public IReadOnlyList<Run> UpdatedRuns => _updates.ToArray();
|
||||
|
||||
public Task InsertAsync(Run run, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task InsertAsync(Run run, CancellationToken cancellationToken = default)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public Task<bool> UpdateAsync(Run run, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<bool> UpdateAsync(Run run, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_updates.Enqueue(run);
|
||||
Interlocked.Increment(ref _updateCount);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task<Run?> GetAsync(string tenantId, string runId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<Run?> GetAsync(string tenantId, string runId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<Run?>(null);
|
||||
|
||||
public Task<IReadOnlyList<Run>> ListAsync(string tenantId, RunQueryOptions? options = null, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Run>> ListAsync(string tenantId, RunQueryOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<Run>>(Array.Empty<Run>());
|
||||
|
||||
public Task<IReadOnlyList<Run>> ListByStateAsync(RunState state, int limit = 50, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Run>> ListByStateAsync(RunState state, int limit = 50, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (state != RunState.Planning)
|
||||
{
|
||||
@@ -266,25 +265,25 @@ public sealed class PlannerBackgroundServiceTests
|
||||
|
||||
private readonly Dictionary<(string TenantId, string ScheduleId), Schedule> _schedules;
|
||||
|
||||
public Task UpsertAsync(Schedule schedule, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task UpsertAsync(Schedule schedule, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_schedules[(schedule.TenantId, schedule.Id)] = schedule;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<Schedule?> GetAsync(string tenantId, string scheduleId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<Schedule?> GetAsync(string tenantId, string scheduleId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_schedules.TryGetValue((tenantId, scheduleId), out var schedule);
|
||||
return Task.FromResult(schedule);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<Schedule>> ListAsync(string tenantId, ScheduleQueryOptions? options = null, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Schedule>> ListAsync(string tenantId, ScheduleQueryOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var results = _schedules.Values.Where(schedule => schedule.TenantId == tenantId).ToArray();
|
||||
return Task.FromResult<IReadOnlyList<Schedule>>(results);
|
||||
}
|
||||
|
||||
public Task<bool> SoftDeleteAsync(string tenantId, string scheduleId, string deletedBy, DateTimeOffset deletedAt, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<bool> SoftDeleteAsync(string tenantId, string scheduleId, string deletedBy, DateTimeOffset deletedAt, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var removed = _schedules.Remove((tenantId, scheduleId));
|
||||
return Task.FromResult(removed);
|
||||
@@ -295,16 +294,16 @@ public sealed class PlannerBackgroundServiceTests
|
||||
{
|
||||
public ImpactSet? LastSnapshot { get; private set; }
|
||||
|
||||
public Task UpsertAsync(ImpactSet snapshot, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task UpsertAsync(ImpactSet snapshot, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LastSnapshot = snapshot;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<ImpactSet?> GetBySnapshotIdAsync(string snapshotId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<ImpactSet?> GetBySnapshotIdAsync(string snapshotId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<ImpactSet?>(null);
|
||||
|
||||
public Task<ImpactSet?> GetLatestBySelectorAsync(Selector selector, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<ImpactSet?> GetLatestBySelectorAsync(Selector selector, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<ImpactSet?>(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using MongoDB.Driver;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Scheduler.Models;
|
||||
using StellaOps.Scheduler.Queue;
|
||||
@@ -187,22 +186,22 @@ public sealed class PlannerExecutionServiceTests
|
||||
_store = schedules.ToDictionary(schedule => (schedule.TenantId, schedule.Id), schedule => schedule);
|
||||
}
|
||||
|
||||
public Task UpsertAsync(Schedule schedule, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task UpsertAsync(Schedule schedule, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_store[(schedule.TenantId, schedule.Id)] = schedule;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<Schedule?> GetAsync(string tenantId, string scheduleId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<Schedule?> GetAsync(string tenantId, string scheduleId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_store.TryGetValue((tenantId, scheduleId), out var schedule);
|
||||
return Task.FromResult(schedule);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<Schedule>> ListAsync(string tenantId, ScheduleQueryOptions? options = null, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Schedule>> ListAsync(string tenantId, ScheduleQueryOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<Schedule>>(_store.Values.Where(schedule => schedule.TenantId == tenantId).ToArray());
|
||||
|
||||
public Task<bool> SoftDeleteAsync(string tenantId, string scheduleId, string deletedBy, DateTimeOffset deletedAt, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<bool> SoftDeleteAsync(string tenantId, string scheduleId, string deletedBy, DateTimeOffset deletedAt, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(_store.Remove((tenantId, scheduleId)));
|
||||
}
|
||||
|
||||
@@ -218,28 +217,28 @@ public sealed class PlannerExecutionServiceTests
|
||||
}
|
||||
}
|
||||
|
||||
public Task InsertAsync(Run run, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task InsertAsync(Run run, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_runs[(run.TenantId, run.Id)] = run;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<bool> UpdateAsync(Run run, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<bool> UpdateAsync(Run run, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_runs[(run.TenantId, run.Id)] = run;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task<Run?> GetAsync(string tenantId, string runId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<Run?> GetAsync(string tenantId, string runId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_runs.TryGetValue((tenantId, runId), out var run);
|
||||
return Task.FromResult(run);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<Run>> ListAsync(string tenantId, RunQueryOptions? options = null, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Run>> ListAsync(string tenantId, RunQueryOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<Run>>(_runs.Values.Where(run => run.TenantId == tenantId).ToArray());
|
||||
|
||||
public Task<IReadOnlyList<Run>> ListByStateAsync(RunState state, int limit = 50, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Run>> ListByStateAsync(RunState state, int limit = 50, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<Run>>(_runs.Values.Where(run => run.State == state).Take(limit).ToArray());
|
||||
}
|
||||
|
||||
@@ -247,16 +246,16 @@ public sealed class PlannerExecutionServiceTests
|
||||
{
|
||||
public ImpactSet? LastSnapshot { get; private set; }
|
||||
|
||||
public Task UpsertAsync(ImpactSet snapshot, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task UpsertAsync(ImpactSet snapshot, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LastSnapshot = snapshot;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<ImpactSet?> GetBySnapshotIdAsync(string snapshotId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<ImpactSet?> GetBySnapshotIdAsync(string snapshotId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<ImpactSet?>(null);
|
||||
|
||||
public Task<ImpactSet?> GetLatestBySelectorAsync(Selector selector, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<ImpactSet?> GetLatestBySelectorAsync(Selector selector, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<ImpactSet?>(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MongoDB.Driver;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scheduler.Models;
|
||||
@@ -67,13 +66,13 @@ public sealed class PolicyRunDispatchBackgroundServiceTests
|
||||
|
||||
public int LeaseAttempts => Volatile.Read(ref _leaseAttempts);
|
||||
|
||||
public Task InsertAsync(PolicyRunJob job, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task InsertAsync(PolicyRunJob job, CancellationToken cancellationToken = default)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
public Task<PolicyRunJob?> GetAsync(string tenantId, string jobId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<PolicyRunJob?> GetAsync(string tenantId, string jobId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<PolicyRunJob?>(null);
|
||||
|
||||
public Task<PolicyRunJob?> GetByRunIdAsync(string tenantId, string runId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<PolicyRunJob?> GetByRunIdAsync(string tenantId, string runId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<PolicyRunJob?>(null);
|
||||
|
||||
public Task<PolicyRunJob?> LeaseAsync(
|
||||
@@ -81,7 +80,6 @@ public sealed class PolicyRunDispatchBackgroundServiceTests
|
||||
DateTimeOffset now,
|
||||
TimeSpan leaseDuration,
|
||||
int maxAttempts,
|
||||
IClientSessionHandle? session = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Interlocked.Increment(ref _leaseAttempts);
|
||||
@@ -95,14 +93,12 @@ public sealed class PolicyRunDispatchBackgroundServiceTests
|
||||
IReadOnlyCollection<PolicyRunJobStatus>? statuses = null,
|
||||
DateTimeOffset? queuedAfter = null,
|
||||
int limit = 50,
|
||||
IClientSessionHandle? session = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<PolicyRunJob>>(Array.Empty<PolicyRunJob>());
|
||||
|
||||
public Task<bool> ReplaceAsync(
|
||||
PolicyRunJob job,
|
||||
string? expectedLeaseOwner = null,
|
||||
IClientSessionHandle? session = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(true);
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Scheduler.Models;
|
||||
using StellaOps.Scheduler.Storage.Postgres.Repositories;
|
||||
using StellaOps.Scheduler.Worker.Options;
|
||||
@@ -310,13 +309,13 @@ public sealed class PolicyRunExecutionServiceTests
|
||||
public string? ExpectedLeaseOwner { get; private set; }
|
||||
public PolicyRunJob? LastJob { get; private set; }
|
||||
|
||||
public Task<PolicyRunJob?> GetAsync(string tenantId, string jobId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<PolicyRunJob?> GetAsync(string tenantId, string jobId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<PolicyRunJob?>(null);
|
||||
|
||||
public Task<PolicyRunJob?> GetByRunIdAsync(string tenantId, string runId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<PolicyRunJob?> GetByRunIdAsync(string tenantId, string runId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<PolicyRunJob?>(null);
|
||||
|
||||
public Task InsertAsync(PolicyRunJob job, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task InsertAsync(PolicyRunJob job, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LastJob = job;
|
||||
return Task.CompletedTask;
|
||||
@@ -325,10 +324,10 @@ public sealed class PolicyRunExecutionServiceTests
|
||||
public Task<long> CountAsync(string tenantId, PolicyRunMode mode, IReadOnlyCollection<PolicyRunJobStatus> statuses, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(0L);
|
||||
|
||||
public Task<PolicyRunJob?> LeaseAsync(string leaseOwner, DateTimeOffset now, TimeSpan leaseDuration, int maxAttempts, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<PolicyRunJob?> LeaseAsync(string leaseOwner, DateTimeOffset now, TimeSpan leaseDuration, int maxAttempts, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<PolicyRunJob?>(null);
|
||||
|
||||
public Task<bool> ReplaceAsync(PolicyRunJob job, string? expectedLeaseOwner = null, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<bool> ReplaceAsync(PolicyRunJob job, string? expectedLeaseOwner = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ReplaceCalled = true;
|
||||
ExpectedLeaseOwner = expectedLeaseOwner;
|
||||
@@ -336,7 +335,7 @@ public sealed class PolicyRunExecutionServiceTests
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<PolicyRunJob>> ListAsync(string tenantId, string? policyId = null, PolicyRunMode? mode = null, IReadOnlyCollection<PolicyRunJobStatus>? statuses = null, DateTimeOffset? queuedAfter = null, int limit = 50, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<PolicyRunJob>> ListAsync(string tenantId, string? policyId = null, PolicyRunMode? mode = null, IReadOnlyCollection<PolicyRunJobStatus>? statuses = null, DateTimeOffset? queuedAfter = null, int limit = 50, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<PolicyRunJob>>(Array.Empty<PolicyRunJob>());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,255 +1,255 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scheduler.Models;
|
||||
using StellaOps.Scheduler.Worker;
|
||||
using StellaOps.Scheduler.Worker.Options;
|
||||
using StellaOps.Scheduler.Worker.Policy;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scheduler.Worker.Tests;
|
||||
|
||||
public sealed class PolicyRunTargetingServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_ReturnsUnchanged_ForNonIncrementalJob()
|
||||
{
|
||||
var service = CreateService();
|
||||
var job = CreateJob(mode: PolicyRunMode.Full);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Unchanged, result.Status);
|
||||
Assert.Equal(job, result.Job);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_ReturnsUnchanged_WhenSbomSetAlreadyPresent()
|
||||
{
|
||||
var service = CreateService();
|
||||
var inputs = new PolicyRunInputs(sbomSet: new[] { "sbom:S-1" });
|
||||
var job = CreateJob(inputs: inputs);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Unchanged, result.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_ReturnsNoWork_WhenNoCandidatesResolved()
|
||||
{
|
||||
var impact = new StubImpactTargetingService();
|
||||
var service = CreateService(impact);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.purls", "pkg:npm/leftpad");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.NoWork, result.Status);
|
||||
Assert.Equal("no_matches", result.Reason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_TargetsDirectSboms()
|
||||
{
|
||||
var service = CreateService();
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.sboms", "sbom:S-2, sbom:S-1, sbom:S-2");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Targeted, result.Status);
|
||||
Assert.Equal(new[] { "sbom:S-1", "sbom:S-2" }, result.Job.Inputs.SbomSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_TargetsUsingImpactIndex()
|
||||
{
|
||||
var impact = new StubImpactTargetingService
|
||||
{
|
||||
OnResolveByPurls = (keys, usageOnly, selector, _) =>
|
||||
{
|
||||
var image = new ImpactImage(
|
||||
"sha256:111",
|
||||
"registry",
|
||||
"repo",
|
||||
labels: ImmutableSortedDictionary.Create<string, string>(StringComparer.Ordinal).Add("sbomId", "sbom:S-42"));
|
||||
var impactSet = new ImpactSet(
|
||||
selector,
|
||||
new[] { image },
|
||||
usageOnly,
|
||||
DateTimeOffset.UtcNow,
|
||||
total: 1,
|
||||
snapshotId: null,
|
||||
schemaVersion: SchedulerSchemaVersions.ImpactSet);
|
||||
return ValueTask.FromResult(impactSet);
|
||||
}
|
||||
};
|
||||
|
||||
var service = CreateService(impact);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.purls", "pkg:npm/example");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Targeted, result.Status);
|
||||
Assert.Equal(new[] { "sbom:S-42" }, result.Job.Inputs.SbomSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_FallsBack_WhenLimitExceeded()
|
||||
{
|
||||
var service = CreateService(configure: options => options.MaxSboms = 1);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.sboms", "sbom:S-1,sbom:S-2");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Unchanged, result.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_FallbacksToDigest_WhenLabelMissing()
|
||||
{
|
||||
var impact = new StubImpactTargetingService
|
||||
{
|
||||
OnResolveByVulnerabilities = (ids, usageOnly, selector, _) =>
|
||||
{
|
||||
var image = new ImpactImage("sha256:aaa", "registry", "repo");
|
||||
var impactSet = new ImpactSet(
|
||||
selector,
|
||||
new[] { image },
|
||||
usageOnly,
|
||||
DateTimeOffset.UtcNow,
|
||||
total: 1,
|
||||
snapshotId: null,
|
||||
schemaVersion: SchedulerSchemaVersions.ImpactSet);
|
||||
return ValueTask.FromResult(impactSet);
|
||||
}
|
||||
};
|
||||
|
||||
var service = CreateService(impact);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.vulns", "CVE-2025-1234");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Targeted, result.Status);
|
||||
Assert.Equal(new[] { "sbom:sha256:aaa" }, result.Job.Inputs.SbomSet);
|
||||
}
|
||||
|
||||
private static PolicyRunTargetingService CreateService(
|
||||
IImpactTargetingService? impact = null,
|
||||
Action<SchedulerWorkerOptions.PolicyOptions.TargetingOptions>? configure = null)
|
||||
{
|
||||
impact ??= new StubImpactTargetingService();
|
||||
var options = CreateOptions(configure);
|
||||
return new PolicyRunTargetingService(
|
||||
impact,
|
||||
Microsoft.Extensions.Options.Options.Create(options),
|
||||
timeProvider: null,
|
||||
NullLogger<PolicyRunTargetingService>.Instance);
|
||||
}
|
||||
|
||||
private static SchedulerWorkerOptions CreateOptions(Action<SchedulerWorkerOptions.PolicyOptions.TargetingOptions>? configure)
|
||||
{
|
||||
var options = new SchedulerWorkerOptions
|
||||
{
|
||||
Policy =
|
||||
{
|
||||
Api =
|
||||
{
|
||||
BaseAddress = new Uri("https://policy.example.com"),
|
||||
RunsPath = "/runs",
|
||||
SimulatePath = "/simulate"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configure?.Invoke(options.Policy.Targeting);
|
||||
return options;
|
||||
}
|
||||
|
||||
private static PolicyRunJob CreateJob(
|
||||
PolicyRunMode mode = PolicyRunMode.Incremental,
|
||||
ImmutableSortedDictionary<string, string>? metadata = null,
|
||||
PolicyRunInputs? inputs = null)
|
||||
{
|
||||
return new PolicyRunJob(
|
||||
SchemaVersion: SchedulerSchemaVersions.PolicyRunJob,
|
||||
Id: "job-1",
|
||||
TenantId: "tenant-alpha",
|
||||
PolicyId: "P-7",
|
||||
PolicyVersion: 4,
|
||||
Mode: mode,
|
||||
Priority: PolicyRunPriority.Normal,
|
||||
PriorityRank: 0,
|
||||
RunId: null,
|
||||
RequestedBy: null,
|
||||
CorrelationId: null,
|
||||
Metadata: metadata ?? ImmutableSortedDictionary<string, string>.Empty,
|
||||
Inputs: inputs ?? PolicyRunInputs.Empty,
|
||||
QueuedAt: DateTimeOffset.UtcNow,
|
||||
Status: PolicyRunJobStatus.Dispatching,
|
||||
AttemptCount: 0,
|
||||
LastAttemptAt: null,
|
||||
LastError: null,
|
||||
CreatedAt: DateTimeOffset.UtcNow,
|
||||
UpdatedAt: DateTimeOffset.UtcNow,
|
||||
AvailableAt: DateTimeOffset.UtcNow,
|
||||
SubmittedAt: null,
|
||||
CompletedAt: null,
|
||||
LeaseOwner: "lease",
|
||||
LeaseExpiresAt: DateTimeOffset.UtcNow.AddMinutes(1),
|
||||
CancellationRequested: false,
|
||||
CancellationRequestedAt: null,
|
||||
CancellationReason: null,
|
||||
CancelledAt: null);
|
||||
}
|
||||
|
||||
private sealed class StubImpactTargetingService : IImpactTargetingService
|
||||
{
|
||||
public Func<IEnumerable<string>, bool, Selector, CancellationToken, ValueTask<ImpactSet>>? OnResolveByPurls { get; set; }
|
||||
|
||||
public Func<IEnumerable<string>, bool, Selector, CancellationToken, ValueTask<ImpactSet>>? OnResolveByVulnerabilities { get; set; }
|
||||
|
||||
public ValueTask<ImpactSet> ResolveByPurlsAsync(IEnumerable<string> productKeys, bool usageOnly, Selector selector, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (OnResolveByPurls is null)
|
||||
{
|
||||
return ValueTask.FromResult(CreateEmptyImpactSet(selector, usageOnly));
|
||||
}
|
||||
|
||||
return OnResolveByPurls(productKeys, usageOnly, selector, cancellationToken);
|
||||
}
|
||||
|
||||
public ValueTask<ImpactSet> ResolveByVulnerabilitiesAsync(IEnumerable<string> vulnerabilityIds, bool usageOnly, Selector selector, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (OnResolveByVulnerabilities is null)
|
||||
{
|
||||
return ValueTask.FromResult(CreateEmptyImpactSet(selector, usageOnly));
|
||||
}
|
||||
|
||||
return OnResolveByVulnerabilities(vulnerabilityIds, usageOnly, selector, cancellationToken);
|
||||
}
|
||||
|
||||
public ValueTask<ImpactSet> ResolveAllAsync(Selector selector, bool usageOnly, CancellationToken cancellationToken = default)
|
||||
=> ValueTask.FromResult(CreateEmptyImpactSet(selector, usageOnly));
|
||||
|
||||
private static ImpactSet CreateEmptyImpactSet(Selector selector, bool usageOnly)
|
||||
{
|
||||
return new ImpactSet(
|
||||
selector,
|
||||
ImmutableArray<ImpactImage>.Empty,
|
||||
usageOnly,
|
||||
DateTimeOffset.UtcNow,
|
||||
total: 0,
|
||||
snapshotId: null,
|
||||
schemaVersion: SchedulerSchemaVersions.ImpactSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scheduler.Models;
|
||||
using StellaOps.Scheduler.Worker;
|
||||
using StellaOps.Scheduler.Worker.Options;
|
||||
using StellaOps.Scheduler.Worker.Policy;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scheduler.Worker.Tests;
|
||||
|
||||
public sealed class PolicyRunTargetingServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_ReturnsUnchanged_ForNonIncrementalJob()
|
||||
{
|
||||
var service = CreateService();
|
||||
var job = CreateJob(mode: PolicyRunMode.Full);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Unchanged, result.Status);
|
||||
Assert.Equal(job, result.Job);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_ReturnsUnchanged_WhenSbomSetAlreadyPresent()
|
||||
{
|
||||
var service = CreateService();
|
||||
var inputs = new PolicyRunInputs(sbomSet: new[] { "sbom:S-1" });
|
||||
var job = CreateJob(inputs: inputs);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Unchanged, result.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_ReturnsNoWork_WhenNoCandidatesResolved()
|
||||
{
|
||||
var impact = new StubImpactTargetingService();
|
||||
var service = CreateService(impact);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.purls", "pkg:npm/leftpad");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.NoWork, result.Status);
|
||||
Assert.Equal("no_matches", result.Reason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_TargetsDirectSboms()
|
||||
{
|
||||
var service = CreateService();
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.sboms", "sbom:S-2, sbom:S-1, sbom:S-2");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Targeted, result.Status);
|
||||
Assert.Equal(new[] { "sbom:S-1", "sbom:S-2" }, result.Job.Inputs.SbomSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_TargetsUsingImpactIndex()
|
||||
{
|
||||
var impact = new StubImpactTargetingService
|
||||
{
|
||||
OnResolveByPurls = (keys, usageOnly, selector, _) =>
|
||||
{
|
||||
var image = new ImpactImage(
|
||||
"sha256:111",
|
||||
"registry",
|
||||
"repo",
|
||||
labels: ImmutableSortedDictionary.Create<string, string>(StringComparer.Ordinal).Add("sbomId", "sbom:S-42"));
|
||||
var impactSet = new ImpactSet(
|
||||
selector,
|
||||
new[] { image },
|
||||
usageOnly,
|
||||
DateTimeOffset.UtcNow,
|
||||
total: 1,
|
||||
snapshotId: null,
|
||||
schemaVersion: SchedulerSchemaVersions.ImpactSet);
|
||||
return ValueTask.FromResult(impactSet);
|
||||
}
|
||||
};
|
||||
|
||||
var service = CreateService(impact);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.purls", "pkg:npm/example");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Targeted, result.Status);
|
||||
Assert.Equal(new[] { "sbom:S-42" }, result.Job.Inputs.SbomSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_FallsBack_WhenLimitExceeded()
|
||||
{
|
||||
var service = CreateService(configure: options => options.MaxSboms = 1);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.sboms", "sbom:S-1,sbom:S-2");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Unchanged, result.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureTargetsAsync_FallbacksToDigest_WhenLabelMissing()
|
||||
{
|
||||
var impact = new StubImpactTargetingService
|
||||
{
|
||||
OnResolveByVulnerabilities = (ids, usageOnly, selector, _) =>
|
||||
{
|
||||
var image = new ImpactImage("sha256:aaa", "registry", "repo");
|
||||
var impactSet = new ImpactSet(
|
||||
selector,
|
||||
new[] { image },
|
||||
usageOnly,
|
||||
DateTimeOffset.UtcNow,
|
||||
total: 1,
|
||||
snapshotId: null,
|
||||
schemaVersion: SchedulerSchemaVersions.ImpactSet);
|
||||
return ValueTask.FromResult(impactSet);
|
||||
}
|
||||
};
|
||||
|
||||
var service = CreateService(impact);
|
||||
var metadata = ImmutableSortedDictionary<string, string>.Empty.Add("delta.vulns", "CVE-2025-1234");
|
||||
var job = CreateJob(metadata: metadata, inputs: PolicyRunInputs.Empty);
|
||||
|
||||
var result = await service.EnsureTargetsAsync(job, CancellationToken.None);
|
||||
|
||||
Assert.Equal(PolicyRunTargetingStatus.Targeted, result.Status);
|
||||
Assert.Equal(new[] { "sbom:sha256:aaa" }, result.Job.Inputs.SbomSet);
|
||||
}
|
||||
|
||||
private static PolicyRunTargetingService CreateService(
|
||||
IImpactTargetingService? impact = null,
|
||||
Action<SchedulerWorkerOptions.PolicyOptions.TargetingOptions>? configure = null)
|
||||
{
|
||||
impact ??= new StubImpactTargetingService();
|
||||
var options = CreateOptions(configure);
|
||||
return new PolicyRunTargetingService(
|
||||
impact,
|
||||
Microsoft.Extensions.Options.Options.Create(options),
|
||||
timeProvider: null,
|
||||
NullLogger<PolicyRunTargetingService>.Instance);
|
||||
}
|
||||
|
||||
private static SchedulerWorkerOptions CreateOptions(Action<SchedulerWorkerOptions.PolicyOptions.TargetingOptions>? configure)
|
||||
{
|
||||
var options = new SchedulerWorkerOptions
|
||||
{
|
||||
Policy =
|
||||
{
|
||||
Api =
|
||||
{
|
||||
BaseAddress = new Uri("https://policy.example.com"),
|
||||
RunsPath = "/runs",
|
||||
SimulatePath = "/simulate"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configure?.Invoke(options.Policy.Targeting);
|
||||
return options;
|
||||
}
|
||||
|
||||
private static PolicyRunJob CreateJob(
|
||||
PolicyRunMode mode = PolicyRunMode.Incremental,
|
||||
ImmutableSortedDictionary<string, string>? metadata = null,
|
||||
PolicyRunInputs? inputs = null)
|
||||
{
|
||||
return new PolicyRunJob(
|
||||
SchemaVersion: SchedulerSchemaVersions.PolicyRunJob,
|
||||
Id: "job-1",
|
||||
TenantId: "tenant-alpha",
|
||||
PolicyId: "P-7",
|
||||
PolicyVersion: 4,
|
||||
Mode: mode,
|
||||
Priority: PolicyRunPriority.Normal,
|
||||
PriorityRank: 0,
|
||||
RunId: null,
|
||||
RequestedBy: null,
|
||||
CorrelationId: null,
|
||||
Metadata: metadata ?? ImmutableSortedDictionary<string, string>.Empty,
|
||||
Inputs: inputs ?? PolicyRunInputs.Empty,
|
||||
QueuedAt: DateTimeOffset.UtcNow,
|
||||
Status: PolicyRunJobStatus.Dispatching,
|
||||
AttemptCount: 0,
|
||||
LastAttemptAt: null,
|
||||
LastError: null,
|
||||
CreatedAt: DateTimeOffset.UtcNow,
|
||||
UpdatedAt: DateTimeOffset.UtcNow,
|
||||
AvailableAt: DateTimeOffset.UtcNow,
|
||||
SubmittedAt: null,
|
||||
CompletedAt: null,
|
||||
LeaseOwner: "lease",
|
||||
LeaseExpiresAt: DateTimeOffset.UtcNow.AddMinutes(1),
|
||||
CancellationRequested: false,
|
||||
CancellationRequestedAt: null,
|
||||
CancellationReason: null,
|
||||
CancelledAt: null);
|
||||
}
|
||||
|
||||
private sealed class StubImpactTargetingService : IImpactTargetingService
|
||||
{
|
||||
public Func<IEnumerable<string>, bool, Selector, CancellationToken, ValueTask<ImpactSet>>? OnResolveByPurls { get; set; }
|
||||
|
||||
public Func<IEnumerable<string>, bool, Selector, CancellationToken, ValueTask<ImpactSet>>? OnResolveByVulnerabilities { get; set; }
|
||||
|
||||
public ValueTask<ImpactSet> ResolveByPurlsAsync(IEnumerable<string> productKeys, bool usageOnly, Selector selector, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (OnResolveByPurls is null)
|
||||
{
|
||||
return ValueTask.FromResult(CreateEmptyImpactSet(selector, usageOnly));
|
||||
}
|
||||
|
||||
return OnResolveByPurls(productKeys, usageOnly, selector, cancellationToken);
|
||||
}
|
||||
|
||||
public ValueTask<ImpactSet> ResolveByVulnerabilitiesAsync(IEnumerable<string> vulnerabilityIds, bool usageOnly, Selector selector, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (OnResolveByVulnerabilities is null)
|
||||
{
|
||||
return ValueTask.FromResult(CreateEmptyImpactSet(selector, usageOnly));
|
||||
}
|
||||
|
||||
return OnResolveByVulnerabilities(vulnerabilityIds, usageOnly, selector, cancellationToken);
|
||||
}
|
||||
|
||||
public ValueTask<ImpactSet> ResolveAllAsync(Selector selector, bool usageOnly, CancellationToken cancellationToken = default)
|
||||
=> ValueTask.FromResult(CreateEmptyImpactSet(selector, usageOnly));
|
||||
|
||||
private static ImpactSet CreateEmptyImpactSet(Selector selector, bool usageOnly)
|
||||
{
|
||||
return new ImpactSet(
|
||||
selector,
|
||||
ImmutableArray<ImpactImage>.Empty,
|
||||
usageOnly,
|
||||
DateTimeOffset.UtcNow,
|
||||
total: 0,
|
||||
snapshotId: null,
|
||||
schemaVersion: SchedulerSchemaVersions.ImpactSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Scheduler.Models;
|
||||
using StellaOps.Scheduler.Queue;
|
||||
using StellaOps.Scheduler.Storage.Postgres.Repositories;
|
||||
@@ -205,28 +204,28 @@ public sealed class RunnerExecutionServiceTests
|
||||
}
|
||||
}
|
||||
|
||||
public Task InsertAsync(Run run, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task InsertAsync(Run run, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_runs[(run.TenantId, run.Id)] = run;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<bool> UpdateAsync(Run run, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<bool> UpdateAsync(Run run, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_runs[(run.TenantId, run.Id)] = run;
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
public Task<Run?> GetAsync(string tenantId, string runId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<Run?> GetAsync(string tenantId, string runId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_runs.TryGetValue((tenantId, runId), out var run);
|
||||
return Task.FromResult(run);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<Run>> ListAsync(string tenantId, RunQueryOptions? options = null, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Run>> ListAsync(string tenantId, RunQueryOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<Run>>(_runs.Values.Where(run => run.TenantId == tenantId).ToArray());
|
||||
|
||||
public Task<IReadOnlyList<Run>> ListByStateAsync(RunState state, int limit = 50, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyList<Run>> ListByStateAsync(RunState state, int limit = 50, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<IReadOnlyList<Run>>(_runs.Values.Where(run => run.State == state).Take(limit).ToArray());
|
||||
|
||||
public Run? GetSnapshot(string tenantId, string runId)
|
||||
@@ -253,13 +252,13 @@ public sealed class RunnerExecutionServiceTests
|
||||
total: imageArray.Length);
|
||||
}
|
||||
|
||||
public Task UpsertAsync(ImpactSet snapshot, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task UpsertAsync(ImpactSet snapshot, CancellationToken cancellationToken = default)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
public Task<ImpactSet?> GetBySnapshotIdAsync(string snapshotId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<ImpactSet?> GetBySnapshotIdAsync(string snapshotId, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<ImpactSet?>(string.Equals(snapshotId, _snapshotId, StringComparison.Ordinal) ? _snapshot : null);
|
||||
|
||||
public Task<ImpactSet?> GetLatestBySelectorAsync(Selector selector, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
|
||||
public Task<ImpactSet?> GetLatestBySelectorAsync(Selector selector, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult<ImpactSet?>(_snapshot);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user