diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj b/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj index 750948e5101..9e9a607288a 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj +++ b/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/Akka.Cluster.Tools.Tests.MultiNode.csproj @@ -76,6 +76,7 @@ + diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/ClusterClient/ClusterClientStartSpecConfig.cs b/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/ClusterClient/ClusterClientStartSpecConfig.cs new file mode 100644 index 00000000000..91d01da7ac0 --- /dev/null +++ b/src/contrib/cluster/Akka.Cluster.Tools.Tests.MultiNode/ClusterClient/ClusterClientStartSpecConfig.cs @@ -0,0 +1,135 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Akka.Actor; +using Akka.Cluster.TestKit; +using Akka.Cluster.Tools.Client; +using Akka.Cluster.Tools.PublishSubscribe; +using Akka.Cluster.Tools.PublishSubscribe.Internal; +using Akka.Configuration; +using Akka.Remote.TestKit; +using FluentAssertions; + +namespace Akka.Cluster.Tools.Tests.MultiNode.Client +{ + + public class ClusterClientStartSpecConfig : MultiNodeConfig + { + public RoleName Client { get; } + public RoleName First { get; } + public RoleName Second { get; } + + public ClusterClientStartSpecConfig() + { + Client = Role("client"); + First = Role("first"); + Second = Role("second"); + + CommonConfig = ConfigurationFactory.ParseString(@" + akka.loglevel = INFO + akka.actor.provider = ""Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"" + akka.remote.log-remote-lifecycle-events = off + akka.cluster.client { + heartbeat-interval = 1s + acceptable-heartbeat-pause = 1s + reconnect-timeout = 60s + receptionist.number-of-contacts = 1 + } + akka.test.filter-leeway = 10s + ") + .WithFallback(ClusterClientReceptionist.DefaultConfig()) + .WithFallback(DistributedPubSub.DefaultConfig()); + } + + public class Service : ReceiveActor + { + public Service() + { + ReceiveAny(msg => Sender.Tell(msg)); + } + } + + public class ClusterClientStartMultiNode1 : ClusterClientStartSpec { } + public class ClusterClientStartMultiNode2 : ClusterClientStartSpec { } + public class ClusterClientStartMultiNode3 : ClusterClientStartSpec { } + + public abstract class ClusterClientStartSpec : MultiNodeClusterSpec + { + private readonly ClusterClientStartSpecConfig _config; + + protected ClusterClientStartSpec() : this(new ClusterClientStartSpecConfig()) + { + } + + protected ClusterClientStartSpec(ClusterClientStartSpecConfig config) : base(config) + { + _config = config; + } + + protected override int InitialParticipantsValueFactory => 3; + + private ImmutableHashSet InitialContacts + { + get + { + //return new List().ToImmutableHashSet(); + return ImmutableHashSet + .Create(_config.First, _config.Second) + .Select(r => Node(r) / "system" / "receptionist") + .ToImmutableHashSet(); + } + } + + [MultiNodeFact(Skip = "Disable due to known issues with this spec which are currently under investigation by ArjenSmitss")] + public void ClusterClientStartSpecs() + { + Start_Cluster(); + ClusterClient_can_start_with_zero_buffer(); + } + + public void Start_Cluster() + { + Within(30.Seconds(), () => + { + AwaitClusterUp(_config.First, _config.Second); + + //start our test service + RunOn(() => + { + var service = Sys.ActorOf(Props.Create(() => new ClusterClientStopSpecConfig.Service()), "testService"); + + //here we explicitly do _not_ register the service with the cluster receptionist to force the clusterclient in buffer mode + //ClusterClientReceptionist.Get(Sys).RegisterService(service); + }, _config.First, _config.Second); + + EnterBarrier("receptionist-started"); + }); + } + + public void ClusterClient_can_start_with_zero_buffer() + { + Within(30.Seconds(), () => + { + //start the cluster client + RunOn(() => + { + var c = Sys.ActorOf(ClusterClient.Props(ClusterClientSettings.Create(Sys).WithBufferSize(0).WithInitialContacts(InitialContacts)), "client1"); + //check for the debug log message that the cluster client will output in case of an 0 buffersize + EventFilter.Debug(start: "Receptionist not available and buffering is disabled, dropping message").ExpectOne( + () => + { + c.Tell(new ClusterClient.Send("/user/testService", "hello")); + }); + + //ExpectMsg(3.Seconds()).Should().Be("hello"); + + + ExpectTerminated(c, 10.Seconds()); + }, _config.Client); + + EnterBarrier("end-of-test"); + }); + } + } + } +} \ No newline at end of file diff --git a/src/contrib/cluster/Akka.Cluster.Tools.Tests/ClusterClient/ClusterClientConfigSpec.cs b/src/contrib/cluster/Akka.Cluster.Tools.Tests/ClusterClient/ClusterClientConfigSpec.cs index 0a2838edd77..f485004af09 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools.Tests/ClusterClient/ClusterClientConfigSpec.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools.Tests/ClusterClient/ClusterClientConfigSpec.cs @@ -42,7 +42,7 @@ public void ClusterClientSettings_must_have_default_config() } [Theory] - [InlineData(0)] + [InlineData(-1)] [InlineData(10001)] public void ClusterClientSettings_must_throw_exception_on_wrong_buffer(int bufferSize) { diff --git a/src/contrib/cluster/Akka.Cluster.Tools/Client/ClusterClientSettings.cs b/src/contrib/cluster/Akka.Cluster.Tools/Client/ClusterClientSettings.cs index 9995fcb7254..d65d695e457 100644 --- a/src/contrib/cluster/Akka.Cluster.Tools/Client/ClusterClientSettings.cs +++ b/src/contrib/cluster/Akka.Cluster.Tools/Client/ClusterClientSettings.cs @@ -102,7 +102,7 @@ public ClusterClientSettings( int bufferSize, TimeSpan? reconnectTimeout = null) { - if (bufferSize == 0 || bufferSize > 10000) + if (bufferSize < 0 || bufferSize > 10000) { throw new ArgumentException("BufferSize must be >= 0 and <= 10000"); }