using System.Text.Json;
using Akka.Actor;
using Akka.Event;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Deploy;
using ZB.MOM.WW.OtOpcUa.Commons.Types;
using ZB.MOM.WW.OtOpcUa.Runtime.DeploymentCache;
using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
using ZB.MOM.WW.OtOpcUa.Runtime.Tests.Harness;
namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
///
/// Surgical-deploys Task 7 Part B — a dispatch that arrives while an apply is in flight is
/// STASHED, not re-forwarded to Self.
///
///
///
/// Self.Forward put the message back at the tail of the actor's OWN mailbox, so with
/// nothing else to do the host spun dequeue → log → enqueue for the entire fetch window —
/// thousands of iterations and thousands of log lines for one deferred deployment, burning a
/// core and starving nothing but itself of useful work. The stash holds it outside the mailbox
/// until the apply finishes.
///
///
/// Runs at DEBUG because the assertion IS a log line: a spin is only distinguishable
/// from a single deferral by how many times it is announced. A log event below
/// akka.loglevel never reaches the EventStream at all, so at the default WARNING this
/// test would count zero either way and pass vacuously.
///
///
public sealed class DriverHostActorApplyingStashTests()
: RuntimeActorTestBase(AkkaTestHoconAtLevel("DEBUG"))
{
private static readonly NodeId TestNode = NodeId.Parse("driver-test");
private static readonly RevisionHash RevA = RevisionHash.Parse(new string('a', 64));
private static readonly RevisionHash RevB = RevisionHash.Parse(new string('b', 64));
/// Minimal parseable artifact — no drivers.
private static byte[] ArtifactBytes() =>
JsonSerializer.SerializeToUtf8Bytes(new { DriverInstances = Array.Empty