using Akka.Cluster.Hosting;
using Akka.Cluster.Hosting.SBR;
using Shouldly;
using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Cluster.Tests;
///
/// Guards the split-brain-resolver ACTIVATION (arch-review 03/S1). The split-brain-resolver
/// HOCON block is inert on its own; the resolver only runs when the typed
/// is set. These tests assert
/// registers it, so a future refactor
/// cannot silently drop back to Akka's default NoDowning (the exact "built-but-never-wired" failure
/// mode this finding described).
///
public sealed class SplitBrainResolverActivationTests
{
private static AkkaClusterOptions SampleOptions() => new()
{
SeedNodes = new[] { "akka.tcp://otopcua@127.0.0.1:4053" },
Roles = new[] { "admin", "driver" },
};
/// Verifies the cluster options carry a split-brain resolver (provider gets activated).
[Fact]
public void BuildClusterOptions_activates_a_split_brain_resolver()
{
var options = ServiceCollectionExtensions.BuildClusterOptions(SampleOptions());
options.SplitBrainResolver.ShouldNotBeNull(
"SplitBrainResolver must be set — without it the cluster runs default NoDowning and never fails over on a hard crash.");
}
/// Verifies the resolver is keep-oldest with down-if-alone (correct for a 2-node pair).
[Fact]
public void BuildClusterOptions_uses_keep_oldest_with_down_if_alone()
{
var options = ServiceCollectionExtensions.BuildClusterOptions(SampleOptions());
var keepOldest = options.SplitBrainResolver.ShouldBeOfType();
keepOldest.DownIfAlone.ShouldBe(true);
}
/// Verifies seed nodes and roles are still threaded through unchanged.
[Fact]
public void BuildClusterOptions_preserves_seed_nodes_and_roles()
{
var input = SampleOptions();
var options = ServiceCollectionExtensions.BuildClusterOptions(input);
options.SeedNodes.ShouldBe(input.SeedNodes);
options.Roles.ShouldBe(input.Roles);
}
}