Add unit tests and implementations for MongoDB index models and OpenAPI metadata

- Implemented `MongoIndexModelTests` to verify index models for various stores.
- Created `OpenApiMetadataFactory` with methods to generate OpenAPI metadata.
- Added tests for `OpenApiMetadataFactory` to ensure expected defaults and URL overrides.
- Introduced `ObserverSurfaceSecrets` and `WebhookSurfaceSecrets` for managing secrets.
- Developed `RuntimeSurfaceFsClient` and `WebhookSurfaceFsClient` for manifest retrieval.
- Added dependency injection tests for `SurfaceEnvironmentRegistration` in both Observer and Webhook contexts.
- Implemented tests for secret resolution in `ObserverSurfaceSecretsTests` and `WebhookSurfaceSecretsTests`.
- Created `EnsureLinkNotMergeCollectionsMigrationTests` to validate MongoDB migration logic.
- Added project files for MongoDB tests and NuGet package mirroring.
This commit is contained in:
master
2025-11-17 21:21:56 +02:00
parent d3128aec24
commit 9075bad2d9
146 changed files with 152183 additions and 82 deletions

View File

@@ -0,0 +1,9 @@
# Active Tasks
| ID | Status | Owner(s) | Depends on | Description | Notes |
|----|--------|----------|------------|-------------|-------|
| SCHED-WORKER-23-101 | BLOCKED (2025-11-17) | Scheduler Worker Guild | SCHED-WORKER-21-203 | Implement policy re-evaluation worker that shards assets, honours rate limits, and updates progress for Console after policy activation events. | Waiting on Policy guild contract for activation event shape and throttle source. |
| SCHED-WORKER-15-401 | DONE (2025-11-17) | Scheduler Worker Guild | — | Investigate and stabilize PlannerBackgroundService fairness tests (tenant fairness cap; manual/event trigger priority). | Increased monotonic wait tolerance; tests now stable. |
| SCHED-WORKER-99-901 | DONE (2025-11-17) | Scheduler Worker Guild | — | Harden PolicyRunTargetingService coverage for incremental delta rules (MaxSboms, selector replay). | Added focused unit tests + deterministic stubs. |
| SCHED-SURFACE-01 | BLOCKED (2025-11-17) | Scheduler Worker Guild | — | Evaluate Surface.FS pointers when planning delta scans to avoid redundant work and prioritise drift-triggered assets. | Blocked: Surface.FS pointer schema/data source not documented; need contract from Surface/Policy guild. |
| SCHED-WORKER-99-902 | DONE (2025-11-17) | Scheduler Worker Guild | — | Housekeeping: add guard test to PolicyRunDispatchBackgroundService to ensure disabled policy mode performs no leases. | Added stub repository & clients; verified no lease attempts when disabled. |

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using StellaOps.Scheduler.Models;
using StellaOps.Scheduler.Storage.Mongo.Repositories;
using StellaOps.Scheduler.Worker.Options;
using StellaOps.Scheduler.Worker.Policy;
namespace StellaOps.Scheduler.Worker.Tests;
public sealed class PolicyRunDispatchBackgroundServiceTests
{
[Fact]
public async Task ExecuteAsync_DoesNotLease_WhenPolicyDispatchDisabled()
{
var repository = new RecordingPolicyRunJobRepository();
var options = CreateOptions(policyEnabled: false, idleDelay: TimeSpan.FromMilliseconds(1));
var service = CreateService(repository, options);
using var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(50));
await service.StartAsync(cts.Token);
await service.StopAsync(CancellationToken.None);
Assert.Equal(0, repository.LeaseAttempts);
}
private static PolicyRunDispatchBackgroundService CreateService(
RecordingPolicyRunJobRepository repository,
SchedulerWorkerOptions options)
{
var executionService = new PolicyRunExecutionService(
repository,
new StubPolicyRunClient(),
Options.Create(options),
timeProvider: null,
new SchedulerWorkerMetrics(),
new StubPolicyRunTargetingService(),
new StubPolicySimulationWebhookClient(),
NullLogger<PolicyRunExecutionService>.Instance);
return new PolicyRunDispatchBackgroundService(
repository,
executionService,
Options.Create(options),
timeProvider: null,
NullLogger<PolicyRunDispatchBackgroundService>.Instance);
}
private static SchedulerWorkerOptions CreateOptions(bool policyEnabled, TimeSpan idleDelay)
{
var options = new SchedulerWorkerOptions();
options.Policy.Enabled = policyEnabled;
options.Policy.Dispatch.IdleDelay = idleDelay;
options.Policy.Dispatch.BatchSize = 1;
return options;
}
private sealed class RecordingPolicyRunJobRepository : IPolicyRunJobRepository
{
public int LeaseAttempts { get; private set; }
public Task InsertAsync(PolicyRunJob job, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
public Task<PolicyRunJob?> GetAsync(string tenantId, string jobId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
=> Task.FromResult<PolicyRunJob?>(null);
public Task<PolicyRunJob?> GetByRunIdAsync(string tenantId, string runId, IClientSessionHandle? session = null, CancellationToken cancellationToken = default)
=> Task.FromResult<PolicyRunJob?>(null);
public Task<PolicyRunJob?> LeaseAsync(
string leaseOwner,
DateTimeOffset now,
TimeSpan leaseDuration,
int maxAttempts,
IClientSessionHandle? session = null,
CancellationToken cancellationToken = default)
{
Interlocked.Increment(ref LeaseAttempts);
return Task.FromResult<PolicyRunJob?>(null);
}
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)
=> 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);
public Task<long> CountAsync(
string tenantId,
PolicyRunMode mode,
IReadOnlyCollection<PolicyRunJobStatus> statuses,
CancellationToken cancellationToken = default)
=> Task.FromResult(0L);
}
private sealed class StubPolicyRunClient : IPolicyRunClient
{
public Task<PolicyRunSubmissionResult> SubmitAsync(PolicyRunJob job, PolicyRunRequest request, CancellationToken cancellationToken)
=> Task.FromResult(PolicyRunSubmissionResult.Failed("disabled"));
}
private sealed class StubPolicyRunTargetingService : IPolicyRunTargetingService
{
public Task<PolicyRunTargetingResult> EnsureTargetsAsync(PolicyRunJob job, CancellationToken cancellationToken)
=> Task.FromResult(PolicyRunTargetingResult.Unchanged(job));
}
private sealed class StubPolicySimulationWebhookClient : IPolicySimulationWebhookClient
{
public Task NotifyAsync(PolicySimulationWebhookPayload payload, CancellationToken cancellationToken)
=> Task.CompletedTask;
}
}