using Akka.Actor; using Akka.TestKit.Xunit2; using Microsoft.Extensions.Logging.Abstractions; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Instance; using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts; namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Scripts; public class AttributeSchedulerRegressionTests : TestKit { [Theory] [InlineData(false)] [InlineData(true)] public async Task SR1_SaturatedWorkersCompleteSynchronousAccessWithoutWatchdog(bool write) { const int workers = 2; using var scheduler = new ScriptExecutionScheduler(workers); var probe = CreateTestProbe(); var context = new ScriptRuntimeContext(probe.Ref, null!, 0, 10, TimeSpan.FromSeconds(3), "Pump", NullLogger.Instance); var accessor = new AttributeAccessor(context, ""); var tasks = Enumerable.Range(0, workers).Select(_ => Task.Factory.StartNew(() => { if (write) accessor["x"] = 42; else Assert.Equal(42, accessor["x"]); }, CancellationToken.None, TaskCreationOptions.None, scheduler)).ToArray(); // Hold both replies until every worker is blocked inside the synchronous accessor. var replies = new List<(IActorRef Sender, object Response)>(); for (var i = 0; i < workers; i++) { if (write) { var request = probe.ExpectMsg(); replies.Add((probe.LastSender, new SetStaticAttributeResponse(request.CorrelationId, "Pump", "x", true, null, DateTimeOffset.UtcNow))); } else { var request = probe.ExpectMsg(); replies.Add((probe.LastSender, new GetAttributeResponse(request.CorrelationId, "Pump", "x", 42, true, "Good", DateTimeOffset.UtcNow))); } } foreach (var reply in replies) reply.Sender.Tell(reply.Response); await Task.WhenAll(tasks).WaitAsync(TimeSpan.FromSeconds(2)); } }