using System.Collections.Concurrent; using Microsoft.Extensions.DependencyInjection; using ZB.MOM.WW.ScadaBridge.SiteEventLogging; namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.TestSupport; /// /// M1 Site Event Logging categories: a capturing fake /// used by the actor tests to assert that the right operational events are emitted. /// Thread-safe — the actors fire-and-forget LogEventAsync from background /// tasks, so multiple captures can land concurrently. /// public sealed class FakeSiteEventLogger : ISiteEventLogger { /// One captured invocation. public sealed record Entry( string EventType, string Severity, string? InstanceId, string Source, string Message, string? Details); private readonly ConcurrentQueue _entries = new(); /// All captured events, in arrival order. public IReadOnlyList Entries => _entries.ToArray(); /// Captured events filtered to a single category. public IReadOnlyList OfType(string eventType) => _entries.Where(e => e.EventType == eventType).ToArray(); /// public Task LogEventAsync( string eventType, string severity, string? instanceId, string source, string message, string? details = null) { _entries.Enqueue(new Entry(eventType, severity, instanceId, source, message, details)); return Task.CompletedTask; } /// public long FailedWriteCount => 0; } /// /// Minimal that resolves a single /// — enough for the actors' optional /// _serviceProvider?.GetService<ISiteEventLogger>() resolution /// without pulling a full DI container into the actor tests. /// /// Also serves (returning a scope that just /// re-exposes this provider) so callers that do /// serviceProvider.CreateScope() — e.g. ScriptExecutionActor — /// don't throw before they reach the logging hot path. /// /// public sealed class SingleServiceProvider(ISiteEventLogger logger) : IServiceProvider, IServiceScopeFactory, IServiceScope { private readonly ISiteEventLogger _logger = logger; /// public object? GetService(Type serviceType) { if (serviceType == typeof(ISiteEventLogger)) return _logger; if (serviceType == typeof(IServiceScopeFactory)) return this; return null; } /// public IServiceScope CreateScope() => this; /// public IServiceProvider ServiceProvider => this; /// public void Dispose() { } }