79 lines
3.1 KiB
C#
79 lines
3.1 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Options;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
|
using ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Maintenance;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Maintenance;
|
|
|
|
/// <summary>Tests for the opt-in config-audit retention purge (review 2026-10-21 08/G1).</summary>
|
|
public class ConfigAuditPurgeServiceTests : IDisposable
|
|
{
|
|
private readonly ScadaBridgeDbContext _context = SqliteTestHelper.CreateInMemoryContext();
|
|
|
|
public void Dispose()
|
|
{
|
|
_context.Database.CloseConnection();
|
|
_context.Dispose();
|
|
}
|
|
|
|
private ConfigAuditPurgeService Create(ConfigAuditOptions opts)
|
|
{
|
|
var services = new ServiceCollection();
|
|
services.AddSingleton(_context);
|
|
return new ConfigAuditPurgeService(
|
|
services.BuildServiceProvider().GetRequiredService<IServiceScopeFactory>(),
|
|
Options.Create(opts),
|
|
TimeProvider.System,
|
|
NullLogger<ConfigAuditPurgeService>.Instance);
|
|
}
|
|
|
|
private async Task SeedAsync(int oldCount, int recentCount)
|
|
{
|
|
var now = DateTimeOffset.UtcNow;
|
|
for (var i = 0; i < oldCount; i++)
|
|
_context.AuditLogEntries.Add(new AuditLogEntry("u", "Create", "Template", $"o{i}", $"Old{i}") { Timestamp = now.AddDays(-100).AddMinutes(i) });
|
|
for (var i = 0; i < recentCount; i++)
|
|
_context.AuditLogEntries.Add(new AuditLogEntry("u", "Create", "Template", $"r{i}", $"New{i}") { Timestamp = now.AddDays(-1) });
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RetentionZero_DeletesNothing()
|
|
{
|
|
await SeedAsync(5, 2);
|
|
var deleted = await Create(new ConfigAuditOptions { RetentionDays = 0 }).PurgeOnceAsync();
|
|
Assert.Equal(0, deleted);
|
|
Assert.Equal(7, _context.AuditLogEntries.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Retention_DeletesOnlyOlderThanWindow_AcrossBatches()
|
|
{
|
|
await SeedAsync(25, 3);
|
|
var deleted = await Create(new ConfigAuditOptions { RetentionDays = 30, PurgeBatchSize = 10 }).PurgeOnceAsync();
|
|
Assert.Equal(25, deleted);
|
|
Assert.Equal(3, _context.AuditLogEntries.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Retention_MaxBatchesPerTick_TimeSlicesTheBacklog()
|
|
{
|
|
await SeedAsync(25, 0);
|
|
var svc = Create(new ConfigAuditOptions { RetentionDays = 30, PurgeBatchSize = 10, MaxBatchesPerTick = 2 });
|
|
Assert.Equal(20, await svc.PurgeOnceAsync());
|
|
Assert.Equal(5, await svc.PurgeOnceAsync());
|
|
}
|
|
|
|
[Fact]
|
|
public void Validator_RejectsNegativeRetention_AcceptsZero()
|
|
{
|
|
var v = new ConfigAuditOptionsValidator();
|
|
Assert.True(v.Validate(null, new ConfigAuditOptions { RetentionDays = 0 }).Succeeded);
|
|
Assert.True(v.Validate(null, new ConfigAuditOptions { RetentionDays = 90 }).Succeeded);
|
|
Assert.False(v.Validate(null, new ConfigAuditOptions { RetentionDays = -1 }).Succeeded);
|
|
Assert.False(v.Validate(null, new ConfigAuditOptions { PurgeBatchSize = 0 }).Succeeded);
|
|
}
|
|
}
|