using System; using System.Linq; using Microsoft.Extensions.Options; using StellaOps.Feedser.Source.CertCc.Configuration; using StellaOps.Feedser.Source.CertCc.Internal; using StellaOps.Feedser.Source.Common.Cursors; using Xunit; namespace StellaOps.Feedser.Source.CertCc.Tests.Internal; public sealed class CertCcSummaryPlannerTests { [Fact] public void CreatePlan_UsesInitialBackfillWindow() { var options = Options.Create(new CertCcOptions { SummaryWindow = new TimeWindowCursorOptions { WindowSize = TimeSpan.FromDays(30), Overlap = TimeSpan.FromDays(3), InitialBackfill = TimeSpan.FromDays(120), MinimumWindowSize = TimeSpan.FromDays(1), }, }); var timeProvider = new TestTimeProvider(DateTimeOffset.Parse("2025-10-10T12:00:00Z")); var planner = new CertCcSummaryPlanner(options, timeProvider); var plan = planner.CreatePlan(state: null); Assert.Equal(DateTimeOffset.Parse("2025-06-12T12:00:00Z"), plan.Window.Start); Assert.Equal(DateTimeOffset.Parse("2025-07-12T12:00:00Z"), plan.Window.End); Assert.Equal(3, plan.Requests.Count); var monthly = plan.Requests.Where(r => r.Scope == CertCcSummaryScope.Monthly).ToArray(); Assert.Collection(monthly, request => { Assert.Equal(2025, request.Year); Assert.Equal(6, request.Month); Assert.Equal("https://www.kb.cert.org/vuls/api/2025/06/summary/", request.Uri.AbsoluteUri); }, request => { Assert.Equal(2025, request.Year); Assert.Equal(7, request.Month); Assert.Equal("https://www.kb.cert.org/vuls/api/2025/07/summary/", request.Uri.AbsoluteUri); }); var yearly = plan.Requests.Where(r => r.Scope == CertCcSummaryScope.Yearly).ToArray(); Assert.Single(yearly); Assert.Equal(2025, yearly[0].Year); Assert.Null(yearly[0].Month); Assert.Equal("https://www.kb.cert.org/vuls/api/2025/summary/", yearly[0].Uri.AbsoluteUri); Assert.Equal(plan.Window.End, plan.NextState.LastWindowEnd); } [Fact] public void CreatePlan_AdvancesWindowRespectingOverlap() { var options = Options.Create(new CertCcOptions { SummaryWindow = new TimeWindowCursorOptions { WindowSize = TimeSpan.FromDays(30), Overlap = TimeSpan.FromDays(10), InitialBackfill = TimeSpan.FromDays(90), MinimumWindowSize = TimeSpan.FromDays(1), }, }); var timeProvider = new TestTimeProvider(DateTimeOffset.Parse("2025-12-01T00:00:00Z")); var planner = new CertCcSummaryPlanner(options, timeProvider); var first = planner.CreatePlan(null); var second = planner.CreatePlan(first.NextState); Assert.True(second.Window.Start < second.Window.End); Assert.Equal(first.Window.End - options.Value.SummaryWindow.Overlap, second.Window.Start); } private sealed class TestTimeProvider : TimeProvider { private DateTimeOffset _now; public TestTimeProvider(DateTimeOffset now) => _now = now; public override DateTimeOffset GetUtcNow() => _now; public void Advance(TimeSpan delta) => _now = _now.Add(delta); } }