using Microsoft.Extensions.Logging.Abstractions;
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Scripting;
using ZB.MOM.WW.ScadaBridge.Host.Services;
namespace ZB.MOM.WW.ScadaBridge.Host.Tests;
///
/// #05-T14: unit tests for the in-process script-artifact change bus — delivery,
/// unsubscribe, and the swallow-and-log guard that keeps a faulting subscriber from
/// faulting the producer.
///
public sealed class InProcessScriptArtifactChangeBusTests
{
private static InProcessScriptArtifactChangeBus NewBus() =>
new(NullLogger.Instance);
private static ScriptArtifactsChanged Sample(string kind = ScriptArtifactKinds.ApiMethod) =>
new(kind, new[] { "M1" }, "Management", DateTimeOffset.UnixEpoch);
[Fact]
public void Publish_delivers_to_all_current_subscribers()
{
var bus = NewBus();
var a = new List();
var b = new List();
bus.Subscribe(a.Add);
bus.Subscribe(b.Add);
var n = Sample();
bus.Publish(n);
Assert.Same(n, Assert.Single(a));
Assert.Same(n, Assert.Single(b));
}
[Fact]
public void Disposing_subscription_stops_delivery()
{
var bus = NewBus();
var received = new List();
var token = bus.Subscribe(received.Add);
bus.Publish(Sample());
token.Dispose();
bus.Publish(Sample());
Assert.Single(received); // only the pre-dispose publish landed.
}
[Fact]
public void Dispose_is_idempotent()
{
var bus = NewBus();
var received = new List();
var token = bus.Subscribe(received.Add);
token.Dispose();
token.Dispose(); // must not throw nor corrupt the handler list.
bus.Publish(Sample());
Assert.Empty(received);
}
[Fact]
public void A_faulting_subscriber_does_not_prevent_delivery_to_others_nor_throw()
{
var bus = NewBus();
var good = new List();
bus.Subscribe(_ => throw new InvalidOperationException("bad consumer"));
bus.Subscribe(good.Add);
// Publish must not propagate the subscriber fault...
var ex = Record.Exception(() => bus.Publish(Sample()));
Assert.Null(ex);
// ...and the well-behaved subscriber still receives it.
Assert.Single(good);
}
[Fact]
public void Publish_with_no_subscribers_is_a_noop()
{
var bus = NewBus();
Assert.Null(Record.Exception(() => bus.Publish(Sample())));
}
}