diff --git a/src/core/Akka.Remote.Tests/RemotingSpec.cs b/src/core/Akka.Remote.Tests/RemotingSpec.cs index 0d280425f6d..9e5da7fa0f3 100644 --- a/src/core/Akka.Remote.Tests/RemotingSpec.cs +++ b/src/core/Akka.Remote.Tests/RemotingSpec.cs @@ -43,102 +43,105 @@ public RemotingSpec(ITestOutputHelper helper) : base(GetConfig(), helper) _remote = _remoteSystem.ActorOf(Props.Create(), "echo"); _here = Sys.ActorSelection("akka.test://remote-sys@localhost:12346/user/echo"); - AtStartup(); } private static string GetConfig() { - return @" - common-helios-settings { - port = 0 - hostname = ""localhost"" - #enforce-ip-family = true - } - - akka { - actor.provider = remote - - remote { - transport = ""Akka.Remote.Remoting,Akka.Remote"" - actor.serialize-messages = off - - retry-gate-closed-for = 1 s - log-remote-lifecycle-events = on - - enabled-transports = [ - ""akka.remote.test"", - ""akka.remote.dot-netty.tcp"", - # ""akka.remote.dot-netty.udp"" - ] - - dot-netty.tcp = ${common-helios-settings} - helios.udp = ${common-helios-settings} - - test { - transport-class = ""Akka.Remote.Transport.TestTransport,Akka.Remote"" - applied-adapters = [] - registry-key = aX33k0jWKg - local-address = ""test://RemotingSpec@localhost:12345"" - maximum-payload-bytes = 32000b - scheme-identifier = test - } - } - - actor.deployment { - /blub.remote = ""akka.test://remote-sys@localhost:12346"" - /echo.remote = ""akka.test://remote-sys@localhost:12346"" - /looker/child.remote = ""akka.test://remote-sys@localhost:12346"" - /looker/child/grandchild.remote = ""akka.test://RemotingSpec@localhost:12345"" - } - - test.timefactor = 2.5 - }"; - } - - private string GetOtherRemoteSysConfig() - { - return @" - common-helios-settings { - port = 0 - hostname = ""localhost"" - #enforce-ip-family = true - } - - akka { - actor.provider = remote - - remote { - transport = ""Akka.Remote.Remoting,Akka.Remote"" - - retry-gate-closed-for = 1 s - log-remote-lifecycle-events = on - - enabled-transports = [ - ""akka.remote.test"", - ""akka.remote.dot-netty.tcp"", -#""akka.remote.helios.udp"" - ] - - dot-netty.tcp = ${common-helios-settings} - helios.udp = ${common-helios-settings} - - test { - transport-class = ""Akka.Remote.Transport.TestTransport,Akka.Remote"" - applied-adapters = [] - registry-key = aX33k0jWKg - local-address = ""test://remote-sys@localhost:12346"" - maximum-payload-bytes = 128000b - scheme-identifier = test - } - } - - actor.deployment { - /blub.remote = ""akka.test://remote-sys@localhost:12346"" - /looker/child.remote = ""akka.test://remote-sys@localhost:12346"" - /looker/child/grandchild.remote = ""akka.test://RemotingSpec@localhost:12345"" - } - }"; + return """ + + common-helios-settings { + port = 0 + hostname = "localhost" + #enforce-ip-family = true + } + + akka { + actor.provider = remote + + remote { + transport = "Akka.Remote.Remoting,Akka.Remote" + actor.serialize-messages = off + + retry-gate-closed-for = 1 s + log-remote-lifecycle-events = on + + enabled-transports = [ + "akka.remote.test", + "akka.remote.dot-netty.tcp", + # "akka.remote.dot-netty.udp" + ] + + dot-netty.tcp = ${common-helios-settings} + helios.udp = ${common-helios-settings} + + test { + transport-class = "Akka.Remote.Transport.TestTransport,Akka.Remote" + applied-adapters = [] + registry-key = aX33k0jWKg + local-address = "test://RemotingSpec@localhost:12345" + maximum-payload-bytes = 32000b + scheme-identifier = test + } + } + + actor.deployment { + /blub.remote = "akka.test://remote-sys@localhost:12346" + /echo.remote = "akka.test://remote-sys@localhost:12346" + /looker/child.remote = "akka.test://remote-sys@localhost:12346" + /looker/child/grandchild.remote = "akka.test://RemotingSpec@localhost:12345" + } + + test.timefactor = 2.5 + } + """; + } + + private static string GetOtherRemoteSysConfig() + { + return """ + + common-helios-settings { + port = 0 + hostname = "localhost" + #enforce-ip-family = true + } + + akka { + actor.provider = remote + + remote { + transport = "Akka.Remote.Remoting,Akka.Remote" + + retry-gate-closed-for = 1 s + log-remote-lifecycle-events = on + + enabled-transports = [ + "akka.remote.test", + "akka.remote.dot-netty.tcp", + #"akka.remote.helios.udp" + ] + + dot-netty.tcp = ${common-helios-settings} + helios.udp = ${common-helios-settings} + + test { + transport-class = "Akka.Remote.Transport.TestTransport,Akka.Remote" + applied-adapters = [] + registry-key = aX33k0jWKg + local-address = "test://remote-sys@localhost:12346" + maximum-payload-bytes = 128000b + scheme-identifier = test + } + } + + actor.deployment { + /blub.remote = "akka.test://remote-sys@localhost:12346" + /looker/child.remote = "akka.test://remote-sys@localhost:12346" + /looker/child/grandchild.remote = "akka.test://RemotingSpec@localhost:12345" + } + } + """; } private ActorSystem _remoteSystem; @@ -684,6 +687,12 @@ public async Task Nobody_should_be_converted_back_to_its_singleton() await ExpectMsgAsync(ActorRefs.Nobody, TimeSpan.FromSeconds(1.5)); } + [Fact] + public async Task Should_reply_back_on_original_Transport() + { + + } + #endregion #region Internal Methods diff --git a/src/core/Akka.Remote.Tests/Transport/MultiTransportAddressingSpec.cs b/src/core/Akka.Remote.Tests/Transport/MultiTransportAddressingSpec.cs new file mode 100644 index 00000000000..4167eda003b --- /dev/null +++ b/src/core/Akka.Remote.Tests/Transport/MultiTransportAddressingSpec.cs @@ -0,0 +1,123 @@ +// ----------------------------------------------------------------------- +// +// Copyright (C) 2009-2024 Lightbend Inc. +// Copyright (C) 2013-2024 .NET Foundation +// +// ----------------------------------------------------------------------- + +using System; +using System.Threading.Tasks; +using Akka.Actor; +using Akka.Configuration; +using Akka.TestKit; +using Xunit; +using Xunit.Abstractions; + +namespace Akka.Remote.Tests.Transport; + +/// +/// Added this spec to prove the existence of https://github.com/akkadotnet/akka.net/issues/7378 +/// +public class MultiTransportAddressingSpec : AkkaSpec +{ + public MultiTransportAddressingSpec(ITestOutputHelper output) : base(GetConfig(Sys1Port1, Sys1Port2), output) + { + } + + public const int Sys1Port1 = 9991; + public const int Sys1Port2 = 9992; + + public const int Sys2Port1 = 9993; + public const int Sys2Port2 = 9994; + + private static Config GetConfig(int transportPort1, int transportPort2) + { + return $$""" + + akka { + actor.provider = remote + remote { + enabled-transports = [ + "akka.remote.test1", + "akka.remote.test2" + ] + test1 { + transport-class = "Akka.Remote.Transport.TestTransport, Akka.Remote" + applied-adapters = [] + registry-key = aX33k0jWKg + local-address = "test1://MultiTransportSpec@localhost:{{transportPort1}}" + maximum-payload-bytes = 32000b + scheme-identifier = test1 + } + test2 { + transport-class = "Akka.Remote.Transport.TestTransport, Akka.Remote" + applied-adapters = [] + registry-key = aX33k0j11c + local-address = "test2://MultiTransportSpec@localhost:{{transportPort2}}" + maximum-payload-bytes = 32000b + scheme-identifier = test2 + } + } + } + + """; + } + + + [Fact] + public async Task Should_Use_Second_Transport_For_Communication() + { + var secondSystem = ActorSystem.Create("MultiTransportSpec", GetConfig(Sys2Port1, Sys2Port2).WithFallback(Sys.Settings.Config)); + InitializeLogger(secondSystem); + var assertProbe = CreateTestProbe(secondSystem); + + try + { + + var echoActor = secondSystem.ActorOf(Props.Create(() => new EchoActor(assertProbe)), "echo"); + + // use the first connection + await PingAndVerify("test1", Sys2Port1); + + // use the second connection + await PingAndVerify("test2", Sys2Port2); + } + finally + { + Shutdown(secondSystem); + } + + async Task PingAndVerify(string scheme, int port) + { + var selection = Sys.ActorSelection($"akka.{scheme}://MultiTransportSpec@localhost:{port}/user/echo"); + selection.Tell("ping", TestActor); + + var reply = await ExpectMsgAsync(TimeSpan.FromSeconds(3)); + Assert.Equal("pong", reply); + + var senderFromNode2Pov = await assertProbe.ExpectMsgAsync(); + Assert.Contains(scheme, senderFromNode2Pov.Path.Address.Protocol); + + var senderPath = LastSender.Path.ToString(); + Assert.Contains(scheme, senderPath); + } + } + + public class EchoActor : ReceiveActor + { + private readonly IActorRef _testProbe; + + public EchoActor(IActorRef testProbe) + { + _testProbe = testProbe; + Receive(msg => + { + if (msg == "ping") + { + _testProbe.Tell(Sender); + Sender.Tell("pong"); + } + }); + } + } +} \ No newline at end of file