using Akka.Actor; using Akka.Configuration; using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Cluster.Tests; /// /// Asserts the remoting frame-size canary and the DistributedPubSub extension that are actually /// in force on a real built from the shipped base config. /// /// /// Asserting the akka.conf text instead would pass while a competing HOCON fragment /// silently overrode the value — the failure mode recorded at length in /// ServiceCollectionExtensions.BuildDowningHocon and pinned the same way by /// SplitBrainResolverActivationTests. In this codebase the effective value is the only /// one worth asserting. /// public class MeshTransportHoconTests : IDisposable { private readonly ActorSystem _sys; public MeshTransportHoconTests() { var config = ConfigurationFactory .ParseString("akka.remote.dot-netty.tcp.port = 0\nakka.cluster.seed-nodes = []") .WithFallback(HoconLoader.LoadBaseConfig()); _sys = ActorSystem.Create("mesh-hocon-probe", config); } [Fact] public void Oversized_frames_are_logged_rather_than_dropped_silently() { // The sister project's most expensive incident. A message over the frame limit is dropped // WITHOUT tearing down the association: heartbeats keep flowing, the node still reports // healthy, and the only symptom is a command that never arrived. log-frame-size-exceeding // converts that silence into a log line naming the offending size. _sys.Settings.Config.GetByteSize("akka.remote.dot-netty.tcp.maximum-frame-size").ShouldBe(128000); _sys.Settings.Config.GetByteSize("akka.remote.dot-netty.tcp.log-frame-size-exceeding").ShouldBe(32000); } [Fact] public void Distributed_pub_sub_extension_is_registered_at_startup() { // DPS is PAIR-LOCAL and survives the cross-mesh transport's deletion: it carries // MeshTransport:Mode = Dps (the single-mesh default), the node-local alarm-command publishes // and the node<->node redundancy-state probe leg. Losing it would break far more than deploys. _sys.Settings.Config.GetStringList("akka.extensions") .ShouldContain(s => s.Contains("DistributedPubSubExtensionProvider")); } public void Dispose() { _sys.Terminate().Wait(TimeSpan.FromSeconds(5)); GC.SuppressFinalize(this); } }